From 74febe01e218432be40687ba648d813f8b72a658 Mon Sep 17 00:00:00 2001 From: DanielSchuette Date: Mon, 6 Dec 2021 22:23:17 +0100 Subject: [PATCH] update fugitive and coc plugins --- vim-config/plugins/coc.nvim/.eslintignore | 5 + vim-config/plugins/coc.nvim/.eslintrc.js | 338 + .../plugins/coc.nvim/.github/.codecov.yml | 3 + .../plugins/coc.nvim/.github/workflows/ci.yml | 58 +- .../coc.nvim/.github/workflows/lint.yml | 34 + vim-config/plugins/coc.nvim/.gitignore | 13 +- vim-config/plugins/coc.nvim/.ignore | 1 + vim-config/plugins/coc.nvim/.npmignore | 16 + .../plugins/coc.nvim/.vim/coc-settings.json | 7 + vim-config/plugins/coc.nvim/Backers.md | 207 + vim-config/plugins/coc.nvim/CONTRIBUTING.md | 142 + vim-config/plugins/coc.nvim/LICENSE.md | 2 +- .../plugins/coc.nvim/{Readme.md => README.md} | 27 +- vim-config/plugins/coc.nvim/autoload/coc.vim | 13 +- .../plugins/coc.nvim/autoload/coc/api.vim | 87 +- .../plugins/coc.nvim/autoload/coc/client.vim | 71 +- .../plugins/coc.nvim/autoload/coc/compat.vim | 80 +- .../plugins/coc.nvim/autoload/coc/cursor.vim | 41 + .../plugins/coc.nvim/autoload/coc/float.vim | 303 +- .../plugins/coc.nvim/autoload/coc/helper.vim | 58 + .../coc.nvim/autoload/coc/highlight.vim | 304 +- .../plugins/coc.nvim/autoload/coc/list.vim | 59 +- .../plugins/coc.nvim/autoload/coc/prompt.vim | 3 +- .../plugins/coc.nvim/autoload/coc/task.vim | 14 +- .../plugins/coc.nvim/autoload/coc/util.vim | 243 +- .../plugins/coc.nvim/autoload/coc/window.vim | 56 + .../plugins/coc.nvim/autoload/health/coc.vim | 7 +- vim-config/plugins/coc.nvim/bin/check.js | 13 - vim-config/plugins/coc.nvim/build/index.js | 68732 +++++++++++++++- vim-config/plugins/coc.nvim/data/schema.json | 355 +- vim-config/plugins/coc.nvim/doc/coc.txt | 1580 +- vim-config/plugins/coc.nvim/doc/tags | 238 +- vim-config/plugins/coc.nvim/esbuild.js | 75 + vim-config/plugins/coc.nvim/jest.js | 17 + vim-config/plugins/coc.nvim/package.json | 83 +- vim-config/plugins/coc.nvim/plugin/coc.vim | 165 +- .../__tests__/autoload/coc/source/email.vim | 17 + .../src/__tests__/client/changedFiles.test.ts | 62 + .../src/__tests__/client/connection.test.ts | 140 + .../src/__tests__/client/converter.test.ts | 89 + .../src/__tests__/client/delayer.test.ts | 154 + .../src/__tests__/client/features.test.ts | 1054 + .../src/__tests__/client/integration.test.ts | 128 + .../client/server/testFileWatcher.js | 35 + .../client/server/testInitializeResult.js | 40 + .../src/__tests__/client/server/testServer.js | 414 + .../coc.nvim/src/__tests__/coc-settings.json | 5 + .../src/__tests__/completion/basic.test.ts | 446 + .../src/__tests__/completion/float.test.ts | 122 + .../src/__tests__/completion/match.test.ts | 66 + .../src/__tests__/completion/sources.test.ts | 92 + .../src/__tests__/completion/util.test.ts | 32 + .../src/__tests__/extensions/global/index.js | 7 + .../__tests__/extensions/global/package.json | 7 + .../src/__tests__/extensions/package.json | 6 + .../coc.nvim/src/__tests__/extensions/root.js | 7 + .../src/__tests__/extensions/test/index.js | 13 + .../__tests__/extensions/test/package.json | 33 + .../__tests__/extensions/vim/local/index.js | 7 + .../extensions/vim/local/package.json | 7 + .../__tests__/handler/callHierarchy.test.ts | 398 + .../src/__tests__/handler/codeActions.test.ts | 386 + .../src/__tests__/handler/codelens.test.ts | 269 + .../src/__tests__/handler/colors.test.ts | 254 + .../src/__tests__/handler/commands.test.ts | 82 + .../src/__tests__/handler/fold.test.ts | 71 + .../src/__tests__/handler/format.test.ts | 253 + .../src/__tests__/handler/highlights.test.ts | 138 + .../src/__tests__/handler/hover.test.ts | 178 + .../src/__tests__/handler/index.test.ts | 93 + .../src/__tests__/handler/links.test.ts | 99 + .../src/__tests__/handler/locations.test.ts | 308 + .../src/__tests__/handler/outline.test.ts | 426 + .../coc.nvim/src/__tests__/handler/parser.ts | 117 + .../src/__tests__/handler/refactor.test.ts | 347 + .../src/__tests__/handler/rename.test.ts | 263 + .../src/__tests__/handler/search.test.ts | 101 + .../__tests__/handler/selectionRange.test.ts | 143 + .../__tests__/handler/semanticTokens.test.ts | 180 + .../src/__tests__/handler/signature.test.ts | 376 + .../src/__tests__/handler/symbols.test.ts | 284 + .../coc.nvim/src/__tests__/helper.test.ts | 22 + .../plugins/coc.nvim/src/__tests__/helper.ts | 248 + .../src/__tests__/list/basicList.test.ts | 175 + .../src/__tests__/list/commandTask.test.ts | 134 + .../src/__tests__/list/formatting.test.ts | 32 + .../src/__tests__/list/location.test.ts | 79 + .../src/__tests__/list/manager.test.ts | 509 + .../src/__tests__/list/mappings.test.ts | 903 + .../src/__tests__/list/session.test.ts | 246 + .../src/__tests__/list/sources.test.ts | 203 + .../coc.nvim/src/__tests__/list/ui.test.ts | 140 + .../src/__tests__/list/worker.test.ts | 204 + .../src/__tests__/markdown/index.test.ts | 151 + .../src/__tests__/markdown/renderer.test.ts | 119 + .../plugins/coc.nvim/src/__tests__/memos.json | 1 + .../src/__tests__/modules/array.test.ts | 35 + .../src/__tests__/modules/attach.test.ts | 53 + .../src/__tests__/modules/chars.test.ts | 78 + .../src/__tests__/modules/client.test.ts | 35 + .../src/__tests__/modules/completion.test.ts | 756 + .../__tests__/modules/configurations.test.ts | 247 + .../src/__tests__/modules/cursors.test.ts | 421 + .../coc.nvim/src/__tests__/modules/db.test.ts | 60 + .../src/__tests__/modules/decorator.test.ts | 27 + .../modules/diagnosticBuffer.test.ts | 250 + .../modules/diagnosticCollection.test.ts | 98 + .../modules/diagnosticManager.test.ts | 556 + .../src/__tests__/modules/dialog.test.ts | 60 + .../src/__tests__/modules/diff.test.ts | 178 + .../src/__tests__/modules/document.test.ts | 413 + .../src/__tests__/modules/events.test.ts | 67 + .../src/__tests__/modules/extensions.test.ts | 221 + .../src/__tests__/modules/fetch.test.ts | 87 + .../__tests__/modules/floatFactory.test.ts | 276 + .../src/__tests__/modules/memos.test.ts | 45 + .../src/__tests__/modules/menu.test.ts | 119 + .../src/__tests__/modules/mru.test.ts | 33 + .../__tests__/modules/outputChannel.test.ts | 77 + .../src/__tests__/modules/picker.test.ts | 157 + .../src/__tests__/modules/plugin.test.ts | 49 + .../src/__tests__/modules/position.test.ts | 63 + .../src/__tests__/modules/score.test.ts | 34 + .../src/__tests__/modules/settings.json | 12 + .../src/__tests__/modules/sources.test.ts | 192 + .../src/__tests__/modules/task.test.ts | 113 + .../src/__tests__/modules/terminal.test.ts | 53 + .../__tests__/modules/textdocument.test.ts | 35 + .../src/__tests__/modules/util.test.ts | 295 + .../src/__tests__/modules/watchman.test.ts | 161 + .../src/__tests__/modules/window.test.ts | 365 + .../src/__tests__/modules/workspace.test.ts | 1043 + vim-config/plugins/coc.nvim/src/__tests__/rg | 38 + .../__tests__/sample/.vim/coc-settings.json | 3 + .../src/__tests__/snippets/manager.test.ts | 306 + .../src/__tests__/snippets/parser.test.ts | 780 + .../src/__tests__/snippets/session.test.ts | 537 + .../src/__tests__/snippets/string.test.ts | 78 + .../src/__tests__/tree/basicProvider.test.ts | 541 + .../src/__tests__/tree/treeView.test.ts | 1146 + .../plugins/coc.nvim/src/__tests__/vimrc | 26 + vim-config/plugins/coc.nvim/src/attach.ts | 133 + vim-config/plugins/coc.nvim/src/channels.ts | 82 + vim-config/plugins/coc.nvim/src/commands.ts | 379 + .../coc.nvim/src/completion/complete.ts | 376 + .../coc.nvim/src/completion/floating.ts | 69 + .../plugins/coc.nvim/src/completion/index.ts | 623 + .../plugins/coc.nvim/src/completion/match.ts | 133 + .../src/configuration/configuration.ts | 71 + .../coc.nvim/src/configuration/index.ts | 338 + .../coc.nvim/src/configuration/model.ts | 64 + .../coc.nvim/src/configuration/shape.ts | 47 + .../coc.nvim/src/configuration/util.ts | 271 + .../plugins/coc.nvim/src/cursors/index.ts | 167 + .../plugins/coc.nvim/src/cursors/range.ts | 104 + .../plugins/coc.nvim/src/cursors/session.ts | 444 + .../plugins/coc.nvim/src/cursors/util.ts | 49 + .../plugins/coc.nvim/src/diagnostic/buffer.ts | 392 + .../coc.nvim/src/diagnostic/collection.ts | 86 + .../coc.nvim/src/diagnostic/manager.ts | 635 + .../plugins/coc.nvim/src/diagnostic/util.ts | 74 + vim-config/plugins/coc.nvim/src/events.ts | 209 + vim-config/plugins/coc.nvim/src/extensions.ts | 1061 + .../coc.nvim/src/handler/callHierarchy.ts | 257 + .../coc.nvim/src/handler/codeActions.ts | 140 + .../coc.nvim/src/handler/codelens/buffer.ts | 213 + .../coc.nvim/src/handler/codelens/index.ts | 88 + .../src/handler/colors/colorBuffer.ts | 157 + .../coc.nvim/src/handler/colors/index.ts | 147 + .../plugins/coc.nvim/src/handler/commands.ts | 64 + .../plugins/coc.nvim/src/handler/fold.ts | 37 + .../plugins/coc.nvim/src/handler/format.ts | 228 + .../coc.nvim/src/handler/highlights.ts | 106 + .../plugins/coc.nvim/src/handler/hover.ts | 235 + .../plugins/coc.nvim/src/handler/index.ts | 207 + .../plugins/coc.nvim/src/handler/links.ts | 42 + .../plugins/coc.nvim/src/handler/locations.ts | 175 + .../coc.nvim/src/handler/refactor/buffer.ts | 545 + .../coc.nvim/src/handler/refactor/index.ts | 247 + .../plugins/coc.nvim/src/handler/rename.ts | 67 + .../plugins/coc.nvim/src/handler/search.ts | 201 + .../coc.nvim/src/handler/selectionRange.ts | 83 + .../semanticTokensHighlights/buffer.ts | 301 + .../handler/semanticTokensHighlights/index.ts | 182 + .../plugins/coc.nvim/src/handler/signature.ts | 284 + .../coc.nvim/src/handler/symbols/buffer.ts | 89 + .../coc.nvim/src/handler/symbols/index.ts | 161 + .../coc.nvim/src/handler/symbols/outline.ts | 319 + .../coc.nvim/src/handler/symbols/util.ts | 57 + vim-config/plugins/coc.nvim/src/index.ts | 72 + .../coc.nvim/src/language-client/LICENSE.txt | 23 + .../src/language-client/callHierarchy.ts | 122 + .../coc.nvim/src/language-client/client.ts | 4352 + .../src/language-client/colorProvider.ts | 116 + .../src/language-client/configuration.ts | 94 + .../src/language-client/declaration.ts | 67 + .../src/language-client/fileOperations.ts | 436 + .../src/language-client/foldingRange.ts | 90 + .../src/language-client/implementation.ts | 65 + .../coc.nvim/src/language-client/index.ts | 637 + .../src/language-client/linkedEditingRange.ts | 71 + .../coc.nvim/src/language-client/progress.ts | 45 + .../src/language-client/progressPart.ts | 74 + .../src/language-client/selectionRange.ts | 70 + .../src/language-client/semanticTokens.ts | 202 + .../src/language-client/typeDefinition.ts | 74 + .../src/language-client/utils/async.ts | 87 + .../src/language-client/utils/converter.ts | 135 + .../src/language-client/utils/uuid.ts | 5 + .../src/language-client/workspaceFolders.ts | 170 + vim-config/plugins/coc.nvim/src/languages.ts | 450 + vim-config/plugins/coc.nvim/src/list/basic.ts | 323 + .../plugins/coc.nvim/src/list/commandTask.ts | 59 + .../coc.nvim/src/list/configuration.ts | 120 + .../plugins/coc.nvim/src/list/formatting.ts | 55 + .../plugins/coc.nvim/src/list/history.ts | 83 + .../plugins/coc.nvim/src/list/manager.ts | 496 + .../plugins/coc.nvim/src/list/mappings.ts | 321 + .../plugins/coc.nvim/src/list/prompt.ts | 214 + .../plugins/coc.nvim/src/list/session.ts | 578 + .../coc.nvim/src/list/source/commands.ts | 59 + .../coc.nvim/src/list/source/diagnostics.ts | 49 + .../coc.nvim/src/list/source/extensions.ts | 180 + .../coc.nvim/src/list/source/folders.ts | 48 + .../plugins/coc.nvim/src/list/source/links.ts | 77 + .../plugins/coc.nvim/src/list/source/lists.ts | 55 + .../coc.nvim/src/list/source/location.ts | 85 + .../coc.nvim/src/list/source/outline.ts | 160 + .../coc.nvim/src/list/source/services.ts | 50 + .../coc.nvim/src/list/source/sources.ts | 84 + .../coc.nvim/src/list/source/symbols.ts | 105 + vim-config/plugins/coc.nvim/src/list/ui.ts | 429 + .../plugins/coc.nvim/src/list/worker.ts | 367 + vim-config/plugins/coc.nvim/src/main.ts | 26 + .../plugins/coc.nvim/src/markdown/index.ts | 199 + .../plugins/coc.nvim/src/markdown/renderer.ts | 381 + .../plugins/coc.nvim/src/markdown/styles.ts | 37 + .../plugins/coc.nvim/src/model/bufferSync.ts | 84 + .../plugins/coc.nvim/src/model/chars.ts | 118 + vim-config/plugins/coc.nvim/src/model/db.ts | 133 + .../plugins/coc.nvim/src/model/dialog.ts | 109 + .../plugins/coc.nvim/src/model/document.ts | 723 + .../plugins/coc.nvim/src/model/download.ts | 127 + .../plugins/coc.nvim/src/model/fetch.ts | 257 + .../coc.nvim/src/model/fileSystemWatcher.ts | 98 + .../coc.nvim/src/model/floatFactory.ts | 237 + .../plugins/coc.nvim/src/model/highligher.ts | 108 + .../coc.nvim/src/model/installBuffer.ts | 154 + .../plugins/coc.nvim/src/model/installer.ts | 258 + .../plugins/coc.nvim/src/model/memos.ts | 64 + vim-config/plugins/coc.nvim/src/model/menu.ts | 181 + vim-config/plugins/coc.nvim/src/model/mru.ts | 69 + .../coc.nvim/src/model/notification.ts | 111 + .../coc.nvim/src/model/outputChannel.ts | 94 + .../plugins/coc.nvim/src/model/picker.ts | 284 + .../plugins/coc.nvim/src/model/popup.ts | 95 + .../plugins/coc.nvim/src/model/progress.ts | 90 + .../plugins/coc.nvim/src/model/resolver.ts | 42 + .../plugins/coc.nvim/src/model/status.ts | 91 + vim-config/plugins/coc.nvim/src/model/task.ts | 97 + .../plugins/coc.nvim/src/model/terminal.ts | 106 + .../coc.nvim/src/model/textdocument.ts | 92 + vim-config/plugins/coc.nvim/src/plugin.ts | 370 + .../src/provider/callHierarchyManager.ts | 45 + .../src/provider/codeActionManager.ts | 94 + .../coc.nvim/src/provider/codeLensManager.ts | 58 + .../src/provider/declarationManager.ts | 32 + .../src/provider/definitionManager.ts | 64 + .../src/provider/documentColorManager.ts | 37 + .../src/provider/documentHighlightManager.ts | 31 + .../src/provider/documentLinkManager.ts | 51 + .../src/provider/documentSymbolManager.ts | 31 + .../src/provider/foldingRangeManager.ts | 27 + .../coc.nvim/src/provider/formatManager.ts | 38 + .../src/provider/formatRangeManager.ts | 35 + .../coc.nvim/src/provider/hoverManager.ts | 36 + .../src/provider/implementationManager.ts | 34 + .../plugins/coc.nvim/src/provider/index.ts | 815 + .../src/provider/linkedEditingRangeManager.ts | 29 + .../plugins/coc.nvim/src/provider/manager.ts | 79 + .../src/provider/onTypeFormatManager.ts | 54 + .../coc.nvim/src/provider/referenceManager.ts | 35 + .../coc.nvim/src/provider/renameManager.ts | 47 + .../src/provider/selectionRangeManager.ts | 37 + .../src/provider/semanticTokensManager.ts | 68 + .../provider/semanticTokensRangeManager.ts | 36 + .../coc.nvim/src/provider/signatureManager.ts | 42 + .../src/provider/typeDefinitionManager.ts | 34 + .../src/provider/workspaceSymbolsManager.ts | 47 + .../coc.nvim/src/semanticTokensBuilder.ts | 207 + vim-config/plugins/coc.nvim/src/services.ts | 565 + .../plugins/coc.nvim/src/snippets/manager.ts | 152 + .../plugins/coc.nvim/src/snippets/parser.ts | 1203 + .../plugins/coc.nvim/src/snippets/session.ts | 331 + .../plugins/coc.nvim/src/snippets/snippet.ts | 264 + .../plugins/coc.nvim/src/snippets/string.ts | 102 + .../coc.nvim/src/snippets/variableResolve.ts | 94 + .../plugins/coc.nvim/src/sources/index.ts | 428 + .../coc.nvim/src/sources/native/around.ts | 38 + .../coc.nvim/src/sources/native/buffer.ts | 53 + .../coc.nvim/src/sources/native/file.ts | 151 + .../coc.nvim/src/sources/source-language.ts | 394 + .../coc.nvim/src/sources/source-vim.ts | 97 + .../plugins/coc.nvim/src/sources/source.ts | 170 + .../coc.nvim/src/tree/BasicDataProvider.ts | 261 + .../plugins/coc.nvim/src/tree/TreeItem.ts | 62 + .../plugins/coc.nvim/src/tree/TreeView.ts | 979 + .../plugins/coc.nvim/src/tree/filter.ts | 95 + vim-config/plugins/coc.nvim/src/tree/index.ts | 221 + vim-config/plugins/coc.nvim/src/types.ts | 870 + .../plugins/coc.nvim/src/util/ansiparse.ts | 243 + vim-config/plugins/coc.nvim/src/util/array.ts | 70 + .../plugins/coc.nvim/src/util/callSequence.ts | 43 + .../plugins/coc.nvim/src/util/charCode.ts | 424 + vim-config/plugins/coc.nvim/src/util/color.ts | 32 + .../plugins/coc.nvim/src/util/convert.ts | 60 + .../plugins/coc.nvim/src/util/decorator.ts | 19 + vim-config/plugins/coc.nvim/src/util/diff.ts | 140 + .../plugins/coc.nvim/src/util/extensions.ts | 15 + .../plugins/coc.nvim/src/util/factory.ts | 171 + vim-config/plugins/coc.nvim/src/util/fs.ts | 251 + vim-config/plugins/coc.nvim/src/util/fuzzy.ts | 48 + vim-config/plugins/coc.nvim/src/util/fzy.ts | 201 + vim-config/plugins/coc.nvim/src/util/index.ts | 157 + vim-config/plugins/coc.nvim/src/util/is.ts | 58 + .../plugins/coc.nvim/src/util/lodash.ts | 52 + .../plugins/coc.nvim/src/util/logger.ts | 65 + vim-config/plugins/coc.nvim/src/util/match.ts | 71 + vim-config/plugins/coc.nvim/src/util/mutex.ts | 46 + .../plugins/coc.nvim/src/util/object.ts | 137 + .../plugins/coc.nvim/src/util/platform.ts | 83 + .../plugins/coc.nvim/src/util/position.ts | 132 + .../plugins/coc.nvim/src/util/processes.ts | 56 + vim-config/plugins/coc.nvim/src/util/score.ts | 140 + .../plugins/coc.nvim/src/util/string.ts | 126 + .../plugins/coc.nvim/src/util/textedit.ts | 6 + .../plugins/coc.nvim/src/util/throttle.ts | 42 + vim-config/plugins/coc.nvim/src/watchman.ts | 196 + vim-config/plugins/coc.nvim/src/window.ts | 657 + vim-config/plugins/coc.nvim/src/workspace.ts | 1727 + vim-config/plugins/coc.nvim/tsconfig.json | 28 + vim-config/plugins/coc.nvim/typings/LICENSE | 19 + vim-config/plugins/coc.nvim/typings/Readme.md | 18 + .../plugins/coc.nvim/typings/index.d.ts | 8794 ++ vim-config/plugins/coc.nvim/yarn.lock | 3713 + vim-config/plugins/fugitive/.gitattributes | 2 + .../plugins/fugitive/.github/FUNDING.yml | 2 + vim-config/plugins/fugitive/.gitignore | 1 + .../CONTRIBUTING.markdown | 0 .../README.markdown | 38 +- .../autoload/fugitive.vim | 3981 +- .../doc/fugitive.txt | 177 +- .../ftdetect/fugitive.vim | 0 .../fugitive/ftplugin/fugitiveblame.vim | 6 + .../plugin/fugitive.vim | 525 +- .../syntax/fugitive.vim | 18 +- .../syntax/fugitiveblame.vim | 2 +- vim-config/plugins/vim-fugitive/doc/tags | 144 - 358 files changed, 149757 insertions(+), 3164 deletions(-) create mode 100644 vim-config/plugins/coc.nvim/.eslintignore create mode 100644 vim-config/plugins/coc.nvim/.eslintrc.js create mode 100644 vim-config/plugins/coc.nvim/.github/.codecov.yml create mode 100644 vim-config/plugins/coc.nvim/.github/workflows/lint.yml create mode 100644 vim-config/plugins/coc.nvim/.ignore create mode 100644 vim-config/plugins/coc.nvim/.npmignore create mode 100644 vim-config/plugins/coc.nvim/.vim/coc-settings.json create mode 100644 vim-config/plugins/coc.nvim/Backers.md create mode 100644 vim-config/plugins/coc.nvim/CONTRIBUTING.md rename vim-config/plugins/coc.nvim/{Readme.md => README.md} (86%) create mode 100644 vim-config/plugins/coc.nvim/autoload/coc/cursor.vim create mode 100644 vim-config/plugins/coc.nvim/autoload/coc/window.vim delete mode 100644 vim-config/plugins/coc.nvim/bin/check.js create mode 100755 vim-config/plugins/coc.nvim/esbuild.js create mode 100644 vim-config/plugins/coc.nvim/jest.js create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/autoload/coc/source/email.vim create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/changedFiles.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/connection.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/converter.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/delayer.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/features.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/integration.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/server/testFileWatcher.js create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/server/testInitializeResult.js create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/client/server/testServer.js create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/coc-settings.json create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/completion/basic.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/completion/float.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/completion/match.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/completion/sources.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/completion/util.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/extensions/global/index.js create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/extensions/global/package.json create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/extensions/package.json create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/extensions/root.js create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/extensions/test/index.js create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/extensions/test/package.json create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/extensions/vim/local/index.js create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/extensions/vim/local/package.json create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/callHierarchy.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/codeActions.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/codelens.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/colors.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/commands.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/fold.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/format.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/highlights.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/hover.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/index.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/links.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/locations.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/outline.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/parser.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/refactor.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/rename.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/search.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/selectionRange.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/semanticTokens.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/signature.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/handler/symbols.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/helper.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/helper.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/basicList.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/commandTask.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/formatting.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/location.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/manager.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/mappings.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/session.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/sources.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/ui.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/list/worker.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/markdown/index.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/markdown/renderer.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/memos.json create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/array.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/attach.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/chars.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/client.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/completion.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/configurations.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/cursors.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/db.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/decorator.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticBuffer.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticCollection.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticManager.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/dialog.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/diff.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/document.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/events.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/extensions.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/fetch.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/floatFactory.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/memos.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/menu.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/mru.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/outputChannel.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/picker.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/plugin.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/position.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/score.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/settings.json create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/sources.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/task.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/terminal.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/textdocument.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/util.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/watchman.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/window.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/modules/workspace.test.ts create mode 100755 vim-config/plugins/coc.nvim/src/__tests__/rg create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/sample/.vim/coc-settings.json create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/snippets/manager.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/snippets/parser.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/snippets/session.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/snippets/string.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/tree/basicProvider.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/tree/treeView.test.ts create mode 100644 vim-config/plugins/coc.nvim/src/__tests__/vimrc create mode 100644 vim-config/plugins/coc.nvim/src/attach.ts create mode 100644 vim-config/plugins/coc.nvim/src/channels.ts create mode 100644 vim-config/plugins/coc.nvim/src/commands.ts create mode 100644 vim-config/plugins/coc.nvim/src/completion/complete.ts create mode 100644 vim-config/plugins/coc.nvim/src/completion/floating.ts create mode 100644 vim-config/plugins/coc.nvim/src/completion/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/completion/match.ts create mode 100644 vim-config/plugins/coc.nvim/src/configuration/configuration.ts create mode 100644 vim-config/plugins/coc.nvim/src/configuration/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/configuration/model.ts create mode 100644 vim-config/plugins/coc.nvim/src/configuration/shape.ts create mode 100644 vim-config/plugins/coc.nvim/src/configuration/util.ts create mode 100644 vim-config/plugins/coc.nvim/src/cursors/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/cursors/range.ts create mode 100644 vim-config/plugins/coc.nvim/src/cursors/session.ts create mode 100644 vim-config/plugins/coc.nvim/src/cursors/util.ts create mode 100644 vim-config/plugins/coc.nvim/src/diagnostic/buffer.ts create mode 100644 vim-config/plugins/coc.nvim/src/diagnostic/collection.ts create mode 100644 vim-config/plugins/coc.nvim/src/diagnostic/manager.ts create mode 100644 vim-config/plugins/coc.nvim/src/diagnostic/util.ts create mode 100644 vim-config/plugins/coc.nvim/src/events.ts create mode 100644 vim-config/plugins/coc.nvim/src/extensions.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/callHierarchy.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/codeActions.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/codelens/buffer.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/codelens/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/colors/colorBuffer.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/colors/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/commands.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/fold.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/format.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/highlights.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/hover.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/links.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/locations.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/refactor/buffer.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/refactor/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/rename.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/search.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/selectionRange.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/semanticTokensHighlights/buffer.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/semanticTokensHighlights/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/signature.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/symbols/buffer.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/symbols/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/symbols/outline.ts create mode 100644 vim-config/plugins/coc.nvim/src/handler/symbols/util.ts create mode 100644 vim-config/plugins/coc.nvim/src/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/LICENSE.txt create mode 100644 vim-config/plugins/coc.nvim/src/language-client/callHierarchy.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/client.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/colorProvider.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/configuration.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/declaration.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/fileOperations.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/foldingRange.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/implementation.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/linkedEditingRange.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/progress.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/progressPart.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/selectionRange.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/semanticTokens.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/typeDefinition.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/utils/async.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/utils/converter.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/utils/uuid.ts create mode 100644 vim-config/plugins/coc.nvim/src/language-client/workspaceFolders.ts create mode 100644 vim-config/plugins/coc.nvim/src/languages.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/basic.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/commandTask.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/configuration.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/formatting.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/history.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/manager.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/mappings.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/prompt.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/session.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/commands.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/diagnostics.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/extensions.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/folders.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/links.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/lists.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/location.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/outline.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/services.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/sources.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/source/symbols.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/ui.ts create mode 100644 vim-config/plugins/coc.nvim/src/list/worker.ts create mode 100755 vim-config/plugins/coc.nvim/src/main.ts create mode 100644 vim-config/plugins/coc.nvim/src/markdown/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/markdown/renderer.ts create mode 100644 vim-config/plugins/coc.nvim/src/markdown/styles.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/bufferSync.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/chars.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/db.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/dialog.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/document.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/download.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/fetch.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/fileSystemWatcher.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/floatFactory.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/highligher.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/installBuffer.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/installer.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/memos.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/menu.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/mru.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/notification.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/outputChannel.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/picker.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/popup.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/progress.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/resolver.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/status.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/task.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/terminal.ts create mode 100644 vim-config/plugins/coc.nvim/src/model/textdocument.ts create mode 100644 vim-config/plugins/coc.nvim/src/plugin.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/callHierarchyManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/codeActionManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/codeLensManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/declarationManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/definitionManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/documentColorManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/documentHighlightManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/documentLinkManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/documentSymbolManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/foldingRangeManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/formatManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/formatRangeManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/hoverManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/implementationManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/linkedEditingRangeManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/manager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/onTypeFormatManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/referenceManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/renameManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/selectionRangeManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/semanticTokensManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/semanticTokensRangeManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/signatureManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/typeDefinitionManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/provider/workspaceSymbolsManager.ts create mode 100644 vim-config/plugins/coc.nvim/src/semanticTokensBuilder.ts create mode 100644 vim-config/plugins/coc.nvim/src/services.ts create mode 100644 vim-config/plugins/coc.nvim/src/snippets/manager.ts create mode 100644 vim-config/plugins/coc.nvim/src/snippets/parser.ts create mode 100644 vim-config/plugins/coc.nvim/src/snippets/session.ts create mode 100644 vim-config/plugins/coc.nvim/src/snippets/snippet.ts create mode 100644 vim-config/plugins/coc.nvim/src/snippets/string.ts create mode 100644 vim-config/plugins/coc.nvim/src/snippets/variableResolve.ts create mode 100644 vim-config/plugins/coc.nvim/src/sources/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/sources/native/around.ts create mode 100644 vim-config/plugins/coc.nvim/src/sources/native/buffer.ts create mode 100644 vim-config/plugins/coc.nvim/src/sources/native/file.ts create mode 100644 vim-config/plugins/coc.nvim/src/sources/source-language.ts create mode 100644 vim-config/plugins/coc.nvim/src/sources/source-vim.ts create mode 100644 vim-config/plugins/coc.nvim/src/sources/source.ts create mode 100644 vim-config/plugins/coc.nvim/src/tree/BasicDataProvider.ts create mode 100644 vim-config/plugins/coc.nvim/src/tree/TreeItem.ts create mode 100644 vim-config/plugins/coc.nvim/src/tree/TreeView.ts create mode 100644 vim-config/plugins/coc.nvim/src/tree/filter.ts create mode 100644 vim-config/plugins/coc.nvim/src/tree/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/types.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/ansiparse.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/array.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/callSequence.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/charCode.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/color.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/convert.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/decorator.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/diff.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/extensions.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/factory.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/fs.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/fuzzy.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/fzy.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/index.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/is.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/lodash.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/logger.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/match.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/mutex.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/object.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/platform.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/position.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/processes.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/score.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/string.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/textedit.ts create mode 100644 vim-config/plugins/coc.nvim/src/util/throttle.ts create mode 100644 vim-config/plugins/coc.nvim/src/watchman.ts create mode 100644 vim-config/plugins/coc.nvim/src/window.ts create mode 100644 vim-config/plugins/coc.nvim/src/workspace.ts create mode 100644 vim-config/plugins/coc.nvim/tsconfig.json create mode 100644 vim-config/plugins/coc.nvim/typings/LICENSE create mode 100644 vim-config/plugins/coc.nvim/typings/Readme.md create mode 100644 vim-config/plugins/coc.nvim/typings/index.d.ts create mode 100644 vim-config/plugins/coc.nvim/yarn.lock create mode 100644 vim-config/plugins/fugitive/.gitattributes create mode 100644 vim-config/plugins/fugitive/.github/FUNDING.yml create mode 100644 vim-config/plugins/fugitive/.gitignore rename vim-config/plugins/{vim-fugitive => fugitive}/CONTRIBUTING.markdown (100%) rename vim-config/plugins/{vim-fugitive => fugitive}/README.markdown (79%) rename vim-config/plugins/{vim-fugitive => fugitive}/autoload/fugitive.vim (61%) rename vim-config/plugins/{vim-fugitive => fugitive}/doc/fugitive.txt (81%) rename vim-config/plugins/{vim-fugitive => fugitive}/ftdetect/fugitive.vim (100%) create mode 100644 vim-config/plugins/fugitive/ftplugin/fugitiveblame.vim rename vim-config/plugins/{vim-fugitive => fugitive}/plugin/fugitive.vim (51%) rename vim-config/plugins/{vim-fugitive => fugitive}/syntax/fugitive.vim (73%) rename vim-config/plugins/{vim-fugitive => fugitive}/syntax/fugitiveblame.vim (58%) delete mode 100644 vim-config/plugins/vim-fugitive/doc/tags diff --git a/vim-config/plugins/coc.nvim/.eslintignore b/vim-config/plugins/coc.nvim/.eslintignore new file mode 100644 index 00000000..f38d5306 --- /dev/null +++ b/vim-config/plugins/coc.nvim/.eslintignore @@ -0,0 +1,5 @@ +node_modules +coverage +build +lib +typings diff --git a/vim-config/plugins/coc.nvim/.eslintrc.js b/vim-config/plugins/coc.nvim/.eslintrc.js new file mode 100644 index 00000000..f2faedbb --- /dev/null +++ b/vim-config/plugins/coc.nvim/.eslintrc.js @@ -0,0 +1,338 @@ +module.exports = { + "root": true, + "env": { + "es6": true, + "node": true, + "jest/globals": true + }, + "extends": [ + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json", + "sourceType": "module" + }, + "plugins": [ + "jsdoc", + "jest", + "@typescript-eslint" + ], + "rules": { + "comma-dangle": [ + 0 + ], + "guard-for-in": [ + 0 + ], + "no-dupe-class-members": [ + 0 + ], + "prefer-spread": [ + 0 + ], + "prefer-rest-params": [ + 0 + ], + "func-names": [ + 0 + ], + "require-atomic-updates": [ + 0 + ], + "no-empty": "off", + "no-console": "off", + "linebreak-style": [ + 1, + "unix" + ], + "no-prototype-builtins": [ + 0 + ], + "no-unused-vars": [ + 0 + ], + "no-async-promise-executor": [ + 0 + ], + "constructor-super": "error", + "for-direction": [ + "error" + ], + "getter-return": [ + "error" + ], + "no-case-declarations": [ + "error" + ], + "no-class-assign": [ + "error" + ], + "no-compare-neg-zero": [ + "error" + ], + "no-cond-assign": "error", + "no-const-assign": [ + "error" + ], + "no-constant-condition": [ + "error" + ], + "no-control-regex": [ + "error" + ], + "no-debugger": "error", + "no-delete-var": [ + "error" + ], + "no-dupe-args": [ + "error" + ], + "no-dupe-keys": [ + "error" + ], + "no-duplicate-case": [ + "error" + ], + "no-empty-character-class": [ + "error" + ], + "no-empty-pattern": [ + "error" + ], + "no-ex-assign": [ + "error" + ], + "no-extra-boolean-cast": [ + "error" + ], + "no-extra-semi": [ + "error" + ], + "no-fallthrough": "off", + "no-func-assign": [ + "error" + ], + "no-global-assign": [ + "error" + ], + "no-inner-declarations": [ + "error" + ], + "no-invalid-regexp": [ + "error" + ], + "no-irregular-whitespace": "error", + "no-misleading-character-class": [ + "error" + ], + "no-mixed-spaces-and-tabs": [ + "error" + ], + "no-new-symbol": [ + "error" + ], + "no-obj-calls": [ + "error" + ], + "no-octal": [ + "error" + ], + "no-redeclare": "error", + "no-regex-spaces": [ + "error" + ], + "no-self-assign": [ + "error" + ], + "no-shadow-restricted-names": [ + "error" + ], + "no-sparse-arrays": "error", + "no-this-before-super": [ + "error" + ], + "no-undef": [ + "off" + ], + "no-unexpected-multiline": [ + "error" + ], + "no-unreachable": [ + "warn" + ], + "no-unsafe-finally": "error", + "no-unsafe-negation": [ + "error" + ], + "no-unused-labels": "error", + "no-useless-catch": [ + "error" + ], + "no-useless-escape": [ + "error" + ], + "no-with": [ + "error" + ], + "require-yield": [ + "error" + ], + "use-isnan": "error", + "valid-typeof": "off", + "@typescript-eslint/no-unnecessary-boolean-literal-compare": "off", + "@typescript-eslint/no-unnecessary-type-assertion": "off", + "@typescript-eslint/prefer-string-starts-ends-with": "off", + "@typescript-eslint/prefer-regexp-exec": "off", + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": "off", + "@typescript-eslint/require-await": "off", + "@typescript-eslint/await-thenable": "error", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/restrict-plus-operands": "off", + "@typescript-eslint/restrict-template-expressions": "off", + "@typescript-eslint/consistent-type-assertions": "error", + "@typescript-eslint/consistent-type-definitions": "error", + "@typescript-eslint/explicit-member-accessibility": [ + "error", + { + "accessibility": "explicit", + "overrides": { + "accessors": "explicit", + "constructors": "off" + } + } + ], + "@typescript-eslint/interface-name-prefix": "off", + "@typescript-eslint/member-delimiter-style": "off", + "@typescript-eslint/camelcase": "off", + "@typescript-eslint/member-ordering": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-floating-promises": "error", + "@typescript-eslint/no-misused-promises": "off", + "@typescript-eslint/no-for-in-array": "error", + "@typescript-eslint/no-inferrable-types": "error", + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-parameter-properties": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-unnecessary-qualifier": "error", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/prefer-for-of": "off", + "@typescript-eslint/prefer-function-type": "off", + "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/quotes": "off", + "@typescript-eslint/semi": [ + "error", + "never" + ], + "@typescript-eslint/triple-slash-reference": [ + "error", + { + "path": "always", + "types": "prefer-import", + "lib": "always" + } + ], + "@typescript-eslint/unbound-method": "off", + "@typescript-eslint/unified-signatures": "error", + "arrow-body-style": "off", + "arrow-parens": [ + "error", + "as-needed" + ], + "camelcase": "off", + "complexity": "off", + "curly": "off", + "dot-notation": "off", + "eol-last": "off", + "eqeqeq": [ + "off", + "always" + ], + "id-blacklist": [ + "error", + "any", + "Number", + "number", + "String", + "string", + "Boolean", + "boolean", + "Undefined" + ], + "id-match": "error", + "jsdoc/check-alignment": "error", + "jsdoc/check-indentation": "error", + "jsdoc/newline-after-description": "error", + "max-classes-per-file": "off", + "new-parens": "error", + "no-bitwise": "off", + "no-caller": "error", + "no-eval": "error", + "no-invalid-this": "off", + "no-magic-numbers": "off", + "no-multiple-empty-lines": [ + "error", + { + "max": 1 + } + ], + "no-new-wrappers": "error", + "no-shadow": [ + "off", + { + "hoist": "all" + } + ], + "no-template-curly-in-string": "off", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-undef-init": "error", + "no-underscore-dangle": "off", + "no-unused-expressions": "off", + "no-var": "error", + "no-void": "off", + "object-shorthand": "error", + "one-var": [ + "error", + "never" + ], + "prefer-const": "off", + "prefer-template": "off", + "quote-props": [ + "error", + "as-needed" + ], + "radix": "error", + "space-before-function-paren": [ + "error", + { + "anonymous": "never", + "asyncArrow": "always", + "named": "never" + } + ], + "spaced-comment": [ + "error", + "always", + { + "markers": [ + "/" + ] + } + ] + }, + "settings": {} +} diff --git a/vim-config/plugins/coc.nvim/.github/.codecov.yml b/vim-config/plugins/coc.nvim/.github/.codecov.yml new file mode 100644 index 00000000..fa348a8f --- /dev/null +++ b/vim-config/plugins/coc.nvim/.github/.codecov.yml @@ -0,0 +1,3 @@ +coverage: + status: + patch: off diff --git a/vim-config/plugins/coc.nvim/.github/workflows/ci.yml b/vim-config/plugins/coc.nvim/.github/workflows/ci.yml index 8be307c7..9e8bd99c 100644 --- a/vim-config/plugins/coc.nvim/.github/workflows/ci.yml +++ b/vim-config/plugins/coc.nvim/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: coc.nvim CI +name: Dev on: push: @@ -10,47 +10,65 @@ on: jobs: test: + timeout-minutes: 60 runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ubuntu-latest] - node-version: [10, 14] + os: + - "ubuntu-latest" + node: + - "16" + - "14" + - "12" + include: + # only enable coverage on the fastest job + - os: "ubuntu-latest" + node: "16" + ENABLE_CODE_COVERAGE: true env: NODE_ENV: test steps: - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + - name: Checkout + uses: actions/checkout@v2.3.4 with: - node-version: ${{ matrix.node-version }} - - name: Install yarn - run: | - curl --compressed -o- -L https://yarnpkg.com/install.sh | bash - - uses: actions/checkout@v2 - - name: yarn install + fetch-depth: 2 + + - name: Setup Node.js ${{ matrix.node }} + uses: actions/setup-node@v2.4.0 + with: + node-version: ${{ matrix.node }} + cache: "yarn" + + - name: Install Dependencies run: | yarn global add typescript - yarn - - name: yarn lint - run: yarn lint + yarn install --frozen-lockfile + - if: matrix.os == 'macos-latest' name: yarn test on macOS run: | - curl -LO https://github.com/neovim/neovim/releases/download/nightly/nvim-macos.tar.gz + curl -LO https://github.com/neovim/neovim/releases/download/v0.5.0/nvim-macos.tar.gz tar xzf nvim-macos.tar.gz export PATH="${PATH}:node_modules/.bin:$(pwd)/nvim-osx64/bin" nvim --version - yarn test + yarn test-build --maxWorkers=4 - if: matrix.os == 'ubuntu-latest' name: yarn test on Ubuntu run: | - curl -LO https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.tar.gz + sudo apt-get install ripgrep -y + rg --version + curl -LO https://github.com/neovim/neovim/releases/download/v0.5.0/nvim-linux64.tar.gz tar xzf nvim-linux64.tar.gz export PATH="${PATH}:node_modules/.bin:$(pwd)/nvim-linux64/bin" nvim --version - yarn test - env: - NODE_ENV: test + yarn test-build --maxWorkers=2 + + - name: Codecov + uses: codecov/codecov-action@v2.0.2 + if: ${{ matrix.ENABLE_CODE_COVERAGE }} + with: + fail_ci_if_error: true diff --git a/vim-config/plugins/coc.nvim/.github/workflows/lint.yml b/vim-config/plugins/coc.nvim/.github/workflows/lint.yml new file mode 100644 index 00000000..7fcf066e --- /dev/null +++ b/vim-config/plugins/coc.nvim/.github/workflows/lint.yml @@ -0,0 +1,34 @@ +name: Lint + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2.3.4 + + - name: Setup Node.js + uses: actions/setup-node@v2.4.0 + with: + cache: "yarn" + + - name: Install Dependencies + run: yarn install --frozen-lockfile + + - name: Check Types by TSC + run: yarn lint:typecheck + + - name: Lint ESLint + run: yarn lint + + - name: Check Lock File Changes + run: yarn && echo "Listing changed files:" && git diff --name-only --exit-code && echo "No files changed during lint." diff --git a/vim-config/plugins/coc.nvim/.gitignore b/vim-config/plugins/coc.nvim/.gitignore index f9ec5e3d..266844b7 100644 --- a/vim-config/plugins/coc.nvim/.gitignore +++ b/vim-config/plugins/coc.nvim/.gitignore @@ -1,13 +1,16 @@ lib +.cache *.map coverage __pycache__ .pyc .log -src -publish.sh +build doc/tags -doc/tags-cn +typings/package.json node_modules -src/__tests__/tags -typings +publish.sh +release.sh +!src/__tests__/tags +src/__tests__/extensions/db.json +package-lock.json diff --git a/vim-config/plugins/coc.nvim/.ignore b/vim-config/plugins/coc.nvim/.ignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/vim-config/plugins/coc.nvim/.ignore @@ -0,0 +1 @@ +lib diff --git a/vim-config/plugins/coc.nvim/.npmignore b/vim-config/plugins/coc.nvim/.npmignore new file mode 100644 index 00000000..0193cd28 --- /dev/null +++ b/vim-config/plugins/coc.nvim/.npmignore @@ -0,0 +1,16 @@ +*.map +.cache +lib/extensions +lib/__tests__ +plugin +autoload +rplugin +src +.github +build +coverage +data +tslint.json +tsconfig.json +.zip +.DS_Store diff --git a/vim-config/plugins/coc.nvim/.vim/coc-settings.json b/vim-config/plugins/coc.nvim/.vim/coc-settings.json new file mode 100644 index 00000000..7746fb78 --- /dev/null +++ b/vim-config/plugins/coc.nvim/.vim/coc-settings.json @@ -0,0 +1,7 @@ +{ + "eslint.validate": ["typescript"], + "eslint.lintTask.options": [".", "--ext", ".ts"], + "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, + "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, + "typescript.suggestionActions.enabled": false +} diff --git a/vim-config/plugins/coc.nvim/Backers.md b/vim-config/plugins/coc.nvim/Backers.md new file mode 100644 index 00000000..b3cdb0b2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/Backers.md @@ -0,0 +1,207 @@ +# Backers + +❤️ coc.nvim? Help us keep it alive by [donating funds](https://www.bountysource.com/teams/coc-nvim)😘! + + + oblitum + + + free-easy + + + ruanyl + + + robjuffermans + + + iamcco + + + phcerdan + + + sarene + + + robtrac + + + raidou + + + tomspeak + + + taigacute + + + weirongxu + + + tbo + + + darthShadow + + + yatli + + + Matt Greer + + + malob + + + Emigre + + + OkanEsen + + + Lennaert Meijvogel + + + Nils Landt + + + dlants + + + RCVU + + + yatli + + + mikker + + + Velovix + + + stCarolas + + + Robbie Clarken + + + hallettj + + + appelgriebsch + + + cosminadrianpopescu + + + partizan + + + ksaldana1 + + + jesperryom + + + JackCA + + + peymanmortazavi + + + jonaustin + + + Yuriy Ivanyuk + + + abenz1267 + + + Sh3Rm4n + + + mwcz + + + Philipp-M + + + gvelchuru + + + JSamir + + + toby de havilland + + + viniciusarcanjo + + + Mike Hearn + + + darsto + + + pyrho + + + Frydac + + + gsa9 + + + _andys8 + + + iago-lito + + + ddaletski + + + jonatan-branting + + + yutakatay + + + kevinrambaud + + + tomaskallup + + + LewisSteele + + +## 微信扫码赞助者 + +- free-easy +- sarene +- tomspeak +- robtrac +- 葫芦小金刚 +- leo 陶 +- 飞翔的白斩鸡 +- mark_ll +- 火冷 +- Solomon +- 李宇星 +- Yus +- IndexXuan +- Sniper +- 陈达野 +- 胖听 +- Jimmy +- lightxue +- 小亦俊 +- 周慎敏 +- 凤鸣 +- Wilson +- Abel diff --git a/vim-config/plugins/coc.nvim/CONTRIBUTING.md b/vim-config/plugins/coc.nvim/CONTRIBUTING.md new file mode 100644 index 00000000..a3cac5f5 --- /dev/null +++ b/vim-config/plugins/coc.nvim/CONTRIBUTING.md @@ -0,0 +1,142 @@ +# Contributing + +## How do I... + +- [Use This Guide](#introduction)? +- Make Something? 🤓👩🏽‍💻📜🍳 + - [Project Setup](#project-setup) + - [Contribute Documentation](#contribute-documentation) + - [Contribute Code](#contribute-code) +- Manage Something ✅🙆🏼💃👔 + - [Provide Support on Issues](#provide-support-on-issues) + - [Review Pull Requests](#review-pull-requests) + - [Join the Project Team](#join-the-project-team) + +## Introduction + +Thank you so much for your interest in contributing!. All types of contributions are encouraged and valued. See the [table of contents](#toc) for different ways to help and details about how this project handles them!📝 + +The [Project Team](#join-the-project-team) looks forward to your contributions. 🙌🏾✨ + +## Project Setup + +So you wanna contribute some code! That's great! This project uses GitHub Pull Requests to manage contributions, so [read up on how to fork a GitHub project and file a PR](https://guides.github.com/activities/forking) if you've never done it before. + +If this seems like a lot or you aren't able to do all this setup, you might also be able to [edit the files directly](https://help.github.com/articles/editing-files-in-another-user-s-repository/) without having to do any of this setup. Yes, [even code](#contribute-code). + +If you want to go the usual route and run the project locally, though: + +- [Install Node.js](https://nodejs.org/en/download/) +- [Install Yarn](https://yarnpkg.com) +- [Fork the project](https://guides.github.com/activities/forking/#fork) + +Then in your terminal: + +- Add coc.nvim to your vim's rtp by `set runtimepath^=/path/to/coc.nvim` +- `cd path/to/your/coc.nvim` +- `yarn install` +- Install [coc-tsserver](https://github.com/neoclide/coc-tsserver) by + `:CocInstall coc-tsserver` in your vim +- Install [coc-tslint-plugin](https://github.com/neoclide/coc-tslint-plugin) by + `:CocInstall coc-tslint-plugin` in your vim. + +And you should be ready to go! + +## Contribute Documentation + +Documentation is a super important, critical part of this project. Docs are how we keep track of what we're doing, how, and why. It's how we stay on the same page about our policies. And it's how we tell others everything they need in order to be able to use this project -- or contribute to it. So thank you in advance. + +Documentation contributions of any size are welcome! Feel free to file a PR even if you're just rewording a sentence to be more clear, or fixing a spelling mistake! + +To contribute documentation: + +- [Set up the project](#project-setup). +- Edit or add any relevant documentation. +- Make sure your changes are formatted correctly and consistently with the rest of the documentation. +- Re-read what you wrote, and run a spellchecker on it to make sure you didn't miss anything. +- In your commit message(s), begin the first line with `docs:`. For example: `docs: Adding a doc contrib section to CONTRIBUTING.md`. +- Write clear, concise commit message(s) using [conventional-changelog format](https://github.com/conventional-changelog/conventional-changelog-angular/blob/master/convention.md). Documentation commits should use `docs(): `. +- Go to https://github.com/neoclide/coc.nvim/pulls and open a new pull request with your changes. +- If your PR is connected to an open issue, add a line in your PR's description that says `Fixes: #123`, where `#123` is the number of the issue you're fixing. + +## Contribute Code + +We like code commits a lot! They're super handy, and they keep the project going and doing the work it needs to do to be useful to others. + +Code contributions of just about any size are acceptable! + +The main difference between code contributions and documentation contributions is that contributing code requires inclusion of relevant tests for the code being added or changed. Contributions without accompanying tests will be held off until a test is added, unless the maintainers consider the specific tests to be either impossible, or way too much of a burden for such a contribution. + +To contribute code: + +- [Set up the project](#project-setup). +- Make any necessary changes to the source code. +- Include any [additional documentation](#contribute-documentation) the changes might need. +- Make sure the code doesn't have lint issue by command `yarn lint` in your + terminal. +- Write tests that verify that your contribution works as expected when necessary. +- Make sure all tests passed by command `yarn jest` in your terminal. +- Write clear, concise commit message(s) using [conventional-changelog format](https://github.com/conventional-changelog/conventional-changelog-angular/blob/master/convention.md). +- Dependency updates, additions, or removals must be in individual commits, and the message must use the format: `(deps): PKG@VERSION`, where `` is any of the usual `conventional-changelog` prefixes, at your discretion. +- Go to https://github.com/neoclide/coc.nvim/pulls and open a new pull request with your changes. +- If your PR is connected to an open issue, add a line in your PR's description that says `Fixes: #123`, where `#123` is the number of the issue you're fixing. + +Once you've filed the PR: + +- Barring special circumstances, maintainers will not review PRs until all checks pass (Travis, AppVeyor, etc). +- One or more maintainers will use GitHub's review feature to review your PR. +- If the maintainer asks for any changes, edit your changes, push, and ask for another review. Additional tags (such as `needs-tests`) will be added depending on the review. +- If the maintainer decides to pass on your PR, they will thank you for the contribution and explain why they won't be accepting the changes. That's ok! We still really appreciate you taking the time to do it, and we don't take that lightly. 💚 +- If your PR gets accepted, it will be marked as such, and merged into the `latest` branch soon after. Your contribution will be distributed to the masses next time the maintainers [tag a release](#tag-a-release) + +## Provide Support on Issues + +[Needs Collaborator](#join-the-project-team): none + +Helping out other users with their questions is a really awesome way of contributing to any community. It's not uncommon for most of the issues on an open source projects being support-related questions by users trying to understand something they ran into, or find their way around a known bug. + +Sometimes, the `support` label will be added to things that turn out to actually be other things, like bugs or feature requests. In that case, suss out the details with the person who filed the original issue, add a comment explaining what the bug is, and change the label from `support` to `bug` or `feature`. If you can't do this yourself, @mention a maintainer so they can do it. + +In order to help other folks out with their questions: + +- Go to the issue tracker and [filter open issues by the `support` label](https://github.com/neoclide/coc.nvim/issues?q=is%3Aopen+is%3Aissue+label%3Asupport). +- Read through the list until you find something that you're familiar enough with to give an answer to. +- Respond to the issue with whatever details are needed to clarify the question, or get more details about what's going on. +- Once the discussion wraps up and things are clarified, either close the issue, or ask the original issue filer (or a maintainer) to close it for you. + +Some notes on picking up support issues: + +- Avoid responding to issues you don't know you can answer accurately. +- As much as possible, try to refer to past issues with accepted answers. Link to them from your replies with the `#123` format. +- Be kind and patient with users -- often, folks who have run into confusing things might be upset or impatient. This is ok. Try to understand where they're coming from, and if you're too uncomfortable with the tone, feel free to stay away or withdraw from the issue. (note: if the user is outright hostile or is violating the CoC, [refer to the Code of Conduct](CODE_OF_CONDUCT.md) to resolve the conflict). + +## Review Pull Requests + +[Needs Collaborator](#join-the-project-team): Issue Tracker + +While anyone can comment on a PR, add feedback, etc, PRs are only _approved_ by team members with Issue Tracker or higher permissions. + +PR reviews use [GitHub's own review feature](https://help.github.com/articles/about-pull-request-reviews/), which manages comments, approval, and review iteration. + +Some notes: + +- You may ask for minor changes ("nitpicks"), but consider whether they are really blockers to merging: try to err on the side of "approve, with comments". +- _ALL PULL REQUESTS_ should be covered by a test: either by a previously-failing test, an existing test that covers the entire functionality of the submitted code, or new tests to verify any new/changed behavior. All tests must also pass and follow established conventions. Test coverage should not drop, unless the specific case is considered reasonable by maintainers. +- Please make sure you're familiar with the code or documentation being updated, unless it's a minor change (spellchecking, minor formatting, etc). You may @mention another project member who you think is better suited for the review, but still provide a non-approving review of your own. +- Be extra kind: people who submit code/doc contributions are putting themselves in a pretty vulnerable position, and have put time and care into what they've done (even if that's not obvious to you!) -- always respond with respect, be understanding, but don't feel like you need to sacrifice your standards for their sake, either. Just don't be a jerk about it? + +## Join the Project Team + +### Ways to Join + +There are many ways to contribute! Most of them don't require any official status unless otherwise noted. That said, there's a couple of positions that grant special repository abilities, and this section describes how they're granted and what they do. + +All of the below positions are granted based on the project team's needs, as well as their consensus opinion about whether they would like to work with the person and think that they would fit well into that position. The process is relatively informal, and it's likely that people who express interest in participating can just be granted the permissions they'd like. + +You can spot a collaborator on the repo by looking for the `[Collaborator]` or `[Owner]` tags next to their names. + +| Permission | Description | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Issue Tracker | Granted to contributors who express a strong interest in spending time on the project's issue tracker. These tasks are mainly [labeling issues](#label-issues), [cleaning up old ones](#clean-up-issues-and-prs), and [reviewing pull requests](#review-pull-requests), as well as all the usual things non-team-member contributors can do. Issue handlers should not merge pull requests, tag releases, or directly commit code themselves: that should still be done through the usual pull request process. Becoming an Issue Handler means the project team trusts you to understand enough of the team's process and context to implement it on the issue tracker. | +| Committer | Granted to contributors who want to handle the actual pull request merges, tagging new versions, etc. Committers should have a good level of familiarity with the codebase, and enough context to understand the implications of various changes, as well as a good sense of the will and expectations of the project team. | +| Admin/Owner | Granted to people ultimately responsible for the project, its community, etc. | diff --git a/vim-config/plugins/coc.nvim/LICENSE.md b/vim-config/plugins/coc.nvim/LICENSE.md index bee2bf1d..2a5396de 100644 --- a/vim-config/plugins/coc.nvim/LICENSE.md +++ b/vim-config/plugins/coc.nvim/LICENSE.md @@ -1,4 +1,4 @@ -Copyright 2018-2018 by Qiming Zhao aaa +Copyright 2018-2018 by Qiming Zhao 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: diff --git a/vim-config/plugins/coc.nvim/Readme.md b/vim-config/plugins/coc.nvim/README.md similarity index 86% rename from vim-config/plugins/coc.nvim/Readme.md rename to vim-config/plugins/coc.nvim/README.md index 1b989f0e..cc215f87 100644 --- a/vim-config/plugins/coc.nvim/Readme.md +++ b/vim-config/plugins/coc.nvim/README.md @@ -4,9 +4,10 @@

Make your Vim/Neovim as smart as VSCode.

- Software License + Software License Actions - Doc + Codecov Coverage Status + Doc Gitter

@@ -26,10 +27,10 @@ _True snippet and additional text editing support_ ## Quick Start -Install [nodejs](https://nodejs.org/en/download/) >= 10.12: +Install [nodejs](https://nodejs.org/en/download/) >= 12.12: -```sh -curl -sL install-node.now.sh/lts | bash +```bash +curl -sL install-node.vercel.app/lts | bash ``` For [vim-plug](https://github.com/junegunn/vim-plug) users: @@ -232,7 +233,7 @@ command! -nargs=0 Format :call CocAction('format') command! -nargs=? Fold :call CocAction('fold', ) " Add `:OR` command for organize imports of the current buffer. -command! -nargs=0 OR :call CocAction('runCommand', 'editor.action.organizeImport') +command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport') " Add (Neo)Vim's native statusline support. " NOTE: Please see `:h coc-status` for integrations with external plugins that @@ -312,13 +313,21 @@ Try these steps when you have problem with coc.nvim. + + + + + + + + + -## Supporters +## Support the project - - +Buy cloud service from [www.vultr.com](https://www.vultr.com/?ref=8890170-6G) ## License diff --git a/vim-config/plugins/coc.nvim/autoload/coc.vim b/vim-config/plugins/coc.nvim/autoload/coc.vim index aa20612f..e7bf2dfc 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc.vim @@ -50,11 +50,14 @@ endfunction function! coc#_complete() abort let items = get(g:coc#_context, 'candidates', []) let preselect = get(g:coc#_context, 'preselect', -1) - call complete( - \ g:coc#_context.start + 1, - \ items) + let startcol = g:coc#_context.start + 1 if s:select_api && len(items) && preselect != -1 + noa call complete(startcol, items) call nvim_select_popupmenu_item(preselect, v:false, v:false, {}) + " use specific key to preselect item at once + call feedkeys("\\" , 'i') + else + call complete(startcol, items) endif return '' endfunction @@ -117,10 +120,10 @@ endfunction function! coc#status() let info = get(b:, 'coc_diagnostic_info', {}) let msgs = [] - if get(info, 'error', 0) + if !empty(info) && get(info, 'error', 0) call add(msgs, s:error_sign . info['error']) endif - if get(info, 'warning', 0) + if !empty(info) && get(info, 'warning', 0) call add(msgs, s:warning_sign . info['warning']) endif return s:trim(join(msgs, ' ') . ' ' . get(g:, 'coc_status', '')) diff --git a/vim-config/plugins/coc.nvim/autoload/coc/api.vim b/vim-config/plugins/coc.nvim/autoload/coc/api.vim index 23c7b9cf..3dc4ae31 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/api.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/api.vim @@ -2,7 +2,7 @@ " Description: Client api used by vim8 " Author: Qiming Zhao " Licence: MIT licence -" Last Modified: Nov 11, 2020 +" Last Modified: Aug 10, 2021 " ============================================================================ if has('nvim') | finish | endif scriptencoding utf-8 @@ -16,6 +16,13 @@ function! s:buf_line_count(bufnr) abort if bufnr('%') == a:bufnr return line('$') endif + if exists('*getbufinfo') + let info = getbufinfo(a:bufnr) + if empty(info) + return 0 + endif + return info[0]['linecount'] + endif if exists('*getbufline') let lines = getbufline(a:bufnr, 1, '$') return len(lines) @@ -73,14 +80,20 @@ function! s:funcs.list_wins() abort return map(getwininfo(), 'v:val["winid"]') endfunction +function s:inspect_type(v) abort + let types = ['Number', 'String', 'Funcref', 'List', 'Dictionary', 'Float', 'Boolean', 'Null'] + return get(types, type(a:v), 'Unknown') +endfunction + function! s:funcs.call_atomic(calls) let res = [] - for [key, arglist] in a:calls + for i in range(len(a:calls)) + let [key, arglist] = a:calls[i] let name = key[5:] try call add(res, call(s:funcs[name], arglist)) catch /.*/ - return [res, v:exception] + return [res, [i, "VimException(".s:inspect_type(v:exception).")", v:exception]] endtry endfor return [res, v:null] @@ -109,6 +122,12 @@ function! s:funcs.command(command) abort call timer_start(0, {-> s:execute(a:command)}) else execute a:command + let err = get(g:, 'errmsg', '') + " get error from python script run. + if !empty(err) + unlet g:errmsg + throw err + endif endif endfunction @@ -187,14 +206,18 @@ endfunction function! s:funcs.out_write(str) echon a:str + call timer_start(0, {-> s:execute('redraw')}) endfunction function! s:funcs.err_write(str) - echoerr a:str + "echoerr a:str endfunction function! s:funcs.err_writeln(str) - echoerr a:str + echohl ErrorMsg + echom a:str + echohl None + call timer_start(0, {-> s:execute('redraw')}) endfunction function! s:funcs.create_namespace(name) abort @@ -275,7 +298,6 @@ function! s:funcs.buf_add_highlight(bufnr, srcId, hlGroup, line, colStart, colEn catch /^Vim\%((\a\+)\)\=:E967/ " ignore 967 endtry - let g:i = srcId if a:srcId == 0 " return generated srcId return srcId @@ -401,7 +423,7 @@ function! s:funcs.buf_set_var(bufnr, name, val) endfunction function! s:funcs.buf_del_var(bufnr, name) - call setbufvar(a:bufnr, a:name, v:null) + call coc#compat#buf_del_var(a:bufnr, a:name) endfunction function! s:funcs.buf_get_option(bufnr, name) @@ -458,26 +480,40 @@ else endfunction endif +function! s:get_tabnr(winid) abort + let ref = {} + call s:win_execute(a:winid, 'tabpagenr()', ref) + return get(ref, 'out', 0) +endfunction + function! s:funcs.win_get_cursor(win_id) abort let ref = {} call s:win_execute(a:win_id, "[line('.'), col('.')-1]", ref) - return ref['out'] + return get(ref, 'out', 0) endfunction function! s:funcs.win_get_var(win_id, name) abort - return gettabwinvar(0, a:win_id, a:name) + let tabnr = s:get_tabnr(a:win_id) + if tabnr + return gettabwinvar(tabnr, a:win_id, a:name) + endif + throw 'window '.a:win_id. ' not a valid window' endfunction function! s:funcs.win_set_width(win_id, width) abort - return s:win_execute(a:win_id, 'vertical resize '.a:width) + call s:win_execute(a:win_id, 'vertical resize '.a:width) endfunction function! s:funcs.win_set_buf(win_id, buf_id) abort - return s:win_execute(a:win_id, 'buffer '.a:buf_id) + call s:win_execute(a:win_id, 'buffer '.a:buf_id) endfunction function! s:funcs.win_get_option(win_id, name) abort - return gettabwinvar(0, a:win_id, '&'.a:name) + let tabnr = s:get_tabnr(a:win_id) + if tabnr + return gettabwinvar(tabnr, a:win_id, '&'.a:name) + endif + throw 'window '.a:win_id. ' not a valid window' endfunction function! s:funcs.win_set_height(win_id, height) abort @@ -491,20 +527,30 @@ function! s:funcs.win_set_option(win_id, name, value) abort elseif val is v:false let val = 0 endif - call setwinvar(a:win_id, '&'.a:name, val) + let tabnr = s:get_tabnr(a:win_id) + if tabnr + call settabwinvar(tabnr, a:win_id, '&'.a:name, val) + else + throw 'window '.a:win_id. ' not a valid window' + endif endfunction function! s:funcs.win_set_var(win_id, name, value) abort - call setwinvar(a:win_id, a:name, a:value) + let tabnr = s:get_tabnr(a:win_id) + if tabnr + call settabwinvar(tabnr, a:win_id, a:name, a:value) + else + throw 'window '.a:win_id. ' not a valid window' + endif endfunction function! s:funcs.win_del_var(win_id, name) abort - call settabwinvar(0, a:win_id, a:name, v:null) + call s:win_execute(a:win_id, 'unlet! w:'.a:name) endfunction function! s:funcs.win_is_valid(win_id) abort let info = getwininfo(a:win_id) - return !empty(info) + return empty(info) ? v:false : v:true endfunction function! s:funcs.win_get_number(win_id) abort @@ -521,15 +567,16 @@ function! s:funcs.win_set_cursor(win_id, pos) abort endfunction function! s:funcs.win_close(win_id, ...) abort - call s:win_execute(a:win_id, 'close!') + let force = get(a:, 1, 0) + call s:win_execute(a:win_id, 'close'.(force ? '!' : '')) endfunction function! s:funcs.win_get_tabpage(win_id) abort - let info = getwininfo(a:win_id) - if !info + let tabnr = s:get_tabnr(a:win_id) + if !tabnr throw 'Invalid window id '.a:win_id endif - return info[0]['tabnr'] + return tabnr endfunction " }} diff --git a/vim-config/plugins/coc.nvim/autoload/coc/client.vim b/vim-config/plugins/coc.nvim/autoload/coc/client.vim index bbd87338..6987ebbf 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/client.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/client.vim @@ -56,7 +56,6 @@ function! s:start() dict \ 'VIM_NODE_RPC': '1', \ 'COC_NVIM': '1', \ 'COC_CHANNEL_TIMEOUT': timeout, - \ 'COC_NO_WARNINGS': disable_warning, \ 'TMPDIR': tmpdir, \ } \} @@ -73,35 +72,42 @@ function! s:start() dict let self['running'] = 1 let self['channel'] = job_getchannel(job) else - let original = {'tmpdir': $TMPDIR} - " env option not work on neovim - if exists('*setenv') + let original = {} + let opts = { + \ 'rpc': 1, + \ 'on_stderr': {channel, msgs -> s:on_stderr(self.name, msgs)}, + \ 'on_exit': {channel, code -> s:on_exit(self.name, code)}, + \ } + if has('nvim-0.5.0') + " could use env option + let opts['env'] = { + \ 'NODE_NO_WARNINGS': '1', + \ 'COC_CHANNEL_TIMEOUT': timeout, + \ 'TMPDIR': tmpdir + \ } + else let original = { \ 'NODE_NO_WARNINGS': getenv('NODE_NO_WARNINGS'), - \ 'COC_CHANNEL_TIMEOUT': getenv('COC_CHANNEL_TIMEOUT'), - \ 'COC_NO_WARNINGS': getenv('COC_NO_WARNINGS'), \ 'TMPDIR': getenv('TMPDIR'), \ } - call setenv('NODE_NO_WARNINGS', '1') - call setenv('COC_CHANNEL_TIMEOUT', timeout) - call setenv('COC_NO_WARNINGS', disable_warning) - call setenv('TMPDIR', tmpdir) - else - let $NODE_NO_WARNINGS = 1 - let $COC_NO_WARNINGS = disable_warning - let $TMPDIR = tmpdir + if exists('*setenv') + call setenv('NODE_NO_WARNINGS', '1') + call setenv('COC_CHANNEL_TIMEOUT', timeout) + call setenv('TMPDIR', tmpdir) + else + let $NODE_NO_WARNINGS = 1 + let $TMPDIR = tmpdir + endif endif - let chan_id = jobstart(self.command, { - \ 'rpc': 1, - \ 'on_stderr': {channel, msgs -> s:on_stderr(self.name, msgs)}, - \ 'on_exit': {channel, code -> s:on_exit(self.name, code)}, - \}) - if exists('*setenv') - for key in keys(original) - call setenv(key, original[key]) - endfor - else - let $TMPDIR = original['tmpdir'] + let chan_id = jobstart(self.command, opts) + if !empty(original) + if exists('*setenv') + for key in keys(original) + call setenv(key, original[key]) + endfor + else + let $TMPDIR = original['TMPDIR'] + endif endif if chan_id <= 0 echohl Error | echom 'Failed to start '.self.name.' service' | echohl None @@ -132,10 +138,6 @@ function! s:on_exit(name, code) abort let client['channel'] = v:null let client['async_req_id'] = 1 if a:code != 0 && a:code != 143 - " could be syntax error - if a:code == 1 - call s:check_node() - endif echohl Error | echom 'client '.a:name. ' abnormal exit with: '.a:code | echohl None endif endfunction @@ -327,14 +329,3 @@ function! coc#client#open_log() endif execute 'vs '.s:logfile endfunction - -function! s:check_node() abort - let node = get(g:, 'coc_node_path', $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH) - let output = trim(system(node . ' --version')) - let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)') - if empty(ms) || str2nr(ms[1]) < 10 || (str2nr(ms[1]) == 10 && str2nr(ms[2]) < 12) - echohl Error - echon '[coc.nvim] Node version '.output.' < 10.12.0, please upgrade node.js or use g:coc_node_path variable.' - echohl None - endif -endfunction diff --git a/vim-config/plugins/coc.nvim/autoload/coc/compat.vim b/vim-config/plugins/coc.nvim/autoload/coc/compat.vim index 9507af85..d53c1098 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/compat.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/compat.vim @@ -11,6 +11,14 @@ function! coc#compat#buf_win_id(bufnr) abort return info[0]['winid'] endfunction +function! coc#compat#buf_set_lines(bufnr, start, end, replacement) abort + if s:is_vim + call coc#api#notify('buf_set_lines', [a:bufnr, a:start, a:end, 0, a:replacement]) + else + call nvim_buf_set_lines(a:bufnr, a:start, a:end, 0, a:replacement) + endif +endfunction + function! coc#compat#win_is_valid(winid) abort if exists('*nvim_win_is_valid') return nvim_win_is_valid(a:winid) @@ -63,13 +71,32 @@ function! coc#compat#matchaddpos(group, pos, priority, winid) abort endif endfunction +function! coc#compat#buf_del_var(bufnr, name) abort + if !bufloaded(a:bufnr) + return + endif + if exists('*nvim_buf_del_var') + silent! call nvim_buf_del_var(a:bufnr, a:name) + else + if bufnr == bufnr('%') + execute 'unlet! b:'.a:name + elseif exists('*win_execute') + let winid = coc#compat#buf_win_id(a:bufnr) + if winid != -1 + call win_execute(winid, 'unlet! b:'.a:name) + endif + endif + endif +endfunction + " hlGroup, pos, priority function! coc#compat#matchaddgroups(winid, groups) abort " add by winid - if s:is_vim && has('patch-8.1.0218') || has('nvim-0.4.0') + if has('patch-8.1.0218') || has('nvim-0.4.0') for group in a:groups call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1, {'window': a:winid}) endfor + return endif let curr = win_getid() if curr == a:winid @@ -85,7 +112,7 @@ function! coc#compat#matchaddgroups(winid, groups) abort endif endfunction -" remove keymap for specfic buffer +" remove keymap for specific buffer function! coc#compat#buf_del_keymap(bufnr, mode, lhs) abort if !bufloaded(a:bufnr) return @@ -110,25 +137,54 @@ function! coc#compat#buf_del_keymap(bufnr, mode, lhs) abort endif endfunction -" execute command or list of commands in window -function! coc#compat#execute(winid, command) abort - if s:is_vim - if !exists('*win_execute') - throw 'win_execute function not exists, please upgrade your vim.' +function! coc#compat#buf_add_keymap(bufnr, mode, lhs, rhs, opts) abort + if !bufloaded(a:bufnr) + return + endif + if exists('*nvim_buf_set_keymap') + call nvim_buf_set_keymap(a:bufnr, a:mode, a:lhs, a:rhs, a:opts) + else + let cmd = a:mode . 'noremap ' + for key in keys(a:opts) + if get(a:opts, key, 0) + let cmd .= '<'.key.'>' + endif + endfor + let cmd .= ' '.a:lhs.' '.a:rhs + if bufnr('%') == a:bufnr + execute cmd + elseif exists('*win_execute') + let winid = coc#compat#buf_win_id(a:bufnr) + if winid != -1 + call win_execute(winid, cmd) + endif endif + endif +endfunction + +" execute command or list of commands in window +function! coc#compat#execute(winid, command, ...) abort + if exists('*win_execute') if type(a:command) == v:t_string - keepalt call win_execute(a:winid, a:command) + keepalt call win_execute(a:winid, a:command, get(a:, 1, '')) elseif type(a:command) == v:t_list - keepalt call win_execute(a:winid, join(a:command, "\n")) + keepalt call win_execute(a:winid, join(a:command, "\n"), get(a:, 1, '')) + endif + elseif has('nvim') + if !nvim_win_is_valid(a:winid) + return endif - else let curr = nvim_get_current_win() noa keepalt call nvim_set_current_win(a:winid) if type(a:command) == v:t_string - exec a:command + exe get(a:, 1, '').' '.a:command elseif type(a:command) == v:t_list - exec join(a:command, "\n") + for cmd in a:command + exe get(a:, 1, '').' '.cmd + endfor endif noa keepalt call nvim_set_current_win(curr) + else + throw 'win_execute not exists, please upgrade vim.' endif endfunc diff --git a/vim-config/plugins/coc.nvim/autoload/coc/cursor.vim b/vim-config/plugins/coc.nvim/autoload/coc/cursor.vim new file mode 100644 index 00000000..f5ba66ad --- /dev/null +++ b/vim-config/plugins/coc.nvim/autoload/coc/cursor.vim @@ -0,0 +1,41 @@ +scriptencoding utf-8 + +" Position of cursor relative to screen cell +function! coc#cursor#screen_pos() abort + let nr = winnr() + let [row, col] = win_screenpos(nr) + return [row + winline() - 2, col + wincol() - 2] +endfunction + +function! coc#cursor#move_by_col(delta) + let pos = getcurpos() + call cursor(pos[1], pos[2] + a:delta) +endfunction + +" Get cursor position. +function! coc#cursor#position() + return [line('.') - 1, strchars(strpart(getline('.'), 0, col('.') - 1))] +endfunction + +" Move cursor to position. +function! coc#cursor#move_to(line, character) abort + let content = getline(a:line + 1) + let pre = strcharpart(content, 0, a:character) + let col = strlen(pre) + 1 + call cursor(a:line + 1, col) +endfunction + +" Character offset of current cursor, vim provide bytes offset only. +function! coc#cursor#char_offset() abort + let offset = 0 + let lnum = line('.') + for i in range(1, lnum) + if i == lnum + let offset += strchars(strpart(getline('.'), 0, col('.')-1)) + else + let offset += strchars(getline(i)) + 1 + endif + endfor + return offset +endfunction + diff --git a/vim-config/plugins/coc.nvim/autoload/coc/float.vim b/vim-config/plugins/coc.nvim/autoload/coc/float.vim index ece6f995..5cf6b8c3 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/float.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/float.vim @@ -1,5 +1,4 @@ scriptencoding utf-8 -" Related to float window create let s:is_vim = !has('nvim') let s:root = expand(':h:h:h') let s:progresschars = get(g:, 'coc_progress_chars', ['░', '▇']) @@ -8,6 +7,9 @@ let s:borderjoinchars = get(g:, 'coc_border_joinchars', ['┬', '┤', '┴', ' let s:prompt_win_width = get(g:, 'coc_prompt_win_width', 32) let s:prompt_win_bufnr = 0 let s:float_supported = exists('*nvim_open_win') || has('patch-8.1.1719') +let s:popup_list_api = exists('*popup_list') +" Popup ids, used when popup_list() not exists +let s:popup_list = [] " winvar: border array of numbers, button boolean " Check visible float/popup exists. @@ -52,6 +54,10 @@ endfunction " highlight all borders with first value. " - close: (optional) show close button when is 1. " - buttons: (optional) array of button text for create buttons at bottom. +" - codes: (optional) list of CodeBlock. +" - winblend: winblend option for float window, neovim only. +" - shadow: use shadow as border style, neovim only. +" - focusable: neovim only, default to true. function! coc#float#create_float_win(winid, bufnr, config) abort let lines = get(a:config, 'lines', v:null) let bufnr = coc#float#create_buf(a:bufnr, lines, 'hide') @@ -75,6 +81,7 @@ function! coc#float#create_float_win(winid, bufnr, config) abort endif call popup_setoptions(a:winid, opts) call coc#float#vim_buttons(a:winid, a:config) + call s:add_highlights(a:winid, a:config, 0) return [a:winid, winbufnr(a:winid)] else let config = s:convert_config_nvim(a:config) @@ -82,6 +89,7 @@ function! coc#float#create_float_win(winid, bufnr, config) abort call nvim_win_set_config(a:winid, config) call nvim_win_set_cursor(a:winid, [1, 0]) call coc#float#nvim_create_related(a:winid, config, a:config) + call s:add_highlights(a:winid, a:config, 0) return [a:winid, bufnr] endif endif @@ -108,13 +116,19 @@ function! coc#float#create_float_win(winid, bufnr, config) abort if get(a:config, 'close', 0) let opts['close'] = 'button' endif - if !empty(get(a:config, 'borderhighlight', [])) - let opts['borderhighlight'] = map(a:config['borderhighlight'], 'coc#highlight#compose_hlgroup(v:val,"'.hlgroup.'")') + if !empty(get(a:config, 'borderhighlight', v:null)) + let borderhighlight = a:config['borderhighlight'] + let opts['borderhighlight'] = type(borderhighlight) == 3 + \ ? map(borderhighlight, 'coc#highlight#compose_hlgroup(v:val,"'.hlgroup.'")') + \ : [coc#highlight#compose_hlgroup(borderhighlight, hlgroup)] endif if !s:empty_border(get(a:config, 'border', [])) let opts['border'] = a:config['border'] endif let winid = popup_create(bufnr, opts) + if !s:popup_list_api + call add(s:popup_list, winid) + endif if winid == 0 return [] endif @@ -124,6 +138,10 @@ function! coc#float#create_float_win(winid, bufnr, config) abort endif else let config = s:convert_config_nvim(a:config) + let border = get(a:config, 'border', []) + if has('nvim-0.5.0') && get(a:config, 'shadow', 0) && empty(get(a:config, 'buttons', v:null)) && empty(get(border, 2, 0)) + let config['border'] = 'shadow' + endif noa let winid = nvim_open_win(bufnr, 0, config) if winid == 0 return [] @@ -131,12 +149,18 @@ function! coc#float#create_float_win(winid, bufnr, config) abort let hlgroup = get(a:config, 'highlight', 'CocFloating') call setwinvar(winid, '&winhl', 'Normal:'.hlgroup.',NormalNC:'.hlgroup.',FoldColumn:'.hlgroup) call setwinvar(winid, '&signcolumn', 'no') + call setwinvar(winid, '&foldenable', 0) " cursorline highlight not work on old neovim call setwinvar(winid, '&cursorline', 0) call setwinvar(winid, 'border', get(a:config, 'border', [])) + if get(a:config, 'winblend', 0) + call setwinvar(winid, '&winblend', a:config['winblend']) + endif " no left border if s:empty_border(get(a:config, 'border', [])) || a:config['border'][3] == 0 call setwinvar(winid, '&foldcolumn', 1) + else + call setwinvar(winid, '&foldcolumn', 0) endif call nvim_win_set_cursor(winid, [1, 0]) call coc#float#nvim_create_related(winid, config, a:config) @@ -156,6 +180,7 @@ function! coc#float#create_float_win(winid, bufnr, config) abort call setwinvar(winid, '&wrap', 1) call setwinvar(winid, '&linebreak', 1) call setwinvar(winid, '&conceallevel', 0) + call s:add_highlights(winid, a:config, 0) let g:coc_last_float_win = winid call coc#util#do_autocmd('CocOpenFloat') return [winid, bufnr] @@ -182,24 +207,26 @@ function! coc#float#nvim_create_related(winid, config, opts) abort let title = get(a:opts, 'title', '') let buttons = get(a:opts, 'buttons', []) let pad = empty(border) || get(border, 1, 0) == 0 + let winblend = get(a:opts, 'winblend', 0) + let shadow = get(a:opts, 'shadow', 0) if get(a:opts, 'close', 0) - call coc#float#nvim_close_btn(a:config, a:winid, border, borderhighlight, related) + call coc#float#nvim_close_btn(a:config, a:winid, border, borderhighlight, winblend, related) elseif exists call coc#float#close_related(a:winid, 'close') endif if !empty(buttons) - call coc#float#nvim_buttons(a:config, a:winid, buttons, get(border, 2, 0), pad, hlgroup, borderhighlight, related) + call coc#float#nvim_buttons(a:config, a:winid, buttons, get(border, 2, 0), pad, hlgroup, borderhighlight, winblend, shadow, related) elseif exists call coc#float#close_related(a:winid, 'buttons') endif if !s:empty_border(border) - call coc#float#nvim_border_win(a:config, a:winid, border, title, !empty(buttons), borderhighlight, related) + call coc#float#nvim_border_win(a:config, a:winid, border, title, !empty(buttons), borderhighlight, winblend, shadow, related) elseif exists call coc#float#close_related(a:winid, 'border') endif " Check right border if pad - call coc#float#nvim_right_pad(a:config, a:winid, hlgroup, related) + call coc#float#nvim_right_pad(a:config, a:winid, hlgroup, winblend, related) elseif exists call coc#float#close_related(a:winid, 'pad') endif @@ -207,7 +234,7 @@ function! coc#float#nvim_create_related(winid, config, opts) abort endfunction " border window for neovim, content config with border -function! coc#float#nvim_border_win(config, winid, border, title, hasbtn, hlgroup, related) abort +function! coc#float#nvim_border_win(config, winid, border, title, hasbtn, hlgroup, winblend, shadow, related) abort let winid = coc#float#get_related(a:winid, 'border') let row = a:border[0] ? a:config['row'] - 1 : a:config['row'] let col = a:border[3] ? a:config['col'] - 1 : a:config['col'] @@ -225,12 +252,18 @@ function! coc#float#nvim_border_win(config, winid, border, title, hasbtn, hlgrou \ 'focusable': v:false, \ 'style': 'minimal', \ } + if has('nvim-0.5.0') && a:shadow && !a:hasbtn && a:border[2] + let opt['border'] = 'shadow' + endif if winid call nvim_win_set_config(winid, opt) call setwinvar(winid, '&winhl', 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup) else noa let winid = nvim_open_win(bufnr, 0, opt) if winid + if a:winblend + call setwinvar(winid, '&winblend', a:winblend) + endif call setwinvar(winid, '&winhl', 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup) call setwinvar(winid, 'target_winid', a:winid) call setwinvar(winid, 'kind', 'border') @@ -240,7 +273,7 @@ function! coc#float#nvim_border_win(config, winid, border, title, hasbtn, hlgrou endfunction " neovim only -function! coc#float#nvim_close_btn(config, winid, border, hlgroup, related) abort +function! coc#float#nvim_close_btn(config, winid, border, hlgroup, winblend, related) abort let winid = coc#float#get_related(a:winid, 'close') let config = { \ 'relative': a:config['relative'], @@ -251,6 +284,9 @@ function! coc#float#nvim_close_btn(config, winid, border, hlgroup, related) abor \ 'focusable': v:true, \ 'style': 'minimal', \ } + if has('nvim-0.5.0') + let config['zindex'] = 300 + endif if winid call nvim_win_set_config(winid, config) else @@ -260,6 +296,9 @@ function! coc#float#nvim_close_btn(config, winid, border, hlgroup, related) abor call setwinvar(winid, '&winhl', 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup) call setwinvar(winid, 'target_winid', a:winid) call setwinvar(winid, 'kind', 'close') + if a:winblend + call setwinvar(winid, '&winblend', a:winblend) + endif call add(a:related, winid) endif call s:nvim_create_keymap(winid) @@ -267,8 +306,9 @@ function! coc#float#nvim_close_btn(config, winid, border, hlgroup, related) abor endfunction " Create padding window by config of current window & border config -function! coc#float#nvim_right_pad(config, winid, hlgroup, related) abort +function! coc#float#nvim_right_pad(config, winid, hlgroup, winblend, related) abort let winid = coc#float#get_related(a:winid, 'pad') + let bufnr = 0 let config = { \ 'relative': a:config['relative'], \ 'width': 1, @@ -278,15 +318,28 @@ function! coc#float#nvim_right_pad(config, winid, hlgroup, related) abort \ 'focusable': v:false, \ 'style': 'minimal', \ } - if winid + if has('nvim-0.5.0') + let config['zindex'] = 300 + endif + if winid && nvim_win_is_valid(winid) + let bufnr = nvim_win_get_buf(winid) noa call nvim_win_close(winid, 1) endif - let bufnr = coc#float#create_buf(0, repeat([''], a:config['height'])) + let bufnr = coc#float#create_buf(bufnr, repeat([''], a:config['height'])) noa let winid = nvim_open_win(bufnr, 0, config) if winid - " neovim'bug: the content shown in window could be wired. - call setwinvar(winid, '&foldcolumn', 1) - call setwinvar(winid, '&winhl', 'FoldColumn:'.a:hlgroup) + " minimal not work + if !has('nvim-0.4.3') + call setwinvar(winid, '&colorcolumn', 0) + call setwinvar(winid, '&number', 0) + call setwinvar(winid, '&relativenumber', 0) + call setwinvar(winid, '&foldcolumn', 0) + call setwinvar(winid, '&signcolumn', 0) + endif + if a:winblend + call setwinvar(winid, '&winblend', a:winblend) + endif + call setwinvar(winid, '&winhl', 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup) call setwinvar(winid, 'target_winid', a:winid) call setwinvar(winid, 'kind', 'pad') call add(a:related, winid) @@ -294,7 +347,7 @@ function! coc#float#nvim_right_pad(config, winid, hlgroup, related) abort endfunction " draw buttons window for window with config -function! coc#float#nvim_buttons(config, winid, buttons, borderbottom, pad, hlgroup, borderhighlight, related) abort +function! coc#float#nvim_buttons(config, winid, buttons, borderbottom, pad, hlgroup, borderhighlight, winblend, shadow, related) abort let winid = coc#float#get_related(a:winid, 'buttons') let width = a:config['width'] + (a:pad ? 1 : 0) let config = { @@ -306,6 +359,12 @@ function! coc#float#nvim_buttons(config, winid, buttons, borderbottom, pad, hlgr \ 'focusable': 1, \ 'style': 'minimal', \ } + if has('nvim-0.5.0') + let config['zindex'] = 300 + if a:shadow + let config['border'] = 'shadow' + endif + endif if winid let bufnr = winbufnr(winid) call s:create_btns_buffer(bufnr, width, a:buttons, a:borderbottom) @@ -317,6 +376,9 @@ function! coc#float#nvim_buttons(config, winid, buttons, borderbottom, pad, hlgr call setwinvar(winid, '&winhl', 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup) call setwinvar(winid, 'target_winid', a:winid) call setwinvar(winid, 'kind', 'buttons') + if a:winblend + call setwinvar(winid, '&winblend', a:winblend) + endif call add(a:related, winid) call s:nvim_create_keymap(winid) endif @@ -338,11 +400,21 @@ endfunction " Create or refresh scrollbar for winid " Need called on create, config, buffer change, scrolled function! coc#float#nvim_scrollbar(winid) abort - if !has('nvim-0.4.0') || !coc#float#valid(a:winid) || getwinvar(a:winid, 'target_winid', 0) + if !has('nvim-0.4.0') || getwinvar(a:winid, 'target_winid', 0) + return + endif + let winids = nvim_tabpage_list_wins(nvim_get_current_tabpage()) + if index(winids, a:winid) == -1 return endif let config = nvim_win_get_config(a:winid) let [row, column] = nvim_win_get_position(a:winid) + let relative = 'editor' + if row == 0 && column == 0 + " fix bad value when ext_multigrid is enabled. https://github.com/neovim/neovim/issues/11935 + let [row, column] = [config.row, config.col] + let relative = config.relative + endif let width = nvim_win_get_width(a:winid) let height = nvim_win_get_height(a:winid) let bufnr = winbufnr(a:winid) @@ -350,30 +422,34 @@ function! coc#float#nvim_scrollbar(winid) abort let ch = coc#float#content_height(bufnr, cw, getwinvar(a:winid, '&wrap')) let closewin = coc#float#get_related(a:winid, 'close') let border = getwinvar(a:winid, 'border', []) + let winblend = getwinvar(a:winid, '&winblend', 0) let move_down = closewin && !get(border, 0, 0) - if move_down - let height = height - 1 - endif let id = coc#float#get_related(a:winid, 'scrollbar') - if ch <= height || height <= 0 + if ch <= height || height <= 1 " no scrollbar, remove exists if id call s:close_win(id) endif return endif + if move_down + let height = height - 1 + endif call coc#float#close_related(a:winid, 'pad') let sbuf = id ? winbufnr(id) : 0 let sbuf = coc#float#create_buf(sbuf, repeat([' '], height)) let opts = { \ 'row': move_down ? row + 1 : row, \ 'col': column + width, - \ 'relative': 'editor', + \ 'relative': relative, \ 'width': 1, \ 'height': height, \ 'focusable': v:false, \ 'style': 'minimal', \ } + if has('nvim-0.5.0') + let opts['zindex'] = 300 + endif if id call nvim_win_set_config(id, opts) else @@ -381,9 +457,14 @@ function! coc#float#nvim_scrollbar(winid) abort if id == 0 return endif + if winblend + call setwinvar(id, '&winblend', winblend) + endif call setwinvar(id, 'kind', 'scrollbar') call setwinvar(id, 'target_winid', a:winid) + call s:add_related(id, a:winid) endif + call coc#float#nvim_scroll_adjust(a:winid) let thumb_height = max([1, float2nr(floor(height * (height + 0.0)/ch))]) let wininfo = getwininfo(a:winid)[0] let start = 0 @@ -407,7 +488,6 @@ function! coc#float#nvim_scrollbar(winid) abort call nvim_buf_add_highlight(sbuf, -1, 'PmenuSbar', idx, 0, 1) endif endfor - call s:add_related(id, a:winid) endfunction function! coc#float#create_border_lines(border, title, width, height, hasbtn) abort @@ -467,25 +547,24 @@ function! coc#float#create_cursor_float(winid, bufnr, lines, config) abort return v:null endif let width = dimension['width'] - let lines = map(a:lines, {_, s -> s =~# '^—' ? repeat('—', width) : s}) - let config = extend({'lines': lines, 'relative': 'cursor'}, a:config) - let config = extend(config, dimension) + let lines = map(a:lines, {_, s -> s =~# '^─' ? repeat('─', width) : s}) + let config = extend(extend({'lines': lines, 'relative': 'cursor'}, a:config), dimension) call coc#float#close_auto_hide_wins(a:winid) let res = coc#float#create_float_win(a:winid, a:bufnr, config) if empty(res) return v:null endif + let alignTop = dimension['row'] < 0 let winid = res[0] let bufnr = res[1] - call coc#highlight#add_highlights(winid, get(a:config, 'codes', []), get(a:config, 'highlights', [])) redraw if has('nvim') call coc#float#nvim_scrollbar(winid) endif - return [currbuf, pos, winid, bufnr] + return [currbuf, pos, winid, bufnr, alignTop] endfunction -" Create float window for input, neovim only since vim doesn't support focus +" Create float window for input function! coc#float#create_prompt_win(title, default, opts) abort call coc#float#close_auto_hide_wins() " Calculate col @@ -496,7 +575,7 @@ function! coc#float#create_prompt_win(title, default, opts) abort else let col = curr + width <= &columns - 2 ? 0 : &columns - s:prompt_win_width endif - let [lineIdx, colIdx] = coc#util#cursor_pos() + let [lineIdx, colIdx] = coc#cursor#screen_pos() let bufnr = 0 if has('nvim') let bufnr = s:prompt_win_bufnr @@ -520,7 +599,7 @@ function! coc#float#create_prompt_win(title, default, opts) abort \ 'border': [1,1,1,1], \ 'prompt': 1, \ 'title': a:title, - \ 'lines': [a:default], + \ 'lines': s:is_vim ? v:null : [a:default], \ 'highlight': get(a:opts, 'highlight', 'CocFloating'), \ 'borderhighlight': [get(a:opts, 'borderhighlight', 'CocFloating')], \ }) @@ -535,21 +614,15 @@ function! coc#float#create_prompt_win(title, default, opts) abort call nvim_set_current_win(winid) inoremap inoremap pumvisible() ? "\" : "\" - exe 'inoremap =coc#float#close_i('.winid.')' + exe 'imap ' exe 'nnoremap :call coc#float#close('.winid.')' exe 'inoremap "\=coc#float#prompt_insert(getline(''.''))\\"' call feedkeys('A', 'in') - else - call setbufvar(bufnr, '&termwinkey', '') endif + call coc#util#do_autocmd('CocOpenFloatPrompt') return [bufnr, winid] endfunction -function! coc#float#close_i(winid) abort - call coc#float#close(a:winid) - return '' -endfunction - function! coc#float#prompt_insert(text) abort call coc#rpc#notify('PromptInsert', [a:text]) return '' @@ -575,11 +648,9 @@ function! coc#float#get_float_win() abort endif endif endfor - elseif exists('*popup_list') - let arr = filter(popup_list(), 'popup_getpos(v:val)["visible"]') - if !empty(arr) - return arr[0] - endif + else + let ids = s:popup_list_api ? popup_list() : s:popup_list + return get(filter(ids, 's:popup_visible(v:val)'), 0, 0) endif return 0 endfunction @@ -587,8 +658,11 @@ endfunction function! coc#float#get_float_win_list(...) abort let res = [] let all = get(a:, 1, 0) - if s:is_vim && exists('*popup_list') - return filter(popup_list(), 'popup_getpos(v:val)["visible"]'.(all ? '' : '&& getwinvar(v:val, "float", 0)')) + if s:is_vim + if s:popup_list_api + return filter(popup_list(), 'popup_getpos(v:val)["visible"]'.(all ? '' : '&& getwinvar(v:val, "float", 0)')) + endif + return filter(s:popup_list, 's:popup_visible(v:val)') elseif has('nvim') && exists('*nvim_win_get_config') let res = [] for i in range(1, winnr('$')) @@ -765,22 +839,27 @@ endfunction " Close related windows, or specific kind function! coc#float#close_related(winid, ...) abort - let timer = getwinvar(a:winid, 'timer', 0) - if timer - call timer_stop(timer) - endif - let kind = get(a:, 1, '') - let winids = filter(coc#float#get_float_win_list(1), 'getwinvar(v:val, "target_winid", 0) == '.a:winid) - for id in winids - if s:is_vim - " vim doesn't throw - call popup_close(id) - elseif nvim_win_is_valid(id) - if empty(kind) || getwinvar(id, 'kind', '') ==# kind - noa call nvim_win_close(id, 1) - endif + let tabnr = coc#window#tabnr(a:winid) + if tabnr != -1 + let timer = gettabwinvar(tabnr, a:winid, 'timer', 0) + if timer + call timer_stop(timer) endif - endfor + let kind = get(a:, 1, '') + let winids = gettabwinvar(tabnr, a:winid, 'related', []) + for id in winids + if s:is_vim + " vim doesn't throw + noa call popup_close(id) + else + if empty(kind) || gettabwinvar(tabnr, id, 'kind', '') ==# kind + if nvim_win_is_valid(id) + noa call nvim_win_close(id, 1) + endif + endif + endif + endfor + endif endfunction " Close related windows if target window is not visible. @@ -793,6 +872,9 @@ function! coc#float#check_related() abort call add(invalids, id) endif endfor + if !s:popup_list_api + let s:popup_list = filter(ids, "index(invalids, v:val) == -1") + endif for id in invalids call coc#float#close(id) endfor @@ -825,7 +907,7 @@ function! coc#float#get_config_cursor(lines, config) abort let ch += float2nr(ceil(str2float(string(dw))/(maxWidth - 2))) endfor let width = coc#helper#min(maxWidth, width) - let [lineIdx, colIdx] = coc#util#cursor_pos() + let [lineIdx, colIdx] = coc#cursor#screen_pos() " How much we should move left let offsetX = coc#helper#min(get(a:config, 'offsetX', 0), colIdx) let showTop = 0 @@ -856,7 +938,9 @@ function! coc#float#create_pum_float(winid, bufnr, lines, config) abort let rp = &columns - pumbounding['col'] - pw let showRight = pumbounding['col'] > rp ? 0 : 1 let maxWidth = showRight ? coc#helper#min(rp - 1, a:config['maxWidth']) : coc#helper#min(pumbounding['col'] - 1, a:config['maxWidth']) - let maxHeight = &lines - pumbounding['row'] - &cmdheight - 1 + let border = get(a:config, 'border', []) + let bh = get(border, 0 ,0) + get(border, 2, 0) + let maxHeight = &lines - pumbounding['row'] - &cmdheight - 1 - bh if maxWidth <= 2 || maxHeight < 1 return v:null endif @@ -869,7 +953,7 @@ function! coc#float#create_pum_float(winid, bufnr, lines, config) abort endfor let width = float2nr(coc#helper#min(maxWidth, width)) let height = float2nr(coc#helper#min(maxHeight, ch)) - let lines = map(a:lines, {_, s -> s =~# '^—' ? repeat('—', width - 2 + (s:is_vim && ch > height ? -1 : 0)) : s}) + let lines = map(a:lines, {_, s -> s =~# '^─' ? repeat('─', width - 2 + (s:is_vim && ch > height ? -1 : 0)) : s}) let opts = { \ 'lines': lines, \ 'relative': 'editor', @@ -877,15 +961,19 @@ function! coc#float#create_pum_float(winid, bufnr, lines, config) abort \ 'row': pumbounding['row'], \ 'height': height, \ 'width': width - 2 + (s:is_vim && ch > height ? -1 : 0), + \ 'codes': get(a:config, 'codes', []), \ } + for key in ['border', 'highlight', 'borderhighlight', 'winblend', 'focusable', 'shadow'] + if has_key(a:config, key) + let opts[key] = a:config[key] + endif + endfor call coc#float#close_auto_hide_wins(a:winid) let res = coc#float#create_float_win(a:winid, a:bufnr, opts) if empty(res) return v:null endif - call coc#highlight#add_highlights(res[0], a:config['codes'], a:config['highlights']) call setwinvar(res[0], 'kind', 'pum') - redraw if has('nvim') call coc#float#nvim_scrollbar(res[0]) endif @@ -1050,6 +1138,9 @@ function! coc#float#vim_buttons(winid, config) abort \ }, options) call extend(options, config) let winid = popup_create(bufnr, options) + if !s:popup_list_api + call add(s:popup_list, winid) + endif endif if winid != 0 if !empty(borderhighlight) @@ -1357,7 +1448,7 @@ function! coc#float#cursor_relative(winid) abort if winid == a:winid return v:null endif - let [cursorLine, cursorCol] = coc#util#cursor_pos() + let [cursorLine, cursorCol] = coc#cursor#screen_pos() if has('nvim') let [row, col] = nvim_win_get_position(a:winid) return {'row' : row - cursorLine, 'col' : col - cursorCol} @@ -1366,6 +1457,47 @@ function! coc#float#cursor_relative(winid) abort return {'row' : pos['line'] - cursorLine - 1, 'col' : pos['col'] - cursorCol - 1} endfunction +" Change border window & close window when scrollbar is shown. +function! coc#float#nvim_scroll_adjust(winid) abort + let winid = coc#float#get_related(a:winid, 'border') + if !winid + return + endif + let bufnr = winbufnr(winid) + let lines = nvim_buf_get_lines(bufnr, 0, -1, 0) + if len(lines) > 2 && coc#helper#last_character(lines[1]) ==# s:borderchars[1] + let cw = nvim_win_get_width(a:winid) + let width = nvim_win_get_width(winid) + if width - cw != 1 + (strcharpart(lines[1], 0, 1) ==# s:borderchars[3] ? 1 : 0) + return + endif + call nvim_win_set_width(winid, width + 1) + let lastline = len(lines) - 1 + for i in range(0, lastline) + let line = lines[i] + if i == 0 && strcharpart(lines[0], 0, 1) ==# s:borderchars[4] + let add = s:borderchars[0] + elseif i == lastline && strcharpart(lines[i], 0, 1) ==# s:borderchars[7] + let add = s:borderchars[2] + else + let add = ' ' + endif + let prev = strcharpart(line, 0, strchars(line) - 1) + let lines[i] = prev . add . coc#helper#last_character(line) + endfor + call nvim_buf_set_lines(bufnr, 0, -1, 0, lines) + let id = coc#float#get_related(a:winid, 'close') + if id + let [row, col] = nvim_win_get_position(id) + call nvim_win_set_config(id, { + \ 'relative': 'editor', + \ 'row': row, + \ 'col': col + 1, + \ }) + endif + endif +endfunction + " move winid include relative windows. function! s:adjust_win_row(winid, changed) abort let ids = getwinvar(a:winid, 'related', []) @@ -1514,13 +1646,20 @@ function! s:nvim_create_keymap(winid) abort if a:winid == 0 return endif - let curr = win_getid() - " nvim should support win_execute so we don't break visual mode. - let m = mode() - if m == 'n' || m == 'i' || m == 'ic' - noa call win_gotoid(a:winid) - nnoremap :call coc#float#nvim_float_click() - noa call win_gotoid(curr) + if exists('*nvim_buf_set_keymap') + let bufnr = winbufnr(a:winid) + call nvim_buf_set_keymap(bufnr, 'n', '', ':call coc#float#nvim_float_click()', { + \ 'silent': v:true, + \ 'nowait': v:true + \ }) + else + let curr = win_getid() + let m = mode() + if m == 'n' || m == 'i' || m == 'ic' + noa call win_gotoid(a:winid) + nnoremap :call coc#float#nvim_float_click() + noa call win_gotoid(curr) + endif endif endfunction @@ -1710,3 +1849,19 @@ function! s:str_compose(line, idx, text) abort let first = strcharpart(a:line, 0, a:idx) return first.a:text.strcharpart(a:line, a:idx + strwidth(a:text)) endfunction + +function! s:add_highlights(winid, config, create) abort + let codes = get(a:config, 'codes', []) + let highlights = get(a:config, 'highlights', []) + if empty(codes) && empty(highlights) && a:create + return + endif + let bgGroup = get(a:config, 'highlight', 'CocFloating') + for obj in codes + let hlGroup = get(obj, 'hlGroup', v:null) + if !empty(hlGroup) + let obj['hlGroup'] = coc#highlight#compose_hlgroup(hlGroup, bgGroup) + endif + endfor + call coc#highlight#add_highlights(a:winid, codes, highlights) +endfunction diff --git a/vim-config/plugins/coc.nvim/autoload/coc/helper.vim b/vim-config/plugins/coc.nvim/autoload/coc/helper.vim index a174603c..8bdc9b86 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/helper.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/helper.vim @@ -1,6 +1,64 @@ scriptencoding utf-8 " Helper methods for viml +function! coc#helper#get_charactor(line, col) abort + return strchars(strpart(a:line, 0, a:col - 1)) +endfunction + +function! coc#helper#last_character(line) abort + return strcharpart(a:line, strchars(a:line) - 1, 1) +endfunction + +function! coc#helper#obj_equal(one, two) abort + for key in keys(a:one) + if a:one[key] != a:two[key] + return 0 + endif + endfor + return 1 +endfunction + +" get change between two lines +function! coc#helper#str_diff(curr, previous, col) abort + let end = strpart(a:curr, a:col - 1) + let start = strpart(a:curr, 0, a:col -1) + let endOffset = 0 + let startOffset = 0 + let currLen = strchars(a:curr) + let prevLen = strchars(a:previous) + if len(end) + let endLen = strchars(end) + for i in range(min([prevLen, endLen])) + if strcharpart(end, endLen - 1 - i, 1) ==# strcharpart(a:previous, prevLen -1 -i, 1) + let endOffset = endOffset + 1 + else + break + endif + endfor + endif + let remain = endOffset == 0 ? a:previous : strcharpart(a:previous, 0, prevLen - endOffset) + if len(remain) + for i in range(min([strchars(remain), strchars(start)])) + if strcharpart(remain, i, 1) ==# strcharpart(start, i ,1) + let startOffset = startOffset + 1 + else + break + endif + endfor + endif + return { + \ 'start': startOffset, + \ 'end': prevLen - endOffset, + \ 'text': strcharpart(a:curr, startOffset, currLen - startOffset - endOffset) + \ } +endfunction + +function! coc#helper#str_apply(content, diff) abort + let totalLen = strchars(a:content) + let endLen = totalLen - a:diff['end'] + return strcharpart(a:content, 0, a:diff['start']).a:diff['text'].strcharpart(a:content, a:diff['end'], endLen) +endfunction + " insert inserted to line at position, use ... when result is too long " line should only contains character has strwidth equals 1 function! coc#helper#str_compose(line, position, inserted) abort diff --git a/vim-config/plugins/coc.nvim/autoload/coc/highlight.vim b/vim-config/plugins/coc.nvim/autoload/coc/highlight.vim index 33bc0a63..21ed5d72 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/highlight.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/highlight.vim @@ -1,6 +1,7 @@ scriptencoding utf-8 let s:is_vim = !has('nvim') let s:clear_match_by_window = has('nvim-0.5.0') || has('patch-8.1.1084') +let s:prop_offset = get(g:, 'coc_text_prop_offset', 1000) let s:namespace_map = {} let s:ns_id = 1 @@ -12,14 +13,200 @@ if has('nvim-0.5.0') endtry endif +" Get namespaced coc highlights from range of bufnr +" start - 0 based start line index +" end - 0 based end line index, could be -1 for last line (exclusive) +function! coc#highlight#get(bufnr, key, start, end) abort + if !has('nvim-0.5.0') && !exists('*prop_list') + throw 'Get highlights requires neovim 0.5.0 or vim support prop_list()' + endif + if !has_key(s:namespace_map, a:key) || !bufloaded(a:bufnr) + return {} + endif + let ns = coc#highlight#create_namespace(a:key) + let current = {} + if has('nvim-0.5.0') + let end = a:end == -1 ? [-1, -1] : [a:end - 1, 0] + let markers = nvim_buf_get_extmarks(a:bufnr, ns, [a:start, 0], end, {'details': v:true}) + for [_, row, start_col, details] in markers + let delta = details['end_row'] - row + if delta > 1 || (delta == 1 && details['end_col'] != 0) + " Don't known neovim's api for multiple lines markers. + continue + endif + let lines = getbufline(a:bufnr, row + 1) + if empty(lines) + " It's possible that markers exceeded last line. + continue + endif + let text = lines[0] + let curr = get(current, string(row), []) + call add(curr, { + \ 'hlGroup': details['hl_group'], + \ 'lnum': row, + \ 'colStart': start_col, + \ 'colEnd': delta == 1 ? strlen(text) : details['end_col'] + \ }) + let current[string(row)] = curr + endfor + else + let id = s:prop_offset + ns + " we could only get textprops line by line + let end = a:end == -1 ? getbufinfo(a:bufnr)[0]['linecount'] : a:end + for line in range(a:start + 1, end) + let items = [] + for prop in prop_list(line, {'bufnr': a:bufnr, 'id': id}) + " vim have support for cross line text props, but we're not using + call add(items, { + \ 'hlGroup': s:prop_type_hlgroup(prop['type']), + \ 'lnum': line - 1, + \ 'colStart': prop['col'] - 1, + \ 'colEnd': prop['col'] - 1 + prop['length'] - (prop['end'] == 0 ? 1 : 0), + \ }) + endfor + if !empty(items) + let current[string(line - 1)] = items + endif + endfor + endif + return current +endfunction + +" Update highlights by check exists highlights. +function! coc#highlight#update_highlights(bufnr, key, highlights, ...) abort + let bufnr = a:bufnr + if a:bufnr == 0 + let bufnr = bufnr('%') + endif + if !bufloaded(bufnr) + return + endif + let start = get(a:, 1, 0) + let end = get(a:, 2, -1) + if empty(a:highlights) + call coc#highlight#clear_highlight(bufnr, a:key, start, end) + return + endif + let total = len(a:highlights) + " index list that exists with current highlights + let exists = [] + let ns = coc#highlight#create_namespace(a:key) + let currIndex = 0 + if has('nvim-0.5.0') || exists('*prop_list') + let current = coc#highlight#get(bufnr, a:key, start, end) + for lnum in sort(map(keys(current), 'str2nr(v:val)'), {a, b -> a - b}) + let items = current[lnum] + let indexes = [] + let nextIndex = currIndex + if currIndex != total + for item in items + for i in range(currIndex, total - 1) + let hi = a:highlights[i] + if hi['lnum'] > item['lnum'] + let nextIndex = i + break + endif + if coc#helper#obj_equal(item, hi) + call add(indexes, i) + let nextIndex = max([nextIndex, i + 1]) + endif + endfor + endfor + endif + let currIndex = nextIndex + " all highlights of current line exists, not clear. + if len(indexes) == len(items) + let exists = exists + indexes + else + if has('nvim') + call nvim_buf_clear_namespace(bufnr, ns, lnum, lnum + 1) + else + call coc#api#call('buf_clear_namespace', [bufnr, ns, lnum, lnum + 1]) + endif + endif + endfor + if has('nvim') && end == -1 + let count = nvim_buf_line_count(bufnr) + " remove highlights exceed last line. + call nvim_buf_clear_namespace(bufnr, ns, count, -1) + endif + else + call coc#highlight#clear_highlight(bufnr, a:key, start, end) + endif + let indexes = range(0, total - 1) + if !empty(exists) + let indexes = filter(indexes, 'index(exists, v:val) == -1') + endif + for i in indexes + let hi = a:highlights[i] + call coc#highlight#add_highlight(bufnr, ns, hi['hlGroup'], hi['lnum'], hi['colStart'], hi['colEnd']) + endfor +endfunction + +function! coc#highlight#get_highlights(bufnr, key) abort + if !has_key(s:namespace_map, a:key) || !bufloaded(a:bufnr) + return [] + endif + let res = [] + let ns = s:namespace_map[a:key] + if exists('*prop_list') + let lines = getbufline(a:bufnr, 1, '$') + let linecount = len(lines) + for line in range(1, linecount) + for prop in prop_list(line, {'bufnr': a:bufnr, 'id': s:prop_offset + ns}) + if prop['start'] == 0 || prop['end'] == 0 + " multi line tokens are not supported; simply ignore it + continue + endif + let text = lines[line - 1] + call add(res, { + \ 'hlGroup': s:prop_type_hlgroup(prop['type']), + \ 'lnum': line - 1, + \ 'colStart': coc#helper#get_charactor(text, prop['col']), + \ 'colEnd': coc#helper#get_charactor(text, prop['col'] + prop['length']) + \ }) + endfor + endfor + elseif has('nvim-0.5.0') + let markers = nvim_buf_get_extmarks(a:bufnr, ns, 0, -1, {'details': v:true}) + let lines = getbufline(a:bufnr, 1, '$') + let total = len(lines) + for [_, line, start_col, details] in markers + if line >= total + " Could be markers exceed end of line + continue + endif + let text = lines[line] + let delta = details['end_row'] - line + if delta > 1 || (delta == 1 && details['end_col'] != 0) + " can't handle, single line only + continue + endif + call add(res, { + \ 'hlGroup': details['hl_group'], + \ 'lnum': line, + \ 'colStart': coc#helper#get_charactor(text, start_col + 1), + \ 'colEnd': delta == 1 ? strchars(text) : coc#helper#get_charactor(text, details['end_col'] + 1) + \ }) + endfor + else + throw 'Get highlights requires neovim 0.5.0 or vim support prop_list' + endif + return res +endfunction + " highlight LSP range, function! coc#highlight#ranges(bufnr, key, hlGroup, ranges) abort let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr if !bufloaded(bufnr) || !exists('*getbufline') return endif - let synmaxcol = min([getbufvar(a:bufnr, '&synmaxcol', 1000), 1000]) - let srcId = s:create_namespace(a:key) + let synmaxcol = getbufvar(a:bufnr, '&synmaxcol', 1000) + if synmaxcol == 0 + let synmaxcol = 1000 + endif + let synmaxcol = min([synmaxcol, 1000]) + let srcId = coc#highlight#create_namespace(a:key) for range in a:ranges let start = range['start'] let end = range['end'] @@ -56,7 +243,7 @@ function! coc#highlight#clear_highlight(bufnr, key, start_line, end_line) abort if !bufloaded(bufnr) return endif - let src_id = s:create_namespace(a:key) + let src_id = coc#highlight#create_namespace(a:key) if has('nvim') call nvim_buf_clear_namespace(a:bufnr, src_id, a:start_line, a:end_line) else @@ -94,7 +281,7 @@ endfunction " Add highlights to line groups of winid, support hlGroup and filetype -" config should have startLine, endLine (1 based, end excluded) and filetype or hlGroup +" config should have startLine, endLine (0 based, end excluded) and filetype or hlGroup " endLine should > startLine and endLine is excluded " " export interface CodeBlock { @@ -104,61 +291,80 @@ endfunction " endLine: number " } function! coc#highlight#highlight_lines(winid, blocks) abort - let currwin = win_getid() - let switch = has('nvim') && currwin != a:winid - if switch - noa call nvim_set_current_win(a:winid) - endif - let defined = [] let region_id = 1 + let defined = [] + let cmds = [] for config in a:blocks let start = config['startLine'] + 1 let end = config['endLine'] == -1 ? len(getbufline(winbufnr(a:winid), 1, '$')) + 1 : config['endLine'] + 1 let filetype = get(config, 'filetype', '') let hlGroup = get(config, 'hlGroup', '') if !empty(hlGroup) - call s:execute(a:winid, 'syntax region '.hlGroup.' start=/\%'.start.'l/ end=/\%'.end.'l/') + call add(cmds, 'syntax region '.hlGroup.' start=/\%'.start.'l/ end=/\%'.end.'l/') else let filetype = matchstr(filetype, '\v^\w+') if empty(filetype) || filetype == 'txt' || index(get(g:, 'coc_markdown_disabled_languages', []), filetype) != -1 continue endif if index(defined, filetype) == -1 - call s:execute(a:winid, 'syntax include @'.toupper(filetype).' syntax/'.filetype.'.vim') - if has('nvim') - unlet! b:current_syntax - elseif exists('*win_execute') - call win_execute(a:winid, 'unlet! b:current_syntax') - endif + call add(cmds, 'syntax include @'.toupper(filetype).' syntax/'.filetype.'.vim') + call add(cmds, 'unlet! b:current_syntax') call add(defined, filetype) endif - call s:execute(a:winid, 'syntax region CodeBlock'.region_id.' start=/\%'.start.'l/ end=/\%'.end.'l/ contains=@'.toupper(filetype)) + call add(cmds, 'syntax region CodeBlock'.region_id.' start=/\%'.start.'l/ end=/\%'.end.'l/ contains=@'.toupper(filetype).' keepend') let region_id = region_id + 1 endif endfor - if switch - noa call nvim_set_current_win(currwin) + if !empty(cmds) + call coc#compat#execute(a:winid, cmds, 'silent!') endif endfunction " Copmpose hlGroups with foreground and background colors. function! coc#highlight#compose_hlgroup(fgGroup, bgGroup) abort let hlGroup = 'Fg'.a:fgGroup.'Bg'.a:bgGroup - if a:fgGroup == a:bgGroup + if a:fgGroup ==# a:bgGroup return a:fgGroup endif if hlexists(hlGroup) return hlGroup endif - let fg = synIDattr(synIDtrans(hlID(a:fgGroup)), 'fg', 'gui') - let bg = synIDattr(synIDtrans(hlID(a:bgGroup)), 'bg', 'gui') - if fg =~# '^#' || bg =~# '^#' - call s:create_gui_hlgroup(hlGroup, fg, bg, '') - else - let fg = synIDattr(synIDtrans(hlID(a:fgGroup)), 'fg', 'cterm') - let bg = synIDattr(synIDtrans(hlID(a:bgGroup)), 'bg', 'cterm') - call s:create_cterm_hlgroup(hlGroup, fg, bg, '') + let fgId = synIDtrans(hlID(a:fgGroup)) + let bgId = synIDtrans(hlID(a:bgGroup)) + let isGuiReversed = synIDattr(fgId, 'reverse', 'gui') !=# '1' || synIDattr(bgId, 'reverse', 'gui') !=# '1' + let guifg = isGuiReversed ? synIDattr(fgId, 'fg', 'gui') : synIDattr(fgId, 'bg', 'gui') + let guibg = isGuiReversed ? synIDattr(bgId, 'bg', 'gui') : synIDattr(bgId, 'fg', 'gui') + let isCtermReversed = synIDattr(fgId, 'reverse', 'cterm') !=# '1' || synIDattr(bgId, 'reverse', 'cterm') !=# '1' + let ctermfg = isCtermReversed ? synIDattr(fgId, 'fg', 'cterm') : synIDattr(fgId, 'bg', 'cterm') + let ctermbg = isCtermReversed ? synIDattr(bgId, 'bg', 'cterm') : synIDattr(bgId, 'fg', 'cterm') + let bold = synIDattr(fgId, 'bold') ==# '1' + let italic = synIDattr(fgId, 'italic') ==# '1' + let underline = synIDattr(fgId, 'underline') ==# '1' + let cmd = 'silent hi ' . hlGroup + if !empty(guifg) + let cmd .= ' guifg=' . guifg endif + if !empty(ctermfg) + let cmd .= ' ctermfg=' . ctermfg + elseif guifg =~# '^#' + let cmd .= ' ctermfg=' . coc#color#rgb2term(strpart(guifg, 1)) + endif + if !empty(guibg) + let cmd .= ' guibg=' . guibg + endif + if !empty(ctermbg) + let cmd .= ' ctermbg=' . ctermbg + elseif guibg =~# '^#' + let cmd .= ' ctermbg=' . coc#color#rgb2term(strpart(guibg, 1)) + endif + if bold + let cmd .= ' cterm=bold gui=bold' + elseif italic + let cmd .= ' cterm=italic gui=italic' + elseif underline + let cmd .= ' cterm=underline gui=underline' + endif + execute cmd return hlGroup endfunction @@ -291,40 +497,14 @@ function! coc#highlight#clear_matches(winid, ids) endif endfunction -" Sets the highlighting for the given group -function! s:create_gui_hlgroup(group, fg, bg, attr) - if a:fg != "" - exec "silent hi " . a:group . " guifg=" . a:fg . " ctermfg=" . coc#color#rgb2term(strpart(a:fg, 1)) - endif - if a:bg != "" - exec "silent hi " . a:group . " guibg=" . a:bg . " ctermbg=" . coc#color#rgb2term(strpart(a:bg, 1)) - endif - if a:attr != "" - exec "silent hi " . a:group . " gui=" . a:attr . " cterm=" . a:attr - endif -endfun - -function! s:create_cterm_hlgroup(group, fg, bg, attr) abort - if a:fg != "" - exec "silent hi " . a:group . " ctermfg=" . a:fg - endif - if a:bg != "" - exec "silent hi " . a:group . " ctermbg=" . a:bg - endif - if a:attr != "" - exec "silent hi " . a:group . " cterm=" . a:attr - endif -endfunction - -function! s:execute(winid, cmd) abort - if has('nvim') - execute 'silent! ' a:cmd - else - call win_execute(a:winid, a:cmd, 'silent!') +function! s:prop_type_hlgroup(type) abort + if a:type=~# '^CocHighlight' + return a:type[12:] endif + return prop_type_get(a:type)['highlight'] endfunction -function! s:create_namespace(key) abort +function! coc#highlight#create_namespace(key) abort if type(a:key) == 0 return a:key endif @@ -339,3 +519,7 @@ function! s:create_namespace(key) abort endif return s:namespace_map[a:key] endfunction + +function! coc#highlight#get_syntax_name(lnum, col) + return synIDattr(synIDtrans(synID(a:lnum,a:col,1)),"name") +endfunction diff --git a/vim-config/plugins/coc.nvim/autoload/coc/list.vim b/vim-config/plugins/coc.nvim/autoload/coc/list.vim index fdce144e..b9be251d 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/list.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/list.vim @@ -141,15 +141,11 @@ function! coc#list#scroll_preview(dir) abort endfunction function! coc#list#restore(winid, height) - if has('nvim') - if nvim_win_is_valid(a:winid) - call nvim_win_set_height(a:winid, a:height) - endif - else - if exists('win_execute') - call win_execute(a:winid, 'noa resize '.a:height, 'silent!') - redraw - endif + if has('nvim') && nvim_win_is_valid(a:winid) + call nvim_win_set_height(a:winid, a:height) + elseif s:is_vim && exists('*win_execute') + call win_execute(a:winid, 'noa resize '.a:height, 'silent!') + redraw endif endfunction @@ -164,13 +160,13 @@ function! coc#list#hide(original, height, winid) abort if !empty(arr) && arr[0] != 0 silent! pclose! let previewwin = coc#list#get_preview(arr[0]) - call s:close_win(previewwin) + call coc#window#close(previewwin) endif if !empty(getwininfo(a:original)) call win_gotoid(a:original) endif if a:winid - call s:close_win(a:winid) + silent! call coc#window#close(a:winid) endif if !empty(a:height) && win_getid() == a:original if exists('*nvim_win_set_height') @@ -181,32 +177,6 @@ function! coc#list#hide(original, height, winid) abort endif endfunction -function! s:close_win(winid) abort - if empty(a:winid) || a:winid == -1 || empty(getwininfo(a:winid)) - return - endif - if s:is_vim - if exists('*win_execute') - noa call win_execute(a:winid, 'close!', 'silent!') - else - if win_getid() == a:winid - noa silent! close! - else - let winid = win_getid() - let res = win_gotoid(winid) - if res - noa silent! close! - noa wincmd p - endif - endif - endif - else - if nvim_win_is_valid(a:winid) - silent! noa call nvim_win_close(a:winid, 1) - endif - endif -endfunction - " Improve preview performance by reused window & buffer. " lines - list of lines " config.position - could be 'below' 'top' 'tab'. @@ -275,7 +245,7 @@ function! coc#list#preview(lines, config) abort execute 'noa '.mod.' sb +resize\ '.height.' '.bufnr let winid = win_getid() endif - noa call winrestview({"lnum": lnum ,"topline":max([1, lnum - 3])}) + noa call winrestview({"lnum": lnum ,"topline":s:get_topline(a:config, lnum, winid)}) call setwinvar(winid, '&signcolumn', 'no') call setwinvar(winid, '&number', 1) call setwinvar(winid, '&cursorline', 0) @@ -294,8 +264,9 @@ function! coc#list#preview(lines, config) abort call nvim_win_set_height(winid, height) endif endif - call coc#compat#execute(winid, ['syntax clear', 'noa call winrestview({"lnum":'.lnum.',"topline":'.max([1, lnum - 3]).'})']) + call coc#compat#execute(winid, ['syntax clear', 'noa call winrestview({"lnum":'.lnum.',"topline":'.s:get_topline(a:config, lnum, winid).'})']) endif + call setwinvar(winid, '&foldenable', 0) if s:prefix.' '.name != bufname(bufnr) if s:is_vim call win_execute(winid, 'noa file '.fnameescape(s:prefix.' '.name), 'silent!') @@ -341,3 +312,13 @@ function! s:load_buffer(name) abort endif return 0 endfunction + +function! s:get_topline(config, lnum, winid) abort + let toplineStyle = get(a:config, 'toplineStyle', 'offset') + if toplineStyle == 'middle' + return max([1, a:lnum - winheight(a:winid)/2]) + endif + + let toplineOffset = get(a:config, 'toplineOffset', 3) + return max([1, a:lnum - toplineOffset]) +endfunction diff --git a/vim-config/plugins/coc.nvim/autoload/coc/prompt.vim b/vim-config/plugins/coc.nvim/autoload/coc/prompt.vim index 5fdf9f14..cbe4a97b 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/prompt.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/prompt.vim @@ -21,7 +21,8 @@ let s:char_map = { \ "\": '', \ "\":'' , \ "\":'' , - \ "\":'' , + \ "\":'', + \ "\":'', \ "\": '', \ "\": '', \ "\": '', diff --git a/vim-config/plugins/coc.nvim/autoload/coc/task.vim b/vim-config/plugins/coc.nvim/autoload/coc/task.vim index 4a5befc5..d5b6e1e2 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/task.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/task.vim @@ -53,11 +53,15 @@ function! coc#task#start(id, opts) \ 'detach': get(a:opts, 'detach', 0), \} let original = {} - if !empty(env) && exists('*setenv') && exists('*getenv') - for key in keys(env) - let original[key] = getenv(key) - call setenv(key, env[key]) - endfor + if !empty(env) + if has('nvim-0.5.0') + let options['env'] = env + elseif exists('*setenv') && exists('*getenv') + for key in keys(env) + let original[key] = getenv(key) + call setenv(key, env[key]) + endfor + endif endif if get(a:opts, 'pty', 0) let options['pty'] = 1 diff --git a/vim-config/plugins/coc.nvim/autoload/coc/util.vim b/vim-config/plugins/coc.nvim/autoload/coc/util.vim index 1d70985d..f885b1ec 100644 --- a/vim-config/plugins/coc.nvim/autoload/coc/util.vim +++ b/vim-config/plugins/coc.nvim/autoload/coc/util.vim @@ -3,10 +3,10 @@ let s:root = expand(':h:h:h') let s:is_win = has('win32') || has('win64') let s:is_vim = !has('nvim') let s:clear_match_by_id = has('nvim-0.5.0') || has('patch-8.1.1084') -let s:vim_api_version = 8 - +let s:vim_api_version = 10 let s:activate = "" let s:quit = "" + if has("gui_macvim") && has('gui_running') let s:app = "MacVim" elseif $TERM_PROGRAM ==# "Apple_Terminal" @@ -19,6 +19,15 @@ elseif has('mac') let s:activate = 'activate' endif +function! coc#util#api_version() abort + return s:vim_api_version +endfunction + +" get cursor position +function! coc#util#cursor() + return [line('.') - 1, strchars(strpart(getline('.'), 0, col('.') - 1))] +endfunction + function! coc#util#has_preview() for i in range(1, winnr('$')) if getwinvar(i, '&previewwindow') @@ -28,13 +37,9 @@ function! coc#util#has_preview() return 0 endfunction -function! coc#util#api_version() abort - return s:vim_api_version -endfunction - -" get cursor position -function! coc#util#cursor() - return [line('.') - 1, strchars(strpart(getline('.'), 0, col('.') - 1))] +function! coc#util#jumpTo(line, character) abort + echohl WarningMsg | echon 'coc#util#jumpTo is deprecated, use coc#cursor#move_to instead.' | echohl None + call coc#cursor#move_to(a:line, a:character) endfunction function! coc#util#path_replace_patterns() abort @@ -72,6 +77,31 @@ function! coc#util#check_refresh(bufnr) return 1 endfunction +function! coc#util#diagnostic_info(bufnr, checkInsert) abort + let checked = coc#util#check_refresh(a:bufnr) + if !checked + return v:null + endif + if a:checkInsert && mode() =~# '^i' + return v:null + endif + let locationlist = '' + let winid = -1 + for info in getwininfo() + if info['bufnr'] == a:bufnr + let winid = info['winid'] + let locationlist = get(getloclist(winid, {'title': 1}), 'title', '') + break + endif + endfor + return { + \ 'bufnr': bufnr('%'), + \ 'winid': winid, + \ 'lnum': line('.'), + \ 'locationlist': locationlist + \ } +endfunction + function! coc#util#open_file(cmd, file) let file = fnameescape(a:file) execute a:cmd .' '.file @@ -99,10 +129,14 @@ function! coc#util#job_command() return endif if !filereadable(s:root.'/build/index.js') - echohl Error | echom '[coc.nvim] build/index.js not found, please compile coc.nvim by: npm run build' | echohl None + if isdirectory(s:root.'/src') + echohl Error | echom '[coc.nvim] build/index.js not found, please install dependencies and compile coc.nvim by: yarn install' | echohl None + else + echohl Error | echon '[coc.nvim] your coc.nvim is broken.' | echohl None + endif return endif - return [node] + get(g:, 'coc_node_args', ['--no-warnings']) + ['-r', s:root.'/bin/check.js', s:root.'/build/index.js'] + return [node] + get(g:, 'coc_node_args', ['--no-warnings']) + [s:root.'/build/index.js'] endfunction function! coc#util#echo_hover(msg) @@ -112,16 +146,6 @@ function! coc#util#echo_hover(msg) let g:coc_last_hover_message = a:msg endfunction -function! coc#util#execute(cmd) - silent exe a:cmd - if &filetype ==# '' - filetype detect - endif - if s:is_vim - redraw! - endif -endfunction - function! coc#util#jump(cmd, filepath, ...) abort if a:cmd != 'pedit' silent! normal! m' @@ -135,6 +159,14 @@ function! coc#util#jump(cmd, filepath, ...) abort let extra = empty(get(a:, 1, [])) ? '' : '+'.(a:1[0] + 1) exe 'pedit '.extra.' '.fnameescape(file) return + elseif a:cmd == 'drop' + let dstbuf = bufadd(path) + let binfo = getbufinfo(dstbuf) + if len(binfo) == 1 && empty(binfo[0].windows) + exec 'buffer '.dstbuf + else + exec 'drop '.fnameescape(file) + endif else exe a:cmd.' '.fnameescape(file) endif @@ -155,20 +187,6 @@ function! coc#util#jump(cmd, filepath, ...) abort endif endfunction -function! coc#util#jumpTo(line, character) abort - let content = getline(a:line + 1) - let pre = strcharpart(content, 0, a:character) - let col = strlen(pre) + 1 - call cursor(a:line + 1, col) -endfunction - -" Position of cursor relative to screen cell -function! coc#util#cursor_pos() abort - let nr = winnr() - let [row, col] = win_screenpos(nr) - return [row + winline() - 2, col + wincol() - 2] -endfunction - function! coc#util#echo_messages(hl, msgs) if a:hl !~# 'Error' && (mode() !~# '\v^(i|n)$') return @@ -205,11 +223,7 @@ function! coc#util#get_bufoptions(bufnr, maxFileSize) abort if !bufloaded(a:bufnr) | return v:null | endif let bufname = bufname(a:bufnr) let buftype = getbufvar(a:bufnr, '&buftype') - let previewwindow = 0 let winid = bufwinid(a:bufnr) - if winid != -1 - let previewwindow = getwinvar(winid, '&previewwindow', 0) - endif let size = -1 if bufnr('%') == a:bufnr let size = line2byte(line("$") + 1) @@ -225,7 +239,7 @@ function! coc#util#get_bufoptions(bufnr, maxFileSize) abort \ 'size': size, \ 'buftype': buftype, \ 'winid': winid, - \ 'previewwindow': previewwindow == 0 ? v:false : v:true, + \ 'previewwindow': v:false, \ 'variables': s:variables(a:bufnr), \ 'fullpath': empty(bufname) ? '' : fnamemodify(bufname, ':p'), \ 'eol': getbufvar(a:bufnr, '&eol'), @@ -255,10 +269,6 @@ function! coc#util#get_config(key) abort return coc#rpc#request('getConfig', [a:key]) endfunction -function! coc#util#on_error(msg) abort - echohl Error | echom '[coc.nvim] '.a:msg | echohl None -endfunction - function! coc#util#preview_info(info, filetype, ...) abort pclose keepalt new +setlocal\ previewwindow|setlocal\ buftype=nofile|setlocal\ noswapfile|setlocal\ wrap [Document] @@ -330,11 +340,6 @@ function! coc#util#get_input() return matchstr(before, '\k*$') endfunction -function! coc#util#move_cursor(delta) - let pos = getcurpos() - call cursor(pos[1], pos[2] + a:delta) -endfunction - function! coc#util#get_complete_option() let pos = getcurpos() let line = getline(pos[1]) @@ -401,10 +406,6 @@ function! coc#util#quickpick(title, items, cb) abort endif endfunction -function! coc#util#get_syntax_name(lnum, col) - return synIDattr(synIDtrans(synID(a:lnum,a:col,1)),"name") -endfunction - function! coc#util#echo_signatures(signatures) abort if pumvisible() | return | endif echo "" @@ -428,13 +429,6 @@ function! s:echo_signature(parts) endfor endfunction -function! coc#util#unplace_signs(bufnr, sign_ids) - if !bufloaded(a:bufnr) | return | endif - for id in a:sign_ids - execute 'silent! sign unplace '.id.' buffer='.a:bufnr - endfor -endfunction - function! coc#util#setline(lnum, line) keepjumps call setline(a:lnum, a:line) endfunction @@ -456,6 +450,9 @@ function! coc#util#open_terminal(opts) abort setl norelativenumber setl nonumber setl bufhidden=wipe + if exists('#User#CocTerminalOpen') + exe 'doautocmd User CocTerminalOpen' + endif let cmd = get(a:opts, 'cmd', '') let autoclose = get(a:opts, 'autoclose', 1) if empty(cmd) @@ -547,6 +544,7 @@ function! coc#util#vim_info() \ 'locationlist': get(g:,'coc_enable_locationlist', 1), \ 'progpath': v:progpath, \ 'guicursor': &guicursor, + \ 'updateHighlight': has('nvim-0.5.0') || exists('*prop_list') ? v:true : v:false, \ 'vimCommands': get(g:, 'coc_vim_commands', []), \ 'sign': exists('*sign_place') && exists('*sign_unplace'), \ 'textprop': has('textprop') && has('patch-8.1.1719') && !has('nvim') ? v:true : v:false, @@ -563,16 +561,31 @@ function! coc#util#highlight_options() \} endfunction -function! coc#util#set_lines(bufnr, replacement, start, end) abort - if !s:is_vim - call nvim_buf_set_lines(a:bufnr, a:start, a:end, 0, a:replacement) - else - call coc#api#notify('buf_set_lines', [a:bufnr, a:start, a:end, 0, a:replacement]) +function! coc#util#set_lines(bufnr, changedtick, original, replacement, start, end) abort + if !bufloaded(a:bufnr) + return endif - return { - \ 'lines': getbufline(a:bufnr, 1, '$'), - \ 'changedtick': getbufvar(a:bufnr, 'changedtick') - \ } + if getbufvar(a:bufnr, 'changedtick') != a:changedtick && bufnr('%') == a:bufnr + " try apply current line change + let lnum = line('.') + let idx = a:start - lnum + 1 + let previous = get(a:original, idx, 0) + if type(previous) == 1 + let content = getline('.') + if previous !=# content + let diff = coc#helper#str_diff(content, previous, col('.')) + let changed = get(a:replacement, idx, 0) + if type(changed) == 1 && strcharpart(previous, 0, diff['end']) ==# strcharpart(changed, 0, diff['end']) + let applied = coc#helper#str_apply(changed, diff) + let replacement = copy(a:replacement) + let replacement[idx] = applied + call coc#compat#buf_set_lines(a:bufnr, a:start, a:end, replacement) + return + endif + endif + endif + endif + call coc#compat#buf_set_lines(a:bufnr, a:start, a:end, a:replacement) endfunction function! coc#util#change_lines(bufnr, list) abort @@ -594,16 +607,14 @@ function! coc#util#change_lines(bufnr, list) abort endfor exe 'noa buffer '.bufnr endif - return { - \ 'lines': getbufline(a:bufnr, 1, '$'), - \ 'changedtick': getbufvar(a:bufnr, 'changedtick') - \ } endfunction " used by vim function! coc#util#get_buf_lines(bufnr, changedtick) - if !bufloaded(a:bufnr) | return '' | endif + if !bufloaded(a:bufnr) + return v:null + endif let changedtick = getbufvar(a:bufnr, 'changedtick') if changedtick == a:changedtick return v:null @@ -623,36 +634,6 @@ function! coc#util#get_changeinfo() \} endfunction -" show diff of current buffer -function! coc#util#diff_content(lines) abort - let tmpfile = tempname() - setl foldenable - call writefile(a:lines, tmpfile) - let ft = &filetype - diffthis - execute 'vs '.tmpfile - if !empty(ft) - execute 'setf ' . ft - endif - diffthis - setl foldenable -endfunction - -function! coc#util#clear_signs() - let buflist = filter(range(1, bufnr('$')), 'buflisted(v:val)') - for b in buflist - let signIds = [] - let lines = split(execute('sign place buffer='.b), "\n") - for line in lines - let ms = matchlist(line, 'id=\(\d\+\)\s\+name=Coc') - if len(ms) > 0 - call add(signIds, ms[1]) - endif - endfor - call coc#util#unplace_signs(b, signIds) - endfor -endfunction - function! coc#util#open_url(url) if has('mac') && executable('open') call system('open '.a:url) @@ -730,17 +711,6 @@ function! coc#util#rebuild() \}) endfunction -" content of first echo line -function! coc#util#echo_line() - let str = '' - let line = &lines - (&cmdheight - 1) - for i in range(1, &columns - 1) - let nr = screenchar(line, i) - let str = str . nr2char(nr) - endfor - return str -endfunction - " [r, g, b] ['255', '255', '255'] " return ['65535', '65535', '65535'] or return v:false to cancel function! coc#util#pick_color(default_color) @@ -848,11 +818,6 @@ function! s:system(cmd) return output endfunction -function! coc#util#set_buf_var(bufnr, name, val) abort - if !bufloaded(a:bufnr) | return | endif - call setbufvar(a:bufnr, a:name, a:val) -endfunction - function! coc#util#unmap(bufnr, keys) abort if bufnr('%') == a:bufnr for key in a:keys @@ -899,10 +864,6 @@ function! coc#util#refactor_foldlevel(lnum) abort return 1 endfunction -function! coc#util#get_pretext() abort - return strpart(getline('.'), 0, col('.') - 1) -endfunction - function! coc#util#refactor_fold_text(lnum) abort let range = '' let info = get(b:line_infos, a:lnum, []) @@ -912,13 +873,6 @@ function! coc#util#refactor_fold_text(lnum) abort return trim(getline(a:lnum)[3:]).' '.range endfunction -function! coc#util#set_buf_lines(bufnr, lines) abort - let res = setbufline(a:bufnr, 1, a:lines) - if res == 0 - silent call deletebufline(a:bufnr, len(a:lines) + 1, '$') - endif -endfunction - " get tabsize & expandtab option function! coc#util#get_format_opts(bufnr) abort if a:bufnr && bufloaded(a:bufnr) @@ -931,30 +885,3 @@ function! coc#util#get_format_opts(bufnr) abort let tabsize = &shiftwidth == 0 ? &tabstop : &shiftwidth return [tabsize, &expandtab] endfunction - -function! coc#util#clearmatches(ids, ...) - let winid = get(a:, 1, win_getid()) - call coc#highlight#clear_matches(winid, a:ids) -endfunction - -" Character offset of current cursor -function! coc#util#get_offset() abort - let offset = 0 - let lnum = line('.') - for i in range(1, lnum) - if i == lnum - let offset += strchars(strpart(getline('.'), 0, col('.')-1)) - else - let offset += strchars(getline(i)) + 1 - endif - endfor - return offset -endfunction - -" Make sure window exists -function! coc#util#win_gotoid(winid) abort - noa let res = win_gotoid(a:winid) - if res == 0 - throw 'Invalid window number' - endif -endfunction diff --git a/vim-config/plugins/coc.nvim/autoload/coc/window.vim b/vim-config/plugins/coc.nvim/autoload/coc/window.vim new file mode 100644 index 00000000..113d727f --- /dev/null +++ b/vim-config/plugins/coc.nvim/autoload/coc/window.vim @@ -0,0 +1,56 @@ +function! coc#window#tabnr(winid) abort + if exists('*win_execute') + let ref = {} + call win_execute(a:winid, 'let ref["out"] = tabpagenr()') + return get(ref, 'out', -1) + elseif has('nvim') + let info = getwininfo(a:winid) + return empty(info) ? -1 : info[0]['tabnr'] + else + throw 'win_execute() not exists, please upgrade your vim.' + endif +endfunction + +" Get single window by window variable, current tab only +function! coc#window#find(key, val) abort + for i in range(1, winnr('$')) + let res = getwinvar(i, a:key) + if res == a:val + return win_getid(i) + endif + endfor + return -1 +endfunction + +" Make sure window exists +function! coc#window#gotoid(winid) abort + noa let res = win_gotoid(a:winid) + if res == 0 + throw 'Invalid window number' + endif +endfunction + +" Avoid errors +function! coc#window#close(winid) abort + if empty(a:winid) || a:winid == -1 + return + endif + if exists('*nvim_win_is_valid') && exists('*nvim_win_close') + if nvim_win_is_valid(a:winid) + call nvim_win_close(a:winid, 1) + endif + elseif exists('*win_execute') + call coc#compat#execute(a:winid, 'noa close!', 'silent!') + else + let curr = win_getid() + if curr == a:winid + silent! close! + else + let res = win_gotoid(a:winid) + if res + silent! close! + call win_gotoid(curr) + endif + endif + endif +endfunction diff --git a/vim-config/plugins/coc.nvim/autoload/health/coc.vim b/vim-config/plugins/coc.nvim/autoload/health/coc.vim index 20707f2a..8daa6b80 100644 --- a/vim-config/plugins/coc.nvim/autoload/health/coc.vim +++ b/vim-config/plugins/coc.nvim/autoload/health/coc.vim @@ -21,12 +21,9 @@ function! s:checkEnvironment() abort if empty(ms) let valid = 0 call health#report_error('Unable to detect version of node, make sure your node executable is http://nodejs.org/') - elseif str2nr(ms[1]) < 8 || (str2nr(ms[1]) == 8 && str2nr(ms[2]) < 10) + elseif str2nr(ms[1]) < 12 || (str2nr(ms[1]) == 12 && str2nr(ms[2]) < 12) let valid = 0 - call health#report_error('Node.js version '.output.' < 8.10.0, please upgrade node.js') - elseif str2nr(ms[1]) < 10 || (str2nr(ms[1]) == 10 && str2nr(ms[2]) < 12) - let valid = 0 - call health#report_warn('Node.js version '.trim(output).' < 10.12.0, please upgrade node.js') + call health#report_warn('Node.js version '.trim(output).' < 12.12.0, please upgrade node.js') endif if valid call health#report_ok('Environment check passed') diff --git a/vim-config/plugins/coc.nvim/bin/check.js b/vim-config/plugins/coc.nvim/bin/check.js deleted file mode 100644 index 05fe6227..00000000 --- a/vim-config/plugins/coc.nvim/bin/check.js +++ /dev/null @@ -1,13 +0,0 @@ -let version = process.version.replace('v', '') -let parts = version.split('.') -function greatThanOrEqual(nums, major, minor) { - if (nums[0] > major) return true - if (nums[0] == major && nums[1] >= minor) return true - return false -} -let numbers = parts.map(function (s) { - return parseInt(s, 10) -}) -if (!greatThanOrEqual(numbers, 10, 12)) { - throw new Error('node version ' + version + ' < 10.12.0, please upgrade nodejs, or use \`let g:coc_node_path = "/path/to/node"\` in your vimrc') -} diff --git a/vim-config/plugins/coc.nvim/build/index.js b/vim-config/plugins/coc.nvim/build/index.js index fe81c730..ba483823 100644 --- a/vim-config/plugins/coc.nvim/build/index.js +++ b/vim-config/plugins/coc.nvim/build/index.js @@ -1,251 +1,68494 @@ -var RJ=Object.create,rc=Object.defineProperty,kJ=Object.getPrototypeOf,IJ=Object.prototype.hasOwnProperty,FJ=Object.getOwnPropertyNames,jP=Object.getOwnPropertyDescriptor;var UP=r=>rc(r,"__esModule",{value:!0});var v=(r,e)=>()=>(e||(e={exports:{}},r(e.exports,e)),e.exports),ho=(r,e)=>{UP(r);for(var t in e)rc(r,t,{get:e[t],enumerable:!0})},AJ=(r,e,t)=>{if(UP(r),e&&typeof e=="object"||typeof e=="function")for(let i of FJ(e))!IJ.call(r,i)&&i!=="default"&&rc(r,i,{get:()=>e[i],enumerable:!(t=jP(e,i))||t.enumerable});return r},S=r=>r&&r.__esModule?r:AJ(rc(r!=null?RJ(kJ(r)):{},"default",{value:r,enumerable:!0}),r),Iy=(r,e,t,i)=>{for(var n=i>1?void 0:i?jP(e,t):e,o=r.length-1,s;o>=0;o--)(s=r[o])&&(n=(i?s(e,t,n):s(n))||n);return i&&n&&rc(e,t,n),n};var HP=v((hSe,WP)=>{"use strict";var OJ="Function.prototype.bind called on incompatible ",Fy=Array.prototype.slice,LJ=Object.prototype.toString,MJ="[object Function]";WP.exports=function(e){var t=this;if(typeof t!="function"||LJ.call(t)!==MJ)throw new TypeError(OJ+t);for(var i=Fy.call(arguments,1),n,o=function(){if(this instanceof n){var c=t.apply(this,i.concat(Fy.call(arguments)));return Object(c)===c?c:this}else return t.apply(e,i.concat(Fy.call(arguments)))},s=Math.max(0,t.length-i.length),a=[],l=0;l{"use strict";var NJ=HP();zP.exports=Function.prototype.bind||NJ});var Ay=v((gSe,GP)=>{"use strict";var VP=Object.prototype.toString;GP.exports=function(e){var t=VP.call(e),i=t==="[object Arguments]";return i||(i=t!=="[object Array]"&&e!==null&&typeof e=="object"&&typeof e.length=="number"&&e.length>=0&&VP.call(e.callee)==="[object Function]"),i}});var rT=v((vSe,KP)=>{"use strict";var JP;Object.keys||(ic=Object.prototype.hasOwnProperty,Oy=Object.prototype.toString,YP=Ay(),Ly=Object.prototype.propertyIsEnumerable,XP=!Ly.call({toString:null},"toString"),ZP=Ly.call(function(){},"prototype"),nc=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],Pd=function(r){var e=r.constructor;return e&&e.prototype===r},QP={$applicationCache:!0,$console:!0,$external:!0,$frame:!0,$frameElement:!0,$frames:!0,$innerHeight:!0,$innerWidth:!0,$onmozfullscreenchange:!0,$onmozfullscreenerror:!0,$outerHeight:!0,$outerWidth:!0,$pageXOffset:!0,$pageYOffset:!0,$parent:!0,$scrollLeft:!0,$scrollTop:!0,$scrollX:!0,$scrollY:!0,$self:!0,$webkitIndexedDB:!0,$webkitStorageInfo:!0,$window:!0},eT=function(){if(typeof window=="undefined")return!1;for(var r in window)try{if(!QP["$"+r]&&ic.call(window,r)&&window[r]!==null&&typeof window[r]=="object")try{Pd(window[r])}catch(e){return!0}}catch(e){return!0}return!1}(),tT=function(r){if(typeof window=="undefined"||!eT)return Pd(r);try{return Pd(r)}catch(e){return!1}},JP=function(e){var t=e!==null&&typeof e=="object",i=Oy.call(e)==="[object Function]",n=YP(e),o=t&&Oy.call(e)==="[object String]",s=[];if(!t&&!i&&!n)throw new TypeError("Object.keys called on a non-object");var a=ZP&&i;if(o&&e.length>0&&!ic.call(e,0))for(var l=0;l0)for(var u=0;u{"use strict";var qJ=Array.prototype.slice,$J=Ay(),nT=Object.keys,Td=nT?function(e){return nT(e)}:rT(),oT=Object.keys;Td.shim=function(){if(Object.keys){var e=function(){var t=Object.keys(arguments);return t&&t.length===arguments.length}(1,2);e||(Object.keys=function(i){return $J(i)?oT(qJ.call(i)):oT(i)})}else Object.keys=Td;return Object.keys||Td};iT.exports=Td});var Fn=v((bSe,aT)=>{"use strict";var BJ=sT(),jJ=typeof Symbol=="function"&&typeof Symbol("foo")=="symbol",UJ=Object.prototype.toString,WJ=Array.prototype.concat,My=Object.defineProperty,HJ=function(r){return typeof r=="function"&&UJ.call(r)==="[object Function]"},zJ=function(){var r={};try{My(r,"x",{enumerable:!1,value:r});for(var e in r)return!1;return r.x===r}catch(t){return!1}},lT=My&&zJ(),GJ=function(r,e,t,i){e in r&&(!HJ(i)||!i())||(lT?My(r,e,{configurable:!0,enumerable:!1,value:t,writable:!0}):r[e]=t)},uT=function(r,e){var t=arguments.length>2?arguments[2]:{},i=BJ(e);jJ&&(i=WJ.call(i,Object.getOwnPropertySymbols(e)));for(var n=0;n{"use strict";cT.exports=function(){if(typeof Promise!="function")throw new TypeError("`Promise.prototype.finally` requires a global `Promise` be available.")}});var Ny=v((xSe,fT)=>{"use strict";var pT=Function.prototype.toString,VJ=/^\s*class\b/,dT=function(e){try{var t=pT.call(e);return VJ.test(t)}catch(i){return!1}},KJ=function(e){try{return dT(e)?!1:(pT.call(e),!0)}catch(t){return!1}},JJ=Object.prototype.toString,YJ="[object Function]",XJ="[object GeneratorFunction]",ZJ=typeof Symbol=="function"&&typeof Symbol.toStringTag=="symbol";fT.exports=function(e){if(!e||typeof e!="function"&&typeof e!="object")return!1;if(typeof e=="function"&&!e.prototype)return!0;if(ZJ)return KJ(e);if(dT(e))return!1;var t=JJ.call(e);return t===YJ||t===XJ}});var mT=v((DSe,hT)=>{"use strict";hT.exports=Ny()});var vT=v((SSe,gT)=>{"use strict";gT.exports=function(){if(typeof Symbol!="function"||typeof Object.getOwnPropertySymbols!="function")return!1;if(typeof Symbol.iterator=="symbol")return!0;var e={},t=Symbol("test"),i=Object(t);if(typeof t=="string"||Object.prototype.toString.call(t)!=="[object Symbol]"||Object.prototype.toString.call(i)!=="[object Symbol]")return!1;var n=42;e[t]=n;for(t in e)return!1;if(typeof Object.keys=="function"&&Object.keys(e).length!==0||typeof Object.getOwnPropertyNames=="function"&&Object.getOwnPropertyNames(e).length!==0)return!1;var o=Object.getOwnPropertySymbols(e);if(o.length!==1||o[0]!==t||!Object.prototype.propertyIsEnumerable.call(e,t))return!1;if(typeof Object.getOwnPropertyDescriptor=="function"){var s=Object.getOwnPropertyDescriptor(e,t);if(s.value!==n||s.enumerable!==!0)return!1}return!0}});var Li=v((ESe,yT)=>{"use strict";var bT=global.Symbol,QJ=vT();yT.exports=function(){return typeof bT!="function"||typeof Symbol!="function"||typeof bT("foo")!="symbol"||typeof Symbol("bar")!="symbol"?!1:QJ()}});var ST=v((CSe,wT)=>{"use strict";var J,oc=TypeError,ys=Object.getOwnPropertyDescriptor;if(ys)try{ys({},"")}catch(r){ys=null}var qy=function(){throw new oc},eY=ys?function(){try{return arguments.callee,qy}catch(r){try{return ys(arguments,"callee").get}catch(e){return qy}}}():qy,mo=Li()(),Mi=Object.getPrototypeOf||function(r){return r.__proto__},kd,$y=kd?Mi(kd):J,xT,By=xT?xT.constructor:J,sc,jy=sc?Mi(sc):J,Uy=sc?sc():J,Wy=typeof Uint8Array=="undefined"?J:Mi(Uint8Array),Hy={"%Array%":Array,"%ArrayBuffer%":typeof ArrayBuffer=="undefined"?J:ArrayBuffer,"%ArrayBufferPrototype%":typeof ArrayBuffer=="undefined"?J:ArrayBuffer.prototype,"%ArrayIteratorPrototype%":mo?Mi([][Symbol.iterator]()):J,"%ArrayPrototype%":Array.prototype,"%ArrayProto_entries%":Array.prototype.entries,"%ArrayProto_forEach%":Array.prototype.forEach,"%ArrayProto_keys%":Array.prototype.keys,"%ArrayProto_values%":Array.prototype.values,"%AsyncFromSyncIteratorPrototype%":J,"%AsyncFunction%":By,"%AsyncFunctionPrototype%":By?By.prototype:J,"%AsyncGenerator%":sc?Mi(Uy):J,"%AsyncGeneratorFunction%":jy,"%AsyncGeneratorPrototype%":jy?jy.prototype:J,"%AsyncIteratorPrototype%":Uy&&mo&&Symbol.asyncIterator?Uy[Symbol.asyncIterator]():J,"%Atomics%":typeof Atomics=="undefined"?J:Atomics,"%Boolean%":Boolean,"%BooleanPrototype%":Boolean.prototype,"%DataView%":typeof DataView=="undefined"?J:DataView,"%DataViewPrototype%":typeof DataView=="undefined"?J:DataView.prototype,"%Date%":Date,"%DatePrototype%":Date.prototype,"%decodeURI%":decodeURI,"%decodeURIComponent%":decodeURIComponent,"%encodeURI%":encodeURI,"%encodeURIComponent%":encodeURIComponent,"%Error%":Error,"%ErrorPrototype%":Error.prototype,"%eval%":eval,"%EvalError%":EvalError,"%EvalErrorPrototype%":EvalError.prototype,"%Float32Array%":typeof Float32Array=="undefined"?J:Float32Array,"%Float32ArrayPrototype%":typeof Float32Array=="undefined"?J:Float32Array.prototype,"%Float64Array%":typeof Float64Array=="undefined"?J:Float64Array,"%Float64ArrayPrototype%":typeof Float64Array=="undefined"?J:Float64Array.prototype,"%Function%":Function,"%FunctionPrototype%":Function.prototype,"%Generator%":kd?Mi(kd()):J,"%GeneratorFunction%":$y,"%GeneratorPrototype%":$y?$y.prototype:J,"%Int8Array%":typeof Int8Array=="undefined"?J:Int8Array,"%Int8ArrayPrototype%":typeof Int8Array=="undefined"?J:Int8Array.prototype,"%Int16Array%":typeof Int16Array=="undefined"?J:Int16Array,"%Int16ArrayPrototype%":typeof Int16Array=="undefined"?J:Int8Array.prototype,"%Int32Array%":typeof Int32Array=="undefined"?J:Int32Array,"%Int32ArrayPrototype%":typeof Int32Array=="undefined"?J:Int32Array.prototype,"%isFinite%":isFinite,"%isNaN%":isNaN,"%IteratorPrototype%":mo?Mi(Mi([][Symbol.iterator]())):J,"%JSON%":typeof JSON=="object"?JSON:J,"%JSONParse%":typeof JSON=="object"?JSON.parse:J,"%Map%":typeof Map=="undefined"?J:Map,"%MapIteratorPrototype%":typeof Map=="undefined"||!mo?J:Mi(new Map()[Symbol.iterator]()),"%MapPrototype%":typeof Map=="undefined"?J:Map.prototype,"%Math%":Math,"%Number%":Number,"%NumberPrototype%":Number.prototype,"%Object%":Object,"%ObjectPrototype%":Object.prototype,"%ObjProto_toString%":Object.prototype.toString,"%ObjProto_valueOf%":Object.prototype.valueOf,"%parseFloat%":parseFloat,"%parseInt%":parseInt,"%Promise%":typeof Promise=="undefined"?J:Promise,"%PromisePrototype%":typeof Promise=="undefined"?J:Promise.prototype,"%PromiseProto_then%":typeof Promise=="undefined"?J:Promise.prototype.then,"%Promise_all%":typeof Promise=="undefined"?J:Promise.all,"%Promise_reject%":typeof Promise=="undefined"?J:Promise.reject,"%Promise_resolve%":typeof Promise=="undefined"?J:Promise.resolve,"%Proxy%":typeof Proxy=="undefined"?J:Proxy,"%RangeError%":RangeError,"%RangeErrorPrototype%":RangeError.prototype,"%ReferenceError%":ReferenceError,"%ReferenceErrorPrototype%":ReferenceError.prototype,"%Reflect%":typeof Reflect=="undefined"?J:Reflect,"%RegExp%":RegExp,"%RegExpPrototype%":RegExp.prototype,"%Set%":typeof Set=="undefined"?J:Set,"%SetIteratorPrototype%":typeof Set=="undefined"||!mo?J:Mi(new Set()[Symbol.iterator]()),"%SetPrototype%":typeof Set=="undefined"?J:Set.prototype,"%SharedArrayBuffer%":typeof SharedArrayBuffer=="undefined"?J:SharedArrayBuffer,"%SharedArrayBufferPrototype%":typeof SharedArrayBuffer=="undefined"?J:SharedArrayBuffer.prototype,"%String%":String,"%StringIteratorPrototype%":mo?Mi(""[Symbol.iterator]()):J,"%StringPrototype%":String.prototype,"%Symbol%":mo?Symbol:J,"%SymbolPrototype%":mo?Symbol.prototype:J,"%SyntaxError%":SyntaxError,"%SyntaxErrorPrototype%":SyntaxError.prototype,"%ThrowTypeError%":eY,"%TypedArray%":Wy,"%TypedArrayPrototype%":Wy?Wy.prototype:J,"%TypeError%":oc,"%TypeErrorPrototype%":oc.prototype,"%Uint8Array%":typeof Uint8Array=="undefined"?J:Uint8Array,"%Uint8ArrayPrototype%":typeof Uint8Array=="undefined"?J:Uint8Array.prototype,"%Uint8ClampedArray%":typeof Uint8ClampedArray=="undefined"?J:Uint8ClampedArray,"%Uint8ClampedArrayPrototype%":typeof Uint8ClampedArray=="undefined"?J:Uint8ClampedArray.prototype,"%Uint16Array%":typeof Uint16Array=="undefined"?J:Uint16Array,"%Uint16ArrayPrototype%":typeof Uint16Array=="undefined"?J:Uint16Array.prototype,"%Uint32Array%":typeof Uint32Array=="undefined"?J:Uint32Array,"%Uint32ArrayPrototype%":typeof Uint32Array=="undefined"?J:Uint32Array.prototype,"%URIError%":URIError,"%URIErrorPrototype%":URIError.prototype,"%WeakMap%":typeof WeakMap=="undefined"?J:WeakMap,"%WeakMapPrototype%":typeof WeakMap=="undefined"?J:WeakMap.prototype,"%WeakSet%":typeof WeakSet=="undefined"?J:WeakSet,"%WeakSetPrototype%":typeof WeakSet=="undefined"?J:WeakSet.prototype},tY=un(),DT=tY.call(Function.call,String.prototype.replace),rY=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g,iY=/\\(\\)?/g,nY=function(e){var t=[];return DT(e,rY,function(i,n,o,s){t[t.length]=o?DT(s,iY,"$1"):n||i}),t},oY=function(e,t){if(!(e in Hy))throw new SyntaxError("intrinsic "+e+" does not exist!");if(typeof Hy[e]=="undefined"&&!t)throw new oc("intrinsic "+e+" exists, but is not available. Please file an issue!");return Hy[e]};wT.exports=function(e,t){if(typeof e!="string"||e.length===0)throw new TypeError("intrinsic name must be a non-empty string");if(arguments.length>1&&typeof t!="boolean")throw new TypeError('"allowMissing" argument must be a boolean');for(var i=nY(e),n=oY("%"+(i.length>0?i[0]:"")+"%",t),o=1;o=i.length){var s=ys(n,i[o]);if(!t&&!(i[o]in n))throw new oc("base intrinsic for "+e+" exists, but the property is not available.");n=s?s.get||s.value:n[i[o]]}else n=n[i[o]];return n}});var CT=v((_Se,ET)=>{"use strict";ET.exports=function(e){return typeof e=="function"&&!!e.prototype}});var PT=v((PSe,_T)=>{"use strict";_T.exports=function(e){if(e===null)return"Null";if(typeof e=="undefined")return"Undefined";if(typeof e=="function"||typeof e=="object")return"Object";if(typeof e=="number")return"Number";if(typeof e=="boolean")return"Boolean";if(typeof e=="string")return"String"}});var zy=v((TSe,TT)=>{"use strict";var sY=PT();TT.exports=function(e){return typeof e=="symbol"?"Symbol":sY(e)}});var AT=v((RSe,RT)=>{"use strict";var kT=ST(),IT=kT("%Symbol.species%",!0),Gy=kT("%TypeError%"),aY=CT(),FT=zy();RT.exports=function(e,t){if(FT(e)!=="Object")throw new Gy("Assertion failed: Type(O) is not Object");var i=e.constructor;if(typeof i=="undefined")return t;if(FT(i)!=="Object")throw new Gy("O.constructor is not an Object");var n=IT?i[IT]:void 0;if(n==null)return t;if(aY(n))return n;throw new Gy("no constructor found")}});var Jy=v((kSe,OT)=>{"use strict";var lY=Rd();lY();var uY=mT(),cY=AT(),fY=zy(),LT=function(e,t){return new e(function(i){i(t)})},pY=Promise,dY=function(e,t){return function(i){var n=t(),o=LT(e,n),s=function(){return i};return o.then(s)}},hY=function(e,t){return function(i){var n=t(),o=LT(e,n),s=function(){throw i};return o.then(s)}},Vy=function(e){var t=this;if(fY(t)!=="Object")throw new TypeError("receiver is not an Object");var i=cY(t,pY),n=e,o=e;return uY(e)&&(n=dY(i,e),o=hY(i,e)),t.then(n,o)};Object.getOwnPropertyDescriptor&&(Ky=Object.getOwnPropertyDescriptor(Vy,"name"),Ky&&Ky.configurable&&Object.defineProperty(Vy,"name",{configurable:!0,value:"finally"}));var Ky;OT.exports=Vy});var Yy=v((ISe,MT)=>{"use strict";var mY=Rd(),gY=Jy();MT.exports=function(){return mY(),typeof Promise.prototype.finally=="function"?Promise.prototype.finally:gY}});var qT=v((FSe,NT)=>{"use strict";var vY=Rd(),yY=Yy(),bY=Fn();NT.exports=function(){vY();var e=yY();return bY(Promise.prototype,{finally:e},{finally:function(){return Promise.prototype.finally!==e}}),e}});var UT=v((ASe,$T)=>{"use strict";var wY=un(),xY=Fn(),DY=Jy(),BT=Yy(),SY=qT(),jT=wY.call(Function.call,BT());xY(jT,{getPolyfill:BT,implementation:DY,shim:SY});$T.exports=jT});var HT=v((OSe,WT)=>{var qa=1e3,$a=qa*60,Ba=$a*60,bs=Ba*24,EY=bs*7,CY=bs*365.25;WT.exports=function(r,e){e=e||{};var t=typeof r;if(t==="string"&&r.length>0)return _Y(r);if(t==="number"&&isFinite(r))return e.long?TY(r):PY(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function _Y(r){if(r=String(r),!(r.length>100)){var e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(r);if(!!e){var t=parseFloat(e[1]),i=(e[2]||"ms").toLowerCase();switch(i){case"years":case"year":case"yrs":case"yr":case"y":return t*CY;case"weeks":case"week":case"w":return t*EY;case"days":case"day":case"d":return t*bs;case"hours":case"hour":case"hrs":case"hr":case"h":return t*Ba;case"minutes":case"minute":case"mins":case"min":case"m":return t*$a;case"seconds":case"second":case"secs":case"sec":case"s":return t*qa;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return t;default:return}}}}function PY(r){var e=Math.abs(r);return e>=bs?Math.round(r/bs)+"d":e>=Ba?Math.round(r/Ba)+"h":e>=$a?Math.round(r/$a)+"m":e>=qa?Math.round(r/qa)+"s":r+"ms"}function TY(r){var e=Math.abs(r);return e>=bs?Id(r,e,bs,"day"):e>=Ba?Id(r,e,Ba,"hour"):e>=$a?Id(r,e,$a,"minute"):e>=qa?Id(r,e,qa,"second"):r+" ms"}function Id(r,e,t,i){var n=e>=t*1.5;return Math.round(r/t)+" "+i+(n?"s":"")}});var Xy=v((LSe,zT)=>{function RY(r){t.debug=t,t.default=t,t.coerce=u,t.disable=s,t.enable=o,t.enabled=a,t.humanize=HT(),Object.keys(r).forEach(c=>{t[c]=r[c]}),t.instances=[],t.names=[],t.skips=[],t.formatters={};function e(c){let f=0;for(let p=0;p{if(x==="%%")return x;g++;let P=t.formatters[E];if(typeof P=="function"){let k=d[g];x=P.call(h,k),d.splice(g,1),g--}return x}),t.formatArgs.call(h,d),(h.log||t.log).apply(h,d)}return p.namespace=c,p.enabled=t.enabled(c),p.useColors=t.useColors(),p.color=e(c),p.destroy=i,p.extend=n,typeof t.init=="function"&&t.init(p),t.instances.push(p),p}function i(){let c=t.instances.indexOf(this);return c!==-1?(t.instances.splice(c,1),!0):!1}function n(c,f){let p=t(this.namespace+(typeof f=="undefined"?":":f)+c);return p.log=this.log,p}function o(c){t.save(c),t.names=[],t.skips=[];let f,p=(typeof c=="string"?c:"").split(/[\s,]+/),d=p.length;for(f=0;f"-"+f)].join(",");return t.enable(""),c}function a(c){if(c[c.length-1]==="*")return!0;let f,p;for(f=0,p=t.skips.length;f{ai.log=kY;ai.formatArgs=IY;ai.save=FY;ai.load=AY;ai.useColors=OY;ai.storage=LY();ai.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"];function OY(){return typeof window!="undefined"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs)?!0:typeof navigator!="undefined"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)?!1:typeof document!="undefined"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window!="undefined"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator!="undefined"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||typeof navigator!="undefined"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function IY(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+Fd.exports.humanize(this.diff),!this.useColors)return;let e="color: "+this.color;r.splice(1,0,e,"color: inherit");let t=0,i=0;r[0].replace(/%[a-zA-Z%]/g,n=>{n!=="%%"&&(t++,n==="%c"&&(i=t))}),r.splice(i,0,e)}function kY(...r){return typeof console=="object"&&console.log&&console.log(...r)}function FY(r){try{r?ai.storage.setItem("debug",r):ai.storage.removeItem("debug")}catch(e){}}function AY(){let r;try{r=ai.storage.getItem("debug")}catch(e){}return!r&&typeof process!="undefined"&&"env"in process&&(r=process.env.DEBUG),r}function LY(){try{return localStorage}catch(r){}}Fd.exports=Xy()(ai);var{formatters:MY}=Fd.exports;MY.j=function(r){try{return JSON.stringify(r)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var KT=v((MSe,VT)=>{"use strict";VT.exports=(r,e=process.argv)=>{let t=r.startsWith("-")?"":r.length===1?"-":"--",i=e.indexOf(t+r),n=e.indexOf("--");return i!==-1&&(n===-1||i{"use strict";var NY=require("os"),YT=require("tty"),li=KT(),{env:Pt}=process,go;li("no-color")||li("no-colors")||li("color=false")||li("color=never")?go=0:(li("color")||li("colors")||li("color=true")||li("color=always"))&&(go=1);"FORCE_COLOR"in Pt&&(Pt.FORCE_COLOR==="true"?go=1:Pt.FORCE_COLOR==="false"?go=0:go=Pt.FORCE_COLOR.length===0?1:Math.min(parseInt(Pt.FORCE_COLOR,10),3));function Zy(r){return r===0?!1:{level:r,hasBasic:!0,has256:r>=2,has16m:r>=3}}function Qy(r,e){if(go===0)return 0;if(li("color=16m")||li("color=full")||li("color=truecolor"))return 3;if(li("color=256"))return 2;if(r&&!e&&go===void 0)return 0;let t=go||0;if(Pt.TERM==="dumb")return t;if(process.platform==="win32"){let i=NY.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in Pt)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(i=>i in Pt)||Pt.CI_NAME==="codeship"?1:t;if("TEAMCITY_VERSION"in Pt)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(Pt.TEAMCITY_VERSION)?1:0;if("GITHUB_ACTIONS"in Pt)return 1;if(Pt.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in Pt){let i=parseInt((Pt.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(Pt.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(Pt.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(Pt.TERM)||"COLORTERM"in Pt?1:t}function qY(r){let e=Qy(r,r&&r.isTTY);return Zy(e)}JT.exports={supportsColor:qY,stdout:Zy(Qy(!0,YT.isatty(1))),stderr:Zy(Qy(!0,YT.isatty(2)))}});var QT=v((Qt,Ad)=>{var $Y=require("tty"),eb=require("util");Qt.init=BY;Qt.log=jY;Qt.formatArgs=UY;Qt.save=WY;Qt.load=HY;Qt.useColors=zY;Qt.colors=[6,2,3,4,5,1];try{let r=XT();r&&(r.stderr||r).level>=2&&(Qt.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(r){}Qt.inspectOpts=Object.keys(process.env).filter(r=>/^debug_/i.test(r)).reduce((r,e)=>{let t=e.substring(6).toLowerCase().replace(/_([a-z])/g,(n,o)=>o.toUpperCase()),i=process.env[e];return/^(yes|on|true|enabled)$/i.test(i)?i=!0:/^(no|off|false|disabled)$/i.test(i)?i=!1:i==="null"?i=null:i=Number(i),r[t]=i,r},{});function zY(){return"colors"in Qt.inspectOpts?Boolean(Qt.inspectOpts.colors):$Y.isatty(process.stderr.fd)}function UY(r){let{namespace:e,useColors:t}=this;if(t){let i=this.color,n="[3"+(i<8?i:"8;5;"+i),o=` ${n};1m${e} `;r[0]=o+r[0].split(` -`).join(` -`+o),r.push(n+"m+"+Ad.exports.humanize(this.diff)+"")}else r[0]=GY()+e+" "+r[0]}function GY(){return Qt.inspectOpts.hideDate?"":new Date().toISOString()+" "}function jY(...r){return process.stderr.write(eb.format(...r)+` -`)}function WY(r){r?process.env.DEBUG=r:delete process.env.DEBUG}function HY(){return process.env.DEBUG}function BY(r){r.inspectOpts={};let e=Object.keys(Qt.inspectOpts);for(let t=0;t{typeof process=="undefined"||process.type==="renderer"||process.browser===!0||process.__nwjs?tb.exports=GT():tb.exports=QT()});var tR=v(($Se,eR)=>{"use strict";eR.exports=VY;function VY(r){if(r=r||{},r.circles)return KY(r);return r.proto?i:t;function e(n,o){for(var s=Object.keys(n),a=new Array(s.length),l=0;l{var JY=require("util"),ws=vt()("log4js:configuration"),Od=[],Ld=[],iR=r=>!r,nR=r=>r&&typeof r=="object"&&!Array.isArray(r),YY=r=>/^[A-Za-z][A-Za-z0-9_]*$/g.test(r),XY=r=>r&&typeof r=="number"&&Number.isInteger(r),ZY=r=>{Ld.push(r),ws(`Added listener, now ${Ld.length} listeners`)},QY=r=>{Od.push(r),ws(`Added pre-processing listener, now ${Od.length} listeners`)},oR=(r,e,t)=>{(Array.isArray(e)?e:[e]).forEach(n=>{if(n)throw new Error(`Problem with log4js configuration: (${JY.inspect(r,{depth:5})}) - ${t}`)})},eX=r=>{ws("New configuration to be validated: ",r),oR(r,iR(nR(r)),"must be an object."),ws(`Calling pre-processing listeners (${Od.length})`),Od.forEach(e=>e(r)),ws("Configuration pre-processing finished."),ws(`Calling configuration listeners (${Ld.length})`),Ld.forEach(e=>e(r)),ws("Configuration finished.")};rR.exports={configure:eX,addListener:ZY,addPreProcessingListener:QY,throwExceptionIf:oR,anObject:nR,anInteger:XY,validIdentifier:YY,not:iR}});var lR=v((jSe,ui)=>{"use strict";function sR(r,e){for(var t=r.toString();t.length-1?n:o,a=Ds(e.getHours()),l=Ds(e.getMinutes()),u=Ds(e.getSeconds()),c=sR(e.getMilliseconds(),3),f=tX(e.getTimezoneOffset()),p=r.replace(/dd/g,t).replace(/MM/g,i).replace(/y{1,4}/g,s).replace(/hh/g,a).replace(/mm/g,l).replace(/ss/g,u).replace(/SSS/g,c).replace(/O/g,f);return p}function Ss(r,e,t,i){r["set"+(i?"":"UTC")+e](t)}function rX(r,e,t){var i=r.indexOf("O")<0,n=[{pattern:/y{1,4}/,regexp:"\\d{1,4}",fn:function(c,f){Ss(c,"FullYear",f,i)}},{pattern:/MM/,regexp:"\\d{1,2}",fn:function(c,f){Ss(c,"Month",f-1,i)}},{pattern:/dd/,regexp:"\\d{1,2}",fn:function(c,f){Ss(c,"Date",f,i)}},{pattern:/hh/,regexp:"\\d{1,2}",fn:function(c,f){Ss(c,"Hours",f,i)}},{pattern:/mm/,regexp:"\\d\\d",fn:function(c,f){Ss(c,"Minutes",f,i)}},{pattern:/ss/,regexp:"\\d\\d",fn:function(c,f){Ss(c,"Seconds",f,i)}},{pattern:/SSS/,regexp:"\\d\\d\\d",fn:function(c,f){Ss(c,"Milliseconds",f,i)}},{pattern:/O/,regexp:"[+-]\\d{3,4}|Z",fn:function(c,f){f==="Z"&&(f=0);var p=Math.abs(f),d=(f>0?-1:1)*(p%100+Math.floor(p/100)*60);c.setUTCMinutes(c.getUTCMinutes()+d)}}],o=n.reduce(function(c,f){return f.pattern.test(c.regexp)?(f.index=c.regexp.match(f.pattern).index,c.regexp=c.regexp.replace(f.pattern,"("+f.regexp+")")):f.index=-1,c},{regexp:r,index:[]}),s=n.filter(function(c){return c.index>-1});s.sort(function(c,f){return c.index-f.index});var a=new RegExp(o.regexp),l=a.exec(e);if(l){var u=t||ui.exports.now();return s.forEach(function(c,f){c.fn(u,l[f+1])}),u}throw new Error("String '"+e+"' could not be parsed as '"+r+"'")}function iX(r,e,t){if(!r)throw new Error("pattern must be supplied");return rX(r,e,t)}function nX(){return new Date}ui.exports=aR;ui.exports.asString=aR;ui.exports.parse=iX;ui.exports.now=nX;ui.exports.ISO8601_FORMAT="yyyy-MM-ddThh:mm:ss.SSS";ui.exports.ISO8601_WITH_TZ_OFFSET_FORMAT="yyyy-MM-ddThh:mm:ss.SSSO";ui.exports.DATETIME_FORMAT="dd MM yyyy hh:mm:ss.SSS";ui.exports.ABSOLUTETIME_FORMAT="hh:mm:ss.SSS"});var ib=v((USe,uR)=>{var vo=lR(),cR=require("os"),ac=require("util"),fR=require("path"),pR={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[90,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[91,39],yellow:[33,39]};function dR(r){return r?`[${pR[r][0]}m`:""}function hR(r){return r?`[${pR[r][1]}m`:""}function oX(r,e){return dR(e)+r+hR(e)}function mR(r,e){return oX(ac.format("[%s] [%s] %s - ",vo.asString(r.startTime),r.level.toString(),r.categoryName),e)}function gR(r){return mR(r)+ac.format(...r.data)}function Md(r){return mR(r,r.level.colour)+ac.format(...r.data)}function vR(r){return ac.format(...r.data)}function yR(r){return r.data[0]}function bR(r,e){let t="%r %p %c - %m%n",i=/%(-?[0-9]+)?(\.?-?[0-9]+)?([[\]cdhmnprzxXyflos%])(\{([^}]+)\})?|([^%]+)/;r=r||t;function n(R,F){let q=R.categoryName;if(F){let K=parseInt(F,10),ae=q.split(".");KK&&(q=ae.slice(-K).join(fR.sep))}return q}function x(R){return R.lineNumber?`${R.lineNumber}`:""}function E(R){return R.columnNumber?`${R.columnNumber}`:""}function P(R){return R.callStack||""}let k={c:n,d:o,h:s,m:a,n:l,p:u,r:c,"[":f,"]":p,y:m,z:h,"%":d,x:y,X:g,f:w,l:x,o:E,s:P};function _(R,F,q){return k[R](F,q)}function L(R,F){let q;return R?(q=parseInt(R.substr(1),10),q>0?F.slice(0,q):F.slice(q)):F}function I(R,F){let q;if(R)if(R.charAt(0)==="-")for(q=parseInt(R.substr(1),10);F.length{var yt=xs(),xR=["white","grey","black","blue","cyan","green","magenta","red","yellow"],Tt=class{constructor(e,t,i){this.level=e,this.levelStr=t,this.colour=i}toString(){return this.levelStr}static getLevel(e,t){return e?e instanceof Tt?e:(e instanceof Object&&e.levelStr&&(e=e.levelStr),Tt[e.toString().toUpperCase()]||t):t}static addLevels(e){e&&(Object.keys(e).forEach(i=>{let n=i.toUpperCase();Tt[n]=new Tt(e[i].value,n,e[i].colour);let o=Tt.levels.findIndex(s=>s.levelStr===n);o>-1?Tt.levels[o]=Tt[n]:Tt.levels.push(Tt[n])}),Tt.levels.sort((i,n)=>i.level-n.level))}isLessThanOrEqualTo(e){return typeof e=="string"&&(e=Tt.getLevel(e)),this.level<=e.level}isGreaterThanOrEqualTo(e){return typeof e=="string"&&(e=Tt.getLevel(e)),this.level>=e.level}isEqualTo(e){return typeof e=="string"&&(e=Tt.getLevel(e)),this.level===e.level}};Tt.levels=[];Tt.addLevels({ALL:{value:Number.MIN_VALUE,colour:"grey"},TRACE:{value:5e3,colour:"blue"},DEBUG:{value:1e4,colour:"cyan"},INFO:{value:2e4,colour:"green"},WARN:{value:3e4,colour:"yellow"},ERROR:{value:4e4,colour:"red"},FATAL:{value:5e4,colour:"magenta"},MARK:{value:9007199254740992,colour:"grey"},OFF:{value:Number.MAX_VALUE,colour:"grey"}});yt.addListener(r=>{let e=r.levels;e&&(yt.throwExceptionIf(r,yt.not(yt.anObject(e)),"levels must be an object"),Object.keys(e).forEach(i=>{yt.throwExceptionIf(r,yt.not(yt.validIdentifier(i)),`level name "${i}" is not a valid identifier (must start with a letter, only contain A-Z,a-z,0-9,_)`),yt.throwExceptionIf(r,yt.not(yt.anObject(e[i])),`level "${i}" must be an object`),yt.throwExceptionIf(r,yt.not(e[i].value),`level "${i}" must have a 'value' property`),yt.throwExceptionIf(r,yt.not(yt.anInteger(e[i].value)),`level "${i}".value must have an integer value`),yt.throwExceptionIf(r,yt.not(e[i].colour),`level "${i}" must have a 'colour' property`),yt.throwExceptionIf(r,yt.not(xR.indexOf(e[i].colour)>-1),`level "${i}".colour must be one of ${xR.join(", ")}`)}))});yt.addListener(r=>{Tt.addLevels(r.levels)});wR.exports=Tt});var DR=v(sX=>{ho(sX,{default:()=>aX,parse:()=>lX,stringify:()=>uX});var nb=function(r,e){var t={parse:function(u,c){var f=JSON.parse(u,a).map(s),p=f[0],d=c||i,h=typeof p=="object"&&p?n(f,new Set,p,d):p;return d.call({"":h},"",h)},stringify:function(u,c,f){for(var p,d=new Map,h=[],m=[],y=c&&typeof c==typeof h?function(x,E){if(x===""||-1{var ER=DR(),CR=Es(),lc=class{constructor(e,t,i,n,o){this.startTime=new Date,this.categoryName=e,this.data=i,this.level=t,this.context=Object.assign({},n),this.pid=process.pid,o&&(this.functionName=o.functionName,this.fileName=o.fileName,this.lineNumber=o.lineNumber,this.columnNumber=o.columnNumber,this.callStack=o.callStack)}serialise(){let e=this.data.map(t=>(t&&t.message&&t.stack&&(t=Object.assign({message:t.message,stack:t.stack},t)),t));return this.data=e,ER.stringify(this)}static deserialise(e){let t;try{let i=ER.parse(e);i.data=i.data.map(n=>{if(n&&n.message&&n.stack){let o=new Error(n);Object.keys(n).forEach(s=>{o[s]=n[s]}),n=o}return n}),t=new lc(i.categoryName,CR.getLevel(i.level.levelStr),i.data,i.context),t.startTime=new Date(i.startTime),t.pid=i.pid,t.cluster=i.cluster}catch(i){t=new lc("log4js",CR.ERROR,["Unable to parse log:",e,"because: ",i])}return t}};SR.exports=lc});var qd=v((GSe,_R)=>{var ci=vt()("log4js:clustering"),cX=ob(),fX=xs(),ja=!1,cn=null;try{cn=require("cluster")}catch(r){ci("cluster module not present"),ja=!0}var sb=[],uc=!1,cc="NODE_APP_INSTANCE",PR=()=>uc&&process.env[cc]==="0",ab=()=>ja||cn.isMaster||PR(),TR=r=>{sb.forEach(e=>e(r))},Nd=(r,e)=>{if(ci("cluster message received from worker ",r,": ",e),r.topic&&r.data&&(e=r,r=void 0),e&&e.topic&&e.topic==="log4js:message"){ci("received message: ",e.data);let t=cX.deserialise(e.data);TR(t)}};ja||fX.addListener(r=>{sb.length=0,{pm2:uc,disableClustering:ja,pm2InstanceVar:cc="NODE_APP_INSTANCE"}=r,ci(`clustering disabled ? ${ja}`),ci(`cluster.isMaster ? ${cn&&cn.isMaster}`),ci(`pm2 enabled ? ${uc}`),ci(`pm2InstanceVar = ${cc}`),ci(`process.env[${cc}] = ${process.env[cc]}`),uc&&process.removeListener("message",Nd),cn&&cn.removeListener&&cn.removeListener("message",Nd),ja||r.disableClustering?ci("Not listening for cluster messages, because clustering disabled."):PR()?(ci("listening for PM2 broadcast messages"),process.on("message",Nd)):cn.isMaster?(ci("listening for cluster messages"),cn.on("message",Nd)):ci("not listening for messages, because we are not a master process")});_R.exports={onlyOnMaster:(r,e)=>ab()?r():e,isMaster:ab,send:r=>{ab()?TR(r):(uc||(r.cluster={workerId:cn.worker.id,worker:process.pid}),process.send({topic:"log4js:message",data:r.serialise()}))},onMessage:r=>{sb.push(r)}}});var FR=v((VSe,RR)=>{function pX(r){if(typeof r=="number"&&Number.isInteger(r))return r;let e={K:1024,M:1024*1024,G:1024*1024*1024},t=Object.keys(e),i=r.substr(r.length-1).toLocaleUpperCase(),n=r.substring(0,r.length-1).trim();if(t.indexOf(i)<0||!Number.isInteger(Number(n)))throw Error(`maxLogSize: "${r}" is invalid`);return n*e[i]}function dX(r,e){let t=Object.assign({},e);return Object.keys(r).forEach(i=>{t[i]&&(t[i]=r[i](e[i]))}),t}function kR(r){return dX({maxLogSize:pX},r)}var IR={file:kR,fileSync:kR};RR.exports.modifyConfig=r=>IR[r.type]?IR[r.type](r):r});var OR=v((KSe,AR)=>{var hX=console.log.bind(console);function mX(r,e){return t=>{hX(r(t,e))}}function gX(r,e){let t=e.colouredLayout;return r.layout&&(t=e.layout(r.layout.type,r.layout)),mX(t,r.timezoneOffset)}AR.exports.configure=gX});var MR=v(LR=>{function vX(r,e){return t=>{process.stdout.write(`${r(t,e)} -`)}}function yX(r,e){let t=e.colouredLayout;return r.layout&&(t=e.layout(r.layout.type,r.layout)),vX(t,r.timezoneOffset)}LR.configure=yX});var qR=v((YSe,NR)=>{function bX(r,e){return t=>{process.stderr.write(`${r(t,e)} -`)}}function wX(r,e){let t=e.colouredLayout;return r.layout&&(t=e.layout(r.layout.type,r.layout)),bX(t,r.timezoneOffset)}NR.exports.configure=wX});var BR=v((XSe,$R)=>{function xX(r,e,t,i){let n=i.getLevel(r),o=i.getLevel(e,i.FATAL);return s=>{let a=s.level;a.isGreaterThanOrEqualTo(n)&&a.isLessThanOrEqualTo(o)&&t(s)}}function DX(r,e,t,i){let n=t(r.appender);return xX(r.level,r.maxLevel,n,i)}$R.exports.configure=DX});var WR=v((ZSe,jR)=>{var UR=vt()("log4js:categoryFilter");function SX(r,e){return typeof r=="string"&&(r=[r]),t=>{UR(`Checking ${t.categoryName} against ${r}`),r.indexOf(t.categoryName)===-1&&(UR("Not excluded, sending to appender"),e(t))}}function EX(r,e,t){let i=t(r.appender);return SX(r.exclude,i)}jR.exports.configure=EX});var GR=v((QSe,HR)=>{var zR=vt()("log4js:noLogFilter");function CX(r){return r.filter(t=>t!=null&&t!=="")}function _X(r,e){return t=>{zR(`Checking data: ${t.data} against filters: ${r}`),typeof r=="string"&&(r=[r]),r=CX(r);let i=new RegExp(r.join("|"),"i");(r.length===0||t.data.findIndex(n=>i.test(n))<0)&&(zR("Not excluded, sending to appender"),e(t))}}function PX(r,e,t){let i=t(r.appender);return _X(r.exclude,i)}HR.exports.configure=PX});var Cr=v(lb=>{"use strict";lb.fromCallback=function(r){return Object.defineProperty(function(){if(typeof arguments[arguments.length-1]=="function")r.apply(this,arguments);else return new Promise((e,t)=>{arguments[arguments.length]=(i,n)=>{if(i)return t(i);e(n)},arguments.length++,r.apply(this,arguments)})},"name",{value:r.name})};lb.fromPromise=function(r){return Object.defineProperty(function(){let e=arguments[arguments.length-1];if(typeof e!="function")return r.apply(this,arguments);r.apply(this,arguments).then(t=>e(null,t),e)},"name",{value:r.name})}});var KR=v((tEe,VR)=>{var yo=require("constants"),TX=process.cwd,$d=null,RX=process.env.GRACEFUL_FS_PLATFORM||process.platform;process.cwd=function(){return $d||($d=TX.call(process)),$d};try{process.cwd()}catch(r){}var kX=process.chdir;process.chdir=function(r){$d=null,kX.call(process,r)};VR.exports=IX;function IX(r){yo.hasOwnProperty("O_SYMLINK")&&process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)&&e(r),r.lutimes||t(r),r.chown=o(r.chown),r.fchown=o(r.fchown),r.lchown=o(r.lchown),r.chmod=i(r.chmod),r.fchmod=i(r.fchmod),r.lchmod=i(r.lchmod),r.chownSync=s(r.chownSync),r.fchownSync=s(r.fchownSync),r.lchownSync=s(r.lchownSync),r.chmodSync=n(r.chmodSync),r.fchmodSync=n(r.fchmodSync),r.lchmodSync=n(r.lchmodSync),r.stat=a(r.stat),r.fstat=a(r.fstat),r.lstat=a(r.lstat),r.statSync=l(r.statSync),r.fstatSync=l(r.fstatSync),r.lstatSync=l(r.lstatSync),r.lchmod||(r.lchmod=function(c,f,p){p&&process.nextTick(p)},r.lchmodSync=function(){}),r.lchown||(r.lchown=function(c,f,p,d){d&&process.nextTick(d)},r.lchownSync=function(){}),RX==="win32"&&(r.rename=function(c){return function(f,p,d){var h=Date.now(),m=0;c(f,p,function y(g){if(g&&(g.code==="EACCES"||g.code==="EPERM")&&Date.now()-h<6e4){setTimeout(function(){r.stat(p,function(w,x){w&&w.code==="ENOENT"?c(f,p,y):d(g)})},m),m<100&&(m+=10);return}d&&d(g)})}}(r.rename)),r.read=function(c){function f(p,d,h,m,y,g){var w;if(g&&typeof g=="function"){var x=0;w=function(E,P,k){if(E&&E.code==="EAGAIN"&&x<10)return x++,c.call(r,p,d,h,m,y,w);g.apply(this,arguments)}}return c.call(r,p,d,h,m,y,w)}return f.__proto__=c,f}(r.read),r.readSync=function(c){return function(f,p,d,h,m){for(var y=0;;)try{return c.call(r,f,p,d,h,m)}catch(g){if(g.code==="EAGAIN"&&y<10){y++;continue}throw g}}}(r.readSync);function e(c){c.lchmod=function(f,p,d){c.open(f,yo.O_WRONLY|yo.O_SYMLINK,p,function(h,m){if(h){d&&d(h);return}c.fchmod(m,p,function(y){c.close(m,function(g){d&&d(y||g)})})})},c.lchmodSync=function(f,p){var d=c.openSync(f,yo.O_WRONLY|yo.O_SYMLINK,p),h=!0,m;try{m=c.fchmodSync(d,p),h=!1}finally{if(h)try{c.closeSync(d)}catch(y){}else c.closeSync(d)}return m}}function t(c){yo.hasOwnProperty("O_SYMLINK")?(c.lutimes=function(f,p,d,h){c.open(f,yo.O_SYMLINK,function(m,y){if(m){h&&h(m);return}c.futimes(y,p,d,function(g){c.close(y,function(w){h&&h(g||w)})})})},c.lutimesSync=function(f,p,d){var h=c.openSync(f,yo.O_SYMLINK),m,y=!0;try{m=c.futimesSync(h,p,d),y=!1}finally{if(y)try{c.closeSync(h)}catch(g){}else c.closeSync(h)}return m}):(c.lutimes=function(f,p,d,h){h&&process.nextTick(h)},c.lutimesSync=function(){})}function i(c){return c&&function(f,p,d){return c.call(r,f,p,function(h){u(h)&&(h=null),d&&d.apply(this,arguments)})}}function n(c){return c&&function(f,p){try{return c.call(r,f,p)}catch(d){if(!u(d))throw d}}}function o(c){return c&&function(f,p,d,h){return c.call(r,f,p,d,function(m){u(m)&&(m=null),h&&h.apply(this,arguments)})}}function s(c){return c&&function(f,p,d){try{return c.call(r,f,p,d)}catch(h){if(!u(h))throw h}}}function a(c){return c&&function(f,p,d){typeof p=="function"&&(d=p,p=null);function h(m,y){y&&(y.uid<0&&(y.uid+=4294967296),y.gid<0&&(y.gid+=4294967296)),d&&d.apply(this,arguments)}return p?c.call(r,f,p,h):c.call(r,f,h)}}function l(c){return c&&function(f,p){var d=p?c.call(r,f,p):c.call(r,f);return d.uid<0&&(d.uid+=4294967296),d.gid<0&&(d.gid+=4294967296),d}}function u(c){if(!c||c.code==="ENOSYS")return!0;var f=!process.getuid||process.getuid()!==0;return!!(f&&(c.code==="EINVAL"||c.code==="EPERM"))}}});var XR=v((rEe,JR)=>{var YR=require("stream").Stream;JR.exports=FX;function FX(r){return{ReadStream:e,WriteStream:t};function e(i,n){if(!(this instanceof e))return new e(i,n);YR.call(this);var o=this;this.path=i,this.fd=null,this.readable=!0,this.paused=!1,this.flags="r",this.mode=438,this.bufferSize=64*1024,n=n||{};for(var s=Object.keys(n),a=0,l=s.length;athis.end)throw new Error("start must be <= end");this.pos=this.start}if(this.fd!==null){process.nextTick(function(){o._read()});return}r.open(this.path,this.flags,this.mode,function(c,f){if(c){o.emit("error",c),o.readable=!1;return}o.fd=f,o.emit("open",f),o._read()})}function t(i,n){if(!(this instanceof t))return new t(i,n);YR.call(this),this.path=i,this.fd=null,this.writable=!0,this.flags="w",this.encoding="binary",this.mode=438,this.bytesWritten=0,n=n||{};for(var o=Object.keys(n),s=0,a=o.length;s= zero");this.pos=this.start}this.busy=!1,this._queue=[],this.fd===null&&(this._open=r.open,this._queue.push([this._open,this.path,this.flags,this.mode,void 0]),this.flush())}}});var QR=v((iEe,ZR)=>{"use strict";ZR.exports=AX;function AX(r){if(r===null||typeof r!="object")return r;if(r instanceof Object)var e={__proto__:r.__proto__};else var e=Object.create(null);return Object.getOwnPropertyNames(r).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}),e}});var Ce=v((nEe,ub)=>{var Bt=require("fs"),OX=KR(),LX=XR(),MX=QR(),Bd=require("util"),Ni,jd;typeof Symbol=="function"&&typeof Symbol.for=="function"?(Ni=Symbol.for("graceful-fs.queue"),jd=Symbol.for("graceful-fs.previous")):(Ni="___graceful-fs.queue",jd="___graceful-fs.previous");function NX(){}function ek(r,e){Object.defineProperty(r,Ni,{get:function(){return e}})}var fc=NX;Bd.debuglog?fc=Bd.debuglog("gfs4"):/\bgfs4\b/i.test(process.env.NODE_DEBUG||"")&&(fc=function(){var r=Bd.format.apply(Bd,arguments);r="GFS4: "+r.split(/\n/).join(` -GFS4: `),console.error(r)});Bt[Ni]||(tk=global[Ni]||[],ek(Bt,tk),Bt.close=function(r){function e(t,i){return r.call(Bt,t,function(n){n||Cs(),typeof i=="function"&&i.apply(this,arguments)})}return Object.defineProperty(e,jd,{value:r}),e}(Bt.close),Bt.closeSync=function(r){function e(t){r.apply(Bt,arguments),Cs()}return Object.defineProperty(e,jd,{value:r}),e}(Bt.closeSync),/\bgfs4\b/i.test(process.env.NODE_DEBUG||"")&&process.on("exit",function(){fc(Bt[Ni]),require("assert").equal(Bt[Ni].length,0)}));var tk;global[Ni]||ek(global,Bt[Ni]);ub.exports=cb(MX(Bt));process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH&&!Bt.__patched&&(ub.exports=cb(Bt),Bt.__patched=!0);function cb(r){OX(r),r.gracefulify=cb,r.createReadStream=x,r.createWriteStream=E;var e=r.readFile;r.readFile=t;function t(_,L,I){return typeof L=="function"&&(I=L,L=null),O(_,L,I);function O(R,F,q){return e(R,F,function(K){K&&(K.code==="EMFILE"||K.code==="ENFILE")?pc([O,[R,F,q]]):(typeof q=="function"&&q.apply(this,arguments),Cs())})}}var i=r.writeFile;r.writeFile=n;function n(_,L,I,O){return typeof I=="function"&&(O=I,I=null),R(_,L,I,O);function R(F,q,K,ae){return i(F,q,K,function(Pe){Pe&&(Pe.code==="EMFILE"||Pe.code==="ENFILE")?pc([R,[F,q,K,ae]]):(typeof ae=="function"&&ae.apply(this,arguments),Cs())})}}var o=r.appendFile;o&&(r.appendFile=s);function s(_,L,I,O){return typeof I=="function"&&(O=I,I=null),R(_,L,I,O);function R(F,q,K,ae){return o(F,q,K,function(Pe){Pe&&(Pe.code==="EMFILE"||Pe.code==="ENFILE")?pc([R,[F,q,K,ae]]):(typeof ae=="function"&&ae.apply(this,arguments),Cs())})}}var a=r.readdir;r.readdir=l;function l(_,L,I){var O=[_];return typeof L!="function"?O.push(L):I=L,O.push(R),u(O);function R(F,q){q&&q.sort&&q.sort(),F&&(F.code==="EMFILE"||F.code==="ENFILE")?pc([u,[O]]):(typeof I=="function"&&I.apply(this,arguments),Cs())}}function u(_){return a.apply(r,_)}if(process.version.substr(0,4)==="v0.8"){var c=LX(r);m=c.ReadStream,g=c.WriteStream}var f=r.ReadStream;f&&(m.prototype=Object.create(f.prototype),m.prototype.open=y);var p=r.WriteStream;p&&(g.prototype=Object.create(p.prototype),g.prototype.open=w),Object.defineProperty(r,"ReadStream",{get:function(){return m},set:function(_){m=_},enumerable:!0,configurable:!0}),Object.defineProperty(r,"WriteStream",{get:function(){return g},set:function(_){g=_},enumerable:!0,configurable:!0});var d=m;Object.defineProperty(r,"FileReadStream",{get:function(){return d},set:function(_){d=_},enumerable:!0,configurable:!0});var h=g;Object.defineProperty(r,"FileWriteStream",{get:function(){return h},set:function(_){h=_},enumerable:!0,configurable:!0});function m(_,L){return this instanceof m?(f.apply(this,arguments),this):m.apply(Object.create(m.prototype),arguments)}function y(){var _=this;k(_.path,_.flags,_.mode,function(L,I){L?(_.autoClose&&_.destroy(),_.emit("error",L)):(_.fd=I,_.emit("open",I),_.read())})}function g(_,L){return this instanceof g?(p.apply(this,arguments),this):g.apply(Object.create(g.prototype),arguments)}function w(){var _=this;k(_.path,_.flags,_.mode,function(L,I){L?(_.destroy(),_.emit("error",L)):(_.fd=I,_.emit("open",I))})}function x(_,L){return new r.ReadStream(_,L)}function E(_,L){return new r.WriteStream(_,L)}var P=r.open;r.open=k;function k(_,L,I,O){return typeof I=="function"&&(O=I,I=null),R(_,L,I,O);function R(F,q,K,ae){return P(F,q,K,function(Pe,We){Pe&&(Pe.code==="EMFILE"||Pe.code==="ENFILE")?pc([R,[F,q,K,ae]]):(typeof ae=="function"&&ae.apply(this,arguments),Cs())})}}return r}function pc(r){fc("ENQUEUE",r[0].name,r[1]),Bt[Ni].push(r)}function Cs(){var r=Bt[Ni].shift();r&&(fc("RETRY",r[0].name,r[1]),r[0].apply(null,r[1]))}});var fb=v(_s=>{"use strict";var rk=Cr().fromCallback,fi=Ce(),qX=["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(r=>typeof fi[r]=="function");Object.keys(fi).forEach(r=>{r!=="promises"&&(_s[r]=fi[r])});qX.forEach(r=>{_s[r]=rk(fi[r])});_s.exists=function(r,e){return typeof e=="function"?fi.exists(r,e):new Promise(t=>fi.exists(r,t))};_s.read=function(r,e,t,i,n,o){return typeof o=="function"?fi.read(r,e,t,i,n,o):new Promise((s,a)=>{fi.read(r,e,t,i,n,(l,u,c)=>{if(l)return a(l);s({bytesRead:u,buffer:c})})})};_s.write=function(r,e,...t){return typeof t[t.length-1]=="function"?fi.write(r,e,...t):new Promise((i,n)=>{fi.write(r,e,...t,(o,s,a)=>{if(o)return n(o);i({bytesWritten:s,buffer:a})})})};typeof fi.realpath.native=="function"&&(_s.realpath.native=rk(fi.realpath.native))});var db=v((sEe,ik)=>{"use strict";var pb=require("path");function nk(r){return r=pb.normalize(pb.resolve(r)).split(pb.sep),r.length>0?r[0]:null}var $X=/[<>:"|?*]/;function BX(r){let e=nk(r);return r=r.replace(e,""),$X.test(r)}ik.exports={getRootPath:nk,invalidWin32Path:BX}});var sk=v((aEe,ok)=>{"use strict";var jX=Ce(),hb=require("path"),UX=db().invalidWin32Path,WX=parseInt("0777",8);function mb(r,e,t,i){if(typeof e=="function"?(t=e,e={}):(!e||typeof e!="object")&&(e={mode:e}),process.platform==="win32"&&UX(r)){let s=new Error(r+" contains invalid WIN32 path characters.");return s.code="EINVAL",t(s)}let n=e.mode,o=e.fs||jX;n===void 0&&(n=WX&~process.umask()),i||(i=null),t=t||function(){},r=hb.resolve(r),o.mkdir(r,n,s=>{if(!s)return i=i||r,t(null,i);switch(s.code){case"ENOENT":if(hb.dirname(r)===r)return t(s);mb(hb.dirname(r),e,(a,l)=>{a?t(a,l):mb(r,e,t,l)});break;default:o.stat(r,(a,l)=>{a||!l.isDirectory()?t(s,i):t(null,i)});break}})}ok.exports=mb});var lk=v((lEe,ak)=>{"use strict";var HX=Ce(),gb=require("path"),zX=db().invalidWin32Path,GX=parseInt("0777",8);function vb(r,e,t){(!e||typeof e!="object")&&(e={mode:e});let i=e.mode,n=e.fs||HX;if(process.platform==="win32"&&zX(r)){let o=new Error(r+" contains invalid WIN32 path characters.");throw o.code="EINVAL",o}i===void 0&&(i=GX&~process.umask()),t||(t=null),r=gb.resolve(r);try{n.mkdirSync(r,i),t=t||r}catch(o){if(o.code==="ENOENT"){if(gb.dirname(r)===r)throw o;t=vb(gb.dirname(r),e,t),vb(r,e,t)}else{let s;try{s=n.statSync(r)}catch(a){throw o}if(!s.isDirectory())throw o}}return t}ak.exports=vb});var jr=v((uEe,uk)=>{"use strict";var VX=Cr().fromCallback,yb=VX(sk()),bb=lk();uk.exports={mkdirs:yb,mkdirsSync:bb,mkdirp:yb,mkdirpSync:bb,ensureDir:yb,ensureDirSync:bb}});var wb=v((cEe,ck)=>{"use strict";var er=Ce(),fk=require("os"),Ud=require("path");function KX(){let r=Ud.join("millis-test-sync"+Date.now().toString()+Math.random().toString().slice(2));r=Ud.join(fk.tmpdir(),r);let e=new Date(1435410243862);er.writeFileSync(r,"https://github.com/jprichardson/node-fs-extra/pull/141");let t=er.openSync(r,"r+");return er.futimesSync(t,e,e),er.closeSync(t),er.statSync(r).mtime>1435410243e3}function JX(r){let e=Ud.join("millis-test"+Date.now().toString()+Math.random().toString().slice(2));e=Ud.join(fk.tmpdir(),e);let t=new Date(1435410243862);er.writeFile(e,"https://github.com/jprichardson/node-fs-extra/pull/141",i=>{if(i)return r(i);er.open(e,"r+",(n,o)=>{if(n)return r(n);er.futimes(o,t,t,s=>{if(s)return r(s);er.close(o,a=>{if(a)return r(a);er.stat(e,(l,u)=>{if(l)return r(l);r(null,u.mtime>1435410243e3)})})})})})}function YX(r){if(typeof r=="number")return Math.floor(r/1e3)*1e3;if(r instanceof Date)return new Date(Math.floor(r.getTime()/1e3)*1e3);throw new Error("fs-extra: timeRemoveMillis() unknown parameter type")}function XX(r,e,t,i){er.open(r,"r+",(n,o)=>{if(n)return i(n);er.futimes(o,e,t,s=>{er.close(o,a=>{i&&i(s||a)})})})}function ZX(r,e,t){let i=er.openSync(r,"r+");return er.futimesSync(i,e,t),er.closeSync(i)}ck.exports={hasMillisRes:JX,hasMillisResSync:KX,timeRemoveMillis:YX,utimesMillis:XX,utimesMillisSync:ZX}});var mc=v((fEe,pk)=>{"use strict";var pi=Ce(),_r=require("path"),dk=10,hk=5,QX=0,xb=process.versions.node.split("."),mk=Number.parseInt(xb[0],10),gk=Number.parseInt(xb[1],10),eZ=Number.parseInt(xb[2],10);function dc(){if(mk>dk)return!0;if(mk===dk){if(gk>hk)return!0;if(gk===hk&&eZ>=QX)return!0}return!1}function tZ(r,e,t){dc()?pi.stat(r,{bigint:!0},(i,n)=>{if(i)return t(i);pi.stat(e,{bigint:!0},(o,s)=>o?o.code==="ENOENT"?t(null,{srcStat:n,destStat:null}):t(o):t(null,{srcStat:n,destStat:s}))}):pi.stat(r,(i,n)=>{if(i)return t(i);pi.stat(e,(o,s)=>o?o.code==="ENOENT"?t(null,{srcStat:n,destStat:null}):t(o):t(null,{srcStat:n,destStat:s}))})}function rZ(r,e){let t,i;dc()?t=pi.statSync(r,{bigint:!0}):t=pi.statSync(r);try{dc()?i=pi.statSync(e,{bigint:!0}):i=pi.statSync(e)}catch(n){if(n.code==="ENOENT")return{srcStat:t,destStat:null};throw n}return{srcStat:t,destStat:i}}function iZ(r,e,t,i){tZ(r,e,(n,o)=>{if(n)return i(n);let{srcStat:s,destStat:a}=o;return a&&a.ino&&a.dev&&a.ino===s.ino&&a.dev===s.dev?i(new Error("Source and destination must not be the same.")):s.isDirectory()&&Db(r,e)?i(new Error(hc(r,e,t))):i(null,{srcStat:s,destStat:a})})}function nZ(r,e,t){let{srcStat:i,destStat:n}=rZ(r,e);if(n&&n.ino&&n.dev&&n.ino===i.ino&&n.dev===i.dev)throw new Error("Source and destination must not be the same.");if(i.isDirectory()&&Db(r,e))throw new Error(hc(r,e,t));return{srcStat:i,destStat:n}}function Sb(r,e,t,i,n){let o=_r.resolve(_r.dirname(r)),s=_r.resolve(_r.dirname(t));if(s===o||s===_r.parse(s).root)return n();dc()?pi.stat(s,{bigint:!0},(a,l)=>a?a.code==="ENOENT"?n():n(a):l.ino&&l.dev&&l.ino===e.ino&&l.dev===e.dev?n(new Error(hc(r,t,i))):Sb(r,e,s,i,n)):pi.stat(s,(a,l)=>a?a.code==="ENOENT"?n():n(a):l.ino&&l.dev&&l.ino===e.ino&&l.dev===e.dev?n(new Error(hc(r,t,i))):Sb(r,e,s,i,n))}function vk(r,e,t,i){let n=_r.resolve(_r.dirname(r)),o=_r.resolve(_r.dirname(t));if(o===n||o===_r.parse(o).root)return;let s;try{dc()?s=pi.statSync(o,{bigint:!0}):s=pi.statSync(o)}catch(a){if(a.code==="ENOENT")return;throw a}if(s.ino&&s.dev&&s.ino===e.ino&&s.dev===e.dev)throw new Error(hc(r,t,i));return vk(r,e,o,i)}function Db(r,e){let t=_r.resolve(r).split(_r.sep).filter(n=>n),i=_r.resolve(e).split(_r.sep).filter(n=>n);return t.reduce((n,o,s)=>n&&i[s]===o,!0)}function hc(r,e,t){return`Cannot ${t} '${r}' to a subdirectory of itself, '${e}'.`}pk.exports={checkPaths:iZ,checkPathsSync:nZ,checkParentPaths:Sb,checkParentPathsSync:vk,isSrcSubdir:Db}});var bk=v((pEe,yk)=>{"use strict";yk.exports=function(r){if(typeof Buffer.allocUnsafe=="function")try{return Buffer.allocUnsafe(r)}catch(e){return new Buffer(r)}return new Buffer(r)}});var Ek=v((dEe,wk)=>{"use strict";var nt=Ce(),gc=require("path"),oZ=jr().mkdirsSync,sZ=wb().utimesMillisSync,vc=mc();function lZ(r,e,t){typeof t=="function"&&(t={filter:t}),t=t||{},t.clobber="clobber"in t?!!t.clobber:!0,t.overwrite="overwrite"in t?!!t.overwrite:t.clobber,t.preserveTimestamps&&process.arch==="ia32"&&console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended; - - see https://github.com/jprichardson/node-fs-extra/issues/269`);let{srcStat:i,destStat:n}=vc.checkPathsSync(r,e,"copy");return vc.checkParentPathsSync(r,i,e,"copy"),aZ(n,r,e,t)}function aZ(r,e,t,i){if(i.filter&&!i.filter(e,t))return;let n=gc.dirname(t);return nt.existsSync(n)||oZ(n),xk(r,e,t,i)}function xk(r,e,t,i){if(!(i.filter&&!i.filter(e,t)))return uZ(r,e,t,i)}function uZ(r,e,t,i){let o=(i.dereference?nt.statSync:nt.lstatSync)(e);if(o.isDirectory())return fZ(o,r,e,t,i);if(o.isFile()||o.isCharacterDevice()||o.isBlockDevice())return cZ(o,r,e,t,i);if(o.isSymbolicLink())return pZ(r,e,t,i)}function cZ(r,e,t,i,n){return e?dZ(r,t,i,n):Dk(r,t,i,n)}function dZ(r,e,t,i){if(i.overwrite)return nt.unlinkSync(t),Dk(r,e,t,i);if(i.errorOnExist)throw new Error(`'${t}' already exists`)}function Dk(r,e,t,i){return typeof nt.copyFileSync=="function"?(nt.copyFileSync(e,t),nt.chmodSync(t,r.mode),i.preserveTimestamps?sZ(t,r.atime,r.mtime):void 0):hZ(r,e,t,i)}function hZ(r,e,t,i){let n=64*1024,o=bk()(n),s=nt.openSync(e,"r"),a=nt.openSync(t,"w",r.mode),l=0;for(;lgZ(i,r,e,t))}function gZ(r,e,t,i){let n=gc.join(e,r),o=gc.join(t,r),{destStat:s}=vc.checkPathsSync(n,o,"copy");return xk(s,n,o,i)}function pZ(r,e,t,i){let n=nt.readlinkSync(e);if(i.dereference&&(n=gc.resolve(process.cwd(),n)),r){let o;try{o=nt.readlinkSync(t)}catch(s){if(s.code==="EINVAL"||s.code==="UNKNOWN")return nt.symlinkSync(n,t);throw s}if(i.dereference&&(o=gc.resolve(process.cwd(),o)),vc.isSrcSubdir(n,o))throw new Error(`Cannot copy '${n}' to a subdirectory of itself, '${o}'.`);if(nt.statSync(t).isDirectory()&&vc.isSrcSubdir(o,n))throw new Error(`Cannot overwrite '${o}' with '${n}'.`);return vZ(n,t)}else return nt.symlinkSync(n,t)}function vZ(r,e){return nt.unlinkSync(e),nt.symlinkSync(r,e)}wk.exports=lZ});var Eb=v((hEe,Ck)=>{"use strict";Ck.exports={copySync:Ek()}});var fn=v((mEe,_k)=>{"use strict";var yZ=Cr().fromPromise,Pk=fb();function bZ(r){return Pk.access(r).then(()=>!0).catch(()=>!1)}_k.exports={pathExists:yZ(bZ),pathExistsSync:Pk.existsSync}});var Mk=v((gEe,Tk)=>{"use strict";var jt=Ce(),yc=require("path"),wZ=jr().mkdirs,xZ=fn().pathExists,DZ=wb().utimesMillis,bc=mc();function SZ(r,e,t,i){typeof t=="function"&&!i?(i=t,t={}):typeof t=="function"&&(t={filter:t}),i=i||function(){},t=t||{},t.clobber="clobber"in t?!!t.clobber:!0,t.overwrite="overwrite"in t?!!t.overwrite:t.clobber,t.preserveTimestamps&&process.arch==="ia32"&&console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended; - - see https://github.com/jprichardson/node-fs-extra/issues/269`),bc.checkPaths(r,e,"copy",(n,o)=>{if(n)return i(n);let{srcStat:s,destStat:a}=o;bc.checkParentPaths(r,s,e,"copy",l=>l?i(l):t.filter?kk(Rk,a,r,e,t,i):Rk(a,r,e,t,i))})}function Rk(r,e,t,i,n){let o=yc.dirname(t);xZ(o,(s,a)=>{if(s)return n(s);if(a)return Cb(r,e,t,i,n);wZ(o,l=>l?n(l):Cb(r,e,t,i,n))})}function kk(r,e,t,i,n,o){Promise.resolve(n.filter(t,i)).then(s=>s?r(e,t,i,n,o):o(),s=>o(s))}function Cb(r,e,t,i,n){return i.filter?kk(Ik,r,e,t,i,n):Ik(r,e,t,i,n)}function Ik(r,e,t,i,n){(i.dereference?jt.stat:jt.lstat)(e,(s,a)=>{if(s)return n(s);if(a.isDirectory())return CZ(a,r,e,t,i,n);if(a.isFile()||a.isCharacterDevice()||a.isBlockDevice())return EZ(a,r,e,t,i,n);if(a.isSymbolicLink())return _Z(r,e,t,i,n)})}function EZ(r,e,t,i,n,o){return e?PZ(r,t,i,n,o):Fk(r,t,i,n,o)}function PZ(r,e,t,i,n){if(i.overwrite)jt.unlink(t,o=>o?n(o):Fk(r,e,t,i,n));else return i.errorOnExist?n(new Error(`'${t}' already exists`)):n()}function Fk(r,e,t,i,n){return typeof jt.copyFile=="function"?jt.copyFile(e,t,o=>o?n(o):Ak(r,t,i,n)):TZ(r,e,t,i,n)}function TZ(r,e,t,i,n){let o=jt.createReadStream(e);o.on("error",s=>n(s)).once("open",()=>{let s=jt.createWriteStream(t,{mode:r.mode});s.on("error",a=>n(a)).on("open",()=>o.pipe(s)).once("close",()=>Ak(r,t,i,n))})}function Ak(r,e,t,i){jt.chmod(e,r.mode,n=>n?i(n):t.preserveTimestamps?DZ(e,r.atime,r.mtime,i):i())}function CZ(r,e,t,i,n,o){return e?e&&!e.isDirectory()?o(new Error(`Cannot overwrite non-directory '${i}' with directory '${t}'.`)):Ok(t,i,n,o):RZ(r,t,i,n,o)}function RZ(r,e,t,i,n){jt.mkdir(t,o=>{if(o)return n(o);Ok(e,t,i,s=>s?n(s):jt.chmod(t,r.mode,n))})}function Ok(r,e,t,i){jt.readdir(r,(n,o)=>n?i(n):Lk(o,r,e,t,i))}function Lk(r,e,t,i,n){let o=r.pop();return o?kZ(r,o,e,t,i,n):n()}function kZ(r,e,t,i,n,o){let s=yc.join(t,e),a=yc.join(i,e);bc.checkPaths(s,a,"copy",(l,u)=>{if(l)return o(l);let{destStat:c}=u;Cb(c,s,a,n,f=>f?o(f):Lk(r,t,i,n,o))})}function _Z(r,e,t,i,n){jt.readlink(e,(o,s)=>{if(o)return n(o);if(i.dereference&&(s=yc.resolve(process.cwd(),s)),r)jt.readlink(t,(a,l)=>a?a.code==="EINVAL"||a.code==="UNKNOWN"?jt.symlink(s,t,n):n(a):(i.dereference&&(l=yc.resolve(process.cwd(),l)),bc.isSrcSubdir(s,l)?n(new Error(`Cannot copy '${s}' to a subdirectory of itself, '${l}'.`)):r.isDirectory()&&bc.isSrcSubdir(l,s)?n(new Error(`Cannot overwrite '${l}' with '${s}'.`)):IZ(s,t,n)));else return jt.symlink(s,t,n)})}function IZ(r,e,t){jt.unlink(e,i=>i?t(i):jt.symlink(r,e,t))}Tk.exports=SZ});var _b=v((vEe,Nk)=>{"use strict";var FZ=Cr().fromCallback;Nk.exports={copy:FZ(Mk())}});var Gk=v((yEe,qk)=>{"use strict";var $k=Ce(),Bk=require("path"),Le=require("assert"),wc=process.platform==="win32";function jk(r){["unlink","chmod","stat","lstat","rmdir","readdir"].forEach(t=>{r[t]=r[t]||$k[t],t=t+"Sync",r[t]=r[t]||$k[t]}),r.maxBusyTries=r.maxBusyTries||3}function Pb(r,e,t){let i=0;typeof e=="function"&&(t=e,e={}),Le(r,"rimraf: missing path"),Le.strictEqual(typeof r,"string","rimraf: path should be a string"),Le.strictEqual(typeof t,"function","rimraf: callback function required"),Le(e,"rimraf: invalid options argument provided"),Le.strictEqual(typeof e,"object","rimraf: options should be object"),jk(e),Uk(r,e,function n(o){if(o){if((o.code==="EBUSY"||o.code==="ENOTEMPTY"||o.code==="EPERM")&&iUk(r,e,n),s)}o.code==="ENOENT"&&(o=null)}t(o)})}function Uk(r,e,t){Le(r),Le(e),Le(typeof t=="function"),e.lstat(r,(i,n)=>{if(i&&i.code==="ENOENT")return t(null);if(i&&i.code==="EPERM"&&wc)return Wk(r,e,i,t);if(n&&n.isDirectory())return Wd(r,e,i,t);e.unlink(r,o=>{if(o){if(o.code==="ENOENT")return t(null);if(o.code==="EPERM")return wc?Wk(r,e,o,t):Wd(r,e,o,t);if(o.code==="EISDIR")return Wd(r,e,o,t)}return t(o)})})}function Wk(r,e,t,i){Le(r),Le(e),Le(typeof i=="function"),t&&Le(t instanceof Error),e.chmod(r,438,n=>{n?i(n.code==="ENOENT"?null:t):e.stat(r,(o,s)=>{o?i(o.code==="ENOENT"?null:t):s.isDirectory()?Wd(r,e,t,i):e.unlink(r,i)})})}function Hk(r,e,t){let i;Le(r),Le(e),t&&Le(t instanceof Error);try{e.chmodSync(r,438)}catch(n){if(n.code==="ENOENT")return;throw t}try{i=e.statSync(r)}catch(n){if(n.code==="ENOENT")return;throw t}i.isDirectory()?Hd(r,e,t):e.unlinkSync(r)}function Wd(r,e,t,i){Le(r),Le(e),t&&Le(t instanceof Error),Le(typeof i=="function"),e.rmdir(r,n=>{n&&(n.code==="ENOTEMPTY"||n.code==="EEXIST"||n.code==="EPERM")?AZ(r,e,i):n&&n.code==="ENOTDIR"?i(t):i(n)})}function AZ(r,e,t){Le(r),Le(e),Le(typeof t=="function"),e.readdir(r,(i,n)=>{if(i)return t(i);let o=n.length,s;if(o===0)return e.rmdir(r,t);n.forEach(a=>{Pb(Bk.join(r,a),e,l=>{if(!s){if(l)return t(s=l);--o==0&&e.rmdir(r,t)}})})})}function zk(r,e){let t;e=e||{},jk(e),Le(r,"rimraf: missing path"),Le.strictEqual(typeof r,"string","rimraf: path should be a string"),Le(e,"rimraf: missing options"),Le.strictEqual(typeof e,"object","rimraf: options should be object");try{t=e.lstatSync(r)}catch(i){if(i.code==="ENOENT")return;i.code==="EPERM"&&wc&&Hk(r,e,i)}try{t&&t.isDirectory()?Hd(r,e,null):e.unlinkSync(r)}catch(i){if(i.code==="ENOENT")return;if(i.code==="EPERM")return wc?Hk(r,e,i):Hd(r,e,i);if(i.code!=="EISDIR")throw i;Hd(r,e,i)}}function Hd(r,e,t){Le(r),Le(e),t&&Le(t instanceof Error);try{e.rmdirSync(r)}catch(i){if(i.code==="ENOTDIR")throw t;if(i.code==="ENOTEMPTY"||i.code==="EEXIST"||i.code==="EPERM")OZ(r,e);else if(i.code!=="ENOENT")throw i}}function OZ(r,e){if(Le(r),Le(e),e.readdirSync(r).forEach(t=>zk(Bk.join(r,t),e)),wc){let t=Date.now();do try{return e.rmdirSync(r,e)}catch(i){}while(Date.now()-t<500)}else return e.rmdirSync(r,e)}qk.exports=Pb;Pb.sync=zk});var xc=v((bEe,Vk)=>{"use strict";var LZ=Cr().fromCallback,Kk=Gk();Vk.exports={remove:LZ(Kk),removeSync:Kk.sync}});var r1=v((wEe,Jk)=>{"use strict";var MZ=Cr().fromCallback,Yk=Ce(),Xk=require("path"),Zk=jr(),Qk=xc(),e1=MZ(function(e,t){t=t||function(){},Yk.readdir(e,(i,n)=>{if(i)return Zk.mkdirs(e,t);n=n.map(s=>Xk.join(e,s)),o();function o(){let s=n.pop();if(!s)return t();Qk.remove(s,a=>{if(a)return t(a);o()})}})});function t1(r){let e;try{e=Yk.readdirSync(r)}catch(t){return Zk.mkdirsSync(r)}e.forEach(t=>{t=Xk.join(r,t),Qk.removeSync(t)})}Jk.exports={emptyDirSync:t1,emptydirSync:t1,emptyDir:e1,emptydir:e1}});var s1=v((xEe,i1)=>{"use strict";var NZ=Cr().fromCallback,n1=require("path"),Dc=Ce(),o1=jr(),qZ=fn().pathExists;function $Z(r,e){function t(){Dc.writeFile(r,"",i=>{if(i)return e(i);e()})}Dc.stat(r,(i,n)=>{if(!i&&n.isFile())return e();let o=n1.dirname(r);qZ(o,(s,a)=>{if(s)return e(s);if(a)return t();o1.mkdirs(o,l=>{if(l)return e(l);t()})})})}function BZ(r){let e;try{e=Dc.statSync(r)}catch(i){}if(e&&e.isFile())return;let t=n1.dirname(r);Dc.existsSync(t)||o1.mkdirsSync(t),Dc.writeFileSync(r,"")}i1.exports={createFile:NZ($Z),createFileSync:BZ}});var f1=v((DEe,a1)=>{"use strict";var jZ=Cr().fromCallback,l1=require("path"),Ps=Ce(),u1=jr(),c1=fn().pathExists;function UZ(r,e,t){function i(n,o){Ps.link(n,o,s=>{if(s)return t(s);t(null)})}c1(e,(n,o)=>{if(n)return t(n);if(o)return t(null);Ps.lstat(r,s=>{if(s)return s.message=s.message.replace("lstat","ensureLink"),t(s);let a=l1.dirname(e);c1(a,(l,u)=>{if(l)return t(l);if(u)return i(r,e);u1.mkdirs(a,c=>{if(c)return t(c);i(r,e)})})})})}function WZ(r,e){if(Ps.existsSync(e))return;try{Ps.lstatSync(r)}catch(o){throw o.message=o.message.replace("lstat","ensureLink"),o}let i=l1.dirname(e);return Ps.existsSync(i)||u1.mkdirsSync(i),Ps.linkSync(r,e)}a1.exports={createLink:jZ(UZ),createLinkSync:WZ}});var d1=v((SEe,p1)=>{"use strict";var bo=require("path"),Sc=Ce(),HZ=fn().pathExists;function zZ(r,e,t){if(bo.isAbsolute(r))return Sc.lstat(r,i=>i?(i.message=i.message.replace("lstat","ensureSymlink"),t(i)):t(null,{toCwd:r,toDst:r}));{let i=bo.dirname(e),n=bo.join(i,r);return HZ(n,(o,s)=>o?t(o):s?t(null,{toCwd:n,toDst:r}):Sc.lstat(r,a=>a?(a.message=a.message.replace("lstat","ensureSymlink"),t(a)):t(null,{toCwd:r,toDst:bo.relative(i,r)})))}}function GZ(r,e){let t;if(bo.isAbsolute(r)){if(t=Sc.existsSync(r),!t)throw new Error("absolute srcpath does not exist");return{toCwd:r,toDst:r}}else{let i=bo.dirname(e),n=bo.join(i,r);if(t=Sc.existsSync(n),t)return{toCwd:n,toDst:r};if(t=Sc.existsSync(r),!t)throw new Error("relative srcpath does not exist");return{toCwd:r,toDst:bo.relative(i,r)}}}p1.exports={symlinkPaths:zZ,symlinkPathsSync:GZ}});var g1=v((EEe,h1)=>{"use strict";var m1=Ce();function VZ(r,e,t){if(t=typeof e=="function"?e:t,e=typeof e=="function"?!1:e,e)return t(null,e);m1.lstat(r,(i,n)=>{if(i)return t(null,"file");e=n&&n.isDirectory()?"dir":"file",t(null,e)})}function KZ(r,e){let t;if(e)return e;try{t=m1.lstatSync(r)}catch(i){return"file"}return t&&t.isDirectory()?"dir":"file"}h1.exports={symlinkType:VZ,symlinkTypeSync:KZ}});var S1=v((CEe,v1)=>{"use strict";var JZ=Cr().fromCallback,y1=require("path"),Ua=Ce(),b1=jr(),YZ=b1.mkdirs,XZ=b1.mkdirsSync,w1=d1(),ZZ=w1.symlinkPaths,QZ=w1.symlinkPathsSync,x1=g1(),eQ=x1.symlinkType,tQ=x1.symlinkTypeSync,D1=fn().pathExists;function rQ(r,e,t,i){i=typeof t=="function"?t:i,t=typeof t=="function"?!1:t,D1(e,(n,o)=>{if(n)return i(n);if(o)return i(null);ZZ(r,e,(s,a)=>{if(s)return i(s);r=a.toDst,eQ(a.toCwd,t,(l,u)=>{if(l)return i(l);let c=y1.dirname(e);D1(c,(f,p)=>{if(f)return i(f);if(p)return Ua.symlink(r,e,u,i);YZ(c,d=>{if(d)return i(d);Ua.symlink(r,e,u,i)})})})})})}function iQ(r,e,t){if(Ua.existsSync(e))return;let n=QZ(r,e);r=n.toDst,t=tQ(n.toCwd,t);let o=y1.dirname(e);return Ua.existsSync(o)||XZ(o),Ua.symlinkSync(r,e,t)}v1.exports={createSymlink:JZ(rQ),createSymlinkSync:iQ}});var C1=v((_Ee,E1)=>{"use strict";var zd=s1(),Gd=f1(),Vd=S1();E1.exports={createFile:zd.createFile,createFileSync:zd.createFileSync,ensureFile:zd.createFile,ensureFileSync:zd.createFileSync,createLink:Gd.createLink,createLinkSync:Gd.createLinkSync,ensureLink:Gd.createLink,ensureLinkSync:Gd.createLinkSync,createSymlink:Vd.createSymlink,createSymlinkSync:Vd.createSymlinkSync,ensureSymlink:Vd.createSymlink,ensureSymlinkSync:Vd.createSymlinkSync}});var R1=v((PEe,_1)=>{var Wa;try{Wa=Ce()}catch(r){Wa=require("fs")}function nQ(r,e,t){t==null&&(t=e,e={}),typeof e=="string"&&(e={encoding:e}),e=e||{};var i=e.fs||Wa,n=!0;"throws"in e&&(n=e.throws),i.readFile(r,e,function(o,s){if(o)return t(o);s=P1(s);var a;try{a=JSON.parse(s,e?e.reviver:null)}catch(l){return n?(l.message=r+": "+l.message,t(l)):t(null,null)}t(null,a)})}function oQ(r,e){e=e||{},typeof e=="string"&&(e={encoding:e});var t=e.fs||Wa,i=!0;"throws"in e&&(i=e.throws);try{var n=t.readFileSync(r,e);return n=P1(n),JSON.parse(n,e.reviver)}catch(o){if(i)throw o.message=r+": "+o.message,o;return null}}function T1(r,e){var t,i=` -`;typeof e=="object"&&e!==null&&(e.spaces&&(t=e.spaces),e.EOL&&(i=e.EOL));var n=JSON.stringify(r,e?e.replacer:null,t);return n.replace(/\n/g,i)+i}function sQ(r,e,t,i){i==null&&(i=t,t={}),t=t||{};var n=t.fs||Wa,o="";try{o=T1(e,t)}catch(s){i&&i(s,null);return}n.writeFile(r,o,t,i)}function aQ(r,e,t){t=t||{};var i=t.fs||Wa,n=T1(e,t);return i.writeFileSync(r,n,t)}function P1(r){return Buffer.isBuffer(r)&&(r=r.toString("utf8")),r=r.replace(/^\uFEFF/,""),r}var lQ={readFile:nQ,readFileSync:oQ,writeFile:sQ,writeFileSync:aQ};_1.exports=lQ});var Jd=v((TEe,k1)=>{"use strict";var I1=Cr().fromCallback,Kd=R1();k1.exports={readJson:I1(Kd.readFile),readJsonSync:Kd.readFileSync,writeJson:I1(Kd.writeFile),writeJsonSync:Kd.writeFileSync}});var O1=v((REe,F1)=>{"use strict";var uQ=require("path"),cQ=jr(),fQ=fn().pathExists,A1=Jd();function pQ(r,e,t,i){typeof t=="function"&&(i=t,t={});let n=uQ.dirname(r);fQ(n,(o,s)=>{if(o)return i(o);if(s)return A1.writeJson(r,e,t,i);cQ.mkdirs(n,a=>{if(a)return i(a);A1.writeJson(r,e,t,i)})})}F1.exports=pQ});var M1=v((kEe,L1)=>{"use strict";var dQ=Ce(),hQ=require("path"),mQ=jr(),gQ=Jd();function vQ(r,e,t){let i=hQ.dirname(r);dQ.existsSync(i)||mQ.mkdirsSync(i),gQ.writeJsonSync(r,e,t)}L1.exports=vQ});var q1=v((IEe,N1)=>{"use strict";var yQ=Cr().fromCallback,gr=Jd();gr.outputJson=yQ(O1());gr.outputJsonSync=M1();gr.outputJSON=gr.outputJson;gr.outputJSONSync=gr.outputJsonSync;gr.writeJSON=gr.writeJson;gr.writeJSONSync=gr.writeJsonSync;gr.readJSON=gr.readJson;gr.readJSONSync=gr.readJsonSync;N1.exports=gr});var H1=v((FEe,$1)=>{"use strict";var B1=Ce(),bQ=require("path"),wQ=Eb().copySync,j1=xc().removeSync,xQ=jr().mkdirpSync,U1=mc();function SQ(r,e,t){t=t||{};let i=t.overwrite||t.clobber||!1,{srcStat:n}=U1.checkPathsSync(r,e,"move");return U1.checkParentPathsSync(r,n,e,"move"),xQ(bQ.dirname(e)),DQ(r,e,i)}function DQ(r,e,t){if(t)return j1(e),W1(r,e,t);if(B1.existsSync(e))throw new Error("dest already exists.");return W1(r,e,t)}function W1(r,e,t){try{B1.renameSync(r,e)}catch(i){if(i.code!=="EXDEV")throw i;return EQ(r,e,t)}}function EQ(r,e,t){return wQ(r,e,{overwrite:t,errorOnExist:!0}),j1(r)}$1.exports=SQ});var G1=v((AEe,z1)=>{"use strict";z1.exports={moveSync:H1()}});var X1=v((OEe,V1)=>{"use strict";var CQ=Ce(),_Q=require("path"),PQ=_b().copy,K1=xc().remove,TQ=jr().mkdirp,RQ=fn().pathExists,J1=mc();function IQ(r,e,t,i){typeof t=="function"&&(i=t,t={});let n=t.overwrite||t.clobber||!1;J1.checkPaths(r,e,"move",(o,s)=>{if(o)return i(o);let{srcStat:a}=s;J1.checkParentPaths(r,a,e,"move",l=>{if(l)return i(l);TQ(_Q.dirname(e),u=>u?i(u):kQ(r,e,n,i))})})}function kQ(r,e,t,i){if(t)return K1(e,n=>n?i(n):Y1(r,e,t,i));RQ(e,(n,o)=>n?i(n):o?i(new Error("dest already exists.")):Y1(r,e,t,i))}function Y1(r,e,t,i){CQ.rename(r,e,n=>n?n.code!=="EXDEV"?i(n):FQ(r,e,t,i):i())}function FQ(r,e,t,i){PQ(r,e,{overwrite:t,errorOnExist:!0},o=>o?i(o):K1(r,i))}V1.exports=IQ});var Q1=v((LEe,Z1)=>{"use strict";var AQ=Cr().fromCallback;Z1.exports={move:AQ(X1())}});var iI=v((MEe,eI)=>{"use strict";var OQ=Cr().fromCallback,Ec=Ce(),tI=require("path"),rI=jr(),LQ=fn().pathExists;function MQ(r,e,t,i){typeof t=="function"&&(i=t,t="utf8");let n=tI.dirname(r);LQ(n,(o,s)=>{if(o)return i(o);if(s)return Ec.writeFile(r,e,t,i);rI.mkdirs(n,a=>{if(a)return i(a);Ec.writeFile(r,e,t,i)})})}function NQ(r,...e){let t=tI.dirname(r);if(Ec.existsSync(t))return Ec.writeFileSync(r,...e);rI.mkdirsSync(t),Ec.writeFileSync(r,...e)}eI.exports={outputFile:OQ(MQ),outputFileSync:NQ}});var Rb=v((NEe,Tb)=>{"use strict";Tb.exports=Object.assign({},fb(),Eb(),_b(),r1(),C1(),q1(),jr(),G1(),Q1(),iI(),fn(),xc());var nI=require("fs");Object.getOwnPropertyDescriptor(nI,"promises")&&Object.defineProperty(Tb.exports,"promises",{get(){return nI.promises}})});var sI=v((qEe,oI)=>{oI.exports=()=>new Date});var kb=v(($Ee,di)=>{"use strict";function aI(r,e){for(var t=r.toString();t.length-1,i=Ts(Rs(e,t,"Date")),n=Ts(Rs(e,t,"Month")+1),o=Ts(Rs(e,t,"FullYear")),s=Ts(o.substring(2,4)),a=r.indexOf("yyyy")>-1?o:s,l=Ts(Rs(e,t,"Hours")),u=Ts(Rs(e,t,"Minutes")),c=Ts(Rs(e,t,"Seconds")),f=aI(Rs(e,t,"Milliseconds"),3),p=qQ(e.getTimezoneOffset()),d=r.replace(/dd/g,i).replace(/MM/g,n).replace(/y{1,4}/g,a).replace(/hh/g,l).replace(/mm/g,u).replace(/ss/g,c).replace(/SSS/g,f).replace(/O/g,p);return d}function $Q(r,e,t){var i=[{pattern:/y{1,4}/,regexp:"\\d{1,4}",fn:function(u,c){u.setFullYear(c)}},{pattern:/MM/,regexp:"\\d{1,2}",fn:function(u,c){u.setMonth(c-1)}},{pattern:/dd/,regexp:"\\d{1,2}",fn:function(u,c){u.setDate(c)}},{pattern:/hh/,regexp:"\\d{1,2}",fn:function(u,c){u.setHours(c)}},{pattern:/mm/,regexp:"\\d\\d",fn:function(u,c){u.setMinutes(c)}},{pattern:/ss/,regexp:"\\d\\d",fn:function(u,c){u.setSeconds(c)}},{pattern:/SSS/,regexp:"\\d\\d\\d",fn:function(u,c){u.setMilliseconds(c)}},{pattern:/O/,regexp:"[+-]\\d{3,4}|Z",fn:function(u,c){c==="Z"&&(c=0);var f=Math.abs(c),p=f%100+Math.floor(f/100)*60;u.setMinutes(u.getMinutes()+(c>0?p:-p))}}],n=i.reduce(function(u,c){return c.pattern.test(u.regexp)?(c.index=u.regexp.match(c.pattern).index,u.regexp=u.regexp.replace(c.pattern,"("+c.regexp+")")):c.index=-1,u},{regexp:r,index:[]}),o=i.filter(function(u){return u.index>-1});o.sort(function(u,c){return u.index-c.index});var s=new RegExp(n.regexp),a=s.exec(e);if(a){var l=t||di.exports.now();return o.forEach(function(u,c){u.fn(l,a[c+1])}),l}throw new Error("String '"+e+"' could not be parsed as '"+r+"'")}function BQ(r,e,t){if(!r)throw new Error("pattern must be supplied");return $Q(r,e,t)}function jQ(){return new Date}di.exports=lI;di.exports.asString=lI;di.exports.parse=BQ;di.exports.now=jQ;di.exports.ISO8601_FORMAT="yyyy-MM-ddThh:mm:ss.SSS";di.exports.ISO8601_WITH_TZ_OFFSET_FORMAT="yyyy-MM-ddThh:mm:ss.SSSO";di.exports.DATETIME_FORMAT="dd MM yyyy hh:mm:ss.SSS";di.exports.ABSOLUTETIME_FORMAT="hh:mm:ss.SSS"});var fI=v((BEe,uI)=>{var UQ=vt()("streamroller:fileNameFormatter"),WQ=require("path"),cI=".",HQ=".gz";uI.exports=({file:r,keepFileExt:e,needsIndex:t,alwaysIncludeDate:i,compress:n})=>{let o=WQ.join(r.dir,r.name),s=f=>f+r.ext,a=(f,p,d)=>(t||!d)&&p?f+cI+p:f,l=(f,p,d)=>(p>0||i)&&d?f+cI+d:f,u=(f,p)=>p&&n?f+HQ:f,c=e?[l,a,s,u]:[s,l,a,u];return({date:f,index:p})=>(UQ(`_formatFileName: date=${f}, index=${p}`),c.reduce((d,h)=>h(d,p,f),o))}});var mI=v((jEe,pI)=>{var ks=vt()("streamroller:fileNameParser"),zQ=".",dI=".gz",hI=kb();pI.exports=({file:r,keepFileExt:e,pattern:t})=>{let i=(c,f)=>c.endsWith(dI)?(ks("it is gzipped"),f.isCompressed=!0,c.slice(0,-1*dI.length)):c,n="__NOT_MATCHING__",u=[i,e?c=>c.startsWith(r.name)&&c.endsWith(r.ext)?(ks("it starts and ends with the right things"),c.slice(r.name.length+1,-1*r.ext.length)):n:c=>c.startsWith(r.base)?(ks("it starts with the right things"),c.slice(r.base.length+1)):n,t?(c,f)=>{let p=c.split(zQ),d=p[p.length-1];ks("items: ",p,", indexStr: ",d);let h=c;d!==void 0&&d.match(/^\d+$/)?(h=c.slice(0,-1*(d.length+1)),ks(`dateStr is ${h}`),t&&!h&&(h=d,d="0")):d="0";try{let m=hI.parse(t,h,new Date(0,0));return hI.asString(t,m)!==h?c:(f.index=parseInt(d,10),f.date=h,f.timestamp=m.getTime(),"")}catch(m){return ks(`Problem parsing ${h} as ${t}, error was: `,m),c}}:(c,f)=>c.match(/^\d+$/)?(ks("it has an index"),f.index=parseInt(c,10),""):c];return c=>{let f={filename:c,index:0,isCompressed:!1};return u.reduce((d,h)=>h(d,f),c)?null:f}}});var vI=v((UEe,gI)=>{var Is=vt()("streamroller:moveAndMaybeCompressFile"),wo=Rb(),GQ=require("zlib"),VQ=async(r,e,t)=>{if(r===e){Is("moveAndMaybeCompressFile: source and target are the same, not doing anything");return}if(await wo.pathExists(r))if(Is(`moveAndMaybeCompressFile: moving file from ${r} to ${e} ${t?"with":"without"} compress`),t)await new Promise((i,n)=>{wo.createReadStream(r).pipe(GQ.createGzip()).pipe(wo.createWriteStream(e)).on("finish",()=>{Is(`moveAndMaybeCompressFile: finished compressing ${e}, deleting ${r}`),wo.unlink(r).then(i).catch(()=>{Is(`Deleting ${r} failed, truncating instead`),wo.truncate(r).then(i).catch(n)})})});else{Is(`moveAndMaybeCompressFile: deleting file=${e}, renaming ${r} to ${e}`);try{await wo.move(r,e,{overwrite:!0})}catch(i){Is(`moveAndMaybeCompressFile: error moving ${r} to ${e}`,i),Is("Trying copy+truncate instead"),await wo.copy(r,e,{overwrite:!0}),await wo.truncate(r)}}};gI.exports=VQ});var Qd=v((WEe,yI)=>{var Ur=vt()("streamroller:RollingFileWriteStream"),Cc=Rb(),Yd=require("path"),Xd=sI(),Zd=kb(),{Writable:KQ}=require("stream"),JQ=fI(),YQ=mI(),XQ=vI(),bI=class extends KQ{constructor(e,t){Ur(`constructor: creating RollingFileWriteStream. path=${e}`),super(t),this.options=this._parseOption(t),this.fileObject=Yd.parse(e),this.fileObject.dir===""&&(this.fileObject=Yd.parse(Yd.join(process.cwd(),e))),this.fileFormatter=JQ({file:this.fileObject,alwaysIncludeDate:this.options.alwaysIncludePattern,needsIndex:this.options.maxSize 0`);if(i.numToKeep<=0)throw new Error(`options.numToKeep (${i.numToKeep}) should be > 0`);return Ur(`_parseOption: creating stream with option=${JSON.stringify(i)}`),i}_final(e){this.currentFileStream.end("",this.options.encoding,e)}_write(e,t,i){this._shouldRoll().then(()=>{Ur(`_write: writing chunk. file=${this.currentFileStream.path} state=${JSON.stringify(this.state)} chunk=${e}`),this.currentFileStream.write(e,t,n=>{this.state.currentSize+=e.length,i(n)})})}async _shouldRoll(){(this._dateChanged()||this._tooBig())&&(Ur(`_shouldRoll: rolling because dateChanged? ${this._dateChanged()} or tooBig? ${this._tooBig()}`),await this._roll())}_dateChanged(){return this.state.currentDate&&this.state.currentDate!==Zd(this.options.pattern,Xd())}_tooBig(){return this.state.currentSize>=this.options.maxSize}_roll(){return Ur("_roll: closing the current stream"),new Promise((e,t)=>{this.currentFileStream.end("",this.options.encoding,()=>{this._moveOldFiles().then(e).catch(t)})})}async _moveOldFiles(){let e=await this._getExistingFiles(),t=this.state.currentDate?e.filter(i=>i.date===this.state.currentDate):e;for(let i=t.length;i>=0;i--){Ur(`_moveOldFiles: i = ${i}`);let n=this.fileFormatter({date:this.state.currentDate,index:i}),o=this.fileFormatter({date:this.state.currentDate,index:i+1});await XQ(n,o,this.options.compress&&i===0)}this.state.currentSize=0,this.state.currentDate=this.state.currentDate?Zd(this.options.pattern,Xd()):null,Ur(`_moveOldFiles: finished rolling files. state=${JSON.stringify(this.state)}`),this._renewWriteStream(),await new Promise((i,n)=>{this.currentFileStream.write("","utf8",()=>{this._clean().then(i).catch(n)})})}async _getExistingFiles(){let e=await Cc.readdir(this.fileObject.dir).catch(()=>[]);Ur(`_getExistingFiles: files=${e}`);let t=e.map(n=>this.fileNameParser(n)).filter(n=>n),i=n=>(n.timestamp?n.timestamp:Xd().getTime())-n.index;return t.sort((n,o)=>i(n)-i(o)),t}_renewWriteStream(){Cc.ensureDirSync(this.fileObject.dir);let e=this.fileFormatter({date:this.state.currentDate,index:0}),t={flags:this.options.flags,encoding:this.options.encoding,mode:this.options.mode};this.currentFileStream=Cc.createWriteStream(e,t),this.currentFileStream.on("error",i=>{this.emit("error",i)})}async _clean(){let e=await this._getExistingFiles();if(Ur(`_clean: numToKeep = ${this.options.numToKeep}, existingFiles = ${e.length}`),Ur("_clean: existing files are: ",e),this._tooManyFiles(e.length)){let t=e.slice(0,e.length-this.options.numToKeep-1).map(i=>Yd.format({dir:this.fileObject.dir,base:i.filename}));await ZQ(t)}}_tooManyFiles(e){return this.options.numToKeep>0&&e>this.options.numToKeep}},ZQ=r=>(Ur(`deleteFiles: files to delete: ${r}`),Promise.all(r.map(e=>Cc.unlink(e).catch(t=>{Ur(`deleteFiles: error when unlinking ${e}, ignoring. Error was ${t}`)}))));yI.exports=bI});var DI=v((HEe,wI)=>{var QQ=Qd(),xI=class extends QQ{constructor(e,t,i,n){n||(n={}),t&&(n.maxSize=t),i||(i=1),n.numToKeep=i,super(e,n),this.backups=this.options.numToKeep,this.size=this.options.maxSize}get theStream(){return this.currentFileStream}};wI.exports=xI});var CI=v((zEe,SI)=>{var eee=Qd(),EI=class extends eee{constructor(e,t,i){t&&typeof t=="object"&&(i=t,t=null),i||(i={}),t||(t="yyyy-MM-dd"),i.daysToKeep&&(i.numToKeep=i.daysToKeep),t.startsWith(".")&&(t=t.substring(1)),i.pattern=t,super(e,i),this.mode=this.options.mode}get theStream(){return this.currentFileStream}};SI.exports=EI});var Ib=v((GEe,_I)=>{_I.exports={RollingFileWriteStream:Qd(),RollingFileStream:DI(),DateRollingFileStream:CI()}});var kI=v((VEe,PI)=>{var TI=vt()("log4js:file"),tee=require("path"),ree=Ib(),iee=require("os"),nee=iee.EOL;function RI(r,e,t,i){let n=new ree.RollingFileStream(r,e,t,i);return n.on("error",o=>{console.error("log4js.fileAppender - Writing to file %s, error happened ",r,o)}),n.on("drain",()=>{process.emit("log4js:pause",!1)}),n}function oee(r,e,t,i,n,o){r=tee.normalize(r),i=i===void 0?5:i,i=i===0?1:i,TI("Creating file appender (",r,", ",t,", ",i,", ",n,", ",o,")");let s=RI(r,t,i,n),a=function(l){if(n.removeColor===!0){let u=/\x1b[[0-9;]*m/g;l.data=l.data.map(c=>typeof c=="string"?c.replace(u,""):c)}s.write(e(l,o)+nee,"utf8")||process.emit("log4js:pause",!0)};return a.reopen=function(){s.end(()=>{s=RI(r,t,i,n)})},a.sighupHandler=function(){TI("SIGHUP handler called."),a.reopen()},a.shutdown=function(l){process.removeListener("SIGHUP",a.sighupHandler),s.end("","utf-8",l)},process.on("SIGHUP",a.sighupHandler),a}function see(r,e){let t=e.basicLayout;return r.layout&&(t=e.layout(r.layout.type,r.layout)),oee(r.filename,t,r.maxLogSize,r.backups,r,r.timezoneOffset)}PI.exports.configure=see});var FI=v((KEe,II)=>{var aee=Ib(),lee=require("os"),uee=lee.EOL;function cee(r,e,t,i,n){i.maxSize=i.maxLogSize;let o=new aee.DateRollingFileStream(r,e,i);o.on("drain",()=>{process.emit("log4js:pause",!1)});let s=function(a){o.write(t(a,n)+uee,"utf8")||process.emit("log4js:pause",!0)};return s.shutdown=function(a){o.write("","utf-8",()=>{o.end(a)})},s}function fee(r,e){let t=e.basicLayout;return r.layout&&(t=e.layout(r.layout.type,r.layout)),r.alwaysIncludePattern||(r.alwaysIncludePattern=!1),cee(r.filename,r.pattern,t,r,r.timezoneOffset)}II.exports.configure=fee});var MI=v((JEe,AI)=>{var An=vt()("log4js:fileSync"),Ha=require("path"),On=require("fs"),pee=require("os"),dee=pee.EOL||` -`;function OI(r,e){if(On.existsSync(r))return;let t=On.openSync(r,e.flags,e.mode);On.closeSync(t)}var LI=class{constructor(e,t,i,n){An("In RollingFileStream");function o(){if(!e||!t||t<=0)throw new Error("You must specify a filename and file size")}o(),this.filename=e,this.size=t,this.backups=i||1,this.options=n,this.currentSize=0;function s(a){let l=0;try{l=On.statSync(a).size}catch(u){OI(a,n)}return l}this.currentSize=s(this.filename)}shouldRoll(){return An("should roll with current size %d, and max size %d",this.currentSize,this.size),this.currentSize>=this.size}roll(e){let t=this,i=new RegExp(`^${Ha.basename(e)}`);function n(u){return i.test(u)}function o(u){return parseInt(u.substring(`${Ha.basename(e)}.`.length),10)||0}function s(u,c){return o(u)>o(c)?1:o(u) ${e}.${c+1}`),On.renameSync(Ha.join(Ha.dirname(e),u),`${e}.${c+1}`)}}function l(){An("Renaming the old files"),On.readdirSync(Ha.dirname(e)).filter(n).sort(s).reverse().forEach(a)}An("Rolling, rolling, rolling"),l()}write(e,t){let i=this;function n(){An("writing the chunk to the file"),i.currentSize+=e.length,On.appendFileSync(i.filename,e)}An("in write"),this.shouldRoll()&&(this.currentSize=0,this.roll(this.filename)),n()}};function hee(r,e,t,i,n,o){An("fileSync appender created"),r=Ha.normalize(r),i=i===void 0?5:i,i=i===0?1:i;function s(l,u,c){let f;return u?f=new LI(l,u,c,o):f=(p=>(OI(p,o),{write(d){On.appendFileSync(p,d)}}))(l),f}let a=s(r,t,i);return l=>{a.write(e(l,n)+dee)}}function mee(r,e){let t=e.basicLayout;r.layout&&(t=e.layout(r.layout.type,r.layout));let i={flags:r.flags||"a",encoding:r.encoding||"utf8",mode:r.mode||420};return hee(r.filename,t,r.maxLogSize,r.backups,r.timezoneOffset,i)}AI.exports.configure=mee});var Ab=v((YEe,NI)=>{var gee=require("path"),Fs=vt()("log4js:appenders"),hi=xs(),qI=qd(),vee=Es(),yee=ib(),bee=FR(),pn=new Map;pn.set("console",OR());pn.set("stdout",MR());pn.set("stderr",qR());pn.set("logLevelFilter",BR());pn.set("categoryFilter",WR());pn.set("noLogFilter",GR());pn.set("file",kI());pn.set("dateFile",FI());pn.set("fileSync",MI());var _c=new Map,Fb=(r,e)=>{Fs("Loading module from ",r);try{return require(r)}catch(t){hi.throwExceptionIf(e,t.code!=="MODULE_NOT_FOUND",`appender "${r}" could not be loaded (error was: ${t})`);return}},wee=(r,e)=>pn.get(r)||Fb(`./${r}`,e)||Fb(r,e)||""||Fb(gee.join(process.cwd(),r),e),eh=new Set,$I=(r,e)=>{if(_c.has(r))return _c.get(r);if(!e.appenders[r])return!1;if(eh.has(r))throw new Error(`Dependency loop detected for appender ${r}.`);eh.add(r),Fs(`Creating appender ${r}`);let t=xee(r,e);return eh.delete(r),_c.set(r,t),t},xee=(r,e)=>{let t=e.appenders[r],i=t.type.configure?t.type:wee(t.type,e);return hi.throwExceptionIf(e,hi.not(i),`appender "${r}" is not valid (type "${t.type}" could not be found)`),i.appender&&Fs(`DEPRECATION: Appender ${t.type} exports an appender function.`),i.shutdown&&Fs(`DEPRECATION: Appender ${t.type} exports a shutdown function.`),Fs(`${r}: clustering.isMaster ? ${qI.isMaster()}`),Fs(`${r}: appenderModule is ${require("util").inspect(i)}`),qI.onlyOnMaster(()=>(Fs(`calling appenderModule.configure for ${r} / ${t.type}`),i.configure(bee.modifyConfig(t),yee,n=>$I(n,e),vee)),()=>{})},BI=r=>{_c.clear(),eh.clear();let e=[];Object.values(r.categories).forEach(t=>{e.push(...t.appenders)}),Object.keys(r.appenders).forEach(t=>{(e.includes(t)||r.appenders[t].type==="tcp-server")&&$I(t,r)})};BI({appenders:{out:{type:"stdout"}},categories:{default:{appenders:["out"],level:"trace"}}});hi.addListener(r=>{hi.throwExceptionIf(r,hi.not(hi.anObject(r.appenders)),'must have a property "appenders" of type object.');let e=Object.keys(r.appenders);hi.throwExceptionIf(r,hi.not(e.length),"must define at least one appender."),e.forEach(t=>{hi.throwExceptionIf(r,hi.not(r.appenders[t].type),`appender "${t}" is not valid (must be an object with property "type")`)})});hi.addListener(BI);NI.exports=_c});var Lb=v((XEe,jI)=>{var As=vt()("log4js:categories"),lt=xs(),Ob=Es(),UI=Ab(),za=new Map;function WI(r,e,t){if(e.inherit===!1)return;let i=t.lastIndexOf(".");if(i<0)return;let n=t.substring(0,i),o=r.categories[n];o||(o={inherit:!0,appenders:[]}),WI(r,o,n),!r.categories[n]&&o.appenders&&o.appenders.length&&o.level&&(r.categories[n]=o),e.appenders=e.appenders||[],e.level=e.level||o.level,o.appenders.forEach(s=>{e.appenders.includes(s)||e.appenders.push(s)}),e.parent=o}function Dee(r){if(!r.categories)return;Object.keys(r.categories).forEach(t=>{let i=r.categories[t];WI(r,i,t)})}lt.addPreProcessingListener(r=>Dee(r));lt.addListener(r=>{lt.throwExceptionIf(r,lt.not(lt.anObject(r.categories)),'must have a property "categories" of type object.');let e=Object.keys(r.categories);lt.throwExceptionIf(r,lt.not(e.length),"must define at least one category."),e.forEach(t=>{let i=r.categories[t];lt.throwExceptionIf(r,[lt.not(i.appenders),lt.not(i.level)],`category "${t}" is not valid (must be an object with properties "appenders" and "level")`),lt.throwExceptionIf(r,lt.not(Array.isArray(i.appenders)),`category "${t}" is not valid (appenders must be an array of appender names)`),lt.throwExceptionIf(r,lt.not(i.appenders.length),`category "${t}" is not valid (appenders must contain at least one appender name)`),Object.prototype.hasOwnProperty.call(i,"enableCallStack")&<.throwExceptionIf(r,typeof i.enableCallStack!="boolean",`category "${t}" is not valid (enableCallStack must be boolean type)`),i.appenders.forEach(n=>{lt.throwExceptionIf(r,lt.not(UI.get(n)),`category "${t}" is not valid (appender "${n}" is not defined)`)}),lt.throwExceptionIf(r,lt.not(Ob.getLevel(i.level)),`category "${t}" is not valid (level "${i.level}" not recognised; valid levels are ${Ob.levels.join(", ")})`)}),lt.throwExceptionIf(r,lt.not(r.categories.default),'must define a "default" category.')});var HI=r=>{za.clear(),Object.keys(r.categories).forEach(t=>{let i=r.categories[t],n=[];i.appenders.forEach(o=>{n.push(UI.get(o)),As(`Creating category ${t}`),za.set(t,{appenders:n,level:Ob.getLevel(i.level),enableCallStack:i.enableCallStack||!1})})})};HI({categories:{default:{appenders:["out"],level:"OFF"}}});lt.addListener(HI);var Os=r=>(As(`configForCategory: searching for config for ${r}`),za.has(r)?(As(`configForCategory: ${r} exists in config, returning it`),za.get(r)):r.indexOf(".")>0?(As(`configForCategory: ${r} has hierarchy, searching for parents`),Os(r.substring(0,r.lastIndexOf(".")))):(As("configForCategory: returning config for default category"),Os("default"))),See=r=>Os(r).appenders,Eee=r=>Os(r).level,Cee=(r,e)=>{let t=za.get(r);if(As(`setLevelForCategory: found ${t} for ${r}`),!t){let i=Os(r);As(`setLevelForCategory: no config found for category, found ${i} for parents of ${r}`),t={appenders:i.appenders}}t.level=e,za.set(r,t)},_ee=r=>Os(r).enableCallStack===!0,Pee=(r,e)=>{Os(r).enableCallStack=e};jI.exports={appendersForCategory:See,getLevelForCategory:Eee,setLevelForCategory:Cee,getEnableCallStackForCategory:_ee,setEnableCallStackForCategory:Pee}});var KI=v((ZEe,zI)=>{var GI=vt()("log4js:logger"),Tee=ob(),xo=Es(),Ree=qd(),th=Lb(),kee=xs(),Iee=/at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/;function Fee(r,e=4){let t=r.stack.split(` -`).slice(e),i=Iee.exec(t[0]);return i&&i.length===6?{functionName:i[1],fileName:i[2],lineNumber:parseInt(i[3],10),columnNumber:parseInt(i[4],10),callStack:t.join(` -`)}:null}var rh=class{constructor(e){if(!e)throw new Error("No category provided.");this.category=e,this.context={},this.parseCallStack=Fee,GI(`Logger created (${this.category}, ${this.level})`)}get level(){return xo.getLevel(th.getLevelForCategory(this.category),xo.TRACE)}set level(e){th.setLevelForCategory(this.category,xo.getLevel(e,this.level))}get useCallStack(){return th.getEnableCallStackForCategory(this.category)}set useCallStack(e){th.setEnableCallStackForCategory(this.category,e===!0)}log(e,...t){let i=xo.getLevel(e,xo.INFO);this.isLevelEnabled(i)&&this._log(i,t)}isLevelEnabled(e){return this.level.isLessThanOrEqualTo(e)}_log(e,t){GI(`sending log data (${e}) to appenders`);let i=new Tee(this.category,e,t,this.context,this.useCallStack&&this.parseCallStack(new Error));Ree.send(i)}addContext(e,t){this.context[e]=t}removeContext(e){delete this.context[e]}clearContext(){this.context={}}setParseCallStackFunction(e){this.parseCallStack=e}};function VI(r){let e=xo.getLevel(r),i=e.toString().toLowerCase().replace(/_([a-z])/g,o=>o[1].toUpperCase()),n=i[0].toUpperCase()+i.slice(1);rh.prototype[`is${n}Enabled`]=function(){return this.isLevelEnabled(e)},rh.prototype[i]=function(...o){this.log(e,...o)}}xo.levels.forEach(VI);kee.addListener(()=>{xo.levels.forEach(VI)});zI.exports=rh});var XI=v((QEe,JI)=>{var Ga=Es(),Aee=':remote-addr - - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"';function Oee(r){return r.originalUrl||r.url}function Lee(r,e,t){let i=o=>{let s=o.concat();for(let a=0;ai.source?i.source:i);e=new RegExp(t.join("|"))}return e}function Nee(r,e,t){let i=e;if(t){let n=t.find(o=>{let s=!1;return o.from&&o.to?s=r>=o.from&&r<=o.to:s=o.codes.indexOf(r)!==-1,s});n&&(i=Ga.getLevel(n.level,i))}return i}JI.exports=function(e,t){typeof t=="string"||typeof t=="function"?t={format:t}:t=t||{};let i=e,n=Ga.getLevel(t.level,Ga.INFO),o=t.format||Aee,s=Mee(t.nolog);return(a,l,u)=>{if(a._logging||s&&s.test(a.originalUrl))return u();if(i.isLevelEnabled(n)||t.level==="auto"){let c=new Date,{writeHead:f}=l;a._logging=!0,l.writeHead=(p,d)=>{l.writeHead=f,l.writeHead(p,d),l.__statusCode=p,l.__headers=d||{}},l.on("finish",()=>{l.responseTime=new Date-c,l.statusCode&&t.level==="auto"&&(n=Ga.INFO,l.statusCode>=300&&(n=Ga.WARN),l.statusCode>=400&&(n=Ga.ERROR)),n=Nee(l.statusCode,n,t.statusRules);let p=Lee(a,l,t.tokens||[]);if(t.context&&i.addContext("res",l),typeof o=="function"){let d=o(a,l,h=>YI(h,p));d&&i.log(n,d)}else i.log(n,YI(o,p));t.context&&i.removeContext("res")})}return u()}}});var Mb=v((eCe,ZI)=>{var Do=vt()("log4js:main"),qee=require("fs"),$ee=tR()({proto:!0}),Bee=xs(),jee=ib(),Uee=Es(),Wee=Ab(),Hee=Lb(),zee=KI(),Gee=qd(),Vee=XI(),ih=!1;function Kee(r){if(!ih)return;Do("Received log event ",r),Hee.appendersForCategory(r.categoryName).forEach(t=>{t(r)})}function Jee(r){Do(`Loading configuration from ${r}`);try{return JSON.parse(qee.readFileSync(r,"utf8"))}catch(e){throw new Error(`Problem reading config from file "${r}". Error was ${e.message}`,e)}}function eF(r){let e=r;return typeof e=="string"&&(e=Jee(r)),Do(`Configuration is ${e}`),Bee.configure($ee(e)),Gee.onMessage(Kee),ih=!0,QI}function Yee(r){Do("Shutdown called. Disabling all log writing."),ih=!1;let e=Array.from(Wee.values()),t=e.reduceRight((s,a)=>a.shutdown?s+1:s,0),i=0,n;Do(`Found ${t} appenders with shutdown functions.`);function o(s){n=n||s,i+=1,Do(`Appender shutdowns complete: ${i} / ${t}`),i>=t&&(Do("All shutdown functions completed."),r&&r(n))}return t===0?(Do("No appenders with shutdown functions found."),r!==void 0&&r()):(e.filter(s=>s.shutdown).forEach(s=>s.shutdown(o)),null)}function Xee(r){return ih||eF(process.env.LOG4JS_CONFIG||{appenders:{out:{type:"stdout"}},categories:{default:{appenders:["out"],level:"OFF"}}}),new zee(r||"default")}var QI={getLogger:Xee,configure:eF,shutdown:Yee,connectLogger:Vee,levels:Uee,addLayout:jee.addLayout};ZI.exports=QI});var Wr=v(Nb=>{"use strict";Nb.fromCallback=function(r){return Object.defineProperty(function(...e){if(typeof e[e.length-1]=="function")r.apply(this,e);else return new Promise((t,i)=>{r.apply(this,e.concat([(n,o)=>n?i(n):t(o)]))})},"name",{value:r.name})};Nb.fromPromise=function(r){return Object.defineProperty(function(...e){let t=e[e.length-1];if(typeof t!="function")return r.apply(this,e);r.apply(this,e.slice(0,-1)).then(i=>t(null,i),t)},"name",{value:r.name})}});var Pc=v(So=>{"use strict";var tF=Wr().fromCallback,vr=Ce(),Zee=["access","appendFile","chmod","chown","close","copyFile","fchmod","fchown","fdatasync","fstat","fsync","ftruncate","futimes","lchmod","lchown","link","lstat","mkdir","mkdtemp","open","opendir","readdir","readFile","readlink","realpath","rename","rmdir","stat","symlink","truncate","unlink","utimes","writeFile"].filter(r=>typeof vr[r]=="function");Object.keys(vr).forEach(r=>{r!=="promises"&&(So[r]=vr[r])});Zee.forEach(r=>{So[r]=tF(vr[r])});So.exists=function(r,e){return typeof e=="function"?vr.exists(r,e):new Promise(t=>vr.exists(r,t))};So.read=function(r,e,t,i,n,o){return typeof o=="function"?vr.read(r,e,t,i,n,o):new Promise((s,a)=>{vr.read(r,e,t,i,n,(l,u,c)=>{if(l)return a(l);s({bytesRead:u,buffer:c})})})};So.write=function(r,e,...t){return typeof t[t.length-1]=="function"?vr.write(r,e,...t):new Promise((i,n)=>{vr.write(r,e,...t,(o,s,a)=>{if(o)return n(o);i({bytesWritten:s,buffer:a})})})};typeof vr.writev=="function"&&(So.writev=function(r,e,...t){return typeof t[t.length-1]=="function"?vr.writev(r,e,...t):new Promise((i,n)=>{vr.writev(r,e,...t,(o,s,a)=>{if(o)return n(o);i({bytesWritten:s,buffers:a})})})});typeof vr.realpath.native=="function"&&(So.realpath.native=tF(vr.realpath.native))});var qb=v((iCe,rF)=>{rF.exports=r=>{let e=process.versions.node.split(".").map(t=>parseInt(t,10));return r=r.split(".").map(t=>parseInt(t,10)),e[0]>r[0]||e[0]===r[0]&&(e[1]>r[1]||e[1]===r[1]&&e[2]>=r[2])}});var aF=v((nCe,$b)=>{"use strict";var Va=Pc(),Ln=require("path"),Qee=qb(),iF=Qee("10.12.0"),nF=r=>{if(process.platform==="win32"&&/[<>:"|?*]/.test(r.replace(Ln.parse(r).root,""))){let t=new Error(`Path contains invalid characters: ${r}`);throw t.code="EINVAL",t}},oF=r=>{let e={mode:511};return typeof r=="number"&&(r={mode:r}),{...e,...r}},sF=r=>{let e=new Error(`operation not permitted, mkdir '${r}'`);return e.code="EPERM",e.errno=-4048,e.path=r,e.syscall="mkdir",e};$b.exports.makeDir=async(r,e)=>{if(nF(r),e=oF(e),iF){let i=Ln.resolve(r);return Va.mkdir(i,{mode:e.mode,recursive:!0})}let t=async i=>{try{await Va.mkdir(i,e.mode)}catch(n){if(n.code==="EPERM")throw n;if(n.code==="ENOENT"){if(Ln.dirname(i)===i)throw sF(i);if(n.message.includes("null bytes"))throw n;return await t(Ln.dirname(i)),t(i)}try{if(!(await Va.stat(i)).isDirectory())throw new Error("The path is not a directory")}catch{throw n}}};return t(Ln.resolve(r))};$b.exports.makeDirSync=(r,e)=>{if(nF(r),e=oF(e),iF){let i=Ln.resolve(r);return Va.mkdirSync(i,{mode:e.mode,recursive:!0})}let t=i=>{try{Va.mkdirSync(i,e.mode)}catch(n){if(n.code==="EPERM")throw n;if(n.code==="ENOENT"){if(Ln.dirname(i)===i)throw sF(i);if(n.message.includes("null bytes"))throw n;return t(Ln.dirname(i)),t(i)}try{if(!Va.statSync(i).isDirectory())throw new Error("The path is not a directory")}catch{throw n}}};return t(Ln.resolve(r))}});var qi=v((oCe,lF)=>{"use strict";var ete=Wr().fromPromise,{makeDir:tte,makeDirSync:Bb}=aF(),jb=ete(tte);lF.exports={mkdirs:jb,mkdirsSync:Bb,mkdirp:jb,mkdirpSync:Bb,ensureDir:jb,ensureDirSync:Bb}});var Ub=v((sCe,uF)=>{"use strict";var Ka=Ce();function rte(r,e,t,i){Ka.open(r,"r+",(n,o)=>{if(n)return i(n);Ka.futimes(o,e,t,s=>{Ka.close(o,a=>{i&&i(s||a)})})})}function ite(r,e,t){let i=Ka.openSync(r,"r+");return Ka.futimesSync(i,e,t),Ka.closeSync(i)}uF.exports={utimesMillis:rte,utimesMillisSync:ite}});var Tc=v((aCe,cF)=>{"use strict";var Ja=Pc(),Pr=require("path"),nte=require("util"),ote=qb(),nh=ote("10.5.0"),fF=r=>nh?Ja.stat(r,{bigint:!0}):Ja.stat(r),Wb=r=>nh?Ja.statSync(r,{bigint:!0}):Ja.statSync(r);function ste(r,e){return Promise.all([fF(r),fF(e).catch(t=>{if(t.code==="ENOENT")return null;throw t})]).then(([t,i])=>({srcStat:t,destStat:i}))}function ate(r,e){let t,i=Wb(r);try{t=Wb(e)}catch(n){if(n.code==="ENOENT")return{srcStat:i,destStat:null};throw n}return{srcStat:i,destStat:t}}function lte(r,e,t,i){nte.callbackify(ste)(r,e,(n,o)=>{if(n)return i(n);let{srcStat:s,destStat:a}=o;return a&&oh(s,a)?i(new Error("Source and destination must not be the same.")):s.isDirectory()&&Hb(r,e)?i(new Error(sh(r,e,t))):i(null,{srcStat:s,destStat:a})})}function ute(r,e,t){let{srcStat:i,destStat:n}=ate(r,e);if(n&&oh(i,n))throw new Error("Source and destination must not be the same.");if(i.isDirectory()&&Hb(r,e))throw new Error(sh(r,e,t));return{srcStat:i,destStat:n}}function pF(r,e,t,i,n){let o=Pr.resolve(Pr.dirname(r)),s=Pr.resolve(Pr.dirname(t));if(s===o||s===Pr.parse(s).root)return n();let a=(l,u)=>l?l.code==="ENOENT"?n():n(l):oh(e,u)?n(new Error(sh(r,t,i))):pF(r,e,s,i,n);nh?Ja.stat(s,{bigint:!0},a):Ja.stat(s,a)}function dF(r,e,t,i){let n=Pr.resolve(Pr.dirname(r)),o=Pr.resolve(Pr.dirname(t));if(o===n||o===Pr.parse(o).root)return;let s;try{s=Wb(o)}catch(a){if(a.code==="ENOENT")return;throw a}if(oh(e,s))throw new Error(sh(r,t,i));return dF(r,e,o,i)}function oh(r,e){return!!(e.ino&&e.dev&&e.ino===r.ino&&e.dev===r.dev&&(nh||e.inon),i=Pr.resolve(e).split(Pr.sep).filter(n=>n);return t.reduce((n,o,s)=>n&&i[s]===o,!0)}function sh(r,e,t){return`Cannot ${t} '${r}' to a subdirectory of itself, '${e}'.`}cF.exports={checkPaths:lte,checkPathsSync:ute,checkParentPaths:pF,checkParentPathsSync:dF,isSrcSubdir:Hb}});var yF=v((lCe,hF)=>{"use strict";var tr=Ce(),Rc=require("path"),cte=qi().mkdirsSync,fte=Ub().utimesMillisSync,kc=Tc();function dte(r,e,t){typeof t=="function"&&(t={filter:t}),t=t||{},t.clobber="clobber"in t?!!t.clobber:!0,t.overwrite="overwrite"in t?!!t.overwrite:t.clobber,t.preserveTimestamps&&process.arch==="ia32"&&console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended; - - see https://github.com/jprichardson/node-fs-extra/issues/269`);let{srcStat:i,destStat:n}=kc.checkPathsSync(r,e,"copy");return kc.checkParentPathsSync(r,i,e,"copy"),pte(n,r,e,t)}function pte(r,e,t,i){if(i.filter&&!i.filter(e,t))return;let n=Rc.dirname(t);return tr.existsSync(n)||cte(n),mF(r,e,t,i)}function mF(r,e,t,i){if(!(i.filter&&!i.filter(e,t)))return hte(r,e,t,i)}function hte(r,e,t,i){let o=(i.dereference?tr.statSync:tr.lstatSync)(e);if(o.isDirectory())return gte(o,r,e,t,i);if(o.isFile()||o.isCharacterDevice()||o.isBlockDevice())return mte(o,r,e,t,i);if(o.isSymbolicLink())return vte(r,e,t,i)}function mte(r,e,t,i,n){return e?yte(r,t,i,n):gF(r,t,i,n)}function yte(r,e,t,i){if(i.overwrite)return tr.unlinkSync(t),gF(r,e,t,i);if(i.errorOnExist)throw new Error(`'${t}' already exists`)}function gF(r,e,t,i){return tr.copyFileSync(e,t),i.preserveTimestamps&&bte(r.mode,e,t),zb(t,r.mode)}function bte(r,e,t){return wte(r)&&xte(t,r),Dte(e,t)}function wte(r){return(r&128)==0}function xte(r,e){return zb(r,e|128)}function zb(r,e){return tr.chmodSync(r,e)}function Dte(r,e){let t=tr.statSync(r);return fte(e,t.atime,t.mtime)}function gte(r,e,t,i,n){if(!e)return Ste(r.mode,t,i,n);if(e&&!e.isDirectory())throw new Error(`Cannot overwrite non-directory '${i}' with directory '${t}'.`);return vF(t,i,n)}function Ste(r,e,t,i){return tr.mkdirSync(t),vF(e,t,i),zb(t,r)}function vF(r,e,t){tr.readdirSync(r).forEach(i=>Ete(i,r,e,t))}function Ete(r,e,t,i){let n=Rc.join(e,r),o=Rc.join(t,r),{destStat:s}=kc.checkPathsSync(n,o,"copy");return mF(s,n,o,i)}function vte(r,e,t,i){let n=tr.readlinkSync(e);if(i.dereference&&(n=Rc.resolve(process.cwd(),n)),r){let o;try{o=tr.readlinkSync(t)}catch(s){if(s.code==="EINVAL"||s.code==="UNKNOWN")return tr.symlinkSync(n,t);throw s}if(i.dereference&&(o=Rc.resolve(process.cwd(),o)),kc.isSrcSubdir(n,o))throw new Error(`Cannot copy '${n}' to a subdirectory of itself, '${o}'.`);if(tr.statSync(t).isDirectory()&&kc.isSrcSubdir(o,n))throw new Error(`Cannot overwrite '${o}' with '${n}'.`);return Cte(n,t)}else return tr.symlinkSync(n,t)}function Cte(r,e){return tr.unlinkSync(e),tr.symlinkSync(r,e)}hF.exports=dte});var Gb=v((uCe,bF)=>{"use strict";bF.exports={copySync:yF()}});var Eo=v((cCe,wF)=>{"use strict";var _te=Wr().fromPromise,xF=Pc();function Pte(r){return xF.access(r).then(()=>!0).catch(()=>!1)}wF.exports={pathExists:_te(Pte),pathExistsSync:xF.existsSync}});var kF=v((fCe,DF)=>{"use strict";var Tr=Ce(),Ic=require("path"),Tte=qi().mkdirs,Rte=Eo().pathExists,kte=Ub().utimesMillis,Fc=Tc();function Ite(r,e,t,i){typeof t=="function"&&!i?(i=t,t={}):typeof t=="function"&&(t={filter:t}),i=i||function(){},t=t||{},t.clobber="clobber"in t?!!t.clobber:!0,t.overwrite="overwrite"in t?!!t.overwrite:t.clobber,t.preserveTimestamps&&process.arch==="ia32"&&console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended; - - see https://github.com/jprichardson/node-fs-extra/issues/269`),Fc.checkPaths(r,e,"copy",(n,o)=>{if(n)return i(n);let{srcStat:s,destStat:a}=o;Fc.checkParentPaths(r,s,e,"copy",l=>l?i(l):t.filter?EF(SF,a,r,e,t,i):SF(a,r,e,t,i))})}function SF(r,e,t,i,n){let o=Ic.dirname(t);Rte(o,(s,a)=>{if(s)return n(s);if(a)return Vb(r,e,t,i,n);Tte(o,l=>l?n(l):Vb(r,e,t,i,n))})}function EF(r,e,t,i,n,o){Promise.resolve(n.filter(t,i)).then(s=>s?r(e,t,i,n,o):o(),s=>o(s))}function Vb(r,e,t,i,n){return i.filter?EF(CF,r,e,t,i,n):CF(r,e,t,i,n)}function CF(r,e,t,i,n){(i.dereference?Tr.stat:Tr.lstat)(e,(s,a)=>{if(s)return n(s);if(a.isDirectory())return Ate(a,r,e,t,i,n);if(a.isFile()||a.isCharacterDevice()||a.isBlockDevice())return Fte(a,r,e,t,i,n);if(a.isSymbolicLink())return Ote(r,e,t,i,n)})}function Fte(r,e,t,i,n,o){return e?Lte(r,t,i,n,o):_F(r,t,i,n,o)}function Lte(r,e,t,i,n){if(i.overwrite)Tr.unlink(t,o=>o?n(o):_F(r,e,t,i,n));else return i.errorOnExist?n(new Error(`'${t}' already exists`)):n()}function _F(r,e,t,i,n){Tr.copyFile(e,t,o=>o?n(o):i.preserveTimestamps?Mte(r.mode,e,t,n):ah(t,r.mode,n))}function Mte(r,e,t,i){return Nte(r)?qte(t,r,n=>n?i(n):PF(r,e,t,i)):PF(r,e,t,i)}function Nte(r){return(r&128)==0}function qte(r,e,t){return ah(r,e|128,t)}function PF(r,e,t,i){$te(e,t,n=>n?i(n):ah(t,r,i))}function ah(r,e,t){return Tr.chmod(r,e,t)}function $te(r,e,t){Tr.stat(r,(i,n)=>i?t(i):kte(e,n.atime,n.mtime,t))}function Ate(r,e,t,i,n,o){return e?e&&!e.isDirectory()?o(new Error(`Cannot overwrite non-directory '${i}' with directory '${t}'.`)):TF(t,i,n,o):Bte(r.mode,t,i,n,o)}function Bte(r,e,t,i,n){Tr.mkdir(t,o=>{if(o)return n(o);TF(e,t,i,s=>s?n(s):ah(t,r,n))})}function TF(r,e,t,i){Tr.readdir(r,(n,o)=>n?i(n):RF(o,r,e,t,i))}function RF(r,e,t,i,n){let o=r.pop();return o?jte(r,o,e,t,i,n):n()}function jte(r,e,t,i,n,o){let s=Ic.join(t,e),a=Ic.join(i,e);Fc.checkPaths(s,a,"copy",(l,u)=>{if(l)return o(l);let{destStat:c}=u;Vb(c,s,a,n,f=>f?o(f):RF(r,t,i,n,o))})}function Ote(r,e,t,i,n){Tr.readlink(e,(o,s)=>{if(o)return n(o);if(i.dereference&&(s=Ic.resolve(process.cwd(),s)),r)Tr.readlink(t,(a,l)=>a?a.code==="EINVAL"||a.code==="UNKNOWN"?Tr.symlink(s,t,n):n(a):(i.dereference&&(l=Ic.resolve(process.cwd(),l)),Fc.isSrcSubdir(s,l)?n(new Error(`Cannot copy '${s}' to a subdirectory of itself, '${l}'.`)):r.isDirectory()&&Fc.isSrcSubdir(l,s)?n(new Error(`Cannot overwrite '${l}' with '${s}'.`)):Ute(s,t,n)));else return Tr.symlink(s,t,n)})}function Ute(r,e,t){Tr.unlink(e,i=>i?t(i):Tr.symlink(r,e,t))}DF.exports=Ite});var Kb=v((pCe,IF)=>{"use strict";var Wte=Wr().fromCallback;IF.exports={copy:Wte(kF())}});var BF=v((dCe,FF)=>{"use strict";var AF=Ce(),OF=require("path"),Ke=require("assert"),Ac=process.platform==="win32";function LF(r){["unlink","chmod","stat","lstat","rmdir","readdir"].forEach(t=>{r[t]=r[t]||AF[t],t=t+"Sync",r[t]=r[t]||AF[t]}),r.maxBusyTries=r.maxBusyTries||3}function Jb(r,e,t){let i=0;typeof e=="function"&&(t=e,e={}),Ke(r,"rimraf: missing path"),Ke.strictEqual(typeof r,"string","rimraf: path should be a string"),Ke.strictEqual(typeof t,"function","rimraf: callback function required"),Ke(e,"rimraf: invalid options argument provided"),Ke.strictEqual(typeof e,"object","rimraf: options should be object"),LF(e),MF(r,e,function n(o){if(o){if((o.code==="EBUSY"||o.code==="ENOTEMPTY"||o.code==="EPERM")&&iMF(r,e,n),s)}o.code==="ENOENT"&&(o=null)}t(o)})}function MF(r,e,t){Ke(r),Ke(e),Ke(typeof t=="function"),e.lstat(r,(i,n)=>{if(i&&i.code==="ENOENT")return t(null);if(i&&i.code==="EPERM"&&Ac)return NF(r,e,i,t);if(n&&n.isDirectory())return lh(r,e,i,t);e.unlink(r,o=>{if(o){if(o.code==="ENOENT")return t(null);if(o.code==="EPERM")return Ac?NF(r,e,o,t):lh(r,e,o,t);if(o.code==="EISDIR")return lh(r,e,o,t)}return t(o)})})}function NF(r,e,t,i){Ke(r),Ke(e),Ke(typeof i=="function"),e.chmod(r,438,n=>{n?i(n.code==="ENOENT"?null:t):e.stat(r,(o,s)=>{o?i(o.code==="ENOENT"?null:t):s.isDirectory()?lh(r,e,t,i):e.unlink(r,i)})})}function qF(r,e,t){let i;Ke(r),Ke(e);try{e.chmodSync(r,438)}catch(n){if(n.code==="ENOENT")return;throw t}try{i=e.statSync(r)}catch(n){if(n.code==="ENOENT")return;throw t}i.isDirectory()?uh(r,e,t):e.unlinkSync(r)}function lh(r,e,t,i){Ke(r),Ke(e),Ke(typeof i=="function"),e.rmdir(r,n=>{n&&(n.code==="ENOTEMPTY"||n.code==="EEXIST"||n.code==="EPERM")?Hte(r,e,i):n&&n.code==="ENOTDIR"?i(t):i(n)})}function Hte(r,e,t){Ke(r),Ke(e),Ke(typeof t=="function"),e.readdir(r,(i,n)=>{if(i)return t(i);let o=n.length,s;if(o===0)return e.rmdir(r,t);n.forEach(a=>{Jb(OF.join(r,a),e,l=>{if(!s){if(l)return t(s=l);--o==0&&e.rmdir(r,t)}})})})}function $F(r,e){let t;e=e||{},LF(e),Ke(r,"rimraf: missing path"),Ke.strictEqual(typeof r,"string","rimraf: path should be a string"),Ke(e,"rimraf: missing options"),Ke.strictEqual(typeof e,"object","rimraf: options should be object");try{t=e.lstatSync(r)}catch(i){if(i.code==="ENOENT")return;i.code==="EPERM"&&Ac&&qF(r,e,i)}try{t&&t.isDirectory()?uh(r,e,null):e.unlinkSync(r)}catch(i){if(i.code==="ENOENT")return;if(i.code==="EPERM")return Ac?qF(r,e,i):uh(r,e,i);if(i.code!=="EISDIR")throw i;uh(r,e,i)}}function uh(r,e,t){Ke(r),Ke(e);try{e.rmdirSync(r)}catch(i){if(i.code==="ENOTDIR")throw t;if(i.code==="ENOTEMPTY"||i.code==="EEXIST"||i.code==="EPERM")zte(r,e);else if(i.code!=="ENOENT")throw i}}function zte(r,e){if(Ke(r),Ke(e),e.readdirSync(r).forEach(t=>$F(OF.join(r,t),e)),Ac){let t=Date.now();do try{return e.rmdirSync(r,e)}catch{}while(Date.now()-t<500)}else return e.rmdirSync(r,e)}FF.exports=Jb;Jb.sync=$F});var Oc=v((hCe,jF)=>{"use strict";var Gte=Wr().fromCallback,UF=BF();jF.exports={remove:Gte(UF),removeSync:UF.sync}});var YF=v((mCe,WF)=>{"use strict";var Vte=Wr().fromCallback,HF=Ce(),zF=require("path"),GF=qi(),VF=Oc(),KF=Vte(function(e,t){t=t||function(){},HF.readdir(e,(i,n)=>{if(i)return GF.mkdirs(e,t);n=n.map(s=>zF.join(e,s)),o();function o(){let s=n.pop();if(!s)return t();VF.remove(s,a=>{if(a)return t(a);o()})}})});function JF(r){let e;try{e=HF.readdirSync(r)}catch{return GF.mkdirsSync(r)}e.forEach(t=>{t=zF.join(r,t),VF.removeSync(t)})}WF.exports={emptyDirSync:JF,emptydirSync:JF,emptyDir:KF,emptydir:KF}});var eA=v((gCe,XF)=>{"use strict";var Kte=Wr().fromCallback,ZF=require("path"),Co=Ce(),QF=qi();function Jte(r,e){function t(){Co.writeFile(r,"",i=>{if(i)return e(i);e()})}Co.stat(r,(i,n)=>{if(!i&&n.isFile())return e();let o=ZF.dirname(r);Co.stat(o,(s,a)=>{if(s)return s.code==="ENOENT"?QF.mkdirs(o,l=>{if(l)return e(l);t()}):e(s);a.isDirectory()?t():Co.readdir(o,l=>{if(l)return e(l)})})})}function Yte(r){let e;try{e=Co.statSync(r)}catch{}if(e&&e.isFile())return;let t=ZF.dirname(r);try{Co.statSync(t).isDirectory()||Co.readdirSync(t)}catch(i){if(i&&i.code==="ENOENT")QF.mkdirsSync(t);else throw i}Co.writeFileSync(r,"")}XF.exports={createFile:Kte(Jte),createFileSync:Yte}});var oA=v((vCe,tA)=>{"use strict";var Xte=Wr().fromCallback,rA=require("path"),Ls=Ce(),iA=qi(),nA=Eo().pathExists;function Zte(r,e,t){function i(n,o){Ls.link(n,o,s=>{if(s)return t(s);t(null)})}nA(e,(n,o)=>{if(n)return t(n);if(o)return t(null);Ls.lstat(r,s=>{if(s)return s.message=s.message.replace("lstat","ensureLink"),t(s);let a=rA.dirname(e);nA(a,(l,u)=>{if(l)return t(l);if(u)return i(r,e);iA.mkdirs(a,c=>{if(c)return t(c);i(r,e)})})})})}function Qte(r,e){if(Ls.existsSync(e))return;try{Ls.lstatSync(r)}catch(o){throw o.message=o.message.replace("lstat","ensureLink"),o}let i=rA.dirname(e);return Ls.existsSync(i)||iA.mkdirsSync(i),Ls.linkSync(r,e)}tA.exports={createLink:Xte(Zte),createLinkSync:Qte}});var aA=v((yCe,sA)=>{"use strict";var _o=require("path"),Lc=Ce(),ere=Eo().pathExists;function tre(r,e,t){if(_o.isAbsolute(r))return Lc.lstat(r,i=>i?(i.message=i.message.replace("lstat","ensureSymlink"),t(i)):t(null,{toCwd:r,toDst:r}));{let i=_o.dirname(e),n=_o.join(i,r);return ere(n,(o,s)=>o?t(o):s?t(null,{toCwd:n,toDst:r}):Lc.lstat(r,a=>a?(a.message=a.message.replace("lstat","ensureSymlink"),t(a)):t(null,{toCwd:r,toDst:_o.relative(i,r)})))}}function rre(r,e){let t;if(_o.isAbsolute(r)){if(t=Lc.existsSync(r),!t)throw new Error("absolute srcpath does not exist");return{toCwd:r,toDst:r}}else{let i=_o.dirname(e),n=_o.join(i,r);if(t=Lc.existsSync(n),t)return{toCwd:n,toDst:r};if(t=Lc.existsSync(r),!t)throw new Error("relative srcpath does not exist");return{toCwd:r,toDst:_o.relative(i,r)}}}sA.exports={symlinkPaths:tre,symlinkPathsSync:rre}});var cA=v((bCe,lA)=>{"use strict";var uA=Ce();function ire(r,e,t){if(t=typeof e=="function"?e:t,e=typeof e=="function"?!1:e,e)return t(null,e);uA.lstat(r,(i,n)=>{if(i)return t(null,"file");e=n&&n.isDirectory()?"dir":"file",t(null,e)})}function nre(r,e){let t;if(e)return e;try{t=uA.lstatSync(r)}catch{return"file"}return t&&t.isDirectory()?"dir":"file"}lA.exports={symlinkType:ire,symlinkTypeSync:nre}});var vA=v((wCe,fA)=>{"use strict";var ore=Wr().fromCallback,pA=require("path"),Ya=Ce(),dA=qi(),sre=dA.mkdirs,are=dA.mkdirsSync,hA=aA(),lre=hA.symlinkPaths,ure=hA.symlinkPathsSync,mA=cA(),cre=mA.symlinkType,fre=mA.symlinkTypeSync,gA=Eo().pathExists;function pre(r,e,t,i){i=typeof t=="function"?t:i,t=typeof t=="function"?!1:t,gA(e,(n,o)=>{if(n)return i(n);if(o)return i(null);lre(r,e,(s,a)=>{if(s)return i(s);r=a.toDst,cre(a.toCwd,t,(l,u)=>{if(l)return i(l);let c=pA.dirname(e);gA(c,(f,p)=>{if(f)return i(f);if(p)return Ya.symlink(r,e,u,i);sre(c,d=>{if(d)return i(d);Ya.symlink(r,e,u,i)})})})})})}function dre(r,e,t){if(Ya.existsSync(e))return;let n=ure(r,e);r=n.toDst,t=fre(n.toCwd,t);let o=pA.dirname(e);return Ya.existsSync(o)||are(o),Ya.symlinkSync(r,e,t)}fA.exports={createSymlink:ore(pre),createSymlinkSync:dre}});var bA=v((xCe,yA)=>{"use strict";var ch=eA(),fh=oA(),ph=vA();yA.exports={createFile:ch.createFile,createFileSync:ch.createFileSync,ensureFile:ch.createFile,ensureFileSync:ch.createFileSync,createLink:fh.createLink,createLinkSync:fh.createLinkSync,ensureLink:fh.createLink,ensureLinkSync:fh.createLinkSync,createSymlink:ph.createSymlink,createSymlinkSync:ph.createSymlinkSync,ensureSymlink:ph.createSymlink,ensureSymlinkSync:ph.createSymlinkSync}});var wA=v(Yb=>{"use strict";Yb.fromCallback=function(r){return Object.defineProperty(function(...e){if(typeof e[e.length-1]=="function")r.apply(this,e);else return new Promise((t,i)=>{r.call(this,...e,(n,o)=>n!=null?i(n):t(o))})},"name",{value:r.name})};Yb.fromPromise=function(r){return Object.defineProperty(function(...e){let t=e[e.length-1];if(typeof t!="function")return r.apply(this,e);r.apply(this,e.slice(0,-1)).then(i=>t(null,i),t)},"name",{value:r.name})}});var dh=v((SCe,xA)=>{function hre(r,{EOL:e=` -`,finalEOL:t=!0,replacer:i=null,spaces:n}={}){let o=t?e:"";return JSON.stringify(r,i,n).replace(/\n/g,e)+o}function mre(r){return Buffer.isBuffer(r)&&(r=r.toString("utf8")),r.replace(/^\uFEFF/,"")}xA.exports={stringify:hre,stripBom:mre}});var CA=v((ECe,DA)=>{var Xa;try{Xa=Ce()}catch(r){Xa=require("fs")}var hh=wA(),{stringify:SA,stripBom:EA}=dh();async function gre(r,e={}){typeof e=="string"&&(e={encoding:e});let t=e.fs||Xa,i="throws"in e?e.throws:!0,n=await hh.fromCallback(t.readFile)(r,e);n=EA(n);let o;try{o=JSON.parse(n,e?e.reviver:null)}catch(s){if(i)throw s.message=`${r}: ${s.message}`,s;return null}return o}var vre=hh.fromPromise(gre);function yre(r,e={}){typeof e=="string"&&(e={encoding:e});let t=e.fs||Xa,i="throws"in e?e.throws:!0;try{let n=t.readFileSync(r,e);return n=EA(n),JSON.parse(n,e.reviver)}catch(n){if(i)throw n.message=`${r}: ${n.message}`,n;return null}}async function bre(r,e,t={}){let i=t.fs||Xa,n=SA(e,t);await hh.fromCallback(i.writeFile)(r,n,t)}var wre=hh.fromPromise(bre);function xre(r,e,t={}){let i=t.fs||Xa,n=SA(e,t);return i.writeFileSync(r,n,t)}var Dre={readFile:vre,readFileSync:yre,writeFile:wre,writeFileSync:xre};DA.exports=Dre});var PA=v((CCe,_A)=>{"use strict";var mh=CA();_A.exports={readJson:mh.readFile,readJsonSync:mh.readFileSync,writeJson:mh.writeFile,writeJsonSync:mh.writeFileSync}});var gh=v((_Ce,TA)=>{"use strict";var Sre=Wr().fromCallback,Mc=Ce(),RA=require("path"),kA=qi(),Ere=Eo().pathExists;function Cre(r,e,t,i){typeof t=="function"&&(i=t,t="utf8");let n=RA.dirname(r);Ere(n,(o,s)=>{if(o)return i(o);if(s)return Mc.writeFile(r,e,t,i);kA.mkdirs(n,a=>{if(a)return i(a);Mc.writeFile(r,e,t,i)})})}function _re(r,...e){let t=RA.dirname(r);if(Mc.existsSync(t))return Mc.writeFileSync(r,...e);kA.mkdirsSync(t),Mc.writeFileSync(r,...e)}TA.exports={outputFile:Sre(Cre),outputFileSync:_re}});var FA=v((PCe,IA)=>{"use strict";var{stringify:Pre}=dh(),{outputFile:Tre}=gh();async function Rre(r,e,t={}){let i=Pre(e,t);await Tre(r,i,t)}IA.exports=Rre});var OA=v((TCe,AA)=>{"use strict";var{stringify:kre}=dh(),{outputFileSync:Ire}=gh();function Fre(r,e,t){let i=kre(e,t);Ire(r,i,t)}AA.exports=Fre});var MA=v((RCe,LA)=>{"use strict";var Are=Wr().fromPromise,yr=PA();yr.outputJson=Are(FA());yr.outputJsonSync=OA();yr.outputJSON=yr.outputJson;yr.outputJSONSync=yr.outputJsonSync;yr.writeJSON=yr.writeJson;yr.writeJSONSync=yr.writeJsonSync;yr.readJSON=yr.readJson;yr.readJSONSync=yr.readJsonSync;LA.exports=yr});var UA=v((kCe,NA)=>{"use strict";var qA=Ce(),Ore=require("path"),Lre=Gb().copySync,$A=Oc().removeSync,Mre=qi().mkdirpSync,BA=Tc();function qre(r,e,t){t=t||{};let i=t.overwrite||t.clobber||!1,{srcStat:n}=BA.checkPathsSync(r,e,"move");return BA.checkParentPathsSync(r,n,e,"move"),Mre(Ore.dirname(e)),Nre(r,e,i)}function Nre(r,e,t){if(t)return $A(e),jA(r,e,t);if(qA.existsSync(e))throw new Error("dest already exists.");return jA(r,e,t)}function jA(r,e,t){try{qA.renameSync(r,e)}catch(i){if(i.code!=="EXDEV")throw i;return $re(r,e,t)}}function $re(r,e,t){return Lre(r,e,{overwrite:t,errorOnExist:!0}),$A(r)}NA.exports=qre});var HA=v((ICe,WA)=>{"use strict";WA.exports={moveSync:UA()}});var JA=v((FCe,zA)=>{"use strict";var Bre=Ce(),jre=require("path"),Ure=Kb().copy,GA=Oc().remove,Wre=qi().mkdirp,Hre=Eo().pathExists,VA=Tc();function Gre(r,e,t,i){typeof t=="function"&&(i=t,t={});let n=t.overwrite||t.clobber||!1;VA.checkPaths(r,e,"move",(o,s)=>{if(o)return i(o);let{srcStat:a}=s;VA.checkParentPaths(r,a,e,"move",l=>{if(l)return i(l);Wre(jre.dirname(e),u=>u?i(u):zre(r,e,n,i))})})}function zre(r,e,t,i){if(t)return GA(e,n=>n?i(n):KA(r,e,t,i));Hre(e,(n,o)=>n?i(n):o?i(new Error("dest already exists.")):KA(r,e,t,i))}function KA(r,e,t,i){Bre.rename(r,e,n=>n?n.code!=="EXDEV"?i(n):Vre(r,e,t,i):i())}function Vre(r,e,t,i){Ure(r,e,{overwrite:t,errorOnExist:!0},o=>o?i(o):GA(r,i))}zA.exports=Gre});var XA=v((ACe,YA)=>{"use strict";var Kre=Wr().fromCallback;YA.exports={move:Kre(JA())}});var $i=v((OCe,Xb)=>{"use strict";Xb.exports={...Pc(),...Gb(),...Kb(),...YF(),...bA(),...MA(),...qi(),...HA(),...XA(),...gh(),...Eo(),...Oc()};var ZA=require("fs");Object.getOwnPropertyDescriptor(ZA,"promises")&&Object.defineProperty(Xb.exports,"promises",{get(){return ZA.promises}})});var U=v((LCe,QA)=>{var Ms=S(require("fs")),Zb=S(Mb()),vh=S(require("path")),eO=S(require("os")),tO=S($i());function Jre(){let r=process.env.NVIM_COC_LOG_FILE;if(r)return r;let e=process.env.XDG_RUNTIME_DIR;if(e)try{return Ms.default.accessSync(e,Ms.default.constants.R_OK|Ms.default.constants.W_OK),vh.default.join(e,`coc-nvim-${process.pid}.log`)}catch(i){}let t=eO.default.tmpdir();return e=vh.default.join(t,`coc.nvim-${process.pid}`),Ms.default.existsSync(e)||tO.mkdirpSync(e),vh.default.join(e,"coc-nvim.log")}var Yre=1024*1024,Xre=10,yh=Jre(),Zre=process.env.NVIM_COC_LOG_LEVEL||"info";if(Ms.default.existsSync(yh))try{Ms.default.writeFileSync(yh,"",{encoding:"utf8",mode:438})}catch(r){}Zb.default.configure({disableClustering:!0,appenders:{out:{type:"file",mode:438,filename:yh,maxLogSize:Yre,backups:Xre,layout:{type:"pattern",pattern:`%d{ISO8601} %p (pid:${process.pid}) [%c] - %m`}}},categories:{default:{appenders:["out"],level:Zre}}});QA.exports=(r="coc-nvim")=>{let e=Zb.default.getLogger(r);return e.getLogFile=()=>yh,e}});var bh=v(()=>{Promise.prototype.logError=function(){this.catch(r=>{U()("extensions").error(r)})}});var iO=v((Qb,rO)=>{rO.exports=ew(typeof Buffer!="undefined"&&Buffer)||ew(Qb.Buffer)||ew(typeof window!="undefined"&&window.Buffer)||Qb.Buffer;function ew(r){return r&&r.isBuffer&&r}});var wh=v((qCe,nO)=>{var Qre={}.toString;nO.exports=Array.isArray||function(r){return Qre.call(r)=="[object Array]"}});var aO=v((Za,oO)=>{var Qa=Hr(),Za=oO.exports=sO(0);Za.alloc=sO;Za.concat=Qa.concat;Za.from=eie;function sO(r){return new Array(r)}function eie(r){if(!Qa.isBuffer(r)&&Qa.isView(r))r=Qa.Uint8Array.from(r);else if(Qa.isArrayBuffer(r))r=new Uint8Array(r);else{if(typeof r=="string")return Qa.from.call(Za,r);if(typeof r=="number")throw new TypeError('"value" argument must not be a number')}return Array.prototype.slice.call(r)}});var cO=v((el,lO)=>{var Mn=Hr(),tl=Mn.global,el=lO.exports=Mn.hasBuffer?uO(0):[];el.alloc=Mn.hasBuffer&&tl.alloc||uO;el.concat=Mn.concat;el.from=tie;function uO(r){return new tl(r)}function tie(r){if(!Mn.isBuffer(r)&&Mn.isView(r))r=Mn.Uint8Array.from(r);else if(Mn.isArrayBuffer(r))r=new Uint8Array(r);else{if(typeof r=="string")return Mn.from.call(el,r);if(typeof r=="number")throw new TypeError('"value" argument must not be a number')}return tl.from&&tl.from.length!==1?tl.from(r):new tl(r)}});var dO=v((rl,fO)=>{var xh=Hr(),rl=fO.exports=xh.hasArrayBuffer?pO(0):[];rl.alloc=pO;rl.concat=xh.concat;rl.from=rie;function pO(r){return new Uint8Array(r)}function rie(r){if(xh.isView(r)){var e=r.byteOffset,t=r.byteLength;r=r.buffer,r.byteLength!==t&&(r.slice?r=r.slice(e,e+t):(r=new Uint8Array(r),r.byteLength!==t&&(r=Array.prototype.slice.call(r,e,e+t))))}else{if(typeof r=="string")return xh.from.call(rl,r);if(typeof r=="number")throw new TypeError('"value" argument must not be a number')}return new Uint8Array(r)}});var hO=v(Dh=>{Dh.copy=iie;Dh.toString=nie;Dh.write=oie;function oie(r,e){for(var t=this,i=e||(e|=0),n=r.length,o=0,s=0;s>>6,t[i++]=128|o&63):o<55296||o>57343?(t[i++]=224|o>>>12,t[i++]=128|o>>>6&63,t[i++]=128|o&63):(o=(o-55296<<10|r.charCodeAt(s++)-56320)+65536,t[i++]=240|o>>>18,t[i++]=128|o>>>12&63,t[i++]=128|o>>>6&63,t[i++]=128|o&63);return i-e}function nie(r,e,t){var i=this,n=e|0;t||(t=i.length);for(var o="",s=0;n=65536?(s-=65536,o+=String.fromCharCode((s>>>10)+55296,(s&1023)+56320)):o+=String.fromCharCode(s)}return o}function iie(r,e,t,i){var n;t||(t=0),!i&&i!==0&&(i=this.length),e||(e=0);var o=i-t;if(r===this&&t=0;n--)r[n+e]=this[n+t];else for(n=0;n{var tw=hO();Nc.copy=mO;Nc.slice=gO;Nc.toString=sie;Nc.write=aie("write");var Po=Hr(),vO=Po.global,yO=Po.hasBuffer&&"TYPED_ARRAY_SUPPORT"in vO,bO=yO&&!vO.TYPED_ARRAY_SUPPORT;function mO(r,e,t,i){var n=Po.isBuffer(this),o=Po.isBuffer(r);if(n&&o)return this.copy(r,e,t,i);if(!bO&&!n&&!o&&Po.isView(this)&&Po.isView(r)){var s=t||i!=null?gO.call(this,t,i):this;return r.set(s,e),s.length}else return tw.copy.call(this,r,e,t,i)}function gO(r,e){var t=this.slice||!bO&&this.subarray;if(t)return t.call(this,r,e);var i=Po.alloc.call(this,e-r);return mO.call(this,i,0,r,e),i}function sie(r,e,t){var i=!yO&&Po.isBuffer(this)?this.toString:tw.toString;return i.apply(this,arguments)}function aie(r){return e;function e(){var t=this[r]||tw[r];return t.apply(this,arguments)}}});var Hr=v(rr=>{var rw=rr.global=iO(),wO=rr.hasBuffer=rw&&!!rw.isBuffer,iw=rr.hasArrayBuffer=typeof ArrayBuffer!="undefined",lie=rr.isArray=wh();rr.isArrayBuffer=iw?uie:nw;var cie=rr.isBuffer=wO?rw.isBuffer:nw,fie=rr.isView=iw?ArrayBuffer.isView||xO("ArrayBuffer","buffer"):nw;rr.alloc=ow;rr.concat=pie;rr.from=die;var DO=rr.Array=aO(),SO=rr.Buffer=cO(),EO=rr.Uint8Array=dO(),sw=rr.prototype=Sh();function die(r){return typeof r=="string"?hie.call(this,r):CO(this).from(r)}function ow(r){return CO(this).alloc(r)}function pie(r,e){e||(e=0,Array.prototype.forEach.call(r,o));var t=this!==rr&&this||r[0],i=ow.call(t,e),n=0;return Array.prototype.forEach.call(r,s),i;function o(a){e+=a.length}function s(a){n+=sw.copy.call(a,i,n)}}var mie=xO("ArrayBuffer");function uie(r){return r instanceof ArrayBuffer||mie(r)}function hie(r){var e=r.length*3,t=ow.call(this,e),i=sw.write.call(t,r);return e!==i&&(t=sw.slice.call(t,0,i)),t}function CO(r){return cie(r)?SO:fie(r)?EO:lie(r)?DO:wO?SO:iw?EO:DO}function nw(){return!1}function xO(r,e){return r="[object "+r+"]",function(t){return t!=null&&{}.toString.call(e?t[e]:t)===r}}});var Eh=v(_O=>{_O.ExtBuffer=aw;var gie=Hr();function aw(r,e){if(!(this instanceof aw))return new aw(r,e);this.buffer=gie.from(r),this.type=e}});var TO=v(PO=>{PO.setExtPackers=vie;var Ch=Hr(),yie=Ch.global,Bi=Ch.Uint8Array.from,lw,bie={name:1,message:1,stack:1,columnNumber:1,fileName:1,lineNumber:1};function vie(r){r.addExtPacker(14,Error,[Ns,mi]),r.addExtPacker(1,EvalError,[Ns,mi]),r.addExtPacker(2,RangeError,[Ns,mi]),r.addExtPacker(3,ReferenceError,[Ns,mi]),r.addExtPacker(4,SyntaxError,[Ns,mi]),r.addExtPacker(5,TypeError,[Ns,mi]),r.addExtPacker(6,URIError,[Ns,mi]),r.addExtPacker(10,RegExp,[wie,mi]),r.addExtPacker(11,Boolean,[uw,mi]),r.addExtPacker(12,String,[uw,mi]),r.addExtPacker(13,Date,[Number,mi]),r.addExtPacker(15,Number,[uw,mi]),typeof Uint8Array!="undefined"&&(r.addExtPacker(17,Int8Array,Bi),r.addExtPacker(18,Uint8Array,Bi),r.addExtPacker(19,Int16Array,Bi),r.addExtPacker(20,Uint16Array,Bi),r.addExtPacker(21,Int32Array,Bi),r.addExtPacker(22,Uint32Array,Bi),r.addExtPacker(23,Float32Array,Bi),typeof Float64Array!="undefined"&&r.addExtPacker(24,Float64Array,Bi),typeof Uint8ClampedArray!="undefined"&&r.addExtPacker(25,Uint8ClampedArray,Bi),r.addExtPacker(26,ArrayBuffer,Bi),r.addExtPacker(29,DataView,Bi)),Ch.hasBuffer&&r.addExtPacker(27,yie,Ch.from)}function mi(r){return lw||(lw=cw().encode),lw(r)}function uw(r){return r.valueOf()}function wie(r){r=RegExp.prototype.toString.call(r).split("/"),r.shift();var e=[r.pop()];return e.unshift(r.join("/")),e}function Ns(r){var e={};for(var t in bie)e[t]=r[t];return e}});var _h=v(qc=>{var xie,Die,Sie,Eie;(function(r){var e="undefined",t=e!==typeof Buffer&&Buffer,i=e!==typeof Uint8Array&&Uint8Array,n=e!==typeof ArrayBuffer&&ArrayBuffer,o=[0,0,0,0,0,0,0,0],s=Array.isArray||P,a=4294967296,l=16777216,u;xie=c("Uint64BE",!0,!0),Die=c("Int64BE",!0,!1),Sie=c("Uint64LE",!1,!0),Eie=c("Int64LE",!1,!1);function c(k,_,L){var I=_?0:4,O=_?4:0,R=_?0:3,F=_?1:2,q=_?2:1,K=_?3:0,ae=_?g:x,Pe=_?w:E,We=hr.prototype,Yt="is"+k,qt="_"+Yt;return We.buffer=void 0,We.offset=0,We[qt]=!0,We.toNumber=Cd,We.toString=Ry,We.toJSON=Cd,We.toArray=f,t&&(We.toBuffer=p),i&&(We.toArrayBuffer=d),hr[Yt]=kn,r[k]=hr,hr;function hr(Se,ve,fe,Ee){return this instanceof hr?In(this,Se,ve,fe,Ee):new hr(Se,ve,fe,Ee)}function kn(Se){return!!(Se&&Se[qt])}function In(Se,ve,fe,Ee,Ct){if(i&&n&&(ve instanceof n&&(ve=new i(ve)),Ee instanceof n&&(Ee=new i(Ee))),!ve&&!fe&&!Ee&&!u){Se.buffer=y(o,0);return}if(!h(ve,fe)){var Oi=u||Array;Ct=fe,Ee=ve,fe=0,ve=new Oi(8)}Se.buffer=ve,Se.offset=fe|=0,e!==typeof Ee&&(typeof Ee=="string"?Ty(ve,fe,Ee,Ct||10):h(Ee,Ct)?m(ve,fe,Ee,Ct):typeof Ct=="number"?(Oa(ve,fe+I,Ee),Oa(ve,fe+O,Ct)):Ee>0?ae(ve,fe,Ee):Ee<0?Pe(ve,fe,Ee):m(ve,fe,o,0))}function Ty(Se,ve,fe,Ee){var Ct=0,Oi=fe.length,Xt=0,$t=0;fe[0]==="-"&&Ct++;for(var ky=Ct;Ct=0))break;$t=$t*Ee+_d,Xt=Xt*Ee+Math.floor($t/a),$t%=a}ky&&(Xt=~Xt,$t?$t=a-$t:Xt++),Oa(Se,ve+I,Xt),Oa(Se,ve+O,$t)}function Cd(){var Se=this.buffer,ve=this.offset,fe=La(Se,ve+I),Ee=La(Se,ve+O);return L||(fe|=0),fe?fe*a+Ee:Ee}function Ry(Se){var ve=this.buffer,fe=this.offset,Ee=La(ve,fe+I),Ct=La(ve,fe+O),Oi="",Xt=!L&&Ee&2147483648;for(Xt&&(Ee=~Ee,Ct=a-Ct),Se=Se||10;;){var $t=Ee%Se*a+Ct;if(Ee=Math.floor(Ee/Se),Ct=Math.floor($t/Se),Oi=($t%Se).toString(Se)+Oi,!Ee&&!Ct)break}return Xt&&(Oi="-"+Oi),Oi}function Oa(Se,ve,fe){Se[ve+K]=fe&255,fe=fe>>8,Se[ve+q]=fe&255,fe=fe>>8,Se[ve+F]=fe&255,fe=fe>>8,Se[ve+R]=fe&255}function La(Se,ve){return Se[ve+R]*l+(Se[ve+F]<<16)+(Se[ve+q]<<8)+Se[ve+K]}}function f(k){var _=this.buffer,L=this.offset;return u=null,k!==!1&&L===0&&_.length===8&&s(_)?_:y(_,L)}function p(k){var _=this.buffer,L=this.offset;if(u=t,k!==!1&&L===0&&_.length===8&&Buffer.isBuffer(_))return _;var I=new t(8);return m(I,0,_,L),I}function d(k){var _=this.buffer,L=this.offset,I=_.buffer;if(u=i,k!==!1&&L===0&&I instanceof n&&I.byteLength===8)return I;var O=new i(8);return m(O,0,_,L),O.buffer}function h(k,_){var L=k&&k.length;return _|=0,L&&_+8<=L&&typeof k[_]!="string"}function m(k,_,L,I){_|=0,I|=0;for(var O=0;O<8;O++)k[_++]=L[I++]&255}function y(k,_){return Array.prototype.slice.call(k,_,_+8)}function g(k,_,L){for(var I=_+8;I>_;)k[--I]=L&255,L/=256}function w(k,_,L){var I=_+8;for(L++;I>_;)k[--I]=-L&255^255,L/=256}function x(k,_,L){for(var I=_+8;_{fw.read=function(r,e,t,i,n){var o,s,a=n*8-i-1,l=(1<>1,c=-7,f=t?n-1:0,p=t?-1:1,d=r[e+f];for(f+=p,o=d&(1<<-c)-1,d>>=-c,c+=a;c>0;o=o*256+r[e+f],f+=p,c-=8);for(s=o&(1<<-c)-1,o>>=-c,c+=i;c>0;s=s*256+r[e+f],f+=p,c-=8);if(o===0)o=1-u;else{if(o===l)return s?NaN:(d?-1:1)*Infinity;s=s+Math.pow(2,i),o=o-u}return(d?-1:1)*s*Math.pow(2,o-i)};fw.write=function(r,e,t,i,n,o){var s,a,l,u=o*8-n-1,c=(1<>1,p=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,d=i?0:o-1,h=i?1:-1,m=e<0||e===0&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===Infinity?(a=isNaN(e)?1:0,s=c):(s=Math.floor(Math.log(e)/Math.LN2),e*(l=Math.pow(2,-s))<1&&(s--,l*=2),s+f>=1?e+=p/l:e+=p*Math.pow(2,1-f),e*l>=2&&(s++,l/=2),s+f>=c?(a=0,s=c):s+f>=1?(a=(e*l-1)*Math.pow(2,n),s=s+f):(a=e*Math.pow(2,f-1)*Math.pow(2,n),s=0));n>=8;r[t+d]=a&255,d+=h,a/=256,n-=8);for(s=s<0;r[t+d]=s&255,d+=h,s/=256,u-=8);r[t+d-h]|=m*128}});var dw=v(RO=>{var Cie=RO.uint8=new Array(256);for(var Ph=0;Ph<=255;Ph++)Cie[Ph]=_ie(Ph);function _ie(r){return function(e){var t=e.reserve(1);e.buffer[t]=r}}});var BO=v(kO=>{var IO=pw(),FO=_h(),Pie=FO.Uint64BE,Tie=FO.Int64BE,AO=dw().uint8,Th=Hr(),ot=Th.global,Rie=Th.hasBuffer&&"TYPED_ARRAY_SUPPORT"in ot,kie=Rie&&!ot.TYPED_ARRAY_SUPPORT,OO=Th.hasBuffer&&ot.prototype||{};kO.getWriteToken=Iie;function Iie(r){return r&&r.uint8array?Fie():kie||Th.hasBuffer&&r&&r.safe?Aie():LO()}function Fie(){var r=LO();return r[202]=je(202,4,MO),r[203]=je(203,8,NO),r}function LO(){var r=AO.slice();return r[196]=$c(196),r[197]=qs(197),r[198]=$s(198),r[199]=$c(199),r[200]=qs(200),r[201]=$s(201),r[202]=je(202,4,OO.writeFloatBE||MO,!0),r[203]=je(203,8,OO.writeDoubleBE||NO,!0),r[204]=$c(204),r[205]=qs(205),r[206]=$s(206),r[207]=je(207,8,qO),r[208]=$c(208),r[209]=qs(209),r[210]=$s(210),r[211]=je(211,8,$O),r[217]=$c(217),r[218]=qs(218),r[219]=$s(219),r[220]=qs(220),r[221]=$s(221),r[222]=qs(222),r[223]=$s(223),r}function Aie(){var r=AO.slice();return r[196]=je(196,1,ot.prototype.writeUInt8),r[197]=je(197,2,ot.prototype.writeUInt16BE),r[198]=je(198,4,ot.prototype.writeUInt32BE),r[199]=je(199,1,ot.prototype.writeUInt8),r[200]=je(200,2,ot.prototype.writeUInt16BE),r[201]=je(201,4,ot.prototype.writeUInt32BE),r[202]=je(202,4,ot.prototype.writeFloatBE),r[203]=je(203,8,ot.prototype.writeDoubleBE),r[204]=je(204,1,ot.prototype.writeUInt8),r[205]=je(205,2,ot.prototype.writeUInt16BE),r[206]=je(206,4,ot.prototype.writeUInt32BE),r[207]=je(207,8,qO),r[208]=je(208,1,ot.prototype.writeInt8),r[209]=je(209,2,ot.prototype.writeInt16BE),r[210]=je(210,4,ot.prototype.writeInt32BE),r[211]=je(211,8,$O),r[217]=je(217,1,ot.prototype.writeUInt8),r[218]=je(218,2,ot.prototype.writeUInt16BE),r[219]=je(219,4,ot.prototype.writeUInt32BE),r[220]=je(220,2,ot.prototype.writeUInt16BE),r[221]=je(221,4,ot.prototype.writeUInt32BE),r[222]=je(222,2,ot.prototype.writeUInt16BE),r[223]=je(223,4,ot.prototype.writeUInt32BE),r}function $c(r){return function(e,t){var i=e.reserve(2),n=e.buffer;n[i++]=r,n[i]=t}}function qs(r){return function(e,t){var i=e.reserve(3),n=e.buffer;n[i++]=r,n[i++]=t>>>8,n[i]=t}}function $s(r){return function(e,t){var i=e.reserve(5),n=e.buffer;n[i++]=r,n[i++]=t>>>24,n[i++]=t>>>16,n[i++]=t>>>8,n[i]=t}}function je(r,e,t,i){return function(n,o){var s=n.reserve(e+1);n.buffer[s++]=r,t.call(n.buffer,o,s,i)}}function qO(r,e){new Pie(this,e,r)}function $O(r,e){new Tie(this,e,r)}function MO(r,e){IO.write(this,r,e,!1,23,4)}function NO(r,e){IO.write(this,r,e,!1,52,8)}});var zO=v(jO=>{var Oie=wh(),UO=_h(),Lie=UO.Uint64BE,Mie=UO.Int64BE,WO=Hr(),HO=Sh(),Nie=BO(),qie=dw().uint8,$ie=Eh().ExtBuffer,Bie=typeof Uint8Array!="undefined",jie=typeof Map!="undefined",il=[];il[1]=212;il[2]=213;il[4]=214;il[8]=215;il[16]=216;jO.getWriteType=Uie;function Uie(r){var e=Nie.getWriteToken(r),t=r&&r.useraw,i=Bie&&r&&r.binarraybuffer,n=i?WO.isArrayBuffer:WO.isBuffer,o=i?P:E,s=jie&&r&&r.usemap,a=s?L:_,l={boolean:u,function:w,number:c,object:t?g:y,string:m(t?h:d),symbol:w,undefined:w};return l;function u(O,R){var F=R?195:194;e[F](O,R)}function c(O,R){var F=R|0,q;if(R!==F){q=203,e[q](O,R);return}else-32<=F&&F<=127?q=F&255:0<=F?q=F<=255?204:F<=65535?205:206:q=-128<=F?208:-32768<=F?209:210;e[q](O,F)}function f(O,R){var F=207;e[F](O,R.toArray())}function p(O,R){var F=211;e[F](O,R.toArray())}function d(O){return O<32?1:O<=255?2:O<=65535?3:5}function h(O){return O<32?1:O<=65535?3:5}function m(O){return R;function R(F,q){var K=q.length,ae=5+K*3;F.offset=F.reserve(ae);var Pe=F.buffer,We=O(K),Yt=F.offset+We;K=HO.write.call(Pe,q,Yt);var qt=O(K);if(We!==qt){var hr=Yt+qt-We,kn=Yt+K;HO.copy.call(Pe,Pe,hr,Yt,kn)}var In=qt===1?160+K:qt<=3?215+qt:219;e[In](F,K),F.offset+=K}}function y(O,R){if(R===null)return w(O,R);if(n(R))return o(O,R);if(Oie(R))return x(O,R);if(Lie.isUint64BE(R))return f(O,R);if(Mie.isInt64BE(R))return p(O,R);var F=O.codec.getExtPacker(R);if(F&&(R=F(R)),R instanceof $ie)return k(O,R);a(O,R)}function g(O,R){if(n(R))return I(O,R);y(O,R)}function w(O,R){var F=192;e[F](O,R)}function x(O,R){var F=R.length,q=F<16?144+F:F<=65535?220:221;e[q](O,F);for(var K=O.codec.encode,ae=0;ae{var Wie=wh();Bc.createCodec=GO;Bc.install=Hie;Bc.filter=zie;var Gie=Hr();function nl(r){if(!(this instanceof nl))return new nl(r);this.options=r,this.init()}nl.prototype.init=function(){var r=this.options;return r&&r.uint8array&&(this.bufferish=Gie.Uint8Array),this};function Hie(r){for(var e in r)nl.prototype[e]=Vie(nl.prototype[e],r[e])}function Vie(r,e){return r&&e?t:r||e;function t(){return r.apply(this,arguments),e.apply(this,arguments)}}function Kie(r){return r=r.slice(),function(t){return r.reduce(e,t)};function e(t,i){return i(t)}}function zie(r){return Wie(r)?Kie(r):r}function GO(r){return new nl(r)}Bc.preset=GO({preset:!0})});var Rh=v(VO=>{var Jie=Eh().ExtBuffer,Yie=TO(),Xie=zO(),hw=jc();hw.install({addExtPacker:Zie,getExtPacker:Qie,init:KO});VO.preset=KO.call(hw.preset);function ene(r){var e=Xie.getWriteType(r);return t;function t(i,n){var o=e[typeof n];if(!o)throw new Error('Unsupported type "'+typeof n+'": '+n);o(i,n)}}function KO(){var r=this.options;return this.encode=ene(r),r&&r.preset&&Yie.setExtPackers(this),this}function Zie(r,e,t){t=hw.filter(t);var i=e.name;if(i&&i!=="Object"){var n=this.extPackers||(this.extPackers={});n[i]=s}else{var o=this.extEncoderList||(this.extEncoderList=[]);o.unshift([e,s])}function s(a){return t&&(a=t(a)),new Jie(a,r)}}function Qie(r){var e=this.extPackers||(this.extPackers={}),t=r.constructor,i=t&&t.name&&e[t.name];if(i)return i;for(var n=this.extEncoderList||(this.extEncoderList=[]),o=n.length,s=0;s{mw.FlexDecoder=ol;mw.FlexEncoder=sl;var Uc=Hr(),tne=2048,rne=65536,JO="BUFFER_SHORTAGE";function ol(){if(!(this instanceof ol))return new ol}function sl(){if(!(this instanceof sl))return new sl}ol.mixin=YO(ine());ol.mixin(ol.prototype);sl.mixin=YO(nne());sl.mixin(sl.prototype);function ine(){return{bufferish:Uc,write:r,fetch:one,flush:e,push:ZO,pull:sne,read:XO,reserve:t,offset:0};function r(i){var n=this.offset?Uc.prototype.slice.call(this.buffer,this.offset):this.buffer;this.buffer=n?i?this.bufferish.concat([n,i]):n:i,this.offset=0}function e(){for(;this.offsetthis.buffer.length)throw new Error(JO);return this.offset=o,n}}function nne(){return{bufferish:Uc,write:ane,fetch:r,flush:e,push:ZO,pull:t,read:XO,reserve:i,send:n,maxBufferSize:rne,minBufferSize:tne,offset:0,start:0};function r(){var o=this.start;if(o1?this.bufferish.concat(o):o[0];return o.length=0,s}function i(o){var s=o|0;if(this.buffer){var a=this.buffer.length,l=this.offset|0,u=l+s;if(uthis.minBufferSize)this.flush(),this.push(o);else{var a=this.reserve(s);Uc.prototype.copy.call(o,this.buffer,a)}}}function ane(){throw new Error("method not implemented: write()")}function one(){throw new Error("method not implemented: fetch()")}function XO(){var r=this.buffers&&this.buffers.length;return r?(this.flush(),this.pull()):this.fetch()}function ZO(r){var e=this.buffers||(this.buffers=[]);e.push(r)}function sne(){var r=this.buffers||(this.buffers=[]);return r.shift()}function YO(r){return e;function e(t){for(var i in r)t[i]=r[i];return t}}});var kh=v(QO=>{QO.EncodeBuffer=al;var lne=Rh().preset,une=gw().FlexEncoder;une.mixin(al.prototype);function al(r){if(!(this instanceof al))return new al(r);if(r&&(this.options=r,r.codec)){var e=this.codec=r.codec;e.bufferish&&(this.bufferish=e.bufferish)}}al.prototype.codec=lne;al.prototype.write=function(r){this.codec.encode(this,r)}});var cw=v(eL=>{eL.encode=cne;var fne=kh().EncodeBuffer;function cne(r,e){var t=new fne(e);return t.write(r),t.read()}});var iL=v(tL=>{tL.setExtUnpackers=pne;var rL=Hr(),dne=rL.global,vw,hne={name:1,message:1,stack:1,columnNumber:1,fileName:1,lineNumber:1};function pne(r){r.addExtUnpacker(14,[gi,Bs(Error)]),r.addExtUnpacker(1,[gi,Bs(EvalError)]),r.addExtUnpacker(2,[gi,Bs(RangeError)]),r.addExtUnpacker(3,[gi,Bs(ReferenceError)]),r.addExtUnpacker(4,[gi,Bs(SyntaxError)]),r.addExtUnpacker(5,[gi,Bs(TypeError)]),r.addExtUnpacker(6,[gi,Bs(URIError)]),r.addExtUnpacker(10,[gi,mne]),r.addExtUnpacker(11,[gi,br(Boolean)]),r.addExtUnpacker(12,[gi,br(String)]),r.addExtUnpacker(13,[gi,br(Date)]),r.addExtUnpacker(15,[gi,br(Number)]),typeof Uint8Array!="undefined"&&(r.addExtUnpacker(17,br(Int8Array)),r.addExtUnpacker(18,br(Uint8Array)),r.addExtUnpacker(19,[To,br(Int16Array)]),r.addExtUnpacker(20,[To,br(Uint16Array)]),r.addExtUnpacker(21,[To,br(Int32Array)]),r.addExtUnpacker(22,[To,br(Uint32Array)]),r.addExtUnpacker(23,[To,br(Float32Array)]),typeof Float64Array!="undefined"&&r.addExtUnpacker(24,[To,br(Float64Array)]),typeof Uint8ClampedArray!="undefined"&&r.addExtUnpacker(25,br(Uint8ClampedArray)),r.addExtUnpacker(26,To),r.addExtUnpacker(29,[To,br(DataView)])),rL.hasBuffer&&r.addExtUnpacker(27,br(dne))}function gi(r){return vw||(vw=yw().decode),vw(r)}function mne(r){return RegExp.apply(null,r)}function Bs(r){return function(e){var t=new r;for(var i in hne)t[i]=e[i];return t}}function br(r){return function(e){return new r(e)}}function To(r){return new Uint8Array(r).buffer}});var xw=v(bw=>{var nL=pw(),oL=_h(),sL=oL.Uint64BE,aL=oL.Int64BE;bw.getReadFormat=gne;bw.readUint8=lL;var ww=Hr(),Ih=Sh(),vne=typeof Map!="undefined",yne=!0;function gne(r){var e=ww.hasArrayBuffer&&r&&r.binarraybuffer,t=r&&r.int64,i=vne&&r&&r.usemap,n={map:i?wne:bne,array:xne,str:Dne,bin:e?Ene:Sne,ext:Cne,uint8:lL,uint16:Pne,uint32:Rne,uint64:Fh(8,t?Ane:Ine),int8:_ne,int16:Tne,int32:kne,int64:Fh(8,t?One:Fne),float32:Fh(4,Lne),float64:Fh(8,Mne)};return n}function bne(r,e){var t={},i,n=new Array(e),o=new Array(e),s=r.codec.decode;for(i=0;i{var Nne=xw();uL.getReadToken=qne;function qne(r){var e=Nne.getReadFormat(r);return r&&r.useraw?$ne(e):cL(e)}function cL(r){var e,t=new Array(256);for(e=0;e<=127;e++)t[e]=Wc(e);for(e=128;e<=143;e++)t[e]=Nn(e-128,r.map);for(e=144;e<=159;e++)t[e]=Nn(e-144,r.array);for(e=160;e<=191;e++)t[e]=Nn(e-160,r.str);for(t[192]=Wc(null),t[193]=null,t[194]=Wc(!1),t[195]=Wc(!0),t[196]=zr(r.uint8,r.bin),t[197]=zr(r.uint16,r.bin),t[198]=zr(r.uint32,r.bin),t[199]=zr(r.uint8,r.ext),t[200]=zr(r.uint16,r.ext),t[201]=zr(r.uint32,r.ext),t[202]=r.float32,t[203]=r.float64,t[204]=r.uint8,t[205]=r.uint16,t[206]=r.uint32,t[207]=r.uint64,t[208]=r.int8,t[209]=r.int16,t[210]=r.int32,t[211]=r.int64,t[212]=Nn(1,r.ext),t[213]=Nn(2,r.ext),t[214]=Nn(4,r.ext),t[215]=Nn(8,r.ext),t[216]=Nn(16,r.ext),t[217]=zr(r.uint8,r.str),t[218]=zr(r.uint16,r.str),t[219]=zr(r.uint32,r.str),t[220]=zr(r.uint16,r.array),t[221]=zr(r.uint32,r.array),t[222]=zr(r.uint16,r.map),t[223]=zr(r.uint32,r.map),e=224;e<=255;e++)t[e]=Wc(e-256);return t}function $ne(r){var e,t=cL(r).slice();for(t[217]=t[196],t[218]=t[197],t[219]=t[198],e=160;e<=191;e++)t[e]=Nn(e-160,r.bin);return t}function Wc(r){return function(){return r}}function zr(r,e){return function(t){var i=r(t);return e(t,i)}}function Nn(r,e){return function(t){return e(t,r)}}});var Ah=v(pL=>{var Bne=Eh().ExtBuffer,jne=iL(),Une=xw().readUint8,Wne=fL(),Dw=jc();Dw.install({addExtUnpacker:Hne,getExtUnpacker:zne,init:dL});pL.preset=dL.call(Dw.preset);function Gne(r){var e=Wne.getReadToken(r);return t;function t(i){var n=Une(i),o=e[n];if(!o)throw new Error("Invalid type: "+(n&&"0x"+n.toString(16)));return o(i)}}function dL(){var r=this.options;return this.decode=Gne(r),r&&r.preset&&jne.setExtUnpackers(this),this}function Hne(r,e){var t=this.extUnpackers||(this.extUnpackers=[]);t[r]=Dw.filter(e)}function zne(r){var e=this.extUnpackers||(this.extUnpackers=[]);return e[r]||t;function t(i){return new Bne(i,r)}}});var Oh=v(hL=>{hL.DecodeBuffer=ll;var Vne=Ah().preset,Kne=gw().FlexDecoder;Kne.mixin(ll.prototype);function ll(r){if(!(this instanceof ll))return new ll(r);if(r&&(this.options=r,r.codec)){var e=this.codec=r.codec;e.bufferish&&(this.bufferish=e.bufferish)}}ll.prototype.codec=Vne;ll.prototype.fetch=function(){return this.codec.decode(this)}});var yw=v(mL=>{mL.decode=Jne;var Yne=Oh().DecodeBuffer;function Jne(r,e){var t=new Yne(e);return t.write(r),t.read()}});var Cw=v((s_e,Sw)=>{function Ew(){if(!(this instanceof Ew))return new Ew}(function(r){typeof Sw!="undefined"&&(Sw.exports=r);var e="listeners",t={on:n,once:o,off:s,emit:a};i(r.prototype),r.mixin=i;function i(u){for(var c in t)u[c]=t[c];return u}function n(u,c){return l(this,u).push(c),this}function o(u,c){var f=this;return p.originalListener=c,l(f,u).push(p),f;function p(){s.call(f,u,p),c.apply(this,arguments)}}function s(u,c){var f=this,p;if(!arguments.length)delete f[e];else if(c){if(p=l(f,u,!0),p){if(p=p.filter(d),!p.length)return s.call(f,u);f[e][u]=p}}else if(p=f[e],p&&(delete p[u],!Object.keys(p).length))return s.call(f);return f;function d(h){return h!==c&&h.originalListener!==c}}function a(u,c){var f=this,p=l(f,u,!0);if(!p)return!1;var d=arguments.length;if(d===1)p.forEach(m);else if(d===2)p.forEach(y);else{var h=Array.prototype.slice.call(arguments,1);p.forEach(g)}return!!p.length;function m(w){w.call(f)}function y(w){w.call(f,c)}function g(w){w.apply(f,h)}}function l(u,c,f){if(!(f&&!u[e])){var p=u[e]||(u[e]={});return p[c]||(p[c]=[])}}})(Ew)});var yL=v(gL=>{gL.Encoder=js;var Xne=Cw(),vL=kh().EncodeBuffer;function js(r){if(!(this instanceof js))return new js(r);vL.call(this,r)}js.prototype=new vL;Xne.mixin(js.prototype);js.prototype.encode=function(r){this.write(r),this.emit("data",this.read())};js.prototype.end=function(r){arguments.length&&this.encode(r),this.flush(),this.emit("end")}});var xL=v(bL=>{bL.Decoder=Ro;var Zne=Cw(),wL=Oh().DecodeBuffer;function Ro(r){if(!(this instanceof Ro))return new Ro(r);wL.call(this,r)}Ro.prototype=new wL;Zne.mixin(Ro.prototype);Ro.prototype.decode=function(r){arguments.length&&this.write(r),this.flush()};Ro.prototype.push=function(r){this.emit("data",r)};Ro.prototype.end=function(r){this.decode(r),this.emit("end")}});var EL=v(DL=>{DL.createEncodeStream=ul;var Qne=require("util"),SL=require("stream").Transform,eoe=kh().EncodeBuffer;Qne.inherits(ul,SL);var toe={objectMode:!0};function ul(r){if(!(this instanceof ul))return new ul(r);r?r.objectMode=!0:r=toe,SL.call(this,r);var e=this,t=this.encoder=new eoe(r);t.push=function(i){e.push(i)}}ul.prototype._transform=function(r,e,t){this.encoder.write(r),t&&t()};ul.prototype._flush=function(r){this.encoder.flush(),r&&r()}});var PL=v(CL=>{CL.createDecodeStream=Hc;var roe=require("util"),_L=require("stream").Transform,ioe=Oh().DecodeBuffer;roe.inherits(Hc,_L);var noe={objectMode:!0};function Hc(r){if(!(this instanceof Hc))return new Hc(r);r?r.objectMode=!0:r=noe,_L.call(this,r);var e=this,t=this.decoder=new ioe(r);t.push=function(i){e.push(i)}}Hc.prototype._transform=function(r,e,t){this.decoder.write(r),this.decoder.flush(),t&&t()}});var RL=v(TL=>{Ah();Rh();TL.createCodec=jc().createCodec});var IL=v(kL=>{Ah();Rh();kL.codec={preset:jc().preset}});var FL=v(qn=>{qn.encode=cw().encode;qn.decode=yw().decode;qn.Encoder=yL().Encoder;qn.Decoder=xL().Decoder;qn.createEncodeStream=EL().createEncodeStream;qn.createDecodeStream=PL().createDecodeStream;qn.createCodec=RL().createCodec;qn.codec=IL().codec});var OL=v(_w=>{"use strict";Object.defineProperty(_w,"__esModule",{value:!0});var ooe=require("stream"),AL=class extends ooe.Transform{constructor(){super({readableHighWaterMark:10*1024*1024,writableHighWaterMark:10*1024*1024});this.chunks=null,this.timer=null}sendData(){let{chunks:e}=this;if(e){this.chunks=null;let t=Buffer.concat(e);this.push(t)}}_transform(e,t,i){let{chunks:n,timer:o}=this,s=Buffer.poolSize;if(o&&clearTimeout(o),e.length{"use strict";Object.defineProperty(Lh,"__esModule",{value:!0});Lh.BaseApi=void 0;var soe=require("events"),aoe=process.env.VIM_NODE_RPC=="1",LL=class extends soe.EventEmitter{constructor({transport:e,data:t,client:i}){super();this.setTransport(e),this.data=t,this.client=i}setTransport(e){this.transport=e}equals(e){try{return String(this.data)===String(e.data)}catch(t){return!1}}async request(e,t=[]){let i=Error().stack;return new Promise((n,o)=>{this.transport.request(e,this.getArgsByPrefix(t),(s,a)=>{if(s){let l=new Error(`request error ${e} - ${s[1]}`);l.stack=i,e.endsWith("get_var")||this.client.logError(`request error on "${e}"`,t,s[1],i),o(l)}else n(a)})})}getArgsByPrefix(e){return this.prefix!=="nvim_"&&e[0]!=this?[aoe?this.data:this,...e]:e}getVar(e){return this.request(`${this.prefix}get_var`,[e]).then(t=>t,t=>null)}setVar(e,t,i=!1){if(i){this.notify(`${this.prefix}set_var`,[e,t]);return}return this.request(`${this.prefix}set_var`,[e,t])}deleteVar(e){this.notify(`${this.prefix}del_var`,[e])}getOption(e){return this.request(`${this.prefix}get_option`,[e])}setOption(e,t,i){if(i){this.notify(`${this.prefix}set_option`,[e,t]);return}return this.request(`${this.prefix}set_option`,[e,t])}notify(e,t=[]){this.transport.notify(e,this.getArgsByPrefix(t))}};Lh.BaseApi=LL});var Gc=v(Mh=>{"use strict";Object.defineProperty(Mh,"__esModule",{value:!0});Mh.Buffer=void 0;var loe=zc(),ML=class extends loe.BaseApi{constructor(){super(...arguments);this.prefix="nvim_buf_"}async attach(e=!1,t={}){return await this.request(`${this.prefix}attach`,[e,t])}async detach(){return await this.request(`${this.prefix}detach`,[])}get id(){return this.data}get length(){return this.request(`${this.prefix}line_count`,[])}get lines(){return this.getLines()}get changedtick(){return this.request(`${this.prefix}get_changedtick`,[])}get commands(){return this.getCommands()}getCommands(e={}){return this.request(`${this.prefix}get_commands`,[e])}getLines({start:e,end:t,strictIndexing:i}={start:0,end:-1,strictIndexing:!0}){let n=typeof i=="undefined"?!0:i;return this.request(`${this.prefix}get_lines`,[e,t,n])}setLines(e,{start:t,end:i,strictIndexing:n}={strictIndexing:!0},o=!1){let s=typeof n=="undefined"?!0:n,a=typeof e=="string"?[e]:e,l=typeof i!="undefined"?i:t+1;return this[o?"notify":"request"](`${this.prefix}set_lines`,[t,l,s,a])}setVirtualText(e,t,i,n={}){return this.notify(`${this.prefix}set_virtual_text`,[e,t,i,n]),Promise.resolve(e)}insert(e,t){return this.setLines(e,{start:t,end:t,strictIndexing:!0})}replace(e,t){let i=typeof e=="string"?[e]:e;return this.setLines(i,{start:t,end:t+i.length,strictIndexing:!1})}remove(e,t,i=!1){return this.setLines([],{start:e,end:t,strictIndexing:i})}append(e){return this.setLines(e,{start:-1,end:-1,strictIndexing:!1})}get name(){return this.request(`${this.prefix}get_name`,[])}setName(e){return this.request(`${this.prefix}set_name`,[e])}get valid(){return this.request(`${this.prefix}is_valid`,[])}mark(e){return this.request(`${this.prefix}get_mark`,[e])}getKeymap(e){return this.request(`${this.prefix}get_keymap`,[e])}get loaded(){return this.request(`${this.prefix}is_loaded`,[])}getOffset(e){return this.request(`${this.prefix}get_offset`,[e])}addHighlight({hlGroup:e,line:t,colStart:i,colEnd:n,srcId:o}){if(!e)throw new Error("hlGroup should not empty");let s=typeof n!="undefined"?n:-1,a=typeof i!="undefined"?i:-0,l=typeof o!="undefined"?o:-1,u=l==0?"request":"notify",c=this[u](`${this.prefix}add_highlight`,[l,e,t,a,s]);return u==="request"?c:Promise.resolve(null)}clearHighlight(e={}){let t={srcId:-1,lineStart:0,lineEnd:-1},{srcId:i,lineStart:n,lineEnd:o}=Object.assign({},t,e);return this.notify(`${this.prefix}clear_highlight`,[i,n,o])}highlightRanges(e,t,i){this.client.call("coc#highlight#ranges",[this.id,e,t,i],!0)}clearNamespace(e,t=0,i=-1){this.client.call("coc#highlight#clear_highlight",[this.id,e,t,i])}listen(e,t,i){this.client.attachBufferEvent(this,e,t),i&&i.push({dispose:()=>{this.client.detachBufferEvent(this,e,t)}})}};Mh.Buffer=ML});var Vc=v(Nh=>{"use strict";Object.defineProperty(Nh,"__esModule",{value:!0});Nh.Window=void 0;var uoe=zc(),Pw=require("timers"),NL=class extends uoe.BaseApi{constructor(){super(...arguments);this.prefix="nvim_win_"}get id(){return this.data}get buffer(){return this.request(`${this.prefix}get_buf`,[])}get tabpage(){return this.request(`${this.prefix}get_tabpage`,[])}get cursor(){return this.request(`${this.prefix}get_cursor`,[])}setCursor(e,t=!1){return this[t?"notify":"request"](`${this.prefix}set_cursor`,[e])}get height(){return this.request(`${this.prefix}get_height`,[])}setHeight(e,t=!1){return this[t?"notify":"request"](`${this.prefix}set_height`,[e])}get width(){return this.request(`${this.prefix}get_width`,[])}setWidth(e,t=!1){return this[t?"notify":"request"](`${this.prefix}set_height`,[e])}get position(){return this.request(`${this.prefix}get_position`,[])}get row(){return this.request(`${this.prefix}get_position`,[]).then(e=>e[0])}get col(){return this.request(`${this.prefix}get_position`,[]).then(e=>e[1])}get valid(){return this.request(`${this.prefix}is_valid`,[])}get number(){return this.request(`${this.prefix}get_number`,[])}setConfig(e,t){return this[t?"notify":"request"](`${this.prefix}set_config`,[e])}getConfig(){return this.request(`${this.prefix}get_config`,[])}close(e,t){if(t){this.notify(`${this.prefix}close`,[e]);let i=0,n=setInterval(()=>{if(i==5)return Pw.clearInterval(n);this.request(`${this.prefix}is_valid`,[]).then(o=>{o?this.notify(`${this.prefix}close`,[e]):Pw.clearInterval(n)},()=>{Pw.clearInterval(n)}),i++},50);return null}return this.request(`${this.prefix}close`,[e])}highlightRanges(e,t,i=10,n){if(n){this.client.call("coc#highlight#match_ranges",[this.id,0,t,e,i],!0);return}return this.client.call("coc#highlight#match_ranges",[this.id,0,t,e,i])}clearMatchGroup(e){this.client.call("coc#highlight#clear_match_group",[this.id,e],!0)}clearMatches(e){this.client.call("coc#highlight#clear_matches",[this.id,e],!0)}};Nh.Window=NL});var Kc=v(qh=>{"use strict";Object.defineProperty(qh,"__esModule",{value:!0});qh.Tabpage=void 0;var coe=zc(),qL=class extends coe.BaseApi{constructor(){super(...arguments);this.prefix="nvim_tabpage_"}get windows(){return this.request(`${this.prefix}list_wins`,[])}get window(){return this.request(`${this.prefix}get_win`,[])}get valid(){return this.request(`${this.prefix}is_valid`,[])}get number(){return this.request(`${this.prefix}get_number`,[])}getOption(){throw new Error("Tabpage does not have `getOption`")}setOption(){throw new Error("Tabpage does not have `setOption`")}};qh.Tabpage=qL});var $L=v(Us=>{"use strict";Object.defineProperty(Us,"__esModule",{value:!0});Us.Metadata=Us.ExtType=void 0;var foe=Gc(),poe=Vc(),doe=Kc(),hoe;(function(r){r[r.Buffer=0]="Buffer",r[r.Window=1]="Window",r[r.Tabpage=2]="Tabpage"})(hoe=Us.ExtType||(Us.ExtType={}));Us.Metadata=[{constructor:foe.Buffer,name:"Buffer",prefix:"nvim_buf_"},{constructor:poe.Window,name:"Window",prefix:"nvim_win_"},{constructor:doe.Tabpage,name:"Tabpage",prefix:"nvim_tabpage_"}]});var Jc=v(cl=>{"use strict";var Tw=cl&&cl.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(cl,"__esModule",{value:!0});cl.createLogger=void 0;var Rw=Tw(require("fs")),moe=Tw(require("os")),kw=Tw(require("path"));function goe(){let r=process.env.NODE_CLIENT_LOG_FILE;if(r)return r;let e=process.env.XDG_RUNTIME_DIR;return e?kw.default.join(e,"node-client.log"):kw.default.join(moe.default.tmpdir(),`node-client-${process.pid}.log`)}var Iw=goe(),BL=process.env.NODE_CLIENT_LOG_LEVEL||"info",Fw=process.getuid&&process.getuid()==0;if(!Fw)try{Rw.default.mkdirSync(kw.default.dirname(Iw),{recursive:!0}),Rw.default.writeFileSync(Iw,"",{encoding:"utf8",mode:438})}catch(r){Fw=!0}function jL(r){return r==null?r:Array.isArray(r)?r.map(e=>jL(e)):typeof r=="object"&&typeof r.prefix=="string"&&typeof r.data=="number"?"["+r.prefix+r.data+"]":r}function voe(r){return r==null?String(r):typeof r=="object"?JSON.stringify(r,null,2):String(r)}var UL=class{constructor(e){this.name=e}get stream(){return Fw?null:this._stream?this._stream:(this._stream=Rw.default.createWriteStream(Iw,{encoding:"utf8"}),this._stream)}getText(e,t,i){let n="";if(i.length){let o=jL(i);n=" "+o.map(s=>voe(s))}return`${new Date().toLocaleTimeString()} ${e.toUpperCase()} [${this.name}] - ${t}${n} -`}debug(e,...t){BL!="debug"||this.stream==null||this.stream.write(this.getText("debug",e,t))}info(e,...t){this.stream!=null&&this.stream.write(this.getText("info",e,t))}error(e,...t){this.stream!=null&&this.stream.write(this.getText("error",e,t))}trace(e,...t){BL!="trace"||this.stream==null||this.stream.write(this.getText("trace",e,t))}};function yoe(r){return new UL(r)}cl.createLogger=yoe});var Ow=v(Aw=>{"use strict";Object.defineProperty(Aw,"__esModule",{value:!0});var boe=require("events"),woe=Jc(),WL=process.env.NODE_CLIENT_LOG_LEVEL=="debug",Yc=woe.createLogger("transport"),HL=class extends boe.EventEmitter{constructor(e){super();this.logger=e,this.pauseLevel=0,this.paused=new Map}debug(e,...t){!WL||Yc.debug(e,...t)}info(e,...t){Yc.info(e,...t)}debugMessage(e){if(!WL)return;let t=e[0];t==0?Yc.debug("receive request:",e.slice(1)):t==1||(t==2?Yc.debug("receive notification:",e.slice(1)):Yc.debug("unknown message:",e))}pauseNotification(){this.pauseLevel=this.pauseLevel+1,this.paused.set(this.pauseLevel,[])}cancelNotification(){let{pauseLevel:e}=this;e>0&&(this.paused.delete(e),this.pauseLevel=e-1)}resumeNotification(e=!1){let{pauseLevel:t}=this;if(t==0)return e?null:Promise.resolve([null,null]);let i=Error().stack;this.pauseLevel=t-1;let n=this.paused.get(t);return this.paused.delete(t),n&&n.length?new Promise((o,s)=>{if(!e)return this.request("nvim_call_atomic",[n],(a,l)=>{if(a){let u=new Error(`call_atomic error: ${a[1]}`);return u.stack=i,s(u)}if(Array.isArray(l)&&l[1]!=null){let[u,c,f]=l[1],[p,d]=n[u];this.logger.error(`request error ${c} on "${p}"`,d,f,i)}o(l)});this.notify("nvim_call_atomic",[n]),o()}):e?null:Promise.resolve([[],void 0])}};Aw.default=HL});var VL=v(vi=>{"use strict";var xoe=vi&&vi.__createBinding||(Object.create?function(r,e,t,i){i===void 0&&(i=t),Object.defineProperty(r,i,{enumerable:!0,get:function(){return e[t]}})}:function(r,e,t,i){i===void 0&&(i=t),r[i]=e[t]}),Doe=vi&&vi.__setModuleDefault||(Object.create?function(r,e){Object.defineProperty(r,"default",{enumerable:!0,value:e})}:function(r,e){r.default=e}),Soe=vi&&vi.__importStar||function(r){if(r&&r.__esModule)return r;var e={};if(r!=null)for(var t in r)t!=="default"&&Object.prototype.hasOwnProperty.call(r,t)&&xoe(e,r,t);return Doe(e,r),e},zL=vi&&vi.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(vi,"__esModule",{value:!0});vi.NvimTransport=void 0;var $n=Soe(FL()),Eoe=zL(OL()),Coe=$L(),_oe=zL(Ow()),GL=class extends _oe.default{constructor(e){super(e);this.pending=new Map,this.nextRequestId=1,this.attached=!1;let t=this.setupCodec();this.encodeStream=$n.createEncodeStream({codec:t}),this.decodeStream=$n.createDecodeStream({codec:t}),this.decodeStream.on("data",i=>{this.parseMessage(i)}),this.decodeStream.on("end",()=>{this.detach(),this.emit("detach")})}parseMessage(e){let t=e[0];if(this.debugMessage(e),t===0)this.emit("request",e[2].toString(),e[3],this.createResponse(e[1]));else if(t===1){let i=e[1],n=this.pending.get(i);if(n){this.pending.delete(i);let o=e[2];o&&o.length!=2&&(o=[0,o instanceof Error?o.message:o]),n(o,e[3])}}else t===2?this.emit("notification",e[1].toString(),e[2]):console.error(`Invalid message type ${t}`)}setupCodec(){let e=$n.createCodec();return Coe.Metadata.forEach(({constructor:t},i)=>{e.addExtPacker(i,t,n=>$n.encode(n.data)),e.addExtUnpacker(i,n=>new t({transport:this,client:this.client,data:$n.decode(n)}))}),this.codec=e,this.codec}attach(e,t,i){this.encodeStream=this.encodeStream.pipe(e);let n=new Eoe.default;t.pipe(n).pipe(this.decodeStream),this.writer=e,this.reader=t,this.client=i,this.attached=!0}detach(){!this.attached||(this.attached=!1,this.encodeStream.unpipe(this.writer),this.reader.unpipe(this.decodeStream))}request(e,t,i){if(!this.attached)return;let n=this.nextRequestId;this.nextRequestId=this.nextRequestId+1;let o=Date.now();this.debug("request to nvim:",n,e,t),this.encodeStream.write($n.encode([0,n,e,t],{codec:this.codec}));let s=Error().stack,a=setTimeout(()=>{this.debug(`request to vim blocked more than 1s: ${e}`,t,s)},1e3);this.pending.set(n,(l,u)=>{clearTimeout(a),this.debug("response of nvim:",n,`${Date.now()-o}ms`,u,l),i(l,u)})}notify(e,t){if(!!this.attached){if(this.pauseLevel!=0){let i=this.paused.get(this.pauseLevel);if(i){i.push([e,t]);return}}this.debug("nvim notification:",e,t),this.encodeStream.write($n.encode([2,e,t],{codec:this.codec}))}}send(e){this.encodeStream.write($n.encode(e,{codec:this.codec}))}createResponse(e){let{encodeStream:t}=this,i=Date.now(),n=!1,o=setTimeout(()=>{this.debug("request to client cost more than 1s",e)},1e3);return{send:(s,a)=>{clearTimeout(o),!(n||!this.attached)&&(this.debug("response of client:",e,`${Date.now()-i}ms`,s,a==!0),n=!0,t.write($n.encode([1,e,a?s:null,a?null:s])))}}}};vi.NvimTransport=GL});var YL=v(Xc=>{"use strict";var KL=Xc&&Xc.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(Xc,"__esModule",{value:!0});var Poe=KL(require("events")),Toe=KL(require("readline")),Roe=Jc(),fl=Roe.createLogger("connection"),S_e=process.env.NODE_CLIENT_LOG_LEVEL=="debug",JL=class extends Poe.default{constructor(e,t){super();this.readable=e,this.writeable=t;let i=Toe.default.createInterface(this.readable);i.on("line",n=>{this.parseData(n)}),i.on("close",()=>{fl.error("connection closed"),process.exit(0)})}parseData(e){if(e.length==0)return;let t;try{t=JSON.parse(e)}catch(o){console.error(`Invalid data from vim: ${e}`);return}let[i,n]=t;i>0?(fl.debug("received request:",i,n),this.emit("request",i,n)):i==0?(fl.debug("received notification:",n),this.emit("notification",n)):(fl.debug("received response:",i,n),this.emit("response",i,n))}response(e,t){this.send([e,t||null])}notify(e,t){this.send([0,[e,t||null]])}send(e){fl.debug("send to vim:",e);try{this.writeable.write(JSON.stringify(e)+` -`)}catch(t){fl.error("Send error:",e)}}redraw(e=!1){this.send(["redraw",e?"force":""])}commmand(e){this.send(["ex",e])}expr(e){this.send(["expr",e])}call(e,t,i){if(!i){this.send(["call",e,t]);return}this.send(["call",e,t,i])}dispose(){this.removeAllListeners()}};Xc.default=JL});var ZL=v(Lw=>{"use strict";Object.defineProperty(Lw,"__esModule",{value:!0});var koe=Jc(),Ioe=koe.createLogger("request"),Foe=process.env.NODE_CLIENT_LOG_LEVEL=="debug",Aoe=process.env.COC_NVIM=="1"?"coc#api#call":"nvim#api#call",XL=class{constructor(e,t,i){this.connection=e,this.cb=t,this.id=i}request(e,t=[]){this.method=e,this.args=t,this.connection.call(Aoe,[e.slice(5),t],this.id)}callback(e,t,i){let{method:n,cb:o}=this;if(Foe&&t&&Ioe.debug(`request ${this.method} error:`,t,this.args),t)return o([0,t.toString()]);switch(n){case"nvim_list_wins":case"nvim_tabpage_list_wins":return o(null,i.map(s=>e.createWindow(s)));case"nvim_tabpage_get_win":case"nvim_get_current_win":case"nvim_open_win":return o(null,e.createWindow(i));case"nvim_list_bufs":return o(null,i.map(s=>e.createBuffer(s)));case"nvim_win_get_buf":case"nvim_create_buf":case"nvim_get_current_buf":return o(null,e.createBuffer(i));case"nvim_list_tabpages":return o(null,i.map(s=>e.createTabpage(s)));case"nvim_get_current_tabpage":return o(null,e.createTabpage(i));default:return o(null,i)}}};Lw.default=XL});var eM=v(pl=>{"use strict";var Mw=pl&&pl.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(pl,"__esModule",{value:!0});pl.VimTransport=void 0;var Ooe=Mw(Ow()),Loe=Mw(YL()),Moe=Mw(ZL()),QL=class extends Ooe.default{constructor(e){super(e);this.pending=new Map,this.nextRequestId=-1,this.attached=!1,this.notifyMethod=process.env.COC_NVIM=="1"?"coc#api#notify":"nvim#api#notify"}attach(e,t,i){let n=this.connection=new Loe.default(t,e);this.attached=!0,this.client=i,n.on("request",(o,s)=>{let[a,l]=s;this.emit("request",a,l,this.createResponse(o))}),n.on("notification",o=>{let[s,a]=o;this.emit("notification",s.toString(),a)}),n.on("response",(o,s)=>{let a=this.pending.get(o);if(a){this.pending.delete(o);let l=null,u=null;Array.isArray(s)?(l=s[0],u=s[1]):l=s,a.callback(this.client,l,u)}})}send(e){this.connection.send(e)}detach(){!this.attached||(this.attached=!1,this.connection.dispose())}request(e,t,i){if(!this.attached)return i([0,"transport disconnected"]);let n=this.nextRequestId;this.nextRequestId=this.nextRequestId-1;let o=Date.now();this.debug("request to vim:",n,e,t);let s=setTimeout(()=>{this.debug("request to vim cost more than 1s",e,t)},1e3),a=new Moe.default(this.connection,(l,u)=>{clearTimeout(s),this.debug("response from vim cost:",n,`${Date.now()-o}ms`),i(l,u)},n);this.pending.set(n,a),a.request(e,t)}notify(e,t){if(!!this.attached){if(this.pauseLevel!=0){let i=this.paused.get(this.pauseLevel);if(i){i.push([e,t]);return}}this.connection.call(this.notifyMethod,[e.slice(5),t])}}createResponse(e){let t=!1,{connection:i}=this,n=Date.now(),o=setTimeout(()=>{this.debug("request to client cost more than 1s",e)},1e3);return{send:(s,a)=>{if(clearTimeout(o),t||!this.attached)return;t=!0;let l=null;a&&(l=typeof s=="string"?s:s.toString()),this.debug("response of client cost:",e,`${Date.now()-n}ms`),i.response(e,[l,a?null:s])}}}};pl.VimTransport=QL});var rM=v($h=>{"use strict";Object.defineProperty($h,"__esModule",{value:!0});$h.Neovim=void 0;var Noe=zc(),qoe=Gc(),$oe=Kc(),Boe=Vc(),joe=process.env.VIM_NODE_RPC=="1",tM=class extends Noe.BaseApi{constructor(){super(...arguments);this.prefix="nvim_",this.Buffer=qoe.Buffer,this.Window=Boe.Window,this.Tabpage=$oe.Tabpage}getArgs(e){return e?Array.isArray(e)?e:[e]:[]}get apiInfo(){return this.request(`${this.prefix}get_api_info`)}get buffers(){return this.request(`${this.prefix}list_bufs`)}get buffer(){return this.request(`${this.prefix}get_current_buf`)}async setBuffer(e){await this.request(`${this.prefix}set_current_buf`,[e])}get chans(){return this.request(`${this.prefix}list_chans`)}getChanInfo(e){return this.request(`${this.prefix}get_chan_info`,[e])}createNamespace(e=""){return this.request(`${this.prefix}create_namespace`,[e])}get namespaces(){return this.request(`${this.prefix}get_namespaces`,[])}get commands(){return this.getCommands()}getCommands(e={}){return this.request(`${this.prefix}get_commands`,[e])}get tabpages(){return this.request(`${this.prefix}list_tabpages`)}get tabpage(){return this.request(`${this.prefix}get_current_tabpage`)}async setTabpage(e){await this.request(`${this.prefix}set_current_tabpage`,[e])}get windows(){return this.getWindows()}get window(){return this.request(`${this.prefix}get_current_win`)}getWindows(){return this.request(`${this.prefix}list_wins`)}async setWindow(e){await this.request(`${this.prefix}set_current_win`,[e])}get runtimePaths(){return this.request(`${this.prefix}list_runtime_paths`)}setDirectory(e){return this.request(`${this.prefix}set_current_dir`,[e])}get line(){return this.getLine()}createNewBuffer(e=!1,t=!1){return this.request(`${this.prefix}create_buf`,[e,t])}openFloatWindow(e,t,i){return this.request(`${this.prefix}open_win`,[e,t,i])}getLine(){return this.request(`${this.prefix}get_current_line`)}setLine(e){return this.request(`${this.prefix}set_current_line`,[e])}getKeymap(e){return this.request(`${this.prefix}get_keymap`,[e])}get mode(){return this.request(`${this.prefix}get_mode`)}get colorMap(){return this.request(`${this.prefix}get_color_map`)}getColorByName(e){return this.request(`${this.prefix}get_color_by_name`,[e])}getHighlight(e,t=!0){let i=typeof e=="string"?"by_name":"by_id";return this.request(`${this.prefix}get_hl_${i}`,[e,t])}getHighlightByName(e,t=!0){return this.request(`${this.prefix}get_hl_by_name`,[e,t])}getHighlightById(e,t=!0){return this.request(`${this.prefix}get_hl_by_id`,[e,t])}deleteCurrentLine(){return this.request(`${this.prefix}del_current_line`)}eval(e){return this.request(`${this.prefix}eval`,[e])}lua(e,t=[]){let i=this.getArgs(t);return this.request(`${this.prefix}execute_lua`,[e,i])}executeLua(e,t=[]){return this.lua(e,t)}callDictFunction(e,t,i=[]){let n=this.getArgs(i);return this.request(`${this.prefix}call_dict_function`,[e,t,n])}call(e,t=[],i){let n=this.getArgs(t);return i?(this.notify(`${this.prefix}call_function`,[e,n]),null):this.request(`${this.prefix}call_function`,[e,n])}callTimer(e,t=[],i){let n=this.getArgs(t);return i?(this.notify(`${this.prefix}call_function`,["coc#util#timer",[e,n]]),null):joe?(this.notify(`${this.prefix}call_function`,["coc#util#timer",[e,n]]),new Promise(o=>{setTimeout(()=>{o(null)},20)})):this.request(`${this.prefix}call_function`,["coc#util#timer",[e,n]])}callAsync(e,t=[]){let i=this.getArgs(t);return this.client.sendAsyncRequest(e,i)}callFunction(e,t=[]){return this.call(e,t)}callAtomic(e){return this.request(`${this.prefix}call_atomic`,[e])}command(e,t){return t?(this.notify(`${this.prefix}command`,[e]),null):this.request(`${this.prefix}command`,[e])}commandOutput(e){return this.request(`${this.prefix}command_output`,[e])}getVvar(e){return this.request(`${this.prefix}get_vvar`,[e])}feedKeys(e,t,i){return this.request(`${this.prefix}feedkeys`,[e,t,i])}input(e){return this.request(`${this.prefix}input`,[e])}parseExpression(e,t,i){return this.request(`${this.prefix}parse_expression`,[e,t,i])}getProc(e){return this.request(`${this.prefix}get_proc`,[e])}getProcChildren(e){return this.request(`${this.prefix}get_proc_children`,[e])}replaceTermcodes(e,t,i,n){return this.request(`${this.prefix}replace_termcodes`,[e,t,i,n])}strWidth(e){return this.request(`${this.prefix}strwidth`,[e])}outWrite(e){this.notify(`${this.prefix}out_write`,[e])}outWriteLine(e){this.outWrite(`${e} -`)}errWrite(e){this.notify(`${this.prefix}err_write`,[e])}errWriteLine(e){this.notify(`${this.prefix}err_writeln`,[e])}get uis(){return this.request(`${this.prefix}list_uis`)}uiAttach(e,t,i){return this.request(`${this.prefix}ui_attach`,[e,t,i])}uiDetach(){return this.request(`${this.prefix}ui_detach`,[])}uiTryResize(e,t){return this.request(`${this.prefix}ui_try_resize`,[e,t])}uiSetOption(e,t){return this.request(`${this.prefix}ui_set_option`,[e,t])}subscribe(e){return this.request(`${this.prefix}subscribe`,[e])}unsubscribe(e){return this.request(`${this.prefix}unsubscribe`,[e])}setClientInfo(e,t,i,n,o){this.notify(`${this.prefix}set_client_info`,[e,t,i,n,o])}async quit(){this.command("qa!",!0),this.transport&&this.transport.detach()}};$h.Neovim=tM});var Bh=v(dl=>{"use strict";Object.defineProperty(dl,"__esModule",{value:!0});dl.NeovimClient=dl.AsyncResponse=void 0;var Uoe=VL(),Woe=eM(),Hoe=rM(),zoe=Gc(),Goe=Vc(),Voe=Kc(),Koe=Jc(),iM=Koe.createLogger("client"),Joe=process.env.VIM_NODE_RPC=="1",Nw=class{constructor(e,t){this.requestId=e,this.cb=t,this.finished=!1}finish(e,t){if(!this.finished){if(this.finished=!0,e){this.cb(new Error(e));return}this.cb(null,t)}}};dl.AsyncResponse=Nw;var nM=class extends Hoe.Neovim{constructor(e){super({});this.logger=e,this.requestId=1,this.responses=new Map,this.attachedBuffers=new Map,Object.defineProperty(this,"client",{value:this});let t=Joe?new Woe.VimTransport(e):new Uoe.NvimTransport(e);this.setTransport(t),this.transportAttached=!1,this.handleRequest=this.handleRequest.bind(this),this.handleNotification=this.handleNotification.bind(this)}logError(e,...t){!this.logger||this.logger.error(e,...t)}createBuffer(e){return new zoe.Buffer({transport:this.transport,data:e,client:this})}createWindow(e){return new Goe.Window({transport:this.transport,data:e,client:this})}createTabpage(e){return new Voe.Tabpage({transport:this.transport,data:e,client:this})}send(e){this.transport.send(e)}attach({reader:e,writer:t},i=!0){this.transport.attach(t,e,this),this.transportAttached=!0,this.setupTransport(i)}detach(){this.transport.detach(),this.transportAttached=!1}get isApiReady(){return this.transportAttached&&typeof this._channelId!="undefined"}get channelId(){return this._isReady.then(()=>this._channelId)}isAttached(e){return this.attachedBuffers.has(e)}handleRequest(e,t,i){this.emit("request",e,t,i)}sendAsyncRequest(e,t){let i=this.requestId;return this.requestId=i+1,this.notify("nvim_call_function",["coc#rpc#async_request",[i,e,t||[]]]),new Promise((n,o)=>{let s=new Nw(i,(a,l)=>{if(a)return o(a);n(l)});this.responses.set(i,s)})}emitNotification(e,t){if(e.endsWith("_event")){if(e.startsWith("nvim_buf_")){let i=e.replace(/nvim_buf_(.*)_event/,"$1"),{id:n}=t[0];if(!this.attachedBuffers.has(n))return;(this.attachedBuffers.get(n).get(i)||[]).forEach(a=>a(...t)),i==="detach"&&this.attachedBuffers.delete(n);return}if(e.startsWith("nvim_async_request")){let[i,n,o]=t;this.handleRequest(n,o,{send:(s,a)=>{this.notify("nvim_call_function",["coc#rpc#async_response",[i,s,a]])}})}if(e.startsWith("nvim_async_response")){let[i,n,o]=t,s=this.responses.get(i);if(!s){console.error(`Response not found for request ${i}`);return}this.responses.delete(i),s.finish(n,o);return}}else this.emit("notification",e,t)}handleNotification(e,t){this.emitNotification(e,t)}setupTransport(e=!0){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")}),e?this._isReady=this.generateApi():(this._channelId=0,this._isReady=Promise.resolve(!0))}requestApi(){return new Promise((e,t)=>{this.transport.request("nvim_get_api_info",[],(i,n)=>{i?t(new Error(Array.isArray(i)?i[1]:i.message||i.toString())):e(n)})})}async generateApi(){let e;try{e=await this.requestApi()}catch(t){console.error("Could not get vim api results"),iM.error(t)}if(e)try{let[t,i]=e;return this.functions=i.functions.map(n=>n.name),this._channelId=t,!0}catch(t){return iM.error(t.stack),null}return null}attachBufferEvent(e,t,i){let n=this.attachedBuffers.get(e.id)||new Map,o=n.get(t)||[];o.includes(i)||(o.push(i),n.set(t,o),this.attachedBuffers.set(e.id,n))}detachBufferEvent(e,t,i){let n=this.attachedBuffers.get(e.id);if(!n||!n.has(t))return;let o=n.get(t).filter(s=>s!==i);n.set(t,o)}pauseNotification(){this.transport.pauseNotification();let e=Error().stack;process.nextTick(()=>{this.transport.pauseLevel>0&&this.logError("resumeNotification not called within same tick:",e)})}resumeNotification(e,t){return e?Promise.resolve(this.transport.cancelNotification()):t?Promise.resolve(this.transport.resumeNotification(!0)):Promise.resolve(this.transport.resumeNotification())}hasFunction(e){return this.functions?this.functions.indexOf(e)!==-1:!0}};dl.NeovimClient=nM});var oM=v(jh=>{"use strict";Object.defineProperty(jh,"__esModule",{value:!0});jh.attach=void 0;var Yoe=require("net"),Xoe=Bh();function Zoe({reader:r,writer:e,proc:t,socket:i},n=null,o=!0){let s,a,l;if(i){let u=Yoe.createConnection(i);s=u,a=u,u.once("close",()=>{l.detach()})}else r&&e?(s=e,a=r):t&&(s=t.stdin,a=t.stdout,t.once("disconnect",()=>{l.detach()}));if(s.on("error",u=>{u.code=="EPIPE"&&l.detach()}),s&&a)return l=new Xoe.NeovimClient(n),l.attach({writer:s,reader:a},o),l;throw new Error("Invalid arguments, could not attach")}jh.attach=Zoe});var sM=v(yi=>{"use strict";Object.defineProperty(yi,"__esModule",{value:!0});yi.Tabpage=yi.Window=yi.Buffer=yi.NeovimClient=yi.Neovim=void 0;var Qoe=Bh();Object.defineProperty(yi,"Neovim",{enumerable:!0,get:function(){return Qoe.NeovimClient}});var ese=Bh();Object.defineProperty(yi,"NeovimClient",{enumerable:!0,get:function(){return ese.NeovimClient}});var tse=Gc();Object.defineProperty(yi,"Buffer",{enumerable:!0,get:function(){return tse.Buffer}});var rse=Vc();Object.defineProperty(yi,"Window",{enumerable:!0,get:function(){return rse.Window}});var ise=Kc();Object.defineProperty(yi,"Tabpage",{enumerable:!0,get:function(){return ise.Tabpage}})});var qw=v(Rr=>{"use strict";Object.defineProperty(Rr,"__esModule",{value:!0});Rr.Window=Rr.Tabpage=Rr.Buffer=Rr.NeovimClient=Rr.Neovim=Rr.attach=void 0;var nse=oM();Object.defineProperty(Rr,"attach",{enumerable:!0,get:function(){return nse.attach}});var Zc=sM();Object.defineProperty(Rr,"Neovim",{enumerable:!0,get:function(){return Zc.Neovim}});Object.defineProperty(Rr,"NeovimClient",{enumerable:!0,get:function(){return Zc.NeovimClient}});Object.defineProperty(Rr,"Buffer",{enumerable:!0,get:function(){return Zc.Buffer}});Object.defineProperty(Rr,"Tabpage",{enumerable:!0,get:function(){return Zc.Tabpage}});Object.defineProperty(Rr,"Window",{enumerable:!0,get:function(){return Zc.Window}})});var hl=v(Bn=>{"use strict";Object.defineProperty(Bn,"__esModule",{value:!0});function ose(r){return r===!0||r===!1}Bn.boolean=ose;function aM(r){return typeof r=="string"||r instanceof String}Bn.string=aM;function sse(r){return typeof r=="number"||r instanceof Number}Bn.number=sse;function ase(r){return r instanceof Error}Bn.error=ase;function lse(r){return typeof r=="function"}Bn.func=lse;function lM(r){return Array.isArray(r)}Bn.array=lM;function use(r){return lM(r)&&r.every(e=>aM(e))}Bn.stringArray=use});var FM=v(Me=>{"use strict";Object.defineProperty(Me,"__esModule",{value:!0});var Ws=hl(),uM;(function(r){r.ParseError=-32700,r.InvalidRequest=-32600,r.MethodNotFound=-32601,r.InvalidParams=-32602,r.InternalError=-32603,r.serverErrorStart=-32099,r.serverErrorEnd=-32e3,r.ServerNotInitialized=-32002,r.UnknownErrorCode=-32001,r.RequestCancelled=-32800,r.ContentModified=-32801,r.MessageWriteError=1,r.MessageReadError=2})(uM=Me.ErrorCodes||(Me.ErrorCodes={}));var Uh=class extends Error{constructor(e,t,i){super(t);this.code=Ws.number(e)?e:uM.UnknownErrorCode,this.data=i,Object.setPrototypeOf(this,Uh.prototype)}toJson(){return{code:this.code,message:this.message,data:this.data}}};Me.ResponseError=Uh;var st=class{constructor(e,t){this._method=e,this._numberOfParams=t}get method(){return this._method}get numberOfParams(){return this._numberOfParams}};Me.AbstractMessageType=st;var cM=class extends st{constructor(e){super(e,0)}};Me.RequestType0=cM;var fM=class extends st{constructor(e){super(e,1)}};Me.RequestType=fM;var pM=class extends st{constructor(e){super(e,1)}};Me.RequestType1=pM;var dM=class extends st{constructor(e){super(e,2)}};Me.RequestType2=dM;var hM=class extends st{constructor(e){super(e,3)}};Me.RequestType3=hM;var mM=class extends st{constructor(e){super(e,4)}};Me.RequestType4=mM;var gM=class extends st{constructor(e){super(e,5)}};Me.RequestType5=gM;var vM=class extends st{constructor(e){super(e,6)}};Me.RequestType6=vM;var yM=class extends st{constructor(e){super(e,7)}};Me.RequestType7=yM;var bM=class extends st{constructor(e){super(e,8)}};Me.RequestType8=bM;var wM=class extends st{constructor(e){super(e,9)}};Me.RequestType9=wM;var xM=class extends st{constructor(e){super(e,1);this._=void 0}};Me.NotificationType=xM;var DM=class extends st{constructor(e){super(e,0)}};Me.NotificationType0=DM;var SM=class extends st{constructor(e){super(e,1)}};Me.NotificationType1=SM;var EM=class extends st{constructor(e){super(e,2)}};Me.NotificationType2=EM;var CM=class extends st{constructor(e){super(e,3)}};Me.NotificationType3=CM;var _M=class extends st{constructor(e){super(e,4)}};Me.NotificationType4=_M;var PM=class extends st{constructor(e){super(e,5)}};Me.NotificationType5=PM;var TM=class extends st{constructor(e){super(e,6)}};Me.NotificationType6=TM;var RM=class extends st{constructor(e){super(e,7)}};Me.NotificationType7=RM;var kM=class extends st{constructor(e){super(e,8)}};Me.NotificationType8=kM;var IM=class extends st{constructor(e){super(e,9)}};Me.NotificationType9=IM;function cse(r){let e=r;return e&&Ws.string(e.method)&&(Ws.string(e.id)||Ws.number(e.id))}Me.isRequestMessage=cse;function fse(r){let e=r;return e&&Ws.string(e.method)&&r.id===void 0}Me.isNotificationMessage=fse;function pse(r){let e=r;return e&&(e.result!==void 0||!!e.error)&&(Ws.string(e.id)||Ws.number(e.id)||e.id===null)}Me.isResponseMessage=pse});var ef=v(Hs=>{"use strict";Object.defineProperty(Hs,"__esModule",{value:!0});var dse;(function(r){function e(t){return{dispose:t}}r.create=e})(dse=Hs.Disposable||(Hs.Disposable={}));var hse;(function(r){let e={dispose(){}};r.None=function(){return e}})(hse=Hs.Event||(Hs.Event={}));var AM=class{add(e,t=null,i){this._callbacks||(this._callbacks=[],this._contexts=[]),this._callbacks.push(e),this._contexts.push(t),Array.isArray(i)&&i.push({dispose:()=>this.remove(e,t)})}remove(e,t=null){if(!!this._callbacks){for(var i=!1,n=0,o=this._callbacks.length;n{this._callbacks||(this._callbacks=new AM),this._options&&this._options.onFirstListenerAdd&&this._callbacks.isEmpty()&&this._options.onFirstListenerAdd(this),this._callbacks.add(e,t);let n;return n={dispose:()=>{this._callbacks.remove(e,t),n.dispose=Qc._noop,this._options&&this._options.onLastListenerRemove&&this._callbacks.isEmpty()&&this._options.onLastListenerRemove(this)}},Array.isArray(i)&&i.push(n),n}),this._event}fire(e){this._callbacks&&this._callbacks.invoke.call(this._callbacks,e)}dispose(){this._callbacks&&(this._callbacks.dispose(),this._callbacks=void 0)}};Hs.Emitter=Qc;Qc._noop=function(){}});var Hh=v(ko=>{"use strict";Object.defineProperty(ko,"__esModule",{value:!0});var $w=ef(),ml=hl(),Bw=8192,OM=Buffer.from("\r","ascii")[0],LM=Buffer.from(` -`,"ascii")[0],mse=`\r -`,MM=class{constructor(e="utf8"){this.encoding=e,this.index=0,this.buffer=Buffer.allocUnsafe(Bw)}append(e){var t=e;if(typeof e=="string"){var i=e,n=Buffer.byteLength(i,this.encoding);t=Buffer.allocUnsafe(n),t.write(i,0,n,this.encoding)}if(this.buffer.length-this.index>=t.length)t.copy(this.buffer,this.index,0,t.length);else{var o=(Math.ceil((this.index+t.length)/Bw)+1)*Bw;this.index===0?(this.buffer=Buffer.allocUnsafe(o),t.copy(this.buffer,0,0,t.length)):this.buffer=Buffer.concat([this.buffer.slice(0,this.index),t],o)}this.index+=t.length}tryReadHeaders(){let e,t=0;for(;t+3=this.index)return e;e=Object.create(null),this.buffer.toString("ascii",0,t).split(mse).forEach(o=>{let s=o.indexOf(":");if(s===-1)throw new Error("Message header must separate key and value using :");let a=o.substr(0,s),l=o.substr(s+1).trim();e[a]=l});let n=t+4;return this.buffer=this.buffer.slice(n),this.index=this.index-n,e}tryReadContent(e){if(this.index{this.onData(t)}),this.readable.on("error",t=>this.fireError(t)),this.readable.on("close",()=>this.fireClose())}onData(e){for(this.buffer.append(e);;){if(this.nextMessageLength===-1){let n=this.buffer.tryReadHeaders();if(!n)return;let o=n["Content-Length"];if(!o)throw new Error("Header must provide a Content-Length property.");let s=parseInt(o);if(isNaN(s))throw new Error("Content-Length value must be a number.");this.nextMessageLength=s}var t=this.buffer.tryReadContent(this.nextMessageLength);if(t===null){this.setPartialMessageTimer();return}this.clearPartialMessageTimer(),this.nextMessageLength=-1,this.messageToken++;var i=JSON.parse(t);this.callback(i)}}clearPartialMessageTimer(){this.partialMessageTimer&&(clearTimeout(this.partialMessageTimer),this.partialMessageTimer=void 0)}setPartialMessageTimer(){this.clearPartialMessageTimer(),!(this._partialMessageTimeout<=0)&&(this.partialMessageTimer=setTimeout((e,t)=>{this.partialMessageTimer=void 0,e===this.messageToken&&(this.firePartialMessage({messageToken:e,waitingTime:t}),this.setPartialMessageTimer())},this._partialMessageTimeout,this.messageToken,this._partialMessageTimeout))}};ko.StreamMessageReader=jw;var NM=class extends Wh{constructor(e){super();this.process=e;let t=this.process;t.on("error",i=>this.fireError(i)),t.on("close",()=>this.fireClose())}listen(e){this.process.on("message",e)}};ko.IPCMessageReader=NM;var qM=class extends jw{constructor(e,t="utf-8"){super(e,t)}};ko.SocketMessageReader=qM});var Gh=v(Io=>{"use strict";Object.defineProperty(Io,"__esModule",{value:!0});var $M=ef(),tf=hl(),BM="Content-Length: ",zh=`\r -`,vse;(function(r){function e(t){let i=t;return i&&tf.func(i.dispose)&&tf.func(i.onClose)&&tf.func(i.onError)&&tf.func(i.write)}r.is=e})(vse=Io.MessageWriter||(Io.MessageWriter={}));var rf=class{constructor(){this.errorEmitter=new $M.Emitter,this.closeEmitter=new $M.Emitter}dispose(){this.errorEmitter.dispose(),this.closeEmitter.dispose()}get onError(){return this.errorEmitter.event}fireError(e,t,i){this.errorEmitter.fire([this.asError(e),t,i])}get onClose(){return this.closeEmitter.event}fireClose(){this.closeEmitter.fire(void 0)}asError(e){return e instanceof Error?e:new Error(`Writer received error. Reason: ${tf.string(e.message)?e.message:"unknown"}`)}};Io.AbstractMessageWriter=rf;var jM=class extends rf{constructor(e,t="utf8"){super();this.writable=e,this.encoding=t,this.errorCount=0,this.writable.on("error",i=>this.fireError(i)),this.writable.on("close",()=>this.fireClose())}write(e){let t=JSON.stringify(e),i=Buffer.byteLength(t,this.encoding),n=[BM,i.toString(),zh,zh];try{this.writable.write(n.join(""),"ascii"),this.writable.write(t,this.encoding),this.errorCount=0}catch(o){this.errorCount++,this.fireError(o,e,this.errorCount)}}};Io.StreamMessageWriter=jM;var UM=class extends rf{constructor(e){super();this.process=e,this.errorCount=0,this.queue=[],this.sending=!1;let t=this.process;t.on("error",i=>this.fireError(i)),t.on("close",()=>this.fireClose)}write(e){!this.sending&&this.queue.length===0?this.doWriteMessage(e):this.queue.push(e)}doWriteMessage(e){try{this.process.send&&(this.sending=!0,this.process.send(e,void 0,void 0,t=>{this.sending=!1,t?(this.errorCount++,this.fireError(t,e,this.errorCount)):this.errorCount=0,this.queue.length>0&&this.doWriteMessage(this.queue.shift())}))}catch(t){this.errorCount++,this.fireError(t,e,this.errorCount)}}};Io.IPCMessageWriter=UM;var WM=class extends rf{constructor(e,t="utf8"){super();this.socket=e,this.queue=[],this.sending=!1,this.encoding=t,this.errorCount=0,this.socket.on("error",i=>this.fireError(i)),this.socket.on("close",()=>this.fireClose())}dispose(){super.dispose(),this.socket.destroy()}write(e){!this.sending&&this.queue.length===0?this.doWriteMessage(e):this.queue.push(e)}doWriteMessage(e){let t=JSON.stringify(e),i=Buffer.byteLength(t,this.encoding),n=[BM,i.toString(),zh,zh];try{this.sending=!0,this.socket.write(n.join(""),"ascii",o=>{o&&this.handleError(o,e);try{this.socket.write(t,this.encoding,s=>{this.sending=!1,s?this.handleError(s,e):this.errorCount=0,this.queue.length>0&&this.doWriteMessage(this.queue.shift())})}catch(s){this.handleError(s,e)}})}catch(o){this.handleError(o,e)}}handleError(e,t){this.errorCount++,this.fireError(e,t,this.errorCount)}};Io.SocketMessageWriter=WM});var zM=v(nf=>{"use strict";Object.defineProperty(nf,"__esModule",{value:!0});var Uw=ef(),yse=hl(),Ww;(function(r){r.None=Object.freeze({isCancellationRequested:!1,onCancellationRequested:Uw.Event.None}),r.Cancelled=Object.freeze({isCancellationRequested:!0,onCancellationRequested:Uw.Event.None});function e(t){let i=t;return i&&(i===r.None||i===r.Cancelled||yse.boolean(i.isCancellationRequested)&&!!i.onCancellationRequested)}r.is=e})(Ww=nf.CancellationToken||(nf.CancellationToken={}));var bse=Object.freeze(function(r,e){let t=setTimeout(r.bind(e),0);return{dispose(){clearTimeout(t)}}}),Hw=class{constructor(){this._isCancelled=!1}cancel(){this._isCancelled||(this._isCancelled=!0,this._emitter&&(this._emitter.fire(void 0),this.dispose()))}get isCancellationRequested(){return this._isCancelled}get onCancellationRequested(){return this._isCancelled?bse:(this._emitter||(this._emitter=new Uw.Emitter),this._emitter.event)}dispose(){this._emitter&&(this._emitter.dispose(),this._emitter=void 0)}},HM=class{get token(){return this._token||(this._token=new Hw),this._token}cancel(){this._token?this._token.cancel():this._token=Ww.Cancelled}dispose(){this._token?this._token instanceof Hw&&this._token.dispose():this._token=Ww.None}};nf.CancellationTokenSource=HM});var VM=v(of=>{"use strict";Object.defineProperty(of,"__esModule",{value:!0});var dn;(function(r){r.None=0,r.First=1,r.Last=2})(dn=of.Touch||(of.Touch={}));var GM=class{constructor(){this._map=new Map,this._head=void 0,this._tail=void 0,this._size=0}clear(){this._map.clear(),this._head=void 0,this._tail=void 0,this._size=0}isEmpty(){return!this._head&&!this._tail}get size(){return this._size}has(e){return this._map.has(e)}get(e){let t=this._map.get(e);if(!!t)return t.value}set(e,t,i=dn.None){let n=this._map.get(e);if(n)n.value=t,i!==dn.None&&this.touch(n,i);else{switch(n={key:e,value:t,next:void 0,previous:void 0},i){case dn.None:this.addItemLast(n);break;case dn.First:this.addItemFirst(n);break;case dn.Last:this.addItemLast(n);break;default:this.addItemLast(n);break}this._map.set(e,n),this._size++}}delete(e){let t=this._map.get(e);return t?(this._map.delete(e),this.removeItem(t),this._size--,!0):!1}shift(){if(!this._head&&!this._tail)return;if(!this._head||!this._tail)throw new Error("Invalid list");let e=this._head;return this._map.delete(e.key),this.removeItem(e),this._size--,e.value}forEach(e,t){let i=this._head;for(;i;)t?e.bind(t)(i.value,i.key,this):e(i.value,i.key,this),i=i.next}forEachReverse(e,t){let i=this._tail;for(;i;)t?e.bind(t)(i.value,i.key,this):e(i.value,i.key,this),i=i.previous}values(){let e=[],t=this._head;for(;t;)e.push(t.value),t=t.next;return e}keys(){let e=[],t=this._head;for(;t;)e.push(t.key),t=t.next;return e}addItemFirst(e){if(!this._head&&!this._tail)this._tail=e;else if(this._head)e.next=this._head,this._head.previous=e;else throw new Error("Invalid list");this._head=e}addItemLast(e){if(!this._head&&!this._tail)this._head=e;else if(this._tail)e.previous=this._tail,this._tail.next=e;else throw new Error("Invalid list");this._tail=e}removeItem(e){if(e===this._head&&e===this._tail)this._head=void 0,this._tail=void 0;else if(e===this._head)this._head=e.next;else if(e===this._tail)this._tail=e.previous;else{let t=e.next,i=e.previous;if(!t||!i)throw new Error("Invalid list");t.previous=i,i.next=t}}touch(e,t){if(!this._head||!this._tail)throw new Error("Invalid list");if(!(t!==dn.First&&t!==dn.Last)){if(t===dn.First){if(e===this._head)return;let i=e.next,n=e.previous;e===this._tail?(n.next=void 0,this._tail=n):(i.previous=n,n.next=i),e.previous=void 0,e.next=this._head,this._head.previous=e,this._head=e}else if(t===dn.Last){if(e===this._tail)return;let i=e.next,n=e.previous;e===this._head?(i.previous=void 0,this._head=i):(i.previous=n,n.next=i),e.next=void 0,e.previous=this._tail,this._tail.next=e,this._tail=e}}}};of.LinkedMap=GM});var XM=v(sf=>{"use strict";Object.defineProperty(sf,"__esModule",{value:!0});var wse=require("path"),xse=require("os"),Dse=require("crypto"),KM=require("net"),JM=Hh(),YM=Gh();function Sse(){let r=Dse.randomBytes(21).toString("hex");return process.platform==="win32"?`\\\\.\\pipe\\vscode-jsonrpc-${r}-sock`:wse.join(xse.tmpdir(),`vscode-${r}.sock`)}sf.generateRandomPipeName=Sse;function Ese(r,e="utf-8"){let t,i=new Promise((n,o)=>{t=n});return new Promise((n,o)=>{let s=KM.createServer(a=>{s.close(),t([new JM.SocketMessageReader(a,e),new YM.SocketMessageWriter(a,e)])});s.on("error",o),s.listen(r,()=>{s.removeListener("error",o),n({onConnected:()=>i})})})}sf.createClientPipeTransport=Ese;function Cse(r,e="utf-8"){let t=KM.createConnection(r);return[new JM.SocketMessageReader(t,e),new YM.SocketMessageWriter(t,e)]}sf.createServerPipeTransport=Cse});var tN=v(Vh=>{"use strict";Object.defineProperty(Vh,"__esModule",{value:!0});var ZM=require("net"),QM=Hh(),eN=Gh();function _se(r,e="utf-8"){let t,i=new Promise((n,o)=>{t=n});return new Promise((n,o)=>{let s=ZM.createServer(a=>{s.close(),t([new QM.SocketMessageReader(a,e),new eN.SocketMessageWriter(a,e)])});s.on("error",o),s.listen(r,"127.0.0.1",()=>{s.removeListener("error",o),n({onConnected:()=>i})})})}Vh.createClientSocketTransport=_se;function Pse(r,e="utf-8"){let t=ZM.createConnection(r,"127.0.0.1");return[new QM.SocketMessageReader(t,e),new eN.SocketMessageWriter(t,e)]}Vh.createServerSocketTransport=Pse});var bi=v(Q=>{"use strict";function rN(r){for(var e in r)Q.hasOwnProperty(e)||(Q[e]=r[e])}Object.defineProperty(Q,"__esModule",{value:!0});var Ut=hl(),ne=FM();Q.RequestType=ne.RequestType;Q.RequestType0=ne.RequestType0;Q.RequestType1=ne.RequestType1;Q.RequestType2=ne.RequestType2;Q.RequestType3=ne.RequestType3;Q.RequestType4=ne.RequestType4;Q.RequestType5=ne.RequestType5;Q.RequestType6=ne.RequestType6;Q.RequestType7=ne.RequestType7;Q.RequestType8=ne.RequestType8;Q.RequestType9=ne.RequestType9;Q.ResponseError=ne.ResponseError;Q.ErrorCodes=ne.ErrorCodes;Q.NotificationType=ne.NotificationType;Q.NotificationType0=ne.NotificationType0;Q.NotificationType1=ne.NotificationType1;Q.NotificationType2=ne.NotificationType2;Q.NotificationType3=ne.NotificationType3;Q.NotificationType4=ne.NotificationType4;Q.NotificationType5=ne.NotificationType5;Q.NotificationType6=ne.NotificationType6;Q.NotificationType7=ne.NotificationType7;Q.NotificationType8=ne.NotificationType8;Q.NotificationType9=ne.NotificationType9;var af=Hh();Q.MessageReader=af.MessageReader;Q.StreamMessageReader=af.StreamMessageReader;Q.IPCMessageReader=af.IPCMessageReader;Q.SocketMessageReader=af.SocketMessageReader;var lf=Gh();Q.MessageWriter=lf.MessageWriter;Q.StreamMessageWriter=lf.StreamMessageWriter;Q.IPCMessageWriter=lf.IPCMessageWriter;Q.SocketMessageWriter=lf.SocketMessageWriter;var Fo=ef();Q.Disposable=Fo.Disposable;Q.Event=Fo.Event;Q.Emitter=Fo.Emitter;var gl=zM();Q.CancellationTokenSource=gl.CancellationTokenSource;Q.CancellationToken=gl.CancellationToken;var iN=VM();rN(XM());rN(tN());var uf;(function(r){r.type=new ne.NotificationType("$/cancelRequest")})(uf||(uf={}));var Kh;(function(r){r.type=new ne.NotificationType("$/progress")})(Kh||(Kh={}));var nN=class{constructor(){}};Q.ProgressType=nN;Q.NullLogger=Object.freeze({error:()=>{},warn:()=>{},info:()=>{},log:()=>{}});var bt;(function(r){r[r.Off=0]="Off",r[r.Messages=1]="Messages",r[r.Verbose=2]="Verbose"})(bt=Q.Trace||(Q.Trace={}));(function(r){function e(i){if(!Ut.string(i))return r.Off;switch(i=i.toLowerCase(),i){case"off":return r.Off;case"messages":return r.Messages;case"verbose":return r.Verbose;default:return r.Off}}r.fromString=e;function t(i){switch(i){case r.Off:return"off";case r.Messages:return"messages";case r.Verbose:return"verbose";default:return"off"}}r.toString=t})(bt=Q.Trace||(Q.Trace={}));var ji;(function(r){r.Text="text",r.JSON="json"})(ji=Q.TraceFormat||(Q.TraceFormat={}));(function(r){function e(t){return t=t.toLowerCase(),t==="json"?r.JSON:r.Text}r.fromString=e})(ji=Q.TraceFormat||(Q.TraceFormat={}));var oN;(function(r){r.type=new ne.NotificationType("$/setTraceNotification")})(oN=Q.SetTraceNotification||(Q.SetTraceNotification={}));var zw;(function(r){r.type=new ne.NotificationType("$/logTraceNotification")})(zw=Q.LogTraceNotification||(Q.LogTraceNotification={}));var Jh;(function(r){r[r.Closed=1]="Closed",r[r.Disposed=2]="Disposed",r[r.AlreadyListening=3]="AlreadyListening"})(Jh=Q.ConnectionErrors||(Q.ConnectionErrors={}));var zs=class extends Error{constructor(e,t){super(t);this.code=e,Object.setPrototypeOf(this,zs.prototype)}};Q.ConnectionError=zs;var Tse;(function(r){function e(t){let i=t;return i&&Ut.func(i.cancelUndispatched)}r.is=e})(Tse=Q.ConnectionStrategy||(Q.ConnectionStrategy={}));var Ui;(function(r){r[r.New=1]="New",r[r.Listening=2]="Listening",r[r.Closed=3]="Closed",r[r.Disposed=4]="Disposed"})(Ui||(Ui={}));function Rse(r,e,t,i){let n=0,o=0,s=0,a="2.0",l,u=Object.create(null),c,f=Object.create(null),p=new Map,d,h=new iN.LinkedMap,m=Object.create(null),y=Object.create(null),g=bt.Off,w=ji.Text,x,E=Ui.New,P=new Fo.Emitter,k=new Fo.Emitter,_=new Fo.Emitter,L=new Fo.Emitter,I=new Fo.Emitter;function O(T){return"req-"+T.toString()}function R(T){return T===null?"res-unknown-"+(++s).toString():"res-"+T.toString()}function F(){return"not-"+(++o).toString()}function q(T,j){ne.isRequestMessage(j)?T.set(O(j.id),j):ne.isResponseMessage(j)?T.set(R(j.id),j):T.set(F(),j)}function K(T){}function ae(){return E===Ui.Listening}function Pe(){return E===Ui.Closed}function We(){return E===Ui.Disposed}function Yt(){(E===Ui.New||E===Ui.Listening)&&(E=Ui.Closed,k.fire(void 0))}function qt(T){P.fire([T,void 0,void 0])}function hr(T){P.fire(T)}r.onClose(Yt),r.onError(qt),e.onClose(Yt),e.onError(hr);function kn(){d||h.size===0||(d=setImmediate(()=>{d=void 0,In()}))}function In(){if(h.size===0)return;let T=h.shift();try{ne.isRequestMessage(T)?Cd(T):ne.isNotificationMessage(T)?Oa(T):ne.isResponseMessage(T)?Ry(T):La(T)}finally{kn()}}let Ty=T=>{try{if(ne.isNotificationMessage(T)&&T.method===uf.type.method){let j=O(T.params.id),V=h.get(j);if(ne.isRequestMessage(V)){let te=i&&i.cancelUndispatched?i.cancelUndispatched(V,K):K(V);if(te&&(te.error!==void 0||te.result!==void 0)){h.delete(j),te.id=V.id,fe(te,T.method,Date.now()),e.write(te);return}}}q(h,T)}finally{kn()}};function Cd(T){if(We())return;function j(rt,mr,it){let Zt={jsonrpc:a,id:T.id};rt instanceof ne.ResponseError?Zt.error=rt.toJson():Zt.result=rt===void 0?null:rt,fe(Zt,mr,it),e.write(Zt)}function V(rt,mr,it){let Zt={jsonrpc:a,id:T.id,error:rt.toJson()};fe(Zt,mr,it),e.write(Zt)}function te(rt,mr,it){rt===void 0&&(rt=null);let Zt={jsonrpc:a,id:T.id,result:rt};fe(Zt,mr,it),e.write(Zt)}Ee(T);let et=u[T.method],si,ln;et&&(si=et.type,ln=et.handler);let _t=Date.now();if(ln||l){let rt=new gl.CancellationTokenSource,mr=String(T.id);y[mr]=rt;try{let it;T.params===void 0||si!==void 0&&si.numberOfParams===0?it=ln?ln(rt.token):l(T.method,rt.token):Ut.array(T.params)&&(si===void 0||si.numberOfParams>1)?it=ln?ln(...T.params,rt.token):l(T.method,...T.params,rt.token):it=ln?ln(T.params,rt.token):l(T.method,T.params,rt.token);let Zt=it;it?Zt.then?Zt.then(vs=>{delete y[mr],j(vs,T.method,_t)},vs=>{delete y[mr],vs instanceof ne.ResponseError?V(vs,T.method,_t):vs&&Ut.string(vs.message)?V(new ne.ResponseError(ne.ErrorCodes.InternalError,`Request ${T.method} failed with message: ${vs.message}`),T.method,_t):V(new ne.ResponseError(ne.ErrorCodes.InternalError,`Request ${T.method} failed unexpectedly without providing any details.`),T.method,_t)}):(delete y[mr],j(it,T.method,_t)):(delete y[mr],te(it,T.method,_t))}catch(it){delete y[mr],it instanceof ne.ResponseError?j(it,T.method,_t):it&&Ut.string(it.message)?V(new ne.ResponseError(ne.ErrorCodes.InternalError,`Request ${T.method} failed with message: ${it.message}`),T.method,_t):V(new ne.ResponseError(ne.ErrorCodes.InternalError,`Request ${T.method} failed unexpectedly without providing any details.`),T.method,_t)}}else V(new ne.ResponseError(ne.ErrorCodes.MethodNotFound,`Unhandled method ${T.method}`),T.method,_t)}function Ry(T){if(!We())if(T.id===null)T.error?t.error(`Received response message without id: Error is: -${JSON.stringify(T.error,void 0,4)}`):t.error("Received response message without id. No further error information provided.");else{let j=String(T.id),V=m[j];if(Oi(T,V),V){delete m[j];try{if(T.error){let te=T.error;V.reject(new ne.ResponseError(te.code,te.message,te.data))}else if(T.result!==void 0)V.resolve(T.result);else throw new Error("Should never happen.")}catch(te){te.message?t.error(`Response handler '${V.method}' failed with message: ${te.message}`):t.error(`Response handler '${V.method}' failed unexpectedly.`)}}}}function Oa(T){if(We())return;let j,V;if(T.method===uf.type.method)V=te=>{let et=te.id,si=y[String(et)];si&&si.cancel()};else{let te=f[T.method];te&&(V=te.handler,j=te.type)}if(V||c)try{Ct(T),T.params===void 0||j!==void 0&&j.numberOfParams===0?V?V():c(T.method):Ut.array(T.params)&&(j===void 0||j.numberOfParams>1)?V?V(...T.params):c(T.method,...T.params):V?V(T.params):c(T.method,T.params)}catch(te){te.message?t.error(`Notification handler '${T.method}' failed with message: ${te.message}`):t.error(`Notification handler '${T.method}' failed unexpectedly.`)}else _.fire(T)}function La(T){if(!T){t.error("Received empty message.");return}t.error(`Received message which is neither a response nor a notification message: -${JSON.stringify(T,null,4)}`);let j=T;if(Ut.string(j.id)||Ut.number(j.id)){let V=String(j.id),te=m[V];te&&te.reject(new Error("The received response has neither a result nor an error property."))}}function Se(T){if(!(g===bt.Off||!x))if(w===ji.Text){let j;g===bt.Verbose&&T.params&&(j=`Params: ${JSON.stringify(T.params,null,4)} - -`),x.log(`Sending request '${T.method} - (${T.id})'.`,j)}else Xt("send-request",T)}function ve(T){if(!(g===bt.Off||!x))if(w===ji.Text){let j;g===bt.Verbose&&(T.params?j=`Params: ${JSON.stringify(T.params,null,4)} - -`:j=`No parameters provided. - -`),x.log(`Sending notification '${T.method}'.`,j)}else Xt("send-notification",T)}function fe(T,j,V){if(!(g===bt.Off||!x))if(w===ji.Text){let te;g===bt.Verbose&&(T.error&&T.error.data?te=`Error data: ${JSON.stringify(T.error.data,null,4)} - -`:T.result?te=`Result: ${JSON.stringify(T.result,null,4)} - -`:T.error===void 0&&(te=`No result returned. - -`)),x.log(`Sending response '${j} - (${T.id})'. Processing request took ${Date.now()-V}ms`,te)}else Xt("send-response",T)}function Ee(T){if(!(g===bt.Off||!x))if(w===ji.Text){let j;g===bt.Verbose&&T.params&&(j=`Params: ${JSON.stringify(T.params,null,4)} - -`),x.log(`Received request '${T.method} - (${T.id})'.`,j)}else Xt("receive-request",T)}function Ct(T){if(!(g===bt.Off||!x||T.method===zw.type.method))if(w===ji.Text){let j;g===bt.Verbose&&(T.params?j=`Params: ${JSON.stringify(T.params,null,4)} - -`:j=`No parameters provided. - -`),x.log(`Received notification '${T.method}'.`,j)}else Xt("receive-notification",T)}function Oi(T,j){if(!(g===bt.Off||!x))if(w===ji.Text){let V;if(g===bt.Verbose&&(T.error&&T.error.data?V=`Error data: ${JSON.stringify(T.error.data,null,4)} - -`:T.result?V=`Result: ${JSON.stringify(T.result,null,4)} - -`:T.error===void 0&&(V=`No result returned. - -`)),j){let te=T.error?` Request failed: ${T.error.message} (${T.error.code}).`:"";x.log(`Received response '${j.method} - (${T.id})' in ${Date.now()-j.timerStart}ms.${te}`,V)}else x.log(`Received response ${T.id} without active response promise.`,V)}else Xt("receive-response",T)}function Xt(T,j){if(!x||g===bt.Off)return;let V={isLSPMessage:!0,type:T,message:j,timestamp:Date.now()};x.log(V)}function $t(){if(Pe())throw new zs(Jh.Closed,"Connection is closed.");if(We())throw new zs(Jh.Disposed,"Connection is disposed.")}function ky(){if(ae())throw new zs(Jh.AlreadyListening,"Connection is already listening")}function _d(){if(!ae())throw new Error("Call listen() first.")}function Ma(T){return T===void 0?null:T}function BP(T,j){let V,te=T.numberOfParams;switch(te){case 0:V=null;break;case 1:V=Ma(j[0]);break;default:V=[];for(let et=0;et{$t();let V,te;if(Ut.string(T))switch(V=T,j.length){case 0:te=null;break;case 1:te=j[0];break;default:te=j;break}else V=T.method,te=BP(T,j);let et={jsonrpc:a,method:V,params:te};ve(et),e.write(et)},onNotification:(T,j)=>{$t(),Ut.func(T)?c=T:j&&(Ut.string(T)?f[T]={type:void 0,handler:j}:f[T.method]={type:T,handler:j})},onProgress:(T,j,V)=>{if(p.has(j))throw new Error(`Progress handler for token ${j} already registered`);return p.set(j,V),{dispose:()=>{p.delete(j)}}},sendProgress:(T,j,V)=>{Na.sendNotification(Kh.type,{token:j,value:V})},onUnhandledProgress:L.event,sendRequest:(T,...j)=>{$t(),_d();let V,te,et;if(Ut.string(T))switch(V=T,j.length){case 0:te=null;break;case 1:gl.CancellationToken.is(j[0])?(te=null,et=j[0]):te=Ma(j[0]);break;default:let _t=j.length-1;gl.CancellationToken.is(j[_t])?(et=j[_t],j.length===2?te=Ma(j[0]):te=j.slice(0,_t).map(rt=>Ma(rt))):te=j.map(rt=>Ma(rt));break}else{V=T.method,te=BP(T,j);let _t=T.numberOfParams;et=gl.CancellationToken.is(j[_t])?j[_t]:void 0}let si=n++,ln=new Promise((_t,rt)=>{let mr={jsonrpc:a,id:si,method:V,params:te},it={method:V,timerStart:Date.now(),resolve:_t,reject:rt};Se(mr);try{e.write(mr)}catch(Zt){it.reject(new ne.ResponseError(ne.ErrorCodes.MessageWriteError,Zt.message?Zt.message:"Unknown reason")),it=null}it&&(m[String(si)]=it)});return et&&et.onCancellationRequested(()=>{Na.sendNotification(uf.type,{id:si})}),ln},onRequest:(T,j)=>{$t(),Ut.func(T)?l=T:j&&(Ut.string(T)?u[T]={type:void 0,handler:j}:u[T.method]={type:T,handler:j})},trace:(T,j,V)=>{let te=!1,et=ji.Text;V!==void 0&&(Ut.boolean(V)?te=V:(te=V.sendNotification||!1,et=V.traceFormat||ji.Text)),g=T,w=et,g===bt.Off?x=void 0:x=j,te&&!Pe()&&!We()&&Na.sendNotification(oN.type,{value:bt.toString(T)})},onError:P.event,onClose:k.event,onUnhandledNotification:_.event,onDispose:I.event,dispose:()=>{if(We())return;E=Ui.Disposed,I.fire(void 0);let T=new Error("Connection got disposed.");Object.keys(m).forEach(j=>{m[j].reject(T)}),m=Object.create(null),y=Object.create(null),h=new iN.LinkedMap,Ut.func(e.dispose)&&e.dispose(),Ut.func(r.dispose)&&r.dispose()},listen:()=>{$t(),ky(),E=Ui.Listening,r.listen(Ty)},inspect:()=>{console.log("inspect")}};return Na.onNotification(zw.type,T=>{g===bt.Off||!x||x.log(T.message,g===bt.Verbose?T.verbose:void 0)}),Na.onNotification(Kh.type,T=>{let j=p.get(T.token);j?j(T.value):L.fire(T)}),Na}function kse(r){return r.listen!==void 0&&r.read===void 0}function Ise(r){return r.write!==void 0&&r.end===void 0}function Fse(r,e,t,i){t||(t=Q.NullLogger);let n=kse(r)?r:new af.StreamMessageReader(r),o=Ise(e)?e:new lf.StreamMessageWriter(e);return Rse(n,o,t,i)}Q.createMessageConnection=Fse});var jn=v(Ase=>{ho(Ase,{CodeAction:()=>vx,CodeActionContext:()=>gx,CodeActionKind:()=>mx,CodeLens:()=>yx,Color:()=>Xh,ColorInformation:()=>Vw,ColorPresentation:()=>Kw,Command:()=>vl,CompletionItem:()=>nx,CompletionItemKind:()=>tx,CompletionItemTag:()=>ix,CompletionList:()=>ox,CreateFile:()=>df,DeleteFile:()=>mf,Diagnostic:()=>cf,DiagnosticRelatedInformation:()=>Zh,DiagnosticSeverity:()=>Xw,DiagnosticTag:()=>Zw,DocumentHighlight:()=>cx,DocumentHighlightKind:()=>ux,DocumentLink:()=>wx,DocumentSymbol:()=>hx,EOL:()=>Lse,FoldingRange:()=>Yw,FoldingRangeKind:()=>Jw,FormattingOptions:()=>bx,Hover:()=>sx,InsertTextFormat:()=>rx,Location:()=>Yh,LocationLink:()=>Gw,MarkedString:()=>gf,MarkupContent:()=>tm,MarkupKind:()=>yl,ParameterInformation:()=>ax,Position:()=>Wi,Range:()=>ir,RenameFile:()=>hf,SelectionRange:()=>xx,SignatureInformation:()=>lx,SymbolInformation:()=>dx,SymbolKind:()=>fx,SymbolTag:()=>px,TextDocument:()=>Dx,TextDocumentEdit:()=>ff,TextDocumentIdentifier:()=>Qw,TextDocumentItem:()=>ex,TextEdit:()=>Ao,VersionedTextDocumentIdentifier:()=>pf,WorkspaceChange:()=>Ose,WorkspaceEdit:()=>Qh});"use strict";var Wi;(function(r){function e(i,n){return{line:i,character:n}}r.create=e;function t(i){var n=i;return N.objectLiteral(n)&&N.number(n.line)&&N.number(n.character)}r.is=t})(Wi||(Wi={}));var ir;(function(r){function e(i,n,o,s){if(N.number(i)&&N.number(n)&&N.number(o)&&N.number(s))return{start:Wi.create(i,n),end:Wi.create(o,s)};if(Wi.is(i)&&Wi.is(n))return{start:i,end:n};throw new Error("Range#create called with invalid arguments["+i+", "+n+", "+o+", "+s+"]")}r.create=e;function t(i){var n=i;return N.objectLiteral(n)&&Wi.is(n.start)&&Wi.is(n.end)}r.is=t})(ir||(ir={}));var Yh;(function(r){function e(i,n){return{uri:i,range:n}}r.create=e;function t(i){var n=i;return N.defined(n)&&ir.is(n.range)&&(N.string(n.uri)||N.undefined(n.uri))}r.is=t})(Yh||(Yh={}));var Gw;(function(r){function e(i,n,o,s){return{targetUri:i,targetRange:n,targetSelectionRange:o,originSelectionRange:s}}r.create=e;function t(i){var n=i;return N.defined(n)&&ir.is(n.targetRange)&&N.string(n.targetUri)&&(ir.is(n.targetSelectionRange)||N.undefined(n.targetSelectionRange))&&(ir.is(n.originSelectionRange)||N.undefined(n.originSelectionRange))}r.is=t})(Gw||(Gw={}));var Xh;(function(r){function e(i,n,o,s){return{red:i,green:n,blue:o,alpha:s}}r.create=e;function t(i){var n=i;return N.number(n.red)&&N.number(n.green)&&N.number(n.blue)&&N.number(n.alpha)}r.is=t})(Xh||(Xh={}));var Vw;(function(r){function e(i,n){return{range:i,color:n}}r.create=e;function t(i){var n=i;return ir.is(n.range)&&Xh.is(n.color)}r.is=t})(Vw||(Vw={}));var Kw;(function(r){function e(i,n,o){return{label:i,textEdit:n,additionalTextEdits:o}}r.create=e;function t(i){var n=i;return N.string(n.label)&&(N.undefined(n.textEdit)||Ao.is(n))&&(N.undefined(n.additionalTextEdits)||N.typedArray(n.additionalTextEdits,Ao.is))}r.is=t})(Kw||(Kw={}));var Jw;(function(r){r.Comment="comment",r.Imports="imports",r.Region="region"})(Jw||(Jw={}));var Yw;(function(r){function e(i,n,o,s,a){var l={startLine:i,endLine:n};return N.defined(o)&&(l.startCharacter=o),N.defined(s)&&(l.endCharacter=s),N.defined(a)&&(l.kind=a),l}r.create=e;function t(i){var n=i;return N.number(n.startLine)&&N.number(n.startLine)&&(N.undefined(n.startCharacter)||N.number(n.startCharacter))&&(N.undefined(n.endCharacter)||N.number(n.endCharacter))&&(N.undefined(n.kind)||N.string(n.kind))}r.is=t})(Yw||(Yw={}));var Zh;(function(r){function e(i,n){return{location:i,message:n}}r.create=e;function t(i){var n=i;return N.defined(n)&&Yh.is(n.location)&&N.string(n.message)}r.is=t})(Zh||(Zh={}));var Xw;(function(r){r.Error=1,r.Warning=2,r.Information=3,r.Hint=4})(Xw||(Xw={}));var Zw;(function(r){r.Unnecessary=1,r.Deprecated=2})(Zw||(Zw={}));var cf;(function(r){function e(i,n,o,s,a,l){var u={range:i,message:n};return N.defined(o)&&(u.severity=o),N.defined(s)&&(u.code=s),N.defined(a)&&(u.source=a),N.defined(l)&&(u.relatedInformation=l),u}r.create=e;function t(i){var n=i;return N.defined(n)&&ir.is(n.range)&&N.string(n.message)&&(N.number(n.severity)||N.undefined(n.severity))&&(N.number(n.code)||N.string(n.code)||N.undefined(n.code))&&(N.string(n.source)||N.undefined(n.source))&&(N.undefined(n.relatedInformation)||N.typedArray(n.relatedInformation,Zh.is))}r.is=t})(cf||(cf={}));var vl;(function(r){function e(i,n){for(var o=[],s=2;s0&&(a.arguments=o),a}r.create=e;function t(i){var n=i;return N.defined(n)&&N.string(n.title)&&N.string(n.command)}r.is=t})(vl||(vl={}));var Ao;(function(r){function e(o,s){return{range:o,newText:s}}r.replace=e;function t(o,s){return{range:{start:o,end:o},newText:s}}r.insert=t;function i(o){return{range:o,newText:""}}r.del=i;function n(o){var s=o;return N.objectLiteral(s)&&N.string(s.newText)&&ir.is(s.range)}r.is=n})(Ao||(Ao={}));var ff;(function(r){function e(i,n){return{textDocument:i,edits:n}}r.create=e;function t(i){var n=i;return N.defined(n)&&pf.is(n.textDocument)&&Array.isArray(n.edits)}r.is=t})(ff||(ff={}));var df;(function(r){function e(i,n){var o={kind:"create",uri:i};return n!==void 0&&(n.overwrite!==void 0||n.ignoreIfExists!==void 0)&&(o.options=n),o}r.create=e;function t(i){var n=i;return n&&n.kind==="create"&&N.string(n.uri)&&(n.options===void 0||(n.options.overwrite===void 0||N.boolean(n.options.overwrite))&&(n.options.ignoreIfExists===void 0||N.boolean(n.options.ignoreIfExists)))}r.is=t})(df||(df={}));var hf;(function(r){function e(i,n,o){var s={kind:"rename",oldUri:i,newUri:n};return o!==void 0&&(o.overwrite!==void 0||o.ignoreIfExists!==void 0)&&(s.options=o),s}r.create=e;function t(i){var n=i;return n&&n.kind==="rename"&&N.string(n.oldUri)&&N.string(n.newUri)&&(n.options===void 0||(n.options.overwrite===void 0||N.boolean(n.options.overwrite))&&(n.options.ignoreIfExists===void 0||N.boolean(n.options.ignoreIfExists)))}r.is=t})(hf||(hf={}));var mf;(function(r){function e(i,n){var o={kind:"delete",uri:i};return n!==void 0&&(n.recursive!==void 0||n.ignoreIfNotExists!==void 0)&&(o.options=n),o}r.create=e;function t(i){var n=i;return n&&n.kind==="delete"&&N.string(n.uri)&&(n.options===void 0||(n.options.recursive===void 0||N.boolean(n.options.recursive))&&(n.options.ignoreIfNotExists===void 0||N.boolean(n.options.ignoreIfNotExists)))}r.is=t})(mf||(mf={}));var Qh;(function(r){function e(t){var i=t;return i&&(i.changes!==void 0||i.documentChanges!==void 0)&&(i.documentChanges===void 0||i.documentChanges.every(function(n){return N.string(n.kind)?df.is(n)||hf.is(n)||mf.is(n):ff.is(n)}))}r.is=e})(Qh||(Qh={}));var em=function(){function r(e){this.edits=e}return r.prototype.insert=function(e,t){this.edits.push(Ao.insert(e,t))},r.prototype.replace=function(e,t){this.edits.push(Ao.replace(e,t))},r.prototype.delete=function(e){this.edits.push(Ao.del(e))},r.prototype.add=function(e){this.edits.push(e)},r.prototype.all=function(){return this.edits},r.prototype.clear=function(){this.edits.splice(0,this.edits.length)},r}(),Ose=function(){function r(e){var t=this;this._textEditChanges=Object.create(null),e&&(this._workspaceEdit=e,e.documentChanges?e.documentChanges.forEach(function(i){if(ff.is(i)){var n=new em(i.edits);t._textEditChanges[i.textDocument.uri]=n}}):e.changes&&Object.keys(e.changes).forEach(function(i){var n=new em(e.changes[i]);t._textEditChanges[i]=n}))}return Object.defineProperty(r.prototype,"edit",{get:function(){return this._workspaceEdit},enumerable:!0,configurable:!0}),r.prototype.getTextEditChange=function(e){if(pf.is(e)){if(this._workspaceEdit||(this._workspaceEdit={documentChanges:[]}),!this._workspaceEdit.documentChanges)throw new Error("Workspace edit is not configured for document changes.");var t=e,i=this._textEditChanges[t.uri];if(!i){var n=[],o={textDocument:t,edits:n};this._workspaceEdit.documentChanges.push(o),i=new em(n),this._textEditChanges[t.uri]=i}return i}else{if(this._workspaceEdit||(this._workspaceEdit={changes:Object.create(null)}),!this._workspaceEdit.changes)throw new Error("Workspace edit is not configured for normal text edit changes.");var i=this._textEditChanges[e];if(!i){var n=[];this._workspaceEdit.changes[e]=n,i=new em(n),this._textEditChanges[e]=i}return i}},r.prototype.createFile=function(e,t){this.checkDocumentChanges(),this._workspaceEdit.documentChanges.push(df.create(e,t))},r.prototype.renameFile=function(e,t,i){this.checkDocumentChanges(),this._workspaceEdit.documentChanges.push(hf.create(e,t,i))},r.prototype.deleteFile=function(e,t){this.checkDocumentChanges(),this._workspaceEdit.documentChanges.push(mf.create(e,t))},r.prototype.checkDocumentChanges=function(){if(!this._workspaceEdit||!this._workspaceEdit.documentChanges)throw new Error("Workspace edit is not configured for document changes.")},r}(),Qw;(function(r){function e(i){return{uri:i}}r.create=e;function t(i){var n=i;return N.defined(n)&&N.string(n.uri)}r.is=t})(Qw||(Qw={}));var pf;(function(r){function e(i,n){return{uri:i,version:n}}r.create=e;function t(i){var n=i;return N.defined(n)&&N.string(n.uri)&&(n.version===null||N.number(n.version))}r.is=t})(pf||(pf={}));var ex;(function(r){function e(i,n,o,s){return{uri:i,languageId:n,version:o,text:s}}r.create=e;function t(i){var n=i;return N.defined(n)&&N.string(n.uri)&&N.string(n.languageId)&&N.number(n.version)&&N.string(n.text)}r.is=t})(ex||(ex={}));var yl;(function(r){r.PlainText="plaintext",r.Markdown="markdown"})(yl||(yl={}));(function(r){function e(t){var i=t;return i===r.PlainText||i===r.Markdown}r.is=e})(yl||(yl={}));var tm;(function(r){function e(t){var i=t;return N.objectLiteral(t)&&yl.is(i.kind)&&N.string(i.value)}r.is=e})(tm||(tm={}));var tx;(function(r){r.Text=1,r.Method=2,r.Function=3,r.Constructor=4,r.Field=5,r.Variable=6,r.Class=7,r.Interface=8,r.Module=9,r.Property=10,r.Unit=11,r.Value=12,r.Enum=13,r.Keyword=14,r.Snippet=15,r.Color=16,r.File=17,r.Reference=18,r.Folder=19,r.EnumMember=20,r.Constant=21,r.Struct=22,r.Event=23,r.Operator=24,r.TypeParameter=25})(tx||(tx={}));var rx;(function(r){r.PlainText=1,r.Snippet=2})(rx||(rx={}));var ix;(function(r){r.Deprecated=1})(ix||(ix={}));var nx;(function(r){function e(t){return{label:t}}r.create=e})(nx||(nx={}));var ox;(function(r){function e(t,i){return{items:t||[],isIncomplete:!!i}}r.create=e})(ox||(ox={}));var gf;(function(r){function e(i){return i.replace(/[\\`*_{}[\]()#+\-.!]/g,"\\$&")}r.fromPlainText=e;function t(i){var n=i;return N.string(n)||N.objectLiteral(n)&&N.string(n.language)&&N.string(n.value)}r.is=t})(gf||(gf={}));var sx;(function(r){function e(t){var i=t;return!!i&&N.objectLiteral(i)&&(tm.is(i.contents)||gf.is(i.contents)||N.typedArray(i.contents,gf.is))&&(t.range===void 0||ir.is(t.range))}r.is=e})(sx||(sx={}));var ax;(function(r){function e(t,i){return i?{label:t,documentation:i}:{label:t}}r.create=e})(ax||(ax={}));var lx;(function(r){function e(t,i){for(var n=[],o=2;o=0;c--){var f=l[c],p=o.offsetAt(f.range.start),d=o.offsetAt(f.range.end);if(d<=u)a=a.substring(0,p)+f.newText+a.substring(d,a.length);else throw new Error("Overlapping edit");u=p}return a}r.applyEdits=i;function n(o,s){if(o.length<=1)return o;var a=o.length/2|0,l=o.slice(0,a),u=o.slice(a);n(l,s),n(u,s);for(var c=0,f=0,p=0;c0&&e.push(t.length),this._lineOffsets=e}return this._lineOffsets},r.prototype.positionAt=function(e){e=Math.max(Math.min(e,this._content.length),0);var t=this.getLineOffsets(),i=0,n=t.length;if(n===0)return Wi.create(0,e);for(;ie?n=o:i=o+1}var s=i-1;return Wi.create(s,e-t[s])},r.prototype.offsetAt=function(e){var t=this.getLineOffsets();if(e.line>=t.length)return this._content.length;if(e.line<0)return 0;var i=t[e.line],n=e.line+1{"use strict";Object.defineProperty(Hi,"__esModule",{value:!0});function Nse(r){return r===!0||r===!1}Hi.boolean=Nse;function sN(r){return typeof r=="string"||r instanceof String}Hi.string=sN;function qse(r){return typeof r=="number"||r instanceof Number}Hi.number=qse;function $se(r){return r instanceof Error}Hi.error=$se;function Bse(r){return typeof r=="function"}Hi.func=Bse;function aN(r){return Array.isArray(r)}Hi.array=aN;function jse(r){return aN(r)&&r.every(e=>sN(e))}Hi.stringArray=jse;function Use(r,e){return Array.isArray(r)&&r.every(e)}Hi.typedArray=Use;function Wse(r){return r!==null&&typeof r=="object"}Hi.objectLiteral=Wse});var Gr=v(bl=>{"use strict";Object.defineProperty(bl,"__esModule",{value:!0});var rm=bi(),uN=class extends rm.RequestType0{constructor(e){super(e)}};bl.ProtocolRequestType0=uN;var cN=class extends rm.RequestType{constructor(e){super(e)}};bl.ProtocolRequestType=cN;var fN=class extends rm.NotificationType{constructor(e){super(e)}};bl.ProtocolNotificationType=fN;var pN=class extends rm.NotificationType0{constructor(e){super(e)}};bl.ProtocolNotificationType0=pN});var dN=v(im=>{"use strict";Object.defineProperty(im,"__esModule",{value:!0});var Hse=bi(),zse=Gr(),Gse;(function(r){r.method="textDocument/implementation",r.type=new zse.ProtocolRequestType(r.method),r.resultType=new Hse.ProgressType})(Gse=im.ImplementationRequest||(im.ImplementationRequest={}))});var hN=v(nm=>{"use strict";Object.defineProperty(nm,"__esModule",{value:!0});var Vse=bi(),Kse=Gr(),Jse;(function(r){r.method="textDocument/typeDefinition",r.type=new Kse.ProtocolRequestType(r.method),r.resultType=new Vse.ProgressType})(Jse=nm.TypeDefinitionRequest||(nm.TypeDefinitionRequest={}))});var gN=v(wl=>{"use strict";Object.defineProperty(wl,"__esModule",{value:!0});var mN=Gr(),Yse;(function(r){r.type=new mN.ProtocolRequestType0("workspace/workspaceFolders")})(Yse=wl.WorkspaceFoldersRequest||(wl.WorkspaceFoldersRequest={}));var Xse;(function(r){r.type=new mN.ProtocolNotificationType("workspace/didChangeWorkspaceFolders")})(Xse=wl.DidChangeWorkspaceFoldersNotification||(wl.DidChangeWorkspaceFoldersNotification={}))});var vN=v(om=>{"use strict";Object.defineProperty(om,"__esModule",{value:!0});var Zse=Gr(),Qse;(function(r){r.type=new Zse.ProtocolRequestType("workspace/configuration")})(Qse=om.ConfigurationRequest||(om.ConfigurationRequest={}))});var bN=v(xl=>{"use strict";Object.defineProperty(xl,"__esModule",{value:!0});var eae=bi(),yN=Gr(),tae;(function(r){r.method="textDocument/documentColor",r.type=new yN.ProtocolRequestType(r.method),r.resultType=new eae.ProgressType})(tae=xl.DocumentColorRequest||(xl.DocumentColorRequest={}));var rae;(function(r){r.type=new yN.ProtocolRequestType("textDocument/colorPresentation")})(rae=xl.ColorPresentationRequest||(xl.ColorPresentationRequest={}))});var wN=v(Dl=>{"use strict";Object.defineProperty(Dl,"__esModule",{value:!0});var iae=bi(),nae=Gr(),oae;(function(r){r.Comment="comment",r.Imports="imports",r.Region="region"})(oae=Dl.FoldingRangeKind||(Dl.FoldingRangeKind={}));var sae;(function(r){r.method="textDocument/foldingRange",r.type=new nae.ProtocolRequestType(r.method),r.resultType=new iae.ProgressType})(sae=Dl.FoldingRangeRequest||(Dl.FoldingRangeRequest={}))});var xN=v(sm=>{"use strict";Object.defineProperty(sm,"__esModule",{value:!0});var aae=bi(),lae=Gr(),uae;(function(r){r.method="textDocument/declaration",r.type=new lae.ProtocolRequestType(r.method),r.resultType=new aae.ProgressType})(uae=sm.DeclarationRequest||(sm.DeclarationRequest={}))});var DN=v(am=>{"use strict";Object.defineProperty(am,"__esModule",{value:!0});var cae=bi(),fae=Gr(),pae;(function(r){r.method="textDocument/selectionRange",r.type=new fae.ProtocolRequestType(r.method),r.resultType=new cae.ProgressType})(pae=am.SelectionRangeRequest||(am.SelectionRangeRequest={}))});var EN=v(Oo=>{"use strict";Object.defineProperty(Oo,"__esModule",{value:!0});var dae=bi(),SN=Gr(),hae;(function(r){r.type=new dae.ProgressType})(hae=Oo.WorkDoneProgress||(Oo.WorkDoneProgress={}));var mae;(function(r){r.type=new SN.ProtocolRequestType("window/workDoneProgress/create")})(mae=Oo.WorkDoneProgressCreateRequest||(Oo.WorkDoneProgressCreateRequest={}));var gae;(function(r){r.type=new SN.ProtocolNotificationType("window/workDoneProgress/cancel")})(gae=Oo.WorkDoneProgressCancelNotification||(Oo.WorkDoneProgressCancelNotification={}))});var RN=v(M=>{"use strict";Object.defineProperty(M,"__esModule",{value:!0});var Lo=lN(),Un=bi(),pe=Gr(),vae=dN();M.ImplementationRequest=vae.ImplementationRequest;var yae=hN();M.TypeDefinitionRequest=yae.TypeDefinitionRequest;var CN=gN();M.WorkspaceFoldersRequest=CN.WorkspaceFoldersRequest;M.DidChangeWorkspaceFoldersNotification=CN.DidChangeWorkspaceFoldersNotification;var bae=vN();M.ConfigurationRequest=bae.ConfigurationRequest;var _N=bN();M.DocumentColorRequest=_N.DocumentColorRequest;M.ColorPresentationRequest=_N.ColorPresentationRequest;var wae=wN();M.FoldingRangeRequest=wae.FoldingRangeRequest;var xae=xN();M.DeclarationRequest=xae.DeclarationRequest;var Dae=DN();M.SelectionRangeRequest=Dae.SelectionRangeRequest;var Sx=EN();M.WorkDoneProgress=Sx.WorkDoneProgress;M.WorkDoneProgressCreateRequest=Sx.WorkDoneProgressCreateRequest;M.WorkDoneProgressCancelNotification=Sx.WorkDoneProgressCancelNotification;var PN;(function(r){function e(t){let i=t;return Lo.string(i.language)||Lo.string(i.scheme)||Lo.string(i.pattern)}r.is=e})(PN=M.DocumentFilter||(M.DocumentFilter={}));var TN;(function(r){function e(t){if(!Array.isArray(t))return!1;for(let i of t)if(!Lo.string(i)&&!PN.is(i))return!1;return!0}r.is=e})(TN=M.DocumentSelector||(M.DocumentSelector={}));var Sae;(function(r){r.type=new pe.ProtocolRequestType("client/registerCapability")})(Sae=M.RegistrationRequest||(M.RegistrationRequest={}));var Eae;(function(r){r.type=new pe.ProtocolRequestType("client/unregisterCapability")})(Eae=M.UnregistrationRequest||(M.UnregistrationRequest={}));var Cae;(function(r){r.Create="create",r.Rename="rename",r.Delete="delete"})(Cae=M.ResourceOperationKind||(M.ResourceOperationKind={}));var _ae;(function(r){r.Abort="abort",r.Transactional="transactional",r.TextOnlyTransactional="textOnlyTransactional",r.Undo="undo"})(_ae=M.FailureHandlingKind||(M.FailureHandlingKind={}));var Pae;(function(r){function e(t){let i=t;return i&&Lo.string(i.id)&&i.id.length>0}r.hasId=e})(Pae=M.StaticRegistrationOptions||(M.StaticRegistrationOptions={}));var Tae;(function(r){function e(t){let i=t;return i&&(i.documentSelector===null||TN.is(i.documentSelector))}r.is=e})(Tae=M.TextDocumentRegistrationOptions||(M.TextDocumentRegistrationOptions={}));var Rae;(function(r){function e(i){let n=i;return Lo.objectLiteral(n)&&(n.workDoneProgress===void 0||Lo.boolean(n.workDoneProgress))}r.is=e;function t(i){let n=i;return n&&Lo.boolean(n.workDoneProgress)}r.hasWorkDoneProgress=t})(Rae=M.WorkDoneProgressOptions||(M.WorkDoneProgressOptions={}));var kae;(function(r){r.type=new pe.ProtocolRequestType("initialize")})(kae=M.InitializeRequest||(M.InitializeRequest={}));var Iae;(function(r){r.unknownProtocolVersion=1})(Iae=M.InitializeError||(M.InitializeError={}));var Fae;(function(r){r.type=new pe.ProtocolNotificationType("initialized")})(Fae=M.InitializedNotification||(M.InitializedNotification={}));var Aae;(function(r){r.type=new pe.ProtocolRequestType0("shutdown")})(Aae=M.ShutdownRequest||(M.ShutdownRequest={}));var Oae;(function(r){r.type=new pe.ProtocolNotificationType0("exit")})(Oae=M.ExitNotification||(M.ExitNotification={}));var Lae;(function(r){r.type=new pe.ProtocolNotificationType("workspace/didChangeConfiguration")})(Lae=M.DidChangeConfigurationNotification||(M.DidChangeConfigurationNotification={}));var Mae;(function(r){r.Error=1,r.Warning=2,r.Info=3,r.Log=4})(Mae=M.MessageType||(M.MessageType={}));var Nae;(function(r){r.type=new pe.ProtocolNotificationType("window/showMessage")})(Nae=M.ShowMessageNotification||(M.ShowMessageNotification={}));var qae;(function(r){r.type=new pe.ProtocolRequestType("window/showMessageRequest")})(qae=M.ShowMessageRequest||(M.ShowMessageRequest={}));var $ae;(function(r){r.type=new pe.ProtocolNotificationType("window/logMessage")})($ae=M.LogMessageNotification||(M.LogMessageNotification={}));var Bae;(function(r){r.type=new pe.ProtocolNotificationType("telemetry/event")})(Bae=M.TelemetryEventNotification||(M.TelemetryEventNotification={}));var jae;(function(r){r.None=0,r.Full=1,r.Incremental=2})(jae=M.TextDocumentSyncKind||(M.TextDocumentSyncKind={}));var Uae;(function(r){r.method="textDocument/didOpen",r.type=new pe.ProtocolNotificationType(r.method)})(Uae=M.DidOpenTextDocumentNotification||(M.DidOpenTextDocumentNotification={}));var Wae;(function(r){r.method="textDocument/didChange",r.type=new pe.ProtocolNotificationType(r.method)})(Wae=M.DidChangeTextDocumentNotification||(M.DidChangeTextDocumentNotification={}));var Hae;(function(r){r.method="textDocument/didClose",r.type=new pe.ProtocolNotificationType(r.method)})(Hae=M.DidCloseTextDocumentNotification||(M.DidCloseTextDocumentNotification={}));var zae;(function(r){r.method="textDocument/didSave",r.type=new pe.ProtocolNotificationType(r.method)})(zae=M.DidSaveTextDocumentNotification||(M.DidSaveTextDocumentNotification={}));var Gae;(function(r){r.Manual=1,r.AfterDelay=2,r.FocusOut=3})(Gae=M.TextDocumentSaveReason||(M.TextDocumentSaveReason={}));var Vae;(function(r){r.method="textDocument/willSave",r.type=new pe.ProtocolNotificationType(r.method)})(Vae=M.WillSaveTextDocumentNotification||(M.WillSaveTextDocumentNotification={}));var Kae;(function(r){r.method="textDocument/willSaveWaitUntil",r.type=new pe.ProtocolRequestType(r.method)})(Kae=M.WillSaveTextDocumentWaitUntilRequest||(M.WillSaveTextDocumentWaitUntilRequest={}));var Jae;(function(r){r.type=new pe.ProtocolNotificationType("workspace/didChangeWatchedFiles")})(Jae=M.DidChangeWatchedFilesNotification||(M.DidChangeWatchedFilesNotification={}));var Yae;(function(r){r.Created=1,r.Changed=2,r.Deleted=3})(Yae=M.FileChangeType||(M.FileChangeType={}));var Xae;(function(r){r.Create=1,r.Change=2,r.Delete=4})(Xae=M.WatchKind||(M.WatchKind={}));var Zae;(function(r){r.type=new pe.ProtocolNotificationType("textDocument/publishDiagnostics")})(Zae=M.PublishDiagnosticsNotification||(M.PublishDiagnosticsNotification={}));var Qae;(function(r){r.Invoked=1,r.TriggerCharacter=2,r.TriggerForIncompleteCompletions=3})(Qae=M.CompletionTriggerKind||(M.CompletionTriggerKind={}));var ele;(function(r){r.method="textDocument/completion",r.type=new pe.ProtocolRequestType(r.method),r.resultType=new Un.ProgressType})(ele=M.CompletionRequest||(M.CompletionRequest={}));var tle;(function(r){r.method="completionItem/resolve",r.type=new pe.ProtocolRequestType(r.method)})(tle=M.CompletionResolveRequest||(M.CompletionResolveRequest={}));var rle;(function(r){r.method="textDocument/hover",r.type=new pe.ProtocolRequestType(r.method)})(rle=M.HoverRequest||(M.HoverRequest={}));var ile;(function(r){r.Invoked=1,r.TriggerCharacter=2,r.ContentChange=3})(ile=M.SignatureHelpTriggerKind||(M.SignatureHelpTriggerKind={}));var nle;(function(r){r.method="textDocument/signatureHelp",r.type=new pe.ProtocolRequestType(r.method)})(nle=M.SignatureHelpRequest||(M.SignatureHelpRequest={}));var ole;(function(r){r.method="textDocument/definition",r.type=new pe.ProtocolRequestType(r.method),r.resultType=new Un.ProgressType})(ole=M.DefinitionRequest||(M.DefinitionRequest={}));var sle;(function(r){r.method="textDocument/references",r.type=new pe.ProtocolRequestType(r.method),r.resultType=new Un.ProgressType})(sle=M.ReferencesRequest||(M.ReferencesRequest={}));var ale;(function(r){r.method="textDocument/documentHighlight",r.type=new pe.ProtocolRequestType(r.method),r.resultType=new Un.ProgressType})(ale=M.DocumentHighlightRequest||(M.DocumentHighlightRequest={}));var lle;(function(r){r.method="textDocument/documentSymbol",r.type=new pe.ProtocolRequestType(r.method),r.resultType=new Un.ProgressType})(lle=M.DocumentSymbolRequest||(M.DocumentSymbolRequest={}));var ule;(function(r){r.method="textDocument/codeAction",r.type=new pe.ProtocolRequestType(r.method),r.resultType=new Un.ProgressType})(ule=M.CodeActionRequest||(M.CodeActionRequest={}));var cle;(function(r){r.method="workspace/symbol",r.type=new pe.ProtocolRequestType(r.method),r.resultType=new Un.ProgressType})(cle=M.WorkspaceSymbolRequest||(M.WorkspaceSymbolRequest={}));var fle;(function(r){r.type=new pe.ProtocolRequestType("textDocument/codeLens"),r.resultType=new Un.ProgressType})(fle=M.CodeLensRequest||(M.CodeLensRequest={}));var ple;(function(r){r.type=new pe.ProtocolRequestType("codeLens/resolve")})(ple=M.CodeLensResolveRequest||(M.CodeLensResolveRequest={}));var dle;(function(r){r.method="textDocument/documentLink",r.type=new pe.ProtocolRequestType(r.method),r.resultType=new Un.ProgressType})(dle=M.DocumentLinkRequest||(M.DocumentLinkRequest={}));var hle;(function(r){r.type=new pe.ProtocolRequestType("documentLink/resolve")})(hle=M.DocumentLinkResolveRequest||(M.DocumentLinkResolveRequest={}));var mle;(function(r){r.method="textDocument/formatting",r.type=new pe.ProtocolRequestType(r.method)})(mle=M.DocumentFormattingRequest||(M.DocumentFormattingRequest={}));var gle;(function(r){r.method="textDocument/rangeFormatting",r.type=new pe.ProtocolRequestType(r.method)})(gle=M.DocumentRangeFormattingRequest||(M.DocumentRangeFormattingRequest={}));var vle;(function(r){r.method="textDocument/onTypeFormatting",r.type=new pe.ProtocolRequestType(r.method)})(vle=M.DocumentOnTypeFormattingRequest||(M.DocumentOnTypeFormattingRequest={}));var yle;(function(r){r.method="textDocument/rename",r.type=new pe.ProtocolRequestType(r.method)})(yle=M.RenameRequest||(M.RenameRequest={}));var ble;(function(r){r.method="textDocument/prepareRename",r.type=new pe.ProtocolRequestType(r.method)})(ble=M.PrepareRenameRequest||(M.PrepareRenameRequest={}));var wle;(function(r){r.type=new pe.ProtocolRequestType("workspace/executeCommand")})(wle=M.ExecuteCommandRequest||(M.ExecuteCommandRequest={}));var xle;(function(r){r.type=new pe.ProtocolRequestType("workspace/applyEdit")})(xle=M.ApplyWorkspaceEditRequest||(M.ApplyWorkspaceEditRequest={}))});var kN=v(Mo=>{"use strict";Object.defineProperty(Mo,"__esModule",{value:!0});var Ex=Gr(),Dle;(function(r){r.method="textDocument/prepareCallHierarchy",r.type=new Ex.ProtocolRequestType(r.method)})(Dle=Mo.CallHierarchyPrepareRequest||(Mo.CallHierarchyPrepareRequest={}));var Sle;(function(r){r.method="callHierarchy/incomingCalls",r.type=new Ex.ProtocolRequestType(r.method)})(Sle=Mo.CallHierarchyIncomingCallsRequest||(Mo.CallHierarchyIncomingCallsRequest={}));var Ele;(function(r){r.method="callHierarchy/outgoingCalls",r.type=new Ex.ProtocolRequestType(r.method)})(Ele=Mo.CallHierarchyOutgoingCallsRequest||(Mo.CallHierarchyOutgoingCallsRequest={}))});var IN=v(kr=>{"use strict";Object.defineProperty(kr,"__esModule",{value:!0});var Cx=Gr(),Cle;(function(r){r.comment="comment",r.keyword="keyword",r.string="string",r.number="number",r.regexp="regexp",r.operator="operator",r.namespace="namespace",r.type="type",r.struct="struct",r.class="class",r.interface="interface",r.enum="enum",r.typeParameter="typeParameter",r.function="function",r.member="member",r.property="property",r.macro="macro",r.variable="variable",r.parameter="parameter",r.label="label"})(Cle=kr.SemanticTokenTypes||(kr.SemanticTokenTypes={}));var _le;(function(r){r.documentation="documentation",r.declaration="declaration",r.definition="definition",r.reference="reference",r.static="static",r.abstract="abstract",r.deprecated="deprecated",r.async="async",r.volatile="volatile",r.readonly="readonly"})(_le=kr.SemanticTokenModifiers||(kr.SemanticTokenModifiers={}));var Ple;(function(r){function e(t){let i=t;return i!==void 0&&(i.resultId===void 0||typeof i.resultId=="string")&&Array.isArray(i.data)&&(i.data.length===0||typeof i.data[0]=="number")}r.is=e})(Ple=kr.SemanticTokens||(kr.SemanticTokens={}));var Tle;(function(r){r.method="textDocument/semanticTokens",r.type=new Cx.ProtocolRequestType(r.method)})(Tle=kr.SemanticTokensRequest||(kr.SemanticTokensRequest={}));var Rle;(function(r){r.method="textDocument/semanticTokens/edits",r.type=new Cx.ProtocolRequestType(r.method)})(Rle=kr.SemanticTokensEditsRequest||(kr.SemanticTokensEditsRequest={}));var kle;(function(r){r.method="textDocument/semanticTokens/range",r.type=new Cx.ProtocolRequestType(r.method)})(kle=kr.SemanticTokensRangeRequest||(kr.SemanticTokensRangeRequest={}))});var W=v(_e=>{"use strict";function FN(r){for(var e in r)_e.hasOwnProperty(e)||(_e[e]=r[e])}Object.defineProperty(_e,"__esModule",{value:!0});var Ue=bi();_e.ErrorCodes=Ue.ErrorCodes;_e.ResponseError=Ue.ResponseError;_e.CancellationToken=Ue.CancellationToken;_e.CancellationTokenSource=Ue.CancellationTokenSource;_e.Disposable=Ue.Disposable;_e.Event=Ue.Event;_e.Emitter=Ue.Emitter;_e.Trace=Ue.Trace;_e.TraceFormat=Ue.TraceFormat;_e.SetTraceNotification=Ue.SetTraceNotification;_e.LogTraceNotification=Ue.LogTraceNotification;_e.RequestType=Ue.RequestType;_e.RequestType0=Ue.RequestType0;_e.NotificationType=Ue.NotificationType;_e.NotificationType0=Ue.NotificationType0;_e.MessageReader=Ue.MessageReader;_e.MessageWriter=Ue.MessageWriter;_e.ConnectionStrategy=Ue.ConnectionStrategy;_e.StreamMessageReader=Ue.StreamMessageReader;_e.StreamMessageWriter=Ue.StreamMessageWriter;_e.IPCMessageReader=Ue.IPCMessageReader;_e.IPCMessageWriter=Ue.IPCMessageWriter;_e.createClientPipeTransport=Ue.createClientPipeTransport;_e.createServerPipeTransport=Ue.createServerPipeTransport;_e.generateRandomPipeName=Ue.generateRandomPipeName;_e.createClientSocketTransport=Ue.createClientSocketTransport;_e.createServerSocketTransport=Ue.createServerSocketTransport;_e.ProgressType=Ue.ProgressType;FN(jn());FN(RN());var Sl=kN(),Wn=IN(),Ile;(function(r){let e;(function(a){a.method=Sl.CallHierarchyPrepareRequest.method,a.type=Sl.CallHierarchyPrepareRequest.type})(e=r.CallHierarchyPrepareRequest||(r.CallHierarchyPrepareRequest={}));let t;(function(a){a.method=Sl.CallHierarchyIncomingCallsRequest.method,a.type=Sl.CallHierarchyIncomingCallsRequest.type})(t=r.CallHierarchyIncomingCallsRequest||(r.CallHierarchyIncomingCallsRequest={}));let i;(function(a){a.method=Sl.CallHierarchyOutgoingCallsRequest.method,a.type=Sl.CallHierarchyOutgoingCallsRequest.type})(i=r.CallHierarchyOutgoingCallsRequest||(r.CallHierarchyOutgoingCallsRequest={})),r.SemanticTokenTypes=Wn.SemanticTokenTypes,r.SemanticTokenModifiers=Wn.SemanticTokenModifiers,r.SemanticTokens=Wn.SemanticTokens;let n;(function(a){a.method=Wn.SemanticTokensRequest.method,a.type=Wn.SemanticTokensRequest.type})(n=r.SemanticTokensRequest||(r.SemanticTokensRequest={}));let o;(function(a){a.method=Wn.SemanticTokensEditsRequest.method,a.type=Wn.SemanticTokensEditsRequest.type})(o=r.SemanticTokensEditsRequest||(r.SemanticTokensEditsRequest={}));let s;(function(a){a.method=Wn.SemanticTokensRangeRequest.method,a.type=Wn.SemanticTokensRangeRequest.type})(s=r.SemanticTokensRangeRequest||(r.SemanticTokensRangeRequest={}))})(Ile=_e.Proposed||(_e.Proposed={}));function Fle(r,e,t,i){return Ue.createMessageConnection(r,e,t,i)}_e.createProtocolConnection=Fle});var Vr=v((nPe,AN)=>{function _x(r,e,t){var i,n,o,s,a;e==null&&(e=100);function l(){var c=Date.now()-s;c=0?i=setTimeout(l,e-c):(i=null,t||(a=r.apply(o,n),o=n=null))}var u=function(){o=this,n=arguments,s=Date.now();var c=t&&!i;return i||(i=setTimeout(l,e)),c&&(a=r.apply(o,n),o=n=null),a};return u.clear=function(){i&&(clearTimeout(i),i=null)},u.flush=function(){i&&(a=r.apply(o,n),o=n=null,clearTimeout(i),i=null)},u}_x.debounce=_x;AN.exports=_x});var LN=v((oPe,ON)=>{"use strict";var ut={rfc3986:{}};ut.generate=function(){var r="|",e="0-9",t="["+e+"]",i="a-zA-Z",n="["+i+"]";ut.rfc3986.cidr=t+r+"[1-2]"+t+r+"3[0-2]";var o=e+"A-Fa-f",s="["+o+"]",a=i+e+"-\\._~",l="!\\$&'\\(\\)\\*\\+,;=",u="%"+o,c=a+u+l+":@",f="["+c+"]",p="0?",d="(?:"+p+p+t+r+p+"[1-9]"+t+r+"1"+t+t+r+"2[0-4]"+t+r+"25[0-5])";ut.rfc3986.IPv4address="(?:"+d+"\\.){3}"+d;var h=s+"{1,4}",m="(?:"+h+":"+h+"|"+ut.rfc3986.IPv4address+")",y="(?:"+h+":){6}"+m,g="::(?:"+h+":){5}"+m,w="(?:"+h+")?::(?:"+h+":){4}"+m,x="(?:(?:"+h+":){0,1}"+h+")?::(?:"+h+":){3}"+m,E="(?:(?:"+h+":){0,2}"+h+")?::(?:"+h+":){2}"+m,P="(?:(?:"+h+":){0,3}"+h+")?::"+h+":"+m,k="(?:(?:"+h+":){0,4}"+h+")?::"+m,_="(?:(?:"+h+":){0,5}"+h+")?::"+h,L="(?:(?:"+h+":){0,6}"+h+")?::";ut.rfc3986.IPv6address="(?:"+y+r+g+r+w+r+x+r+E+r+P+r+k+r+_+r+L+")",ut.rfc3986.IPvFuture="v"+s+"+\\.["+a+l+":]+",ut.rfc3986.scheme=n+"["+i+e+"+-\\.]*";var I="["+a+u+l+":]*";ut.rfc3986.IPLiteral="\\[(?:"+ut.rfc3986.IPv6address+r+ut.rfc3986.IPvFuture+")\\]";var O="["+a+u+l+"]{0,255}",R="(?:"+ut.rfc3986.IPLiteral+r+ut.rfc3986.IPv4address+r+O+")",F=t+"*",q="(?:"+I+"@)?"+R+"(?::"+F+")?",K=f+"*",ae=f+"+",Pe="(?:\\/"+K+")*",We="\\/(?:"+ae+Pe+")?",Yt=ae+Pe;ut.rfc3986.hierPart="(?:(?:\\/\\/"+q+Pe+")"+r+We+r+Yt+")",ut.rfc3986.query="["+c+"\\/\\?]*(?=#|$)",ut.rfc3986.fragment="["+c+"\\/\\?]*",ut.rfc3986.uri="^(?:"+ut.rfc3986.scheme+":"+ut.rfc3986.hierPart+")(?:\\?"+ut.rfc3986.query+")?(?:#"+ut.rfc3986.fragment+")?$"};ut.generate();ON.exports=ut.rfc3986});var Px=v((sPe,MN)=>{"use strict";var vf=LN();function Ale(r){return r.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g,"\\$&")}var yf={Uri:{createUriRegex:function(r){if(r=r||{},typeof r!="object"||Array.isArray(r))throw new Error("options must be an object");var e="";if(r.scheme){if(Array.isArray(r.scheme)||(r.scheme=[r.scheme]),r.scheme.length<=0)throw new Error("scheme must have at least 1 scheme specified");for(var t=0;t{HN.exports=zN;zN.sync=Wle;var GN=require("fs");function Hle(r,e){var t=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!t||(t=t.split(";"),t.indexOf("")!==-1))return!0;for(var i=0;i{JN.exports=YN;YN.sync=zle;var XN=require("fs");function YN(r,e,t){XN.stat(r,function(i,n){t(i,i?!1:ZN(n,e))})}function zle(r,e){return ZN(XN.statSync(r),e)}function ZN(r,e){return r.isFile()&&Gle(r,e)}function Gle(r,e){var t=r.mode,i=r.uid,n=r.gid,o=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),s=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),a=parseInt("100",8),l=parseInt("010",8),u=parseInt("001",8),c=a|l,f=t&u||t&l&&n===s||t&a&&i===o||t&c&&o===0;return f}});var tq=v((fPe,eq)=>{var cPe=require("fs"),um;process.platform==="win32"||global.TESTING_WINDOWS?um=KN():um=QN();eq.exports=Rx;Rx.sync=Vle;function Rx(r,e,t){if(typeof e=="function"&&(t=e,e={}),!t){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(i,n){Rx(r,e||{},function(o,s){o?n(o):i(s)})})}um(r,e||{},function(i,n){i&&(i.code==="EACCES"||e&&e.ignoreErrors)&&(i=null,n=!1),t(i,n)})}function Vle(r,e){try{return um.sync(r,e||{})}catch(t){if(e&&e.ignoreErrors||t.code==="EACCES")return!1;throw t}}});var _l=v((pPe,rq)=>{var Cl=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",iq=require("path"),Kle=Cl?";":":",nq=tq(),oq=r=>Object.assign(new Error(`not found: ${r}`),{code:"ENOENT"}),sq=(r,e)=>{let t=e.colon||Kle,i=r.match(/\//)||Cl&&r.match(/\\/)?[""]:[...Cl?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(t)],n=Cl?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",o=Cl?n.split(t):[""];return Cl&&r.indexOf(".")!==-1&&o[0]!==""&&o.unshift(""),{pathEnv:i,pathExt:o,pathExtExe:n}},aq=(r,e,t)=>{typeof e=="function"&&(t=e,e={}),e||(e={});let{pathEnv:i,pathExt:n,pathExtExe:o}=sq(r,e),s=[],a=u=>new Promise((c,f)=>{if(u===i.length)return e.all&&s.length?c(s):f(oq(r));let p=i[u],d=/^".*"$/.test(p)?p.slice(1,-1):p,h=iq.join(d,r),m=!d&&/^\.[\\\/]/.test(r)?r.slice(0,2)+h:h;c(l(m,u,0))}),l=(u,c,f)=>new Promise((p,d)=>{if(f===n.length)return p(a(c+1));let h=n[f];nq(u+h,{pathExt:o},(m,y)=>{if(!m&&y)if(e.all)s.push(u+h);else return p(u+h);return p(l(u,c,f+1))})});return t?a(0).then(u=>t(null,u),t):a(0)},Jle=(r,e)=>{e=e||{};let{pathEnv:t,pathExt:i,pathExtExe:n}=sq(r,e),o=[];for(let s=0;s{var aue="2.0.0",lue=256,uue=Number.MAX_SAFE_INTEGER||9007199254740991,cue=16;vq.exports={SEMVER_SPEC_VERSION:aue,MAX_LENGTH:lue,MAX_SAFE_INTEGER:uue,MAX_SAFE_COMPONENT_LENGTH:cue}});var Sf=v((CPe,yq)=>{var fue=typeof process=="object"&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...r)=>console.error("SEMVER",...r):()=>{};yq.exports=fue});var Vs=v((qo,bq)=>{var{MAX_SAFE_COMPONENT_LENGTH:qx}=Df(),pue=Sf();qo=bq.exports={};var due=qo.re=[],Y=qo.src=[],X=qo.t={},hue=0,de=(r,e,t)=>{let i=hue++;pue(i,e),X[r]=i,Y[i]=e,due[i]=new RegExp(e,t?"g":void 0)};de("NUMERICIDENTIFIER","0|[1-9]\\d*");de("NUMERICIDENTIFIERLOOSE","[0-9]+");de("NONNUMERICIDENTIFIER","\\d*[a-zA-Z-][a-zA-Z0-9-]*");de("MAINVERSION",`(${Y[X.NUMERICIDENTIFIER]})\\.(${Y[X.NUMERICIDENTIFIER]})\\.(${Y[X.NUMERICIDENTIFIER]})`);de("MAINVERSIONLOOSE",`(${Y[X.NUMERICIDENTIFIERLOOSE]})\\.(${Y[X.NUMERICIDENTIFIERLOOSE]})\\.(${Y[X.NUMERICIDENTIFIERLOOSE]})`);de("PRERELEASEIDENTIFIER",`(?:${Y[X.NUMERICIDENTIFIER]}|${Y[X.NONNUMERICIDENTIFIER]})`);de("PRERELEASEIDENTIFIERLOOSE",`(?:${Y[X.NUMERICIDENTIFIERLOOSE]}|${Y[X.NONNUMERICIDENTIFIER]})`);de("PRERELEASE",`(?:-(${Y[X.PRERELEASEIDENTIFIER]}(?:\\.${Y[X.PRERELEASEIDENTIFIER]})*))`);de("PRERELEASELOOSE",`(?:-?(${Y[X.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${Y[X.PRERELEASEIDENTIFIERLOOSE]})*))`);de("BUILDIDENTIFIER","[0-9A-Za-z-]+");de("BUILD",`(?:\\+(${Y[X.BUILDIDENTIFIER]}(?:\\.${Y[X.BUILDIDENTIFIER]})*))`);de("FULLPLAIN",`v?${Y[X.MAINVERSION]}${Y[X.PRERELEASE]}?${Y[X.BUILD]}?`);de("FULL",`^${Y[X.FULLPLAIN]}$`);de("LOOSEPLAIN",`[v=\\s]*${Y[X.MAINVERSIONLOOSE]}${Y[X.PRERELEASELOOSE]}?${Y[X.BUILD]}?`);de("LOOSE",`^${Y[X.LOOSEPLAIN]}$`);de("GTLT","((?:<|>)?=?)");de("XRANGEIDENTIFIERLOOSE",`${Y[X.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);de("XRANGEIDENTIFIER",`${Y[X.NUMERICIDENTIFIER]}|x|X|\\*`);de("XRANGEPLAIN",`[v=\\s]*(${Y[X.XRANGEIDENTIFIER]})(?:\\.(${Y[X.XRANGEIDENTIFIER]})(?:\\.(${Y[X.XRANGEIDENTIFIER]})(?:${Y[X.PRERELEASE]})?${Y[X.BUILD]}?)?)?`);de("XRANGEPLAINLOOSE",`[v=\\s]*(${Y[X.XRANGEIDENTIFIERLOOSE]})(?:\\.(${Y[X.XRANGEIDENTIFIERLOOSE]})(?:\\.(${Y[X.XRANGEIDENTIFIERLOOSE]})(?:${Y[X.PRERELEASELOOSE]})?${Y[X.BUILD]}?)?)?`);de("XRANGE",`^${Y[X.GTLT]}\\s*${Y[X.XRANGEPLAIN]}$`);de("XRANGELOOSE",`^${Y[X.GTLT]}\\s*${Y[X.XRANGEPLAINLOOSE]}$`);de("COERCE",`(^|[^\\d])(\\d{1,${qx}})(?:\\.(\\d{1,${qx}}))?(?:\\.(\\d{1,${qx}}))?(?:$|[^\\d])`);de("COERCERTL",Y[X.COERCE],!0);de("LONETILDE","(?:~>?)");de("TILDETRIM",`(\\s*)${Y[X.LONETILDE]}\\s+`,!0);qo.tildeTrimReplace="$1~";de("TILDE",`^${Y[X.LONETILDE]}${Y[X.XRANGEPLAIN]}$`);de("TILDELOOSE",`^${Y[X.LONETILDE]}${Y[X.XRANGEPLAINLOOSE]}$`);de("LONECARET","(?:\\^)");de("CARETTRIM",`(\\s*)${Y[X.LONECARET]}\\s+`,!0);qo.caretTrimReplace="$1^";de("CARET",`^${Y[X.LONECARET]}${Y[X.XRANGEPLAIN]}$`);de("CARETLOOSE",`^${Y[X.LONECARET]}${Y[X.XRANGEPLAINLOOSE]}$`);de("COMPARATORLOOSE",`^${Y[X.GTLT]}\\s*(${Y[X.LOOSEPLAIN]})$|^$`);de("COMPARATOR",`^${Y[X.GTLT]}\\s*(${Y[X.FULLPLAIN]})$|^$`);de("COMPARATORTRIM",`(\\s*)${Y[X.GTLT]}\\s*(${Y[X.LOOSEPLAIN]}|${Y[X.XRANGEPLAIN]})`,!0);qo.comparatorTrimReplace="$1$2$3";de("HYPHENRANGE",`^\\s*(${Y[X.XRANGEPLAIN]})\\s+-\\s+(${Y[X.XRANGEPLAIN]})\\s*$`);de("HYPHENRANGELOOSE",`^\\s*(${Y[X.XRANGEPLAINLOOSE]})\\s+-\\s+(${Y[X.XRANGEPLAINLOOSE]})\\s*$`);de("STAR","(<|>)?=?\\s*\\*");de("GTE0","^\\s*>=\\s*0.0.0\\s*$");de("GTE0PRE","^\\s*>=\\s*0.0.0-0\\s*$")});var gm=v((_Pe,wq)=>{var xq=/^[0-9]+$/,Dq=(r,e)=>{let t=xq.test(r),i=xq.test(e);return t&&i&&(r=+r,e=+e),r===e?0:t&&!i?-1:i&&!t?1:rDq(e,r);wq.exports={compareIdentifiers:Dq,rcompareIdentifiers:mue}});var nr=v((PPe,Sq)=>{var vm=Sf(),{MAX_LENGTH:Eq,MAX_SAFE_INTEGER:ym}=Df(),{re:Cq,t:_q}=Vs(),{compareIdentifiers:Ef}=gm(),wi=class{constructor(e,t){if((!t||typeof t!="object")&&(t={loose:!!t,includePrerelease:!1}),e instanceof wi){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if(typeof e!="string")throw new TypeError(`Invalid Version: ${e}`);if(e.length>Eq)throw new TypeError(`version is longer than ${Eq} characters`);vm("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;let i=e.trim().match(t.loose?Cq[_q.LOOSE]:Cq[_q.FULL]);if(!i)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+i[1],this.minor=+i[2],this.patch=+i[3],this.major>ym||this.major<0)throw new TypeError("Invalid major version");if(this.minor>ym||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>ym||this.patch<0)throw new TypeError("Invalid patch version");i[4]?this.prerelease=i[4].split(".").map(n=>{if(/^[0-9]+$/.test(n)){let o=+n;if(o>=0&&o=0;)typeof this.prerelease[i]=="number"&&(this.prerelease[i]++,i=-2);i===-1&&this.prerelease.push(0)}t&&(this.prerelease[0]===t?isNaN(this.prerelease[1])&&(this.prerelease=[t,0]):this.prerelease=[t,0]);break;default:throw new Error(`invalid increment argument: ${e}`)}return this.format(),this.raw=this.version,this}};Sq.exports=wi});var Ks=v((TPe,Pq)=>{var{MAX_LENGTH:gue}=Df(),{re:Tq,t:Rq}=Vs(),kq=nr(),vue=(r,e)=>{if((!e||typeof e!="object")&&(e={loose:!!e,includePrerelease:!1}),r instanceof kq)return r;if(typeof r!="string"||r.length>gue||!(e.loose?Tq[Rq.LOOSE]:Tq[Rq.FULL]).test(r))return null;try{return new kq(r,e)}catch(i){return null}};Pq.exports=vue});var Fq=v((RPe,Iq)=>{var yue=Ks(),bue=(r,e)=>{let t=yue(r,e);return t?t.version:null};Iq.exports=bue});var Oq=v((kPe,Aq)=>{var wue=Ks(),xue=(r,e)=>{let t=wue(r.trim().replace(/^[=v]+/,""),e);return t?t.version:null};Aq.exports=xue});var Mq=v((IPe,Lq)=>{var Due=nr(),Sue=(r,e,t,i)=>{typeof t=="string"&&(i=t,t=void 0);try{return new Due(r,t).inc(e,i).version}catch(n){return null}};Lq.exports=Sue});var xi=v((FPe,Nq)=>{var qq=nr(),Eue=(r,e,t)=>new qq(r,t).compare(new qq(e,t));Nq.exports=Eue});var bm=v((APe,$q)=>{var Cue=xi(),_ue=(r,e,t)=>Cue(r,e,t)===0;$q.exports=_ue});var Uq=v((OPe,Bq)=>{var jq=Ks(),Pue=bm(),Tue=(r,e)=>{if(Pue(r,e))return null;{let t=jq(r),i=jq(e),n=t.prerelease.length||i.prerelease.length,o=n?"pre":"",s=n?"prerelease":"";for(let a in t)if((a==="major"||a==="minor"||a==="patch")&&t[a]!==i[a])return o+a;return s}};Bq.exports=Tue});var Hq=v((LPe,Wq)=>{var Rue=nr(),kue=(r,e)=>new Rue(r,e).major;Wq.exports=kue});var Gq=v((MPe,zq)=>{var Iue=nr(),Fue=(r,e)=>new Iue(r,e).minor;zq.exports=Fue});var Kq=v((NPe,Vq)=>{var Aue=nr(),Oue=(r,e)=>new Aue(r,e).patch;Vq.exports=Oue});var Yq=v((qPe,Jq)=>{var Lue=Ks(),Mue=(r,e)=>{let t=Lue(r,e);return t&&t.prerelease.length?t.prerelease:null};Jq.exports=Mue});var Zq=v(($Pe,Xq)=>{var Nue=xi(),que=(r,e,t)=>Nue(e,r,t);Xq.exports=que});var e2=v((BPe,Qq)=>{var $ue=xi(),Bue=(r,e)=>$ue(r,e,!0);Qq.exports=Bue});var wm=v((jPe,t2)=>{var r2=nr(),jue=(r,e,t)=>{let i=new r2(r,t),n=new r2(e,t);return i.compare(n)||i.compareBuild(n)};t2.exports=jue});var n2=v((UPe,i2)=>{var Uue=wm(),Wue=(r,e)=>r.sort((t,i)=>Uue(t,i,e));i2.exports=Wue});var s2=v((WPe,o2)=>{var Hue=wm(),zue=(r,e)=>r.sort((t,i)=>Hue(i,t,e));o2.exports=zue});var Cf=v((HPe,a2)=>{var Gue=xi(),Vue=(r,e,t)=>Gue(r,e,t)>0;a2.exports=Vue});var xm=v((zPe,l2)=>{var Kue=xi(),Jue=(r,e,t)=>Kue(r,e,t)<0;l2.exports=Jue});var $x=v((GPe,u2)=>{var Yue=xi(),Xue=(r,e,t)=>Yue(r,e,t)!==0;u2.exports=Xue});var Dm=v((VPe,c2)=>{var Zue=xi(),Que=(r,e,t)=>Zue(r,e,t)>=0;c2.exports=Que});var Sm=v((KPe,f2)=>{var ece=xi(),tce=(r,e,t)=>ece(r,e,t)<=0;f2.exports=tce});var Bx=v((JPe,p2)=>{var rce=bm(),ice=$x(),nce=Cf(),oce=Dm(),sce=xm(),ace=Sm(),lce=(r,e,t,i)=>{switch(e){case"===":return typeof r=="object"&&(r=r.version),typeof t=="object"&&(t=t.version),r===t;case"!==":return typeof r=="object"&&(r=r.version),typeof t=="object"&&(t=t.version),r!==t;case"":case"=":case"==":return rce(r,t,i);case"!=":return ice(r,t,i);case">":return nce(r,t,i);case">=":return oce(r,t,i);case"<":return sce(r,t,i);case"<=":return ace(r,t,i);default:throw new TypeError(`Invalid operator: ${e}`)}};p2.exports=lce});var h2=v((YPe,d2)=>{var uce=nr(),cce=Ks(),{re:Em,t:Cm}=Vs(),fce=(r,e)=>{if(r instanceof uce)return r;if(typeof r=="number"&&(r=String(r)),typeof r!="string")return null;e=e||{};let t=null;if(!e.rtl)t=r.match(Em[Cm.COERCE]);else{let i;for(;(i=Em[Cm.COERCERTL].exec(r))&&(!t||t.index+t[0].length!==r.length);)(!t||i.index+i[0].length!==t.index+t[0].length)&&(t=i),Em[Cm.COERCERTL].lastIndex=i.index+i[1].length+i[2].length;Em[Cm.COERCERTL].lastIndex=-1}return t===null?null:cce(`${t[2]}.${t[3]||"0"}.${t[4]||"0"}`,e)};d2.exports=fce});var Di=v((XPe,m2)=>{var Il=class{constructor(e,t){if((!t||typeof t!="object")&&(t={loose:!!t,includePrerelease:!1}),e instanceof Il)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new Il(e.raw,t);if(e instanceof jx)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e,this.set=e.split(/\s*\|\|\s*/).map(i=>this.parseRange(i.trim())).filter(i=>i.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${e}`);this.format()}format(){return this.range=this.set.map(e=>e.join(" ").trim()).join("||").trim(),this.range}toString(){return this.range}parseRange(e){let t=this.options.loose;e=e.trim();let i=t?or[Wt.HYPHENRANGELOOSE]:or[Wt.HYPHENRANGE];e=e.replace(i,yce(this.options.includePrerelease)),pt("hyphen replace",e),e=e.replace(or[Wt.COMPARATORTRIM],dce),pt("comparator trim",e,or[Wt.COMPARATORTRIM]),e=e.replace(or[Wt.TILDETRIM],hce),e=e.replace(or[Wt.CARETTRIM],mce),e=e.split(/\s+/).join(" ");let n=t?or[Wt.COMPARATORLOOSE]:or[Wt.COMPARATOR];return e.split(" ").map(o=>gce(o,this.options)).join(" ").split(/\s+/).map(o=>vce(o,this.options)).filter(this.options.loose?o=>!!o.match(n):()=>!0).map(o=>new jx(o,this.options))}intersects(e,t){if(!(e instanceof Il))throw new TypeError("a Range is required");return this.set.some(i=>g2(i,t)&&e.set.some(n=>g2(n,t)&&i.every(o=>n.every(s=>o.intersects(s,t)))))}test(e){if(!e)return!1;if(typeof e=="string")try{e=new pce(e,this.options)}catch(t){return!1}for(let t=0;t{let t=!0,i=r.slice(),n=i.pop();for(;t&&i.length;)t=i.every(o=>n.intersects(o,e)),n=i.pop();return t},gce=(r,e)=>(pt("comp",r,e),r=xce(r,e),pt("caret",r),r=wce(r,e),pt("tildes",r),r=Dce(r,e),pt("xrange",r),r=Sce(r,e),pt("stars",r),r),wr=r=>!r||r.toLowerCase()==="x"||r==="*",wce=(r,e)=>r.trim().split(/\s+/).map(t=>Ece(t,e)).join(" "),Ece=(r,e)=>{let t=e.loose?or[Wt.TILDELOOSE]:or[Wt.TILDE];return r.replace(t,(i,n,o,s,a)=>{pt("tilde",r,i,n,o,s,a);let l;return wr(n)?l="":wr(o)?l=`>=${n}.0.0 <${+n+1}.0.0-0`:wr(s)?l=`>=${n}.${o}.0 <${n}.${+o+1}.0-0`:a?(pt("replaceTilde pr",a),l=`>=${n}.${o}.${s}-${a} <${n}.${+o+1}.0-0`):l=`>=${n}.${o}.${s} <${n}.${+o+1}.0-0`,pt("tilde return",l),l})},xce=(r,e)=>r.trim().split(/\s+/).map(t=>Cce(t,e)).join(" "),Cce=(r,e)=>{pt("caret",r,e);let t=e.loose?or[Wt.CARETLOOSE]:or[Wt.CARET],i=e.includePrerelease?"-0":"";return r.replace(t,(n,o,s,a,l)=>{pt("caret",r,n,o,s,a,l);let u;return wr(o)?u="":wr(s)?u=`>=${o}.0.0${i} <${+o+1}.0.0-0`:wr(a)?o==="0"?u=`>=${o}.${s}.0${i} <${o}.${+s+1}.0-0`:u=`>=${o}.${s}.0${i} <${+o+1}.0.0-0`:l?(pt("replaceCaret pr",l),o==="0"?s==="0"?u=`>=${o}.${s}.${a}-${l} <${o}.${s}.${+a+1}-0`:u=`>=${o}.${s}.${a}-${l} <${o}.${+s+1}.0-0`:u=`>=${o}.${s}.${a}-${l} <${+o+1}.0.0-0`):(pt("no pr"),o==="0"?s==="0"?u=`>=${o}.${s}.${a}${i} <${o}.${s}.${+a+1}-0`:u=`>=${o}.${s}.${a}${i} <${o}.${+s+1}.0-0`:u=`>=${o}.${s}.${a} <${+o+1}.0.0-0`),pt("caret return",u),u})},Dce=(r,e)=>(pt("replaceXRanges",r,e),r.split(/\s+/).map(t=>_ce(t,e)).join(" ")),_ce=(r,e)=>{r=r.trim();let t=e.loose?or[Wt.XRANGELOOSE]:or[Wt.XRANGE];return r.replace(t,(i,n,o,s,a,l)=>{pt("xRange",r,i,n,o,s,a,l);let u=wr(o),c=u||wr(s),f=c||wr(a),p=f;return n==="="&&p&&(n=""),l=e.includePrerelease?"-0":"",u?n===">"||n==="<"?i="<0.0.0-0":i="*":n&&p?(c&&(s=0),a=0,n===">"?(n=">=",c?(o=+o+1,s=0,a=0):(s=+s+1,a=0)):n==="<="&&(n="<",c?o=+o+1:s=+s+1),n==="<"&&(l="-0"),i=`${n+o}.${s}.${a}${l}`):c?i=`>=${o}.0.0${l} <${+o+1}.0.0-0`:f&&(i=`>=${o}.${s}.0${l} <${o}.${+s+1}.0-0`),pt("xRange return",i),i})},Sce=(r,e)=>(pt("replaceStars",r,e),r.trim().replace(or[Wt.STAR],"")),vce=(r,e)=>(pt("replaceGTE0",r,e),r.trim().replace(or[e.includePrerelease?Wt.GTE0PRE:Wt.GTE0],"")),yce=r=>(e,t,i,n,o,s,a,l,u,c,f,p,d)=>(wr(i)?t="":wr(n)?t=`>=${i}.0.0${r?"-0":""}`:wr(o)?t=`>=${i}.${n}.0${r?"-0":""}`:s?t=`>=${t}`:t=`>=${t}${r?"-0":""}`,wr(u)?l="":wr(c)?l=`<${+u+1}.0.0-0`:wr(f)?l=`<${u}.${+c+1}.0-0`:p?l=`<=${u}.${c}.${f}-${p}`:r?l=`<${u}.${c}.${+f+1}-0`:l=`<=${l}`,`${t} ${l}`.trim()),bce=(r,e,t)=>{for(let i=0;i0){let n=r[i].semver;if(n.major===e.major&&n.minor===e.minor&&n.patch===e.patch)return!0}return!1}return!0}});var _f=v((ZPe,v2)=>{var Pf=Symbol("SemVer ANY"),Tf=class{static get ANY(){return Pf}constructor(e,t){if((!t||typeof t!="object")&&(t={loose:!!t,includePrerelease:!1}),e instanceof Tf){if(e.loose===!!t.loose)return e;e=e.value}Wx("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===Pf?this.value="":this.value=this.operator+this.semver.version,Wx("comp",this)}parse(e){let t=this.options.loose?y2[b2.COMPARATORLOOSE]:y2[b2.COMPARATOR],i=e.match(t);if(!i)throw new TypeError(`Invalid comparator: ${e}`);this.operator=i[1]!==void 0?i[1]:"",this.operator==="="&&(this.operator=""),i[2]?this.semver=new w2(i[2],this.options.loose):this.semver=Pf}toString(){return this.value}test(e){if(Wx("Comparator.test",e,this.options.loose),this.semver===Pf||e===Pf)return!0;if(typeof e=="string")try{e=new w2(e,this.options)}catch(t){return!1}return Ux(e,this.operator,this.semver,this.options)}intersects(e,t){if(!(e instanceof Tf))throw new TypeError("a Comparator is required");if((!t||typeof t!="object")&&(t={loose:!!t,includePrerelease:!1}),this.operator==="")return this.value===""?!0:new x2(e.value,t).test(this.value);if(e.operator==="")return e.value===""?!0:new x2(this.value,t).test(e.semver);let i=(this.operator===">="||this.operator===">")&&(e.operator===">="||e.operator===">"),n=(this.operator==="<="||this.operator==="<")&&(e.operator==="<="||e.operator==="<"),o=this.semver.version===e.semver.version,s=(this.operator===">="||this.operator==="<=")&&(e.operator===">="||e.operator==="<="),a=Ux(this.semver,"<",e.semver,t)&&(this.operator===">="||this.operator===">")&&(e.operator==="<="||e.operator==="<"),l=Ux(this.semver,">",e.semver,t)&&(this.operator==="<="||this.operator==="<")&&(e.operator===">="||e.operator===">");return i||n||o&&s||a||l}};v2.exports=Tf;var{re:y2,t:b2}=Vs(),Ux=Bx(),Wx=Sf(),w2=nr(),x2=Di()});var Rf=v((QPe,D2)=>{var Pce=Di(),Tce=(r,e,t)=>{try{e=new Pce(e,t)}catch(i){return!1}return e.test(r)};D2.exports=Tce});var E2=v((eTe,S2)=>{var Rce=Di(),kce=(r,e)=>new Rce(r,e).set.map(t=>t.map(i=>i.value).join(" ").trim().split(" "));S2.exports=kce});var _2=v((tTe,C2)=>{var Ice=nr(),Fce=Di(),Ace=(r,e,t)=>{let i=null,n=null,o=null;try{o=new Fce(e,t)}catch(s){return null}return r.forEach(s=>{o.test(s)&&(!i||n.compare(s)===-1)&&(i=s,n=new Ice(i,t))}),i};C2.exports=Ace});var T2=v((rTe,P2)=>{var Oce=nr(),Lce=Di(),Mce=(r,e,t)=>{let i=null,n=null,o=null;try{o=new Lce(e,t)}catch(s){return null}return r.forEach(s=>{o.test(s)&&(!i||n.compare(s)===1)&&(i=s,n=new Oce(i,t))}),i};P2.exports=Mce});var k2=v((iTe,R2)=>{var Hx=nr(),Nce=Di(),qce=Cf(),$ce=(r,e)=>{r=new Nce(r,e);let t=new Hx("0.0.0");if(r.test(t)||(t=new Hx("0.0.0-0"),r.test(t)))return t;t=null;for(let i=0;i{let s=new Hx(o.semver.version);switch(o.operator){case">":s.prerelease.length===0?s.patch++:s.prerelease.push(0),s.raw=s.format();case"":case">=":(!t||qce(t,s))&&(t=s);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${o.operator}`)}});return t&&r.test(t)?t:null};R2.exports=$ce});var F2=v((nTe,I2)=>{var Bce=Di(),jce=(r,e)=>{try{return new Bce(r,e).range||"*"}catch(t){return null}};I2.exports=jce});var _m=v((oTe,A2)=>{var Uce=nr(),O2=_f(),{ANY:Wce}=O2,Hce=Di(),zce=Rf(),L2=Cf(),M2=xm(),Gce=Sm(),Vce=Dm(),Kce=(r,e,t,i)=>{r=new Uce(r,i),e=new Hce(e,i);let n,o,s,a,l;switch(t){case">":n=L2,o=Gce,s=M2,a=">",l=">=";break;case"<":n=M2,o=Vce,s=L2,a="<",l="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(zce(r,e,i))return!1;for(let u=0;u{d.semver===Wce&&(d=new O2(">=0.0.0")),f=f||d,p=p||d,n(d.semver,f.semver,i)?f=d:s(d.semver,p.semver,i)&&(p=d)}),f.operator===a||f.operator===l||(!p.operator||p.operator===a)&&o(r,p.semver))return!1;if(p.operator===l&&s(r,p.semver))return!1}return!0};A2.exports=Kce});var q2=v((sTe,N2)=>{var Jce=_m(),Yce=(r,e,t)=>Jce(r,e,">",t);N2.exports=Yce});var B2=v((aTe,$2)=>{var Xce=_m(),Zce=(r,e,t)=>Xce(r,e,"<",t);$2.exports=Zce});var W2=v((lTe,j2)=>{var U2=Di(),Qce=(r,e,t)=>(r=new U2(r,t),e=new U2(e,t),r.intersects(e));j2.exports=Qce});var z2=v((uTe,H2)=>{var efe=Rf(),tfe=xi();H2.exports=(r,e,t)=>{let i=[],n=null,o=null,s=r.sort((c,f)=>tfe(c,f,t));for(let c of s)efe(c,e,t)?(o=c,n||(n=c)):(o&&i.push([n,o]),o=null,n=null);n&&i.push([n,null]);let a=[];for(let[c,f]of i)c===f?a.push(c):!f&&c===s[0]?a.push("*"):f?c===s[0]?a.push(`<=${f}`):a.push(`${c} - ${f}`):a.push(`>=${c}`);let l=a.join(" || "),u=typeof e.raw=="string"?e.raw:String(e);return l.length{var V2=Di(),{ANY:K2}=_f(),kf=Rf(),zx=xi(),ife=(r,e,t)=>{r=new V2(r,t),e=new V2(e,t);let i=!1;e:for(let n of r.set){for(let o of e.set){let s=rfe(n,o,t);if(i=i||s!==null,s)continue e}if(i)return!1}return!0},rfe=(r,e,t)=>{if(r.length===1&&r[0].semver===K2)return e.length===1&&e[0].semver===K2;let i=new Set,n,o;for(let f of r)f.operator===">"||f.operator===">="?n=J2(n,f,t):f.operator==="<"||f.operator==="<="?o=Y2(o,f,t):i.add(f.semver);if(i.size>1)return null;let s;if(n&&o){if(s=zx(n.semver,o.semver,t),s>0)return null;if(s===0&&(n.operator!==">="||o.operator!=="<="))return null}for(let f of i){if(n&&!kf(f,String(n),t)||o&&!kf(f,String(o),t))return null;for(let p of e)if(!kf(f,String(p),t))return!1;return!0}let a,l,u,c;for(let f of e){if(c=c||f.operator===">"||f.operator===">=",u=u||f.operator==="<"||f.operator==="<=",n){if(f.operator===">"||f.operator===">="){if(a=J2(n,f,t),a===f)return!1}else if(n.operator===">="&&!kf(n.semver,String(f),t))return!1}if(o){if(f.operator==="<"||f.operator==="<="){if(l=Y2(o,f,t),l===f)return!1}else if(o.operator==="<="&&!kf(o.semver,String(f),t))return!1}if(!f.operator&&(o||n)&&s!==0)return!1}return!(n&&u&&!o&&s!==0||o&&c&&!n&&s!==0)},J2=(r,e,t)=>{if(!r)return e;let i=zx(r.semver,e.semver,t);return i>0?r:i<0||e.operator===">"&&r.operator===">="?e:r},Y2=(r,e,t)=>{if(!r)return e;let i=zx(r.semver,e.semver,t);return i<0?r:i>0||e.operator==="<"&&r.operator==="<="?e:r};G2.exports=ife});var If=v((fTe,Z2)=>{var Gx=Vs();Z2.exports={re:Gx.re,src:Gx.src,tokens:Gx.t,SEMVER_SPEC_VERSION:Df().SEMVER_SPEC_VERSION,SemVer:nr(),compareIdentifiers:gm().compareIdentifiers,rcompareIdentifiers:gm().rcompareIdentifiers,parse:Ks(),valid:Fq(),clean:Oq(),inc:Mq(),diff:Uq(),major:Hq(),minor:Gq(),patch:Kq(),prerelease:Yq(),compare:xi(),rcompare:Zq(),compareLoose:e2(),compareBuild:wm(),sort:n2(),rsort:s2(),gt:Cf(),lt:xm(),eq:bm(),neq:$x(),gte:Dm(),lte:Sm(),cmp:Bx(),coerce:h2(),Comparator:_f(),Range:Di(),satisfies:Rf(),toComparators:E2(),maxSatisfying:_2(),minSatisfying:T2(),minVersion:k2(),validRange:F2(),outside:_m(),gtr:q2(),ltr:B2(),intersects:W2(),simplifyRange:z2(),subset:X2()}});var Fl=v((pTe,Vx)=>{function Q2(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:null,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tokenizer:null,walkTokens:null,xhtml:!1}}function nfe(r){Vx.exports.defaults=r}Vx.exports={defaults:Q2(),getDefaults:Q2,changeDefaults:nfe}});var Js=v((dTe,e$)=>{var ofe=/[&<>"']/,sfe=/[&<>"']/g,afe=/[<>"']|&(?!#?\w+;)/,lfe=/[<>"']|&(?!#?\w+;)/g,ufe={"&":"&","<":"<",">":">",'"':""","'":"'"},t$=r=>ufe[r];function cfe(r,e){if(e){if(ofe.test(r))return r.replace(sfe,t$)}else if(afe.test(r))return r.replace(lfe,t$);return r}var ffe=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;function r$(r){return r.replace(ffe,(e,t)=>(t=t.toLowerCase(),t==="colon"?":":t.charAt(0)==="#"?t.charAt(1)==="x"?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""))}var pfe=/(^|[^\[])\^/g;function dfe(r,e){r=r.source||r,e=e||"";let t={replace:(i,n)=>(n=n.source||n,n=n.replace(pfe,"$1"),r=r.replace(i,n),t),getRegex:()=>new RegExp(r,e)};return t}var hfe=/[^\w:]/g,mfe=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function gfe(r,e,t){if(r){let i;try{i=decodeURIComponent(r$(t)).replace(hfe,"").toLowerCase()}catch(n){return null}if(i.indexOf("javascript:")===0||i.indexOf("vbscript:")===0||i.indexOf("data:")===0)return null}e&&!mfe.test(t)&&(t=i$(e,t));try{t=encodeURI(t).replace(/%25/g,"%")}catch(i){return null}return t}var Pm={},vfe=/^[^:]+:\/*[^/]*$/,yfe=/^([^:]+:)[\s\S]*$/,bfe=/^([^:]+:\/*[^/]*)[\s\S]*$/;function i$(r,e){Pm[" "+r]||(vfe.test(r)?Pm[" "+r]=r+"/":Pm[" "+r]=n$(r,"/",!0)),r=Pm[" "+r];let t=r.indexOf(":")===-1;return e.substring(0,2)==="//"?t?e:r.replace(yfe,"$1")+e:e.charAt(0)==="/"?t?e:r.replace(bfe,"$1")+e:r+e}var wfe={exec:function(){}};function xfe(r){let e=1,t,i;for(;e{let l=!1,u=s;for(;--u>=0&&a[u]==="\\";)l=!l;return l?"|":" |"}),i=t.split(/ \|/),n=0;if(i.length>e)i.splice(e);else for(;i.length1;)e&1&&(t+=r),e>>=1,r+=r;return t+r}e$.exports={escape:cfe,unescape:r$,edit:dfe,cleanUrl:gfe,resolveUrl:i$,noopTest:wfe,merge:xfe,splitCells:Dfe,rtrim:n$,findClosingBracket:Sfe,checkSanitizeDeprecation:Efe,repeatString:Cfe}});var Kx=v((mTe,o$)=>{var{defaults:_fe}=Fl(),{rtrim:Pfe,splitCells:Tm,escape:Si,findClosingBracket:Tfe}=Js();function s$(r,e,t){let i=e.href,n=e.title?Si(e.title):null,o=r[1].replace(/\\([\[\]])/g,"$1");return r[0].charAt(0)!=="!"?{type:"link",raw:t,href:i,title:n,text:o}:{type:"image",raw:t,href:i,title:n,text:Si(o)}}function Rfe(r,e){let t=r.match(/^(\s+)(?:```)/);if(t===null)return e;let i=t[1];return e.split(` -`).map(n=>{let o=n.match(/^\s+/);if(o===null)return n;let[s]=o;return s.length>=i.length?n.slice(i.length):n}).join(` -`)}o$.exports=class{constructor(e){this.options=e||_fe}space(e){let t=this.rules.block.newline.exec(e);if(t)return t[0].length>1?{type:"space",raw:t[0]}:{raw:` -`}}code(e,t){let i=this.rules.block.code.exec(e);if(i){let n=t[t.length-1];if(n&&n.type==="paragraph")return{raw:i[0],text:i[0].trimRight()};let o=i[0].replace(/^ {4}/gm,"");return{type:"code",raw:i[0],codeBlockStyle:"indented",text:this.options.pedantic?o:Pfe(o,` -`)}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let i=t[0],n=Rfe(i,t[3]||"");return{type:"code",raw:i,lang:t[2]?t[2].trim():t[2],text:n}}}heading(e){let t=this.rules.block.heading.exec(e);if(t)return{type:"heading",raw:t[0],depth:t[1].length,text:t[2]}}nptable(e){let t=this.rules.block.nptable.exec(e);if(t){let i={type:"table",header:Tm(t[1].replace(/^ *| *\| *$/g,"")),align:t[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:t[3]?t[3].replace(/\n$/,"").split(` -`):[],raw:t[0]};if(i.header.length===i.align.length){let n=i.align.length,o;for(o=0;o ?/gm,"");return{type:"blockquote",raw:t[0],text:i}}}list(e){let t=this.rules.block.list.exec(e);if(t){let i=t[0],n=t[2],o=n.length>1,s={type:"list",raw:i,ordered:o,start:o?+n.slice(0,-1):"",loose:!1,items:[]},a=t[0].match(this.rules.block.item),l=!1,u,c,f,p,d,h,m,y,g=a.length;f=this.rules.block.listItemStart.exec(a[0]);for(let w=0;wf[0].length||p[1].length>3){a.splice(w,2,a[w]+` -`+a[w+1]),w--,g--;continue}else(!this.options.pedantic||this.options.smartLists?p[2][p[2].length-1]!==n[n.length-1]:o===(p[2].length===1))&&(d=a.slice(w+1).join(` -`),s.raw=s.raw.substring(0,s.raw.length-d.length),w=g-1);f=p}c=u.length,u=u.replace(/^ *([*+-]|\d+[.)]) ?/,""),~u.indexOf(` - `)&&(c-=u.length,u=this.options.pedantic?u.replace(/^ {1,4}/gm,""):u.replace(new RegExp("^ {1,"+c+"}","gm"),"")),h=l||/\n\n(?!\s*$)/.test(u),w!==g-1&&(l=u.charAt(u.length-1)===` -`,h||(h=l)),h&&(s.loose=!0),this.options.gfm&&(m=/^\[[ xX]\] /.test(u),y=void 0,m&&(y=u[1]!==" ",u=u.replace(/^\[[ xX]\] +/,""))),s.items.push({type:"list_item",raw:i,task:m,checked:y,loose:h,text:u})}return s}}html(e){let t=this.rules.block.html.exec(e);if(t)return{type:this.options.sanitize?"paragraph":"html",raw:t[0],pre:!this.options.sanitizer&&(t[1]==="pre"||t[1]==="script"||t[1]==="style"),text:this.options.sanitize?this.options.sanitizer?this.options.sanitizer(t[0]):Si(t[0]):t[0]}}def(e){let t=this.rules.block.def.exec(e);if(t)return t[3]&&(t[3]=t[3].substring(1,t[3].length-1)),{tag:t[1].toLowerCase().replace(/\s+/g," "),raw:t[0],href:t[2],title:t[3]}}table(e){let t=this.rules.block.table.exec(e);if(t){let i={type:"table",header:Tm(t[1].replace(/^ *| *\| *$/g,"")),align:t[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:t[3]?t[3].replace(/\n$/,"").split(` -`):[]};if(i.header.length===i.align.length){i.raw=t[0];let n=i.align.length,o;for(o=0;o/i.test(n[0])&&(t=!1),!i&&/^<(pre|code|kbd|script)(\s|>)/i.test(n[0])?i=!0:i&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(n[0])&&(i=!1),{type:this.options.sanitize?"text":"html",raw:n[0],inLink:t,inRawBlock:i,text:this.options.sanitize?this.options.sanitizer?this.options.sanitizer(n[0]):Si(n[0]):n[0]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let i=Tfe(t[2],"()");if(i>-1){let l=(t[0].indexOf("!")===0?5:4)+t[1].length+i;t[2]=t[2].substring(0,i),t[0]=t[0].substring(0,l).trim(),t[3]=""}let n=t[2],o="";if(this.options.pedantic){let a=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(n);a?(n=a[1],o=a[3]):o=""}else o=t[3]?t[3].slice(1,-1):"";return n=n.trim().replace(/^<([\s\S]*)>$/,"$1"),s$(t,{href:n&&n.replace(this.rules.inline._escapes,"$1"),title:o&&o.replace(this.rules.inline._escapes,"$1")},t[0])}}reflink(e,t){let i;if((i=this.rules.inline.reflink.exec(e))||(i=this.rules.inline.nolink.exec(e))){let n=(i[2]||i[1]).replace(/\s+/g," ");if(n=t[n.toLowerCase()],!n||!n.href){let s=i[0].charAt(0);return{type:"text",raw:s,text:s}}return s$(i,n,i[0])}}strong(e,t,i=""){let n=this.rules.inline.strong.start.exec(e);if(n&&(!n[1]||n[1]&&(i===""||this.rules.inline.punctuation.exec(i)))){t=t.slice(-1*e.length);let o=n[0]==="**"?this.rules.inline.strong.endAst:this.rules.inline.strong.endUnd;o.lastIndex=0;let s;for(;(n=o.exec(t))!=null;)if(s=this.rules.inline.strong.middle.exec(t.slice(0,n.index+3)),s)return{type:"strong",raw:e.slice(0,s[0].length),text:e.slice(2,s[0].length-2)}}}em(e,t,i=""){let n=this.rules.inline.em.start.exec(e);if(n&&(!n[1]||n[1]&&(i===""||this.rules.inline.punctuation.exec(i)))){t=t.slice(-1*e.length);let o=n[0]==="*"?this.rules.inline.em.endAst:this.rules.inline.em.endUnd;o.lastIndex=0;let s;for(;(n=o.exec(t))!=null;)if(s=this.rules.inline.em.middle.exec(t.slice(0,n.index+2)),s)return{type:"em",raw:e.slice(0,s[0].length),text:e.slice(1,s[0].length-1)}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){let i=t[2].replace(/\n/g," "),n=/[^ ]/.test(i),o=i.startsWith(" ")&&i.endsWith(" ");return n&&o&&(i=i.substring(1,i.length-1)),i=Si(i,!0),{type:"codespan",raw:t[0],text:i}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){let t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2]}}autolink(e,t){let i=this.rules.inline.autolink.exec(e);if(i){let n,o;return i[2]==="@"?(n=Si(this.options.mangle?t(i[1]):i[1]),o="mailto:"+n):(n=Si(i[1]),o=n),{type:"link",raw:i[0],text:n,href:o,tokens:[{type:"text",raw:n,text:n}]}}}url(e,t){let i;if(i=this.rules.inline.url.exec(e)){let n,o;if(i[2]==="@")n=Si(this.options.mangle?t(i[0]):i[0]),o="mailto:"+n;else{let s;do s=i[0],i[0]=this.rules.inline._backpedal.exec(i[0])[0];while(s!==i[0]);n=Si(i[0]),i[1]==="www."?o="http://"+n:o=n}return{type:"link",raw:i[0],text:n,href:o,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(e,t,i){let n=this.rules.inline.text.exec(e);if(n){let o;return t?o=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(n[0]):Si(n[0]):n[0]:o=Si(this.options.smartypants?i(n[0]):n[0]),{type:"text",raw:n[0],text:o}}}}});var l$=v((gTe,a$)=>{var{noopTest:Ff,edit:Te,merge:Ys}=Js(),se={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:/^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,nptable:Ff,table:Ff,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,text:/^[^\n]+/};se._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;se._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;se.def=Te(se.def).replace("label",se._label).replace("title",se._title).getRegex();se.bullet=/(?:[*+-]|\d{1,9}[.)])/;se.item=/^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/;se.item=Te(se.item,"gm").replace(/bull/g,se.bullet).getRegex();se.listItemStart=Te(/^( *)(bull)/).replace("bull",se.bullet).getRegex();se.list=Te(se.list).replace(/bull/g,se.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+se.def.source+")").getRegex();se._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";se._comment=/|$)/;se.html=Te(se.html,"i").replace("comment",se._comment).replace("tag",se._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();se.paragraph=Te(se._paragraph).replace("hr",se.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",se._tag).getRegex();se.blockquote=Te(se.blockquote).replace("paragraph",se.paragraph).getRegex();se.normal=Ys({},se);se.gfm=Ys({},se.normal,{nptable:"^ *([^|\\n ].*\\|.*)\\n {0,3}([-:]+ *\\|[-| :]*)(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)",table:"^ *\\|(.+)\\n {0,3}\\|?( *[-:]+[-| :]*)(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"});se.gfm.nptable=Te(se.gfm.nptable).replace("hr",se.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",se._tag).getRegex();se.gfm.table=Te(se.gfm.table).replace("hr",se.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",se._tag).getRegex();se.pedantic=Ys({},se.normal,{html:Te(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",se._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,fences:Ff,paragraph:Te(se.normal._paragraph).replace("hr",se.hr).replace("heading",` *#{1,6} *[^ -]`).replace("lheading",se.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()});var H={escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:Ff,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,reflinkSearch:"reflink|nolink(?!\\()",strong:{start:/^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/,middle:/^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,endAst:/[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/,endUnd:/[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/},em:{start:/^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/,middle:/^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,endAst:/[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/,endUnd:/[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/},code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:Ff,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~";H.punctuation=Te(H.punctuation).replace(/punctuation/g,H._punctuation).getRegex();H._blockSkip="\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>";H._overlapSkip="__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*";H._comment=Te(se._comment).replace("(?:-->|$)","-->").getRegex();H.em.start=Te(H.em.start).replace(/punctuation/g,H._punctuation).getRegex();H.em.middle=Te(H.em.middle).replace(/punctuation/g,H._punctuation).replace(/overlapSkip/g,H._overlapSkip).getRegex();H.em.endAst=Te(H.em.endAst,"g").replace(/punctuation/g,H._punctuation).getRegex();H.em.endUnd=Te(H.em.endUnd,"g").replace(/punctuation/g,H._punctuation).getRegex();H.strong.start=Te(H.strong.start).replace(/punctuation/g,H._punctuation).getRegex();H.strong.middle=Te(H.strong.middle).replace(/punctuation/g,H._punctuation).replace(/overlapSkip/g,H._overlapSkip).getRegex();H.strong.endAst=Te(H.strong.endAst,"g").replace(/punctuation/g,H._punctuation).getRegex();H.strong.endUnd=Te(H.strong.endUnd,"g").replace(/punctuation/g,H._punctuation).getRegex();H.blockSkip=Te(H._blockSkip,"g").getRegex();H.overlapSkip=Te(H._overlapSkip,"g").getRegex();H._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;H._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;H._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;H.autolink=Te(H.autolink).replace("scheme",H._scheme).replace("email",H._email).getRegex();H._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;H.tag=Te(H.tag).replace("comment",H._comment).replace("attribute",H._attribute).getRegex();H._label=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;H._href=/<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/;H._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;H.link=Te(H.link).replace("label",H._label).replace("href",H._href).replace("title",H._title).getRegex();H.reflink=Te(H.reflink).replace("label",H._label).getRegex();H.reflinkSearch=Te(H.reflinkSearch,"g").replace("reflink",H.reflink).replace("nolink",H.nolink).getRegex();H.normal=Ys({},H);H.pedantic=Ys({},H.normal,{strong:{start:/^__|\*\*/,middle:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,endAst:/\*\*(?!\*)/g,endUnd:/__(?!_)/g},em:{start:/^_|\*/,middle:/^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,endAst:/\*(?!\*)/g,endUnd:/_(?!_)/g},link:Te(/^!?\[(label)\]\((.*?)\)/).replace("label",H._label).getRegex(),reflink:Te(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",H._label).getRegex()});H.gfm=Ys({},H.normal,{escape:Te(H.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\{var kfe=Kx(),{defaults:Ife}=Fl(),{block:Rm,inline:Af}=l$(),{repeatString:c$}=Js();function Ffe(r){return r.replace(/---/g,"\u2014").replace(/--/g,"\u2013").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1\u2018").replace(/'/g,"\u2019").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1\u201C").replace(/"/g,"\u201D").replace(/\.{3}/g,"\u2026")}function f$(r){let e="",t,i,n=r.length;for(t=0;t.5&&(i="x"+i.toString(16)),e+="&#"+i+";";return e}u$.exports=class Jx{constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||Ife,this.options.tokenizer=this.options.tokenizer||new kfe,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options;let t={block:Rm.normal,inline:Af.normal};this.options.pedantic?(t.block=Rm.pedantic,t.inline=Af.pedantic):this.options.gfm&&(t.block=Rm.gfm,this.options.breaks?t.inline=Af.breaks:t.inline=Af.gfm),this.tokenizer.rules=t}static get rules(){return{block:Rm,inline:Af}}static lex(e,t){return new Jx(t).lex(e)}static lexInline(e,t){return new Jx(t).inlineTokens(e)}lex(e){return e=e.replace(/\r\n|\r/g,` -`).replace(/\t/g," "),this.blockTokens(e,this.tokens,!0),this.inline(this.tokens),this.tokens}blockTokens(e,t=[],i=!0){e=e.replace(/^ +$/gm,"");let n,o,s,a;for(;e;){if(n=this.tokenizer.space(e)){e=e.substring(n.raw.length),n.type&&t.push(n);continue}if(n=this.tokenizer.code(e,t)){e=e.substring(n.raw.length),n.type?t.push(n):(a=t[t.length-1],a.raw+=` -`+n.raw,a.text+=` -`+n.text);continue}if(n=this.tokenizer.fences(e)){e=e.substring(n.raw.length),t.push(n);continue}if(n=this.tokenizer.heading(e)){e=e.substring(n.raw.length),t.push(n);continue}if(n=this.tokenizer.nptable(e)){e=e.substring(n.raw.length),t.push(n);continue}if(n=this.tokenizer.hr(e)){e=e.substring(n.raw.length),t.push(n);continue}if(n=this.tokenizer.blockquote(e)){e=e.substring(n.raw.length),n.tokens=this.blockTokens(n.text,[],i),t.push(n);continue}if(n=this.tokenizer.list(e)){for(e=e.substring(n.raw.length),s=n.items.length,o=0;o0)for(;(a=this.tokenizer.rules.inline.reflinkSearch.exec(s))!=null;)c.includes(a[0].slice(a[0].lastIndexOf("[")+1,-1))&&(s=s.slice(0,a.index)+"["+c$("a",a[0].length-2)+"]"+s.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(a=this.tokenizer.rules.inline.blockSkip.exec(s))!=null;)s=s.slice(0,a.index)+"["+c$("a",a[0].length-2)+"]"+s.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;e;){if(l||(u=""),l=!1,o=this.tokenizer.escape(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.tag(e,i,n)){e=e.substring(o.raw.length),i=o.inLink,n=o.inRawBlock,t.push(o);continue}if(o=this.tokenizer.link(e)){e=e.substring(o.raw.length),o.type==="link"&&(o.tokens=this.inlineTokens(o.text,[],!0,n)),t.push(o);continue}if(o=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(o.raw.length),o.type==="link"&&(o.tokens=this.inlineTokens(o.text,[],!0,n)),t.push(o);continue}if(o=this.tokenizer.strong(e,s,u)){e=e.substring(o.raw.length),o.tokens=this.inlineTokens(o.text,[],i,n),t.push(o);continue}if(o=this.tokenizer.em(e,s,u)){e=e.substring(o.raw.length),o.tokens=this.inlineTokens(o.text,[],i,n),t.push(o);continue}if(o=this.tokenizer.codespan(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.br(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.del(e)){e=e.substring(o.raw.length),o.tokens=this.inlineTokens(o.text,[],i,n),t.push(o);continue}if(o=this.tokenizer.autolink(e,f$)){e=e.substring(o.raw.length),t.push(o);continue}if(!i&&(o=this.tokenizer.url(e,f$))){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.inlineText(e,n,Ffe)){e=e.substring(o.raw.length),u=o.raw.slice(-1),l=!0,t.push(o);continue}if(e){let c="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(c);break}else throw new Error(c)}}return t}}});var Yx=v((bTe,d$)=>{var{defaults:Afe}=Fl(),{cleanUrl:h$,escape:km}=Js();d$.exports=class{constructor(e){this.options=e||Afe}code(e,t,i){let n=(t||"").match(/\S*/)[0];if(this.options.highlight){let o=this.options.highlight(e,n);o!=null&&o!==e&&(i=!0,e=o)}return n?'
'+(i?e:km(e,!0))+`
-`:"
"+(i?e:km(e,!0))+`
-`}blockquote(e){return`
-`+e+`
-`}html(e){return e}heading(e,t,i,n){return this.options.headerIds?"'+e+" -`:""+e+" -`}hr(){return this.options.xhtml?`
-`:`
-`}list(e,t,i){let n=t?"ol":"ul",o=t&&i!==1?' start="'+i+'"':"";return"<"+n+o+`> -`+e+" -`}listitem(e){return"
  • "+e+`
  • -`}checkbox(e){return" "}paragraph(e){return"

    "+e+`

    -`}table(e,t){return t&&(t=""+t+""),` - -`+e+` -`+t+`
    -`}tablerow(e){return` -`+e+` -`}tablecell(e,t){let i=t.header?"th":"td";return(t.align?"<"+i+' align="'+t.align+'">':"<"+i+">")+e+" -`}strong(e){return""+e+""}em(e){return""+e+""}codespan(e){return""+e+""}br(){return this.options.xhtml?"
    ":"
    "}del(e){return""+e+""}link(e,t,i){if(e=h$(this.options.sanitize,this.options.baseUrl,e),e===null)return i;let n='",n}image(e,t,i){if(e=h$(this.options.sanitize,this.options.baseUrl,e),e===null)return i;let n=''+i+'":">",n}text(e){return e}}});var Xx=v((xTe,m$)=>{m$.exports=class{strong(e){return e}em(e){return e}codespan(e){return e}del(e){return e}html(e){return e}text(e){return e}link(e,t,i){return""+i}image(e,t,i){return""+i}br(){return""}}});var Zx=v((STe,g$)=>{g$.exports=class{constructor(){this.seen={}}serialize(e){return e.toLowerCase().trim().replace(/<[!\/a-z].*?>/ig,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-")}getNextSafeSlug(e,t){let i=e,n=0;if(this.seen.hasOwnProperty(i)){n=this.seen[e];do n++,i=e+"-"+n;while(this.seen.hasOwnProperty(i))}return t||(this.seen[e]=n,this.seen[i]=0),i}slug(e,t={}){let i=this.serialize(e);return this.getNextSafeSlug(i,t.dryrun)}}});var y$=v((ETe,v$)=>{var Ofe=Yx(),Lfe=Xx(),Mfe=Zx(),{defaults:Nfe}=Fl(),{unescape:qfe}=Js();v$.exports=class Qx{constructor(e){this.options=e||Nfe,this.options.renderer=this.options.renderer||new Ofe,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new Lfe,this.slugger=new Mfe}static parse(e,t){return new Qx(t).parse(e)}static parseInline(e,t){return new Qx(t).parseInline(e)}parse(e,t=!0){let i="",n,o,s,a,l,u,c,f,p,d,h,m,y,g,w,x,E,P,k=e.length;for(n=0;n0&&w.tokens[0].type==="text"?(w.tokens[0].text=P+" "+w.tokens[0].text,w.tokens[0].tokens&&w.tokens[0].tokens.length>0&&w.tokens[0].tokens[0].type==="text"&&(w.tokens[0].tokens[0].text=P+" "+w.tokens[0].tokens[0].text)):w.tokens.unshift({type:"text",text:P}):g+=P),g+=this.parse(w.tokens,y),p+=this.renderer.listitem(g,E,x);i+=this.renderer.list(p,h,m);continue}case"html":{i+=this.renderer.html(d.text);continue}case"paragraph":{i+=this.renderer.paragraph(this.parseInline(d.tokens));continue}case"text":{for(p=d.tokens?this.parseInline(d.tokens):d.text;n+1{var Of=p$(),Lf=y$(),w$=Kx(),x$=Yx(),$fe=Xx(),Bfe=Zx(),{merge:Im,checkSanitizeDeprecation:D$,escape:S$}=Js(),{getDefaults:jfe,changeDefaults:Ufe,defaults:Wfe}=Fl();function Re(r,e,t){if(typeof r=="undefined"||r===null)throw new Error("marked(): input parameter is undefined or null");if(typeof r!="string")throw new Error("marked(): input parameter is of type "+Object.prototype.toString.call(r)+", string expected");if(typeof e=="function"&&(t=e,e=null),e=Im({},Re.defaults,e||{}),D$(e),t){let i=e.highlight,n;try{n=Of.lex(r,e)}catch(a){return t(a)}let o=function(a){let l;if(!a)try{l=Lf.parse(n,e)}catch(u){a=u}return e.highlight=i,a?t(a):t(null,l)};if(!i||i.length<3||(delete e.highlight,!n.length))return o();let s=0;Re.walkTokens(n,function(a){a.type==="code"&&(s++,setTimeout(()=>{i(a.text,a.lang,function(l,u){if(l)return o(l);u!=null&&u!==a.text&&(a.text=u,a.escaped=!0),s--,s===0&&o()})},0))}),s===0&&o();return}try{let i=Of.lex(r,e);return e.walkTokens&&Re.walkTokens(i,e.walkTokens),Lf.parse(i,e)}catch(i){if(i.message+=` -Please report this to https://github.com/markedjs/marked.`,e.silent)return"

    An error occurred:

    "+S$(i.message+"",!0)+"
    ";throw i}}Re.options=Re.setOptions=function(r){return Im(Re.defaults,r),Ufe(Re.defaults),Re};Re.getDefaults=jfe;Re.defaults=Wfe;Re.use=function(r){let e=Im({},r);if(r.renderer){let t=Re.defaults.renderer||new x$;for(let i in r.renderer){let n=t[i];t[i]=(...o)=>{let s=r.renderer[i].apply(t,o);return s===!1&&(s=n.apply(t,o)),s}}e.renderer=t}if(r.tokenizer){let t=Re.defaults.tokenizer||new w$;for(let i in r.tokenizer){let n=t[i];t[i]=(...o)=>{let s=r.tokenizer[i].apply(t,o);return s===!1&&(s=n.apply(t,o)),s}}e.tokenizer=t}if(r.walkTokens){let t=Re.defaults.walkTokens;e.walkTokens=i=>{r.walkTokens(i),t&&t(i)}}Re.setOptions(e)};Re.walkTokens=function(r,e){for(let t of r)switch(e(t),t.type){case"table":{for(let i of t.tokens.header)Re.walkTokens(i,e);for(let i of t.tokens.cells)for(let n of i)Re.walkTokens(n,e);break}case"list":{Re.walkTokens(t.items,e);break}default:t.tokens&&Re.walkTokens(t.tokens,e)}};Re.parseInline=function(r,e){if(typeof r=="undefined"||r===null)throw new Error("marked.parseInline(): input parameter is undefined or null");if(typeof r!="string")throw new Error("marked.parseInline(): input parameter is of type "+Object.prototype.toString.call(r)+", string expected");e=Im({},Re.defaults,e||{}),D$(e);try{let t=Of.lexInline(r,e);return e.walkTokens&&Re.walkTokens(t,e.walkTokens),Lf.parseInline(t,e)}catch(t){if(t.message+=` -Please report this to https://github.com/markedjs/marked.`,e.silent)return"

    An error occurred:

    "+S$(t.message+"",!0)+"
    ";throw t}};Re.Parser=Lf;Re.parser=Lf.parse;Re.Renderer=x$;Re.TextRenderer=$fe;Re.Lexer=Of;Re.lexer=Of.lex;Re.Tokenizer=w$;Re.Slugger=Bfe;Re.parse=Re;b$.exports=Re});var _$=v((_Te,C$)=>{"use strict";var Hfe=/[|\\{}()[\]^$+*?.]/g;C$.exports=function(r){if(typeof r!="string")throw new TypeError("Expected a string");return r.replace(Hfe,"\\$&")}});var T$=v((PTe,P$)=>{"use strict";P$.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var tD=v((TTe,R$)=>{var Xs=T$(),k$={};for(var eD in Xs)Xs.hasOwnProperty(eD)&&(k$[Xs[eD]]=eD);var ee=R$.exports={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};for(var Ir in ee)if(ee.hasOwnProperty(Ir)){if(!("channels"in ee[Ir]))throw new Error("missing channels property: "+Ir);if(!("labels"in ee[Ir]))throw new Error("missing channel labels property: "+Ir);if(ee[Ir].labels.length!==ee[Ir].channels)throw new Error("channel and label counts mismatch: "+Ir);I$=ee[Ir].channels,F$=ee[Ir].labels,delete ee[Ir].channels,delete ee[Ir].labels,Object.defineProperty(ee[Ir],"channels",{value:I$}),Object.defineProperty(ee[Ir],"labels",{value:F$})}var I$,F$;ee.rgb.hsl=function(r){var e=r[0]/255,t=r[1]/255,i=r[2]/255,n=Math.min(e,t,i),o=Math.max(e,t,i),s=o-n,a,l,u;return o===n?a=0:e===o?a=(t-i)/s:t===o?a=2+(i-e)/s:i===o&&(a=4+(e-t)/s),a=Math.min(a*60,360),a<0&&(a+=360),u=(n+o)/2,o===n?l=0:u<=.5?l=s/(o+n):l=s/(2-o-n),[a,l*100,u*100]};ee.rgb.hsv=function(r){var e,t,i,n,o,s=r[0]/255,a=r[1]/255,l=r[2]/255,u=Math.max(s,a,l),c=u-Math.min(s,a,l),f=function(p){return(u-p)/6/c+1/2};return c===0?n=o=0:(o=c/u,e=f(s),t=f(a),i=f(l),s===u?n=i-t:a===u?n=1/3+e-i:l===u&&(n=2/3+t-e),n<0?n+=1:n>1&&(n-=1)),[n*360,o*100,u*100]};ee.rgb.hwb=function(r){var e=r[0],t=r[1],i=r[2],n=ee.rgb.hsl(r)[0],o=1/255*Math.min(e,Math.min(t,i));return i=1-1/255*Math.max(e,Math.max(t,i)),[n,o*100,i*100]};ee.rgb.cmyk=function(r){var e=r[0]/255,t=r[1]/255,i=r[2]/255,n,o,s,a;return a=Math.min(1-e,1-t,1-i),n=(1-e-a)/(1-a)||0,o=(1-t-a)/(1-a)||0,s=(1-i-a)/(1-a)||0,[n*100,o*100,s*100,a*100]};function zfe(r,e){return Math.pow(r[0]-e[0],2)+Math.pow(r[1]-e[1],2)+Math.pow(r[2]-e[2],2)}ee.rgb.keyword=function(r){var e=k$[r];if(e)return e;var t=Infinity,i;for(var n in Xs)if(Xs.hasOwnProperty(n)){var o=Xs[n],s=zfe(r,o);s.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,t=t>.04045?Math.pow((t+.055)/1.055,2.4):t/12.92,i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92;var n=e*.4124+t*.3576+i*.1805,o=e*.2126+t*.7152+i*.0722,s=e*.0193+t*.1192+i*.9505;return[n*100,o*100,s*100]};ee.rgb.lab=function(r){var e=ee.rgb.xyz(r),t=e[0],i=e[1],n=e[2],o,s,a;return t/=95.047,i/=100,n/=108.883,t=t>.008856?Math.pow(t,1/3):7.787*t+16/116,i=i>.008856?Math.pow(i,1/3):7.787*i+16/116,n=n>.008856?Math.pow(n,1/3):7.787*n+16/116,o=116*i-16,s=500*(t-i),a=200*(i-n),[o,s,a]};ee.hsl.rgb=function(r){var e=r[0]/360,t=r[1]/100,i=r[2]/100,n,o,s,a,l;if(t===0)return l=i*255,[l,l,l];i<.5?o=i*(1+t):o=i+t-i*t,n=2*i-o,a=[0,0,0];for(var u=0;u<3;u++)s=e+1/3*-(u-1),s<0&&s++,s>1&&s--,6*s<1?l=n+(o-n)*6*s:2*s<1?l=o:3*s<2?l=n+(o-n)*(2/3-s)*6:l=n,a[u]=l*255;return a};ee.hsl.hsv=function(r){var e=r[0],t=r[1]/100,i=r[2]/100,n=t,o=Math.max(i,.01),s,a;return i*=2,t*=i<=1?i:2-i,n*=o<=1?o:2-o,a=(i+t)/2,s=i===0?2*n/(o+n):2*t/(i+t),[e,s*100,a*100]};ee.hsv.rgb=function(r){var e=r[0]/60,t=r[1]/100,i=r[2]/100,n=Math.floor(e)%6,o=e-Math.floor(e),s=255*i*(1-t),a=255*i*(1-t*o),l=255*i*(1-t*(1-o));switch(i*=255,n){case 0:return[i,l,s];case 1:return[a,i,s];case 2:return[s,i,l];case 3:return[s,a,i];case 4:return[l,s,i];case 5:return[i,s,a]}};ee.hsv.hsl=function(r){var e=r[0],t=r[1]/100,i=r[2]/100,n=Math.max(i,.01),o,s,a;return a=(2-t)*i,o=(2-t)*n,s=t*n,s/=o<=1?o:2-o,s=s||0,a/=2,[e,s*100,a*100]};ee.hwb.rgb=function(r){var e=r[0]/360,t=r[1]/100,i=r[2]/100,n=t+i,o,s,a,l;n>1&&(t/=n,i/=n),o=Math.floor(6*e),s=1-i,a=6*e-o,(o&1)!=0&&(a=1-a),l=t+a*(s-t);var u,c,f;switch(o){default:case 6:case 0:u=s,c=l,f=t;break;case 1:u=l,c=s,f=t;break;case 2:u=t,c=s,f=l;break;case 3:u=t,c=l,f=s;break;case 4:u=l,c=t,f=s;break;case 5:u=s,c=t,f=l;break}return[u*255,c*255,f*255]};ee.cmyk.rgb=function(r){var e=r[0]/100,t=r[1]/100,i=r[2]/100,n=r[3]/100,o,s,a;return o=1-Math.min(1,e*(1-n)+n),s=1-Math.min(1,t*(1-n)+n),a=1-Math.min(1,i*(1-n)+n),[o*255,s*255,a*255]};ee.xyz.rgb=function(r){var e=r[0]/100,t=r[1]/100,i=r[2]/100,n,o,s;return n=e*3.2406+t*-1.5372+i*-.4986,o=e*-.9689+t*1.8758+i*.0415,s=e*.0557+t*-.204+i*1.057,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*12.92,o=o>.0031308?1.055*Math.pow(o,1/2.4)-.055:o*12.92,s=s>.0031308?1.055*Math.pow(s,1/2.4)-.055:s*12.92,n=Math.min(Math.max(0,n),1),o=Math.min(Math.max(0,o),1),s=Math.min(Math.max(0,s),1),[n*255,o*255,s*255]};ee.xyz.lab=function(r){var e=r[0],t=r[1],i=r[2],n,o,s;return e/=95.047,t/=100,i/=108.883,e=e>.008856?Math.pow(e,1/3):7.787*e+16/116,t=t>.008856?Math.pow(t,1/3):7.787*t+16/116,i=i>.008856?Math.pow(i,1/3):7.787*i+16/116,n=116*t-16,o=500*(e-t),s=200*(t-i),[n,o,s]};ee.lab.xyz=function(r){var e=r[0],t=r[1],i=r[2],n,o,s;o=(e+16)/116,n=t/500+o,s=o-i/200;var a=Math.pow(o,3),l=Math.pow(n,3),u=Math.pow(s,3);return o=a>.008856?a:(o-16/116)/7.787,n=l>.008856?l:(n-16/116)/7.787,s=u>.008856?u:(s-16/116)/7.787,n*=95.047,o*=100,s*=108.883,[n,o,s]};ee.lab.lch=function(r){var e=r[0],t=r[1],i=r[2],n,o,s;return n=Math.atan2(i,t),o=n*360/2/Math.PI,o<0&&(o+=360),s=Math.sqrt(t*t+i*i),[e,s,o]};ee.lch.lab=function(r){var e=r[0],t=r[1],i=r[2],n,o,s;return s=i/360*2*Math.PI,n=t*Math.cos(s),o=t*Math.sin(s),[e,n,o]};ee.rgb.ansi16=function(r){var e=r[0],t=r[1],i=r[2],n=1 in arguments?arguments[1]:ee.rgb.hsv(r)[2];if(n=Math.round(n/50),n===0)return 30;var o=30+(Math.round(i/255)<<2|Math.round(t/255)<<1|Math.round(e/255));return n===2&&(o+=60),o};ee.hsv.ansi16=function(r){return ee.rgb.ansi16(ee.hsv.rgb(r),r[2])};ee.rgb.ansi256=function(r){var e=r[0],t=r[1],i=r[2];if(e===t&&t===i)return e<8?16:e>248?231:Math.round((e-8)/247*24)+232;var n=16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(i/255*5);return n};ee.ansi16.rgb=function(r){var e=r%10;if(e===0||e===7)return r>50&&(e+=3.5),e=e/10.5*255,[e,e,e];var t=(~~(r>50)+1)*.5,i=(e&1)*t*255,n=(e>>1&1)*t*255,o=(e>>2&1)*t*255;return[i,n,o]};ee.ansi256.rgb=function(r){if(r>=232){var e=(r-232)*10+8;return[e,e,e]}r-=16;var t,i=Math.floor(r/36)/5*255,n=Math.floor((t=r%36)/6)/5*255,o=t%6/5*255;return[i,n,o]};ee.rgb.hex=function(r){var e=((Math.round(r[0])&255)<<16)+((Math.round(r[1])&255)<<8)+(Math.round(r[2])&255),t=e.toString(16).toUpperCase();return"000000".substring(t.length)+t};ee.hex.rgb=function(r){var e=r.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];var t=e[0];e[0].length===3&&(t=t.split("").map(function(a){return a+a}).join(""));var i=parseInt(t,16),n=i>>16&255,o=i>>8&255,s=i&255;return[n,o,s]};ee.rgb.hcg=function(r){var e=r[0]/255,t=r[1]/255,i=r[2]/255,n=Math.max(Math.max(e,t),i),o=Math.min(Math.min(e,t),i),s=n-o,a,l;return s<1?a=o/(1-s):a=0,s<=0?l=0:n===e?l=(t-i)/s%6:n===t?l=2+(i-e)/s:l=4+(e-t)/s+4,l/=6,l%=1,[l*360,s*100,a*100]};ee.hsl.hcg=function(r){var e=r[1]/100,t=r[2]/100,i=1,n=0;return t<.5?i=2*e*t:i=2*e*(1-t),i<1&&(n=(t-.5*i)/(1-i)),[r[0],i*100,n*100]};ee.hsv.hcg=function(r){var e=r[1]/100,t=r[2]/100,i=e*t,n=0;return i<1&&(n=(t-i)/(1-i)),[r[0],i*100,n*100]};ee.hcg.rgb=function(r){var e=r[0]/360,t=r[1]/100,i=r[2]/100;if(t===0)return[i*255,i*255,i*255];var n=[0,0,0],o=e%1*6,s=o%1,a=1-s,l=0;switch(Math.floor(o)){case 0:n[0]=1,n[1]=s,n[2]=0;break;case 1:n[0]=a,n[1]=1,n[2]=0;break;case 2:n[0]=0,n[1]=1,n[2]=s;break;case 3:n[0]=0,n[1]=a,n[2]=1;break;case 4:n[0]=s,n[1]=0,n[2]=1;break;default:n[0]=1,n[1]=0,n[2]=a}return l=(1-t)*i,[(t*n[0]+l)*255,(t*n[1]+l)*255,(t*n[2]+l)*255]};ee.hcg.hsv=function(r){var e=r[1]/100,t=r[2]/100,i=e+t*(1-e),n=0;return i>0&&(n=e/i),[r[0],n*100,i*100]};ee.hcg.hsl=function(r){var e=r[1]/100,t=r[2]/100,i=t*(1-e)+.5*e,n=0;return i>0&&i<.5?n=e/(2*i):i>=.5&&i<1&&(n=e/(2*(1-i))),[r[0],n*100,i*100]};ee.hcg.hwb=function(r){var e=r[1]/100,t=r[2]/100,i=e+t*(1-e);return[r[0],(i-e)*100,(1-i)*100]};ee.hwb.hcg=function(r){var e=r[1]/100,t=r[2]/100,i=1-t,n=i-e,o=0;return n<1&&(o=(i-n)/(1-n)),[r[0],n*100,o*100]};ee.apple.rgb=function(r){return[r[0]/65535*255,r[1]/65535*255,r[2]/65535*255]};ee.rgb.apple=function(r){return[r[0]/255*65535,r[1]/255*65535,r[2]/255*65535]};ee.gray.rgb=function(r){return[r[0]/100*255,r[0]/100*255,r[0]/100*255]};ee.gray.hsl=ee.gray.hsv=function(r){return[0,0,r[0]]};ee.gray.hwb=function(r){return[0,100,r[0]]};ee.gray.cmyk=function(r){return[0,0,0,r[0]]};ee.gray.lab=function(r){return[r[0],0,0]};ee.gray.hex=function(r){var e=Math.round(r[0]/100*255)&255,t=(e<<16)+(e<<8)+e,i=t.toString(16).toUpperCase();return"000000".substring(i.length)+i};ee.rgb.gray=function(r){var e=(r[0]+r[1]+r[2])/3;return[e/255*100]}});var O$=v((RTe,A$)=>{var Fm=tD();function Gfe(){for(var r={},e=Object.keys(Fm),t=e.length,i=0;i{var rD=tD(),Yfe=O$(),Al={},Xfe=Object.keys(rD);function Zfe(r){var e=function(t){return t==null?t:(arguments.length>1&&(t=Array.prototype.slice.call(arguments)),r(t))};return"conversion"in r&&(e.conversion=r.conversion),e}function Qfe(r){var e=function(t){if(t==null)return t;arguments.length>1&&(t=Array.prototype.slice.call(arguments));var i=r(t);if(typeof i=="object")for(var n=i.length,o=0;o{"use strict";var Ol=M$(),Am=(r,e)=>function(){return`[${r.apply(Ol,arguments)+e}m`},Om=(r,e)=>function(){let t=r.apply(Ol,arguments);return`[${38+e};5;${t}m`},Lm=(r,e)=>function(){let t=r.apply(Ol,arguments);return`[${38+e};2;${t[0]};${t[1]};${t[2]}m`};function epe(){let r=new Map,e={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],gray:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};e.color.grey=e.color.gray;for(let n of Object.keys(e)){let o=e[n];for(let s of Object.keys(o)){let a=o[s];e[s]={open:`[${a[0]}m`,close:`[${a[1]}m`},o[s]=e[s],r.set(a[0],a[1])}Object.defineProperty(e,n,{value:o,enumerable:!1}),Object.defineProperty(e,"codes",{value:r,enumerable:!1})}let t=n=>n,i=(n,o,s)=>[n,o,s];e.color.close="",e.bgColor.close="",e.color.ansi={ansi:Am(t,0)},e.color.ansi256={ansi256:Om(t,0)},e.color.ansi16m={rgb:Lm(i,0)},e.bgColor.ansi={ansi:Am(t,10)},e.bgColor.ansi256={ansi256:Om(t,10)},e.bgColor.ansi16m={rgb:Lm(i,10)};for(let n of Object.keys(Ol)){if(typeof Ol[n]!="object")continue;let o=Ol[n];n==="ansi16"&&(n="ansi"),"ansi16"in o&&(e.color.ansi[n]=Am(o.ansi16,0),e.bgColor.ansi[n]=Am(o.ansi16,10)),"ansi256"in o&&(e.color.ansi256[n]=Om(o.ansi256,0),e.bgColor.ansi256[n]=Om(o.ansi256,10)),"rgb"in o&&(e.color.ansi16m[n]=Lm(o.rgb,0),e.bgColor.ansi16m[n]=Lm(o.rgb,10))}return e}Object.defineProperty(N$,"exports",{enumerable:!0,get:epe})});var B$=v((FTe,$$)=>{"use strict";$$.exports=(r,e)=>{e=e||process.argv;let t=r.startsWith("-")?"":r.length===1?"-":"--",i=e.indexOf(t+r),n=e.indexOf("--");return i!==-1&&(n===-1?!0:i{"use strict";var tpe=require("os"),Vi=B$(),sr=process.env,Ll;Vi("no-color")||Vi("no-colors")||Vi("color=false")?Ll=!1:(Vi("color")||Vi("colors")||Vi("color=true")||Vi("color=always"))&&(Ll=!0);"FORCE_COLOR"in sr&&(Ll=sr.FORCE_COLOR.length===0||parseInt(sr.FORCE_COLOR,10)!==0);function rpe(r){return r===0?!1:{level:r,hasBasic:!0,has256:r>=2,has16m:r>=3}}function ipe(r){if(Ll===!1)return 0;if(Vi("color=16m")||Vi("color=full")||Vi("color=truecolor"))return 3;if(Vi("color=256"))return 2;if(r&&!r.isTTY&&Ll!==!0)return 0;let e=Ll?1:0;if(process.platform==="win32"){let t=tpe.release().split(".");return Number(process.versions.node.split(".")[0])>=8&&Number(t[0])>=10&&Number(t[2])>=10586?Number(t[2])>=14931?3:2:1}if("CI"in sr)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(t=>t in sr)||sr.CI_NAME==="codeship"?1:e;if("TEAMCITY_VERSION"in sr)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(sr.TEAMCITY_VERSION)?1:0;if(sr.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in sr){let t=parseInt((sr.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(sr.TERM_PROGRAM){case"iTerm.app":return t>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(sr.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(sr.TERM)||"COLORTERM"in sr?1:(sr.TERM==="dumb",e)}function iD(r){let e=ipe(r);return rpe(e)}j$.exports={supportsColor:iD,stdout:iD(process.stdout),stderr:iD(process.stderr)}});var V$=v((OTe,W$)=>{"use strict";var npe=/(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,H$=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,ope=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,spe=/\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi,ape=new Map([["n",` -`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e",""],["a","\x07"]]);function z$(r){return r[0]==="u"&&r.length===5||r[0]==="x"&&r.length===3?String.fromCharCode(parseInt(r.slice(1),16)):ape.get(r)||r}function lpe(r,e){let t=[],i=e.trim().split(/\s*,\s*/g),n;for(let o of i)if(!isNaN(o))t.push(Number(o));else if(n=o.match(ope))t.push(n[2].replace(spe,(s,a,l)=>a?z$(a):l));else throw new Error(`Invalid Chalk template style argument: ${o} (in style '${r}')`);return t}function upe(r){H$.lastIndex=0;let e=[],t;for(;(t=H$.exec(r))!==null;){let i=t[1];if(t[2]){let n=lpe(i,t[2]);e.push([i].concat(n))}else e.push([i])}return e}function G$(r,e){let t={};for(let n of e)for(let o of n.styles)t[o[0]]=n.inverse?null:o.slice(1);let i=r;for(let n of Object.keys(t))if(Array.isArray(t[n])){if(!(n in i))throw new Error(`Unknown Chalk style: ${n}`);t[n].length>0?i=i[n].apply(i,t[n]):i=i[n]}return i}W$.exports=(r,e)=>{let t=[],i=[],n=[];if(e.replace(npe,(o,s,a,l,u,c)=>{if(s)n.push(z$(s));else if(l){let f=n.join("");n=[],i.push(t.length===0?f:G$(r,t)(f)),t.push({inverse:a,styles:upe(l)})}else if(u){if(t.length===0)throw new Error("Found extraneous } in Chalk template literal");i.push(G$(r,t)(n.join(""))),n=[],t.pop()}else n.push(c)}),i.push(n.join("")),t.length>0){let o=`Chalk template literal is missing ${t.length} closing bracket${t.length===1?"":"s"} (\`}\`)`;throw new Error(o)}return i.join("")}});var Z$=v((LTe,Mf)=>{"use strict";var nD=_$(),Dt=q$(),oD=U$().stdout,cpe=V$(),K$=process.platform==="win32"&&!(process.env.TERM||"").toLowerCase().startsWith("xterm"),J$=["ansi","ansi","ansi256","ansi16m"],Y$=new Set(["gray"]),Ml=Object.create(null);function X$(r,e){e=e||{};let t=oD?oD.level:0;r.level=e.level===void 0?t:e.level,r.enabled="enabled"in e?e.enabled:r.level>0}function Nf(r){if(!this||!(this instanceof Nf)||this.template){let e={};return X$(e,r),e.template=function(){let t=[].slice.call(arguments);return fpe.apply(null,[e.template].concat(t))},Object.setPrototypeOf(e,Nf.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=Nf,e.template}X$(this,r)}K$&&(Dt.blue.open="");for(let r of Object.keys(Dt))Dt[r].closeRe=new RegExp(nD(Dt[r].close),"g"),Ml[r]={get(){let e=Dt[r];return Mm.call(this,this._styles?this._styles.concat(e):[e],this._empty,r)}};Ml.visible={get(){return Mm.call(this,this._styles||[],!0,"visible")}};Dt.color.closeRe=new RegExp(nD(Dt.color.close),"g");for(let r of Object.keys(Dt.color.ansi))Y$.has(r)||(Ml[r]={get(){let e=this.level;return function(){let i={open:Dt.color[J$[e]][r].apply(null,arguments),close:Dt.color.close,closeRe:Dt.color.closeRe};return Mm.call(this,this._styles?this._styles.concat(i):[i],this._empty,r)}}});Dt.bgColor.closeRe=new RegExp(nD(Dt.bgColor.close),"g");for(let r of Object.keys(Dt.bgColor.ansi)){if(Y$.has(r))continue;let e="bg"+r[0].toUpperCase()+r.slice(1);Ml[e]={get(){let t=this.level;return function(){let n={open:Dt.bgColor[J$[t]][r].apply(null,arguments),close:Dt.bgColor.close,closeRe:Dt.bgColor.closeRe};return Mm.call(this,this._styles?this._styles.concat(n):[n],this._empty,r)}}}}var ppe=Object.defineProperties(()=>{},Ml);function Mm(r,e,t){let i=function(){return dpe.apply(i,arguments)};i._styles=r,i._empty=e;let n=this;return Object.defineProperty(i,"level",{enumerable:!0,get(){return n.level},set(o){n.level=o}}),Object.defineProperty(i,"enabled",{enumerable:!0,get(){return n.enabled},set(o){n.enabled=o}}),i.hasGrey=this.hasGrey||t==="gray"||t==="grey",i.__proto__=ppe,i}function dpe(){let r=arguments,e=r.length,t=String(arguments[0]);if(e===0)return"";if(e>1)for(let n=1;n{"use strict";Q$.exports=({onlyFirst:r=!1}={})=>{let e=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(e,r?void 0:"g")}});var sD=v((NTe,tB)=>{"use strict";var hpe=eB();tB.exports=r=>typeof r=="string"?r.replace(hpe(),""):r});var iB=v((qTe,aD)=>{"use strict";var rB=r=>Number.isNaN(r)?!1:r>=4352&&(r<=4447||r===9001||r===9002||11904<=r&&r<=12871&&r!==12351||12880<=r&&r<=19903||19968<=r&&r<=42182||43360<=r&&r<=43388||44032<=r&&r<=55203||63744<=r&&r<=64255||65040<=r&&r<=65049||65072<=r&&r<=65131||65281<=r&&r<=65376||65504<=r&&r<=65510||110592<=r&&r<=110593||127488<=r&&r<=127569||131072<=r&&r<=262141);aD.exports=rB;aD.exports.default=rB});var oB=v(($Te,nB)=>{"use strict";nB.exports=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g}});var aB=v((BTe,lD)=>{"use strict";var mpe=sD(),gpe=iB(),vpe=oB(),sB=r=>{if(r=r.replace(vpe()," "),typeof r!="string"||r.length===0)return 0;r=mpe(r);let e=0;for(let t=0;t=127&&i<=159||i>=768&&i<=879||(i>65535&&t++,e+=gpe(i)?2:1)}return e};lD.exports=sB;lD.exports.default=sB});var uB=v(Nl=>{var ype=aB();Nl.repeat=function(r,e){return Array(e+1).join(r)};Nl.pad=function(r,e,t,i){if(e+1>=r.length)switch(i){case"left":r=Array(e+1-r.length).join(t)+r;break;case"both":var n=Math.ceil((padlen=e-r.length)/2),o=padlen-n;r=Array(o+1).join(t)+r+Array(n+1).join(t);break;default:r=r+Array(e+1-r.length).join(t)}return r};Nl.truncate=function(r,e,t){return t=t||"\u2026",r.length>=e?r.substr(0,e-t.length)+t:r};function lB(r,e){for(var t in e)e[t]&&e[t].constructor&&e[t].constructor===Object?(r[t]=r[t]||{},lB(r[t],e[t])):r[t]=e[t];return r}Nl.options=lB;Nl.strlen=function(r){var e=/\u001b\[(?:\d*;){0,5}\d*m/g,t=(""+(r!=null?r:"")).replace(e,""),i=t.split(` -`);return i.reduce(function(n,o){var s=ype(o);return s>n?s:n},0)}});var fB=v((UTe,cB)=>{cB.exports={name:"cli-table",description:"Pretty unicode tables for the CLI",version:"0.3.4",license:"MIT",author:"Guillermo Rauch ",contributors:["Sonny Michaud (http://github.com/sonnym)","Gabriel Sambarino (http://github.com/chrean)"],repository:{type:"git",url:"https://github.com/Automattic/cli-table.git"},keywords:["cli","colors","table"],dependencies:{chalk:"^2.4.1","string-width":"^4.2.0"},devDependencies:{"@babel/core":"^7.12.9","@babel/preset-env":"^7.12.7","@babel/preset-typescript":"^7.12.7","babel-jest":"^26.6.3",expect:"^26.6.2",expresso:"~0.9",jest:"^26.6.3","jest-mock":"^26.6.2","publish-please":"^5.5.2","ts-node":"^9.1.0",typescript:"^4.1.2"},main:"lib",files:["lib"],scripts:{test:"jest","publish-please":"publish-please --access public"},engines:{node:">= 10.0.0"}}});var pB=v((WTe,uD)=>{var bpe=Z$(),Zs=uB(),cD=Zs.repeat,wpe=Zs.truncate,xpe=Zs.pad;function qf(r){this.options=Zs.options({chars:{top:"\u2500","top-mid":"\u252C","top-left":"\u250C","top-right":"\u2510",bottom:"\u2500","bottom-mid":"\u2534","bottom-left":"\u2514","bottom-right":"\u2518",left:"\u2502","left-mid":"\u251C",mid:"\u2500","mid-mid":"\u253C",right:"\u2502","right-mid":"\u2524",middle:"\u2502"},truncate:"\u2026",colors:!0,colWidths:[],colAligns:[],style:{"padding-left":1,"padding-right":1,head:["red"],border:["white"],compact:!1},head:[]},r)}qf.prototype.__proto__=Array.prototype;qf.prototype.__defineGetter__("width",function(){var r=this.toString().split(` -`);return r.length?r[0].length:0});qf.prototype.render;qf.prototype.toString=function(){var r="",e=this.options,t=e.style,i=e.head,n=e.chars,o=e.truncate,s=e.colWidths||new Array(this.head.length),a=0;if(!i.length&&!this.length)return"";if(!s.length){var l=this.slice(0);i.length&&(l=l.concat([i])),l.forEach(function(g){if(Array.isArray(g)&&g.length)u(g);else{var w=Object.keys(g)[0],x=g[w];s[0]=Math.max(s[0]||0,c(w)||0),Array.isArray(x)&&x.length?u(x,1):s[1]=Math.max(s[1]||0,c(x)||0)}})}a=(s.length==1?s[0]:s.reduce(function(g,w){return g+w}))+s.length+1;function u(g,w){var w=w||0;g.forEach(function(x,E){s[E+w]=Math.max(s[E+w]||0,c(x)||0)})}function c(g){return typeof g=="object"&&g&&g.width!=null?g.width:(typeof g=="object"&&g!==null?Zs.strlen(g.text):Zs.strlen(g))+(t["padding-left"]||0)+(t["padding-right"]||0)}function f(g,w,x,E){var P=0,g=w+cD(g,a-2)+x;return s.forEach(function(k,_){_!=s.length-1&&(P+=k+1,g=g.substr(0,P)+E+g.substr(P+1))}),h(e.style.border,g)}function p(){var g=f(n.top,n["top-left"]||n.top,n["top-right"]||n.top,n["top-mid"]);g&&(r+=g+` -`)}function d(g,w){var x=[],E=0;if(!Array.isArray(g)&&typeof g=="object"){var P=Object.keys(g)[0],k=g[P],_=!0;Array.isArray(k)?(g=k,g.unshift(P)):g=[P,k]}g.forEach(function(O,R){var F=(O==null?"":O).toString().split(` -`).reduce(function(K,ae){return K.push(m(ae,R)),K},[]),q=F.length;q>E&&(E=q),x.push({contents:F,height:q})});var L=new Array(E);x.forEach(function(O,R){O.contents.forEach(function(K,ae){L[ae]||(L[ae]=[]),(w||_&&R===0&&e.style.head)&&(K=h(e.style.head,K)),L[ae].push(K)});for(var F=O.height,q=E;F0&&(I+=` -`+h(e.style.border,n.left)),I+=O.join(h(e.style.border,n.middle))+h(e.style.border,n.right)}),h(e.style.border,n.left)+I}function h(g,w){return w?(e.colors&&g.forEach(function(x){w=bpe[x](w)}),w):""}function m(g,w){var g=String(typeof g=="object"&&g.text?g.text:g),x=Zs.strlen(g),E=s[w]-(t["padding-left"]||0)-(t["padding-right"]||0),P=e.colAligns[w]||"left";return cD(" ",t["padding-left"]||0)+(x==E?g:x{"use strict";var hB=10,mB=(r=0)=>e=>`[${38+r};5;${e}m`,gB=(r=0)=>(e,t,i)=>`[${38+r};2;${e};${t};${i}m`;function Dpe(){let r=new Map,e={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};e.color.gray=e.color.blackBright,e.bgColor.bgGray=e.bgColor.bgBlackBright,e.color.grey=e.color.blackBright,e.bgColor.bgGrey=e.bgColor.bgBlackBright;for(let[t,i]of Object.entries(e)){for(let[n,o]of Object.entries(i))e[n]={open:`[${o[0]}m`,close:`[${o[1]}m`},i[n]=e[n],r.set(o[0],o[1]);Object.defineProperty(e,t,{value:i,enumerable:!1})}return Object.defineProperty(e,"codes",{value:r,enumerable:!1}),e.color.close="",e.bgColor.close="",e.color.ansi256=mB(),e.color.ansi16m=gB(),e.bgColor.ansi256=mB(hB),e.bgColor.ansi16m=gB(hB),e.rgbToAnsi256=(t,i,n)=>t===i&&i===n?t<8?16:t>248?231:Math.round((t-8)/247*24)+232:16+36*Math.round(t/255*5)+6*Math.round(i/255*5)+Math.round(n/255*5),e.hexToRgb=t=>{let i=/(?[a-f\d]{6}|[a-f\d]{3})/i.exec(t.toString(16));if(!i)return[0,0,0];let{colorString:n}=i.groups;n.length===3&&(n=n.split("").map(s=>s+s).join(""));let o=Number.parseInt(n,16);return[o>>16&255,o>>8&255,o&255]},e.hexToAnsi256=t=>e.rgbToAnsi256(...e.hexToRgb(t)),e}Object.defineProperty(dB,"exports",{enumerable:!0,get:Dpe})});var l3=v((rke,zm)=>{"use strict";zm.exports=Ype;zm.exports.format=s3;zm.exports.parse=a3;var Xpe=/\B(?=(\d{3})+(?!\d))/g,Zpe=/(?:\.0*|(\.[^0]+)0+)$/,Bo={b:1,kb:1<<10,mb:1<<20,gb:1<<30,tb:Math.pow(1024,4),pb:Math.pow(1024,5)},Qpe=/^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;function Ype(r,e){return typeof r=="string"?a3(r):typeof r=="number"?s3(r,e):null}function s3(r,e){if(!Number.isFinite(r))return null;var t=Math.abs(r),i=e&&e.thousandsSeparator||"",n=e&&e.unitSeparator||"",o=e&&e.decimalPlaces!==void 0?e.decimalPlaces:2,s=Boolean(e&&e.fixedDecimals),a=e&&e.unit||"";(!a||!Bo[a.toLowerCase()])&&(t>=Bo.pb?a="PB":t>=Bo.tb?a="TB":t>=Bo.gb?a="GB":t>=Bo.mb?a="MB":t>=Bo.kb?a="KB":a="B");var l=r/Bo[a.toLowerCase()],u=l.toFixed(o);return s||(u=u.replace(Zpe,"$1")),i&&(u=u.replace(Xpe,i)),u+n+a}function a3(r){if(typeof r=="number"&&!isNaN(r))return r;if(typeof r!="string")return null;var e=Qpe.exec(r),t,i="b";return e?(t=parseFloat(e[1]),i=e[4].toLowerCase()):(t=parseInt(r,10),i="b"),Math.floor(Bo[i]*t)}});var Ul=v((ike,u3)=>{var vn=-1,Yi=1,Fr=0;function Hf(r,e,t,i){if(r===e)return r?[[Fr,r]]:[];if(t!=null){var n=tde(r,e,t);if(n)return n}var o=FD(r,e),s=r.substring(0,o);r=r.substring(o),e=e.substring(o),o=AD(r,e);var a=r.substring(r.length-o);r=r.substring(0,r.length-o),e=e.substring(0,e.length-o);var l=ede(r,e);return s&&l.unshift([Fr,s]),a&&l.push([Fr,a]),c3(l,i),l}function ede(r,e){var t;if(!r)return[[Yi,e]];if(!e)return[[vn,r]];var i=r.length>e.length?r:e,n=r.length>e.length?e:r,o=i.indexOf(n);if(o!==-1)return t=[[Yi,i.substring(0,o)],[Fr,n],[Yi,i.substring(o+n.length)]],r.length>e.length&&(t[0][0]=t[2][0]=vn),t;if(n.length===1)return[[vn,r],[Yi,e]];var s=ide(r,e);if(s){var a=s[0],l=s[1],u=s[2],c=s[3],f=s[4],p=Hf(a,u),d=Hf(l,c);return p.concat([[Fr,f]],d)}return rde(r,e)}function rde(r,e){for(var t=r.length,i=e.length,n=Math.ceil((t+i)/2),o=n,s=2*n,a=new Array(s),l=new Array(s),u=0;ut)d+=2;else if(E>i)p+=2;else if(f){var P=o+c-g;if(P>=0&&P=k)return f3(r,e,x,E)}}}for(var _=-y+h;_<=y-m;_+=2){var P=o+_,k;_===-y||_!==y&&l[P-1]t)m+=2;else if(L>i)h+=2;else if(!f){var w=o+c-_;if(w>=0&&w=k)return f3(r,e,x,E)}}}}return[[vn,r],[Yi,e]]}function f3(r,e,t,i){var n=r.substring(0,t),o=e.substring(0,i),s=r.substring(t),a=e.substring(i),l=Hf(n,o),u=Hf(s,a);return l.concat(u)}function FD(r,e){if(!r||!e||r.charAt(0)!==e.charAt(0))return 0;for(var t=0,i=Math.min(r.length,e.length),n=i,o=0;te.length?r:e,i=r.length>e.length?e:r;if(t.length<4||i.length*2=d.length?[x,E,P,k,w]:null}var o=n(t,i,Math.ceil(t.length/4)),s=n(t,i,Math.ceil(t.length/2)),a;if(!o&&!s)return null;s?o?a=o[4].length>s[4].length?o:s:a=s:a=o;var l,u,c,f;r.length>e.length?(l=a[0],u=a[1],c=a[2],f=a[3]):(c=a[0],f=a[1],l=a[2],u=a[3]);var p=a[4];return[l,u,c,f,p]}function c3(r,e){r.push([Fr,""]);for(var t=0,i=0,n=0,o="",s="",a;t=0&&m3(r[l][1])){var u=r[l][1].slice(-1);if(r[l][1]=r[l][1].slice(0,-1),o=u+o,s=u+s,!r[l][1]){r.splice(l,1),t--;var c=l-1;r[c]&&r[c][0]===Yi&&(n++,s=r[c][1]+s,c--),r[c]&&r[c][0]===vn&&(i++,o=r[c][1]+o,c--),l=c}}if(h3(r[t][1])){var u=r[t][1].charAt(0);r[t][1]=r[t][1].slice(1),o+=u,s+=u}}if(t0||s.length>0){o.length>0&&s.length>0&&(a=FD(s,o),a!==0&&(l>=0?r[l][1]+=s.substring(0,a):(r.splice(0,0,[Fr,s.substring(0,a)]),t++),s=s.substring(a),o=o.substring(a)),a=AD(s,o),a!==0&&(r[t][1]=s.substring(s.length-a)+r[t][1],s=s.substring(0,s.length-a),o=o.substring(0,o.length-a)));var f=n+i;o.length===0&&s.length===0?(r.splice(t-f,f),t=t-f):o.length===0?(r.splice(t-f,f,[Yi,s]),t=t-f+1):s.length===0?(r.splice(t-f,f,[vn,o]),t=t-f+1):(r.splice(t-f,f,[vn,o],[Yi,s]),t=t-f+2)}t!==0&&r[t-1][0]===Fr?(r[t-1][1]+=r[t][1],r.splice(t,1)):t++,n=0,i=0,o="",s="";break}}r[r.length-1][1]===""&&r.pop();var p=!1;for(t=1;t=55296&&r<=56319}function d3(r){return r>=56320&&r<=57343}function h3(r){return d3(r.charCodeAt(0))}function m3(r){return p3(r.charCodeAt(r.length-1))}function nde(r){for(var e=[],t=0;t0&&e.push(r[t]);return e}function OD(r,e,t,i){return m3(r)||h3(i)?null:nde([[Fr,r],[vn,e],[Yi,t],[Fr,i]])}function tde(r,e,t){var i=typeof t=="number"?{index:t,length:0}:t.oldRange,n=typeof t=="number"?null:t.newRange,o=r.length,s=e.length;if(i.length===0&&(n===null||n.length===0)){var a=i.index,l=r.slice(0,a),u=r.slice(a),c=n?n.index:null;e:{var f=a+s-o;if(c!==null&&c!==f||f<0||f>s)break e;var p=e.slice(0,f),d=e.slice(f);if(d!==u)break e;var h=Math.min(a,f),m=l.slice(0,h),y=p.slice(0,h);if(m!==y)break e;var g=l.slice(h),w=p.slice(h);return OD(m,g,w,u)}e:{if(c!==null&&c!==a)break e;var x=a,p=e.slice(0,x),d=e.slice(x);if(p!==l)break e;var E=Math.min(o-x,s-x),P=u.slice(u.length-E),k=d.slice(d.length-E);if(P!==k)break e;var g=u.slice(0,u.length-E),w=d.slice(0,d.length-E);return OD(l,g,w,P)}}if(i.length>0&&n&&n.length===0){e:{var m=r.slice(0,i.index),P=r.slice(i.index+i.length),h=m.length,E=P.length;if(s{R3.exports=function(r,e){for(var t=[],i=0;i{"use strict";I3.exports=F3;function F3(r,e,t){r instanceof RegExp&&(r=A3(r,t)),e instanceof RegExp&&(e=A3(e,t));var i=O3(r,e,t);return i&&{start:i[0],end:i[1],pre:t.slice(0,i[0]),body:t.slice(i[0]+r.length,i[1]),post:t.slice(i[1]+e.length)}}function A3(r,e){var t=e.match(r);return t?t[0]:null}F3.range=O3;function O3(r,e,t){var i,n,o,s,a,l=t.indexOf(r),u=t.indexOf(e,l+1),c=l;if(l>=0&&u>0){for(i=[],o=t.length;c>=0&&!a;)c==l?(i.push(c),l=t.indexOf(r,c+1)):i.length==1?a=[i.pop(),u]:(n=i.pop(),n=0?l:u;i.length&&(a=[o,s])}return a}});var W3=v((Bke,M3)=>{var hde=k3(),N3=L3();M3.exports=mde;var q3="\0SLASH"+Math.random()+"\0",$3="\0OPEN"+Math.random()+"\0",UD="\0CLOSE"+Math.random()+"\0",B3="\0COMMA"+Math.random()+"\0",j3="\0PERIOD"+Math.random()+"\0";function WD(r){return parseInt(r,10)==r?parseInt(r,10):r.charCodeAt(0)}function gde(r){return r.split("\\\\").join(q3).split("\\{").join($3).split("\\}").join(UD).split("\\,").join(B3).split("\\.").join(j3)}function vde(r){return r.split(q3).join("\\").split($3).join("{").split(UD).join("}").split(B3).join(",").split(j3).join(".")}function U3(r){if(!r)return[""];var e=[],t=N3("{","}",r);if(!t)return r.split(",");var i=t.pre,n=t.body,o=t.post,s=i.split(",");s[s.length-1]+="{"+n+"}";var a=U3(o);return o.length&&(s[s.length-1]+=a.shift(),s.push.apply(s,a)),e.push.apply(e,s),e}function mde(r){return r?(r.substr(0,2)==="{}"&&(r="\\{\\}"+r.substr(2)),zl(gde(r),!0).map(vde)):[]}function yde(r){return"{"+r+"}"}function bde(r){return/^-?0\d/.test(r)}function wde(r,e){return r<=e}function xde(r,e){return r>=e}function zl(r,e){var t=[],i=N3("{","}",r);if(!i||/\$$/.test(i.pre))return[r];var n=/^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(i.body),o=/^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(i.body),s=n||o,a=i.body.indexOf(",")>=0;if(!s&&!a)return i.post.match(/,.*\}/)?(r=i.pre+"{"+i.body+UD+i.post,zl(r)):[r];var l;if(s)l=i.body.split(/\.\./);else if(l=U3(i.body),l.length===1&&(l=zl(l[0],!1).map(yde),l.length===1)){var c=i.post.length?zl(i.post,!1):[""];return c.map(function(R){return i.pre+l[0]+R})}var u=i.pre,c=i.post.length?zl(i.post,!1):[""],f;if(s){var p=WD(l[0]),d=WD(l[1]),h=Math.max(l[0].length,l[1].length),m=l.length==3?Math.abs(WD(l[2])):1,y=wde,g=d0){var k=new Array(P+1).join("0");x<0?E="-"+k+E.slice(1):E=k+E}}f.push(E)}}else f=hde(l,function(O){return zl(O,!1)});for(var _=0;_{H3.exports=Ei;Ei.Minimatch=Ot;var Xf={sep:"/"};try{Xf=require("path")}catch(r){}var HD=Ei.GLOBSTAR=Ot.GLOBSTAR={},Dde=W3(),z3={"!":{open:"(?:(?!(?:",close:"))[^/]*?)"},"?":{open:"(?:",close:")?"},"+":{open:"(?:",close:")+"},"*":{open:"(?:",close:")*"},"@":{open:"(?:",close:")"}},zD="[^/]",GD=zD+"*?",Sde="(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?",Ede="(?:(?!(?:\\/|^)\\.).)*?",G3=Cde("().*{}+?[]^$\\!");function Cde(r){return r.split("").reduce(function(e,t){return e[t]=!0,e},{})}var V3=/\/+/;Ei.filter=_de;function _de(r,e){return e=e||{},function(t,i,n){return Ei(t,r,e)}}function K3(r,e){r=r||{},e=e||{};var t={};return Object.keys(e).forEach(function(i){t[i]=e[i]}),Object.keys(r).forEach(function(i){t[i]=r[i]}),t}Ei.defaults=function(r){if(!r||!Object.keys(r).length)return Ei;var e=Ei,t=function(n,o,s){return e.minimatch(n,o,K3(r,s))};return t.Minimatch=function(n,o){return new e.Minimatch(n,K3(r,o))},t};Ot.defaults=function(r){return!r||!Object.keys(r).length?Ot:Ei.defaults(r).Minimatch};function Ei(r,e,t){if(typeof e!="string")throw new TypeError("glob pattern string required");return t||(t={}),!t.nocomment&&e.charAt(0)==="#"?!1:e.trim()===""?r==="":new Ot(e,t).match(r)}function Ot(r,e){if(!(this instanceof Ot))return new Ot(r,e);if(typeof r!="string")throw new TypeError("glob pattern string required");e||(e={}),r=r.trim(),Xf.sep!=="/"&&(r=r.split(Xf.sep).join("/")),this.options=e,this.set=[],this.pattern=r,this.regexp=null,this.negate=!1,this.comment=!1,this.empty=!1,this.make()}Ot.prototype.debug=function(){};Ot.prototype.make=Pde;function Pde(){if(!this._made){var r=this.pattern,e=this.options;if(!e.nocomment&&r.charAt(0)==="#"){this.comment=!0;return}if(!r){this.empty=!0;return}this.parseNegate();var t=this.globSet=this.braceExpand();e.debug&&(this.debug=console.error),this.debug(this.pattern,t),t=this.globParts=t.map(function(i){return i.split(V3)}),this.debug(this.pattern,t),t=t.map(function(i,n,o){return i.map(this.parse,this)},this),this.debug(this.pattern,t),t=t.filter(function(i){return i.indexOf(!1)===-1}),this.debug(this.pattern,t),this.set=t}}Ot.prototype.parseNegate=Tde;function Tde(){var r=this.pattern,e=!1,t=this.options,i=0;if(!t.nonegate){for(var n=0,o=r.length;n1024*64)throw new TypeError("pattern is too long");var t=this.options;if(!t.noglobstar&&r==="**")return HD;if(r==="")return"";var i="",n=!!t.nocase,o=!1,s=[],a=[],l,u=!1,c=-1,f=-1,p=r.charAt(0)==="."?"":t.dot?"(?!(?:^|\\/)\\.{1,2}(?:$|\\/))":"(?!\\.)",d=this;function h(){if(l){switch(l){case"*":i+=GD,n=!0;break;case"?":i+=zD,n=!0;break;default:i+="\\"+l;break}d.debug("clearStateChar %j %j",l,i),l=!1}}for(var m=0,y=r.length,g;m-1;L--){var I=a[L],O=i.slice(0,I.reStart),R=i.slice(I.reStart,I.reEnd-8),F=i.slice(I.reEnd-8,I.reEnd),q=i.slice(I.reEnd);F+=q;var K=O.split("(").length-1,ae=q;for(m=0;m=0&&(n=r[o],!n);o--);for(o=0;o>> no match, partial?`,r,c,e,f),c===s))}var d;if(typeof l=="string"?(i.nocase?d=u.toLowerCase()===l.toLowerCase():d=u===l,this.debug("string match",l,u,d)):(d=u.match(l),this.debug("pattern match",l,u,d)),!d)return!1}if(n===s&&o===a)return!0;if(n===s)return t;if(o===a){var h=n===s-1&&r[n]==="";return h}throw new Error("wtf?")};function kde(r){return r.replace(/\\(.)/g,"$1")}function Fde(r){return r.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")}});var bj=v((cIe,vj)=>{var h0=4294967296,yj=[];for(var ip=0;ip<256;ip++)yj[ip]=(ip>15?"":"0")+ip.toString(16);var np=vj.exports=function(r,e){r instanceof Buffer?(this.buffer=r,this.offset=e||0):Object.prototype.toString.call(r)=="[object Uint8Array]"?(this.buffer=new Buffer(r),this.offset=e||0):(this.buffer=this.buffer||new Buffer(8),this.offset=0,this.setValue.apply(this,arguments))};np.MAX_INT=Math.pow(2,53);np.MIN_INT=-Math.pow(2,53);np.prototype={constructor:np,_2scomp:function(){for(var r=this.buffer,e=this.offset,t=1,i=e+7;i>=e;i--){var n=(r[i]^255)+t;r[i]=n&255,t=n>>8}},setValue:function(r,e){var t=!1;if(arguments.length==1)if(typeof r=="number"){if(t=r<0,r=Math.abs(r),e=r%h0,r=r/h0,r>h0)throw new RangeError(r+" is outside Int64 range");r=r|0}else if(typeof r=="string")r=(r+"").replace(/^0x/,""),e=r.substr(-8),r=r.length>8?r.substr(0,r.length-8):"",r=parseInt(r,16),e=parseInt(e,16);else throw new Error(r+" must be a Number or String");for(var i=this.buffer,n=this.offset,o=7;o>=0;o--)i[n+o]=e&255,e=o==4?r:e>>>8;t&&this._2scomp()},toNumber:function(r){for(var e=this.buffer,t=this.offset,i=e[t]&128,n=0,o=1,s=7,a=1;s>=0;s--,a*=256){var l=e[t+s];i&&(l=(l^255)+o,o=l>>8,l=l&255),n+=l*a}return!r&&n>=np.MAX_INT?i?-Infinity:Infinity:i?-n:n},valueOf:function(){return this.toNumber(!1)},toString:function(r){return this.valueOf().toString(r||10)},toOctetString:function(r){for(var e=new Array(8),t=this.buffer,i=this.offset,n=0;n<8;n++)e[n]=yj[t[i+n]];return e.join(r||"")},toBuffer:function(r){if(r&&this.offset===0)return this.buffer;var e=new Buffer(8);return this.buffer.copy(e,0,this.offset,this.offset+8),e},copy:function(r,e){this.buffer.copy(r,e||0,this.offset,this.offset+8)},compare:function(r){if((this.buffer[this.offset]&128)!=(r.buffer[r.offset]&128))return r.buffer[r.offset]-this.buffer[this.offset];for(var e=0;e<8;e++)if(this.buffer[this.offset+e]!==r.buffer[r.offset+e])return this.buffer[this.offset+e]-r.buffer[r.offset+e];return 0},equals:function(r){return this.compare(r)===0},inspect:function(){return"[Int64 value:"+this+" octets:"+this.toOctetString(" ")+"]"}}});var kj=v(op=>{var wj=require("events").EventEmitter,$de=require("util"),Bde=require("os"),fIe=require("assert"),sp=bj(),Ho=Bde.endianness()=="BE";function xj(r){return Math.pow(2,Math.ceil(Math.log(r)/Math.LN2))}function Lt(r){this.buf=Buffer.alloc(xj(r||8192)),this.readOffset=0,this.writeOffset=0}op.Accumulator=Lt;Lt.prototype.writeAvail=function(){return this.buf.length-this.writeOffset};Lt.prototype.readAvail=function(){return this.writeOffset-this.readOffset};Lt.prototype.reserve=function(r){if(!(r0&&(this.buf.copy(this.buf,0,this.readOffset,this.writeOffset),this.writeOffset-=this.readOffset,this.readOffset=0),!(r0)this.assertReadableSize(r);else if(r<0&&this.readOffset+r<0)throw new Error("advance with negative offset "+r+" would seek off the start of the buffer");this.readOffset+=r};Lt.prototype.writeByte=function(r){this.reserve(1),this.buf.writeInt8(r,this.writeOffset),++this.writeOffset};Lt.prototype.writeInt=function(r,e){switch(this.reserve(e),e){case 1:this.buf.writeInt8(r,this.writeOffset);break;case 2:Ho?this.buf.writeInt16BE(r,this.writeOffset):this.buf.writeInt16LE(r,this.writeOffset);break;case 4:Ho?this.buf.writeInt32BE(r,this.writeOffset):this.buf.writeInt32LE(r,this.writeOffset);break;default:throw new Error("unsupported integer size "+e)}this.writeOffset+=e};Lt.prototype.writeDouble=function(r){this.reserve(8),Ho?this.buf.writeDoubleBE(r,this.writeOffset):this.buf.writeDoubleLE(r,this.writeOffset),this.writeOffset+=8};var m0=0,g0=1,v0=2,y0=3,b0=4,ag=5,lg=6,Sj=7,Ej=8,Cj=9,_j=10,Pj=11,jde=12,w0=0,Tj=1,Ude=127,Wde=32767,Hde=2147483647;function Or(){wj.call(this),this.buf=new Lt,this.state=w0}$de.inherits(Or,wj);op.BunserBuf=Or;Or.prototype.append=function(r,e){if(e)return this.buf.append(r),this.process(e);try{this.buf.append(r)}catch(t){this.emit("error",t);return}this.processLater()};Or.prototype.processLater=function(){var r=this;process.nextTick(function(){try{r.process(!1)}catch(e){r.emit("error",e)}})};Or.prototype.process=function(r){if(this.state==w0){if(this.buf.readAvail()<2)return;if(this.expectCode(0),this.expectCode(1),this.pduLen=this.decodeInt(!0),this.pduLen===!1){this.buf.readAdvance(-2);return}this.buf.reserve(this.pduLen),this.state=Tj}if(this.state==Tj){if(this.buf.readAvail()0&&this.processLater()};Or.prototype.raise=function(r){throw new Error(r+", 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()))};Or.prototype.expectCode=function(r){var e=this.buf.readInt(1);e!=r&&this.raise("expected bser opcode "+r+" but got "+e)};Or.prototype.decodeAny=function(){var r=this.buf.peekInt(1);switch(r){case y0:case b0:case ag:case lg:return this.decodeInt();case Sj:return this.buf.readAdvance(1),this.buf.readDouble();case Ej:return this.buf.readAdvance(1),!0;case Cj:return this.buf.readAdvance(1),!1;case _j:return this.buf.readAdvance(1),null;case v0:return this.decodeString();case m0:return this.decodeArray();case g0:return this.decodeObject();case Pj:return this.decodeTemplate();default:this.raise("unhandled bser opcode "+r)}};Or.prototype.decodeArray=function(){this.expectCode(m0);for(var r=this.decodeInt(),e=[],t=0;t{"use strict";var Vde=require("net"),Fj=require("events").EventEmitter,Kde=require("util"),Jde=require("child_process"),Aj=kj(),Oj=["subscription","log"];function Kn(r){var e=this;Fj.call(this),this.watchmanBinaryPath="watchman",r&&r.watchmanBinaryPath&&(this.watchmanBinaryPath=r.watchmanBinaryPath.trim()),this.commands=[]}Kde.inherits(Kn,Fj);Ij.exports.Client=Kn;Kn.prototype.sendNextCommand=function(){this.currentCommand||(this.currentCommand=this.commands.shift(),!!this.currentCommand&&this.socket.write(Aj.dumpToBuffer(this.currentCommand.cmd)))};Kn.prototype.cancelCommands=function(r){var e=new Error(r),t=this.commands;this.commands=[],this.currentCommand&&(t.unshift(this.currentCommand),this.currentCommand=null),t.forEach(function(i){i.cb(e)})};Kn.prototype.connect=function(){var r=this;function e(l){r.bunser=new Aj.BunserBuf,r.bunser.on("value",function(u){for(var c=!1,f=0;f=0:!1}Kn.prototype._synthesizeCapabilityCheck=function(r,e,t){r.capabilities={};var i=r.version;return e.forEach(function(n){r.capabilities[n]=Mj(i,n)}),t.forEach(function(n){var o=Mj(i,n);r.capabilities[n]=o,o||(r.error="client required capability `"+n+"` is not supported by this server")}),r};Kn.prototype.capabilityCheck=function(r,e){var t=r.optional||[],i=r.required||[],n=this;this.command(["version",{optional:t,required:i}],function(o,s){if(o){e(o);return}if(!("capabilities"in s)&&(s=n._synthesizeCapabilityCheck(s,t,i),s.error)){o=new Error(s.error),o.watchmanResponse=s,e(o);return}e(null,s)})};Kn.prototype.end=function(){this.cancelCommands("The client was ended"),this.socket&&(this.socket.end(),this.socket=null),this.bunser=null}});var lU=v(oa=>{oa.parse=oa.decode=lhe;oa.stringify=oa.encode=oU;oa.safe=eu;oa.unsafe=vg;var A0=typeof process!="undefined"&&process.platform==="win32"?`\r -`:` -`;function oU(r,e){var t=[],i="";typeof e=="string"?e={section:e,whitespace:!1}:(e=e||{},e.whitespace=e.whitespace===!0);var n=e.whitespace?" = ":"=";return Object.keys(r).forEach(function(o,s,a){var l=r[o];l&&Array.isArray(l)?l.forEach(function(u){i+=eu(o+"[]")+n+eu(u)+` -`}):l&&typeof l=="object"?t.push(o):i+=eu(o)+n+eu(l)+A0}),e.section&&i.length&&(i="["+eu(e.section)+"]"+A0+i),t.forEach(function(o,s,a){var l=sU(o).join("\\."),u=(e.section?e.section+".":"")+l,c=oU(r[o],{section:u,whitespace:e.whitespace});i.length&&c.length&&(i+=A0),i+=c}),i}function sU(r){return r.replace(/\1/g,"LITERAL\\1LITERAL").replace(/\\\./g,"").split(/\./).map(function(e){return e.replace(/\1/g,"\\.").replace(/\2LITERAL\\1LITERAL\2/g,"")})}function lhe(r){var e={},t=e,i=null,n=/^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i,o=r.split(/[\r\n]+/g);return o.forEach(function(s,a,l){if(!(!s||s.match(/^\s*[;#]/))){var u=s.match(n);if(!!u){if(u[1]!==void 0){i=vg(u[1]),t=e[i]=e[i]||{};return}var c=vg(u[2]),f=u[3]?vg(u[4]):!0;switch(f){case"true":case"false":case"null":f=JSON.parse(f)}c.length>2&&c.slice(-2)==="[]"&&(c=c.substring(0,c.length-2),t[c]?Array.isArray(t[c])||(t[c]=[t[c]]):t[c]=[]),Array.isArray(t[c])?t[c].push(f):t[c]=f}}}),Object.keys(e).filter(function(s,a,l){if(!e[s]||typeof e[s]!="object"||Array.isArray(e[s]))return!1;var u=sU(s),c=e,f=u.pop(),p=f.replace(/\\\./g,".");return u.forEach(function(d,h,m){(!c[d]||typeof c[d]!="object")&&(c[d]={}),c=c[d]}),c===e&&p===f?!1:(c[p]=e[s],!0)}).forEach(function(s,a,l){delete e[s]}),e}function aU(r){return r.charAt(0)==='"'&&r.slice(-1)==='"'||r.charAt(0)==="'"&&r.slice(-1)==="'"}function eu(r){return typeof r!="string"||r.match(/[=\r\n]/)||r.match(/^\[/)||r.length>1&&aU(r)||r!==r.trim()?JSON.stringify(r):r.replace(/;/g,"\\;").replace(/#/g,"\\#")}function vg(r,e){if(r=(r||"").trim(),aU(r)){r.charAt(0)==="'"&&(r=r.substr(1,r.length-2));try{r=JSON.parse(r)}catch(a){}}else{for(var t=!1,i="",n=0,o=r.length;n{"use strict";var O0=1,cU=2;function uhe(){return""}function che(r,e,t){return r.slice(e,t).replace(/\S/g," ")}uU.exports=function(r,e){e=e||{};for(var t,i,n=!1,o=!1,s=0,a="",l=e.whitespace===!1?uhe:che,u=0;u{"use strict";var pU=require("fs"),fhe=lU(),pp=require("path"),phe=fU(),dhe=tu.parse=function(r){return/^\s*{/.test(r)?JSON.parse(phe(r)):fhe.parse(r)},hhe=tu.file=function(){var r=[].slice.call(arguments).filter(function(n){return n!=null});for(var e in r)if(typeof r[e]!="string")return;var t=pp.join.apply(null,r),i;try{return pU.readFileSync(t,"utf-8")}catch(n){return}},MAe=tu.json=function(){var r=hhe.apply(null,arguments);return r?dhe(r):null},NAe=tu.env=function(r,e){e=e||process.env;var t={},i=r.length;for(var n in e)if(n.toLowerCase().indexOf(r.toLowerCase())===0){for(var o=n.substring(i).split("__"),s;(s=o.indexOf(""))>-1;)o.splice(s,1);var a=t;o.forEach(function(u,c){!u||typeof a!="object"||(c===o.length-1&&(a[u]=e[n]),a[u]===void 0&&(a[u]={}),a=a[u])})}return t},qAe=tu.find=function(){var r=pp.join.apply(null,[].slice.call(arguments));function e(t,i){var n=pp.join(t,i);try{return pU.statSync(n),n}catch(o){if(pp.dirname(t)!==t)return e(pp.dirname(t),i)}}return e(process.cwd(),r)}});var bU=v((BAe,hU)=>{"use strict";function mU(r){return r instanceof Buffer||r instanceof Date||r instanceof RegExp}function gU(r){if(r instanceof Buffer){var e=Buffer.alloc?Buffer.alloc(r.length):new Buffer(r.length);return r.copy(e),e}else{if(r instanceof Date)return new Date(r.getTime());if(r instanceof RegExp)return new RegExp(r);throw new Error("Unexpected situation")}}function vU(r){var e=[];return r.forEach(function(t,i){typeof t=="object"&&t!==null?Array.isArray(t)?e[i]=vU(t):mU(t)?e[i]=gU(t):e[i]=L0({},t):e[i]=t}),e}function yU(r,e){return e==="__proto__"?void 0:r[e]}var L0=hU.exports=function(){if(arguments.length<1||typeof arguments[0]!="object")return!1;if(arguments.length<2)return arguments[0];var r=arguments[0],e=Array.prototype.slice.call(arguments,1),t,i,n;return e.forEach(function(o){typeof o!="object"||o===null||Array.isArray(o)||Object.keys(o).forEach(function(s){if(i=yU(r,s),t=yU(o,s),t!==r)if(typeof t!="object"||t===null){r[s]=t;return}else if(Array.isArray(t)){r[s]=vU(t);return}else if(mU(t)){r[s]=gU(t);return}else if(typeof i!="object"||i===null||Array.isArray(i)){r[s]=L0({},t);return}else{r[s]=L0(i,t);return}})}),r}});var DU=v((jAe,wU)=>{wU.exports=function(r,e){e||(e={});var t={bools:{},strings:{},unknownFn:null};typeof e.unknown=="function"&&(t.unknownFn=e.unknown),typeof e.boolean=="boolean"&&e.boolean?t.allBools=!0:[].concat(e.boolean).filter(Boolean).forEach(function(E){t.bools[E]=!0});var i={};Object.keys(e.alias||{}).forEach(function(E){i[E]=[].concat(e.alias[E]),i[E].forEach(function(P){i[P]=[E].concat(i[E].filter(function(k){return P!==k}))})}),[].concat(e.string).filter(Boolean).forEach(function(E){t.strings[E]=!0,i[E]&&(t.strings[i[E]]=!0)});var n=e.default||{},o={_:[]};Object.keys(t.bools).forEach(function(E){l(E,n[E]===void 0?!1:n[E])});var s=[];r.indexOf("--")!==-1&&(s=r.slice(r.indexOf("--")+1),r=r.slice(0,r.indexOf("--")));function a(E,P){return t.allBools&&/^--[^=]+$/.test(P)||t.strings[E]||t.bools[E]||i[E]}function l(E,P,k){if(!(k&&t.unknownFn&&!a(E,k)&&t.unknownFn(k)===!1)){var _=!t.strings[E]&&xU(P)?Number(P):P;u(o,E.split("."),_),(i[E]||[]).forEach(function(L){u(o,L.split("."),_)})}}function u(E,P,k){for(var _=E,L=0;L{var dp=dU(),ru=require("path").join,ghe=bU(),EU="/etc",CU=process.platform==="win32",hp=CU?process.env.USERPROFILE:process.env.HOME;SU.exports=function(r,e,t,i){if(typeof r!="string")throw new Error("rc(name): name *must* be string");t||(t=DU()(process.argv.slice(2))),e=(typeof e=="string"?dp.json(e):e)||{},i=i||dp.parse;var n=dp.env(r+"_"),o=[e],s=[];function a(l){if(!(s.indexOf(l)>=0)){var u=dp.file(l);u&&(o.push(i(u)),s.push(l))}}return CU||[ru(EU,r,"config"),ru(EU,r+"rc")].forEach(a),hp&&[ru(hp,".config",r,"config"),ru(hp,".config",r),ru(hp,"."+r,"config"),ru(hp,"."+r+"rc")].forEach(a),a(dp.find("."+r+"rc")),n.config&&a(n.config),t.config&&a(t.config),ghe.apply(null,o.concat([n,t,s.length?{configs:s,config:s[s.length-1]}:void 0]))}});var RU=v((M0,PU)=>{var yg=require("buffer"),Yn=yg.Buffer;function TU(r,e){for(var t in r)e[t]=r[t]}Yn.from&&Yn.alloc&&Yn.allocUnsafe&&Yn.allocUnsafeSlow?PU.exports=yg:(TU(yg,M0),M0.Buffer=iu);function iu(r,e,t){return Yn(r,e,t)}TU(Yn,iu);iu.from=function(r,e,t){if(typeof r=="number")throw new TypeError("Argument must not be a number");return Yn(r,e,t)};iu.alloc=function(r,e,t){if(typeof r!="number")throw new TypeError("Argument must be a number");var i=Yn(r);return e!==void 0?typeof t=="string"?i.fill(e,t):i.fill(e):i.fill(0),i};iu.allocUnsafe=function(r){if(typeof r!="number")throw new TypeError("Argument must be a number");return Yn(r)};iu.allocUnsafeSlow=function(r){if(typeof r!="number")throw new TypeError("Argument must be a number");return yg.SlowBuffer(r)}});var LU=v((WAe,N0)=>{"use strict";N0.exports=vhe;N0.exports.parse=yhe;var kU=require("path").basename,bhe=RU().Buffer,whe=/[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g,xhe=/%[0-9A-Fa-f]{2}/,Dhe=/%([0-9A-Fa-f]{2})/g,IU=/[^\x20-\x7e\xa0-\xff]/g,She=/\\([\u0000-\u007f])/g,Ehe=/([\\"])/g,FU=/;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g,Che=/^[\x20-\x7e\x80-\xff]+$/,_he=/^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/,Phe=/^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/,The=/^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/;function vhe(r,e){var t=e||{},i=t.type||"attachment",n=Rhe(r,t.fallback);return khe(new AU(i,n))}function Rhe(r,e){if(r!==void 0){var t={};if(typeof r!="string")throw new TypeError("filename must be a string");if(e===void 0&&(e=!0),typeof e!="string"&&typeof e!="boolean")throw new TypeError("fallback must be a string or boolean");if(typeof e=="string"&&IU.test(e))throw new TypeError("fallback must be ISO-8859-1 string");var i=kU(r),n=Che.test(i),o=typeof e!="string"?e&&OU(i):kU(e),s=typeof o=="string"&&o!==i;return(s||!n||xhe.test(i))&&(t["filename*"]=i),(n||s)&&(t.filename=s?o:i),t}}function khe(r){var e=r.parameters,t=r.type;if(!t||typeof t!="string"||!_he.test(t))throw new TypeError("invalid type");var i=String(t).toLowerCase();if(e&&typeof e=="object")for(var n,o=Object.keys(e).sort(),s=0;s{var q0;try{q0=vt()("follow-redirects")}catch(r){q0=function(){}}MU.exports=q0});var W0=v((zAe,$0)=>{var nu=require("url"),B0=nu.URL,Mhe=require("http"),Nhe=require("https"),qU=require("stream").Writable,qhe=require("assert"),$U=NU(),j0=Object.create(null);["abort","aborted","connect","error","socket","timeout"].forEach(function(r){j0[r]=function(e,t,i){this._redirectable.emit(r,e,t,i)}});var $he=bg("ERR_FR_REDIRECTION_FAILURE",""),Bhe=bg("ERR_FR_TOO_MANY_REDIRECTS","Maximum number of redirects exceeded"),jhe=bg("ERR_FR_MAX_BODY_LENGTH_EXCEEDED","Request body larger than maxBodyLength limit"),Uhe=bg("ERR_STREAM_WRITE_AFTER_END","write after end");function Ti(r,e){qU.call(this),this._sanitizeOptions(r),this._options=r,this._ended=!1,this._ending=!1,this._redirectCount=0,this._redirects=[],this._requestBodyLength=0,this._requestBodyBuffers=[],e&&this.on("response",e);var t=this;this._onNativeResponse=function(i){t._processResponse(i)},this._performRequest()}Ti.prototype=Object.create(qU.prototype);Ti.prototype.write=function(r,e,t){if(this._ending)throw new Uhe;if(!(typeof r=="string"||typeof r=="object"&&"length"in r))throw new TypeError("data should be a string, Buffer or Uint8Array");if(typeof e=="function"&&(t=e,e=null),r.length===0){t&&t();return}this._requestBodyLength+r.length<=this._options.maxBodyLength?(this._requestBodyLength+=r.length,this._requestBodyBuffers.push({data:r,encoding:e}),this._currentRequest.write(r,e,t)):(this.emit("error",new jhe),this.abort())};Ti.prototype.end=function(r,e,t){if(typeof r=="function"?(t=r,r=e=null):typeof e=="function"&&(t=e,e=null),!r)this._ended=this._ending=!0,this._currentRequest.end(null,null,t);else{var i=this,n=this._currentRequest;this.write(r,e,function(){i._ended=!0,n.end(null,null,t)}),this._ending=!0}};Ti.prototype.setHeader=function(r,e){this._options.headers[r]=e,this._currentRequest.setHeader(r,e)};Ti.prototype.removeHeader=function(r){delete this._options.headers[r],this._currentRequest.removeHeader(r)};Ti.prototype.setTimeout=function(r,e){if(e&&this.once("timeout",e),this.socket)BU(this,r);else{var t=this;this._currentRequest.once("socket",function(){BU(t,r)})}return this.once("response",jU),this.once("error",jU),this};function BU(r,e){clearTimeout(r._timeout),r._timeout=setTimeout(function(){r.emit("timeout")},e)}function jU(){clearTimeout(this._timeout)}["abort","flushHeaders","getHeader","setNoDelay","setSocketKeepAlive"].forEach(function(r){Ti.prototype[r]=function(e,t){return this._currentRequest[r](e,t)}});["aborted","connection","socket"].forEach(function(r){Object.defineProperty(Ti.prototype,r,{get:function(){return this._currentRequest[r]}})});Ti.prototype._sanitizeOptions=function(r){if(r.headers||(r.headers={}),r.host&&(r.hostname||(r.hostname=r.host),delete r.host),!r.pathname&&r.path){var e=r.path.indexOf("?");e<0?r.pathname=r.path:(r.pathname=r.path.substring(0,e),r.search=r.path.substring(e))}};Ti.prototype._performRequest=function(){var r=this._options.protocol,e=this._options.nativeProtocols[r];if(!e){this.emit("error",new TypeError("Unsupported protocol "+r));return}if(this._options.agents){var t=r.substr(0,r.length-1);this._options.agent=this._options.agents[t]}var i=this._currentRequest=e.request(this._options,this._onNativeResponse);this._currentUrl=nu.format(this._options),i._redirectable=this;for(var n in j0)n&&i.on(n,j0[n]);if(this._isRedirect){var o=0,s=this,a=this._requestBodyBuffers;(function l(u){if(i===s._currentRequest)if(u)s.emit("error",u);else if(o=300&&e<400){if(this._currentRequest.removeAllListeners(),this._currentRequest.on("error",Whe),this._currentRequest.abort(),r.destroy(),++this._redirectCount>this._options.maxRedirects){this.emit("error",new Bhe);return}((e===301||e===302)&&this._options.method==="POST"||e===303&&!/^(?:GET|HEAD)$/.test(this._options.method))&&(this._options.method="GET",this._requestBodyBuffers=[],U0(/^content-/i,this._options.headers));var i=U0(/^host$/i,this._options.headers)||nu.parse(this._currentUrl).hostname,n=nu.resolve(this._currentUrl,t);$U("redirecting to",n),this._isRedirect=!0;var o=nu.parse(n);if(Object.assign(this._options,o),o.hostname!==i&&U0(/^authorization$/i,this._options.headers),typeof this._options.beforeRedirect=="function"){var s={headers:r.headers};try{this._options.beforeRedirect.call(null,this._options,s)}catch(l){this.emit("error",l);return}this._sanitizeOptions(this._options)}try{this._performRequest()}catch(l){var a=new $he("Redirected request failed: "+l.message);a.cause=l,this.emit("error",a)}}else r.responseUrl=this._currentUrl,r.redirects=this._redirects,this.emit("response",r),this._requestBodyBuffers=[]};function WU(r){var e={maxRedirects:21,maxBodyLength:10*1024*1024},t={};return Object.keys(r).forEach(function(i){var n=i+":",o=t[n]=r[i],s=e[i]=Object.create(o);s.request=function(a,l,u){if(typeof a=="string"){var c=a;try{a=UU(new B0(c))}catch(f){a=nu.parse(c)}}else B0&&a instanceof B0?a=UU(a):(u=l,l=a,a={protocol:n});return typeof l=="function"&&(u=l,l=null),l=Object.assign({maxRedirects:e.maxRedirects,maxBodyLength:e.maxBodyLength},a,l),l.nativeProtocols=t,qhe.equal(l.protocol,n,"protocol mismatch"),$U("options",l),new Ti(l,u)},s.get=function(a,l,u){var c=s.request(a,l,u);return c.end(),c}}),e}function Whe(){}function UU(r){var e={protocol:r.protocol,hostname:r.hostname.startsWith("[")?r.hostname.slice(1,-1):r.hostname,hash:r.hash,search:r.search,pathname:r.pathname,path:r.pathname+r.search,href:r.href};return r.port!==""&&(e.port=Number(r.port)),e}function U0(r,e){var t;for(var i in e)r.test(i)&&(t=e[i],delete e[i]);return t}function bg(r,e){function t(i){Error.captureStackTrace(this,this.constructor),this.message=i||e}return t.prototype=new Error,t.prototype.constructor=t,t.prototype.name="Error ["+r+"]",t.prototype.code=r,t}$0.exports=WU({http:Mhe,https:Nhe});$0.exports.wrap=WU});var ou=v((VAe,HU)=>{"use strict";var zU=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"]]),GAe=HU.exports=r=>r?Object.keys(r).map(e=>[zU.has(e)?zU.get(e):e,r[e]]).reduce((e,t)=>(e[t[0]]=t[1],e),Object.create(null)):{}});var VU=v((KAe,GU)=>{"use strict";GU.exports=function(r){r.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}});var wg=v((JAe,KU)=>{"use strict";KU.exports=Ae;Ae.Node=sa;Ae.create=Ae;function Ae(r){var e=this;if(e instanceof Ae||(e=new Ae),e.tail=null,e.head=null,e.length=0,r&&typeof r.forEach=="function")r.forEach(function(n){e.push(n)});else if(arguments.length>0)for(var t=0,i=arguments.length;t1)t=e;else if(this.head)i=this.head.next,t=this.head.value;else throw new TypeError("Reduce of empty list with no initial value");for(var n=0;i!==null;n++)t=r(t,i.value,n),i=i.next;return t};Ae.prototype.reduceReverse=function(r,e){var t,i=this.tail;if(arguments.length>1)t=e;else if(this.tail)i=this.tail.prev,t=this.tail.value;else throw new TypeError("Reduce of empty list with no initial value");for(var n=this.length-1;i!==null;n--)t=r(t,i.value,n),i=i.prev;return t};Ae.prototype.toArray=function(){for(var r=new Array(this.length),e=0,t=this.head;t!==null;e++)r[e]=t.value,t=t.next;return r};Ae.prototype.toArrayReverse=function(){for(var r=new Array(this.length),e=0,t=this.tail;t!==null;e++)r[e]=t.value,t=t.prev;return r};Ae.prototype.slice=function(r,e){e=e||this.length,e<0&&(e+=this.length),r=r||0,r<0&&(r+=this.length);var t=new Ae;if(ethis.length&&(e=this.length);for(var i=0,n=this.head;n!==null&&ithis.length&&(e=this.length);for(var i=this.length,n=this.tail;n!==null&&i>e;i--)n=n.prev;for(;n!==null&&i>r;i--,n=n.prev)t.push(n.value);return t};Ae.prototype.splice=function(r,e,...t){r>this.length&&(r=this.length-1),r<0&&(r=this.length+r);for(var i=0,n=this.head;n!==null&&i{"use strict";var Vhe=require("events"),YU=require("stream"),mp=wg(),XU=require("string_decoder").StringDecoder,Xn=Symbol("EOF"),gp=Symbol("maybeEmitEnd"),Vo=Symbol("emittedEnd"),xg=Symbol("emittingEnd"),Dg=Symbol("closed"),ZU=Symbol("read"),QU=Symbol("flush"),e6=Symbol("flushChunk"),Lr=Symbol("encoding"),Zn=Symbol("decoder"),Sg=Symbol("flowing"),vp=Symbol("paused"),yp=Symbol("resume"),Mr=Symbol("bufferLength"),t6=Symbol("bufferPush"),H0=Symbol("bufferShift"),ur=Symbol("objectMode"),cr=Symbol("destroyed"),r6=global._MP_NO_ITERATOR_SYMBOLS_!=="1",Khe=r6&&Symbol.asyncIterator||Symbol("asyncIterator not implemented"),Jhe=r6&&Symbol.iterator||Symbol("iterator not implemented"),i6=r=>r==="end"||r==="finish"||r==="prefinish",Yhe=r=>r instanceof ArrayBuffer||typeof r=="object"&&r.constructor&&r.constructor.name==="ArrayBuffer"&&r.byteLength>=0,Xhe=r=>!Buffer.isBuffer(r)&&ArrayBuffer.isView(r);JU.exports=class n6 extends YU{constructor(e){super();this[Sg]=!1,this[vp]=!1,this.pipes=new mp,this.buffer=new mp,this[ur]=e&&e.objectMode||!1,this[ur]?this[Lr]=null:this[Lr]=e&&e.encoding||null,this[Lr]==="buffer"&&(this[Lr]=null),this[Zn]=this[Lr]?new XU(this[Lr]):null,this[Xn]=!1,this[Vo]=!1,this[xg]=!1,this[Dg]=!1,this.writable=!0,this.readable=!0,this[Mr]=0,this[cr]=!1}get bufferLength(){return this[Mr]}get encoding(){return this[Lr]}set encoding(e){if(this[ur])throw new Error("cannot set encoding in objectMode");if(this[Lr]&&e!==this[Lr]&&(this[Zn]&&this[Zn].lastNeed||this[Mr]))throw new Error("cannot change encoding");this[Lr]!==e&&(this[Zn]=e?new XU(e):null,this.buffer.length&&(this.buffer=this.buffer.map(t=>this[Zn].write(t)))),this[Lr]=e}setEncoding(e){this.encoding=e}get objectMode(){return this[ur]}set objectMode(e){this[ur]=this[ur]||!!e}write(e,t,i){if(this[Xn])throw new Error("write after end");if(this[cr])return this.emit("error",Object.assign(new Error("Cannot call write after a stream was destroyed"),{code:"ERR_STREAM_DESTROYED"})),!0;if(typeof t=="function"&&(i=t,t="utf8"),t||(t="utf8"),!this[ur]&&!Buffer.isBuffer(e)&&(Xhe(e)?e=Buffer.from(e.buffer,e.byteOffset,e.byteLength):Yhe(e)?e=Buffer.from(e):typeof e!="string"&&(this.objectMode=!0)),!this.objectMode&&!e.length){let n=this.flowing;return this[Mr]!==0&&this.emit("readable"),i&&i(),n}typeof e=="string"&&!this[ur]&&!(t===this[Lr]&&!this[Zn].lastNeed)&&(e=Buffer.from(e,t)),Buffer.isBuffer(e)&&this[Lr]&&(e=this[Zn].write(e));try{return this.flowing?(this.emit("data",e),this.flowing):(this[t6](e),!1)}finally{this[Mr]!==0&&this.emit("readable"),i&&i()}}read(e){if(this[cr])return null;try{return this[Mr]===0||e===0||e>this[Mr]?null:(this[ur]&&(e=null),this.buffer.length>1&&!this[ur]&&(this.encoding?this.buffer=new mp([Array.from(this.buffer).join("")]):this.buffer=new mp([Buffer.concat(Array.from(this.buffer),this[Mr])])),this[ZU](e||null,this.buffer.head.value))}finally{this[gp]()}}[ZU](e,t){return e===t.length||e===null?this[H0]():(this.buffer.head.value=t.slice(e),t=t.slice(0,e),this[Mr]-=e),this.emit("data",t),!this.buffer.length&&!this[Xn]&&this.emit("drain"),t}end(e,t,i){return typeof e=="function"&&(i=e,e=null),typeof t=="function"&&(i=t,t="utf8"),e&&this.write(e,t),i&&this.once("end",i),this[Xn]=!0,this.writable=!1,(this.flowing||!this[vp])&&this[gp](),this}[yp](){this[cr]||(this[vp]=!1,this[Sg]=!0,this.emit("resume"),this.buffer.length?this[QU]():this[Xn]?this[gp]():this.emit("drain"))}resume(){return this[yp]()}pause(){this[Sg]=!1,this[vp]=!0}get destroyed(){return this[cr]}get flowing(){return this[Sg]}get paused(){return this[vp]}[t6](e){return this[ur]?this[Mr]+=1:this[Mr]+=e.length,this.buffer.push(e)}[H0](){return this.buffer.length&&(this[ur]?this[Mr]-=1:this[Mr]-=this.buffer.head.value.length),this.buffer.shift()}[QU](){do;while(this[e6](this[H0]()));!this.buffer.length&&!this[Xn]&&this.emit("drain")}[e6](e){return e?(this.emit("data",e),this.flowing):!1}pipe(e,t){if(this[cr])return;let i=this[Vo];t=t||{},e===process.stdout||e===process.stderr?t.end=!1:t.end=t.end!==!1;let n={dest:e,opts:t,ondrain:o=>this[yp]()};return this.pipes.push(n),e.on("drain",n.ondrain),this[yp](),i&&n.opts.end&&n.dest.end(),e}addListener(e,t){return this.on(e,t)}on(e,t){try{return super.on(e,t)}finally{e==="data"&&!this.pipes.length&&!this.flowing?this[yp]():i6(e)&&this[Vo]&&(super.emit(e),this.removeAllListeners(e))}}get emittedEnd(){return this[Vo]}[gp](){!this[xg]&&!this[Vo]&&!this[cr]&&this.buffer.length===0&&this[Xn]&&(this[xg]=!0,this.emit("end"),this.emit("prefinish"),this.emit("finish"),this[Dg]&&this.emit("close"),this[xg]=!1)}emit(e,t){if(e!=="error"&&e!=="close"&&e!==cr&&this[cr])return;if(e==="data"){if(!t)return;this.pipes.length&&this.pipes.forEach(n=>n.dest.write(t)===!1&&this.pause())}else if(e==="end"){if(this[Vo]===!0)return;this[Vo]=!0,this.readable=!1,this[Zn]&&(t=this[Zn].end(),t&&(this.pipes.forEach(n=>n.dest.write(t)),super.emit("data",t))),this.pipes.forEach(n=>{n.dest.removeListener("drain",n.ondrain),n.opts.end&&n.dest.end()})}else if(e==="close"&&(this[Dg]=!0,!this[Vo]&&!this[cr]))return;let i=new Array(arguments.length);if(i[0]=e,i[1]=t,arguments.length>2)for(let n=2;n{e.push(i),this[ur]||(e.dataLength+=i.length)}),t.then(()=>e)}concat(){return this[ur]?Promise.reject(new Error("cannot concat in objectMode")):this.collect().then(e=>this[ur]?Promise.reject(new Error("cannot concat in objectMode")):this[Lr]?e.join(""):Buffer.concat(e,e.dataLength))}promise(){return new Promise((e,t)=>{this.on(cr,()=>t(new Error("stream destroyed"))),this.on("end",()=>e()),this.on("error",i=>t(i))})}[Khe](){return{next:()=>{let t=this.read();if(t!==null)return Promise.resolve({done:!1,value:t});if(this[Xn])return Promise.resolve({done:!0});let i=null,n=null,o=u=>{this.removeListener("data",s),this.removeListener("end",a),n(u)},s=u=>{this.removeListener("error",o),this.removeListener("end",a),this.pause(),i({value:u,done:!!this[Xn]})},a=()=>{this.removeListener("error",o),this.removeListener("data",s),i({done:!0})},l=()=>o(new Error("stream destroyed"));return new Promise((u,c)=>{n=c,i=u,this.once(cr,l),this.once("error",o),this.once("end",a),this.once("data",s)})}}}[Jhe](){return{next:()=>{let t=this.read();return{value:t,done:t===null}}}}destroy(e){return this[cr]?(e?this.emit("error",e):this.emit(cr),this):(this[cr]=!0,this.buffer=new mp,this[Mr]=0,typeof this.close=="function"&&!this[Dg]&&this.close(),e?this.emit("error",e):this.emit(cr),this)}static isStream(e){return!!e&&(e instanceof n6||e instanceof YU||e instanceof Vhe&&(typeof e.pipe=="function"||typeof e.write=="function"&&typeof e.end=="function"))}}});var s6=v((XAe,o6)=>{var Zhe=require("zlib").constants||{ZLIB_VERNUM:4736};o6.exports=Object.freeze(Object.assign(Object.create(null),{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,DEFLATE:1,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:7,BROTLI_DECODE:8,BROTLI_ENCODE:9,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,BROTLI_OPERATION_PROCESS:0,BROTLI_OPERATION_FLUSH:1,BROTLI_OPERATION_FINISH:2,BROTLI_OPERATION_EMIT_METADATA:3,BROTLI_MODE_GENERIC:0,BROTLI_MODE_TEXT:1,BROTLI_MODE_FONT:2,BROTLI_DEFAULT_MODE:0,BROTLI_MIN_QUALITY:0,BROTLI_MAX_QUALITY:11,BROTLI_DEFAULT_QUALITY:11,BROTLI_MIN_WINDOW_BITS:10,BROTLI_MAX_WINDOW_BITS:24,BROTLI_LARGE_MAX_WINDOW_BITS:30,BROTLI_DEFAULT_WINDOW:22,BROTLI_MIN_INPUT_BLOCK_BITS:16,BROTLI_MAX_INPUT_BLOCK_BITS:24,BROTLI_PARAM_MODE:0,BROTLI_PARAM_QUALITY:1,BROTLI_PARAM_LGWIN:2,BROTLI_PARAM_LGBLOCK:3,BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:4,BROTLI_PARAM_SIZE_HINT:5,BROTLI_PARAM_LARGE_WINDOW:6,BROTLI_PARAM_NPOSTFIX:7,BROTLI_PARAM_NDIRECT:8,BROTLI_DECODER_RESULT_ERROR:0,BROTLI_DECODER_RESULT_SUCCESS:1,BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:2,BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:0,BROTLI_DECODER_PARAM_LARGE_WINDOW:1,BROTLI_DECODER_NO_ERROR:0,BROTLI_DECODER_SUCCESS:1,BROTLI_DECODER_NEEDS_MORE_INPUT:2,BROTLI_DECODER_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:-1,BROTLI_DECODER_ERROR_FORMAT_RESERVED:-2,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:-3,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:-4,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:-5,BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:-6,BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:-7,BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:-8,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:-9,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:-10,BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:-11,BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:-12,BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:-13,BROTLI_DECODER_ERROR_FORMAT_PADDING_1:-14,BROTLI_DECODER_ERROR_FORMAT_PADDING_2:-15,BROTLI_DECODER_ERROR_FORMAT_DISTANCE:-16,BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:-19,BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:-20,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:-21,BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:-22,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:-25,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:-26,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:-27,BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:-30,BROTLI_DECODER_ERROR_UNREACHABLE:-31},Zhe))});var Q0=v(ti=>{"use strict";var z0=require("assert"),Ko=require("buffer").Buffer,a6=require("zlib"),aa=ti.constants=s6(),Qhe=su(),l6=Ko.concat,la=Symbol("_superWrite"),bp=class extends Error{constructor(e){super("zlib: "+e.message);this.code=e.code,this.errno=e.errno,this.code||(this.code="ZLIB_ERROR"),this.message="zlib: "+e.message,Error.captureStackTrace(this,this.constructor)}get name(){return"ZlibError"}},eme=Symbol("opts"),wp=Symbol("flushFlag"),u6=Symbol("finishFlushFlag"),G0=Symbol("fullFlushFlag"),Ze=Symbol("handle"),Eg=Symbol("onError"),au=Symbol("sawError"),V0=Symbol("level"),K0=Symbol("strategy"),J0=Symbol("ended"),ZAe=Symbol("_defaultFullFlush"),Y0=class extends Qhe{constructor(e,t){if(!e||typeof e!="object")throw new TypeError("invalid options for ZlibBase constructor");super(e);this[au]=!1,this[J0]=!1,this[eme]=e,this[wp]=e.flush,this[u6]=e.finishFlush;try{this[Ze]=new a6[t](e)}catch(i){throw new bp(i)}this[Eg]=i=>{this[au]||(this[au]=!0,this.close(),this.emit("error",i))},this[Ze].on("error",i=>this[Eg](new bp(i))),this.once("end",()=>this.close)}close(){this[Ze]&&(this[Ze].close(),this[Ze]=null,this.emit("close"))}reset(){if(!this[au])return z0(this[Ze],"zlib binding closed"),this[Ze].reset()}flush(e){this.ended||(typeof e!="number"&&(e=this[G0]),this.write(Object.assign(Ko.alloc(0),{[wp]:e})))}end(e,t,i){return e&&this.write(e,t),this.flush(this[u6]),this[J0]=!0,super.end(null,null,i)}get ended(){return this[J0]}write(e,t,i){if(typeof t=="function"&&(i=t,t="utf8"),typeof e=="string"&&(e=Ko.from(e,t)),this[au])return;z0(this[Ze],"zlib binding closed");let n=this[Ze]._handle,o=n.close;n.close=()=>{};let s=this[Ze].close;this[Ze].close=()=>{},Ko.concat=u=>u;let a;try{let u=typeof e[wp]=="number"?e[wp]:this[wp];a=this[Ze]._processChunk(e,u),Ko.concat=l6}catch(u){Ko.concat=l6,this[Eg](new bp(u))}finally{this[Ze]&&(this[Ze]._handle=n,n.close=o,this[Ze].close=s,this[Ze].removeAllListeners("error"))}this[Ze]&&this[Ze].on("error",u=>this[Eg](new bp(u)));let l;if(a)if(Array.isArray(a)&&a.length>0){l=this[la](Ko.from(a[0]));for(let u=1;u{this.flush(n),o()};try{this[Ze].params(e,t)}finally{this[Ze].flush=i}this[Ze]&&(this[V0]=e,this[K0]=t)}}}},c6=class extends Jo{constructor(e){super(e,"Deflate")}},f6=class extends Jo{constructor(e){super(e,"Inflate")}},X0=Symbol("_portable"),p6=class extends Jo{constructor(e){super(e,"Gzip");this[X0]=e&&!!e.portable}[la](e){return this[X0]?(this[X0]=!1,e[9]=255,super[la](e)):super[la](e)}},d6=class extends Jo{constructor(e){super(e,"Gunzip")}},h6=class extends Jo{constructor(e){super(e,"DeflateRaw")}},m6=class extends Jo{constructor(e){super(e,"InflateRaw")}},g6=class extends Jo{constructor(e){super(e,"Unzip")}},Z0=class extends Y0{constructor(e,t){e=e||{},e.flush=e.flush||aa.BROTLI_OPERATION_PROCESS,e.finishFlush=e.finishFlush||aa.BROTLI_OPERATION_FINISH,super(e,t),this[G0]=aa.BROTLI_OPERATION_FLUSH}},v6=class extends Z0{constructor(e){super(e,"BrotliCompress")}},y6=class extends Z0{constructor(e){super(e,"BrotliDecompress")}};ti.Deflate=c6;ti.Inflate=f6;ti.Gzip=p6;ti.Gunzip=d6;ti.DeflateRaw=h6;ti.InflateRaw=m6;ti.Unzip=g6;typeof a6.BrotliCompress=="function"?(ti.BrotliCompress=v6,ti.BrotliDecompress=y6):ti.BrotliCompress=ti.BrotliDecompress=class{constructor(){throw new Error("Brotli is not supported in this version of Node.js")}}});var xp=v(Cg=>{"use strict";Cg.name=new Map([["0","File"],["","OldFile"],["1","Link"],["2","SymbolicLink"],["3","CharacterDevice"],["4","BlockDevice"],["5","Directory"],["6","FIFO"],["7","ContiguousFile"],["g","GlobalExtendedHeader"],["x","ExtendedHeader"],["A","SolarisACL"],["D","GNUDumpDir"],["I","Inode"],["K","NextFileHasLongLinkpath"],["L","NextFileHasLongPath"],["M","ContinuationFile"],["N","OldGnuLongPath"],["S","SparseFile"],["V","TapeVolumeHeader"],["X","OldExtendedHeader"]]);Cg.code=new Map(Array.from(Cg.name).map(r=>[r[1],r[0]]))});var Dp=v((iOe,b6)=>{"use strict";var tOe=xp(),tme=su(),eS=Symbol("slurp");b6.exports=class extends tme{constructor(e,t,i){super();switch(this.pause(),this.extended=t,this.globalExtended=i,this.header=e,this.startBlockSize=512*Math.ceil(e.size/512),this.blockRemain=this.startBlockSize,this.remain=e.size,this.type=e.type,this.meta=!1,this.ignore=!1,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=!0;break;default:this.ignore=!0}this.path=e.path,this.mode=e.mode,this.mode&&(this.mode=this.mode&4095),this.uid=e.uid,this.gid=e.gid,this.uname=e.uname,this.gname=e.gname,this.size=e.size,this.mtime=e.mtime,this.atime=e.atime,this.ctime=e.ctime,this.linkpath=e.linkpath,this.uname=e.uname,this.gname=e.gname,t&&this[eS](t),i&&this[eS](i,!0)}write(e){let t=e.length;if(t>this.blockRemain)throw new Error("writing more to entry than is appropriate");let i=this.remain,n=this.blockRemain;return this.remain=Math.max(0,i-t),this.blockRemain=Math.max(0,n-t),this.ignore?!0:i>=t?super.write(e):super.write(e.slice(0,i))}[eS](e,t){for(let i in e)e[i]!==null&&e[i]!==void 0&&!(t&&i==="path")&&(this[i]=e[i])}}});var D6=v(tS=>{"use strict";var nOe=tS.encode=(r,e)=>{if(Number.isSafeInteger(r))r<0?ime(r,e):rme(r,e);else throw Error("cannot encode number outside of javascript safe integer range");return e},rme=(r,e)=>{e[0]=128;for(var t=e.length;t>1;t--)e[t-1]=r&255,r=Math.floor(r/256)},ime=(r,e)=>{e[0]=255;var t=!1;r=r*-1;for(var i=e.length;i>1;i--){var n=r&255;r=Math.floor(r/256),t?e[i-1]=w6(n):n===0?e[i-1]=0:(t=!0,e[i-1]=x6(n))}},oOe=tS.parse=r=>{var e=r[r.length-1],t=r[0],i;if(t===128)i=ome(r.slice(1,r.length));else if(t===255)i=nme(r);else throw Error("invalid base256 encoding");if(!Number.isSafeInteger(i))throw Error("parsed number outside of javascript safe integer range");return i},nme=r=>{for(var e=r.length,t=0,i=!1,n=e-1;n>-1;n--){var o=r[n],s;i?s=w6(o):o===0?s=o:(i=!0,s=x6(o)),s!==0&&(t-=s*Math.pow(256,e-n-1))}return t},ome=r=>{for(var e=r.length,t=0,i=e-1;i>-1;i--){var n=r[i];n!==0&&(t+=n*Math.pow(256,e-i-1))}return t},w6=r=>(255^r)&255,x6=r=>(255^r)+1&255});var uu=v((aOe,S6)=>{"use strict";var rS=xp(),lu=require("path").posix,E6=D6(),iS=Symbol("slurp"),ri=Symbol("type"),C6=class{constructor(e,t,i,n){this.cksumValid=!1,this.needPax=!1,this.nullBlock=!1,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[ri]="0",this.linkpath=null,this.uname=null,this.gname=null,this.devmaj=0,this.devmin=0,this.atime=null,this.ctime=null,Buffer.isBuffer(e)?this.decode(e,t||0,i,n):e&&this.set(e)}decode(e,t,i,n){if(t||(t=0),!e||!(e.length>=t+512))throw new Error("need 512 bytes for header");if(this.path=ua(e,t,100),this.mode=Yo(e,t+100,8),this.uid=Yo(e,t+108,8),this.gid=Yo(e,t+116,8),this.size=Yo(e,t+124,12),this.mtime=nS(e,t+136,12),this.cksum=Yo(e,t+148,12),this[iS](i),this[iS](n,!0),this[ri]=ua(e,t+156,1),this[ri]===""&&(this[ri]="0"),this[ri]==="0"&&this.path.substr(-1)==="/"&&(this[ri]="5"),this[ri]==="5"&&(this.size=0),this.linkpath=ua(e,t+157,100),e.slice(t+257,t+265).toString()==="ustar\x0000")if(this.uname=ua(e,t+265,32),this.gname=ua(e,t+297,32),this.devmaj=Yo(e,t+329,8),this.devmin=Yo(e,t+337,8),e[t+475]!==0){let s=ua(e,t+345,155);this.path=s+"/"+this.path}else{let s=ua(e,t+345,130);s&&(this.path=s+"/"+this.path),this.atime=nS(e,t+476,12),this.ctime=nS(e,t+488,12)}let o=8*32;for(let s=t;s=t+512))throw new Error("need 512 bytes for header");let i=this.ctime||this.atime?130:155,n=sme(this.path||"",i),o=n[0],s=n[1];this.needPax=n[2],this.needPax=ca(e,t,100,o)||this.needPax,this.needPax=Xo(e,t+100,8,this.mode)||this.needPax,this.needPax=Xo(e,t+108,8,this.uid)||this.needPax,this.needPax=Xo(e,t+116,8,this.gid)||this.needPax,this.needPax=Xo(e,t+124,12,this.size)||this.needPax,this.needPax=oS(e,t+136,12,this.mtime)||this.needPax,e[t+156]=this[ri].charCodeAt(0),this.needPax=ca(e,t+157,100,this.linkpath)||this.needPax,e.write("ustar\x0000",t+257,8),this.needPax=ca(e,t+265,32,this.uname)||this.needPax,this.needPax=ca(e,t+297,32,this.gname)||this.needPax,this.needPax=Xo(e,t+329,8,this.devmaj)||this.needPax,this.needPax=Xo(e,t+337,8,this.devmin)||this.needPax,this.needPax=ca(e,t+345,i,s)||this.needPax,e[t+475]!==0?this.needPax=ca(e,t+345,155,s)||this.needPax:(this.needPax=ca(e,t+345,130,s)||this.needPax,this.needPax=oS(e,t+476,12,this.atime)||this.needPax,this.needPax=oS(e,t+488,12,this.ctime)||this.needPax);let a=8*32;for(let l=t;l{let t=100,i=r,n="",o,s=lu.parse(r).root||".";if(Buffer.byteLength(i)t&&Buffer.byteLength(n)<=e?o=[i.substr(0,t-1),n,!0]:(i=lu.join(lu.basename(n),i),n=lu.dirname(n));while(n!==s&&!o);o||(o=[r.substr(0,t-1),"",!0])}return o},ua=(r,e,t)=>r.slice(e,e+t).toString("utf8").replace(/\0.*/,""),nS=(r,e,t)=>ame(Yo(r,e,t)),ame=r=>r===null?null:new Date(r*1e3),Yo=(r,e,t)=>r[e]&128?E6.parse(r.slice(e,e+t)):lme(r,e,t),ume=r=>isNaN(r)?null:r,lme=(r,e,t)=>ume(parseInt(r.slice(e,e+t).toString("utf8").replace(/\0.*$/,"").trim(),8)),cme={12:8589934591,8:2097151},Xo=(r,e,t,i)=>i===null?!1:i>cme[t]||i<0?(E6.encode(i,r.slice(e,e+t)),!0):(fme(r,e,t,i),!1),fme=(r,e,t,i)=>r.write(pme(i,t),e,t,"ascii"),pme=(r,e)=>dme(Math.floor(r).toString(8),e),dme=(r,e)=>(r.length===e-1?r:new Array(e-r.length-1).join("0")+r+" ")+"\0",oS=(r,e,t,i)=>i===null?!1:Xo(r,e,t,i.getTime()/1e3),hme=new Array(156).join("\0"),ca=(r,e,t,i)=>i===null?!1:(r.write(i+hme,e,t,"utf8"),i.length!==Buffer.byteLength(i)||i.length>t);S6.exports=C6});var Pg=v((lOe,_6)=>{"use strict";var mme=uu(),gme=require("path"),_g=class{constructor(e,t){this.atime=e.atime||null,this.charset=e.charset||null,this.comment=e.comment||null,this.ctime=e.ctime||null,this.gid=e.gid||null,this.gname=e.gname||null,this.linkpath=e.linkpath||null,this.mtime=e.mtime||null,this.path=e.path||null,this.size=e.size||null,this.uid=e.uid||null,this.uname=e.uname||null,this.dev=e.dev||null,this.ino=e.ino||null,this.nlink=e.nlink||null,this.global=t||!1}encode(){let e=this.encodeBody();if(e==="")return null;let t=Buffer.byteLength(e),i=512*Math.ceil(1+t/512),n=Buffer.allocUnsafe(i);for(let o=0;o<512;o++)n[o]=0;new mme({path:("PaxHeader/"+gme.basename(this.path)).slice(0,99),mode:this.mode||420,uid:this.uid||null,gid:this.gid||null,size:t,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(n),n.write(e,512,t,"utf8");for(let o=t+512;o=Math.pow(10,o)&&(o+=1),o+n+i}};_g.parse=(r,e,t)=>new _g(vme(yme(r),e),t);var vme=(r,e)=>e?Object.keys(r).reduce((t,i)=>(t[i]=r[i],t),e):r,yme=r=>r.replace(/\n$/,"").split(` -`).reduce(bme,Object.create(null)),bme=(r,e)=>{let t=parseInt(e,10);if(t!==Buffer.byteLength(e)+1)return r;e=e.substr((t+" ").length);let i=e.split("="),n=i.shift().replace(/^SCHILY\.(dev|ino|nlink)/,"$1");if(!n)return r;let o=i.join("=");return r[n]=/^([A-Z]+\.)?([mac]|birth|creation)time$/.test(n)?new Date(o*1e3):/^[0-9]+$/.test(o)?+o:o,r};_6.exports=_g});var Tg=v((uOe,P6)=>{"use strict";P6.exports=r=>class extends r{warn(e,t,i={}){this.file&&(i.file=this.file),this.cwd&&(i.cwd=this.cwd),i.code=t instanceof Error&&t.code||e,i.tarCode=e,!this.strict&&i.recoverable!==!1?(t instanceof Error&&(i=Object.assign(t,i),t=t.message),this.emit("warn",i.tarCode,t,i)):t instanceof Error?this.emit("error",Object.assign(t,i)):this.emit("error",Object.assign(new Error(`${e}: ${t}`),i))}}});var aS=v((cOe,T6)=>{"use strict";var Rg=["|","<",">","?",":"],sS=Rg.map(r=>String.fromCharCode(61440+r.charCodeAt(0))),wme=new Map(Rg.map((r,e)=>[r,sS[e]])),xme=new Map(sS.map((r,e)=>[r,Rg[e]]));T6.exports={encode:r=>Rg.reduce((e,t)=>e.split(t).join(wme.get(t)),r),decode:r=>sS.reduce((e,t)=>e.split(t).join(xme.get(t)),r)}});var k6=v((fOe,R6)=>{"use strict";R6.exports=(r,e,t)=>(r&=4095,t&&(r=(r|384)&~18),e&&(r&256&&(r|=64),r&32&&(r|=8),r&4&&(r|=1)),r)});var hS=v((gOe,I6)=>{"use strict";var F6=su(),A6=Pg(),O6=uu(),pOe=Dp(),bn=require("fs"),cu=require("path"),dOe=xp(),Dme=16*1024*1024,L6=Symbol("process"),M6=Symbol("file"),N6=Symbol("directory"),lS=Symbol("symlink"),q6=Symbol("hardlink"),Sp=Symbol("header"),kg=Symbol("read"),uS=Symbol("lstat"),Ig=Symbol("onlstat"),cS=Symbol("onread"),fS=Symbol("onreadlink"),pS=Symbol("openfile"),dS=Symbol("onopenfile"),fa=Symbol("close"),Fg=Symbol("mode"),$6=Tg(),Sme=aS(),B6=k6(),Ag=$6(class extends F6{constructor(e,t){if(t=t||{},super(t),typeof e!="string")throw new TypeError("path is required");this.path=e,this.portable=!!t.portable,this.myuid=process.getuid&&process.getuid(),this.myuser=process.env.USER||"",this.maxReadSize=t.maxReadSize||Dme,this.linkCache=t.linkCache||new Map,this.statCache=t.statCache||new Map,this.preservePaths=!!t.preservePaths,this.cwd=t.cwd||process.cwd(),this.strict=!!t.strict,this.noPax=!!t.noPax,this.noMtime=!!t.noMtime,this.mtime=t.mtime||null,typeof t.onwarn=="function"&&this.on("warn",t.onwarn);let i=!1;if(!this.preservePaths&&cu.win32.isAbsolute(e)){let n=cu.win32.parse(e);this.path=e.substr(n.root.length),i=n.root}this.win32=!!t.win32||process.platform==="win32",this.win32&&(this.path=Sme.decode(this.path.replace(/\\/g,"/")),e=e.replace(/\\/g,"/")),this.absolute=t.absolute||cu.resolve(this.cwd,e),this.path===""&&(this.path="./"),i&&this.warn("TAR_ENTRY_INFO",`stripping ${i} from absolute path`,{entry:this,path:i+this.path}),this.statCache.has(this.absolute)?this[Ig](this.statCache.get(this.absolute)):this[uS]()}[uS](){bn.lstat(this.absolute,(e,t)=>{if(e)return this.emit("error",e);this[Ig](t)})}[Ig](e){this.statCache.set(this.absolute,e),this.stat=e,e.isFile()||(e.size=0),this.type=Eme(e),this.emit("stat",e),this[L6]()}[L6](){switch(this.type){case"File":return this[M6]();case"Directory":return this[N6]();case"SymbolicLink":return this[lS]();default:return this.end()}}[Fg](e){return B6(e,this.type==="Directory",this.portable)}[Sp](){this.type==="Directory"&&this.portable&&(this.noMtime=!0),this.header=new O6({path:this.path,linkpath:this.linkpath,mode:this[Fg](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}),this.header.encode()&&!this.noPax&&this.write(new A6({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)}[N6](){this.path.substr(-1)!=="/"&&(this.path+="/"),this.stat.size=0,this[Sp](),this.end()}[lS](){bn.readlink(this.absolute,(e,t)=>{if(e)return this.emit("error",e);this[fS](t)})}[fS](e){this.linkpath=e.replace(/\\/g,"/"),this[Sp](),this.end()}[q6](e){this.type="Link",this.linkpath=cu.relative(this.cwd,e).replace(/\\/g,"/"),this.stat.size=0,this[Sp](),this.end()}[M6](){if(this.stat.nlink>1){let e=this.stat.dev+":"+this.stat.ino;if(this.linkCache.has(e)){let t=this.linkCache.get(e);if(t.indexOf(this.cwd)===0)return this[q6](t)}this.linkCache.set(e,this.absolute)}if(this[Sp](),this.stat.size===0)return this.end();this[pS]()}[pS](){bn.open(this.absolute,"r",(e,t)=>{if(e)return this.emit("error",e);this[dS](t)})}[dS](e){let t=512*Math.ceil(this.stat.size/512),i=Math.min(t,this.maxReadSize),n=Buffer.allocUnsafe(i);this[kg](e,n,0,n.length,0,this.stat.size,t)}[kg](e,t,i,n,o,s,a){bn.read(e,t,i,n,o,(l,u)=>{if(l)return this[fa](e,()=>this.emit("error",l));this[cS](e,t,i,n,o,s,a,u)})}[fa](e,t){bn.close(e,t)}[cS](e,t,i,n,o,s,a,l){if(l<=0&&s>0){let c=new Error("encountered unexpected EOF");return c.path=this.absolute,c.syscall="read",c.code="EOF",this[fa](e,()=>this.emit("error",c))}if(l>s){let c=new Error("did not encounter expected EOF");return c.path=this.absolute,c.syscall="read",c.code="EOF",this[fa](e,()=>this.emit("error",c))}if(l===s)for(let c=l;cc?this.emit("error",c):this.end());i>=n&&(t=Buffer.allocUnsafe(n),i=0),n=t.length-i,this[kg](e,t,i,n,o,s,a)}}),j6=class extends Ag{constructor(e,t){super(e,t)}[uS](){this[Ig](bn.lstatSync(this.absolute))}[lS](){this[fS](bn.readlinkSync(this.absolute))}[pS](){this[dS](bn.openSync(this.absolute,"r"))}[kg](e,t,i,n,o,s,a){let l=!0;try{let u=bn.readSync(e,t,i,n,o);this[cS](e,t,i,n,o,s,a,u),l=!1}finally{if(l)try{this[fa](e,()=>{})}catch(u){}}}[fa](e,t){bn.closeSync(e),t()}},Cme=$6(class extends F6{constructor(e,t){t=t||{},super(t),this.preservePaths=!!t.preservePaths,this.portable=!!t.portable,this.strict=!!t.strict,this.noPax=!!t.noPax,this.noMtime=!!t.noMtime,this.readEntry=e,this.type=e.type,this.type==="Directory"&&this.portable&&(this.noMtime=!0),this.path=e.path,this.mode=this[Fg](e.mode),this.uid=this.portable?null:e.uid,this.gid=this.portable?null:e.gid,this.uname=this.portable?null:e.uname,this.gname=this.portable?null:e.gname,this.size=e.size,this.mtime=this.noMtime?null:t.mtime||e.mtime,this.atime=this.portable?null:e.atime,this.ctime=this.portable?null:e.ctime,this.linkpath=e.linkpath,typeof t.onwarn=="function"&&this.on("warn",t.onwarn);let i=!1;if(cu.isAbsolute(this.path)&&!this.preservePaths){let n=cu.parse(this.path);i=n.root,this.path=this.path.substr(n.root.length)}this.remain=e.size,this.blockRemain=e.startBlockSize,this.header=new O6({path:this.path,linkpath:this.linkpath,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}),i&&this.warn("TAR_ENTRY_INFO",`stripping ${i} from absolute path`,{entry:this,path:i+this.path}),this.header.encode()&&!this.noPax&&super.write(new A6({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),e.pipe(this)}[Fg](e){return B6(e,this.type==="Directory",this.portable)}write(e){let t=e.length;if(t>this.blockRemain)throw new Error("writing more to entry than is appropriate");return this.blockRemain-=t,super.write(e)}end(){return this.blockRemain&&this.write(Buffer.alloc(this.blockRemain)),super.end()}});Ag.Sync=j6;Ag.Tar=Cme;var Eme=r=>r.isFile()?"File":r.isDirectory()?"Directory":r.isSymbolicLink()?"SymbolicLink":"Unsupported";I6.exports=Ag});var jg=v((yOe,U6)=>{"use strict";var mS=class{constructor(e,t){this.path=e||"./",this.absolute=t,this.entry=null,this.stat=null,this.readdir=null,this.pending=!1,this.ignore=!1,this.piped=!1}},_me=su(),Pme=Q0(),Tme=Dp(),gS=hS(),Rme=gS.Sync,kme=gS.Tar,Ime=wg(),W6=Buffer.alloc(1024),Og=Symbol("onStat"),Lg=Symbol("ended"),wn=Symbol("queue"),fu=Symbol("current"),pa=Symbol("process"),Mg=Symbol("processing"),H6=Symbol("processJob"),xn=Symbol("jobs"),vS=Symbol("jobDone"),Ng=Symbol("addFSEntry"),z6=Symbol("addTarEntry"),yS=Symbol("stat"),bS=Symbol("readdir"),qg=Symbol("onreaddir"),$g=Symbol("pipe"),G6=Symbol("entry"),wS=Symbol("entryOpt"),xS=Symbol("writeEntryClass"),V6=Symbol("write"),DS=Symbol("ondrain"),Bg=require("fs"),K6=require("path"),Fme=Tg(),SS=Fme(class extends _me{constructor(e){super(e);e=e||Object.create(null),this.opt=e,this.file=e.file||"",this.cwd=e.cwd||process.cwd(),this.maxReadSize=e.maxReadSize,this.preservePaths=!!e.preservePaths,this.strict=!!e.strict,this.noPax=!!e.noPax,this.prefix=(e.prefix||"").replace(/(\\|\/)+$/,""),this.linkCache=e.linkCache||new Map,this.statCache=e.statCache||new Map,this.readdirCache=e.readdirCache||new Map,this[xS]=gS,typeof e.onwarn=="function"&&this.on("warn",e.onwarn),this.portable=!!e.portable,this.zip=null,e.gzip?(typeof e.gzip!="object"&&(e.gzip={}),this.portable&&(e.gzip.portable=!0),this.zip=new Pme.Gzip(e.gzip),this.zip.on("data",t=>super.write(t)),this.zip.on("end",t=>super.end()),this.zip.on("drain",t=>this[DS]()),this.on("resume",t=>this.zip.resume())):this.on("drain",this[DS]),this.noDirRecurse=!!e.noDirRecurse,this.follow=!!e.follow,this.noMtime=!!e.noMtime,this.mtime=e.mtime||null,this.filter=typeof e.filter=="function"?e.filter:t=>!0,this[wn]=new Ime,this[xn]=0,this.jobs=+e.jobs||4,this[Mg]=!1,this[Lg]=!1}[V6](e){return super.write(e)}add(e){return this.write(e),this}end(e){return e&&this.write(e),this[Lg]=!0,this[pa](),this}write(e){if(this[Lg])throw new Error("write after end");return e instanceof Tme?this[z6](e):this[Ng](e),this.flowing}[z6](e){let t=K6.resolve(this.cwd,e.path);if(this.prefix&&(e.path=this.prefix+"/"+e.path.replace(/^\.(\/+|$)/,"")),!this.filter(e.path,e))e.resume();else{let i=new mS(e.path,t,!1);i.entry=new kme(e,this[wS](i)),i.entry.on("end",n=>this[vS](i)),this[xn]+=1,this[wn].push(i)}this[pa]()}[Ng](e){let t=K6.resolve(this.cwd,e);this.prefix&&(e=this.prefix+"/"+e.replace(/^\.(\/+|$)/,"")),this[wn].push(new mS(e,t)),this[pa]()}[yS](e){e.pending=!0,this[xn]+=1;let t=this.follow?"stat":"lstat";Bg[t](e.absolute,(i,n)=>{e.pending=!1,this[xn]-=1,i?this.emit("error",i):this[Og](e,n)})}[Og](e,t){this.statCache.set(e.absolute,t),e.stat=t,this.filter(e.path,t)||(e.ignore=!0),this[pa]()}[bS](e){e.pending=!0,this[xn]+=1,Bg.readdir(e.absolute,(t,i)=>{if(e.pending=!1,this[xn]-=1,t)return this.emit("error",t);this[qg](e,i)})}[qg](e,t){this.readdirCache.set(e.absolute,t),e.readdir=t,this[pa]()}[pa](){if(!this[Mg]){this[Mg]=!0;for(let e=this[wn].head;e!==null&&this[xn]this.warn(t,i,n),noPax:this.noPax,cwd:this.cwd,absolute:e.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}}[G6](e){this[xn]+=1;try{return new this[xS](e.path,this[wS](e)).on("end",()=>this[vS](e)).on("error",t=>this.emit("error",t))}catch(t){this.emit("error",t)}}[DS](){this[fu]&&this[fu].entry&&this[fu].entry.resume()}[$g](e){e.piped=!0,e.readdir&&e.readdir.forEach(n=>{let o=this.prefix?e.path.slice(this.prefix.length+1)||"./":e.path,s=o==="./"?"":o.replace(/\/*$/,"/");this[Ng](s+n)});let t=e.entry,i=this.zip;i?t.on("data",n=>{i.write(n)||t.pause()}):t.on("data",n=>{super.write(n)||t.pause()})}pause(){return this.zip&&this.zip.pause(),super.pause()}}),J6=class extends SS{constructor(e){super(e);this[xS]=Rme}pause(){}resume(){}[yS](e){let t=this.follow?"statSync":"lstatSync";this[Og](e,Bg[t](e.absolute))}[bS](e,t){this[qg](e,Bg.readdirSync(e.absolute))}[$g](e){let t=e.entry,i=this.zip;e.readdir&&e.readdir.forEach(n=>{let o=this.prefix?e.path.slice(this.prefix.length+1)||"./":e.path,s=o==="./"?"":o.replace(/\/*$/,"/");this[Ng](s+n)}),i?t.on("data",n=>{i.write(n)}):t.on("data",n=>{super[V6](n)})}};SS.Sync=J6;U6.exports=SS});var bu=v(Ep=>{"use strict";var Ame=su(),Ome=require("events").EventEmitter,Nr=require("fs"),ES=Nr.writev;if(!ES){let r=process.binding("fs"),e=r.FSReqWrap||r.FSReqCallback;ES=(t,i,n,o)=>{let s=(l,u)=>o(l,u,i),a=new e;a.oncomplete=s,r.writeBuffers(t,i,n,a)}}var pu=Symbol("_autoClose"),rn=Symbol("_close"),Cp=Symbol("_ended"),ze=Symbol("_fd"),Y6=Symbol("_finished"),Zo=Symbol("_flags"),CS=Symbol("_flush"),_S=Symbol("_handleChunk"),PS=Symbol("_makeBuf"),Ug=Symbol("_mode"),Wg=Symbol("_needDrain"),du=Symbol("_onerror"),hu=Symbol("_onopen"),TS=Symbol("_onread"),mu=Symbol("_onwrite"),Qo=Symbol("_open"),Qn=Symbol("_path"),da=Symbol("_pos"),Dn=Symbol("_queue"),gu=Symbol("_read"),X6=Symbol("_readSize"),es=Symbol("_reading"),Hg=Symbol("_remain"),Z6=Symbol("_size"),zg=Symbol("_write"),vu=Symbol("_writing"),Gg=Symbol("_defaultFlag"),yu=Symbol("_errored"),RS=class extends Ame{constructor(e,t){if(t=t||{},super(t),this.readable=!0,this.writable=!1,typeof e!="string")throw new TypeError("path must be a string");this[yu]=!1,this[ze]=typeof t.fd=="number"?t.fd:null,this[Qn]=e,this[X6]=t.readSize||16*1024*1024,this[es]=!1,this[Z6]=typeof t.size=="number"?t.size:Infinity,this[Hg]=this[Z6],this[pu]=typeof t.autoClose=="boolean"?t.autoClose:!0,typeof this[ze]=="number"?this[gu]():this[Qo]()}get fd(){return this[ze]}get path(){return this[Qn]}write(){throw new TypeError("this is a readable stream")}end(){throw new TypeError("this is a readable stream")}[Qo](){Nr.open(this[Qn],"r",(e,t)=>this[hu](e,t))}[hu](e,t){e?this[du](e):(this[ze]=t,this.emit("open",t),this[gu]())}[PS](){return Buffer.allocUnsafe(Math.min(this[X6],this[Hg]))}[gu](){if(!this[es]){this[es]=!0;let e=this[PS]();if(e.length===0)return process.nextTick(()=>this[TS](null,0,e));Nr.read(this[ze],e,0,e.length,null,(t,i,n)=>this[TS](t,i,n))}}[TS](e,t,i){this[es]=!1,e?this[du](e):this[_S](t,i)&&this[gu]()}[rn](){if(this[pu]&&typeof this[ze]=="number"){let e=this[ze];this[ze]=null,Nr.close(e,t=>t?this.emit("error",t):this.emit("close"))}}[du](e){this[es]=!0,this[rn](),this.emit("error",e)}[_S](e,t){let i=!1;return this[Hg]-=e,e>0&&(i=super.write(ethis[hu](e,t))}[hu](e,t){this[Gg]&&this[Zo]==="r+"&&e&&e.code==="ENOENT"?(this[Zo]="w",this[Qo]()):e?this[du](e):(this[ze]=t,this.emit("open",t),this[CS]())}end(e,t){return e&&this.write(e,t),this[Cp]=!0,!this[vu]&&!this[Dn].length&&typeof this[ze]=="number"&&this[mu](null,0),this}write(e,t){return typeof e=="string"&&(e=Buffer.from(e,t)),this[Cp]?(this.emit("error",new Error("write() after end()")),!1):this[ze]===null||this[vu]||this[Dn].length?(this[Dn].push(e),this[Wg]=!0,!1):(this[vu]=!0,this[zg](e),!0)}[zg](e){Nr.write(this[ze],e,0,e.length,this[da],(t,i)=>this[mu](t,i))}[mu](e,t){e?this[du](e):(this[da]!==null&&(this[da]+=t),this[Dn].length?this[CS]():(this[vu]=!1,this[Cp]&&!this[Y6]?(this[Y6]=!0,this[rn](),this.emit("finish")):this[Wg]&&(this[Wg]=!1,this.emit("drain"))))}[CS](){if(this[Dn].length===0)this[Cp]&&this[mu](null,0);else if(this[Dn].length===1)this[zg](this[Dn].pop());else{let e=this[Dn];this[Dn]=[],ES(this[ze],e,this[da],(t,i)=>this[mu](t,i))}}[rn](){if(this[pu]&&typeof this[ze]=="number"){let e=this[ze];this[ze]=null,Nr.close(e,t=>t?this.emit("error",t):this.emit("close"))}}},e8=class extends kS{[Qo](){let e;if(this[Gg]&&this[Zo]==="r+")try{e=Nr.openSync(this[Qn],this[Zo],this[Ug])}catch(t){if(t.code==="ENOENT")return this[Zo]="w",this[Qo]();throw t}else e=Nr.openSync(this[Qn],this[Zo],this[Ug]);this[hu](null,e)}[rn](){if(this[pu]&&typeof this[ze]=="number"){let e=this[ze];this[ze]=null,Nr.closeSync(e),this.emit("close")}}[zg](e){let t=!0;try{this[mu](null,Nr.writeSync(this[ze],e,0,e.length,this[da])),t=!1}finally{if(t)try{this[rn]()}catch(i){}}}};Ep.ReadStream=RS;Ep.ReadStreamSync=Q6;Ep.WriteStream=kS;Ep.WriteStreamSync=e8});var Tp=v((DOe,t8)=>{"use strict";var Lme=Tg(),wOe=require("path"),Mme=uu(),Nme=require("events"),qme=wg(),$me=1024*1024,Bme=Dp(),r8=Pg(),jme=Q0(),IS=Buffer.from([31,139]),Ri=Symbol("state"),ha=Symbol("writeEntry"),eo=Symbol("readEntry"),FS=Symbol("nextEntry"),i8=Symbol("processEntry"),ki=Symbol("extendedHeader"),_p=Symbol("globalExtendedHeader"),ts=Symbol("meta"),n8=Symbol("emitMeta"),tt=Symbol("buffer"),to=Symbol("queue"),ma=Symbol("ended"),o8=Symbol("emittedEnd"),ga=Symbol("emit"),qr=Symbol("unzip"),Vg=Symbol("consumeChunk"),Kg=Symbol("consumeChunkSub"),AS=Symbol("consumeBody"),s8=Symbol("consumeMeta"),a8=Symbol("consumeHeader"),Jg=Symbol("consuming"),OS=Symbol("bufferConcat"),LS=Symbol("maybeEnd"),Pp=Symbol("writing"),rs=Symbol("aborted"),Yg=Symbol("onDone"),va=Symbol("sawValidEntry"),Xg=Symbol("sawNullBlock"),Zg=Symbol("sawEOF"),Ume=r=>!0;t8.exports=Lme(class extends Nme{constructor(e){e=e||{},super(e),this.file=e.file||"",this[va]=null,this.on(Yg,t=>{(this[Ri]==="begin"||this[va]===!1)&&this.warn("TAR_BAD_ARCHIVE","Unrecognized archive format")}),e.ondone?this.on(Yg,e.ondone):this.on(Yg,t=>{this.emit("prefinish"),this.emit("finish"),this.emit("end"),this.emit("close")}),this.strict=!!e.strict,this.maxMetaEntrySize=e.maxMetaEntrySize||$me,this.filter=typeof e.filter=="function"?e.filter:Ume,this.writable=!0,this.readable=!1,this[to]=new qme,this[tt]=null,this[eo]=null,this[ha]=null,this[Ri]="begin",this[ts]="",this[ki]=null,this[_p]=null,this[ma]=!1,this[qr]=null,this[rs]=!1,this[Xg]=!1,this[Zg]=!1,typeof e.onwarn=="function"&&this.on("warn",e.onwarn),typeof e.onentry=="function"&&this.on("entry",e.onentry)}[a8](e,t){this[va]===null&&(this[va]=!1);let i;try{i=new Mme(e,t,this[ki],this[_p])}catch(n){return this.warn("TAR_ENTRY_INVALID",n)}if(i.nullBlock)this[Xg]?(this[Zg]=!0,this[Ri]==="begin"&&(this[Ri]="header"),this[ga]("eof")):(this[Xg]=!0,this[ga]("nullBlock"));else if(this[Xg]=!1,!i.cksumValid)this.warn("TAR_ENTRY_INVALID","checksum failure",{header:i});else if(!i.path)this.warn("TAR_ENTRY_INVALID","path is required",{header:i});else{let n=i.type;if(/^(Symbolic)?Link$/.test(n)&&!i.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath required",{header:i});else if(!/^(Symbolic)?Link$/.test(n)&&i.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath forbidden",{header:i});else{let o=this[ha]=new Bme(i,this[ki],this[_p]);if(!this[va])if(o.remain){let s=()=>{o.invalid||(this[va]=!0)};o.on("end",s)}else this[va]=!0;o.meta?o.size>this.maxMetaEntrySize?(o.ignore=!0,this[ga]("ignoredEntry",o),this[Ri]="ignore",o.resume()):o.size>0&&(this[ts]="",o.on("data",s=>this[ts]+=s),this[Ri]="meta"):(this[ki]=null,o.ignore=o.ignore||!this.filter(o.path,o),o.ignore?(this[ga]("ignoredEntry",o),this[Ri]=o.remain?"ignore":"header",o.resume()):(o.remain?this[Ri]="body":(this[Ri]="header",o.end()),this[eo]?this[to].push(o):(this[to].push(o),this[FS]())))}}}[i8](e){let t=!0;return e?Array.isArray(e)?this.emit.apply(this,e):(this[eo]=e,this.emit("entry",e),e.emittedEnd||(e.on("end",i=>this[FS]()),t=!1)):(this[eo]=null,t=!1),t}[FS](){do;while(this[i8](this[to].shift()));if(!this[to].length){let e=this[eo];!e||e.flowing||e.size===e.remain?this[Pp]||this.emit("drain"):e.once("drain",i=>this.emit("drain"))}}[AS](e,t){let i=this[ha],n=i.blockRemain,o=n>=e.length&&t===0?e:e.slice(t,t+n);return i.write(o),i.blockRemain||(this[Ri]="header",this[ha]=null,i.end()),o.length}[s8](e,t){let i=this[ha],n=this[AS](e,t);return this[ha]||this[n8](i),n}[ga](e,t,i){!this[to].length&&!this[eo]?this.emit(e,t,i):this[to].push([e,t,i])}[n8](e){switch(this[ga]("meta",this[ts]),e.type){case"ExtendedHeader":case"OldExtendedHeader":this[ki]=r8.parse(this[ts],this[ki],!1);break;case"GlobalExtendedHeader":this[_p]=r8.parse(this[ts],this[_p],!0);break;case"NextFileHasLongPath":case"OldGnuLongPath":this[ki]=this[ki]||Object.create(null),this[ki].path=this[ts].replace(/\0.*/,"");break;case"NextFileHasLongLinkpath":this[ki]=this[ki]||Object.create(null),this[ki].linkpath=this[ts].replace(/\0.*/,"");break;default:throw new Error("unknown meta: "+e.type)}}abort(e){this[rs]=!0,this.emit("abort",e),this.warn("TAR_ABORT",e,{recoverable:!1})}write(e){if(this[rs])return;if(this[qr]===null&&e){if(this[tt]&&(e=Buffer.concat([this[tt],e]),this[tt]=null),e.lengththis[Vg](o)),this[qr].on("error",o=>this.abort(o)),this[qr].on("end",o=>{this[ma]=!0,this[Vg]()}),this[Pp]=!0;let n=this[qr][i?"end":"write"](e);return this[Pp]=!1,n}}this[Pp]=!0,this[qr]?this[qr].write(e):this[Vg](e),this[Pp]=!1;let t=this[to].length?!1:this[eo]?this[eo].flowing:!0;return!t&&!this[to].length&&this[eo].once("drain",i=>this.emit("drain")),t}[OS](e){e&&!this[rs]&&(this[tt]=this[tt]?Buffer.concat([this[tt],e]):e)}[LS](){if(this[ma]&&!this[o8]&&!this[rs]&&!this[Jg]){this[o8]=!0;let e=this[ha];if(e&&e.blockRemain){let t=this[tt]?this[tt].length:0;this.warn("TAR_BAD_ARCHIVE",`Truncated input (needed ${e.blockRemain} more bytes, only ${t} available)`,{entry:e}),this[tt]&&e.write(this[tt]),e.end()}this[ga](Yg)}}[Vg](e){if(this[Jg])this[OS](e);else if(!e&&!this[tt])this[LS]();else{if(this[Jg]=!0,this[tt]){this[OS](e);let t=this[tt];this[tt]=null,this[Kg](t)}else this[Kg](e);for(;this[tt]&&this[tt].length>=512&&!this[rs]&&!this[Zg];){let t=this[tt];this[tt]=null,this[Kg](t)}this[Jg]=!1}(!this[tt]||this[ma])&&this[LS]()}[Kg](e){let t=0,i=e.length;for(;t+512<=i&&!this[rs]&&!this[Zg];)switch(this[Ri]){case"begin":case"header":this[a8](e,t),t+=512;break;case"ignore":case"body":t+=this[AS](e,t);break;case"meta":t+=this[s8](e,t);break;default:throw new Error("invalid state: "+this[Ri])}t{"use strict";var Wme=ou(),u8=Tp(),wu=require("fs"),Hme=bu(),c8=require("path"),SOe=l8.exports=(r,e,t)=>{typeof r=="function"?(t=r,e=null,r={}):Array.isArray(r)&&(e=r,r={}),typeof e=="function"&&(t=e,e=null),e?e=Array.from(e):e=[];let i=Wme(r);if(i.sync&&typeof t=="function")throw new TypeError("callback not supported for sync tar functions");if(!i.file&&typeof t=="function")throw new TypeError("callback only supported with file option");return e.length&&Gme(i,e),i.noResume||zme(i),i.file&&i.sync?Vme(i):i.file?Kme(i,t):f8(i)},zme=r=>{let e=r.onentry;r.onentry=e?t=>{e(t),t.resume()}:t=>t.resume()},Gme=(r,e)=>{let t=new Map(e.map(o=>[o.replace(/\/+$/,""),!0])),i=r.filter,n=(o,s)=>{let a=s||c8.parse(o).root||".",l=o===a?!1:t.has(o)?t.get(o):n(c8.dirname(o),a);return t.set(o,l),l};r.filter=i?(o,s)=>i(o,s)&&n(o.replace(/\/+$/,"")):o=>n(o.replace(/\/+$/,""))},Vme=r=>{let e=f8(r),t=r.file,i=!0,n;try{let o=wu.statSync(t),s=r.maxReadSize||16*1024*1024;if(o.size{let t=new u8(r),i=r.maxReadSize||16*1024*1024,n=r.file,o=new Promise((s,a)=>{t.on("error",a),t.on("end",s),wu.stat(n,(l,u)=>{if(l)a(l);else{let c=new Hme.ReadStream(n,{readSize:i,size:u.size});c.on("error",a),c.pipe(t)}})});return e?o.then(e,e):o},f8=r=>new u8(r)});var v8=v((POe,p8)=>{"use strict";var Jme=ou(),ev=jg(),COe=require("fs"),d8=bu(),h8=Qg(),m8=require("path"),_Oe=p8.exports=(r,e,t)=>{if(typeof e=="function"&&(t=e),Array.isArray(r)&&(e=r,r={}),!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");e=Array.from(e);let i=Jme(r);if(i.sync&&typeof t=="function")throw new TypeError("callback not supported for sync tar functions");if(!i.file&&typeof t=="function")throw new TypeError("callback only supported with file option");return i.file&&i.sync?Yme(i,e):i.file?Xme(i,e,t):i.sync?Zme(i,e):Qme(i,e)},Yme=(r,e)=>{let t=new ev.Sync(r),i=new d8.WriteStreamSync(r.file,{mode:r.mode||438});t.pipe(i),g8(t,e)},Xme=(r,e,t)=>{let i=new ev(r),n=new d8.WriteStream(r.file,{mode:r.mode||438});i.pipe(n);let o=new Promise((s,a)=>{n.on("error",a),n.on("close",s),i.on("error",a)});return MS(i,e),t?o.then(t,t):o},g8=(r,e)=>{e.forEach(t=>{t.charAt(0)==="@"?h8({file:m8.resolve(r.cwd,t.substr(1)),sync:!0,noResume:!0,onentry:i=>r.add(i)}):r.add(t)}),r.end()},MS=(r,e)=>{for(;e.length;){let t=e.shift();if(t.charAt(0)==="@")return h8({file:m8.resolve(r.cwd,t.substr(1)),noResume:!0,onentry:i=>r.add(i)}).then(i=>MS(r,e));r.add(t)}r.end()},Zme=(r,e)=>{let t=new ev.Sync(r);return g8(t,e),t},Qme=(r,e)=>{let t=new ev(r);return MS(t,e),t}});var NS=v((kOe,y8)=>{"use strict";var ege=ou(),b8=jg(),TOe=Tp(),Ii=require("fs"),w8=bu(),x8=Qg(),D8=require("path"),S8=uu(),ROe=y8.exports=(r,e,t)=>{let i=ege(r);if(!i.file)throw new TypeError("file is required");if(i.gzip)throw new TypeError("cannot append to compressed archives");if(!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");return e=Array.from(e),i.sync?tge(i,e):rge(i,e,t)},tge=(r,e)=>{let t=new b8.Sync(r),i=!0,n,o;try{try{n=Ii.openSync(r.file,"r+")}catch(l){if(l.code==="ENOENT")n=Ii.openSync(r.file,"w+");else throw l}let s=Ii.fstatSync(n),a=Buffer.alloc(512);e:for(o=0;os.size)break;o+=u,r.mtimeCache&&r.mtimeCache.set(l.path,l.mtime)}i=!1,ige(r,t,o,n,e)}finally{if(i)try{Ii.closeSync(n)}catch(s){}}},ige=(r,e,t,i,n)=>{let o=new w8.WriteStreamSync(r.file,{fd:i,start:t});e.pipe(o),nge(e,n)},rge=(r,e,t)=>{e=Array.from(e);let i=new b8(r),n=(s,a,l)=>{let u=(h,m)=>{h?Ii.close(s,y=>l(h)):l(null,m)},c=0;if(a===0)return u(null,0);let f=0,p=Buffer.alloc(512),d=(h,m)=>{if(h)return u(h);if(f+=m,f<512&&m)return Ii.read(s,p,f,p.length-f,c+f,d);if(c===0&&p[0]===31&&p[1]===139)return u(new Error("cannot append to compressed archives"));if(f<512)return u(null,c);let y=new S8(p);if(!y.cksumValid)return u(null,c);let g=512*Math.ceil(y.size/512);if(c+g+512>a||(c+=g+512,c>=a))return u(null,c);r.mtimeCache&&r.mtimeCache.set(y.path,y.mtime),f=0,Ii.read(s,p,0,512,c,d)};Ii.read(s,p,0,512,c,d)},o=new Promise((s,a)=>{i.on("error",a);let l="r+",u=(c,f)=>{if(c&&c.code==="ENOENT"&&l==="r+")return l="w+",Ii.open(r.file,l,u);if(c)return a(c);Ii.fstat(f,(p,d)=>{if(p)return a(p);n(f,d.size,(h,m)=>{if(h)return a(h);let y=new w8.WriteStream(r.file,{fd:f,start:m});i.pipe(y),y.on("error",a),y.on("close",s),E8(i,e)})})};Ii.open(r.file,l,u)});return t?o.then(t,t):o},nge=(r,e)=>{e.forEach(t=>{t.charAt(0)==="@"?x8({file:D8.resolve(r.cwd,t.substr(1)),sync:!0,noResume:!0,onentry:i=>r.add(i)}):r.add(t)}),r.end()},E8=(r,e)=>{for(;e.length;){let t=e.shift();if(t.charAt(0)==="@")return x8({file:D8.resolve(r.cwd,t.substr(1)),noResume:!0,onentry:i=>r.add(i)}).then(i=>E8(r,e));r.add(t)}r.end()}});var _8=v((FOe,C8)=>{"use strict";var oge=ou(),sge=NS(),IOe=C8.exports=(r,e,t)=>{let i=oge(r);if(!i.file)throw new TypeError("file is required");if(i.gzip)throw new TypeError("cannot append to compressed archives");if(!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");return e=Array.from(e),age(i),sge(i,e,t)},age=r=>{let e=r.filter;r.mtimeCache||(r.mtimeCache=new Map),r.filter=e?(t,i)=>e(t,i)&&!(r.mtimeCache.get(t)>i.mtime):(t,i)=>!(r.mtimeCache.get(t)>i.mtime)}});var R8=v((AOe,P8)=>{var{promisify:T8}=require("util"),is=require("fs"),lge=r=>{if(!r)r={mode:511,fs:is};else if(typeof r=="object")r={mode:511,fs:is,...r};else if(typeof r=="number")r={mode:r,fs:is};else if(typeof r=="string")r={mode:parseInt(r,8),fs:is};else throw new TypeError("invalid options argument");return r.mkdir=r.mkdir||r.fs.mkdir||is.mkdir,r.mkdirAsync=T8(r.mkdir),r.stat=r.stat||r.fs.stat||is.stat,r.statAsync=T8(r.stat),r.statSync=r.statSync||r.fs.statSync||is.statSync,r.mkdirSync=r.mkdirSync||r.fs.mkdirSync||is.mkdirSync,r};P8.exports=lge});var I8=v((OOe,k8)=>{var uge=process.env.__TESTING_MKDIRP_PLATFORM__||process.platform,{resolve:cge,parse:fge}=require("path"),pge=r=>{if(/\0/.test(r))throw Object.assign(new TypeError("path must be a string without null bytes"),{path:r,code:"ERR_INVALID_ARG_VALUE"});if(r=cge(r),uge==="win32"){let e=/[*|"<>?:]/,{root:t}=fge(r);if(e.test(r.substr(t.length)))throw Object.assign(new Error("Illegal characters in path."),{path:r,code:"EINVAL"})}return r};k8.exports=pge});var M8=v((LOe,F8)=>{var{dirname:A8}=require("path"),O8=(r,e,t=void 0)=>t===e?Promise.resolve():r.statAsync(e).then(i=>i.isDirectory()?t:void 0,i=>i.code==="ENOENT"?O8(r,A8(e),e):void 0),L8=(r,e,t=void 0)=>{if(t!==e)try{return r.statSync(e).isDirectory()?t:void 0}catch(i){return i.code==="ENOENT"?L8(r,A8(e),e):void 0}};F8.exports={findMade:O8,findMadeSync:L8}});var BS=v((MOe,N8)=>{var{dirname:q8}=require("path"),qS=(r,e,t)=>{e.recursive=!1;let i=q8(r);return i===r?e.mkdirAsync(r,e).catch(n=>{if(n.code!=="EISDIR")throw n}):e.mkdirAsync(r,e).then(()=>t||r,n=>{if(n.code==="ENOENT")return qS(i,e).then(o=>qS(r,e,o));if(n.code!=="EEXIST"&&n.code!=="EROFS")throw n;return e.statAsync(r).then(o=>{if(o.isDirectory())return t;throw n},()=>{throw n})})},$S=(r,e,t)=>{let i=q8(r);if(e.recursive=!1,i===r)try{return e.mkdirSync(r,e)}catch(n){if(n.code!=="EISDIR")throw n;return}try{return e.mkdirSync(r,e),t||r}catch(n){if(n.code==="ENOENT")return $S(r,e,$S(i,e,t));if(n.code!=="EEXIST"&&n.code!=="EROFS")throw n;try{if(!e.statSync(r).isDirectory())throw n}catch(o){throw n}}};N8.exports={mkdirpManual:qS,mkdirpManualSync:$S}});var j8=v((NOe,$8)=>{var{dirname:B8}=require("path"),{findMade:dge,findMadeSync:hge}=M8(),{mkdirpManual:mge,mkdirpManualSync:gge}=BS(),vge=(r,e)=>(e.recursive=!0,B8(r)===r?e.mkdirAsync(r,e):dge(e,r).then(i=>e.mkdirAsync(r,e).then(()=>i).catch(n=>{if(n.code==="ENOENT")return mge(r,e);throw n}))),yge=(r,e)=>{if(e.recursive=!0,B8(r)===r)return e.mkdirSync(r,e);let i=hge(e,r);try{return e.mkdirSync(r,e),i}catch(n){if(n.code==="ENOENT")return gge(r,e);throw n}};$8.exports={mkdirpNative:vge,mkdirpNativeSync:yge}});var z8=v((qOe,U8)=>{var W8=require("fs"),bge=process.env.__TESTING_MKDIRP_NODE_VERSION__||process.version,jS=bge.replace(/^v/,"").split("."),H8=+jS[0]>10||+jS[0]==10&&+jS[1]>=12,wge=H8?r=>r.mkdir===W8.mkdir:()=>!1,xge=H8?r=>r.mkdirSync===W8.mkdirSync:()=>!1;U8.exports={useNative:wge,useNativeSync:xge}});var X8=v(($Oe,G8)=>{var xu=R8(),Du=I8(),{mkdirpNative:V8,mkdirpNativeSync:K8}=j8(),{mkdirpManual:J8,mkdirpManualSync:Y8}=BS(),{useNative:Dge,useNativeSync:Sge}=z8(),Su=(r,e)=>(r=Du(r),e=xu(e),Dge(e)?V8(r,e):J8(r,e)),Ege=(r,e)=>(r=Du(r),e=xu(e),Sge(e)?K8(r,e):Y8(r,e));Su.sync=Ege;Su.native=(r,e)=>V8(Du(r),xu(e));Su.manual=(r,e)=>J8(Du(r),xu(e));Su.nativeSync=(r,e)=>K8(Du(r),xu(e));Su.manualSync=(r,e)=>Y8(Du(r),xu(e));G8.exports=Su});var nW=v((BOe,Z8)=>{"use strict";var Fi=require("fs"),ya=require("path"),Cge=Fi.lchown?"lchown":"chown",_ge=Fi.lchownSync?"lchownSync":"chownSync",Q8=Fi.lchown&&!process.version.match(/v1[1-9]+\./)&&!process.version.match(/v10\.[6-9]/),eW=(r,e,t)=>{try{return Fi[_ge](r,e,t)}catch(i){if(i.code!=="ENOENT")throw i}},Pge=(r,e,t)=>{try{return Fi.chownSync(r,e,t)}catch(i){if(i.code!=="ENOENT")throw i}},Tge=Q8?(r,e,t,i)=>n=>{!n||n.code!=="EISDIR"?i(n):Fi.chown(r,e,t,i)}:(r,e,t,i)=>i,US=Q8?(r,e,t)=>{try{return eW(r,e,t)}catch(i){if(i.code!=="EISDIR")throw i;Pge(r,e,t)}}:(r,e,t)=>eW(r,e,t),Rge=process.version,tW=(r,e,t)=>Fi.readdir(r,e,t),kge=(r,e)=>Fi.readdirSync(r,e);/^v4\./.test(Rge)&&(tW=(r,e,t)=>Fi.readdir(r,t));var tv=(r,e,t,i)=>{Fi[Cge](r,e,t,Tge(r,e,t,n=>{i(n&&n.code!=="ENOENT"?n:null)}))},rW=(r,e,t,i,n)=>{if(typeof e=="string")return Fi.lstat(ya.resolve(r,e),(o,s)=>{if(o)return n(o.code!=="ENOENT"?o:null);s.name=e,rW(r,s,t,i,n)});if(e.isDirectory())WS(ya.resolve(r,e.name),t,i,o=>{if(o)return n(o);let s=ya.resolve(r,e.name);tv(s,t,i,n)});else{let o=ya.resolve(r,e.name);tv(o,t,i,n)}},WS=(r,e,t,i)=>{tW(r,{withFileTypes:!0},(n,o)=>{if(n){if(n.code==="ENOENT")return i();if(n.code!=="ENOTDIR"&&n.code!=="ENOTSUP")return i(n)}if(n||!o.length)return tv(r,e,t,i);let s=o.length,a=null,l=u=>{if(!a){if(u)return i(a=u);if(--s==0)return tv(r,e,t,i)}};o.forEach(u=>rW(r,u,e,t,l))})},Ige=(r,e,t,i)=>{if(typeof e=="string")try{let n=Fi.lstatSync(ya.resolve(r,e));n.name=e,e=n}catch(n){if(n.code==="ENOENT")return;throw n}e.isDirectory()&&iW(ya.resolve(r,e.name),t,i),US(ya.resolve(r,e.name),t,i)},iW=(r,e,t)=>{let i;try{i=kge(r,{withFileTypes:!0})}catch(n){if(n.code==="ENOENT")return;if(n.code==="ENOTDIR"||n.code==="ENOTSUP")return US(r,e,t);throw n}return i&&i.length&&i.forEach(n=>Ige(r,n,e,t)),US(r,e,t)};Z8.exports=WS;WS.sync=iW});var lW=v((WOe,HS)=>{"use strict";var oW=X8(),Ai=require("fs"),rv=require("path"),sW=nW(),zS=class extends Error{constructor(e,t){super("Cannot extract through symbolic link");this.path=t,this.symlink=e}get name(){return"SylinkError"}},Rp=class extends Error{constructor(e,t){super(t+": Cannot cd into '"+e+"'");this.path=e,this.code=t}get name(){return"CwdError"}},jOe=HS.exports=(r,e,t)=>{let i=e.umask,n=e.mode|448,o=(n&i)!=0,s=e.uid,a=e.gid,l=typeof s=="number"&&typeof a=="number"&&(s!==e.processUid||a!==e.processGid),u=e.preserve,c=e.unlink,f=e.cache,p=e.cwd,d=(y,g)=>{y?t(y):(f.set(r,!0),g&&l?sW(g,s,a,w=>d(w)):o?Ai.chmod(r,n,t):t())};if(f&&f.get(r)===!0)return d();if(r===p)return Ai.stat(r,(y,g)=>{(y||!g.isDirectory())&&(y=new Rp(r,y&&y.code||"ENOTDIR")),d(y)});if(u)return oW(r,{mode:n}).then(y=>d(null,y),d);let m=rv.relative(p,r).split(/\/|\\/);iv(p,m,n,f,c,p,null,d)},iv=(r,e,t,i,n,o,s,a)=>{if(!e.length)return a(null,s);let l=e.shift(),u=r+"/"+l;if(i.get(u))return iv(u,e,t,i,n,o,s,a);Ai.mkdir(u,t,aW(u,e,t,i,n,o,s,a))},aW=(r,e,t,i,n,o,s,a)=>l=>{if(l){if(l.path&&rv.dirname(l.path)===o&&(l.code==="ENOTDIR"||l.code==="ENOENT"))return a(new Rp(o,l.code));Ai.lstat(r,(u,c)=>{if(u)a(u);else if(c.isDirectory())iv(r,e,t,i,n,o,s,a);else if(n)Ai.unlink(r,f=>{if(f)return a(f);Ai.mkdir(r,t,aW(r,e,t,i,n,o,s,a))});else{if(c.isSymbolicLink())return a(new zS(r,r+"/"+e.join("/")));a(l)}})}else s=s||r,iv(r,e,t,i,n,o,s,a)},UOe=HS.exports.sync=(r,e)=>{let t=e.umask,i=e.mode|448,n=(i&t)!=0,o=e.uid,s=e.gid,a=typeof o=="number"&&typeof s=="number"&&(o!==e.processUid||s!==e.processGid),l=e.preserve,u=e.unlink,c=e.cache,f=e.cwd,p=y=>{c.set(r,!0),y&&a&&sW.sync(y,o,s),n&&Ai.chmodSync(r,i)};if(c&&c.get(r)===!0)return p();if(r===f){let y=!1,g="ENOTDIR";try{y=Ai.statSync(r).isDirectory()}catch(w){g=w.code}finally{if(!y)throw new Rp(r,g)}p();return}if(l)return p(oW.sync(r,i));let h=rv.relative(f,r).split(/\/|\\/),m=null;for(let y=h.shift(),g=f;y&&(g+="/"+y);y=h.shift())if(!c.get(g))try{Ai.mkdirSync(g,i),m=m||g,c.set(g,!0)}catch(w){if(w.path&&rv.dirname(w.path)===f&&(w.code==="ENOTDIR"||w.code==="ENOENT"))return new Rp(f,w.code);let x=Ai.lstatSync(g);if(x.isDirectory()){c.set(g,!0);continue}else if(u){Ai.unlinkSync(g),Ai.mkdirSync(g,i),m=m||g,c.set(g,!0);continue}else if(x.isSymbolicLink())return new zS(g,g+"/"+h.join("/"))}return p(m)}});var fW=v((HOe,uW)=>{var cW=require("assert");uW.exports=()=>{let r=new Map,e=new Map,{join:t}=require("path"),i=c=>t(c).split(/[\\\/]/).slice(0,-1).reduce((f,p)=>f.length?f.concat(t(f[f.length-1],p)):[p],[]),n=new Set,o=c=>{let f=e.get(c);if(!f)throw new Error("function does not have any path reservations");return{paths:f.paths.map(p=>r.get(p)),dirs:[...f.dirs].map(p=>r.get(p))}},s=c=>{let{paths:f,dirs:p}=o(c);return f.every(d=>d[0]===c)&&p.every(d=>d[0]instanceof Set&&d[0].has(c))},a=c=>n.has(c)||!s(c)?!1:(n.add(c),c(()=>l(c)),!0),l=c=>{if(!n.has(c))return!1;let{paths:f,dirs:p}=e.get(c),d=new Set;return f.forEach(h=>{let m=r.get(h);cW.equal(m[0],c),m.length===1?r.delete(h):(m.shift(),typeof m[0]=="function"?d.add(m[0]):m[0].forEach(y=>d.add(y)))}),p.forEach(h=>{let m=r.get(h);cW(m[0]instanceof Set),m[0].size===1&&m.length===1?r.delete(h):m[0].size===1?(m.shift(),d.add(m[0])):m[0].delete(c)}),n.delete(c),d.forEach(h=>a(h)),!0};return{check:s,reserve:(c,f)=>{let p=new Set(c.map(d=>i(d)).reduce((d,h)=>d.concat(h)));return e.set(f,{dirs:p,paths:c}),c.forEach(d=>{let h=r.get(d);h?h.push(f):r.set(d,[f])}),p.forEach(d=>{let h=r.get(d);h?h[h.length-1]instanceof Set?h[h.length-1].add(f):h.push(new Set([f])):r.set(d,[new Set([f])])}),a(f)}}}});var hW=v((zOe,pW)=>{var Fge=process.env.__FAKE_PLATFORM__||process.platform,Age=Fge==="win32",Oge=global.__FAKE_TESTING_FS__||require("fs"),{O_CREAT:Lge,O_TRUNC:Mge,O_WRONLY:Nge,UV_FS_O_FILEMAP:dW=0}=Oge.constants,qge=Age&&!!dW,$ge=512*1024,Bge=dW|Mge|Lge|Nge;pW.exports=qge?r=>r<$ge?Bge:"w":()=>"w"});var eE=v((JOe,mW)=>{"use strict";var jge=require("assert"),GOe=require("events").EventEmitter,Uge=Tp(),$e=require("fs"),Wge=bu(),ro=require("path"),GS=lW(),VOe=GS.sync,gW=aS(),Hge=fW(),vW=Symbol("onEntry"),VS=Symbol("checkFs"),yW=Symbol("checkFs2"),KS=Symbol("isReusable"),io=Symbol("makeFs"),JS=Symbol("file"),YS=Symbol("directory"),nv=Symbol("link"),bW=Symbol("symlink"),wW=Symbol("hardlink"),xW=Symbol("unsupported"),KOe=Symbol("unknown"),DW=Symbol("checkPath"),Eu=Symbol("mkdir"),Dr=Symbol("onError"),ov=Symbol("pending"),SW=Symbol("pend"),Cu=Symbol("unpend"),XS=Symbol("ended"),ZS=Symbol("maybeClose"),QS=Symbol("skip"),kp=Symbol("doChown"),Ip=Symbol("uid"),Fp=Symbol("gid"),EW=require("crypto"),CW=hW(),sv=()=>{throw new Error("sync function called cb somehow?!?")},zge=(r,e)=>{if(process.platform!=="win32")return $e.unlink(r,e);let t=r+".DELETE."+EW.randomBytes(16).toString("hex");$e.rename(r,t,i=>{if(i)return e(i);$e.unlink(t,e)})},Gge=r=>{if(process.platform!=="win32")return $e.unlinkSync(r);let e=r+".DELETE."+EW.randomBytes(16).toString("hex");$e.renameSync(r,e),$e.unlinkSync(e)},_W=(r,e,t)=>r===r>>>0?r:e===e>>>0?e:t,av=class extends Uge{constructor(e){if(e||(e={}),e.ondone=t=>{this[XS]=!0,this[ZS]()},super(e),this.reservations=Hge(),this.transform=typeof e.transform=="function"?e.transform:null,this.writable=!0,this.readable=!1,this[ov]=0,this[XS]=!1,this.dirCache=e.dirCache||new Map,typeof e.uid=="number"||typeof e.gid=="number"){if(typeof e.uid!="number"||typeof e.gid!="number")throw new TypeError("cannot set owner without number uid and gid");if(e.preserveOwner)throw new TypeError("cannot preserve owner in archive and also set owner explicitly");this.uid=e.uid,this.gid=e.gid,this.setOwner=!0}else this.uid=null,this.gid=null,this.setOwner=!1;e.preserveOwner===void 0&&typeof e.uid!="number"?this.preserveOwner=process.getuid&&process.getuid()===0:this.preserveOwner=!!e.preserveOwner,this.processUid=(this.preserveOwner||this.setOwner)&&process.getuid?process.getuid():null,this.processGid=(this.preserveOwner||this.setOwner)&&process.getgid?process.getgid():null,this.forceChown=e.forceChown===!0,this.win32=!!e.win32||process.platform==="win32",this.newer=!!e.newer,this.keep=!!e.keep,this.noMtime=!!e.noMtime,this.preservePaths=!!e.preservePaths,this.unlink=!!e.unlink,this.cwd=ro.resolve(e.cwd||process.cwd()),this.strip=+e.strip||0,this.processUmask=process.umask(),this.umask=typeof e.umask=="number"?e.umask:this.processUmask,this.dmode=e.dmode||511&~this.umask,this.fmode=e.fmode||438&~this.umask,this.on("entry",t=>this[vW](t))}warn(e,t,i={}){return(e==="TAR_BAD_ARCHIVE"||e==="TAR_ABORT")&&(i.recoverable=!1),super.warn(e,t,i)}[ZS](){this[XS]&&this[ov]===0&&(this.emit("prefinish"),this.emit("finish"),this.emit("end"),this.emit("close"))}[DW](e){if(this.strip){let t=e.path.split(/\/|\\/);if(t.length=this.strip&&(e.linkpath=i.slice(this.strip).join("/"))}}if(!this.preservePaths){let t=e.path;if(t.match(/(^|\/|\\)\.\.(\\|\/|$)/))return this.warn("TAR_ENTRY_ERROR","path contains '..'",{entry:e,path:t}),!1;if(ro.win32.isAbsolute(t)){let i=ro.win32.parse(t);e.path=t.substr(i.root.length);let n=i.root;this.warn("TAR_ENTRY_INFO",`stripping ${n} from absolute path`,{entry:e,path:t})}}if(this.win32){let t=ro.win32.parse(e.path);e.path=t.root===""?gW.encode(e.path):t.root+gW.encode(e.path.substr(t.root.length))}return ro.isAbsolute(e.path)?e.absolute=e.path:e.absolute=ro.resolve(this.cwd,e.path),!0}[vW](e){if(!this[DW](e))return e.resume();switch(jge.equal(typeof e.absolute,"string"),e.type){case"Directory":case"GNUDumpDir":e.mode&&(e.mode=e.mode|448);case"File":case"OldFile":case"ContiguousFile":case"Link":case"SymbolicLink":return this[VS](e);case"CharacterDevice":case"BlockDevice":case"FIFO":return this[xW](e)}}[Dr](e,t){e.name==="CwdError"?this.emit("error",e):(this.warn("TAR_ENTRY_ERROR",e,{entry:t}),this[Cu](),t.resume())}[Eu](e,t,i){GS(e,{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:t},i)}[kp](e){return this.forceChown||this.preserveOwner&&(typeof e.uid=="number"&&e.uid!==this.processUid||typeof e.gid=="number"&&e.gid!==this.processGid)||typeof this.uid=="number"&&this.uid!==this.processUid||typeof this.gid=="number"&&this.gid!==this.processGid}[Ip](e){return _W(this.uid,e.uid,this.processUid)}[Fp](e){return _W(this.gid,e.gid,this.processGid)}[JS](e,t){let i=e.mode&4095||this.fmode,n=new Wge.WriteStream(e.absolute,{flags:CW(e.size),mode:i,autoClose:!1});n.on("error",l=>this[Dr](l,e));let o=1,s=l=>{if(l)return this[Dr](l,e);--o==0&&$e.close(n.fd,u=>{t(),u?this[Dr](u,e):this[Cu]()})};n.on("finish",l=>{let u=e.absolute,c=n.fd;if(e.mtime&&!this.noMtime){o++;let f=e.atime||new Date,p=e.mtime;$e.futimes(c,f,p,d=>d?$e.utimes(u,f,p,h=>s(h&&d)):s())}if(this[kp](e)){o++;let f=this[Ip](e),p=this[Fp](e);$e.fchown(c,f,p,d=>d?$e.chown(u,f,p,h=>s(h&&d)):s())}s()});let a=this.transform&&this.transform(e)||e;a!==e&&(a.on("error",l=>this[Dr](l,e)),e.pipe(a)),a.pipe(n)}[YS](e,t){let i=e.mode&4095||this.dmode;this[Eu](e.absolute,i,n=>{if(n)return t(),this[Dr](n,e);let o=1,s=a=>{--o==0&&(t(),this[Cu](),e.resume())};e.mtime&&!this.noMtime&&(o++,$e.utimes(e.absolute,e.atime||new Date,e.mtime,s)),this[kp](e)&&(o++,$e.chown(e.absolute,this[Ip](e),this[Fp](e),s)),s()})}[xW](e){e.unsupported=!0,this.warn("TAR_ENTRY_UNSUPPORTED",`unsupported entry type: ${e.type}`,{entry:e}),e.resume()}[bW](e,t){this[nv](e,e.linkpath,"symlink",t)}[wW](e,t){this[nv](e,ro.resolve(this.cwd,e.linkpath),"link",t)}[SW](){this[ov]++}[Cu](){this[ov]--,this[ZS]()}[QS](e){this[Cu](),e.resume()}[KS](e,t){return e.type==="File"&&!this.unlink&&t.isFile()&&t.nlink<=1&&process.platform!=="win32"}[VS](e){this[SW]();let t=[e.path];e.linkpath&&t.push(e.linkpath),this.reservations.reserve(t,i=>this[yW](e,i))}[yW](e,t){this[Eu](ro.dirname(e.absolute),this.dmode,i=>{if(i)return t(),this[Dr](i,e);$e.lstat(e.absolute,(n,o)=>{o&&(this.keep||this.newer&&o.mtime>e.mtime)?(this[QS](e),t()):n||this[KS](e,o)?this[io](null,e,t):o.isDirectory()?e.type==="Directory"?!e.mode||(o.mode&4095)===e.mode?this[io](null,e,t):$e.chmod(e.absolute,e.mode,s=>this[io](s,e,t)):$e.rmdir(e.absolute,s=>this[io](s,e,t)):zge(e.absolute,s=>this[io](s,e,t))})})}[io](e,t,i){if(e)return this[Dr](e,t);switch(t.type){case"File":case"OldFile":case"ContiguousFile":return this[JS](t,i);case"Link":return this[wW](t,i);case"SymbolicLink":return this[bW](t,i);case"Directory":case"GNUDumpDir":return this[YS](t,i)}}[nv](e,t,i,n){$e[i](t,e.absolute,o=>{if(o)return this[Dr](o,e);n(),this[Cu](),e.resume()})}},PW=class extends av{constructor(e){super(e)}[VS](e){let t=this[Eu](ro.dirname(e.absolute),this.dmode,sv);if(t)return this[Dr](t,e);try{let i=$e.lstatSync(e.absolute);if(this.keep||this.newer&&i.mtime>e.mtime)return this[QS](e);if(this[KS](e,i))return this[io](null,e,sv);try{return i.isDirectory()?e.type==="Directory"?e.mode&&(i.mode&4095)!==e.mode&&$e.chmodSync(e.absolute,e.mode):$e.rmdirSync(e.absolute):Gge(e.absolute),this[io](null,e,sv)}catch(n){return this[Dr](n,e)}}catch(i){return this[io](null,e,sv)}}[JS](e,t){let i=e.mode&4095||this.fmode,n=l=>{let u;try{$e.closeSync(s)}catch(c){u=c}(l||u)&&this[Dr](l||u,e)},o,s;try{s=$e.openSync(e.absolute,CW(e.size),i)}catch(l){return n(l)}let a=this.transform&&this.transform(e)||e;a!==e&&(a.on("error",l=>this[Dr](l,e)),e.pipe(a)),a.on("data",l=>{try{$e.writeSync(s,l,0,l.length)}catch(u){n(u)}}),a.on("end",l=>{let u=null;if(e.mtime&&!this.noMtime){let c=e.atime||new Date,f=e.mtime;try{$e.futimesSync(s,c,f)}catch(p){try{$e.utimesSync(e.absolute,c,f)}catch(d){u=p}}}if(this[kp](e)){let c=this[Ip](e),f=this[Fp](e);try{$e.fchownSync(s,c,f)}catch(p){try{$e.chownSync(e.absolute,c,f)}catch(d){u=u||p}}}n(u)})}[YS](e,t){let i=e.mode&4095||this.dmode,n=this[Eu](e.absolute,i);if(n)return this[Dr](n,e);if(e.mtime&&!this.noMtime)try{$e.utimesSync(e.absolute,e.atime||new Date,e.mtime)}catch(o){}if(this[kp](e))try{$e.chownSync(e.absolute,this[Ip](e),this[Fp](e))}catch(o){}e.resume()}[Eu](e,t){try{return GS.sync(e,{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:t})}catch(i){return i}}[nv](e,t,i,n){try{$e[i+"Sync"](t,e.absolute),e.resume()}catch(o){return this[Dr](o,e)}}};av.Sync=PW;mW.exports=av});var FW=v((XOe,TW)=>{"use strict";var Vge=ou(),lv=eE(),RW=require("fs"),kW=bu(),IW=require("path"),YOe=TW.exports=(r,e,t)=>{typeof r=="function"?(t=r,e=null,r={}):Array.isArray(r)&&(e=r,r={}),typeof e=="function"&&(t=e,e=null),e?e=Array.from(e):e=[];let i=Vge(r);if(i.sync&&typeof t=="function")throw new TypeError("callback not supported for sync tar functions");if(!i.file&&typeof t=="function")throw new TypeError("callback only supported with file option");return e.length&&Kge(i,e),i.file&&i.sync?Jge(i):i.file?Yge(i,t):i.sync?Xge(i):Zge(i)},Kge=(r,e)=>{let t=new Map(e.map(o=>[o.replace(/\/+$/,""),!0])),i=r.filter,n=(o,s)=>{let a=s||IW.parse(o).root||".",l=o===a?!1:t.has(o)?t.get(o):n(IW.dirname(o),a);return t.set(o,l),l};r.filter=i?(o,s)=>i(o,s)&&n(o.replace(/\/+$/,"")):o=>n(o.replace(/\/+$/,""))},Jge=r=>{let e=new lv.Sync(r),t=r.file,i=!0,n,o=RW.statSync(t),s=r.maxReadSize||16*1024*1024;new kW.ReadStreamSync(t,{readSize:s,size:o.size}).pipe(e)},Yge=(r,e)=>{let t=new lv(r),i=r.maxReadSize||16*1024*1024,n=r.file,o=new Promise((s,a)=>{t.on("error",a),t.on("close",s),RW.stat(n,(l,u)=>{if(l)a(l);else{let c=new kW.ReadStream(n,{readSize:i,size:u.size});c.on("error",a),c.pipe(t)}})});return e?o.then(e,e):o},Xge=r=>new lv.Sync(r),Zge=r=>new lv(r)});var AW=v(Ft=>{"use strict";Ft.c=Ft.create=v8();Ft.r=Ft.replace=NS();Ft.t=Ft.list=Qg();Ft.u=Ft.update=_8();Ft.x=Ft.extract=FW();Ft.Pack=jg();Ft.Unpack=eE();Ft.Parse=Tp();Ft.ReadEntry=Dp();Ft.WriteEntry=hS();Ft.Header=uu();Ft.Pax=Pg();Ft.types=xp()});var NW=v((QOe,OW)=>{OW.exports=fr;function fr(r){if(!(this instanceof fr))return new fr(r);this.value=r}fr.prototype.get=function(r){for(var e=this.value,t=0;t{var Qge=NW(),eve=require("events").EventEmitter;qW.exports=_u;function _u(r){var e=_u.saw(r,{}),t=r.call(e.handlers,e);return t!==void 0&&(e.handlers=t),e.record(),e.chain()}_u.light=function(e){var t=_u.saw(e,{}),i=e.call(t.handlers,t);return i!==void 0&&(t.handlers=i),t.chain()};_u.saw=function(r,e){var t=new eve;return t.handlers=e,t.actions=[],t.chain=function(){var i=Qge(t.handlers).map(function(n){if(this.isRoot)return n;var o=this.path;typeof n=="function"&&this.update(function(){return t.actions.push({path:o,args:[].slice.call(arguments)}),i})});return process.nextTick(function(){t.emit("begin"),t.next()}),i},t.pop=function(){return t.actions.shift()},t.next=function(){var i=t.pop();if(!i)t.emit("end");else if(!i.trap){var n=t.handlers;i.path.forEach(function(o){n=n[o]}),n.apply(t.handlers,i.args)}},t.nest=function(i){var n=[].slice.call(arguments,1),o=!0;if(typeof i=="boolean"){var o=i;i=n.shift()}var s=_u.saw(r,{}),a=r.call(s.handlers,s);a!==void 0&&(s.handlers=a),typeof t.step!="undefined"&&s.record(),i.apply(s.chain(),n),o!==!1&&s.on("end",t.next)},t.record=function(){tve(t)},["trap","down","jump"].forEach(function(i){t[i]=function(){throw new Error("To use the trap, down and jump features, please call record() first to start recording actions.")}}),t};function tve(r){r.step=0,r.pop=function(){return r.actions[r.step++]},r.trap=function(e,t){var i=Array.isArray(e)?e:[e];r.actions.push({path:i,step:r.step,cb:t,trap:!0})},r.down=function(e){var t=(Array.isArray(e)?e:[e]).join("/"),i=r.actions.slice(r.step).map(function(o){return o.trap&&o.step<=r.step?!1:o.path.join("/")==t}).indexOf(!0);i>=0?r.step+=i:r.step=r.actions.length;var n=r.actions[r.step-1];n&&n.trap?(r.step=n.step,n.cb()):r.next()},r.jump=function(e){r.step=e,r.next()}}});var jW=v((tLe,BW)=>{BW.exports=Sr;function Sr(r){if(!(this instanceof Sr))return new Sr(r);this.buffers=r||[],this.length=this.buffers.reduce(function(e,t){return e+t.length},0)}Sr.prototype.push=function(){for(var r=0;r=0?r:this.length-r,n=[].slice.call(arguments,2);e===void 0?e=this.length-i:e>this.length-i&&(e=this.length-i);for(var r=0;r0){var u=i-a;if(u+e0){var d=n.slice();d.unshift(f),d.push(p),t.splice.apply(t,[l,1].concat(d)),l+=d.length,n=[]}else t.splice(l,1,f,p),l+=2}else o.push(t[l].slice(u)),t[l]=t[l].slice(0,u),l++}for(n.length>0&&(t.splice.apply(t,[l,0].concat(n)),l+=n.length);o.lengththis.length&&(e=this.length);for(var i=0,n=0;n=e-r?Math.min(u+(e-r)-s,l):l;t[a].copy(o,s,u,c),s+=c-u}return o};Sr.prototype.pos=function(r){if(r<0||r>=this.length)throw new Error("oob");for(var e=r,t=0,i=null;;){if(i=this.buffers[t],e=this.buffers[t].length;)if(i=0,t++,t>=this.buffers.length)return-1;var l=this.buffers[t][i];if(l==r[n]){if(n==0&&(o={i:t,j:i,pos:s}),n++,n==r.length)return o.pos}else n!=0&&(t=o.i,i=o.j,s=o.pos,n=0);i++,s++}};Sr.prototype.toBuffer=function(){return this.slice()};Sr.prototype.toString=function(r,e,t){return this.slice(e,t).toString(r)}});var WW=v((rLe,UW)=>{UW.exports=function(r){function e(i,n){var o=t.store,s=i.split(".");s.slice(0,-1).forEach(function(l){o[l]===void 0&&(o[l]={}),o=o[l]});var a=s[s.length-1];return arguments.length==1?o[a]:o[a]=n}var t={get:function(i){return e(i)},set:function(i,n){return e(i,n)},store:r||{}};return t}});var JW=v((ba,HW)=>{var rve=$W(),zW=require("events").EventEmitter,ive=jW(),uv=WW(),nve=require("stream").Stream;ba=HW.exports=function(r,e){if(Buffer.isBuffer(r))return ba.parse(r);var t=ba.stream();return r&&r.pipe?r.pipe(t):r&&(r.on(e||"data",function(i){t.write(i)}),r.on("end",function(){t.end()})),t};ba.stream=function(r){if(r)return ba.apply(null,arguments);var e=null;function t(f,p,d){e={bytes:f,skip:d,cb:function(h){e=null,p(h)}},n()}var i=null;function n(){if(!e){c&&(u=!0);return}if(typeof e=="function")e();else{var f=i+e.bytes;if(a.length>=f){var p;i==null?(p=a.splice(0,f),e.skip||(p=p.slice())):(e.skip||(p=a.slice(i,f)),i=f),e.skip?e.cb():e.cb(p)}}}function o(f){function p(){u||f.next()}var d=GW(function(h,m){return function(y){t(h,function(g){l.set(y,m(g)),p()})}});return d.tap=function(h){f.nest(h,l.store)},d.into=function(h,m){l.get(h)||l.set(h,{});var y=l;l=uv(y.get(h)),f.nest(function(){m.apply(this,arguments),this.tap(function(){l=y})},l.store)},d.flush=function(){l.store={},p()},d.loop=function(h){var m=!1;f.nest(!1,function y(){this.vars=l.store,h.call(this,function(){m=!0,p()},l.store),this.tap(function(){m?f.next():y.call(this)}.bind(this))},l.store)},d.buffer=function(h,m){typeof m=="string"&&(m=l.get(m)),t(m,function(y){l.set(h,y),p()})},d.skip=function(h){typeof h=="string"&&(h=l.get(h)),t(h,function(){p()})},d.scan=function(m,y){if(typeof y=="string")y=new Buffer(y);else if(!Buffer.isBuffer(y))throw new Error("search must be a Buffer or a string");var g=0;e=function(){var w=a.indexOf(y,i+g),x=w-i-g;w!==-1?(e=null,i!=null?(l.set(m,a.slice(i,i+g+x)),i+=g+x+y.length):(l.set(m,a.slice(0,g+x)),a.splice(0,g+x+y.length)),p(),n()):x=Math.max(a.length-y.length-i-g,0),g+=x},n()},d.peek=function(h){i=0,f.nest(function(){h.call(this,l.store),this.tap(function(){i=null})})},d}var s=rve.light(o);s.writable=!0;var a=ive();s.write=function(f){a.push(f),n()};var l=uv(),u=!1,c=!1;return s.end=function(){c=!0},s.pipe=nve.prototype.pipe,Object.getOwnPropertyNames(zW.prototype).forEach(function(f){s[f]=zW.prototype[f]}),s};ba.parse=function(e){var t=GW(function(o,s){return function(a){if(i+o<=e.length){var l=e.slice(i,i+o);i+=o,n.set(a,s(l))}else n.set(a,null);return t}}),i=0,n=uv();return t.vars=n.store,t.tap=function(o){return o.call(t,n.store),t},t.into=function(o,s){n.get(o)||n.set(o,{});var a=n;return n=uv(a.get(o)),s.call(t,n.store),n=a,t},t.loop=function(o){for(var s=!1,a=function(){s=!0};s===!1;)o.call(t,a,n.store);return t},t.buffer=function(o,s){typeof s=="string"&&(s=n.get(s));var a=e.slice(i,Math.min(e.length,i+s));return i+=s,n.set(o,a),t},t.skip=function(o){return typeof o=="string"&&(o=n.get(o)),i+=o,t},t.scan=function(o,s){if(typeof s=="string")s=new Buffer(s);else if(!Buffer.isBuffer(s))throw new Error("search must be a Buffer or a string");n.set(o,null);for(var a=0;a+i<=e.length-s.length+1;a++){for(var l=0;l=e.length},t};function VW(r){for(var e=0,t=0;t{var XW=require("stream").Transform,ave=require("util");function wa(r,e){if(!(this instanceof wa))return new wa;XW.call(this);var t=typeof r=="object"?r.pattern:r;this.pattern=Buffer.isBuffer(t)?t:Buffer.from(t),this.requiredLength=this.pattern.length,r.requiredExtraSize&&(this.requiredLength+=r.requiredExtraSize),this.data=new Buffer(""),this.bytesSoFar=0,this.matchFn=e}ave.inherits(wa,XW);wa.prototype.checkDataChunk=function(r){var e=this.data.length>=this.requiredLength;if(!!e){var t=this.data.indexOf(this.pattern,r?1:0);if(t>=0&&t+this.requiredLength>this.data.length){if(t>0){var i=this.data.slice(0,t);this.push(i),this.bytesSoFar+=t,this.data=this.data.slice(t)}return}if(t===-1){var n=this.data.length-this.requiredLength+1,i=this.data.slice(0,n);this.push(i),this.bytesSoFar+=n,this.data=this.data.slice(n);return}if(t>0){var i=this.data.slice(0,t);this.data=this.data.slice(t),this.push(i),this.bytesSoFar+=t}var o=this.matchFn?this.matchFn(this.data,this.bytesSoFar):!0;if(o){this.data=new Buffer("");return}return!0}};wa.prototype._transform=function(r,e,t){this.data=Buffer.concat([this.data,r]);for(var i=!0;this.checkDataChunk(!i);)i=!1;t()};wa.prototype._flush=function(r){if(this.data.length>0)for(var e=!0;this.checkDataChunk(!e);)e=!1;this.data.length>0&&(this.push(this.data),this.data=null),r()};YW.exports=wa});var e5=v((nLe,QW)=>{"use strict";var tE=require("stream"),lve=require("util").inherits;function Ap(){if(!(this instanceof Ap))return new Ap;tE.PassThrough.call(this),this.path=null,this.type=null,this.isDirectory=!1}lve(Ap,tE.PassThrough);Ap.prototype.autodrain=function(){return this.pipe(new tE.Transform({transform:function(r,e,t){t()}}))};QW.exports=Ap});var iE=v((oLe,t5)=>{"use strict";var ns=JW(),rE=require("stream"),uve=require("util"),cve=require("zlib"),fve=ZW(),r5=e5(),oe={STREAM_START:0,START:1,LOCAL_FILE_HEADER:2,LOCAL_FILE_HEADER_SUFFIX:3,FILE_DATA:4,FILE_DATA_END:5,DATA_DESCRIPTOR:6,CENTRAL_DIRECTORY_FILE_HEADER:7,CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX:8,CDIR64_END:9,CDIR64_END_DATA_SECTOR:10,CDIR64_LOCATOR:11,CENTRAL_DIRECTORY_END:12,CENTRAL_DIRECTORY_END_COMMENT:13,TRAILING_JUNK:14,ERROR:99},Op=4294967296,pve=67324752,dve=134695760,hve=33639248,mve=101075792,gve=117853008,vve=101010256;function zt(r){if(!(this instanceof zt))return new zt(r);rE.Transform.call(this),this.options=r||{},this.data=new Buffer(""),this.state=oe.STREAM_START,this.skippedBytes=0,this.parsedEntity=null,this.outStreamInfo={}}uve.inherits(zt,rE.Transform);zt.prototype.processDataChunk=function(r){var e;switch(this.state){case oe.STREAM_START:case oe.START:e=4;break;case oe.LOCAL_FILE_HEADER:e=26;break;case oe.LOCAL_FILE_HEADER_SUFFIX:e=this.parsedEntity.fileNameLength+this.parsedEntity.extraFieldLength;break;case oe.DATA_DESCRIPTOR:e=12;break;case oe.CENTRAL_DIRECTORY_FILE_HEADER:e=42;break;case oe.CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX:e=this.parsedEntity.fileNameLength+this.parsedEntity.extraFieldLength+this.parsedEntity.fileCommentLength;break;case oe.CDIR64_END:e=52;break;case oe.CDIR64_END_DATA_SECTOR:e=this.parsedEntity.centralDirectoryRecordSize-44;break;case oe.CDIR64_LOCATOR:e=16;break;case oe.CENTRAL_DIRECTORY_END:e=18;break;case oe.CENTRAL_DIRECTORY_END_COMMENT:e=this.parsedEntity.commentLength;break;case oe.FILE_DATA:return 0;case oe.FILE_DATA_END:return 0;case oe.TRAILING_JUNK:return this.options.debug&&console.log("found",r.length,"bytes of TRAILING_JUNK"),r.length;default:return r.length}var t=r.length;if(t>>8,(o&255)==80){s=a;break}return this.skippedBytes+=s,this.options.debug&&console.log("Skipped",this.skippedBytes,"bytes"),s}this.state=oe.ERROR;var l=n?"Not a valid zip file":"Invalid signature in zip file";if(this.options.debug){var u=r.readUInt32LE(0),c;try{c=r.slice(0,4).toString()}catch(E){}console.log("Unexpected signature in zip file: 0x"+u.toString(16),'"'+c+'", skipped',this.skippedBytes,"bytes")}return this.emit("error",new Error(l)),r.length}return this.skippedBytes=0,e;case oe.LOCAL_FILE_HEADER:return this.parsedEntity=this._readFile(r),this.state=oe.LOCAL_FILE_HEADER_SUFFIX,e;case oe.LOCAL_FILE_HEADER_SUFFIX:var f=new r5,p=(this.parsedEntity.flags&2048)!=0;f.path=this._decodeString(r.slice(0,this.parsedEntity.fileNameLength),p);var d=r.slice(this.parsedEntity.fileNameLength,this.parsedEntity.fileNameLength+this.parsedEntity.extraFieldLength),h=this._readExtraFields(d);if(h&&h.parsed&&(h.parsed.path&&!p&&(f.path=h.parsed.path),Number.isFinite(h.parsed.uncompressedSize)&&this.parsedEntity.uncompressedSize===Op-1&&(this.parsedEntity.uncompressedSize=h.parsed.uncompressedSize),Number.isFinite(h.parsed.compressedSize)&&this.parsedEntity.compressedSize===Op-1&&(this.parsedEntity.compressedSize=h.parsed.compressedSize)),this.parsedEntity.extra=h.parsed||{},this.options.debug){let E=Object.assign({},this.parsedEntity,{path:f.path,flags:"0x"+this.parsedEntity.flags.toString(16),extraFields:h&&h.debug});console.log("decoded LOCAL_FILE_HEADER:",JSON.stringify(E,null,2))}return this._prepareOutStream(this.parsedEntity,f),this.emit("entry",f),this.state=oe.FILE_DATA,e;case oe.CENTRAL_DIRECTORY_FILE_HEADER:return this.parsedEntity=this._readCentralDirectoryEntry(r),this.state=oe.CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX,e;case oe.CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX:var p=(this.parsedEntity.flags&2048)!=0,m=this._decodeString(r.slice(0,this.parsedEntity.fileNameLength),p),d=r.slice(this.parsedEntity.fileNameLength,this.parsedEntity.fileNameLength+this.parsedEntity.extraFieldLength),h=this._readExtraFields(d);h&&h.parsed&&h.parsed.path&&!p&&(m=h.parsed.path),this.parsedEntity.extra=h.parsed;var y=(this.parsedEntity.versionMadeBy&65280)>>8==3,g,w;if(y){g=this.parsedEntity.externalFileAttributes>>>16;var x=g>>>12;w=(x&10)==10}if(this.options.debug){let E=Object.assign({},this.parsedEntity,{path:m,flags:"0x"+this.parsedEntity.flags.toString(16),unixAttrs:g&&"0"+g.toString(8),isSymlink:w,extraFields:h.debug});console.log("decoded CENTRAL_DIRECTORY_FILE_HEADER:",JSON.stringify(E,null,2))}return this.state=oe.START,e;case oe.CDIR64_END:return this.parsedEntity=this._readEndOfCentralDirectory64(r),this.options.debug&&console.log("decoded CDIR64_END_RECORD:",this.parsedEntity),this.state=oe.CDIR64_END_DATA_SECTOR,e;case oe.CDIR64_END_DATA_SECTOR:return this.state=oe.START,e;case oe.CDIR64_LOCATOR:return this.state=oe.START,e;case oe.CENTRAL_DIRECTORY_END:return this.parsedEntity=this._readEndOfCentralDirectory(r),this.options.debug&&console.log("decoded CENTRAL_DIRECTORY_END:",this.parsedEntity),this.state=oe.CENTRAL_DIRECTORY_END_COMMENT,e;case oe.CENTRAL_DIRECTORY_END_COMMENT:return this.options.debug&&console.log("decoded CENTRAL_DIRECTORY_END_COMMENT:",r.slice(0,e).toString()),this.state=oe.TRAILING_JUNK,e;case oe.ERROR:return r.length;default:return console.log("didn't handle state #",this.state,"discarding"),r.length}};zt.prototype._prepareOutStream=function(r,e){var t=this,i=r.uncompressedSize===0&&/[\/\\]$/.test(e.path);e.path=e.path.replace(/^([/\\]*[.]+[/\\]+)*[/\\]*/,""),e.type=i?"Directory":"File",e.isDirectory=i;var n=!(r.flags&8);n&&(e.size=r.uncompressedSize);var o=r.versionsNeededToExtract<=45;if(this.outStreamInfo={stream:null,limit:n?r.compressedSize:-1,written:0},n)this.outStreamInfo.stream=new rE.PassThrough;else{var s=new Buffer(4);s.writeUInt32LE(dve,0);var a=r.extra.zip64Mode,l=a?20:12,u={pattern:s,requiredExtraSize:l},c=new fve(u,function(m,y){var g=t._readDataDescriptor(m,a),w=g.compressedSize===y;if(!a&&!w&&y>=Op)for(var x=y-Op;x>=0&&(w=g.compressedSize===x,!w);)x-=Op;if(!!w){t.state=oe.FILE_DATA_END;var E=a?24:16;return t.data.length>0?t.data=Buffer.concat([m.slice(E),t.data]):t.data=m.slice(E),!0}});this.outStreamInfo.stream=c}var f=r.flags&1||r.flags&64;if(f||!o){var p=f?"Encrypted files are not supported!":"Zip version "+Math.floor(r.versionsNeededToExtract/10)+"."+r.versionsNeededToExtract%10+" is not supported";e.skip=!0,setImmediate(()=>{e.emit("error",new Error(p))}),this.outStreamInfo.stream.pipe(new r5().autodrain());return}var d=r.compressionMethod>0;if(d){var h=cve.createInflateRaw();h.on("error",function(m){t.state=oe.ERROR,t.emit("error",m)}),this.outStreamInfo.stream.pipe(h).pipe(e)}else this.outStreamInfo.stream.pipe(e);this._drainAllEntries&&e.autodrain()};zt.prototype._readFile=function(r){var e=ns.parse(r).word16lu("versionsNeededToExtract").word16lu("flags").word16lu("compressionMethod").word16lu("lastModifiedTime").word16lu("lastModifiedDate").word32lu("crc32").word32lu("compressedSize").word32lu("uncompressedSize").word16lu("fileNameLength").word16lu("extraFieldLength").vars;return e};zt.prototype._readExtraFields=function(r){var e={},t={parsed:e};this.options.debug&&(t.debug=[]);for(var i=0;i=l+4&&a&1&&(e.mtime=new Date(r.readUInt32LE(i+l)*1e3),l+=4),n.extraSize>=l+4&&a&2&&(e.atime=new Date(r.readUInt32LE(i+l)*1e3),l+=4),n.extraSize>=l+4&&a&4&&(e.ctime=new Date(r.readUInt32LE(i+l)*1e3));break;case 28789:o="Info-ZIP Unicode Path Extra Field";var u=r.readUInt8(i);if(u===1){var l=1,c=r.readUInt32LE(i+l);l+=4;var f=r.slice(i+l);e.path=f.toString()}break;case 13:case 22613:o=n.extraId===13?"PKWARE Unix":"Info-ZIP UNIX (type 1)";var l=0;if(n.extraSize>=8){var p=new Date(r.readUInt32LE(i+l)*1e3);l+=4;var d=new Date(r.readUInt32LE(i+l)*1e3);if(l+=4,e.atime=p,e.mtime=d,n.extraSize>=12){var h=r.readUInt16LE(i+l);l+=2;var m=r.readUInt16LE(i+l);l+=2,e.uid=h,e.gid=m}}break;case 30805:o="Info-ZIP UNIX (type 2)";var l=0;if(n.extraSize>=4){var h=r.readUInt16LE(i+l);l+=2;var m=r.readUInt16LE(i+l);l+=2,e.uid=h,e.gid=m}break;case 30837:o="Info-ZIP New Unix";var l=0,y=r.readUInt8(i);if(l+=1,y===1){var g=r.readUInt8(i+l);l+=1,g<=6&&(e.uid=r.readUIntLE(i+l,g)),l+=g;var w=r.readUInt8(i+l);l+=1,w<=6&&(e.gid=r.readUIntLE(i+l,w))}break;case 30062:o="ASi Unix";var l=0;if(n.extraSize>=14){var x=r.readUInt32LE(i+l);l+=4;var E=r.readUInt16LE(i+l);l+=2;var P=r.readUInt32LE(i+l);l+=4;var h=r.readUInt16LE(i+l);l+=2;var m=r.readUInt16LE(i+l);if(l+=2,e.mode=E,e.uid=h,e.gid=m,n.extraSize>14){var k=i+l,_=i+n.extraSize-14,L=this._decodeString(r.slice(k,_));e.symlink=L}}break}this.options.debug&&t.debug.push({extraId:"0x"+n.extraId.toString(16),description:o,data:r.slice(i,i+n.extraSize).inspect()}),i+=n.extraSize}return t};zt.prototype._readDataDescriptor=function(r,e){if(e){var t=ns.parse(r).word32lu("dataDescriptorSignature").word32lu("crc32").word64lu("compressedSize").word64lu("uncompressedSize").vars;return t}var t=ns.parse(r).word32lu("dataDescriptorSignature").word32lu("crc32").word32lu("compressedSize").word32lu("uncompressedSize").vars;return t};zt.prototype._readCentralDirectoryEntry=function(r){var e=ns.parse(r).word16lu("versionMadeBy").word16lu("versionsNeededToExtract").word16lu("flags").word16lu("compressionMethod").word16lu("lastModifiedTime").word16lu("lastModifiedDate").word32lu("crc32").word32lu("compressedSize").word32lu("uncompressedSize").word16lu("fileNameLength").word16lu("extraFieldLength").word16lu("fileCommentLength").word16lu("diskNumber").word16lu("internalFileAttributes").word32lu("externalFileAttributes").word32lu("offsetToLocalFileHeader").vars;return e};zt.prototype._readEndOfCentralDirectory64=function(r){var e=ns.parse(r).word64lu("centralDirectoryRecordSize").word16lu("versionMadeBy").word16lu("versionsNeededToExtract").word32lu("diskNumber").word32lu("diskNumberWithCentralDirectoryStart").word64lu("centralDirectoryEntries").word64lu("totalCentralDirectoryEntries").word64lu("sizeOfCentralDirectory").word64lu("offsetToStartOfCentralDirectory").vars;return e};zt.prototype._readEndOfCentralDirectory=function(r){var e=ns.parse(r).word16lu("diskNumber").word16lu("diskStart").word16lu("centralDirectoryEntries").word16lu("totalCentralDirectoryEntries").word32lu("sizeOfCentralDirectory").word32lu("offsetToStartOfCentralDirectory").word16lu("commentLength").vars;return e};var yve="\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\xB6\xA7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0 ";zt.prototype._decodeString=function(r,e){if(e)return r.toString("utf8");if(this.options.decodeString)return this.options.decodeString(r);let t="";for(var i=0;i0&&(this.data=this.data.slice(t),this.data.length!==0););if(this.state===oe.FILE_DATA){if(this.outStreamInfo.limit>=0){var i=this.outStreamInfo.limit-this.outStreamInfo.written,n;i{if(this.state===oe.FILE_DATA_END)return this.state=oe.START,o.end(e);e()})}return}e()};zt.prototype.drainAll=function(){this._drainAllEntries=!0};zt.prototype._transform=function(r,e,t){var i=this;i.data.length>0?i.data=Buffer.concat([i.data,r]):i.data=r;var n=i.data.length,o=function(){if(i.data.length>0&&i.data.length0){e._parseOrOutput("buffer",function(){if(e.data.length>0)return setImmediate(function(){e._flush(r)});r()});return}if(e.state===oe.FILE_DATA)return r(new Error("Stream finished in an invalid state, uncompression failed"));setImmediate(r)};t5.exports=zt});var n5=v((sLe,i5)=>{var Lp=require("stream").Transform,bve=require("util"),wve=iE();function os(r){if(!(this instanceof os))return new os(r);var e=r||{};Lp.call(this,{readableObjectMode:!0}),this.opts=r||{},this.unzipStream=new wve(this.opts);var t=this;this.unzipStream.on("entry",function(i){t.push(i)}),this.unzipStream.on("error",function(i){t.emit("error",i)})}bve.inherits(os,Lp);os.prototype._transform=function(r,e,t){this.unzipStream.write(r,e,t)};os.prototype._flush=function(r){var e=this;this.unzipStream.end(function(){process.nextTick(function(){e.emit("close")}),r()})};os.prototype.on=function(r,e){return r==="entry"?Lp.prototype.on.call(this,"data",e):Lp.prototype.on.call(this,r,e)};os.prototype.drainAll=function(){return this.unzipStream.drainAll(),this.pipe(new Lp({objectMode:!0,transform:function(r,e,t){t()}}))};i5.exports=os});var l5=v((aLe,o5)=>{var Mp=require("path"),s5=require("fs"),a5=parseInt("0777",8);o5.exports=Pu.mkdirp=Pu.mkdirP=Pu;function Pu(r,e,t,i){typeof e=="function"?(t=e,e={}):(!e||typeof e!="object")&&(e={mode:e});var n=e.mode,o=e.fs||s5;n===void 0&&(n=a5),i||(i=null);var s=t||function(){};r=Mp.resolve(r),o.mkdir(r,n,function(a){if(!a)return i=i||r,s(null,i);switch(a.code){case"ENOENT":if(Mp.dirname(r)===r)return s(a);Pu(Mp.dirname(r),e,function(l,u){l?s(l,u):Pu(r,e,s,u)});break;default:o.stat(r,function(l,u){l||!u.isDirectory()?s(a,i):s(null,i)});break}})}Pu.sync=function r(e,t,i){(!t||typeof t!="object")&&(t={mode:t});var n=t.mode,o=t.fs||s5;n===void 0&&(n=a5),i||(i=null),e=Mp.resolve(e);try{o.mkdirSync(e,n),i=i||e}catch(a){switch(a.code){case"ENOENT":i=r(Mp.dirname(e),t,i),r(e,t,i);break;default:var s;try{s=o.statSync(e)}catch(l){throw a}if(!s.isDirectory())throw a;break}}return i}});var p5=v((lLe,u5)=>{var xve=require("fs"),c5=require("path"),Dve=require("util"),Sve=l5(),f5=require("stream").Transform,Eve=iE();function ss(r){if(!(this instanceof ss))return new ss(r);f5.call(this),this.opts=r||{},this.unzipStream=new Eve(this.opts),this.unfinishedEntries=0,this.afterFlushWait=!1,this.createdDirectories={};var e=this;this.unzipStream.on("entry",this._processEntry.bind(this)),this.unzipStream.on("error",function(t){e.emit("error",t)})}Dve.inherits(ss,f5);ss.prototype._transform=function(r,e,t){this.unzipStream.write(r,e,t)};ss.prototype._flush=function(r){var e=this,t=function(){process.nextTick(function(){e.emit("close")}),r()};this.unzipStream.end(function(){if(e.unfinishedEntries>0)return e.afterFlushWait=!0,e.on("await-finished",t);t()})};ss.prototype._processEntry=function(r){var e=this,t=c5.join(this.opts.path,r.path),i=r.isDirectory?t:c5.dirname(t);this.unfinishedEntries++;var n=function(){var o=xve.createWriteStream(t);o.on("close",function(){e.unfinishedEntries--,e._notifyAwaiter()}),o.on("error",function(s){e.emit("error",s)}),r.pipe(o)};if(this.createdDirectories[i]||i===".")return n();Sve(i,function(o){if(o)return e.emit("error",o);if(e.createdDirectories[i]=!0,r.isDirectory){e.unfinishedEntries--,e._notifyAwaiter();return}n()})};ss.prototype._notifyAwaiter=function(){this.afterFlushWait&&this.unfinishedEntries===0&&(this.emit("await-finished"),this.afterFlushWait=!1)};u5.exports=ss});var d5=v(nE=>{"use strict";nE.Parse=n5();nE.Extract=p5()});var m5=v((cLe,h5)=>{"use strict";function Cve(){}function cv(r,e){let t=cv.spread(r,e),i=t.then(n=>n[0]);return i.cancel=t.cancel,i}(function(r){function e(t,i){let n=null,o=new Promise((s,a)=>{function l(){t.removeListener(i,u),t.removeListener("error",c),o.cancel=Cve}function u(...f){l(),s(f)}function c(f){l(),a(f)}n=l,t.on(i,u),t.on("error",c)});if(!n)throw new TypeError("Could not get `cancel()` function");return o.cancel=n,o}r.spread=e})(cv||(cv={}));h5.exports=cv});var g5=v(oE=>{"use strict";Object.defineProperty(oE,"__esModule",{value:!0});function _ve(r){return function(e,t){return new Promise((i,n)=>{r.call(this,e,t,(o,s)=>{o?n(o):i(s)})})}}oE.default=_ve});var lE=v((sE,v5)=>{"use strict";var y5=sE&&sE.__importDefault||function(r){return r&&r.__esModule?r:{default:r}},Pve=require("events"),Tve=y5(vt()),Rve=y5(g5()),Np=Tve.default("agent-base");function kve(r){return Boolean(r)&&typeof r.addRequest=="function"}function aE(){let{stack:r}=new Error;return typeof r!="string"?!1:r.split(` -`).some(e=>e.indexOf("(https.js:")!==-1||e.indexOf("node:https:")!==-1)}function fv(r,e){return new fv.Agent(r,e)}(function(r){class e extends Pve.EventEmitter{constructor(i,n){super();let o=n;typeof i=="function"?this.callback=i:i&&(o=i),this.timeout=null,o&&typeof o.timeout=="number"&&(this.timeout=o.timeout),this.maxFreeSockets=1,this.maxSockets=1,this.maxTotalSockets=Infinity,this.sockets={},this.freeSockets={},this.requests={},this.options={}}get defaultPort(){return typeof this.explicitDefaultPort=="number"?this.explicitDefaultPort:aE()?443:80}set defaultPort(i){this.explicitDefaultPort=i}get protocol(){return typeof this.explicitProtocol=="string"?this.explicitProtocol:aE()?"https:":"http:"}set protocol(i){this.explicitProtocol=i}callback(i,n,o){throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`')}addRequest(i,n){let o=Object.assign({},n);typeof o.secureEndpoint!="boolean"&&(o.secureEndpoint=aE()),o.host==null&&(o.host="localhost"),o.port==null&&(o.port=o.secureEndpoint?443:80),o.protocol==null&&(o.protocol=o.secureEndpoint?"https:":"http:"),o.host&&o.path&&delete o.path,delete o.agent,delete o.hostname,delete o._defaultAgent,delete o.defaultPort,delete o.createConnection,i._last=!0,i.shouldKeepAlive=!1;let s=!1,a=null,l=o.timeout||this.timeout,u=d=>{i._hadError||(i.emit("error",d),i._hadError=!0)},c=()=>{a=null,s=!0;let d=new Error(`A "socket" was not created for HTTP request before ${l}ms`);d.code="ETIMEOUT",u(d)},f=d=>{s||(a!==null&&(clearTimeout(a),a=null),u(d))},p=d=>{if(s)return;if(a!=null&&(clearTimeout(a),a=null),kve(d)){Np("Callback returned another Agent instance %o",d.constructor.name),d.addRequest(i,o);return}if(d){d.once("free",()=>{this.freeSocket(d,o)}),i.onSocket(d);return}let h=new Error(`no Duplex stream was returned to agent-base for \`${i.method} ${i.path}\``);u(h)};if(typeof this.callback!="function"){u(new Error("`callback` is not defined"));return}this.promisifiedCallback||(this.callback.length>=3?(Np("Converting legacy callback function to promise"),this.promisifiedCallback=Rve.default(this.callback)):this.promisifiedCallback=this.callback),typeof l=="number"&&l>0&&(a=setTimeout(c,l)),"port"in o&&typeof o.port!="number"&&(o.port=Number(o.port));try{Np("Resolving socket for %o request: %o",o.protocol,`${i.method} ${i.path}`),Promise.resolve(this.promisifiedCallback(i,o)).then(p,f)}catch(d){Promise.reject(d).catch(f)}}freeSocket(i,n){Np("Freeing socket %o %o",i.constructor.name,n),i.destroy()}destroy(){Np("Destroying agent %o",this.constructor.name)}}r.Agent=e,r.prototype=r.Agent.prototype})(fv||(fv={}));v5.exports=fv});var w5=v(xa=>{"use strict";var Ive=xa&&xa.__awaiter||function(r,e,t,i){function n(o){return o instanceof t?o:new t(function(s){s(o)})}return new(t||(t=Promise))(function(o,s){function a(c){try{u(i.next(c))}catch(f){s(f)}}function l(c){try{u(i.throw(c))}catch(f){s(f)}}function u(c){c.done?o(c.value):n(c.value).then(a,l)}u((i=i.apply(r,e||[])).next())})},qp=xa&&xa.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(xa,"__esModule",{value:!0});var Fve=qp(require("net")),Ave=qp(require("tls")),uE=qp(require("url")),Ove=qp(vt()),Lve=qp(m5()),Mve=lE(),as=Ove.default("http-proxy-agent");function Nve(r){return typeof r=="string"?/^https:?$/i.test(r):!1}var b5=class extends Mve.Agent{constructor(e){let t;if(typeof e=="string"?t=uE.default.parse(e):t=e,!t)throw new Error("an HTTP(S) proxy server `host` and `port` must be specified!");as("Creating new HttpProxyAgent instance: %o",t),super(t);let i=Object.assign({},t);this.secureProxy=t.secureProxy||Nve(i.protocol),i.host=i.hostname||i.host,typeof i.port=="string"&&(i.port=parseInt(i.port,10)),!i.port&&i.host&&(i.port=this.secureProxy?443:80),i.host&&i.path&&(delete i.path,delete i.pathname),this.proxy=i}callback(e,t){return Ive(this,void 0,void 0,function*(){let{proxy:i,secureProxy:n}=this,o=uE.default.parse(e.path);o.protocol||(o.protocol="http:"),o.hostname||(o.hostname=t.hostname||t.host||null),o.port==null&&typeof t.port&&(o.port=String(t.port)),o.port==="80"&&delete o.port,e.path=uE.default.format(o),i.auth&&e.setHeader("Proxy-Authorization",`Basic ${Buffer.from(i.auth).toString("base64")}`);let s;if(n?(as("Creating `tls.Socket`: %o",i),s=Ave.default.connect(i)):(as("Creating `net.Socket`: %o",i),s=Fve.default.connect(i)),e._header){let a,l;as("Regenerating stored HTTP header string for request"),e._header=null,e._implicitHeader(),e.output&&e.output.length>0?(as("Patching connection write() output buffer with updated header"),a=e.output[0],l=a.indexOf(`\r -\r -`)+4,e.output[0]=e._header+a.substring(l),as("Output buffer: %o",e.output)):e.outputData&&e.outputData.length>0&&(as("Patching connection write() output buffer with updated header"),a=e.outputData[0].data,l=a.indexOf(`\r -\r -`)+4,e.outputData[0].data=e._header+a.substring(l),as("Output buffer: %o",e.outputData[0].data))}return yield Lve.default(s,"connect"),s})}};xa.default=b5});var D5=v((cE,x5)=>{"use strict";var qve=cE&&cE.__importDefault||function(r){return r&&r.__esModule?r:{default:r}},fE=qve(w5());function pE(r){return new fE.default(r)}(function(r){r.HttpProxyAgent=fE.default,r.prototype=fE.default.prototype})(pE||(pE={}));x5.exports=pE});var S5=v($p=>{"use strict";var $ve=$p&&$p.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty($p,"__esModule",{value:!0});var Bve=$ve(vt()),Bp=Bve.default("https-proxy-agent:parse-proxy-response");function jve(r){return new Promise((e,t)=>{let i=0,n=[];function o(){let f=r.read();f?c(f):r.once("readable",o)}function s(){r.removeListener("end",l),r.removeListener("error",u),r.removeListener("close",a),r.removeListener("readable",o)}function a(f){Bp("onclose had error %o",f)}function l(){Bp("onend")}function u(f){s(),Bp("onerror %o",f),t(f)}function c(f){n.push(f),i+=f.length;let p=Buffer.concat(n,i);if(p.indexOf(`\r -\r -`)===-1){Bp("have not received end of HTTP headers yet..."),o();return}let h=p.toString("ascii",0,p.indexOf(`\r -`)),m=+h.split(" ")[1];Bp("got proxy server response: %o",h),e({statusCode:m,buffered:p})}r.on("error",u),r.on("close",a),r.on("end",l),o()})}$p.default=jve});var P5=v(Da=>{"use strict";var Uve=Da&&Da.__awaiter||function(r,e,t,i){function n(o){return o instanceof t?o:new t(function(s){s(o)})}return new(t||(t=Promise))(function(o,s){function a(c){try{u(i.next(c))}catch(f){s(f)}}function l(c){try{u(i.throw(c))}catch(f){s(f)}}function u(c){c.done?o(c.value):n(c.value).then(a,l)}u((i=i.apply(r,e||[])).next())})},Tu=Da&&Da.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(Da,"__esModule",{value:!0});var E5=Tu(require("net")),C5=Tu(require("tls")),Wve=Tu(require("url")),Hve=Tu(require("assert")),zve=Tu(vt()),Gve=lE(),Vve=Tu(S5()),jp=zve.default("https-proxy-agent:agent"),_5=class extends Gve.Agent{constructor(e){let t;if(typeof e=="string"?t=Wve.default.parse(e):t=e,!t)throw new Error("an HTTP(S) proxy server `host` and `port` must be specified!");jp("creating new HttpsProxyAgent instance: %o",t),super(t);let i=Object.assign({},t);this.secureProxy=t.secureProxy||Yve(i.protocol),i.host=i.hostname||i.host,typeof i.port=="string"&&(i.port=parseInt(i.port,10)),!i.port&&i.host&&(i.port=this.secureProxy?443:80),this.secureProxy&&!("ALPNProtocols"in i)&&(i.ALPNProtocols=["http 1.1"]),i.host&&i.path&&(delete i.path,delete i.pathname),this.proxy=i}callback(e,t){return Uve(this,void 0,void 0,function*(){let{proxy:i,secureProxy:n}=this,o;n?(jp("Creating `tls.Socket`: %o",i),o=C5.default.connect(i)):(jp("Creating `net.Socket`: %o",i),o=E5.default.connect(i));let s=Object.assign({},i.headers),l=`CONNECT ${`${t.host}:${t.port}`} HTTP/1.1\r -`;i.auth&&(s["Proxy-Authorization"]=`Basic ${Buffer.from(i.auth).toString("base64")}`);let{host:u,port:c,secureEndpoint:f}=t;Jve(c,f)||(u+=`:${c}`),s.Host=u,s.Connection="close";for(let y of Object.keys(s))l+=`${y}: ${s[y]}\r -`;let p=Vve.default(o);o.write(`${l}\r -`);let{statusCode:d,buffered:h}=yield p;if(d===200){if(e.once("socket",Kve),t.secureEndpoint){let y=t.servername||t.host;if(!y)throw new Error('Could not determine "servername"');return jp("Upgrading socket connection to TLS"),C5.default.connect(Object.assign(Object.assign({},Xve(t,"host","hostname","path","port")),{socket:o,servername:y}))}return o}o.destroy();let m=new E5.default.Socket;return m.readable=!0,e.once("socket",y=>{jp("replaying proxy buffer for failed request"),Hve.default(y.listenerCount("data")>0),y.push(h),y.push(null)}),m})}};Da.default=_5;function Kve(r){r.resume()}function Jve(r,e){return Boolean(!e&&r===80||e&&r===443)}function Yve(r){return typeof r=="string"?/^https:?$/i.test(r):!1}function Xve(r,...e){let t={},i;for(i in r)e.includes(i)||(t[i]=r[i]);return t}});var R5=v((dE,T5)=>{"use strict";var Zve=dE&&dE.__importDefault||function(r){return r&&r.__esModule?r:{default:r}},hE=Zve(P5());function mE(r){return new hE.default(r)}(function(r){r.HttpsProxyAgent=hE.default,r.prototype=hE.default.prototype})(mE||(mE={}));T5.exports=mE});var I5=v((mLe,k5)=>{"use strict";var Qve=["aborted","complete","headers","httpVersion","httpVersionMinor","httpVersionMajor","method","rawHeaders","rawTrailers","setTimeout","socket","statusCode","statusMessage","trailers","url"];k5.exports=(r,e)=>{if(e._readableState.autoDestroy)throw new Error("The second stream must have the `autoDestroy` option set to `false`");let t=new Set(Object.keys(r).concat(Qve)),i={};for(let n of t)n in e||(i[n]={get(){let o=r[n];return typeof o=="function"?o.bind(r):o},set(o){r[n]=o},enumerable:!0,configurable:!1});return Object.defineProperties(e,i),r.once("aborted",()=>{e.destroy(),e.emit("aborted")}),r.once("close",()=>{r.complete&&e.readable?e.once("end",()=>{e.emit("close")}):e.emit("close")}),e}});var A5=v((gLe,F5)=>{"use strict";var{Transform:eye,PassThrough:tye}=require("stream"),gE=require("zlib"),rye=I5();F5.exports=r=>{let e=(r.headers["content-encoding"]||"").toLowerCase();if(!["gzip","deflate","br"].includes(e))return r;let t=e==="br";if(t&&typeof gE.createBrotliDecompress!="function")return r.destroy(new Error("Brotli is not supported on Node.js < 12")),r;let i=!0,n=new eye({transform(a,l,u){i=!1,u(null,a)},flush(a){a()}}),o=new tye({autoDestroy:!1,destroy(a,l){r.destroy(),l(a)}}),s=t?gE.createBrotliDecompress():gE.createUnzip();return s.once("error",a=>{if(i&&!r.readable){o.end();return}o.destroy(a)}),rye(r,o),r.pipe(n).pipe(s).pipe(o),o}});var Hz=v(Vye=>{ho(Vye,{BaseLanguageClient:()=>xv,BasicList:()=>Nt,Buffer:()=>qu.Buffer,CancellationToken:()=>ie.CancellationToken,CancellationTokenSource:()=>ie.CancellationTokenSource,ClientState:()=>be,CloseAction:()=>no,CodeActionKind:()=>ie.CodeActionKind,CompletionItemKind:()=>ie.CompletionItemKind,CompletionTriggerKind:()=>ie.CompletionTriggerKind,ConfigurationTarget:()=>dt,Diagnostic:()=>ie.Diagnostic,DiagnosticSeverity:()=>ie.DiagnosticSeverity,DiagnosticTag:()=>ie.DiagnosticTag,Disposable:()=>ie.Disposable,Document:()=>rg,DocumentHighlightKind:()=>ie.DocumentHighlightKind,Emitter:()=>ie.Emitter,ErrorAction:()=>Fu,Event:()=>ie.Event,ExtensionType:()=>Yr,FileChangeType:()=>ie.FileChangeType,FileSystemWatcher:()=>og,FloatFactory:()=>mn,Highligher:()=>ls,InsertTextFormat:()=>ie.InsertTextFormat,LanguageClient:()=>Tv,Location:()=>ie.Location,LocationLink:()=>ie.LocationLink,MarkupKind:()=>ie.MarkupKind,MessageLevel:()=>gn,MessageTransports:()=>Vp,Mru:()=>Jl,Mutex:()=>ar,Neovim:()=>qu.Neovim,NotificationType:()=>ie.NotificationType,NotificationType0:()=>ie.NotificationType0,NullLogger:()=>iH,PatternType:()=>Jr,Position:()=>ie.Position,ProgressType:()=>Wz.ProgressType,ProposedFeatures:()=>Rv,Range:()=>ie.Range,RequestType:()=>ie.RequestType,RequestType0:()=>ie.RequestType0,RevealOutputChannelOn:()=>ii,ServiceStat:()=>ye,SettingMonitor:()=>jH,SignatureHelpTriggerKind:()=>ie.SignatureHelpTriggerKind,SourceType:()=>Xr,State:()=>ni,SymbolKind:()=>ie.SymbolKind,TextDocumentFeature:()=>Ve,TextEdit:()=>ie.TextEdit,TransportKind:()=>Gt,Uri:()=>$,Watchman:()=>ia,Window:()=>qu.Window,ansiparse:()=>jf,commands:()=>me,concurrent:()=>xf,diagnosticManager:()=>mt,disposeAll:()=>z,download:()=>Wp,events:()=>A,executable:()=>wf,extensions:()=>ge,fetch:()=>Ru,isRunning:()=>dq,languages:()=>B,listManager:()=>Kt,runCommand:()=>hn,services:()=>Vt,snippetManager:()=>At,sources:()=>Ge,wait:()=>He,watchFile:()=>Rl,window:()=>C,workspace:()=>b});var qu=S(qw()),ie=S(W()),Wz=S(bi())});var i9=v(Qye=>{ho(Qye,{default:()=>ebe,regist:()=>tbe});var r9=S(W()),uHe=U()("source-around"),Bv=class extends Tn{constructor(){super({name:"around",filepath:__filename})}doComplete(e){let{bufnr:t,input:i}=e;if(i.length===0)return null;let n=b.getDocument(t);if(!n)return null;let o=n.words,s=n.getMoreWords();return o.push(...s),o=this.filterWords(o,e),Promise.resolve({items:o.map(a=>({word:a,menu:this.menu}))})}},ebe=Bv;function tbe(r){return r.set("around",new Bv),r9.Disposable.create(()=>{r.delete("around")})}});var o9=v(rbe=>{ho(rbe,{default:()=>ibe,regist:()=>nbe});var n9=S(W()),dHe=U()("source-buffer"),jv=class extends Tn{constructor(){super({name:"buffer",filepath:__filename})}get ignoreGitignore(){return this.getConfig("ignoreGitignore",!0)}getWords(e){let{ignoreGitignore:t}=this,i=[];return b.documents.forEach(n=>{if(n.bufnr!=e&&!(t&&n.isIgnored))for(let o of n.words)i.includes(o)||i.push(o)}),i}doComplete(e){let{bufnr:t,input:i}=e;if(i.length==0)return null;let n=this.getWords(t);return n=this.filterWords(n,e),Promise.resolve({items:n.map(o=>({word:o,menu:this.menu}))})}},ibe=jv;function nbe(r){return r.set("buffer",new jv),n9.Disposable.create(()=>{r.delete("buffer")})}});var u9=v(obe=>{ho(obe,{default:()=>lbe,regist:()=>ube});var Uv=S(require("fs")),s9=S(ta()),oi=S(require("path")),a9=S(require("util")),l9=S(W()),sbe=U()("source-file"),abe=/(?:\.{0,2}|~|\$HOME|([\w]+)|)\/(?:[\w.@()-]+\/)*(?:[\w.@()-])*$/,Wv=class extends Tn{constructor(){super({name:"file",filepath:__filename})}resolveEnvVariables(e){let t=e;return t=t.replace(/%([^%]+)%/g,(i,n)=>process.env[n]),t=t.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/gi,(i,n,o)=>process.env[n||o]),t}getPathOption(e){let{line:t,colnr:i}=e,n=Rt(t,0,i-1);if(n=this.resolveEnvVariables(n),!n||n.endsWith("//"))return null;let o=n.match(abe);if(o&&o.length){let s=b.expand(o[0]),a=o[0].match(/[^/]*$/)[0];return{pathstr:s,part:o[1],startcol:i-a.length-1,input:a}}return null}async getFileItem(e,t){let i=oi.default.join(e,t),n=await It(i);if(n){let o=n.isDirectory()?t+"/":t;return{word:t,abbr:o}}return null}filterFiles(e){let t=this.getConfig("ignoreHidden",!0),i=this.getConfig("ignorePatterns",[]);return e.filter(n=>{if(n==null||t&&n.startsWith("."))return!1;for(let o of i)if(s9.default(n,o,{dot:!0}))return!1;return!0})}async getItemsFromRoot(e,t){let i=[],n=e.endsWith("/")?e:oi.default.dirname(e),o=oi.default.isAbsolute(e)?n:oi.default.join(t,n);try{let s=await It(o);if(s&&s.isDirectory()){let a=await a9.default.promisify(Uv.default.readdir)(o);a=this.filterFiles(a);let l=await Promise.all(a.map(u=>this.getFileItem(o,u)));i=i.concat(l)}return i=i.filter(a=>a!=null),i}catch(s){return sbe.error("Error on list files:",s),i}}get trimSameExts(){return this.getConfig("trimSameExts",[])}async doComplete(e){let{col:t,filepath:i}=e,n=this.getPathOption(e);if(!n)return null;let{pathstr:o,part:s,startcol:a,input:l}=n;if(ag.word[0]===y)),{items:h.map(g=>{let w=oi.default.extname(g.word);return g.word=m&&w===f?g.word.replace(f,""):g.word,{word:`${u}${g.word}`,abbr:`${u}${g.abbr}`,menu:this.menu}})}}},lbe=Wv;function ube(r){return r.set("file",new Wv),l9.Disposable.create(()=>{r.delete("file")})}});var lo=v((L9e,F9)=>{"use strict";var hbe=un();F9.exports=hbe.call(Function.call,Object.prototype.hasOwnProperty)});var Yv=v((M9e,A9)=>{"use strict";var we,sd=SyntaxError,mbe=Function,Hu=TypeError,r_=function(r){try{return Function('"use strict"; return ('+r+").constructor;")()}catch(e){}},Ra=Object.getOwnPropertyDescriptor;if(Ra)try{Ra({},"")}catch(r){Ra=null}var i_=function(){throw new Hu},gbe=Ra?function(){try{return arguments.callee,i_}catch(r){try{return Ra(arguments,"callee").get}catch(e){return i_}}}():i_,zu=Li()(),ds=Object.getPrototypeOf||function(r){return r.__proto__},n_=r_("async function* () {}"),o_=n_?n_.prototype:we,O9=o_?o_.prototype:we,vbe=typeof Uint8Array=="undefined"?we:ds(Uint8Array),ad={"%AggregateError%":typeof AggregateError=="undefined"?we:AggregateError,"%Array%":Array,"%ArrayBuffer%":typeof ArrayBuffer=="undefined"?we:ArrayBuffer,"%ArrayIteratorPrototype%":zu?ds([][Symbol.iterator]()):we,"%AsyncFromSyncIteratorPrototype%":we,"%AsyncFunction%":r_("async function () {}"),"%AsyncGenerator%":o_,"%AsyncGeneratorFunction%":n_,"%AsyncIteratorPrototype%":O9?ds(O9):we,"%Atomics%":typeof Atomics=="undefined"?we:Atomics,"%BigInt%":typeof BigInt=="undefined"?we:BigInt,"%Boolean%":Boolean,"%DataView%":typeof DataView=="undefined"?we:DataView,"%Date%":Date,"%decodeURI%":decodeURI,"%decodeURIComponent%":decodeURIComponent,"%encodeURI%":encodeURI,"%encodeURIComponent%":encodeURIComponent,"%Error%":Error,"%eval%":eval,"%EvalError%":EvalError,"%Float32Array%":typeof Float32Array=="undefined"?we:Float32Array,"%Float64Array%":typeof Float64Array=="undefined"?we:Float64Array,"%FinalizationRegistry%":typeof FinalizationRegistry=="undefined"?we:FinalizationRegistry,"%Function%":mbe,"%GeneratorFunction%":r_("function* () {}"),"%Int8Array%":typeof Int8Array=="undefined"?we:Int8Array,"%Int16Array%":typeof Int16Array=="undefined"?we:Int16Array,"%Int32Array%":typeof Int32Array=="undefined"?we:Int32Array,"%isFinite%":isFinite,"%isNaN%":isNaN,"%IteratorPrototype%":zu?ds(ds([][Symbol.iterator]())):we,"%JSON%":typeof JSON=="object"?JSON:we,"%Map%":typeof Map=="undefined"?we:Map,"%MapIteratorPrototype%":typeof Map=="undefined"||!zu?we:ds(new Map()[Symbol.iterator]()),"%Math%":Math,"%Number%":Number,"%Object%":Object,"%parseFloat%":parseFloat,"%parseInt%":parseInt,"%Promise%":typeof Promise=="undefined"?we:Promise,"%Proxy%":typeof Proxy=="undefined"?we:Proxy,"%RangeError%":RangeError,"%ReferenceError%":ReferenceError,"%Reflect%":typeof Reflect=="undefined"?we:Reflect,"%RegExp%":RegExp,"%Set%":typeof Set=="undefined"?we:Set,"%SetIteratorPrototype%":typeof Set=="undefined"||!zu?we:ds(new Set()[Symbol.iterator]()),"%SharedArrayBuffer%":typeof SharedArrayBuffer=="undefined"?we:SharedArrayBuffer,"%String%":String,"%StringIteratorPrototype%":zu?ds(""[Symbol.iterator]()):we,"%Symbol%":zu?Symbol:we,"%SyntaxError%":sd,"%ThrowTypeError%":gbe,"%TypedArray%":vbe,"%TypeError%":Hu,"%Uint8Array%":typeof Uint8Array=="undefined"?we:Uint8Array,"%Uint8ClampedArray%":typeof Uint8ClampedArray=="undefined"?we:Uint8ClampedArray,"%Uint16Array%":typeof Uint16Array=="undefined"?we:Uint16Array,"%Uint32Array%":typeof Uint32Array=="undefined"?we:Uint32Array,"%URIError%":URIError,"%WeakMap%":typeof WeakMap=="undefined"?we:WeakMap,"%WeakRef%":typeof WeakRef=="undefined"?we:WeakRef,"%WeakSet%":typeof WeakSet=="undefined"?we:WeakSet},L9={"%ArrayBufferPrototype%":["ArrayBuffer","prototype"],"%ArrayPrototype%":["Array","prototype"],"%ArrayProto_entries%":["Array","prototype","entries"],"%ArrayProto_forEach%":["Array","prototype","forEach"],"%ArrayProto_keys%":["Array","prototype","keys"],"%ArrayProto_values%":["Array","prototype","values"],"%AsyncFunctionPrototype%":["AsyncFunction","prototype"],"%AsyncGenerator%":["AsyncGeneratorFunction","prototype"],"%AsyncGeneratorPrototype%":["AsyncGeneratorFunction","prototype","prototype"],"%BooleanPrototype%":["Boolean","prototype"],"%DataViewPrototype%":["DataView","prototype"],"%DatePrototype%":["Date","prototype"],"%ErrorPrototype%":["Error","prototype"],"%EvalErrorPrototype%":["EvalError","prototype"],"%Float32ArrayPrototype%":["Float32Array","prototype"],"%Float64ArrayPrototype%":["Float64Array","prototype"],"%FunctionPrototype%":["Function","prototype"],"%Generator%":["GeneratorFunction","prototype"],"%GeneratorPrototype%":["GeneratorFunction","prototype","prototype"],"%Int8ArrayPrototype%":["Int8Array","prototype"],"%Int16ArrayPrototype%":["Int16Array","prototype"],"%Int32ArrayPrototype%":["Int32Array","prototype"],"%JSONParse%":["JSON","parse"],"%JSONStringify%":["JSON","stringify"],"%MapPrototype%":["Map","prototype"],"%NumberPrototype%":["Number","prototype"],"%ObjectPrototype%":["Object","prototype"],"%ObjProto_toString%":["Object","prototype","toString"],"%ObjProto_valueOf%":["Object","prototype","valueOf"],"%PromisePrototype%":["Promise","prototype"],"%PromiseProto_then%":["Promise","prototype","then"],"%Promise_all%":["Promise","all"],"%Promise_reject%":["Promise","reject"],"%Promise_resolve%":["Promise","resolve"],"%RangeErrorPrototype%":["RangeError","prototype"],"%ReferenceErrorPrototype%":["ReferenceError","prototype"],"%RegExpPrototype%":["RegExp","prototype"],"%SetPrototype%":["Set","prototype"],"%SharedArrayBufferPrototype%":["SharedArrayBuffer","prototype"],"%StringPrototype%":["String","prototype"],"%SymbolPrototype%":["Symbol","prototype"],"%SyntaxErrorPrototype%":["SyntaxError","prototype"],"%TypedArrayPrototype%":["TypedArray","prototype"],"%TypeErrorPrototype%":["TypeError","prototype"],"%Uint8ArrayPrototype%":["Uint8Array","prototype"],"%Uint8ClampedArrayPrototype%":["Uint8ClampedArray","prototype"],"%Uint16ArrayPrototype%":["Uint16Array","prototype"],"%Uint32ArrayPrototype%":["Uint32Array","prototype"],"%URIErrorPrototype%":["URIError","prototype"],"%WeakMapPrototype%":["WeakMap","prototype"],"%WeakSetPrototype%":["WeakSet","prototype"]},Vv=un(),Kv=lo(),ybe=Vv.call(Function.call,Array.prototype.concat),bbe=Vv.call(Function.apply,Array.prototype.splice),M9=Vv.call(Function.call,String.prototype.replace),Jv=Vv.call(Function.call,String.prototype.slice),wbe=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g,xbe=/\\(\\)?/g,Dbe=function(e){var t=Jv(e,0,1),i=Jv(e,-1);if(t==="%"&&i!=="%")throw new sd("invalid intrinsic syntax, expected closing `%`");if(i==="%"&&t!=="%")throw new sd("invalid intrinsic syntax, expected opening `%`");var n=[];return M9(e,wbe,function(o,s,a,l){n[n.length]=a?M9(l,xbe,"$1"):s||o}),n},Sbe=function(e,t){var i=e,n;if(Kv(L9,i)&&(n=L9[i],i="%"+n[0]+"%"),Kv(ad,i)){var o=ad[i];if(typeof o=="undefined"&&!t)throw new Hu("intrinsic "+e+" exists, but is not available. Please file an issue!");return{alias:n,name:i,value:o}}throw new sd("intrinsic "+e+" does not exist!")};A9.exports=function(e,t){if(typeof e!="string"||e.length===0)throw new Hu("intrinsic name must be a non-empty string");if(arguments.length>1&&typeof t!="boolean")throw new Hu('"allowMissing" argument must be a boolean');var i=Dbe(e),n=i.length>0?i[0]:"",o=Sbe("%"+n+"%",t),s=o.name,a=o.value,l=!1,u=o.alias;u&&(n=u[0],bbe(i,ybe([0,1],u)));for(var c=1,f=!0;c=i.length){var m=Ra(a,p);f=!!m,f&&"get"in m&&!("originalValue"in m.get)?a=m.get:a=a[p]}else f=Kv(a,p),a=a[p];f&&!l&&(ad[s]=a)}}return a}});var a_=v((N9e,Xv)=>{"use strict";var s_=un(),Zv=Yv(),N9=Zv("%Function.prototype.apply%"),q9=Zv("%Function.prototype.call%"),$9=Zv("%Reflect.apply%",!0)||s_.call(q9,N9),ld=Zv("%Object.defineProperty%",!0);if(ld)try{ld({},"a",{value:1})}catch(r){ld=null}Xv.exports=function(){return $9(s_,q9,arguments)};var B9=function(){return $9(s_,N9,arguments)};ld?ld(Xv.exports,"apply",{value:B9}):Xv.exports.apply=B9});var Oe=v((q9e,j9)=>{"use strict";var De,U9=SyntaxError,Ebe=Function,Gu=TypeError,l_=function(r){try{return Function('"use strict"; return ('+r+").constructor;")()}catch(e){}},ka=Object.getOwnPropertyDescriptor;if(ka)try{ka({},"")}catch(r){ka=null}var u_=function(){throw new Gu},Cbe=ka?function(){try{return arguments.callee,u_}catch(r){try{return ka(arguments,"callee").get}catch(e){return u_}}}():u_,Vu=Li()(),hs=Object.getPrototypeOf||function(r){return r.__proto__},c_=l_("async function* () {}"),f_=c_?c_.prototype:De,W9=f_?f_.prototype:De,_be=typeof Uint8Array=="undefined"?De:hs(Uint8Array),ud={"%AggregateError%":typeof AggregateError=="undefined"?De:AggregateError,"%Array%":Array,"%ArrayBuffer%":typeof ArrayBuffer=="undefined"?De:ArrayBuffer,"%ArrayIteratorPrototype%":Vu?hs([][Symbol.iterator]()):De,"%AsyncFromSyncIteratorPrototype%":De,"%AsyncFunction%":l_("async function () {}"),"%AsyncGenerator%":f_,"%AsyncGeneratorFunction%":c_,"%AsyncIteratorPrototype%":W9?hs(W9):De,"%Atomics%":typeof Atomics=="undefined"?De:Atomics,"%BigInt%":typeof BigInt=="undefined"?De:BigInt,"%Boolean%":Boolean,"%DataView%":typeof DataView=="undefined"?De:DataView,"%Date%":Date,"%decodeURI%":decodeURI,"%decodeURIComponent%":decodeURIComponent,"%encodeURI%":encodeURI,"%encodeURIComponent%":encodeURIComponent,"%Error%":Error,"%eval%":eval,"%EvalError%":EvalError,"%Float32Array%":typeof Float32Array=="undefined"?De:Float32Array,"%Float64Array%":typeof Float64Array=="undefined"?De:Float64Array,"%FinalizationRegistry%":typeof FinalizationRegistry=="undefined"?De:FinalizationRegistry,"%Function%":Ebe,"%GeneratorFunction%":l_("function* () {}"),"%Int8Array%":typeof Int8Array=="undefined"?De:Int8Array,"%Int16Array%":typeof Int16Array=="undefined"?De:Int16Array,"%Int32Array%":typeof Int32Array=="undefined"?De:Int32Array,"%isFinite%":isFinite,"%isNaN%":isNaN,"%IteratorPrototype%":Vu?hs(hs([][Symbol.iterator]())):De,"%JSON%":typeof JSON=="object"?JSON:De,"%Map%":typeof Map=="undefined"?De:Map,"%MapIteratorPrototype%":typeof Map=="undefined"||!Vu?De:hs(new Map()[Symbol.iterator]()),"%Math%":Math,"%Number%":Number,"%Object%":Object,"%parseFloat%":parseFloat,"%parseInt%":parseInt,"%Promise%":typeof Promise=="undefined"?De:Promise,"%Proxy%":typeof Proxy=="undefined"?De:Proxy,"%RangeError%":RangeError,"%ReferenceError%":ReferenceError,"%Reflect%":typeof Reflect=="undefined"?De:Reflect,"%RegExp%":RegExp,"%Set%":typeof Set=="undefined"?De:Set,"%SetIteratorPrototype%":typeof Set=="undefined"||!Vu?De:hs(new Set()[Symbol.iterator]()),"%SharedArrayBuffer%":typeof SharedArrayBuffer=="undefined"?De:SharedArrayBuffer,"%String%":String,"%StringIteratorPrototype%":Vu?hs(""[Symbol.iterator]()):De,"%Symbol%":Vu?Symbol:De,"%SyntaxError%":U9,"%ThrowTypeError%":Cbe,"%TypedArray%":_be,"%TypeError%":Gu,"%Uint8Array%":typeof Uint8Array=="undefined"?De:Uint8Array,"%Uint8ClampedArray%":typeof Uint8ClampedArray=="undefined"?De:Uint8ClampedArray,"%Uint16Array%":typeof Uint16Array=="undefined"?De:Uint16Array,"%Uint32Array%":typeof Uint32Array=="undefined"?De:Uint32Array,"%URIError%":URIError,"%WeakMap%":typeof WeakMap=="undefined"?De:WeakMap,"%WeakRef%":typeof WeakRef=="undefined"?De:WeakRef,"%WeakSet%":typeof WeakSet=="undefined"?De:WeakSet},H9={"%ArrayBufferPrototype%":["ArrayBuffer","prototype"],"%ArrayPrototype%":["Array","prototype"],"%ArrayProto_entries%":["Array","prototype","entries"],"%ArrayProto_forEach%":["Array","prototype","forEach"],"%ArrayProto_keys%":["Array","prototype","keys"],"%ArrayProto_values%":["Array","prototype","values"],"%AsyncFunctionPrototype%":["AsyncFunction","prototype"],"%AsyncGenerator%":["AsyncGeneratorFunction","prototype"],"%AsyncGeneratorPrototype%":["AsyncGeneratorFunction","prototype","prototype"],"%BooleanPrototype%":["Boolean","prototype"],"%DataViewPrototype%":["DataView","prototype"],"%DatePrototype%":["Date","prototype"],"%ErrorPrototype%":["Error","prototype"],"%EvalErrorPrototype%":["EvalError","prototype"],"%Float32ArrayPrototype%":["Float32Array","prototype"],"%Float64ArrayPrototype%":["Float64Array","prototype"],"%FunctionPrototype%":["Function","prototype"],"%Generator%":["GeneratorFunction","prototype"],"%GeneratorPrototype%":["GeneratorFunction","prototype","prototype"],"%Int8ArrayPrototype%":["Int8Array","prototype"],"%Int16ArrayPrototype%":["Int16Array","prototype"],"%Int32ArrayPrototype%":["Int32Array","prototype"],"%JSONParse%":["JSON","parse"],"%JSONStringify%":["JSON","stringify"],"%MapPrototype%":["Map","prototype"],"%NumberPrototype%":["Number","prototype"],"%ObjectPrototype%":["Object","prototype"],"%ObjProto_toString%":["Object","prototype","toString"],"%ObjProto_valueOf%":["Object","prototype","valueOf"],"%PromisePrototype%":["Promise","prototype"],"%PromiseProto_then%":["Promise","prototype","then"],"%Promise_all%":["Promise","all"],"%Promise_reject%":["Promise","reject"],"%Promise_resolve%":["Promise","resolve"],"%RangeErrorPrototype%":["RangeError","prototype"],"%ReferenceErrorPrototype%":["ReferenceError","prototype"],"%RegExpPrototype%":["RegExp","prototype"],"%SetPrototype%":["Set","prototype"],"%SharedArrayBufferPrototype%":["SharedArrayBuffer","prototype"],"%StringPrototype%":["String","prototype"],"%SymbolPrototype%":["Symbol","prototype"],"%SyntaxErrorPrototype%":["SyntaxError","prototype"],"%TypedArrayPrototype%":["TypedArray","prototype"],"%TypeErrorPrototype%":["TypeError","prototype"],"%Uint8ArrayPrototype%":["Uint8Array","prototype"],"%Uint8ClampedArrayPrototype%":["Uint8ClampedArray","prototype"],"%Uint16ArrayPrototype%":["Uint16Array","prototype"],"%Uint32ArrayPrototype%":["Uint32Array","prototype"],"%URIErrorPrototype%":["URIError","prototype"],"%WeakMapPrototype%":["WeakMap","prototype"],"%WeakSetPrototype%":["WeakSet","prototype"]},p_=un(),Qv=lo(),Pbe=p_.call(Function.call,Array.prototype.concat),Tbe=p_.call(Function.apply,Array.prototype.splice),z9=p_.call(Function.call,String.prototype.replace),Rbe=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g,kbe=/\\(\\)?/g,Ibe=function(e){var t=[];return z9(e,Rbe,function(i,n,o,s){t[t.length]=o?z9(s,kbe,"$1"):n||i}),t},Fbe=function(e,t){var i=e,n;if(Qv(H9,i)&&(n=H9[i],i="%"+n[0]+"%"),Qv(ud,i)){var o=ud[i];if(typeof o=="undefined"&&!t)throw new Gu("intrinsic "+e+" exists, but is not available. Please file an issue!");return{alias:n,name:i,value:o}}throw new U9("intrinsic "+e+" does not exist!")};j9.exports=function(e,t){if(typeof e!="string"||e.length===0)throw new Gu("intrinsic name must be a non-empty string");if(arguments.length>1&&typeof t!="boolean")throw new Gu('"allowMissing" argument must be a boolean');var i=Ibe(e),n=i.length>0?i[0]:"",o=Fbe("%"+n+"%",t),s=o.name,a=o.value,l=!1,u=o.alias;u&&(n=u[0],Tbe(i,Pbe([0,1],u)));for(var c=1,f=!0;c=i.length){var d=ka(a,p);if(f=!!d,!t&&!(p in a))throw new Gu("base intrinsic for "+e+" exists, but the property is not available.");f&&"get"in d&&!("originalValue"in d.get)?a=d.get:a=a[p]}else f=Qv(a,p),a=a[p];f&&!l&&(ud[s]=a)}}return a}});var h_=v(($9e,ey)=>{"use strict";var d_=un(),ty=Oe(),G9=ty("%Function.prototype.apply%"),V9=ty("%Function.prototype.call%"),K9=ty("%Reflect.apply%",!0)||d_.call(V9,G9),cd=ty("%Object.defineProperty%",!0);if(cd)try{cd({},"a",{value:1})}catch(r){cd=null}ey.exports=function(){return K9(d_,V9,arguments)};var J9=function(){return K9(d_,G9,arguments)};cd?cd(ey.exports,"apply",{value:J9}):ey.exports.apply=J9});var Ia=v((B9e,Y9)=>{"use strict";var X9=Oe(),Z9=h_(),Abe=Z9(X9("String.prototype.indexOf"));Y9.exports=function(e,t){var i=X9(e,!!t);return typeof i=="function"&&Abe(e,".prototype.")?Z9(i):i}});var m_=v((j9e,Q9)=>{"use strict";var Obe=Oe(),Lbe=Ia(),Mbe=Obe("%Reflect.apply%",!0)||Lbe("%Function.prototype.apply%");Q9.exports=function(e,t){var i=arguments.length>2?arguments[2]:[];return Mbe(e,t,i)}});var t7=v((U9e,e7)=>{e7.exports=require("util").inspect});var E_=v((W9e,r7)=>{var g_=typeof Map=="function"&&Map.prototype,v_=Object.getOwnPropertyDescriptor&&g_?Object.getOwnPropertyDescriptor(Map.prototype,"size"):null,ry=g_&&v_&&typeof v_.get=="function"?v_.get:null,Nbe=g_&&Map.prototype.forEach,y_=typeof Set=="function"&&Set.prototype,b_=Object.getOwnPropertyDescriptor&&y_?Object.getOwnPropertyDescriptor(Set.prototype,"size"):null,iy=y_&&b_&&typeof b_.get=="function"?b_.get:null,qbe=y_&&Set.prototype.forEach,$be=typeof WeakMap=="function"&&WeakMap.prototype,fd=$be?WeakMap.prototype.has:null,Bbe=typeof WeakSet=="function"&&WeakSet.prototype,pd=Bbe?WeakSet.prototype.has:null,jbe=Boolean.prototype.valueOf,Ube=Object.prototype.toString,Wbe=Function.prototype.toString,Hbe=String.prototype.match,zbe=typeof BigInt=="function"?BigInt.prototype.valueOf:null,i7=Object.getOwnPropertySymbols,Gbe=typeof Symbol=="function"?Symbol.prototype.toString:null,Vbe=Object.prototype.propertyIsEnumerable,w_=t7().custom,x_=w_&&n7(w_)?w_:null;r7.exports=function r(e,t,i,n){var o=t||{};if(Fa(o,"quoteStyle")&&o.quoteStyle!=="single"&&o.quoteStyle!=="double")throw new TypeError('option "quoteStyle" must be "single" or "double"');if(Fa(o,"maxStringLength")&&(typeof o.maxStringLength=="number"?o.maxStringLength<0&&o.maxStringLength!==Infinity:o.maxStringLength!==null))throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');var s=Fa(o,"customInspect")?o.customInspect:!0;if(typeof s!="boolean")throw new TypeError('option "customInspect", if provided, must be `true` or `false`');if(Fa(o,"indent")&&o.indent!==null&&o.indent!==" "&&!(parseInt(o.indent,10)===o.indent&&o.indent>0))throw new TypeError('options "indent" must be "\\t", an integer > 0, or `null`');if(typeof e=="undefined")return"undefined";if(e===null)return"null";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="string")return a7(e,o);if(typeof e=="number")return e===0?Infinity/e>0?"0":"-0":String(e);if(typeof e=="bigint")return String(e)+"n";var a=typeof o.depth=="undefined"?5:o.depth;if(typeof i=="undefined"&&(i=0),i>=a&&a>0&&typeof e=="object")return D_(e)?"[Array]":"[Object]";var l=uwe(o,i);if(typeof n=="undefined")n=[];else if(s7(n,e)>=0)return"[Circular]";function u(P,k,_){if(k&&(n=n.slice(),n.push(k)),_){var L={depth:o.depth};return Fa(o,"quoteStyle")&&(L.quoteStyle=o.quoteStyle),r(P,L,i+1,n)}return r(P,o,i+1,n)}if(typeof e=="function"){var c=rwe(e),f=ny(e,u);return"[Function"+(c?": "+c:" (anonymous)")+"]"+(f.length>0?" { "+f.join(", ")+" }":"")}if(n7(e)){var p=Gbe.call(e);return typeof e=="object"?dd(p):p}if(awe(e)){for(var d="<"+String(e.nodeName).toLowerCase(),h=e.attributes||[],m=0;m",d}if(D_(e)){if(e.length===0)return"[]";var y=ny(e,u);return l&&!lwe(y)?"["+S_(y,l)+"]":"[ "+y.join(", ")+" ]"}if(Xbe(e)){var g=ny(e,u);return g.length===0?"["+String(e)+"]":"{ ["+String(e)+"] "+g.join(", ")+" }"}if(typeof e=="object"&&s){if(x_&&typeof e[x_]=="function")return e[x_]();if(typeof e.inspect=="function")return e.inspect()}if(iwe(e)){var w=[];return Nbe.call(e,function(P,k){w.push(u(k,e,!0)+" => "+u(P,e))}),u7("Map",ry.call(e),w,l)}if(owe(e)){var x=[];return qbe.call(e,function(P){x.push(u(P,e))}),u7("Set",iy.call(e),x,l)}if(nwe(e))return l7("WeakMap");if(swe(e))return l7("WeakSet");if(Qbe(e))return dd(u(Number(e)));if(ewe(e))return dd(u(zbe.call(e)));if(twe(e))return dd(jbe.call(e));if(Zbe(e))return dd(u(String(e)));if(!Jbe(e)&&!Ybe(e)){var E=ny(e,u);return E.length===0?"{}":l?"{"+S_(E,l)+"}":"{ "+E.join(", ")+" }"}return String(e)};function o7(r,e,t){var i=(t.quoteStyle||e)==="double"?'"':"'";return i+r+i}function Kbe(r){return String(r).replace(/"/g,""")}function D_(r){return uo(r)==="[object Array]"}function Jbe(r){return uo(r)==="[object Date]"}function Ybe(r){return uo(r)==="[object RegExp]"}function Xbe(r){return uo(r)==="[object Error]"}function n7(r){return uo(r)==="[object Symbol]"}function Zbe(r){return uo(r)==="[object String]"}function Qbe(r){return uo(r)==="[object Number]"}function ewe(r){return uo(r)==="[object BigInt]"}function twe(r){return uo(r)==="[object Boolean]"}var cwe=Object.prototype.hasOwnProperty||function(r){return r in this};function Fa(r,e){return cwe.call(r,e)}function uo(r){return Ube.call(r)}function rwe(r){if(r.name)return r.name;var e=Hbe.call(Wbe.call(r),/^function\s*([\w$]+)/);return e?e[1]:null}function s7(r,e){if(r.indexOf)return r.indexOf(e);for(var t=0,i=r.length;te.maxStringLength){var t=r.length-e.maxStringLength,i="... "+t+" more character"+(t>1?"s":"");return a7(r.slice(0,e.maxStringLength),e)+i}var n=r.replace(/(['\\])/g,"\\$1").replace(/[\x00-\x1f]/g,fwe);return o7(n,"single",e)}function fwe(r){var e=r.charCodeAt(0),t={8:"b",9:"t",10:"n",12:"f",13:"r"}[e];return t?"\\"+t:"\\x"+(e<16?"0":"")+e.toString(16).toUpperCase()}function dd(r){return"Object("+r+")"}function l7(r){return r+" { ? }"}function u7(r,e,t,i){var n=i?S_(t,i):t.join(", ");return r+" ("+e+") {"+n+"}"}function lwe(r){for(var e=0;e=0)return!1;return!0}function uwe(r,e){var t;if(r.indent===" ")t=" ";else if(typeof r.indent=="number"&&r.indent>0)t=Array(r.indent+1).join(" ");else return null;return{base:t,prev:Array(e+1).join(t)}}function S_(r,e){if(r.length===0)return"";var t=` -`+e.prev+e.base;return t+r.join(","+t)+` -`+e.prev}function ny(r,e){var t=D_(r),i=[];if(t){i.length=r.length;for(var n=0;n{"use strict";c7.exports=function(e){return typeof e=="string"||typeof e=="symbol"}});var p7=v((z9e,f7)=>{"use strict";f7.exports=function(e){if(e===null)return"Null";if(typeof e=="undefined")return"Undefined";if(typeof e=="function"||typeof e=="object")return"Object";if(typeof e=="number")return"Number";if(typeof e=="boolean")return"Boolean";if(typeof e=="string")return"String"}});var dr=v((G9e,d7)=>{"use strict";var pwe=p7();d7.exports=function(e){return typeof e=="symbol"?"Symbol":typeof e=="bigint"?"BigInt":pwe(e)}});var hd=v((V9e,h7)=>{"use strict";var dwe=Oe(),m7=dwe("%TypeError%"),hwe=E_(),mwe=Ku(),gwe=dr();h7.exports=function(e,t){if(gwe(e)!=="Object")throw new m7("Assertion failed: Type(O) is not Object");if(!mwe(t))throw new m7("Assertion failed: IsPropertyKey(P) is not true, got "+hwe(t));return e[t]}});var v7=v((K9e,g7)=>{"use strict";var vwe=Oe(),ywe=vwe("%TypeError%");g7.exports=function(e,t){if(e==null)throw new ywe(t||"Cannot call method on "+e);return e}});var C_=v((J9e,y7)=>{"use strict";y7.exports=v7()});var w7=v((Y9e,b7)=>{"use strict";var bwe=Oe(),wwe=bwe("%Object%"),xwe=C_();b7.exports=function(e){return xwe(e),wwe(e)}});var D7=v((X9e,x7)=>{"use strict";var Dwe=Oe(),Swe=Dwe("%TypeError%"),Ewe=Ku(),Cwe=w7();x7.exports=function(e,t){if(!Ewe(t))throw new Swe("Assertion failed: IsPropertyKey(P) is not true");var i=Cwe(e);return i[t]}});var C7=v((Z9e,S7)=>{"use strict";var E7=Function.prototype.toString,Ju=typeof Reflect=="object"&&Reflect!==null&&Reflect.apply,__,oy;if(typeof Ju=="function"&&typeof Object.defineProperty=="function")try{__=Object.defineProperty({},"length",{get:function(){throw oy}}),oy={},Ju(function(){throw 42},null,__)}catch(r){r!==oy&&(Ju=null)}else Ju=null;var _we=/^\s*class\b/,P_=function(e){try{var t=E7.call(e);return _we.test(t)}catch(i){return!1}},Pwe=function(e){try{return P_(e)?!1:(E7.call(e),!0)}catch(t){return!1}},Twe=Object.prototype.toString,Rwe="[object Function]",kwe="[object GeneratorFunction]",Iwe=typeof Symbol=="function"&&typeof Symbol.toStringTag=="symbol";S7.exports=Ju?function(e){if(!e||typeof e!="function"&&typeof e!="object")return!1;if(typeof e=="function"&&!e.prototype)return!0;try{Ju(e,null,__)}catch(t){if(t!==oy)return!1}return!P_(e)}:function(e){if(!e||typeof e!="function"&&typeof e!="object")return!1;if(typeof e=="function"&&!e.prototype)return!0;if(Iwe)return Pwe(e);if(P_(e))return!1;var t=Twe.call(e);return t===Rwe||t===kwe}});var sy=v((Q9e,_7)=>{"use strict";_7.exports=C7()});var R7=v((e7e,P7)=>{"use strict";var Fwe=Oe(),T7=Fwe("%TypeError%"),Awe=D7(),Owe=sy(),Lwe=Ku();P7.exports=function(e,t){if(!Lwe(t))throw new T7("Assertion failed: IsPropertyKey(P) is not true");var i=Awe(e,t);if(i!=null){if(!Owe(i))throw new T7(t+"is not a function");return i}}});var O7=v((t7e,k7)=>{"use strict";var Mwe=Li()(),I7=Mwe&&typeof Symbol.toStringTag=="symbol",F7,A7,T_,R_;I7&&(F7=Function.call.bind(Object.prototype.hasOwnProperty),A7=Function.call.bind(RegExp.prototype.exec),T_={},ay=function(){throw T_},R_={toString:ay,valueOf:ay},typeof Symbol.toPrimitive=="symbol"&&(R_[Symbol.toPrimitive]=ay));var ay,Nwe=Object.prototype.toString,qwe=Object.getOwnPropertyDescriptor,$we="[object RegExp]";k7.exports=I7?function(e){if(!e||typeof e!="object")return!1;var t=qwe(e,"lastIndex"),i=t&&F7(t,"value");if(!i)return!1;try{A7(e,R_)}catch(n){return n===T_}}:function(e){return!e||typeof e!="object"&&typeof e!="function"?!1:Nwe.call(e)===$we}});var k_=v((r7e,L7)=>{"use strict";L7.exports=function(e){return!!e}});var q7=v((i7e,M7)=>{"use strict";var Bwe=Oe(),N7=Bwe("%Symbol.match%",!0),jwe=O7(),Uwe=k_();M7.exports=function(e){if(!e||typeof e!="object")return!1;if(N7){var t=e[N7];if(typeof t!="undefined")return Uwe(t)}return jwe(e)}});var ly=v((n7e,$7)=>{"use strict";var B7=Oe(),Wwe=B7("%String%"),Hwe=B7("%TypeError%");$7.exports=function(e){if(typeof e=="symbol")throw new Hwe("Cannot convert a Symbol value to a string");return Wwe(e)}});var I_=v((o7e,j7)=>{"use strict";var U7=Yv(),W7=a_(),zwe=W7(U7("String.prototype.indexOf"));j7.exports=function(e,t){var i=U7(e,!!t);return typeof i=="function"&&zwe(e,".prototype.")>-1?W7(i):i}});var $_=v((s7e,H7)=>{"use strict";var Z,md=TypeError,Aa=Object.getOwnPropertyDescriptor;if(Aa)try{Aa({},"")}catch(r){Aa=null}var F_=function(){throw new md},Gwe=Aa?function(){try{return arguments.callee,F_}catch(r){try{return Aa(arguments,"callee").get}catch(e){return F_}}}():F_,ms=Li()(),on=Object.getPrototypeOf||function(r){return r.__proto__},uy,A_=uy?on(uy):Z,z7,O_=z7?z7.constructor:Z,gd,L_=gd?on(gd):Z,M_=gd?gd():Z,N_=typeof Uint8Array=="undefined"?Z:on(Uint8Array),q_={"%Array%":Array,"%ArrayBuffer%":typeof ArrayBuffer=="undefined"?Z:ArrayBuffer,"%ArrayBufferPrototype%":typeof ArrayBuffer=="undefined"?Z:ArrayBuffer.prototype,"%ArrayIteratorPrototype%":ms?on([][Symbol.iterator]()):Z,"%ArrayPrototype%":Array.prototype,"%ArrayProto_entries%":Array.prototype.entries,"%ArrayProto_forEach%":Array.prototype.forEach,"%ArrayProto_keys%":Array.prototype.keys,"%ArrayProto_values%":Array.prototype.values,"%AsyncFromSyncIteratorPrototype%":Z,"%AsyncFunction%":O_,"%AsyncFunctionPrototype%":O_?O_.prototype:Z,"%AsyncGenerator%":gd?on(M_):Z,"%AsyncGeneratorFunction%":L_,"%AsyncGeneratorPrototype%":L_?L_.prototype:Z,"%AsyncIteratorPrototype%":M_&&ms&&Symbol.asyncIterator?M_[Symbol.asyncIterator]():Z,"%Atomics%":typeof Atomics=="undefined"?Z:Atomics,"%Boolean%":Boolean,"%BooleanPrototype%":Boolean.prototype,"%DataView%":typeof DataView=="undefined"?Z:DataView,"%DataViewPrototype%":typeof DataView=="undefined"?Z:DataView.prototype,"%Date%":Date,"%DatePrototype%":Date.prototype,"%decodeURI%":decodeURI,"%decodeURIComponent%":decodeURIComponent,"%encodeURI%":encodeURI,"%encodeURIComponent%":encodeURIComponent,"%Error%":Error,"%ErrorPrototype%":Error.prototype,"%eval%":eval,"%EvalError%":EvalError,"%EvalErrorPrototype%":EvalError.prototype,"%Float32Array%":typeof Float32Array=="undefined"?Z:Float32Array,"%Float32ArrayPrototype%":typeof Float32Array=="undefined"?Z:Float32Array.prototype,"%Float64Array%":typeof Float64Array=="undefined"?Z:Float64Array,"%Float64ArrayPrototype%":typeof Float64Array=="undefined"?Z:Float64Array.prototype,"%Function%":Function,"%FunctionPrototype%":Function.prototype,"%Generator%":uy?on(uy()):Z,"%GeneratorFunction%":A_,"%GeneratorPrototype%":A_?A_.prototype:Z,"%Int8Array%":typeof Int8Array=="undefined"?Z:Int8Array,"%Int8ArrayPrototype%":typeof Int8Array=="undefined"?Z:Int8Array.prototype,"%Int16Array%":typeof Int16Array=="undefined"?Z:Int16Array,"%Int16ArrayPrototype%":typeof Int16Array=="undefined"?Z:Int8Array.prototype,"%Int32Array%":typeof Int32Array=="undefined"?Z:Int32Array,"%Int32ArrayPrototype%":typeof Int32Array=="undefined"?Z:Int32Array.prototype,"%isFinite%":isFinite,"%isNaN%":isNaN,"%IteratorPrototype%":ms?on(on([][Symbol.iterator]())):Z,"%JSON%":typeof JSON=="object"?JSON:Z,"%JSONParse%":typeof JSON=="object"?JSON.parse:Z,"%Map%":typeof Map=="undefined"?Z:Map,"%MapIteratorPrototype%":typeof Map=="undefined"||!ms?Z:on(new Map()[Symbol.iterator]()),"%MapPrototype%":typeof Map=="undefined"?Z:Map.prototype,"%Math%":Math,"%Number%":Number,"%NumberPrototype%":Number.prototype,"%Object%":Object,"%ObjectPrototype%":Object.prototype,"%ObjProto_toString%":Object.prototype.toString,"%ObjProto_valueOf%":Object.prototype.valueOf,"%parseFloat%":parseFloat,"%parseInt%":parseInt,"%Promise%":typeof Promise=="undefined"?Z:Promise,"%PromisePrototype%":typeof Promise=="undefined"?Z:Promise.prototype,"%PromiseProto_then%":typeof Promise=="undefined"?Z:Promise.prototype.then,"%Promise_all%":typeof Promise=="undefined"?Z:Promise.all,"%Promise_reject%":typeof Promise=="undefined"?Z:Promise.reject,"%Promise_resolve%":typeof Promise=="undefined"?Z:Promise.resolve,"%Proxy%":typeof Proxy=="undefined"?Z:Proxy,"%RangeError%":RangeError,"%RangeErrorPrototype%":RangeError.prototype,"%ReferenceError%":ReferenceError,"%ReferenceErrorPrototype%":ReferenceError.prototype,"%Reflect%":typeof Reflect=="undefined"?Z:Reflect,"%RegExp%":RegExp,"%RegExpPrototype%":RegExp.prototype,"%Set%":typeof Set=="undefined"?Z:Set,"%SetIteratorPrototype%":typeof Set=="undefined"||!ms?Z:on(new Set()[Symbol.iterator]()),"%SetPrototype%":typeof Set=="undefined"?Z:Set.prototype,"%SharedArrayBuffer%":typeof SharedArrayBuffer=="undefined"?Z:SharedArrayBuffer,"%SharedArrayBufferPrototype%":typeof SharedArrayBuffer=="undefined"?Z:SharedArrayBuffer.prototype,"%String%":String,"%StringIteratorPrototype%":ms?on(""[Symbol.iterator]()):Z,"%StringPrototype%":String.prototype,"%Symbol%":ms?Symbol:Z,"%SymbolPrototype%":ms?Symbol.prototype:Z,"%SyntaxError%":SyntaxError,"%SyntaxErrorPrototype%":SyntaxError.prototype,"%ThrowTypeError%":Gwe,"%TypedArray%":N_,"%TypedArrayPrototype%":N_?N_.prototype:Z,"%TypeError%":md,"%TypeErrorPrototype%":md.prototype,"%Uint8Array%":typeof Uint8Array=="undefined"?Z:Uint8Array,"%Uint8ArrayPrototype%":typeof Uint8Array=="undefined"?Z:Uint8Array.prototype,"%Uint8ClampedArray%":typeof Uint8ClampedArray=="undefined"?Z:Uint8ClampedArray,"%Uint8ClampedArrayPrototype%":typeof Uint8ClampedArray=="undefined"?Z:Uint8ClampedArray.prototype,"%Uint16Array%":typeof Uint16Array=="undefined"?Z:Uint16Array,"%Uint16ArrayPrototype%":typeof Uint16Array=="undefined"?Z:Uint16Array.prototype,"%Uint32Array%":typeof Uint32Array=="undefined"?Z:Uint32Array,"%Uint32ArrayPrototype%":typeof Uint32Array=="undefined"?Z:Uint32Array.prototype,"%URIError%":URIError,"%URIErrorPrototype%":URIError.prototype,"%WeakMap%":typeof WeakMap=="undefined"?Z:WeakMap,"%WeakMapPrototype%":typeof WeakMap=="undefined"?Z:WeakMap.prototype,"%WeakSet%":typeof WeakSet=="undefined"?Z:WeakSet,"%WeakSetPrototype%":typeof WeakSet=="undefined"?Z:WeakSet.prototype},Vwe=un(),G7=Vwe.call(Function.call,String.prototype.replace),Kwe=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g,Jwe=/\\(\\)?/g,Ywe=function(e){var t=[];return G7(e,Kwe,function(i,n,o,s){t[t.length]=o?G7(s,Jwe,"$1"):n||i}),t},Xwe=function(e,t){if(!(e in q_))throw new SyntaxError("intrinsic "+e+" does not exist!");if(typeof q_[e]=="undefined"&&!t)throw new md("intrinsic "+e+" exists, but is not available. Please file an issue!");return q_[e]};H7.exports=function(e,t){if(typeof e!="string"||e.length===0)throw new TypeError("intrinsic name must be a non-empty string");if(arguments.length>1&&typeof t!="boolean")throw new TypeError('"allowMissing" argument must be a boolean');for(var i=Ywe(e),n=Xwe("%"+(i.length>0?i[0]:"")+"%",t),o=1;o=i.length){var s=Aa(n,i[o]);if(!t&&!(i[o]in n))throw new md("base intrinsic for "+e+" exists, but the property is not available.");n=s&&"get"in s&&!("originalValue"in s.get)?s.get:n[i[o]]}else n=n[i[o]];return n}});var X7=v((a7e,cy)=>{"use strict";var B_=un(),fy=$_(),V7=fy("%Function.prototype.apply%"),K7=fy("%Function.prototype.call%"),J7=fy("%Reflect.apply%",!0)||B_.call(K7,V7),vd=fy("%Object.defineProperty%",!0);if(vd)try{vd({},"a",{value:1})}catch(r){vd=null}cy.exports=function(){return J7(B_,K7,arguments)};var Y7=function(){return J7(B_,V7,arguments)};vd?vd(cy.exports,"apply",{value:Y7}):cy.exports.apply=Y7});var j_=v((l7e,Z7)=>{"use strict";var Zwe=Object,Qwe=TypeError;Z7.exports=function(){if(this!=null&&this!==Zwe(this))throw new Qwe("RegExp.prototype.flags getter called on non-object");var e="";return this.global&&(e+="g"),this.ignoreCase&&(e+="i"),this.multiline&&(e+="m"),this.dotAll&&(e+="s"),this.unicode&&(e+="u"),this.sticky&&(e+="y"),e}});var U_=v((u7e,Q7)=>{"use strict";var exe=j_(),txe=Fn().supportsDescriptors,rxe=Object.getOwnPropertyDescriptor,ixe=TypeError;Q7.exports=function(){if(!txe)throw new ixe("RegExp.prototype.flags requires a true ES5 environment that supports property descriptors");if(/a/mig.flags==="gim"){var e=rxe(RegExp.prototype,"flags");if(e&&typeof e.get=="function"&&typeof/a/.dotAll=="boolean")return e.get}return exe}});var rG=v((c7e,eG)=>{"use strict";var nxe=Fn().supportsDescriptors,oxe=U_(),sxe=Object.getOwnPropertyDescriptor,axe=Object.defineProperty,lxe=TypeError,tG=Object.getPrototypeOf,uxe=/a/;eG.exports=function(){if(!nxe||!tG)throw new lxe("RegExp.prototype.flags requires a true ES5 environment that supports property descriptors");var e=oxe(),t=tG(uxe),i=sxe(t,"flags");return(!i||i.get!==e)&&axe(t,"flags",{configurable:!0,enumerable:!1,get:e}),e}});var W_=v((f7e,iG)=>{"use strict";var cxe=Fn(),fxe=X7(),nG=j_(),pxe=U_(),dxe=rG(),oG=fxe(nG);cxe(oG,{getPolyfill:pxe,implementation:nG,shim:dxe});iG.exports=oG});var py=v((p7e,sG)=>{"use strict";sG.exports=Number.isNaN||function(e){return e!==e}});var H_=v((d7e,aG)=>{"use strict";var lG=py();aG.exports=function(e,t){return e===t?e===0?1/e==1/t:!0:lG(e)&&lG(t)}});var z_=v((h7e,uG)=>{"use strict";var hxe=Oe(),dy=hxe("%TypeError%"),mxe=Ku(),cG=H_(),fG=dr(),pG=function(){try{return delete[].length,!0}catch(r){return!1}}();uG.exports=function(e,t,i,n){if(fG(e)!=="Object")throw new dy("Assertion failed: `O` must be an Object");if(!mxe(t))throw new dy("Assertion failed: `P` must be a Property Key");if(fG(n)!=="Boolean")throw new dy("Assertion failed: `Throw` must be a Boolean");if(n){if(e[t]=i,pG&&!cG(e[t],i))throw new dy("Attempted to assign to readonly property.");return!0}else try{return e[t]=i,pG?cG(e[t],i):!0}catch(o){return!1}}});var hG=v((m7e,dG)=>{"use strict";var gxe=Oe(),vxe=lo(),yxe=gxe("%TypeError%");dG.exports=function(e,t){if(e.Type(t)!=="Object")return!1;var i={"[[Configurable]]":!0,"[[Enumerable]]":!0,"[[Get]]":!0,"[[Set]]":!0,"[[Value]]":!0,"[[Writable]]":!0};for(var n in t)if(vxe(t,n)&&!i[n])return!1;if(e.IsDataDescriptor(t)&&e.IsAccessorDescriptor(t))throw new yxe("Property Descriptors may not be both accessor and data descriptors");return!0}});var gG=v((g7e,mG)=>{"use strict";var bxe=Oe(),yd=bxe("%Object.defineProperty%",!0);if(yd)try{yd({},"a",{value:1})}catch(r){yd=null}var wxe=Ia(),xxe=wxe("Object.prototype.propertyIsEnumerable");mG.exports=function(e,t,i,n,o,s){if(!yd){if(!e(s)||!s["[[Configurable]]"]||!s["[[Writable]]"]||o in n&&xxe(n,o)!==!!s["[[Enumerable]]"])return!1;var a=s["[[Value]]"];return n[o]=a,t(n[o],a)}return yd(n,o,i(s)),!0}});var my=v((v7e,vG)=>{"use strict";var yG=Oe(),bG=yG("%TypeError%"),Dxe=yG("%SyntaxError%"),hy=lo(),Sxe={"Property Descriptor":function(e,t){if(e(t)!=="Object")return!1;var i={"[[Configurable]]":!0,"[[Enumerable]]":!0,"[[Get]]":!0,"[[Set]]":!0,"[[Value]]":!0,"[[Writable]]":!0};for(var n in t)if(hy(t,n)&&!i[n])return!1;var o=hy(t,"[[Value]]"),s=hy(t,"[[Get]]")||hy(t,"[[Set]]");if(o&&s)throw new bG("Property Descriptors may not be both accessor and data descriptors");return!0}};vG.exports=function(e,t,i,n){var o=Sxe[t];if(typeof o!="function")throw new Dxe("unknown record type: "+t);if(!o(e,n))throw new bG(i+" must be a "+t)}});var xG=v((y7e,wG)=>{"use strict";var Exe=my(),Cxe=dr();wG.exports=function(e){if(typeof e=="undefined")return e;Exe(Cxe,"Property Descriptor","Desc",e);var t={};return"[[Value]]"in e&&(t.value=e["[[Value]]"]),"[[Writable]]"in e&&(t.writable=e["[[Writable]]"]),"[[Get]]"in e&&(t.get=e["[[Get]]"]),"[[Set]]"in e&&(t.set=e["[[Set]]"]),"[[Enumerable]]"in e&&(t.enumerable=e["[[Enumerable]]"]),"[[Configurable]]"in e&&(t.configurable=e["[[Configurable]]"]),t}});var EG=v((b7e,DG)=>{"use strict";var SG=lo(),_xe=my(),Pxe=dr();DG.exports=function(e){return!(typeof e=="undefined"||(_xe(Pxe,"Property Descriptor","Desc",e),!SG(e,"[[Get]]")&&!SG(e,"[[Set]]")))}});var PG=v((w7e,CG)=>{"use strict";var _G=lo(),Txe=my(),Rxe=dr();CG.exports=function(e){return!(typeof e=="undefined"||(Txe(Rxe,"Property Descriptor","Desc",e),!_G(e,"[[Value]]")&&!_G(e,"[[Writable]]")))}});var kG=v((x7e,TG)=>{"use strict";var Rn=lo(),kxe=Oe(),gy=kxe("%TypeError%"),Ixe=dr(),G_=k_(),RG=sy();TG.exports=function(e){if(Ixe(e)!=="Object")throw new gy("ToPropertyDescriptor requires an object");var t={};if(Rn(e,"enumerable")&&(t["[[Enumerable]]"]=G_(e.enumerable)),Rn(e,"configurable")&&(t["[[Configurable]]"]=G_(e.configurable)),Rn(e,"value")&&(t["[[Value]]"]=e.value),Rn(e,"writable")&&(t["[[Writable]]"]=G_(e.writable)),Rn(e,"get")){var i=e.get;if(typeof i!="undefined"&&!RG(i))throw new gy("getter must be a function");t["[[Get]]"]=i}if(Rn(e,"set")){var n=e.set;if(typeof n!="undefined"&&!RG(n))throw new gy("setter must be a function");t["[[Set]]"]=n}if((Rn(t,"[[Get]]")||Rn(t,"[[Set]]"))&&(Rn(t,"[[Value]]")||Rn(t,"[[Writable]]")))throw new gy("Invalid property descriptor. Cannot both specify accessors and a value or writable attribute");return t}});var OG=v((D7e,IG)=>{"use strict";var Fxe=Oe(),V_=Fxe("%TypeError%"),FG=hG(),Axe=gG(),Oxe=xG(),AG=EG(),K_=PG(),Lxe=Ku(),Mxe=H_(),Nxe=kG(),J_=dr();IG.exports=function(e,t,i){if(J_(e)!=="Object")throw new V_("Assertion failed: Type(O) is not Object");if(!Lxe(t))throw new V_("Assertion failed: IsPropertyKey(P) is not true");var n=FG({Type:J_,IsDataDescriptor:K_,IsAccessorDescriptor:AG},i)?i:Nxe(i);if(!FG({Type:J_,IsDataDescriptor:K_,IsAccessorDescriptor:AG},n))throw new V_("Assertion failed: Desc is not a valid Property Descriptor");return Axe(K_,Mxe,Oxe,e,t,n)}});var MG=v((S7e,Y_)=>{"use strict";var qxe=Oe(),LG=qxe("%Reflect.construct%",!0),vy=OG();try{vy({},"",{"[[Get]]":function(){}})}catch(r){vy=null}vy&&LG?(X_={},Z_={},vy(Z_,"length",{"[[Get]]":function(){throw X_},"[[Enumerable]]":!0}),Y_.exports=function(e){try{LG(e,Z_)}catch(t){return t===X_}}):Y_.exports=function(e){return typeof e=="function"&&!!e.prototype};var X_,Z_});var jG=v((E7e,NG)=>{"use strict";var qG=Oe(),$G=qG("%Symbol.species%",!0),Q_=qG("%TypeError%"),$xe=MG(),BG=dr();NG.exports=function(e,t){if(BG(e)!=="Object")throw new Q_("Assertion failed: Type(O) is not Object");var i=e.constructor;if(typeof i=="undefined")return t;if(BG(i)!=="Object")throw new Q_("O.constructor is not an Object");var n=$G?i[$G]:void 0;if(n==null)return t;if($xe(n))return n;throw new Q_("no constructor found")}});var eP=v((C7e,UG)=>{"use strict";var WG=Oe(),Bxe=WG("%Math%"),jxe=WG("%Number%");UG.exports=jxe.MAX_SAFE_INTEGER||Bxe.pow(2,53)-1});var zG=v((_7e,HG)=>{"use strict";var Uxe=Oe(),Wxe=Uxe("%Math.abs%");HG.exports=function(e){return Wxe(e)}});var VG=v((P7e,GG)=>{"use strict";var Hxe=Math.floor;GG.exports=function(e){return Hxe(e)}});var JG=v((T7e,KG)=>{"use strict";KG.exports=function(e){return+e}});var tP=v((R7e,YG)=>{"use strict";var zxe=Number.isNaN||function(r){return r!==r};YG.exports=Number.isFinite||function(r){return typeof r=="number"&&!zxe(r)&&r!==Infinity&&r!==-Infinity}});var ZG=v((k7e,XG)=>{"use strict";XG.exports=function(e){return e>=0?1:-1}});var eV=v((I7e,QG)=>{"use strict";var Gxe=zG(),Vxe=VG(),Kxe=JG(),Jxe=py(),Yxe=tP(),Xxe=ZG();QG.exports=function(e){var t=Kxe(e);return Jxe(t)?0:t===0||!Yxe(t)?t:Xxe(t)*Vxe(Gxe(t))}});var rV=v((F7e,tV)=>{"use strict";var Zxe=Oe(),Qxe=Zxe("RegExp.prototype.test"),eDe=h_();tV.exports=function(e){return eDe(Qxe,e)}});var nV=v((A7e,iV)=>{"use strict";iV.exports=function(e){return e===null||typeof e!="function"&&typeof e!="object"}});var sV=v((O7e,oV)=>{"use strict";oV.exports=function(e){return e===null||typeof e!="function"&&typeof e!="object"}});var lV=v((L7e,aV)=>{"use strict";var tDe=Date.prototype.getDay,rDe=function(e){try{return tDe.call(e),!0}catch(t){return!1}},iDe=Object.prototype.toString,nDe="[object Date]",oDe=typeof Symbol=="function"&&typeof Symbol.toStringTag=="symbol";aV.exports=function(e){return typeof e!="object"||e===null?!1:oDe?rDe(e):iDe.call(e)===nDe}});var pV=v((M7e,rP)=>{"use strict";var sDe=Object.prototype.toString,aDe=Li()();aDe?(uV=Symbol.prototype.toString,cV=/^Symbol\(.*\)$/,fV=function(e){return typeof e.valueOf()!="symbol"?!1:cV.test(uV.call(e))},rP.exports=function(e){if(typeof e=="symbol")return!0;if(sDe.call(e)!=="[object Symbol]")return!1;try{return fV(e)}catch(t){return!1}}):rP.exports=function(e){return!1};var uV,cV,fV});var gV=v((N7e,dV)=>{"use strict";var lDe=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol",iP=sV(),hV=Ny(),uDe=lV(),mV=pV(),cDe=function(e,t){if(typeof e=="undefined"||e===null)throw new TypeError("Cannot call method on "+e);if(typeof t!="string"||t!=="number"&&t!=="string")throw new TypeError('hint must be "string" or "number"');var i=t==="string"?["toString","valueOf"]:["valueOf","toString"],n,o,s;for(s=0;s1&&(arguments[1]===String?t="string":arguments[1]===Number&&(t="number"));var i;if(lDe&&(Symbol.toPrimitive?i=fDe(e,Symbol.toPrimitive):mV(e)&&(i=Symbol.prototype.valueOf)),typeof i!="undefined"){var n=i.call(e,t);if(iP(n))return n;throw new TypeError("unable to convert exotic object to primitive")}return t==="default"&&(uDe(e)||mV(e))&&(t="string"),cDe(e,t==="default"?"number":t)}});var bV=v((q7e,vV)=>{"use strict";var yV=gV();vV.exports=function(e){return arguments.length>1?yV(e,arguments[1]):yV(e)}});var _V=v(($7e,wV)=>{"use strict";var yy=Oe(),pDe=yy("%TypeError%"),xV=yy("%Number%"),dDe=yy("%RegExp%"),DV=yy("%parseInt%"),SV=Ia(),by=rV(),hDe=nV(),EV=SV("String.prototype.slice"),mDe=by(/^0b[01]+$/i),gDe=by(/^0o[0-7]+$/i),vDe=by(/^[-+]0x[0-9a-f]+$/i),yDe=["\x85","\u200B","\uFFFE"].join(""),bDe=new dDe("["+yDe+"]","g"),wDe=by(bDe),CV=[` -\v\f\r \xA0\u1680\u180E\u2000\u2001\u2002\u2003`,"\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028","\u2029\uFEFF"].join(""),xDe=new RegExp("(^["+CV+"]+)|(["+CV+"]+$)","g"),DDe=SV("String.prototype.replace"),SDe=function(r){return DDe(r,xDe,"")},EDe=bV();wV.exports=function r(e){var t=hDe(e)?e:EDe(e,xV);if(typeof t=="symbol")throw new pDe("Cannot convert a Symbol value to a number");if(typeof t=="string"){if(mDe(t))return r(DV(EV(t,2),2));if(gDe(t))return r(DV(EV(t,2),8));if(wDe(t)||vDe(t))return NaN;var i=SDe(t);if(i!==t)return r(i)}return xV(t)}});var TV=v((B7e,PV)=>{"use strict";var CDe=eV(),_De=_V();PV.exports=function(e){var t=_De(e);return t!==0&&(t=CDe(t)),t===0?0:t}});var nP=v((j7e,RV)=>{"use strict";var kV=eP(),PDe=TV();RV.exports=function(e){var t=PDe(e);return t<=0?0:t>kV?kV:t}});var oP=v((U7e,IV)=>{"use strict";IV.exports=function(e){return typeof e=="number"&&e>=55296&&e<=56319}});var sP=v((W7e,FV)=>{"use strict";FV.exports=function(e){return typeof e=="number"&&e>=56320&&e<=57343}});var MV=v((H7e,AV)=>{"use strict";var OV=Oe(),TDe=OV("%TypeError%"),LV=OV("%String.fromCharCode%"),RDe=oP(),kDe=sP();AV.exports=function(e,t){if(!RDe(e)||!kDe(t))throw new TDe("Assertion failed: `lead` must be a leading surrogate char code, and `trail` must be a trailing surrogate char code");return LV(e)+LV(t)}});var UV=v((z7e,NV)=>{"use strict";var IDe=Oe(),qV=IDe("%TypeError%"),$V=Ia(),FDe=oP(),BV=sP(),ADe=dr(),ODe=MV(),LDe=$V("String.prototype.charAt"),jV=$V("String.prototype.charCodeAt");NV.exports=function(e,t){if(ADe(e)!=="String")throw new qV("Assertion failed: `string` must be a String");var i=e.length;if(t<0||t>=i)throw new qV("Assertion failed: `position` must be >= 0, and < the length of `string`");var n=jV(e,t),o=LDe(e,t),s=FDe(n),a=BV(n);if(!s&&!a)return{"[[CodePoint]]":o,"[[CodeUnitCount]]":1,"[[IsUnpairedSurrogate]]":!1};if(a||t+1===i)return{"[[CodePoint]]":o,"[[CodeUnitCount]]":1,"[[IsUnpairedSurrogate]]":!0};var l=jV(e,t+1);return BV(l)?{"[[CodePoint]]":ODe(n,l),"[[CodeUnitCount]]":2,"[[IsUnpairedSurrogate]]":!1}:{"[[CodePoint]]":o,"[[CodeUnitCount]]":1,"[[IsUnpairedSurrogate]]":!0}}});var HV=v((G7e,WV)=>{"use strict";var MDe=Oe(),NDe=MDe("%Math.abs%");WV.exports=function(e){return NDe(e)}});var GV=v((V7e,zV)=>{"use strict";var qDe=Math.floor;zV.exports=function(e){return qDe(e)}});var KV=v((K7e,VV)=>{"use strict";var $De=HV(),BDe=GV(),jDe=py(),UDe=tP();VV.exports=function(e){if(typeof e!="number"||jDe(e)||!UDe(e))return!1;var t=$De(e);return BDe(t)===t}});var XV=v((J7e,JV)=>{"use strict";var WDe=Oe(),HDe=UV(),zDe=KV(),YV=dr(),GDe=eP(),aP=WDe("%TypeError%");JV.exports=function(e,t,i){if(YV(e)!=="String")throw new aP("Assertion failed: `S` must be a String");if(!zDe(t)||t<0||t>GDe)throw new aP("Assertion failed: `length` must be an integer >= 0 and <= 2**53");if(YV(i)!=="Boolean")throw new aP("Assertion failed: `unicode` must be a Boolean");if(!i)return t+1;var n=e.length;if(t+1>=n)return t+1;var o=HDe(e,t);return t+o["[[CodeUnitCount]]"]}});var QV=v((Y7e,ZV)=>{"use strict";var VDe=Oe(),KDe=VDe("%TypeError%"),JDe=dr();ZV.exports=function(e,t){if(JDe(t)!=="Boolean")throw new KDe("Assertion failed: Type(done) is not Boolean");return{value:e,done:t}}});var rK=v((X7e,eK)=>{"use strict";var YDe=Oe(),tK=YDe("%Array%"),XDe=!tK.isArray&&Ia()("Object.prototype.toString");eK.exports=tK.isArray||function(e){return XDe(e)==="[object Array]"}});var aK=v((Z7e,iK)=>{"use strict";var lP=Oe(),nK=lP("%Object.create%",!0),oK=lP("%TypeError%"),sK=lP("%SyntaxError%"),ZDe=rK(),QDe=dr(),e0e=!({__proto__:null}instanceof Object);iK.exports=function(e){if(e!==null&&QDe(e)!=="Object")throw new oK("Assertion failed: `proto` must be null or an object");var t=arguments.length<2?[]:arguments[1];if(!ZDe(t))throw new oK("Assertion failed: `additionalInternalSlotsList` must be an Array");if(t.length>0)throw new sK("es-abstract does not yet support internal slots");if(nK)return nK(e);if(e0e)return{__proto__:e};if(e===null)throw new sK("native Object.create support is required to create null objects");var i=function(){};return i.prototype=e,new i}});var uK=v((Q7e,lK)=>{"use strict";var t0e=Oe(),uP=t0e("%TypeError%"),r0e=Ia()("RegExp.prototype.exec"),i0e=m_(),n0e=hd(),o0e=sy(),cP=dr();lK.exports=function(e,t){if(cP(e)!=="Object")throw new uP("Assertion failed: `R` must be an Object");if(cP(t)!=="String")throw new uP("Assertion failed: `S` must be a String");var i=n0e(e,"exec");if(o0e(i)){var n=i0e(i,e,[t]);if(n===null||cP(n)==="Object")return n;throw new uP('"exec" method must return `null` or an Object')}return r0e(e,t)}});var fK=v((eGe,cK)=>{"use strict";var fP=Yv(),Yu=I_(),s0e=E_(),a0e=fP("%TypeError%"),wy=fP("%WeakMap%",!0),xy=fP("%Map%",!0),l0e=Yu("WeakMap.prototype.get",!0),u0e=Yu("WeakMap.prototype.set",!0),c0e=Yu("WeakMap.prototype.has",!0),f0e=Yu("Map.prototype.get",!0),p0e=Yu("Map.prototype.set",!0),d0e=Yu("Map.prototype.has",!0),pP=function(r,e){for(var t=r,i;(i=t.next)!==null;t=i)if(i.key===e)return t.next=i.next,i.next=r.next,r.next=i,i},h0e=function(r,e){var t=pP(r,e);return t&&t.value},m0e=function(r,e,t){var i=pP(r,e);i?i.value=t:r.next={key:e,next:r.next,value:t}},g0e=function(r,e){return!!pP(r,e)};cK.exports=function(){var e,t,i,n={assert:function(o){if(!n.has(o))throw new a0e("Side channel does not contain "+s0e(o))},get:function(o){if(wy&&o&&(typeof o=="object"||typeof o=="function")){if(e)return l0e(e,o)}else if(xy){if(t)return f0e(t,o)}else if(i)return h0e(i,o)},has:function(o){if(wy&&o&&(typeof o=="object"||typeof o=="function")){if(e)return c0e(e,o)}else if(xy){if(t)return d0e(t,o)}else if(i)return g0e(i,o);return!1},set:function(o,s){wy&&o&&(typeof o=="object"||typeof o=="function")?(e||(e=new wy),u0e(e,o,s)):xy?(t||(t=new xy),p0e(t,o,s)):(i||(i={key:{},next:null}),m0e(i,o,s))}};return n}});var hK=v((tGe,pK)=>{"use strict";var v0e=$_(),y0e=lo(),bd=fK()(),gs=v0e("%TypeError%"),dK={assert:function(r,e){if(!r||typeof r!="object"&&typeof r!="function")throw new gs("`O` is not an object");if(typeof e!="string")throw new gs("`slot` must be a string");bd.assert(r)},get:function(r,e){if(!r||typeof r!="object"&&typeof r!="function")throw new gs("`O` is not an object");if(typeof e!="string")throw new gs("`slot` must be a string");var t=bd.get(r);return t&&t["$"+e]},has:function(r,e){if(!r||typeof r!="object"&&typeof r!="function")throw new gs("`O` is not an object");if(typeof e!="string")throw new gs("`slot` must be a string");var t=bd.get(r);return!!t&&y0e(t,"$"+e)},set:function(r,e,t){if(!r||typeof r!="object"&&typeof r!="function")throw new gs("`O` is not an object");if(typeof e!="string")throw new gs("`slot` must be a string");var i=bd.get(r);i||(i={},bd.set(r,i)),i["$"+e]=t}};Object.freeze&&Object.freeze(dK);pK.exports=dK});var bK=v((rGe,mK)=>{"use strict";var gK=Fn(),b0e=XV(),Dy=QV(),vK=hd(),w0e=Oe(),x0e=aK(),D0e=uK(),S0e=z_(),E0e=nP(),C0e=ly(),Sy=dr(),_0e=Li()(),Jt=hK(),yK,co=function(e,t,i,n){if(Sy(t)!=="String")throw new TypeError("S must be a string");if(Sy(i)!=="Boolean")throw new TypeError("global must be a boolean");if(Sy(n)!=="Boolean")throw new TypeError("fullUnicode must be a boolean");Jt.set(this,"[[IteratingRegExp]]",e),Jt.set(this,"[[IteratedString]]",t),Jt.set(this,"[[Global]]",i),Jt.set(this,"[[Unicode]]",n),Jt.set(this,"[[Done]]",!1)},dP=w0e("%IteratorPrototype%",!0);dP&&(co.prototype=x0e(dP));gK(co.prototype,{next:function(){var e=this;if(Sy(e)!=="Object")throw new TypeError("receiver must be an object");if(!(e instanceof co)||!Jt.has(e,"[[IteratingRegExp]]")||!Jt.has(e,"[[IteratedString]]")||!Jt.has(e,"[[Global]]")||!Jt.has(e,"[[Unicode]]")||!Jt.has(e,"[[Done]]"))throw new TypeError('"this" value must be a RegExpStringIterator instance');if(Jt.get(e,"[[Done]]"))return Dy(yK,!0);var t=Jt.get(e,"[[IteratingRegExp]]"),i=Jt.get(e,"[[IteratedString]]"),n=Jt.get(e,"[[Global]]"),o=Jt.get(e,"[[Unicode]]"),s=D0e(t,i);if(s===null)return Jt.set(e,"[[Done]]",!0),Dy(yK,!0);if(n){var a=C0e(vK(s,"0"));if(a===""){var l=E0e(vK(t,"lastIndex")),u=b0e(i,l,o);S0e(t,"lastIndex",u,!0)}return Dy(s,!1)}return Jt.set(e,"[[Done]]",!0),Dy(s,!1)}});_0e&&(hP=Object.defineProperty,Symbol.toStringTag&&(hP?hP(co.prototype,Symbol.toStringTag,{configurable:!0,enumerable:!1,value:"RegExp String Iterator",writable:!1}):co.prototype[Symbol.toStringTag]="RegExp String Iterator"),!dP&&Symbol.iterator&&(Ey={},Ey[Symbol.iterator]=co.prototype[Symbol.iterator]||function(){return this},mP={},mP[Symbol.iterator]=function(){return co.prototype[Symbol.iterator]!==Ey[Symbol.iterator]},gK(co.prototype,Ey,mP)));var hP,Ey,mP;mK.exports=co});var _K=v((iGe,wK)=>{"use strict";var xK=hd(),P0e=z_(),T0e=jG(),R0e=nP(),DK=ly(),Cy=dr(),k0e=W_(),I0e=bK(),SK=RegExp,F0e=function(e,t,i,n){if(Cy(t)!=="String")throw new TypeError('"S" value must be a String');if(Cy(i)!=="Boolean")throw new TypeError('"global" value must be a Boolean');if(Cy(n)!=="Boolean")throw new TypeError('"fullUnicode" value must be a Boolean');var o=new I0e(e,t,i,n);return o},A0e="flags"in RegExp.prototype,O0e=function(e,t){var i,n="flags"in t?xK(t,"flags"):DK(k0e(t));return A0e&&typeof n=="string"?i=new e(t,n):e===SK?i=new e(t.source,n):i=new e(t,n),{flags:n,matcher:i}},gP=function(e){var t=this;if(Cy(t)!=="Object")throw new TypeError('"this" value must be an Object');var i=DK(e),n=T0e(t,SK),o=O0e(n,t),s=o.flags,a=o.matcher,l=R0e(xK(t,"lastIndex"));P0e(a,"lastIndex",l,!0);var u=s.indexOf("g")>-1,c=s.indexOf("u")>-1;return F0e(a,i,u,c)},EK=Object.defineProperty,CK=Object.getOwnPropertyDescriptor;EK&&CK&&(vP=CK(gP,"name"),vP&&vP.configurable&&EK(gP,"name",{value:"[Symbol.matchAll]"}));var vP;wK.exports=gP});var yP=v((nGe,PK)=>{"use strict";var L0e=Li()(),M0e=_K();PK.exports=function(){return!L0e||typeof Symbol.matchAll!="symbol"||typeof RegExp.prototype[Symbol.matchAll]!="function"?M0e:RegExp.prototype[Symbol.matchAll]}});var bP=v((oGe,TK)=>{"use strict";var RK=m_(),N0e=hd(),q0e=R7(),kK=q7(),IK=ly(),FK=C_(),$0e=I_(),B0e=Li()(),j0e=W_(),U0e=$0e("String.prototype.indexOf"),W0e=yP(),AK=function(e){var t=W0e();if(B0e&&typeof Symbol.matchAll=="symbol"){var i=q0e(e,Symbol.matchAll);return i===RegExp.prototype[Symbol.matchAll]&&i!==t?t:i}if(kK(e))return t};TK.exports=function(e){var t=FK(this);if(typeof e!="undefined"&&e!==null){var i=kK(e);if(i){var n="flags"in e?N0e(e,"flags"):j0e(e);if(FK(n),U0e(IK(n),"g")<0)throw new TypeError("matchAll requires a global regular expression")}var o=AK(e);if(typeof o!="undefined")return RK(o,e,[t])}var s=IK(t),a=new RegExp(e,"g");return RK(AK(a),a,[s])}});var wP=v((sGe,OK)=>{"use strict";var H0e=bP();OK.exports=function(){if(String.prototype.matchAll)try{"".matchAll(RegExp.prototype)}catch(e){return String.prototype.matchAll}return H0e}});var qK=v((aGe,LK)=>{"use strict";var xP=Fn(),z0e=Li()(),G0e=wP(),V0e=yP(),MK=Object.defineProperty,NK=Object.getOwnPropertyDescriptor;LK.exports=function(){var e=G0e();if(xP(String.prototype,{matchAll:e},{matchAll:function(){return String.prototype.matchAll!==e}}),z0e){var t=Symbol.matchAll||(Symbol.for?Symbol.for("Symbol.matchAll"):Symbol("Symbol.matchAll"));if(xP(Symbol,{matchAll:t},{matchAll:function(){return Symbol.matchAll!==t}}),MK&&NK){var i=NK(Symbol,t);(!i||i.configurable)&&MK(Symbol,t,{configurable:!1,enumerable:!1,value:t,writable:!1})}var n=V0e(),o={};o[t]=n;var s={};s[t]=function(){return RegExp.prototype[t]!==n},xP(RegExp.prototype,o,s)}return e}});var UK=v((lGe,$K)=>{"use strict";var K0e=a_(),J0e=Fn(),BK=bP(),Y0e=wP(),X0e=qK(),jK=K0e(BK);J0e(jK,{getPolyfill:Y0e,implementation:BK,shim:X0e});$K.exports=jK});var TJ=v(lSe=>{ho(lSe,{default:()=>cSe});var CJ=S(qw()),_J=S(Mb()),PJ=S(If()),po=U()("attach"),uSe=global.hasOwnProperty("__TEST__"),cSe=(r,e=!0)=>{let t=CJ.attach(r,_J.default.getLogger("node-client"),e);global.hasOwnProperty("__TEST__")||t.call("coc#util#path_replace_patterns").then(s=>{if(xt(s)){let a=$.file;$.file=l=>(l=l.replace(/\\/g,"/"),Object.keys(s).forEach(u=>l=l.replace(new RegExp("^"+u),s[u])),a(l))}}).logError(),t.setVar("coc_process_pid",process.pid,!0);let i=new EJ(t),n=!1,o=!1;return t.on("notification",async(s,a)=>{switch(s){case"VimEnter":{!o&&n&&(o=!0,await i.init());break}case"TaskExit":case"TaskStderr":case"TaskStdout":case"GlobalChange":case"PromptInsert":case"InputChar":case"MenuInput":case"OptionSet":case"FloatBtnClick":await A.fire(s,a);break;case"CocAutocmd":po.debug("Notification autocmd:",...a),await A.fire(a[0],a.slice(1));break;default:{if(!i.hasAction(s)){if(global.hasOwnProperty("__TEST__"))return;console.error(`action "${s}" not registered`);return}try{i.isReady?po.info("receive notification:",s,a):po.warn(`Plugin not ready when received "${s}"`,a),await i.ready,await i.cocAction(s,...a)}catch(u){console.error(`Error on notification "${s}": ${u.message||u.toString()}`),po.error("Notification error:",s,a,u)}}}}),t.on("request",async(s,a,l)=>{s!="redraw"&&po.info("receive request:",s,a);let u=setTimeout(()=>{po.error("Request cost more than 3s",s,a)},3e3);try{if(s=="CocAutocmd")po.debug("Request autocmd:",...a),await A.fire(a[0],a.slice(1)),l.send();else{i.isReady||po.warn(`Plugin not ready when received "${s}"`,a);let c=await i.cocAction(s,...a);l.send(c)}clearTimeout(u)}catch(c){clearTimeout(u),l.send(c.message||c.toString(),!0),po.error("Request error:",s,a,c)}}),t.channelId.then(async s=>{n=!0,uSe&&t.command(`let g:coc_node_channel_id = ${s}`,!0);let{major:a,minor:l,patch:u}=PJ.default.parse(dg);t.setClientInfo("coc",{major:a,minor:l,patch:u},"remote",{},{}),await t.getVvar("vim_did_enter")&&!o&&(o=!0,await i.init())}).catch(s=>{console.error(`Channel create error: ${s.message}`)}),i}});var fSe=UT();bh();Object.defineProperty(console,"log",{value(){$P.info(...arguments)}});fSe.shim();var $P=U()("server");var Nx=S(W());var lq=S(require("child_process")),uq=S(Vr()),cq=S(require("fs")),fq=S(Px()),Ax=S(require("path")),Ox=S(W());"use strict";var Ole=function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var o in n)n.hasOwnProperty(o)&&(i[o]=n[o])},r(e,t)};return function(e,t){r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}(),ft,bf;typeof process=="object"?bf=process.platform==="win32":typeof navigator=="object"&&(NN=navigator.userAgent,bf=NN.indexOf("Windows")>=0);var NN;var Lle=/^\w[\w\d+.-]*$/,Mle=/^\//,Nle=/^\/\//;function qle(r,e){if(!r.scheme&&e)throw new Error('[UriError]: Scheme is missing: {scheme: "", authority: "'+r.authority+'", path: "'+r.path+'", query: "'+r.query+'", fragment: "'+r.fragment+'"}');if(r.scheme&&!Lle.test(r.scheme))throw new Error("[UriError]: Scheme contains illegal characters.");if(r.path){if(r.authority){if(!Mle.test(r.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(Nle.test(r.path))throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")')}}function $le(r,e){return!r&&!e?"file":r}function Ble(r,e){switch(r){case"https":case"http":case"file":e?e[0]!==zi&&(e=zi+e):e=zi;break}return e}var Je="",zi="/",jle=/^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/,$=function(){function r(e,t,i,n,o,s){s===void 0&&(s=!1),typeof e=="object"?(this.scheme=e.scheme||Je,this.authority=e.authority||Je,this.path=e.path||Je,this.query=e.query||Je,this.fragment=e.fragment||Je):(this.scheme=$le(e,s),this.authority=t||Je,this.path=Ble(this.scheme,i||Je),this.query=n||Je,this.fragment=o||Je,qle(this,s))}return r.isUri=function(e){return e instanceof r?!0:e?typeof e.authority=="string"&&typeof e.fragment=="string"&&typeof e.path=="string"&&typeof e.query=="string"&&typeof e.scheme=="string"&&typeof e.fsPath=="function"&&typeof e.with=="function"&&typeof e.toString=="function":!1},Object.defineProperty(r.prototype,"fsPath",{get:function(){return $N(this,!1)},enumerable:!0,configurable:!0}),r.prototype.with=function(e){if(!e)return this;var t=e.scheme,i=e.authority,n=e.path,o=e.query,s=e.fragment;return t===void 0?t=this.scheme:t===null&&(t=Je),i===void 0?i=this.authority:i===null&&(i=Je),n===void 0?n=this.path:n===null&&(n=Je),o===void 0?o=this.query:o===null&&(o=Je),s===void 0?s=this.fragment:s===null&&(s=Je),t===this.scheme&&i===this.authority&&n===this.path&&o===this.query&&s===this.fragment?this:new El(t,i,n,o,s)},r.parse=function(e,t){t===void 0&&(t=!1);var i=jle.exec(e);return i?new El(i[2]||Je,lm(i[4]||Je),lm(i[5]||Je),lm(i[7]||Je),lm(i[9]||Je),t):new El(Je,Je,Je,Je,Je)},r.file=function(e){var t=Je;if(bf&&(e=e.replace(/\\/g,zi)),e[0]===zi&&e[1]===zi){var i=e.indexOf(zi,2);i===-1?(t=e.substring(2),e=zi):(t=e.substring(2,i),e=e.substring(i)||zi)}return new El("file",t,e,Je,Je)},r.from=function(e){return new El(e.scheme,e.authority,e.path,e.query,e.fragment)},r.prototype.toString=function(e){return e===void 0&&(e=!1),Tx(this,e)},r.prototype.toJSON=function(){return this},r.revive=function(e){if(e){if(e instanceof r)return e;var t=new El(e);return t._formatted=e.external,t._fsPath=e._sep===qN?e.fsPath:null,t}else return e},r}();var qN=bf?1:void 0,El=function(r){Ole(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t._formatted=null,t._fsPath=null,t}return Object.defineProperty(e.prototype,"fsPath",{get:function(){return this._fsPath||(this._fsPath=$N(this,!1)),this._fsPath},enumerable:!0,configurable:!0}),e.prototype.toString=function(t){return t===void 0&&(t=!1),t?Tx(this,!0):(this._formatted||(this._formatted=Tx(this,!1)),this._formatted)},e.prototype.toJSON=function(){var t={$mid:1};return this._fsPath&&(t.fsPath=this._fsPath,t._sep=qN),this._formatted&&(t.external=this._formatted),this.path&&(t.path=this.path),this.scheme&&(t.scheme=this.scheme),this.authority&&(t.authority=this.authority),this.query&&(t.query=this.query),this.fragment&&(t.fragment=this.fragment),t},e}($),BN=(ft={},ft[58]="%3A",ft[47]="%2F",ft[63]="%3F",ft[35]="%23",ft[91]="%5B",ft[93]="%5D",ft[64]="%40",ft[33]="%21",ft[36]="%24",ft[38]="%26",ft[39]="%27",ft[40]="%28",ft[41]="%29",ft[42]="%2A",ft[43]="%2B",ft[44]="%2C",ft[59]="%3B",ft[61]="%3D",ft[32]="%20",ft);function jN(r,e){for(var t=void 0,i=-1,n=0;n=97&&o<=122||o>=65&&o<=90||o>=48&&o<=57||o===45||o===46||o===95||o===126||e&&o===47)i!==-1&&(t+=encodeURIComponent(r.substring(i,n)),i=-1),t!==void 0&&(t+=r.charAt(n));else{t===void 0&&(t=r.substr(0,n));var s=BN[o];s!==void 0?(i!==-1&&(t+=encodeURIComponent(r.substring(i,n)),i=-1),t+=s):i===-1&&(i=n)}}return i!==-1&&(t+=encodeURIComponent(r.substring(i))),t!==void 0?t:r}function Ule(r){for(var e=void 0,t=0;t1&&r.scheme==="file"?t="//"+r.authority+r.path:r.path.charCodeAt(0)===47&&(r.path.charCodeAt(1)>=65&&r.path.charCodeAt(1)<=90||r.path.charCodeAt(1)>=97&&r.path.charCodeAt(1)<=122)&&r.path.charCodeAt(2)===58?e?t=r.path.substr(1):t=r.path[1].toLowerCase()+r.path.substr(2):t=r.path,bf&&(t=t.replace(/\//g,"\\")),t}function Tx(r,e){var t=e?Ule:jN,i="",n=r.scheme,o=r.authority,s=r.path,a=r.query,l=r.fragment;if(n&&(i+=n,i+=":"),(o||n==="file")&&(i+=zi,i+=zi),o){var u=o.indexOf("@");if(u!==-1){var c=o.substr(0,u);o=o.substr(u+1),u=c.indexOf(":"),u===-1?i+=t(c,!1):(i+=t(c.substr(0,u),!1),i+=":",i+=t(c.substr(u+1),!1)),i+="@"}o=o.toLowerCase(),u=o.indexOf(":"),u===-1?i+=t(o,!1):(i+=t(o.substr(0,u),!1),i+=o.substr(u))}if(s){if(s.length>=3&&s.charCodeAt(0)===47&&s.charCodeAt(2)===58){var f=s.charCodeAt(1);f>=65&&f<=90&&(s="/"+String.fromCharCode(f+32)+":"+s.substr(3))}else if(s.length>=2&&s.charCodeAt(1)===58){var f=s.charCodeAt(0);f>=65&&f<=90&&(s=String.fromCharCode(f+32)+":"+s.substr(2))}i+=t(s,!0)}return a&&(i+="?",i+=t(a,!1)),l&&(i+="#",i+=e?l:jN(l,!1)),i}function UN(r){try{return decodeURIComponent(r)}catch(e){return r.length>3?r.substr(0,3)+UN(r.substr(3)):r}}var WN=/(%[0-9A-Za-z][0-9A-Za-z])+/g;function lm(r){return r.match(WN)?r.replace(WN,function(e){return UN(e)}):r}var pq=S(_l());var Pl={};ho(Pl,{OS:()=>nue,OperatingSystem:()=>Tl,Platform:()=>Gs,globals:()=>iue,isLinux:()=>Zle,isMacintosh:()=>Fx,isNative:()=>Qle,isWeb:()=>eue,isWindows:()=>Hn,language:()=>Xle,platform:()=>tue});var cm=!1,fm=!1,kx=!1,Ix=!1,Yle=!1,Xle="en";typeof process=="object"&&typeof process.nextTick=="function"&&typeof process.platform=="string"&&(cm=process.platform==="win32",fm=process.platform==="darwin",kx=process.platform==="linux",Ix=!0);var Gs;(function(r){r[r.Web=0]="Web",r[r.Mac=1]="Mac",r[r.Linux=2]="Linux",r[r.Windows=3]="Windows"})(Gs||(Gs={}));var pm=0;Ix&&(fm?pm=1:cm?pm=3:kx&&(pm=2));var Hn=cm,Fx=fm,Zle=kx,Qle=Ix,eue=Yle,tue=pm,rue=typeof self=="object"?self:typeof global=="object"?global:{},iue=rue,Tl;(function(r){r[r.Windows=1]="Windows",r[r.Macintosh=2]="Macintosh",r[r.Linux=3]="Linux"})(Tl||(Tl={}));var nue=fm?2:cm?1:3;var gPe=U()("util-index"),Gi="coc-settings.json";function He(r){return new Promise(e=>{setTimeout(()=>{e(void 0)},r)})}function dm(r,e,t,i){return r?(Hn&&!i&&!r.startsWith("jdt://")&&(r=Ax.default.win32.normalize(r)),Ax.default.isAbsolute(r)?$.file(r).toString():fq.default.isValid(r)?$.parse(r).toString():t!=""?`${t}:${e}`:`unknown:${e}`):`untitled:${e}`}function z(r){for(;r.length;){let e=r.pop();e&&e.dispose()}}function wf(r){try{pq.default.sync(r)}catch(e){return!1}return!0}function hn(r,e={},t){return Hn||(e.shell=e.shell||process.env.SHELL),e.maxBuffer=500*1024,new Promise((i,n)=>{let o;t&&(o=setTimeout(()=>{n(new Error(`timeout after ${t}s`))},t*1e3)),lq.exec(r,e,(s,a,l)=>{if(o&&clearTimeout(o),s){n(new Error(`exited with ${s.code} -${s} -${l}`));return}i(a)})})}function Rl(r,e){let t=uq.default(e,100);try{let i=cq.default.watch(r,{persistent:!0,recursive:!1,encoding:"utf8"},()=>{t()});return Ox.Disposable.create(()=>{t.clear(),i.close()})}catch(i){return Ox.Disposable.create(()=>{t.clear()})}}function dq(r){try{return process.kill(r,0)==!0}catch(e){return e.code==="EPERM"}}function Lx(r){return r=="n"||r=="o"||r=="x"||r=="v"?"":r=="i"?"":r=="s"?"":""}function xf(r,e,t=3){if(r.length==0)return Promise.resolve();let i=0,n=r.length,o=r.slice();return new Promise(s=>{let a=l=>{let u=()=>{if(i=i+1,i==n)s();else if(o.length){let c=o.shift();a(c)}};e(l).then(u,u)};for(let l=0;l{r[t]&&typeof r[t]=="object"?e[t]=zn(r[t]):e[t]=r[t]}),e}var sue=Object.prototype.hasOwnProperty;function hq(r){if(!r||typeof r!="object")return r;let e=[r];for(;e.length>0;){let t=e.shift();Object.freeze(t);for(let i in t)if(sue.call(t,i)){let n=t[i];typeof n=="object"&&!Object.isFrozen(n)&&e.push(n)}}return r}function Mx(r,e,t=!0){return xt(r)?(xt(e)&&Object.keys(e).forEach(i=>{i in r?t&&(xt(r[i])&&xt(e[i])?Mx(r[i],e[i],t):r[i]=e[i]):r[i]=e[i]}),r):e}function qe(r,e){if(r===e)return!0;if(r==null||e===null||e===void 0||typeof r!=typeof e||typeof r!="object"||Array.isArray(r)!==Array.isArray(e))return!1;let t,i;if(Array.isArray(r)){if(r.length!==e.length)return!1;for(t=0;tn(t)))}catch(n){n.message&&n.message.indexOf("transport disconnected")==-1&&console.error(`Error on ${e}: ${n.message}${n.stack?` -`+n.stack:""} `),mq.error(`Handler Error on ${e}`,n.stack)}}on(e,t,i,n){if(Array.isArray(e)){let o=n||[];for(let s of e)this.on(s,t,i,o);return Nx.Disposable.create(()=>{z(o)})}else{let o=this.handlers.get(e)||[],s=Error().stack,a=u=>new Promise((c,f)=>{let p;try{Promise.resolve(t.apply(i||null,u)).then(()=>{p&&clearTimeout(p),c(void 0)},d=>{p&&clearTimeout(p),f(d)}),p=setTimeout(()=>{mq.warn(`Handler of ${e} blocked more than 2s:`,s)},2e3)}catch(d){f(d)}});o.push(a),this.handlers.set(e,o);let l=Nx.Disposable.create(()=>{let u=o.indexOf(a);u!==-1&&o.splice(u,1)});return n&&n.push(l),l}}},A=new gq;var DJ=S(require("events")),SJ=S(require("path")),NP=S(require("fs")),Ed=S(W());var Gv=S(W());var eU=S(Vr()),tU=S(If()),ht=S(W());var qB=S(Vr()),$m=S(W());var vD=S(E$());var DB=S(pB());var xr=S(vB());function yB(r){return`${xr.default.gray.open}${r}${xr.default.gray.close}`}function fD(r){return`${xr.default.magenta.open}${r}${xr.default.magenta.close}`}function bB(r){return`${xr.default.bold.open}${r}${xr.default.bold.close}`}function Nm(r){return`${xr.default.underline.open}${r}${xr.default.underline.close}`}function wB(r){return`${xr.default.italic.open}${r}${xr.default.italic.close}`}function xB(r){return`${xr.default.yellow.open}${r}${xr.default.yellow.close}`}function pD(r){return`${xr.default.blue.open}${r}${xr.default.blue.close}`}var KTe=U()("markdown-renderer"),SB="^*||*^",dD="*|*|*|*",Spe=new RegExp(EB(dD),"g"),CB="*#COLON|*",Epe=new RegExp(EB(CB),"g"),Cpe=[" "],_pe="\r",_B={code:Ki,blockquote:Ki,html:yB,heading:fD,firstHeading:fD,hr:Ki,listitem:Ki,list:Ppe,table:Ki,paragraph:Ki,strong:bB,em:wB,codespan:xB,del:Nm,link:Nm,href:Nm,text:Ki,unescape:!0,emoji:!1,width:80,showSectionPrefix:!0,tab:2,tableOptions:{}};function PB(r,e){return e?r.replace(_pe,/\n/g):r}function Rpe(r,e){return typeof r=="number"?new Array(r+1).join(" "):typeof r=="string"&&Tpe(r)?r:new Array(e+1).join(" ")}function Tpe(r){return Cpe.some(function(e){return r.match("^("+e+")+$")})}function kpe(r,e){return e.replace(/(^|\n)(.+)/g,"$1"+r+"$2")}function Ipe(r,e){return e&&r+e.split(` -`).join(` -`+r)}var Fpe="\\*",Ape="\\d+\\.",TB="(?:"+[Fpe,Ape].join("|")+")";function Ope(r,e){let t=new RegExp("(\\S(?: | )?)((?:"+e+")+)("+TB+"(?:.*)+)$","gm");return r.replace(t,`$1 -`+e+"$2$3")}var RB=function(r,e){return r.match("^(?:"+e+")*"+TB)};function kB(r){return" ".repeat(r.length)}var hD="* ";function Lpe(r,e){return RB(e,r)?e:kB(hD)+e}function Mpe(r,e){let t=Lpe.bind(null,e);return r.split(` -`).filter(Ki).map(t).join(` -`)}var IB=function(r){return r+". "};function Npe(r,e,t){return RB(e,r)?{num:t+1,line:e.replace(hD,IB(t+1))}:{num:t,line:kB(IB(t))+e}}function qpe(r,e){let t=Npe.bind(null,e),i=0;return r.split(` -`).filter(Ki).map(n=>{let o=t(n,i);return i=o.num,o.line}).join(` -`)}function Ppe(r,e,t){return r=r.trim(),r=e?qpe(r,t):Mpe(r,t),r}function $f(r){return r+` - -`}function $pe(r){return r.replace(Epe,":")}function FB(r,e=null){if(!r)return[];e=e||Ki;let t=e(r).split(` -`),i=[];return t.forEach(function(n){if(!n)return;let o=n.replace(Spe,"").split(SB);i.push(o.splice(0,o.length-1))}),i}function EB(r){return r.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}function Bpe(r){return r.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'")}function Ki(r){return r}var mD=new Map,AB=class{constructor(e={},t={}){this.options=e;this.highlightOptions=t;this.o=Object.assign({},_B,e),this.tab=Rpe(this.o.tab,_B.tab),this.tableSettings=this.o.tableOptions,this.unescape=this.o.unescape?Bpe:Ki,this.highlightOptions=t||{},this.transform=this.compose($pe,this.unescape)}textLength(e){return e.replace(/\u001b\[(?:\d{1,3})(?:;\d{1,3})*m/g,"").length}text(e){return this.o.text(e)}code(e,t,i){return"``` "+t+` -`+e+"\n```\n"}blockquote(e){return $f(this.o.blockquote(Ipe(this.tab,e.trim())))}html(e){return this.o.html(e)}heading(e,t,i){return e=this.transform(e),e=(this.o.showSectionPrefix?new Array(t+1).join("#")+" ":"")+e,$f(t===1?this.o.firstHeading(e):this.o.heading(e))}hr(){return`--- - -`}list(e,t){return e=this.o.list(e,t,this.tab),$f(Ope(kpe(this.tab,e),this.tab))}listitem(e){let t=this.compose(this.o.listitem,this.transform);return e.indexOf(` -`)!==-1&&(e=e.trim()),` -`+hD+t(e)}checkbox(e){return"["+(e?"X":" ")+"] "}paragraph(e){return e=this.compose(this.o.paragraph,this.transform)(e),$f(e)}table(e,t){let i=new DB.default(Object.assign({},{head:FB(e)[0]},this.tableSettings));return FB(t,this.transform).forEach(function(n){i.push(n)}),$f(this.o.table(i.toString()))}tablerow(e){return dD+e+dD+` -`}tablecell(e,t){return e+SB}strong(e){return this.o.strong(e)}em(e){return e=PB(e,this.o.reflowText),this.o.em(e)}codespan(e){return e=PB(e,this.o.reflowText),this.o.codespan(e.replace(/:/g,CB))}br(){return` -`}del(e){return this.o.del(e)}link(e,t,i){let n;if(this.options.sanitize){try{n=decodeURIComponent(unescape(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(s){return""}if(n.startsWith("javascript:"))return""}if(i&&e&&i!=e&&mD.set(i,e),i&&i!=e)return pD(i);let o=this.o.href(e);return this.o.link(o)}image(e,t,i){if(typeof this.o.image=="function")return this.o.image(e,t,i);let n="!["+i;return t&&(n+=" \u2013 "+t),n+"]("+e+`) -`}compose(...e){return(...t)=>{for(let i=e.length;i-- >0;)t=[e[i].apply(this,t)];return t[0]}}static getLinks(){let e=[];for(let[t,i]of mD.entries())e.push(`${pD(t)}: ${i}`);return mD.clear(),e}},gD=AB;function ue(r){return Buffer.byteLength(r)}function ql(r){return r?r[0].toUpperCase()+r.slice(1):""}function Kr(r,e){let t=r.slice(0,e);return Buffer.byteLength(t)}function Bf(r,e){return Buffer.from(r,"utf8").slice(0,e).toString("utf8").length}function Rt(r,e,t){return Buffer.from(r,"utf8").slice(e,t).toString("utf8")}function OB(r){let e=r.charCodeAt(0);return e>128?!1:e==95||e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122}var LB={30:"black",31:"red",32:"green",33:"yellow",34:"blue",35:"magenta",36:"cyan",37:"white",90:"grey"},MB={40:"black",41:"red",42:"green",43:"yellow",44:"blue",45:"magenta",46:"cyan",47:"white"},NB={1:"bold",3:"italic",4:"underline"};function $l(r,e=!1){let t=jf(r),i=[],n="";for(let o of t){if(!o.text)continue;let{foreground:s,background:a,bold:l,italic:u,underline:c}=o,f=ue(n);if(s||a||l||u||c){let p=[f,f+ue(o.text)],d="";s&&a?d=`CocList${ql(s)}${ql(a)}`:s?e?s=="yellow"?d="CocMarkdownCode":s=="blue"?d="CocMarkdownLink":s=="magenta"?d="CocMarkdownHeader":d=`CocListFg${ql(s)}`:d=`CocListFg${ql(s)}`:a?d=`CocListBg${ql(a)}`:l?d="CocBold":u?d="CocItalic":c&&(d="CocUnderline"),i.push({span:p,hlGroup:d})}n=n+o.text}return{line:n,highlights:i}}function jf(r){let e=null,t=null,i="",n=[],o=[],s={},a;a=()=>{let l,u;i.length?i=i.substr(0,i.length-1):o.length&&(l=o.length-1,u=o[l].text,u.length===1?o.pop():o[l].text=u.substr(0,u.length-1))};for(let l=0;l{LB[u]?s.foreground=LB[u]:MB[u]?s.background=MB[u]:u==39?delete s.foreground:u==49?delete s.background:NB[u]?s[NB[u]]=!0:u==22?s.bold=!1:u==23?s.italic=!1:u==24&&(s.underline=!1)}),n=[]):t+=r[l];continue}r[l]==""?e=r[l]:r[l]=="\b"?a():i+=r[l]}return i&&(s.text=i+(e||""),o.push(s)),o}var jpe=["Error","Warning","Info","Hint"],rRe=U()("markdown-index");vD.default.setOptions({renderer:new gD});function qm(r){let e=[],t=[],i=[],n=0;for(let o of r){let s=e.length,{content:a,filetype:l}=o;if(l=="markdown"){let u=Wpe(a);i.push(...u.codes.map(c=>(c.startLine=c.startLine+s,c.endLine=c.endLine+s,c))),t.push(...u.highlights.map(c=>(c.lnum=c.lnum+s,c))),e.push(...u.lines)}else{let u=a.trim().split(/\r?\n/);jpe.includes(o.filetype)?i.push({hlGroup:`Coc${l}Float`,startLine:s,endLine:s+u.length}):i.push({filetype:o.filetype,startLine:s,endLine:s+u.length}),e.push(...u)}if(o.active){let u=Upe(a,s,o.active);u.length&&t.push(...u)}n!=r.length-1&&e.push("\u2014"),n=n+1}return{lines:e,highlights:t,codes:i}}function Upe(r,e,t){let i=[],[n,o]=t,s=r.split(/\r?\n/),a=0,l=!1;for(let u=0;uo){let f=ue(c.slice(0,o-a));i.push({colStart:0,colEnd:f,lnum:u+e,hlGroup:"CocUnderline"}),l=!1;break}else{let f=ue(c);i.push({colStart:0,colEnd:f,lnum:u+e,hlGroup:"CocUnderline"})}else if(a+c.length>n){l=!0;let f=ue(c.slice(0,n-a));if(a+c.length>o){let p=ue(c.slice(0,o-a));l=!1,i.push({colStart:f,colEnd:p,lnum:u+e,hlGroup:"CocUnderline"});break}else{let p=ue(c);i.push({colStart:f,colEnd:p,lnum:u+e,hlGroup:"CocUnderline"})}}a=a+c.length+1}return i}function Wpe(r){let e=[],t=[],i=[],n=0,o=!1,s,a=0,l=vD.default(r),u=gD.getLinks();u.length&&(l=l+` - -`+u.join(` -`));for(let c of l.replace(/\s*$/,"").split(/\n/)){if(!c.length){let p=e[e.length-1];p&&p.length&&(e.push(c),n++);continue}if(/\s*```\s*([A-Za-z0-9_,]+)?$/.test(c)){o?(o=!1,i.push({filetype:s,startLine:a,endLine:n})):(o=!0,s=c.replace(/^\s*```\s*/,""),s=="js"&&(s="javascript"),s=="ts"&&(s="typescript"),s=="bash"&&(s="sh"),a=n);continue}if(o){e.push(c),n++;continue}let f=$l(c,!0);if(f.highlights)for(let p of f.highlights){let{hlGroup:d,span:h}=p;t.push({hlGroup:d,lnum:n,colStart:h[0],colEnd:h[1]})}e.push(f.line),n++}return{lines:e,highlights:t,codes:i}}var ar=class{constructor(){this.tasks=[];this.count=1}sched(){this.count>0&&this.tasks.length>0&&(this.count--,this.tasks.shift()())}get busy(){return this.count==0}acquire(){return new Promise(e=>{let t=()=>{let i=!1;e(()=>{i||(i=!0,this.count++,this.sched())})};this.tasks.push(t),process.nextTick(this.sched.bind(this))})}use(e){return this.acquire().then(t=>e().then(i=>(t(),i)).catch(i=>{throw t(),i}))}};var $B=process.env.VIM_NODE_RPC=="1",BB=U()("model-float"),yD=class{constructor(e){this.nvim=e;this.winid=0;this._bufnr=0;this.mutex=new ar;this.disposables=[];this.alignTop=!1;this.pumAlignTop=!1;this.autoHide=!0;this.mutex=new ar,A.on("BufEnter",t=>{t==this._bufnr||t==this.targetBufnr||this.close()},null,this.disposables),A.on("InsertEnter",t=>{t==this._bufnr||!this.autoHide||this.close()},null,this.disposables),A.on("InsertLeave",()=>{this.close()},null,this.disposables),A.on("MenuPopupChanged",(t,i)=>{(this.pumAlignTop=i>t.row)==this.alignTop&&this.close()},null,this.disposables),this.onCursorMoved=qB.default(this._onCursorMoved.bind(this),300),A.on("CursorMoved",this.onCursorMoved.bind(this,!1),null,this.disposables),A.on("CursorMovedI",this.onCursorMoved.bind(this,!0),null,this.disposables),this.disposables.push($m.Disposable.create(()=>{this.onCursorMoved.clear(),this.cancel()}))}_onCursorMoved(e,t,i){if(t!=this._bufnr&&!(t==this.targetBufnr&&qe(i,this.cursor))){if(this.autoHide){this.close();return}if(!e||t!=this.targetBufnr){this.close();return}}}async create(e,t=!1,i=0){if(this.onCursorMoved.clear(),e.length==0||e.every(o=>o.content.length==0)){this.close();return}let n=await this.mutex.acquire();try{await this.createPopup(e,{offsetX:i}),n()}catch(o){n(),BB.error("Error on create popup:",o.message),this.close()}}async show(e,t={}){if(this.onCursorMoved.clear(),e.length==0||e.every(n=>n.content.length==0)){this.close();return}let i=await this.mutex.acquire();try{await this.createPopup(e,t),i()}catch(n){i(),BB.error("Error on create popup:",n.message),this.close()}}async createPopup(e,t){let n=(this.tokenSource=new $m.CancellationTokenSource).token;e=e.filter(m=>m.content.trim().length>0);let{lines:o,codes:s,highlights:a}=qm(e),l={pumAlignTop:this.pumAlignTop,preferTop:typeof t.preferTop=="boolean"?t.preferTop:!1,offsetX:t.offsetX||0,title:t.title||"",close:t.close?1:0,codes:s,highlights:a,modes:t.modes||["n","i","ic","s"]};t.maxHeight&&(l.maxHeight=t.maxHeight),t.maxWidth&&(l.maxWidth=t.maxWidth),t.border&&!t.border.every(m=>m==0)&&(l.border=t.border),t.title&&!l.border&&(l.border=[1,1,1,1]),t.highlight&&(l.highlight=t.highlight),t.borderhighlight&&(l.borderhighlight=[t.borderhighlight]),t.cursorline&&(l.cursorline=1),this.autoHide=t.autoHide!=!1,this.autoHide&&(l.autohide=1);let u=await this.nvim.call("coc#float#create_cursor_float",[this.winid,this._bufnr,o,l]);if($B&&this.nvim.command("redraw",!0),!u||u.length==0){this.winid=null;return}let[c,f,p,d]=u;if(this.winid=p,n.isCancellationRequested){this.close();return}let h=await this.nvim.call("coc#float#cursor_relative",[p]);h&&(this.alignTop=h.row<0),this._bufnr=d,this.tokenSource.dispose(),this.tokenSource=null,this.targetBufnr=c,this.cursor=f,this.onCursorMoved.clear()}close(){let{winid:e,nvim:t}=this;this.cancel(),e&&(this.winid=0,t.pauseNotification(),t.call("coc#float#close",[e],!0),$B&&this.nvim.command("redraw",!0),t.resumeNotification(!1,!0))}cancel(){let{tokenSource:e}=this;e&&(e.cancel(),this.tokenSource=null)}dispose(){z(this.disposables)}get bufnr(){return this._bufnr}get buffer(){return this.bufnr?this.nvim.createBuffer(this.bufnr):null}get window(){return this.winid?this.nvim.createWindow(this.winid):null}async activated(){return this.winid?await this.nvim.call("coc#float#valid",[this.winid])!=0:!1}},mn=yD;function Ji(r,e){return Ht(r.start,e)===0&&Ht(r.end,e)===0}function Bm(r,e){let{start:t,end:i}=r;return!(Ne(i,e.start)<=0||Ne(t,e.end)>=0)}function Bl(r,e){return!!(Ht(r.start,e)==0||Ht(r.end,e)==0||Ji(e,r))}function jB(r,e){let{start:t,end:i}=e;return r>=t.line&&r<=i.line}function Gn(r){let{start:e,end:t}=r;return e.line==t.line&&e.character==t.character}function Ht(r,e){let{start:t,end:i}=e;return Ne(r,t)<0?-1:Ne(r,i)>0?1:0}function Ne(r,e){return r.line>e.line||e.line==r.line&&r.character>e.character?1:e.line==r.line&&r.character==e.character?0:-1}function Hpe(r){return r.start.line==r.end.line}function bD(r,e){let{range:t,newText:i}=e;if(Ne(t.end,r)<=0){let n=i.split(` -`),o=n.length-(t.end.line-t.start.line)-1,s=0;if(t.end.line==r.line){let a=Hpe(t)&&o==0,l=a?t.end.character-t.start.character:t.end.character;s=(a?i.length:n[n.length-1].length)-l}return{line:o,character:s}}return{line:0,character:0}}function UB(r,e){let{range:t,newText:i}=e;if(Ne(t.start,r)>1)return r;let{start:n,end:o}=t,s=i.split(` -`),a=o.line-n.line-s.length+1,l=s[s.length-1],u=r.line-a;if(r.line!=o.line)return{line:u,character:r.character};let c=s.length==1&&n.line!=o.line?n.character:0,f=n.line==o.line&&s.length==1?o.character-n.character:o.character,p=c+r.character+l.length-f;return{line:u,character:p}}function WB(r,e,t){let i=0;for(let n=0;n<=e;n++)n==e?i+=t:i+=r[n].length+1;return i}function HB(r,e,t){if(!Ji(t.range,r))return e;let{start:i,end:n}=t.range,o=e.split(` -`),s=i.line==r.start.line?i.character-r.start.character:i.character,a=WB(o,i.line-r.start.line,s);s=n.line==r.start.line?n.character-r.start.character:n.character;let l=WB(o,n.line-r.start.line,s);return`${e.slice(0,a)}${t.newText}${e.slice(l,e.length)}`}function jl(r,e){let t={line:0,character:0};for(let i of e){let n=bD(r,i);t={line:t.line+n.line,character:t.character+n.character}}return t.line==0&&t.character==0?null:t}var S0=S(require("fs")),Gj=S(require("os")),E0=S(require("path")),Vj=S(W());var dRe=U()("outpubChannel"),wD=class{constructor(e,t,i){this.name=e;this.nvim=t;this.onDispose=i;this._disposed=!1;this.lines=[""];this.disposables=[]}get content(){return this.lines.join(` -`)}_append(e){let{nvim:t}=this,i=this.lines.length-1,n=e.split(/\r?\n/),o=this.lines[i]+n[0];this.lines[i]=o;let s=n.slice(1);this.lines=this.lines.concat(s),t.pauseNotification(),t.call("setbufline",[this.bufname,"$",o],!0),s.length&&t.call("appendbufline",[this.bufname,"$",s],!0),t.resumeNotification(!1,!0)}append(e){!this.validate()||this._append(e)}appendLine(e){!this.validate()||this._append(e+` -`)}clear(e){if(!this.validate())return;let{nvim:t}=this;this.lines=e?this.lines.slice(-e):[],t.pauseNotification(),t.call("deletebufline",[this.bufname,1,"$"],!0),this.lines.length&&t.call("appendbufline",[this.bufname,"$",this.lines],!0),t.resumeNotification(!1,!0)}hide(){this.nvim.command(`exe 'silent! bd! '.fnameescape('${this.bufname}')`,!0)}get bufname(){return`output:///${this.name}`}show(e){let{nvim:t}=this;t.pauseNotification(),t.command(`exe 'vsplit '.fnameescape('${this.bufname}')`,!0),e&&t.command("wincmd p",!0),t.command("redraw",!0),t.resumeNotification(!1,!0)}validate(){return!this._disposed}dispose(){this._disposed||(this.onDispose&&this.onDispose(),this._disposed=!0,this.hide(),this.lines=[],z(this.disposables))}},zB=wD;var Vn=new Map,GB=class{getProvider(e){return{onDidChange:null,provideTextDocumentContent:async i=>{let n=this.get(i.path.slice(1));return n?(e.pauseNotification(),e.command("setlocal nospell nofoldenable nowrap noswapfile",!0),e.command("setlocal buftype=nofile bufhidden=hide",!0),e.command("setfiletype log",!0),await e.resumeNotification(),n.content):""}}}get names(){return Array.from(Vn.keys())}get(e){return Vn.get(e)}create(e,t){if(Vn.has(e))return Vn.get(e);if(!/^[\w\s-.]+$/.test(e))throw new Error(`Invalid channel name "${e}", only word characters and white space allowed.`);let i=new zB(e,t,()=>{Vn.delete(e)});return Vn.set(e,i),i}show(e,t){let i=Vn.get(e);!i||i.show(t)}dispose(){for(let e of Vn.values())e.dispose();Vn.clear()}},Qs=new GB;var bRe=U()("model-dialog"),xD=class{constructor(e,t){this.nvim=e;this.config=t;this.disposables=[];A.on("BufWinLeave",i=>{i==this.bufnr&&(this.dispose(),t.callback&&t.callback(-1))},null,this.disposables),A.on("FloatBtnClick",(i,n)=>{if(i==this.bufnr){this.dispose();let o=t==null?void 0:t.buttons.filter(s=>s.disabled!=!0);t.callback&&t.callback(o[n].index)}},null,this.disposables)}get lines(){return[...this.config.content.split(/\r?\n/)]}async show(e){let{nvim:t}=this,{title:i,close:n,buttons:o}=this.config,s=this.config.borderhighlight||e.floatBorderHighlight,a=this.config.highlight||e.floatHighlight,l={maxwidth:e.maxWidth||80};i&&(l.title=i),(n||typeof n=="undefined")&&(l.close=1),e.maxHeight&&(l.maxHeight=e.maxHeight),e.maxWidth&&(l.maxWidth=e.maxWidth),a&&(l.highlight=a),s&&(l.borderhighlight=[s]),o&&(l.buttons=o.filter(c=>!c.disabled).map(c=>c.text));let u=await t.call("coc#float#create_dialog",[this.lines,l]);!u[1]||(this.bufnr=u[1],t.command("redraw",!0))}get winid(){return this.bufnr?this.nvim.call("bufwinid",[this.bufnr]):Promise.resolve(null)}dispose(){this.bufnr=void 0,z(this.disposables),this.disposables=[]}},VB=xD;var KB=S(W());var jm=process.env.VIM_NODE_RPC=="1",DD=class{constructor(e,t,i){this.nvim=e;this.winid=t;this.bufnr=i}get valid(){return this.nvim.call("coc#float#valid",[this.winid]).then(e=>!!e)}close(){this.nvim.call("coc#float#close",[this.winid],!0)}refreshScrollbar(){jm||this.nvim.call("coc#float#nvim_scrollbar",[this.winid],!0)}execute(e){this.nvim.call("coc#float#execute",[this.winid,e],!0)}click(e,t){let{nvim:i}=this;i.call("win_gotoid",[this.winid],!0),i.call("cursor",[e,t],!0),i.call("coc#float#nvim_float_click",[],!0)}async scrollForward(){let{nvim:e,bufnr:t,winid:i}=this,o=await e.createBuffer(t).length,s;if(jm)s=await e.eval(`get(popup_getpos(${i}), 'lastline', 0)`);else{let a=await e.call("getwininfo",[i]);if(!a||!a.length)return;s=a[0].botline}s>=o||s==0||(e.pauseNotification(),this.setCursor(s-1),this.execute(`normal! ${s}Gzt`),this.refreshScrollbar(),e.command("redraw",!0),e.resumeNotification(!1,!0))}async scrollBackward(){let{nvim:e,winid:t}=this,i;if(jm)i=await e.eval(`get(popup_getpos(${t}), 'firstline', 0)`);else{let n=await e.call("getwininfo",[t]);if(!n||!n.length)return;i=n[0].topline}i!=1&&(e.pauseNotification(),this.setCursor(i-1),this.execute(`normal! ${i}Gzb`),this.refreshScrollbar(),e.command("redraw",!0),e.resumeNotification(!1,!0))}setCursor(e){let{nvim:t,bufnr:i,winid:n}=this;jm?t.call("win_execute",[n,`exe ${e+1}`],!0):(t.createWindow(n).notify("nvim_win_set_cursor",[[e+1,0]]),t.command(`sign unplace 6 buffer=${i}`,!0),t.command(`sign place 6 line=${e+1} name=CocCurrentLine buffer=${i}`,!0))}},Um=DD;var zpe=U()("model-menu"),SD=class{constructor(e,t,i){this.nvim=e;this.config=t;this.currIndex=0;this.disposables=[];this.keyMappings=new Map;this._onDidClose=new KB.Emitter;this.onDidClose=this._onDidClose.event;this.total=t.items.length,i&&i.onCancellationRequested(()=>{var n;(n=this.win)==null||n.close()}),this.disposables.push(this._onDidClose),this.addKeymappings()}attachEvents(){A.on("InputChar",this.onInputChar.bind(this),null,this.disposables),A.on("BufWinLeave",e=>{e==this.bufnr&&(this._onDidClose.fire(-1),this.bufnr=void 0,this.win=void 0,this.dispose())},null,this.disposables)}addKeymappings(){let{nvim:e}=this;this.addKeys(["",""],()=>{this._onDidClose.fire(-1),this.dispose()}),this.addKeys(["\r",""],()=>{this._onDidClose.fire(this.currIndex),this.dispose()});let t=o=>{var s;!this.win||(e.pauseNotification(),this.setCursor(o),(s=this.win)==null||s.refreshScrollbar(),e.command("redraw",!0),e.resumeNotification(!1,!0))};this.addKeys("",async()=>{var o;await((o=this.win)==null?void 0:o.scrollForward())}),this.addKeys("",async()=>{var o;await((o=this.win)==null?void 0:o.scrollBackward())}),this.addKeys(["j","","",""],()=>{let o=this.currIndex==this.total-1?0:this.currIndex+1;t(o)}),this.addKeys(["k","","",""],()=>{let o=this.currIndex==0?this.total-1:this.currIndex-1;t(o)}),this.addKeys(["g"],()=>{t(0)}),this.addKeys(["G"],()=>{t(this.total-1)});let i,n;this.addKeys(["0","1","2","3","4","5","6","7","8","9"],o=>{i&&clearTimeout(i);let s=parseInt(o,10);if(!(isNaN(s)||s>this.total)&&!(n==null&&s==0)){if(n){let a=n*10+s;n=void 0,this._onDidClose.fire(a-1),this.dispose();return}if(this.total<10||s*10>this.total){this._onDidClose.fire(s-1),this.dispose();return}i=setTimeout(async()=>{this._onDidClose.fire(s-1),this.dispose()},200),n=s}})}async show(e={}){let{nvim:t}=this,{title:i,items:n}=this.config,o={};i&&(o.title=i),e.maxHeight&&(o.maxHeight=e.maxHeight),e.maxWidth&&(o.maxWidth=e.maxWidth),e.floatHighlight&&(o.highlight=e.floatHighlight),e.floatBorderHighlight&&(o.borderhighlight=[e.floatBorderHighlight]);let s=n.map((l,u)=>u<99?`${u+1}. ${l}`:l);e.confirmKey&&e.confirmKey!=""&&this.addKeys(e.confirmKey,()=>{this._onDidClose.fire(this.currIndex),this.dispose()});let a=await t.call("coc#float#create_menu",[s,o]);return this.win=new Um(t,a[0],a[1]),this.bufnr=a[1],this.attachEvents(),t.call("coc#prompt#start_prompt",["menu"],!0),a[0]}get buffer(){return this.bufnr?this.nvim.createBuffer(this.bufnr):void 0}dispose(){var e;z(this.disposables),this.disposables=[],this.nvim.call("coc#prompt#stop_prompt",["menu"],!0),(e=this.win)==null||e.close(),this.win=void 0}async onInputChar(e,t){if(e!="menu"||!this.win)return;let i=this.keyMappings.get(t);i?await Promise.resolve(i(t)):zpe.warn(`Ignored key press: ${t}`)}setCursor(e){!this.win||(this.currIndex=e,this.win.setCursor(e))}addKeys(e,t){if(Array.isArray(e))for(let i of e)this.keyMappings.set(i,t);else this.keyMappings.set(e,t)}},JB=SD;var YB=process.env.VIM_NODE_RPC=="1",IRe=U()("model-notification"),ED=class{constructor(e,t,i=!0){this.nvim=e;this.config=t;this.disposables=[];this._disposed=!1;i&&(A.on("BufWinLeave",n=>{n==this.bufnr&&(this.dispose(),t.callback&&t.callback(-1))},null,this.disposables),A.on("FloatBtnClick",(n,o)=>{if(n==this.bufnr){this.dispose();let s=t==null?void 0:t.buttons.filter(a=>a.disabled!=!0);t.callback&&t.callback(s[o].index)}},null,this.disposables))}get lines(){return this.config.content.split(/\r?\n/)}async show(e){let{nvim:t}=this,{title:i,close:n,timeout:o,buttons:s,borderhighlight:a}=this.config,l=Object.assign({},e);l.close=n?1:0,i&&(l.title=i),a&&(l.borderhighlight=a),s&&(l.buttons=s.filter(c=>!c.disabled).map(c=>c.text)),o&&(l.timeout=o);let u=await t.call("coc#float#create_notification",[this.lines,l]);return u?(this._disposed?(this.nvim.call("coc#float#close",[u[0]],!0),YB&&this.nvim.command("redraw",!0)):(this._winid=u[0],this.bufnr=u[1]),this._winid!=null):!1}get winid(){return this._winid}dispose(){if(this._disposed)return;this._disposed=!0;let{winid:e}=this;e&&(this.nvim.call("coc#float#close",[e],!0),YB&&this.nvim.command("redraw",!0)),this.bufnr=void 0,this._winid=void 0,z(this.disposables),this.disposables=[]}},Uf=ED;var XB=S(W());var Gpe=U()("model-dialog"),ZB=process.env.VIM_NODE_RPC=="1",CD=class{constructor(e,t,i){this.nvim=e;this.config=t;this.picked=new Set;this.currIndex=0;this.disposables=[];this.keyMappings=new Map;this._onDidClose=new XB.Emitter;this.onDidClose=this._onDidClose.event;for(let n=0;n{var n;(n=this.win)==null||n.close()}),this.disposables.push(this._onDidClose),this.addKeymappings()}attachEvents(){A.on("InputChar",this.onInputChar.bind(this),null,this.disposables),A.on("BufWinLeave",e=>{e==this.bufnr&&(this._onDidClose.fire(void 0),this.bufnr=void 0,this.win=void 0,this.dispose())},null,this.disposables),A.on("FloatBtnClick",(e,t)=>{if(e==this.bufnr){if(t==0){let i=Array.from(this.picked);this._onDidClose.fire(i.length?i:void 0)}else this._onDidClose.fire(void 0);this.dispose()}},null,this.disposables)}addKeymappings(){let{nvim:e}=this,t=n=>{this.picked.has(n)?this.picked.delete(n):this.picked.add(n)};this.addKeys("",async()=>{if(ZB||!this.win)return;let[n,o,s]=await e.eval("[v:mouse_winid,v:mouse_lnum,v:mouse_col]");if(global.hasOwnProperty("__TEST__")){let a=await e.getVar("mouse_position");n=a[0],o=a[1],s=a[2]}e.pauseNotification(),n==this.win.winid&&(s<=3?(t(o-1),this.changeLine(o-1)):this.setCursor(o-1)),e.call("win_gotoid",[n],!0),e.call("cursor",[o,s],!0),e.call("coc#float#nvim_float_click",[],!0),e.command("redraw",!0),await e.resumeNotification()}),this.addKeys(["",""],()=>{this._onDidClose.fire(void 0),this.dispose()}),this.addKeys("",()=>{if(this.picked.size==0)this._onDidClose.fire(void 0);else{let n=Array.from(this.picked);this._onDidClose.fire(n)}this.dispose()});let i=n=>{e.pauseNotification(),this.setCursor(n),this.win.refreshScrollbar(),e.command("redraw",!0),e.resumeNotification(!1,!0)};this.addKeys(["j","","",""],()=>{let n=this.currIndex==this.total-1?0:this.currIndex+1;i(n)}),this.addKeys(["k","","",""],()=>{let n=this.currIndex==0?this.total-1:this.currIndex-1;i(n)}),this.addKeys(["g"],()=>{i(0)}),this.addKeys(["G"],()=>{i(this.total-1)}),this.addKeys(" ",async()=>{let n=this.currIndex;t(n),e.pauseNotification(),this.changeLine(n),this.currIndex!=this.total-1&&this.setCursor(this.currIndex+1),e.command("redraw",!0),await e.resumeNotification()}),this.addKeys("",async()=>{var n;await((n=this.win)==null?void 0:n.scrollForward())}),this.addKeys("",async()=>{var n;await((n=this.win)==null?void 0:n.scrollBackward())})}async show(e={}){let{nvim:t}=this,{title:i,items:n}=this.config,o={close:1,cursorline:1};if(e.maxHeight&&(o.maxHeight=e.maxHeight),e.maxWidth&&(o.maxWidth=e.maxWidth),i&&(o.title=i),o.close=1,o.cursorline=1,e.floatHighlight&&(o.highlight=e.floatHighlight),e.floatBorderHighlight&&(o.borderhighlight=[e.floatBorderHighlight]),e.pickerButtons){let c=e.pickerButtonShortcut;o.buttons=["Submit"+(c?" ":""),"Cancel"+(c?" ":"")]}e.confirmKey&&e.confirmKey!=""&&this.addKeys(e.confirmKey,()=>{this._onDidClose.fire(void 0),this.dispose()});let s=[],a=[];for(let c=0;c{i==this.bufnr&&(this.tokenSource&&this.tokenSource.cancel(),this.dispose())},null,this.disposables)}async show(e){let{task:t}=this.option,i=this.tokenSource=new e3.CancellationTokenSource;this.disposables.push(i);let n=0;return await new Promise((s,a)=>{i.token.onCancellationRequested(()=>{s(void 0)}),super.show(Object.assign({minWidth:e.minProgressWidth||30,progress:1},e)).then(l=>{l||a(new Error("Failed to create float window"))}).catch(a),t({report:l=>{if(!this.bufnr)return;let u="";l.message&&(u+=l.message.replace(/\r?\n/g," ")),l.increment&&(n+=l.increment,u=u+(u.length?` ${n}%`:`${n}%`)),this.nvim.call("setbufline",[this.bufnr,2,u],!0)}},i.token).then(l=>{this._disposed||(setTimeout(()=>{this.dispose()},100),s(l))},l=>{this._disposed||(this.dispose(),l instanceof Error?a(l):s(void 0))})})}dispose(){super.dispose(),this.tokenSource=void 0}},t3=_D;var r3=S(require("crypto"));function Wf(){return r3.default.randomBytes(16)}var i3=[];for(var Wm=0;Wm<256;++Wm)i3[Wm]=(Wm+256).toString(16).substr(1);function Vpe(r,e){var t=e||0,i=i3;return[i[r[t++]],i[r[t++]],i[r[t++]],i[r[t++]],"-",i[r[t++]],i[r[t++]],"-",i[r[t++]],i[r[t++]],"-",i[r[t++]],i[r[t++]],"-",i[r[t++]],i[r[t++]],i[r[t++]],i[r[t++]],i[r[t++]],i[r[t++]]].join("")}var Hm=Vpe;var n3,PD,TD=0,RD=0;function Kpe(r,e,t){var i=e&&t||0,n=e||[];r=r||{};var o=r.node||n3,s=r.clockseq!==void 0?r.clockseq:PD;if(o==null||s==null){var a=r.random||(r.rng||Wf)();o==null&&(o=n3=[a[0]|1,a[1],a[2],a[3],a[4],a[5]]),s==null&&(s=PD=(a[6]<<8|a[7])&16383)}var l=r.msecs!==void 0?r.msecs:new Date().getTime(),u=r.nsecs!==void 0?r.nsecs:RD+1,c=l-TD+(u-RD)/1e4;if(c<0&&r.clockseq===void 0&&(s=s+1&16383),(c<0||l>TD)&&r.nsecs===void 0&&(u=0),u>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");TD=l,RD=u,PD=s,l+=122192928e5;var f=((l&268435455)*1e4+u)%4294967296;n[i++]=f>>>24&255,n[i++]=f>>>16&255,n[i++]=f>>>8&255,n[i++]=f&255;var p=l/4294967296*1e4&268435455;n[i++]=p>>>8&255,n[i++]=p&255,n[i++]=p>>>24&15|16,n[i++]=p>>>16&255,n[i++]=s>>>8|128,n[i++]=s&255;for(var d=0;d<6;++d)n[i+d]=o[d];return e||Hm(n)}var $o=Kpe;function Jpe(r,e,t){var i=e&&t||0;typeof r=="string"&&(e=r==="binary"?new Array(16):null,r=null),r=r||{};var n=r.random||(r.rng||Wf)();if(n[6]=n[6]&15|64,n[8]=n[8]&63|128,e)for(var o=0;o<16;++o)e[i+o]=n[o];return e||Hm(n)}var he=Jpe;var eke=U()("model-status"),kD=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],ID=class{constructor(e){this.nvim=e;this.items=new Map;this.shownIds=new Set;this._text="";this.interval=setInterval(()=>{this.setStatusText().logError()},100)}dispose(){clearInterval(this.interval)}createStatusBarItem(e=0,t=!1){let i=$o(),n={text:"",priority:e,isProgress:t,show:()=>{this.shownIds.add(i)},hide:()=>{this.shownIds.delete(i)},dispose:()=>{this.shownIds.delete(i),this.items.delete(i)}};return this.items.set(i,n),n}getText(){if(this.shownIds.size==0)return"";let e=new Date,t=Math.floor(e.getMilliseconds()/100),i="",n=[];for(let[o,s]of this.items)this.shownIds.has(o)&&n.push(s);n.sort((o,s)=>o.priority-s.priority);for(let o of n)o.isProgress?i=`${i} ${kD[t]} ${o.text}`:i=`${i} ${o.text}`;return i}async setStatusText(){let e=this.getText(),{nvim:t}=this;e!=this._text&&(this._text=e,t.pauseNotification(),this.nvim.setVar("coc_status",e,!0),this.nvim.call("coc#util#do_autocmd",["CocStatusChange"],!0),await t.resumeNotification(!1,!0))}},o3=ID;var Jr;(function(r){r[r.Buffer=0]="Buffer",r[r.LanguageServer=1]="LanguageServer",r[r.Global=2]="Global"})(Jr||(Jr={}));var Yr;(function(r){r[r.Global=0]="Global",r[r.Local=1]="Local",r[r.SingleFile=2]="SingleFile",r[r.Internal=3]="Internal"})(Yr||(Yr={}));var Xr;(function(r){r[r.Native=0]="Native",r[r.Remote=1]="Remote",r[r.Service=2]="Service"})(Xr||(Xr={}));var gn;(function(r){r[r.More=0]="More",r[r.Warning=1]="Warning",r[r.Error=2]="Error"})(gn||(gn={}));var dt;(function(r){r[r.Global=0]="Global",r[r.User=1]="User",r[r.Workspace=2]="Workspace"})(dt||(dt={}));var ye;(function(r){r[r.Initial=0]="Initial",r[r.Starting=1]="Starting",r[r.StartFailed=2]="StartFailed",r[r.Running=3]="Running",r[r.Stopping=4]="Stopping",r[r.Stopped=5]="Stopped"})(ye||(ye={}));var jj=S(l3()),Uj=S(Ul()),St=S($i()),Qi=S(require("os")),Fe=S(require("path"));var le=S(W());var Wj=S(_l());var JD=S(require("os")),Uo=S(require("fs")),Xi=S(require("path")),YD=S(W());var S3=S(W());"use strict";var y3=function(){function r(e,t,i,n){this._uri=e,this._languageId=t,this._version=i,this._content=n,this._lineOffsets=void 0}return Object.defineProperty(r.prototype,"uri",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"languageId",{get:function(){return this._languageId},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"version",{get:function(){return this._version},enumerable:!0,configurable:!0}),r.prototype.getText=function(e){if(e){var t=this.offsetAt(e.start),i=this.offsetAt(e.end);return this._content.substring(t,i)}return this._content},r.prototype.update=function(e,t){for(var i=0,n=e;ie?n=o:i=o+1}var s=i-1;return{line:s,character:e-t[s]}},r.prototype.offsetAt=function(e){var t=this.getLineOffsets();if(e.line>=t.length)return this._content.length;if(e.line<0)return 0;var i=t[e.line],n=e.line+1l&&u.push(s.substring(l,d)),p.newText.length&&u.push(p.newText),l=n.offsetAt(p.range.end)}return u.push(s.substr(l)),u.join("")}r.applyEdits=i})(kt||(kt={}));function LD(r,e){if(r.length<=1)return r;var t=r.length/2|0,i=r.slice(0,t),n=r.slice(t);LD(i,e),LD(n,e);for(var o=0,s=0,a=0;ot.line||e.line===t.line&&e.character>t.character?{start:t,end:e}:r}function ode(r){var e=v3(r.range);return e!==r.range?{newText:r.newText,range:e}:r}"use strict";function Gf(r,e){e===void 0&&(e=!1);var t=r.length,i=0,n="",o=0,s=16,a=0,l=0,u=0,c=0,f=0;function p(x,E){for(var P=0,k=0;P=48&&_<=57)k=k*16+_-48;else if(_>=65&&_<=70)k=k*16+_-65+10;else if(_>=97&&_<=102)k=k*16+_-97+10;else break;i++,P++}return P=t){x+=r.substring(E,i),f=2;break}var P=r.charCodeAt(i);if(P===34){x+=r.substring(E,i),i++;break}if(P===92){if(x+=r.substring(E,i),i++,i>=t){f=2;break}var k=r.charCodeAt(i++);switch(k){case 34:x+='"';break;case 92:x+="\\";break;case 47:x+="/";break;case 98:x+="\b";break;case 102:x+="\f";break;case 110:x+=` -`;break;case 114:x+="\r";break;case 116:x+=" ";break;case 117:var _=p(4,!0);_>=0?x+=String.fromCharCode(_):f=4;break;default:f=5}E=i;continue}if(P>=0&&P<=31)if(zf(P)){x+=r.substring(E,i),f=2;break}else f=6;i++}return x}function y(){if(n="",f=0,o=i,l=a,c=u,i>=t)return o=t,s=17;var x=r.charCodeAt(i);if(MD(x)){do i++,n+=String.fromCharCode(x),x=r.charCodeAt(i);while(MD(x));return s=15}if(zf(x))return i++,n+=String.fromCharCode(x),x===13&&r.charCodeAt(i)===10&&(i++,n+=` -`),a++,u=i,s=14;switch(x){case 123:return i++,s=1;case 125:return i++,s=2;case 91:return i++,s=3;case 93:return i++,s=4;case 58:return i++,s=6;case 44:return i++,s=5;case 34:return i++,n=m(),s=10;case 47:var E=i-1;if(r.charCodeAt(i+1)===47){for(i+=2;i=12&&x<=15);return x}return{setPosition:d,getPosition:function(){return i},scan:e?w:y,getToken:function(){return s},getTokenValue:function(){return n},getTokenOffset:function(){return o},getTokenLength:function(){return i-o},getTokenStartLine:function(){return l},getTokenStartCharacter:function(){return o-c},getTokenError:function(){return f}}}function MD(r){return r===32||r===9||r===11||r===12||r===160||r===5760||r>=8192&&r<=8203||r===8239||r===8287||r===12288||r===65279}function zf(r){return r===10||r===13||r===8232||r===8233}function Wl(r){return r>=48&&r<=57}"use strict";function qD(r,e,t){var i,n,o,s,a;if(e){for(s=e.offset,a=s+e.length,o=s;o>0&&!Vf(r,o-1);)o--;for(var l=a;ls&&r.substring(F,q)!==R&&g.push({offset:F,length:q-F,content:R})}var x=y();if(x!==17){var E=d.getTokenOffset()+o,P=ND(p,i);w(P,o,E)}for(;x!==17;){for(var k=d.getTokenOffset()+d.getTokenLength()+o,_=y(),L="";!c&&(_===12||_===13);){var I=d.getTokenOffset()+o;w(" ",k,I),k=d.getTokenOffset()+d.getTokenLength()+o,L=_===12?m():"",_=y()}if(_===2)x!==1&&(f--,L=m());else if(_===4)x!==3&&(f--,L=m());else{switch(x){case 3:case 1:f++,L=m();break;case 5:case 12:L=m();break;case 13:c?L=m():L=" ";break;case 6:L=" ";break;case 10:if(_===6){L="";break}case 7:case 8:case 9:case 11:case 2:case 4:_===12||_===13?L=" ":_!==5&&_!==17&&(h=!0);break;case 16:h=!0;break}c&&(_===12||_===13)&&(L=m())}var O=d.getTokenOffset()+o;w(L,k,O),x=_}return g}function ND(r,e){for(var t="",i=0;i=t.children.length)return;t=t.children[c]}}return t}}function $D(r,e,t){t===void 0&&(t=Kf.DEFAULT);var i=Gf(r,!1);function n(I){return I?function(){return I(i.getTokenOffset(),i.getTokenLength(),i.getTokenStartLine(),i.getTokenStartCharacter())}:function(){return!0}}function o(I){return I?function(O){return I(O,i.getTokenOffset(),i.getTokenLength(),i.getTokenStartLine(),i.getTokenStartCharacter())}:function(){return!0}}var s=n(e.onObjectBegin),a=o(e.onObjectProperty),l=n(e.onObjectEnd),u=n(e.onArrayBegin),c=n(e.onArrayEnd),f=o(e.onLiteralValue),p=o(e.onSeparator),d=n(e.onComment),h=o(e.onError),m=t&&t.disallowComments,y=t&&t.allowTrailingComma;function g(){for(;;){var I=i.scan();switch(i.getTokenError()){case 4:w(14);break;case 5:w(15);break;case 3:w(13);break;case 1:m||w(11);break;case 2:w(12);break;case 6:w(16);break}switch(I){case 12:case 13:m?w(10):d();break;case 16:w(1);break;case 15:case 14:break;default:return I}}}function w(I,O,R){if(O===void 0&&(O=[]),R===void 0&&(R=[]),h(I),O.length+R.length>0)for(var F=i.getToken();F!==17;){if(O.indexOf(F)!==-1){g();break}else if(R.indexOf(F)!==-1)break;F=g()}}function x(I){var O=i.getTokenValue();return I?f(O):a(O),g(),!0}function E(){switch(i.getToken()){case 11:var I=i.getTokenValue(),O=Number(I);isNaN(O)&&(w(2),O=0),f(O);break;case 7:f(null);break;case 8:f(!0);break;case 9:f(!1);break;default:return!1}return g(),!0}function P(){return i.getToken()!==10?(w(3,[],[2,5]),!1):(x(!1),i.getToken()===6?(p(":"),g(),L()||w(4,[],[2,5])):w(5,[],[2,5]),!0)}function k(){s(),g();for(var I=!1;i.getToken()!==2&&i.getToken()!==17;){if(i.getToken()===5){if(I||w(4,[],[]),p(","),g(),i.getToken()===2&&y)break}else I&&w(6,[],[]);P()||w(4,[],[2,5]),I=!0}return l(),i.getToken()!==2?w(7,[2],[]):g(),!0}function _(){u(),g();for(var I=!1;i.getToken()!==4&&i.getToken()!==17;){if(i.getToken()===5){if(I||w(4,[],[]),p(","),g(),i.getToken()===4&&y)break}else I&&w(6,[],[]);L()||w(4,[],[4,5]),I=!0}return c(),i.getToken()!==4?w(8,[4],[]):g(),!0}function L(){switch(i.getToken()){case 3:return _();case 1:return k();case 10:return x(!0);default:return E()}}return g(),i.getToken()===17?t.allowEmptyContent?!0:(w(4,[],[]),!1):L()?(i.getToken()!==17&&w(9,[],[]),!0):(w(4,[],[]),!1)}function lde(r){switch(typeof r){case"boolean":return"boolean";case"number":return"number";case"string":return"string";case"object":{if(r){if(Array.isArray(r))return"array"}else return"null";return"object"}default:return"null"}}"use strict";function w3(r,e,t,i){for(var n,o=e.slice(),s=[],a=BD(r,s),l=void 0,u=void 0;o.length>0&&(u=o.pop(),l=Vm(a,o),l===void 0&&t!==void 0);)typeof u=="string"?t=(n={},n[u]=t,n):t=[t];if(l)if(l.type==="object"&&typeof u=="string"&&Array.isArray(l.children)){var c=Vm(l,[u]);if(c!==void 0)if(t===void 0){if(!c.parent)throw new Error("Malformed AST");var f=l.children.indexOf(c.parent),p=void 0,d=c.parent.offset+c.parent.length;if(f>0){var h=l.children[f-1];p=h.offset+h.length}else if(p=l.offset+1,l.children.length>1){var m=l.children[1];d=m.offset}return ea(r,{offset:p,length:d-p,content:""},i)}else return ea(r,{offset:c.offset,length:c.length,content:JSON.stringify(t)},i);else{if(t===void 0)return[];var y=JSON.stringify(u)+": "+JSON.stringify(t),g=i.getInsertionIndex?i.getInsertionIndex(l.children.map(function(I){return I.children[0].value})):l.children.length,w=void 0;if(g>0){var h=l.children[g-1];w={offset:h.offset+h.length,length:0,content:","+y}}else l.children.length===0?w={offset:l.offset+1,length:0,content:y}:w={offset:l.offset+1,length:0,content:y+","};return ea(r,w,i)}}else if(l.type==="array"&&typeof u=="number"&&Array.isArray(l.children)){var x=u;if(x===-1){var y=""+JSON.stringify(t),w=void 0;if(l.children.length===0)w={offset:l.offset+1,length:0,content:y};else{var h=l.children[l.children.length-1];w={offset:h.offset+h.length,length:0,content:","+y}}return ea(r,w,i)}else if(t===void 0&&l.children.length>=0){var E=u,P=l.children[E],w=void 0;if(l.children.length===1)w={offset:l.offset+1,length:l.length-2,content:""};else if(l.children.length-1===E){var h=l.children[E-1],k=h.offset+h.length,_=l.offset+l.length;w={offset:k,length:_-2-k,content:""}}else w={offset:P.offset,length:l.children[E+1].offset-P.offset,content:""};return ea(r,w,i)}else if(t!==void 0){var w=void 0,y=""+JSON.stringify(t);if(!i.isArrayInsertion&&l.children.length>u){var L=l.children[u];w={offset:L.offset,length:L.length,content:y}}else if(l.children.length===0||u===0)w={offset:l.offset+1,length:0,content:l.children.length===0?y:y+","};else{var g=u>l.children.length?l.children.length:u,h=l.children[g-1];w={offset:h.offset+h.length,length:0,content:","+y}}return ea(r,w,i)}else throw new Error("Can not "+(t===void 0?"remove":i.isArrayInsertion?"insert":"modify")+" Array index "+x+" as length is not sufficient")}else throw new Error("Can not add "+(typeof u!="number"?"index":"property")+" to parent of type "+l.type);else{if(t===void 0)throw new Error("Can not delete in empty document");return ea(r,{offset:a?a.offset:0,length:a?a.length:0,content:JSON.stringify(t)},i)}}function ea(r,e,t){if(!t.formattingOptions)return[e];var i=Km(r,e),n=e.offset,o=e.offset+e.content.length;if(e.length===0||e.content.length===0){for(;n>0&&!Vf(i,n-1);)n--;for(;o=0;a--){var l=s[a];i=Km(i,l),n=Math.min(n,l.offset),o=Math.max(o,l.offset+l.length),o+=l.content.length-l.length}var u=r.length-(i.length-o)-n;return[{offset:n,length:u,content:i.substring(n,o)}]}function Km(r,e){return r.substring(0,e.offset)+e.content+r.substring(e.offset+e.length)}"use strict";var Hl=b3;function x3(r,e,t,i){return w3(r,e,t,i)}function D3(r,e){for(var t=e.length-1;t>=0;t--)r=Km(r,e[t]);return r}var Jf=S(require("fs"));var Jm=S(require("path")),ude=U()("configuration-util"),cde=Jm.dirname(__dirname);function E3(r,e){if(!r||!Jf.default.existsSync(r))return{contents:{}};let t,i=$.file(r).toString();try{t=Jf.default.readFileSync(r,"utf8")}catch(s){t=""}let[n,o]=fde(t);return n&&n.length&&e(pde(i,t,n)),{contents:o}}function fde(r){if(r.length==0)return[[],{}];let e=[],t=Hl(r,e,{allowTrailingComma:!0});function i(o,s,a,l){if(a.length==0)o[s]=n(l);else{o[s]||(o[s]={});let u=o[s],c=a.shift();i(u,c,a,l)}}function n(o,s=!1){if(!xt(o))return o;if(mm(o))return{};let a={};for(let l of Object.keys(o))if(s&&l.includes(".")){let u=l.split("."),c=u.shift();i(a,c,u,o[l])}else a[l]=n(o[l]);return a}return[e,n(t,!0)]}function pde(r,e,t){let i=[],n=kt.create(r,"json",0,e);for(let o of t){let s="parse error";switch(o.error){case 2:s="invalid number";break;case 8:s="close brace expected";break;case 5:s="colon expected";break;case 6:s="comma expected";break;case 9:s="end of file expected";break;case 16:s="invaliad character";break;case 10:s="invalid commment token";break;case 15:s="invalid escape character";break;case 1:s="invalid symbol";break;case 14:s="invalid unicode";break;case 3:s="property name expected";break;case 13:s="unexpected end of number";break;case 12:s="unexpected end of string";break;case 11:s="unexpected end of comment";break;case 4:s="value expected";break;default:s="Unknwn error";break}let a={start:n.positionAt(o.offset),end:n.positionAt(o.offset+o.length)},l=S3.Location.create(r,a);i.push({location:l,message:s})}return i}function Yf(r,e,t,i){let n=e.split("."),o=n.pop(),s=r;for(let a=0;a{let o=t[n].default;o!==void 0&&Yf(i,n,o,s=>{ude.error(s)})}),{contents:i}}function jD(r,e){let t=[];for(let i of Object.keys(r)){let n=r[i],o=e?`${e}.${i}`:i;t.push(o),xt(n)&&t.push(...jD(n,o))}return t}function T3(r,e){let t=[],i=jD(r),n=jD(e),o=n.filter(a=>!i.includes(a)),s=i.filter(a=>!n.includes(a));t.push(...o),t.push(...s);for(let a of i){if(!n.includes(a))continue;let l=Ym(r,a),u=Ym(e,a);qe(l,u)||t.push(a)}return t}var Ar=class{constructor(e={}){this._contents=e}get contents(){return this._contents}clone(){return new Ar(zn(this._contents))}getValue(e){return e?Ym(this.contents,e):this.contents}merge(...e){let t=zn(this.contents);for(let i of e)this.mergeContents(t,i.contents);return new Ar(t)}freeze(){return Object.isFrozen(this._contents)||Object.freeze(this._contents),this}mergeContents(e,t){for(let i of Object.keys(t)){if(i in e&&xt(e[i])&&xt(t[i])){this.mergeContents(e[i],t[i]);continue}e[i]=zn(t[i])}}setValue(e,t){Yf(this.contents,e,t,i=>{console.error(i)})}removeValue(e){_3(this.contents,e)}};var Xm=class{constructor(e,t,i,n=new Ar){this._defaultConfiguration=e;this._userConfiguration=t;this._workspaceConfiguration=i;this._memoryConfiguration=n}getConsolidateConfiguration(){return this._consolidateConfiguration||(this._consolidateConfiguration=this._defaultConfiguration.merge(this._userConfiguration,this._workspaceConfiguration,this._memoryConfiguration),this._consolidateConfiguration=this._consolidateConfiguration.freeze()),this._consolidateConfiguration}getValue(e){return this.getConsolidateConfiguration().getValue(e)}inspect(e){let t=this.getConsolidateConfiguration(),{_workspaceConfiguration:i,_memoryConfiguration:n}=this;return{default:this._defaultConfiguration.freeze().getValue(e),user:this._userConfiguration.freeze().getValue(e),workspace:i.freeze().getValue(e),memory:n.freeze().getValue(e),value:t.getValue(e)}}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}}}};var Ode=S(require("child_process")),Ci=S($i()),Lde=S(require("net")),VD=S(require("os")),Zr=S(require("path")),KD=S(require("readline")),Mde=S(require("util")),Y3=S(ta()),Wke=U()("util-fs");async function It(r){let e=null;try{e=await Ci.default.stat(r)}catch(t){}return e}function X3(r,e){return new Promise((t,i)=>{Ci.default.rename(r,e,n=>{if(n)return i(n);t()})})}function Qf(r,e,t,i=!1,n=!0){let o=VD.default.homedir(),s=Zf(r);if(Xe(s,o,!0))return null;if(n&&t&&Xe(t,s,!0)&&jo(t,e))return t;let a=s.split(Zr.default.sep);if(i){for(;a.length>0;){let l=a.join(Zr.default.sep);if(l==o)break;if(l!=o&&jo(l,e))return l;a.pop()}return null}else{let l=[a.shift()];for(let u of a){l.push(u);let c=l.join(Zr.default.sep);if(c!=o&&jo(c,e))return c}return null}}function jo(r,e){try{let t=Ci.default.readdirSync(r);for(let i of e)if(i.includes("*")?Y3.default.match(t,i,{nobrace:!0,noext:!0,nocomment:!0,nonegate:!0,dot:!0}).length!==0:t.includes(i))return!0}catch(t){}return!1}function Gl(r,e){let t=Zr.default.parse(e).root,i=Array.isArray(r)?r:[r];for(;e&&e!==t;){if(jo(e,i))for(let o of i){let s=Zr.default.join(e,o);if(Ci.default.existsSync(s))return s}e=Zr.default.dirname(e)}return null}function Vl(r,e){return new Promise((t,i)=>{Ci.default.readFile(r,e,(n,o)=>{n&&i(n),t(o)})})}function Z3(r){let e,t=0;return new Promise((i,n)=>{Ci.default.createReadStream(r).on("error",o=>n(o)).on("data",o=>{for(e=0;ei(t))})}function Q3(r,e,t){if(!Ci.default.existsSync(r))return Promise.reject(new Error(`file does not exist: ${r}`));let i=[],n=KD.default.createInterface({input:Ci.default.createReadStream(r,{encoding:"utf8"}),crlfDelay:Infinity,terminal:!1}),o=0;return new Promise((s,a)=>{n.on("line",l=>{o==0&&l.startsWith("\uFEFF")&&(l=l.slice(1)),o>=e&&o<=t&&i.push(l),o==t&&n.close(),o=o+1}),n.on("close",()=>{s(i)}),n.on("error",a)})}function ej(r,e){if(!Ci.default.existsSync(r))return Promise.reject(new Error(`file does not exist: ${r}`));let t=KD.default.createInterface({input:Ci.default.createReadStream(r,{encoding:"utf8"}),crlfDelay:Infinity,terminal:!1}),i=0;return new Promise((n,o)=>{t.on("line",s=>{if(i==e){i==0&&s.startsWith("\uFEFF")&&(s=s.slice(1)),t.close(),n(s);return}i=i+1}),t.on("error",o)})}async function tj(r,e){await Ci.default.writeFile(r,e,{encoding:"utf8"})}function Qm(r){return r.startsWith("file:")}function Xe(r,e,t=!1){let i=Zf(Zr.default.resolve(Zr.default.normalize(r))),n=Zf(Zr.default.resolve(Zr.default.normalize(e)));return i=="//"&&(i="/"),i==n?!!t:i.endsWith(Zr.default.sep)?n.startsWith(i):n.startsWith(i)&&n[i.length]==Zr.default.sep}function Zf(r){return VD.default.platform()!="win32"||r[1]!=":"?r:r[0].toUpperCase()+r.slice(1)}var Nde=U()("configurations");function XD(r,e){if(e){if(r&&r.hasOwnProperty(e))return r[e];let t=e.split("."),i=r;for(let n=0;i&&nn.location.uri!=t);let i=E3(e,n=>{this._errorItems.push(...n)});return this._onError.fire(this._errorItems),i}get errorItems(){return this._errorItems}get foldConfigurations(){return this._folderConfigurations}extendsDefaults(e){let{defaults:t}=this._configuration,{contents:i}=t;i=zn(i),Object.keys(e).forEach(o=>{Yf(i,o,e[o],s=>{Nde.error(s)})});let n={defaults:{contents:i},user:this._configuration.user,workspace:this._configuration.workspace};this._configuration=ra.parse(n)}updateUserConfig(e){if(!e||Object.keys(e).length==0)return;let{user:t}=this._configuration,i=t.clone();Object.keys(e).forEach(n=>{let o=e[n];if(o===void 0)i.removeValue(n);else if(xt(o))for(let s of Object.keys(o))i.setValue(`${n}.${s}`,o[s]);else i.setValue(n,o)}),this.changeConfiguration(dt.User,i)}get defaults(){return this._configuration.defaults}get user(){return this._configuration.user}get workspace(){return this._configuration.workspace}addFolderFile(e){let{_folderConfigurations:t}=this;if(t.has(e)||Xi.default.resolve(e,"../..")==JD.default.homedir())return;let i=this.parseContentFromFile(e);this.watchFile(e,dt.Workspace),this.changeConfiguration(dt.Workspace,i,e)}watchFile(e,t){if(!Uo.default.existsSync(e)||global.hasOwnProperty("__TEST__"))return;let i=Rl(e,()=>{let n=this.parseContentFromFile(e);this.changeConfiguration(t,n,e)});this.disposables.push(i)}changeConfiguration(e,t,i){let{defaults:n,user:o,workspace:s}=this._configuration,{workspaceConfigFile:a}=this,l={defaults:e==dt.Global?t:n,user:e==dt.User?t:o,workspace:e==dt.Workspace?t:s},u=ra.parse(l),c=T3(this._configuration.getValue(),u.getValue());e==dt.Workspace&&i&&(this._folderConfigurations.set(i,new Ar(t.contents)),this.workspaceConfigFile=i),c.length!=0&&(this._configuration=u,this._onChange.fire({affectsConfiguration:(f,p)=>{if(!p||e!=dt.Workspace)return c.includes(f);let d=$.parse(p);if(d.scheme!=="file")return c.includes(f);let h=d.fsPath,m=a?Xi.default.resolve(a,"../.."):"";return i&&!Xe(m,h,!0)&&!Xe(Xi.default.resolve(i,"../.."),h)?!1:c.includes(f)}}))}setFolderConfiguration(e){let t=$.parse(e);if(t.scheme!="file")return;let i=t.fsPath;for(let[n,o]of this.foldConfigurations){let s=Xi.default.resolve(n,"../..");if(Xe(s,i,!0)&&this.workspaceConfigFile!=n){this.changeConfiguration(dt.Workspace,o,n);break}}}hasFolderConfiguration(e){let{folders:t}=this;return t.findIndex(i=>Xe(i,e,!0))!==-1}getConfigFile(e){return e==dt.Global?null:e==dt.User?this.userConfigFile:this.workspaceConfigFile}get folders(){let e=[],{_folderConfigurations:t}=this;for(let i of t.keys())e.push(Xi.default.resolve(i,"../.."));return e}get configuration(){return this._configuration}getConfiguration(e,t){let i;if(t){let{defaults:s,user:a}=this._configuration;i=new Xm(s,a,this.getFolderConfiguration(t))}else i=this._configuration;let n=Object.freeze(XD(i.getValue(null),e)),o={has(s){return typeof XD(n,s)!="undefined"},get:(s,a)=>{let l=XD(n,s);return l==null?a:l},update:(s,a,l=!1)=>{let u=e?`${e}.${s}`:s,c=l?dt.User:dt.Workspace,f=c==dt.User?this.user.clone():this.workspace.clone();if(a==null?f.removeValue(u):f.setValue(u,a),c==dt.Workspace&&!this.workspaceConfigFile&&this._proxy){let p=this.workspaceConfigFile=this._proxy.workspaceConfigFile;if(!Uo.default.existsSync(p)){let d=Xi.default.dirname(p);Uo.default.existsSync(d)||Uo.default.mkdirSync(d),Uo.default.writeFileSync(p,"{}",{encoding:"utf8"})}}this.changeConfiguration(c,f,c==dt.Workspace?this.workspaceConfigFile:this.userConfigFile),this._proxy&&!global.hasOwnProperty("__TEST__")&&(a==null?this._proxy.$removeConfigurationOption(c,u):this._proxy.$updateConfigurationOption(c,u,a))},inspect:s=>{s=e?`${e}.${s}`:s;let a=this._configuration.inspect(s);if(a)return{key:s,defaultValue:a.default,globalValue:a.user,workspaceValue:a.workspace}}};return Object.defineProperty(o,"has",{enumerable:!1}),Object.defineProperty(o,"get",{enumerable:!1}),Object.defineProperty(o,"update",{enumerable:!1}),Object.defineProperty(o,"inspect",{enumerable:!1}),typeof n=="object"&&Mx(o,n,!1),hq(o)}getFolderConfiguration(e){let t=$.parse(e);if(t.scheme!="file")return new Ar;let i=t.fsPath;for(let[n,o]of this.foldConfigurations){let s=Xi.default.resolve(n,"../..");if(Xe(s,i,!0))return o}return new Ar}checkFolderConfiguration(e){let t=$.parse(e);if(t.scheme!="file")return;let i=Xi.default.dirname(t.fsPath);if(this.hasFolderConfiguration(i))this.setFolderConfiguration(e);else{let n=Gl(".vim",i);if(n&&n!=JD.default.homedir()){let o=Xi.default.join(n,Gi);Uo.default.existsSync(o)&&this.addFolderFile(o)}}}static parse(e){let t=new Ar(e.defaults.contents),i=new Ar(e.user.contents),n=new Ar(e.workspace.contents);return new Xm(t,i,n,new Ar)}dispose(){z(this.disposables)}},rj=ra;var ZD=S(require("fs"));var QD=S(require("path"));var d1e=U()("configuration-shape"),e0=class{constructor(e){this.workspace=e}get nvim(){return this.workspace.nvim}async modifyConfiguration(e,t,i){let{nvim:n,workspace:o}=this,s=o.getConfigFile(e);if(!s)return;let a={tabSize:2,insertSpaces:!0},l=ZD.default.readFileSync(s,"utf8");i=i==null?void 0:i;let u=x3(l,[t],i,{formattingOptions:a});l=D3(l,u),ZD.default.writeFileSync(s,l,"utf8"),o.getDocument($.file(s).toString())&&n.command("checktime",!0)}get workspaceConfigFile(){let e=QD.default.join(this.workspace.root,".vim");return QD.default.join(e,Gi)}$updateConfigurationOption(e,t,i){this.modifyConfiguration(e,t,i).logError()}$removeConfigurationOption(e,t){this.modifyConfiguration(e,t).logError()}},ij=e0;var Qr=S($i()),t0=S(require("path")),r0=class{constructor(e){this.filepath=e}fetch(e){let t=this.load();if(!e)return t;let i=e.split(".");for(let n of i){if(typeof t[n]=="undefined")return;t=t[n]}return t}exists(e){let t=this.load(),i=e.split(".");for(let n of i){if(typeof t[n]=="undefined")return!1;t=t[n]}return!0}delete(e){let t=this.load(),i=t,n=e.split("."),o=n.length;for(let s=0;s0){let p=l;for(let d=0;ds.contains(o))||i.push(new _i(o))}return i}contains(e){return e>=this.start&&e<=this.end}},ep=class{constructor(e){this.ranges=[];e&&(this.ranges=_i.fromKeywordOption(e))}addKeyword(e){let t=e.charCodeAt(0),{ranges:i}=this;i.some(n=>n.contains(t))||i.push(new _i(t))}clone(){let e=new ep;return e.ranges=this.ranges.slice(),e}setKeywordOption(e){this.ranges=_i.fromKeywordOption(e)}matchKeywords(e,t=3){let i=e.length;if(i==0)return[];let n=new Set,o="",s=0;for(let a=0;a=t&&s<48&&n.add(o),o="",s=0}return s!=0&&n.add(o),Array.from(n)}isKeywordCode(e){return e>255?!0:e<33?!1:this.ranges.some(t=>t.contains(e))}isKeywordChar(e){let{ranges:t}=this,i=e.charCodeAt(0);return i>255?!0:i<33?!1:t.some(n=>n.contains(i))}isKeyword(e){let{ranges:t}=this;for(let i=0,n=e.length;i255)return!1;if(!t.some(s=>s.contains(o)))return!1}return!0}};function qde(r,e,t=0){let i=e?[t]:[];for(let n=0;ne?n=s:i=s+1}let o=i-1;return{line:o,character:e-t[o]}}offsetAt(e){let t=this.getLineOffsets();if(e.line>=t.length)return this._content.length;if(e.line<0)return 0;let i=t[e.line],n=e.line+1{this._fireContentChanges()},100),this.fetchContent=n0.default(()=>{this._fetchContent().logError()},100)}get content(){return this.syncLines.join(` -`)+(this.eol?` -`:"")}get version(){return this._version}get bufnr(){return this.buffer.id}get filetype(){return this._filetype}get uri(){return this._uri}get shouldAttach(){let{buftype:e,maxFileSize:t}=this;return this.getVar("enabled",!0)?this.uri.endsWith("%5BCommand%20Line%5D")?!0:this.size==-2||t&&this.size>t?!1:e==""||e=="acwrite":!1}get isCommandLine(){return this.uri&&this.uri.endsWith("%5BCommand%20Line%5D")}get enabled(){return this.getVar("enabled",!0)}get words(){return this._words}convertFiletype(e){let t=this.env.filetypeMap;return e=="javascript.jsx"?"javascriptreact":e=="typescript.jsx"||e=="typescript.tsx"?"typescriptreact":t[e]||e}get changedtick(){return this._changedtick}get schema(){return $.parse(this.uri).scheme}get lineCount(){return this.lines.length}get winid(){return this._winid}get previewwindow(){return this._previewwindow}async init(e,t){this.nvim=e;let i=await e.call("coc#util#get_bufoptions",[this.bufnr,this.maxFileSize]);if(i==null)return!1;let n=this.buftype=i.buftype;if(this._previewwindow=i.previewwindow,this._winid=i.winid,this.size=typeof i.size=="number"?i.size:0,this.variables=i.variables||{},this._changedtick=i.changedtick,this.eol=i.eol==1,this._uri=dm(i.fullpath,this.bufnr,n,this.env.isCygwin),t.isCancellationRequested)return!1;if(this.shouldAttach){if(this.lines=i.lines,this.syncLines=this.lines,!await this.attach())return!1;this._attached=!0}return this._filetype=this.convertFiletype(i.filetype),this.setIskeyword(i.iskeyword),t.isCancellationRequested?(this.detach(),!1):!0}async attach(){return await this.buffer.attach(!0)?(this.buffer.listen("lines",this.onChange.bind(this),this.disposables),this.buffer.listen("detach",async t=>{this._onDocumentDetach.fire(t.id)},this.disposables),!0):!1}async onChange(e,t,i,n,o){e.id!==this.bufnr||!this._attached||t==null||this.mutex.busy||t>this._changedtick&&(this._changedtick=t,this.lines=[...this.lines.slice(0,i),...o,...this.lines.slice(n)],this.fireContentChanges())}async checkDocument(){let{buffer:e}=this,t=await this.mutex.acquire();this.fireContentChanges.clear(),this._changedtick=await e.changedtick,this.lines=await e.lines,this._fireContentChanges()&&await He(30),t()}get dirty(){return this.lines===this.syncLines?!1:!qe(this.lines,this.syncLines)}_fireContentChanges(){let{cursor:e}=A,{textDocument:t}=this;try{let i=null;e&&e.bufnr==this.bufnr&&(i=this.getEndOffset(e.lnum,e.col,e.insert));let n=this.getDocumentContent(),o=oj(t.getText(),n,i);if(o==null)return;let s=t.positionAt(o.start),a=t.positionAt(o.end),l=t.getText(Zi.Range.create(s,a));this._version=this._version+1,this.syncLines=this.lines;let u=[{range:{start:s,end:a},rangeLength:o.end-o.start,text:o.newText}];return this._onDocumentChange.fire({bufnr:this.bufnr,original:l,textDocument:{version:this.version,uri:this.uri},contentChanges:u}),this._words=this.chars.matchKeywords(n),!0}catch(i){aj.error(i.message)}return!1}async applyEdits(e){if(!Array.isArray(arguments[0])&&Array.isArray(arguments[1])&&(e=arguments[1]),e.length==0)return;let t=this.getDocumentContent(),i=kt.create(this.uri,this.filetype,1,t),n=kt.applyEdits(i,e);if(Hn&&(n=n.replace(/\r\n/g,` -`)),t!==n){let o=(this.eol&&n.endsWith(` -`)?n.slice(0,-1):n).split(` -`),s=nj(this.lines,o),a=await this.mutex.acquire();try{let l=await this.nvim.call("coc#util#set_lines",[this.bufnr,s.replacement,s.start,s.end]);this._changedtick=l.changedtick,this.lines=o,this.fireContentChanges.clear(),this._fireContentChanges(),qe(o,l.lines)||process.nextTick(()=>{this.lines=l.lines,this.fireContentChanges.clear(),this._fireContentChanges()}),a()}catch(l){aj.error("Error on applyEdits: ",l),a()}}}async changeLines(e){let t=[],i=this.lines.slice();for(let[o,s]of e)i[o]!=s&&(t.push([o,s]),i[o]=s);if(!t.length)return;let n=await this.mutex.acquire();try{let o=await this.nvim.call("coc#util#change_lines",[this.bufnr,t]);o!=null&&(this.lines=i,this._changedtick=o.changedtick,this.fireContentChanges.clear(),this._fireContentChanges(),qe(i,o.lines)||process.nextTick(()=>{this.lines=o.lines,this.fireContentChanges.clear(),this._fireContentChanges()})),n()}catch(o){n()}}forceSync(){this.mutex.busy||(this.fireContentChanges.clear(),this._fireContentChanges())}getOffset(e,t){return this.textDocument.offsetAt({line:e-1,character:t})}isWord(e){return this.chars.isKeyword(e)}getMoreWords(){let e=[],{words:t,chars:i}=this;if(!i.isKeywordChar("-"))return e;for(let n of t)if(n=n.replace(/^-+/,""),n.includes("-")){let o=n.split("-");for(let s of o)s.length>2&&!e.includes(s)&&!t.includes(s)&&e.push(s)}return e}getWordRangeAtPosition(e,t,i=!0){let n=this.chars.clone();if(t&&t.length)for(let l of t)n.addKeyword(l);let o=this.getline(e.line,i);if(o.length==0||e.character>=o.length||!n.isKeywordChar(o[e.character]))return null;let s=e.character,a=e.character+1;if(!n.isKeywordChar(o[s]))return Zi.Range.create(e,{line:e.line,character:e.character+1});for(;s>=0;){let l=o[s-1];if(!l||!n.isKeyword(l))break;s=s-1}for(;a<=o.length;){let l=o[a];if(!l||!n.isKeywordChar(l))break;a=a+1}return Zi.Range.create(e.line,s,e.line,a)}get textDocument(){let{version:e,filetype:t,uri:i}=this;return new i0(i,t,e,this.syncLines,this.eol)}async _fetchContent(){if(!this.env.isVim||!this._attached)return;let{nvim:e,bufnr:t,changedtick:i}=this,n=await this.mutex.acquire(),o=await e.call("coc#util#get_buf_lines",[t,i]);o&&o.changedtick>=this._changedtick&&(this._changedtick=o.changedtick,this.lines=o.lines,this.fireContentChanges.clear(),this._fireContentChanges()),n()}async patchChange(e){if(!!this._attached)if(this.env.isVim)if(e){let t=await this.nvim.call("coc#util#get_changeinfo",[]);if(t.changedtick0&&!u&&o==e&&t.push(Zi.Range.create(i.positionAt(s-o.length),i.positionAt(s))),u||(o="")}return t}fixStartcol(e,t){let i=this.getline(e.line);if(!i)return null;let{character:n}=e,o=i.slice(0,n),s=ue(o),{chars:a}=this;for(let l=o.length-1;l>=0;l--){let u=o[l];if(u==" "||!a.isKeywordChar(u)&&!t.includes(u))break;s=s-ue(u)}return s}getline(e,t=!0){return t?this.lines[e]||"":this.syncLines[e]||""}getLines(e,t){return this.lines.slice(e,t)}getDocumentContent(){let e=this.lines.join(` -`);return this.eol?e+` -`:e}getVar(e,t){let i=this.variables[`coc_${e}`];return i===void 0?t:i}getPosition(e,t){let i=this.getline(e-1);if(!i||t==0)return{line:e-1,character:0};let n=Rt(i,0,t-1);return{line:e-1,character:n.length}}getEndOffset(e,t,i){let n=0,o=this.lines.length;for(let s=e-1;s3e4?this.lines.slice(0,3e4):this.lines;this._words=this.chars.matchKeywords(n.join(` -`))}get attached(){return this._attached}detach(){this._attached=!1,z(this.disposables),this.disposables=[],this.fetchContent.clear(),this.fireContentChanges.clear(),this._onDocumentChange.dispose(),this._onDocumentDetach.dispose()}getLocalifyBonus(e,t){let i=new Map,{chars:n}=this,o=Math.max(0,e.line-100),s=Math.min(this.lineCount,e.line+100),a=this.lines.slice(o,s).join(` -`);e=Zi.Position.create(e.line-o,e.character),t=Zi.Position.create(t.line-o,t.character);let l=kt.create(this.uri,this.filetype,1,a),u=l.offsetAt(e),c=a.length,f=c-l.offsetAt(t),p=0,d=!1;for(let h=0;h1){let y=a.slice(p,h);i.set(y,h/u)}d=m}p=c-f,d=!1;for(let h=p;h1){let y=h==c-1?h+1:h,g=a.slice(p,y),w=i.get(g)||0;i.set(g,Math.max(w,(c-h+(y-p))/f))}d=m}return i}},rg=o0;var tp=S(W());var uj=S(ta()),Kl=S(require("path"));function ig(r,e){let t=[[],[]];for(let i of r)e(i)?t[0].push(i):t[1].push(i);return t}function lj(r,e){let t=r.length,i=[];for(let n=0;nr.indexOf(i)===n);let t=Object.create(null);return r.filter(i=>{let n=e(i);return t[n]?!1:(t[n]=!0,!0)})}var cj=U()("filesystem-watcher"),s0=class{constructor(e,t,i,n,o){this.globPattern=t;this.ignoreCreateEvents=i;this.ignoreChangeEvents=n;this.ignoreDeleteEvents=o;this._onDidCreate=new tp.Emitter;this._onDidChange=new tp.Emitter;this._onDidDelete=new tp.Emitter;this._onDidRename=new tp.Emitter;this.onDidCreate=this._onDidCreate.event;this.onDidChange=this._onDidChange.event;this.onDidDelete=this._onDidDelete.event;this.onDidRename=this._onDidRename.event;this.disposables=[];!e||e.then(s=>{if(s)return this.listen(s)}).catch(s=>{cj.error("watchman initialize failed"),cj.error(s.stack)})}async listen(e){let{globPattern:t,ignoreCreateEvents:i,ignoreChangeEvents:n,ignoreDeleteEvents:o}=this,s=await e.subscribe(t,a=>{let{root:l,files:u}=a;u=u.filter(c=>c.type=="f"&&uj.default(c.name,t,{dot:!0}));for(let c of u){let f=$.file(Kl.default.join(l,c.name));c.exists?c.new===!0?i||this._onDidCreate.fire(f):n||this._onDidChange.fire(f):o||this._onDidDelete.fire(f)}if(u.length==2&&!u[0].exists&&u[1].exists){let c=u[0],f=u[1];c.size==f.size&&this._onDidRename.fire({oldUri:$.file(Kl.default.join(l,c.name)),newUri:$.file(Kl.default.join(l,f.name))})}if(u.length>=2){let[c,f]=ig(u,p=>p.exists===!1);if(c.length==f.length)for(let p of c){let d=f.find(h=>h.size==p.size&&h.mtime_ms==p.mtime_ms);d&&this._onDidRename.fire({oldUri:$.file(Kl.default.join(l,p.name)),newUri:$.file(Kl.default.join(l,d.name))})}}});return this.disposables.push(s),s}dispose(){z(this.disposables)}},og=s0;var a0=S(require("path")),Wo=S($i()),l0=class{constructor(e,t){this.name=e;this.file=a0.default.join(t||process.env.COC_DATA_HOME,e)}async load(){let e=a0.default.dirname(this.file);try{Wo.default.mkdirpSync(e),Wo.default.existsSync(this.file)||Wo.default.writeFileSync(this.file,"","utf8");let t=await Wo.default.readFile(this.file,"utf8");return t=t.trim(),t.length?t.trim().split(` -`):[]}catch(t){return[]}}async add(e){let t=await this.load(),i=t.indexOf(e);i!==-1&&t.splice(i,1),t.unshift(e),Wo.default.writeFileSync(this.file,t.join(` -`),"utf8")}async remove(e){let t=await this.load(),i=t.indexOf(e);i!==-1&&(t.splice(i,1),Wo.default.writeFileSync(this.file,t.join(` -`),"utf8"))}async clean(){try{await Wo.default.unlink(this.file)}catch(e){}}},Jl=l0;var Yl=S(require("path")),fj=S(require("fs"));var G1e=U()("util-decorator");function u0(r,e,t){let i=t.value;if(typeof i!="function")return;let n="$"+e;t.value=function(...o){return this.hasOwnProperty(n)?Promise.resolve(this[n]):new Promise((s,a)=>{Promise.resolve(i.apply(this,o)).then(l=>{this[n]=l,s(l)},l=>{a(l)})})}}var c0=S(sD()),X1e=U()("model-resolver"),rp=class{get nodeFolder(){return wf("npm")?hn("npm --loglevel silent root -g",{},3e3).then(e=>c0.default(e).trim()):Promise.resolve("")}get yarnFolder(){return wf("yarnpkg")?hn("yarnpkg global dir",{},3e3).then(e=>{let t=Yl.default.join(c0.default(e).trim(),"node_modules");return fj.default.existsSync(t)?t:""}):Promise.resolve("")}async resolveModule(e){let t=await this.nodeFolder,i=await this.yarnFolder;if(i){let n=await It(Yl.default.join(i,e,"package.json"));if(n&&n.isFile())return Yl.default.join(i,e)}if(t){let n=await It(Yl.default.join(t,e,"package.json"));if(n&&n.isFile())return Yl.default.join(t,e)}return null}};Iy([u0],rp.prototype,"nodeFolder",1),Iy([u0],rp.prototype,"yarnFolder",1);var pj=rp;var sg=S(W());var f0=class{constructor(e,t){this.nvim=e;this.id=t;this.disposables=[];this._onExit=new sg.Emitter;this._onStderr=new sg.Emitter;this._onStdout=new sg.Emitter;this.onExit=this._onExit.event;this.onStdout=this._onStdout.event;this.onStderr=this._onStderr.event;A.on("TaskExit",(o,s)=>{o==this.id&&this._onExit.fire(s)},null,this.disposables),A.on("TaskStderr",(o,s)=>{o==this.id&&this._onStderr.fire(s)},null,this.disposables);let i=[],n;A.on("TaskStdout",(o,s)=>{o==this.id&&(n&&clearTimeout(n),i.push(...s),n=setTimeout(()=>{this._onStdout.fire(i),i=[]},100))},null,this.disposables)}async start(e){let{nvim:t}=this;return await t.call("coc#task#start",[this.id,e])}async stop(){let{nvim:e}=this;await e.call("coc#task#stop",[this.id])}get running(){let{nvim:e}=this;return e.call("coc#task#running",[this.id])}dispose(){let{nvim:e}=this;e.call("coc#task#stop",[this.id],!0),this._onStdout.dispose(),this._onStderr.dispose(),this._onExit.dispose(),z(this.disposables)}},dj=f0;var nIe=U()("model-terminal"),p0=class{constructor(e,t,i,n){this.cmd=e;this.args=t;this.nvim=i;this._name=n;this.pid=0}async start(e,t){let{nvim:i}=this,n=[this.cmd,...this.args],[o,s]=await i.call("coc#terminal#start",[n,e,t||{}]);this.bufnr=o,this.pid=s}get name(){return this._name||this.cmd}get processId(){return Promise.resolve(this.pid)}sendText(e,t=!0){!this.bufnr||this.nvim.call("coc#terminal#send",[this.bufnr,e,t],!0)}async show(e){let{bufnr:t,nvim:i}=this;if(!t)return;let[n,o,s]=await i.eval(`[bufloaded(${t}),bufwinid(${t}),win_getid()]`);return n?(s==o||(i.pauseNotification(),o==-1?(i.command(`below ${t}sb`,!0),i.command("resize 8",!0),i.call("coc#util#do_autocmd",["CocTerminalOpen"],!0)):i.call("win_gotoid",[o],!0),i.command("normal! G",!0),e&&i.command("wincmd p",!0),await i.resumeNotification()),!0):!1}async hide(){let{bufnr:e,nvim:t}=this;if(!e)return;let i=await t.call("bufwinnr",e);i!=-1&&await t.command(`${i}close!`)}dispose(){let{bufnr:e,nvim:t}=this;!e||t.call("coc#terminal#close",[e],!0)}},hj=p0;var d0=class{constructor(e,t){this._create=e;this.workspace=t;this.disposables=[];this.itemsMap=new Map;let{disposables:i}=this;for(let n of t.documents)this.create(n);t.onDidOpenTextDocument(n=>{let o=t.getDocument(n.bufnr);o&&this.create(o)},null,i),t.onDidChangeTextDocument(n=>{this.onChange(n)},null,i),t.onDidCloseTextDocument(n=>{this.delete(n.bufnr)},null,i)}get items(){return Array.from(this.itemsMap.values()).map(e=>e.item)}getItem(e){var i;if(typeof e=="number")return(i=this.itemsMap.get(e))==null?void 0:i.item;let t=Array.from(this.itemsMap.values()).find(n=>n.uri==e);return t?t.item:void 0}create(e){if(!e||e.isCommandLine||!e.attached)return;let t=this.itemsMap.get(e.bufnr);t&&t.item.dispose();let i=this._create(e);i&&this.itemsMap.set(e.bufnr,{uri:e.uri,item:i})}onChange(e){let t=this.itemsMap.get(e.bufnr);t&&typeof t.item.onChange=="function"&&t.item.onChange(e)}delete(e){let t=this.itemsMap.get(e);t&&(this.itemsMap.delete(e),t.item.dispose())}reset(){for(let e of this.itemsMap.values())e.item.dispose();this.itemsMap.clear()}dispose(){z(this.disposables);for(let e of this.itemsMap.values())e.item.dispose();this.itemsMap.clear()}},mj=d0;var gj=S(ta());function Xl(r,e,t){if(Array.isArray(r)){let i=0;for(let n of r){let o=Xl(n,e,t);if(o===10)return o;o>i&&(i=o)}return i}else{if(typeof r=="string")return r==="*"?5:r===t?10:0;if(r){let i=$.parse(e),{language:n,pattern:o,scheme:s}=r,a=0;if(s)if(s===i.scheme)a=5;else if(s==="*")a=3;else return 0;if(n)if(n===t)a=10;else if(n==="*")a=Math.max(a,5);else return 0;if(o){let l=Hn||Fx,u=l?o.toLowerCase():o,c=l?i.fsPath.toLowerCase():i.fsPath;if(u===c||gj.default(c,u,{dot:!0}))a=5;else return 0}return a}else return 0}}var qj=S(Nj()),x0=S(require("os")),fg=S(require("path"));var $j=S(W()),Bj=S(ta());var pg=U()("watchman"),Xde=["relative_root","cmd-watch-project","wildmatch","field-new"],D0=new Map,ap=class{constructor(e,t){this.channel=t;this._disposed=!1;this.client=new qj.default.Client({watchmanBinaryPath:e}),this.client.setMaxListeners(300)}checkCapability(){let{client:e}=this;return new Promise((t,i)=>{e.capabilityCheck({optional:[],required:Xde},(n,o)=>{if(n)return i(n);let{capabilities:s}=o;for(let a of Object.keys(s))if(!s[a])return t(!1);t(!0)})})}async watchProject(e){try{let t=await this.command(["watch-project",e]),{watch:i,warning:n,relative_path:o}=t;n&&pg.warn(n),this.watch=i,this.relative_path=o,pg.info(`watchman watching project: ${e}`),this.appendOutput(`watchman watching project: ${e}`)}catch(t){return pg.error(t),!1}return!0}command(e){return new Promise((t,i)=>{this.client.command(e,(n,o)=>{if(n)return i(n);t(o)})})}async subscribe(e,t){let{watch:i,relative_path:n}=this;if(!i)return this.appendOutput(`watchman not watching: ${i}`,"Error"),null;let{clock:o}=await this.command(["clock",i]),s=$o(),a={expression:["allof",["match","**/*","wholename"]],fields:["name","size","new","exists","type","mtime_ms","ctime_ms"],since:o},l=i;n&&(a.relative_root=n,l=fg.default.join(i,n));let{subscribe:u}=await this.command(["subscribe",i,s,a]);return global.hasOwnProperty("__TEST__")&&(global.subscribe=u),this.appendOutput(`subscribing "${e}" in ${l}`),this.client.on("subscription",c=>{if(!c||c.subscription!=s)return;let{files:f}=c;if(!f||(f=f.filter(d=>d.type=="f"&&Bj.default(d.name,e,{dot:!0})),!f.length))return;let p=Object.assign({},c);this.relative_path&&(p.root=fg.default.resolve(c.root,this.relative_path)),this.appendOutput(`file change detected: ${JSON.stringify(p,null,2)}`),t(p)}),$j.Disposable.create(()=>this.unsubscribe(u))}unsubscribe(e){if(this._disposed)return Promise.resolve();let{watch:t}=this;if(!!t)return this.appendOutput(`unsubscribe "${e}" in: ${t}`),this.command(["unsubscribe",t,e]).catch(i=>{pg.error(i)})}dispose(){this._disposed||(this._disposed=!0,this.client.removeAllListeners(),this.client.end())}appendOutput(e,t="Info"){this.channel&&this.channel.appendLine(`[${t} - ${new Date().toLocaleTimeString()}] ${e}`)}static dispose(){for(let e of D0.values())e.then(t=>{t.dispose()},t=>{})}static createClient(e,t,i){if(!Zde(t))return null;let n=D0.get(t);if(n)return n;let o=new Promise(async(s,a)=>{try{let l=new ap(e,i);if(!await l.checkCapability()||!await l.watchProject(t))return s(null);s(l)}catch(l){a(l)}});return D0.set(t,o),o}},ia=ap;function Zde(r){return!(r=="/"||r=="/tmp"||r=="/private/tmp"||r.toLowerCase()===x0.default.homedir().toLowerCase()||fg.default.parse(r).base==r||r.startsWith("/tmp/")||r.startsWith("/private/tmp/")||Xe(x0.default.tmpdir(),r,!0))}var dg="0.0.80";var Hj=8,lp=U()("workspace"),hg=2e3,Qde=["showMessage","runTerminalCommand","openTerminal","showQuickpick","menuPick","openLocalConfig","showPrompt","createStatusBarItem","createOutputChannel","showOutputChannel","requestInput","echoLines","getCursorPosition","moveTo","getOffset"],zj=class{constructor(){this.keymaps=new Map;this.resolver=new pj;this.rootPatterns=new Map;this._workspaceFolders=[];this._insertMode=!1;this._cwd=process.cwd();this._initialized=!1;this._attached=!1;this.buffers=new Map;this.autocmdMaxId=0;this.autocmds=new Map;this.terminals=new Map;this.creatingSources=new Map;this.schemeProviderMap=new Map;this.namespaceMap=new Map;this.disposables=[];this.watchedOptions=new Set;this._dynAutocmd=!1;this._disposed=!1;this._onDidOpenDocument=new le.Emitter;this._onDidCloseDocument=new le.Emitter;this._onDidChangeDocument=new le.Emitter;this._onWillSaveDocument=new le.Emitter;this._onDidSaveDocument=new le.Emitter;this._onDidChangeWorkspaceFolders=new le.Emitter;this._onDidChangeConfiguration=new le.Emitter;this._onDidWorkspaceInitialized=new le.Emitter;this._onDidOpenTerminal=new le.Emitter;this._onDidCloseTerminal=new le.Emitter;this._onDidRuntimePathChange=new le.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;this.onDidRuntimePathChange=this._onDidRuntimePathChange.event;this.version=dg,this.configurations=this.createConfigurations();let e=process.cwd();e!=Qi.default.homedir()&&jo(e,[".vim"])&&this._workspaceFolders.push({uri:$.file(e).toString(),name:Fe.default.basename(e)})}async init(){let{nvim:e}=this;for(let o of Qde)Object.defineProperty(this,o,{get:()=>(...s)=>C[o].apply(C,s)});this._env=await e.call("coc#util#vim_info"),this._env.apiversion!=Hj&&(console.error(`API version ${this._env.apiversion} is not ${Hj}, please build coc.nvim by 'yarn install' after pull source code.`),process.exit()),this._insertMode=this._env.mode.startsWith("insert");let i=this.getConfiguration("coc.preferences").get("maxFileSize","10MB");this.maxFileSize=jj.default.parse(i),this._env.workspaceFolders&&(this._workspaceFolders=this._env.workspaceFolders.map(o=>({uri:$.file(o).toString(),name:Fe.default.dirname(o)}))),this.configurations.updateUserConfig(this._env.config),A.on(["InsertEnter","CursorMovedI"],()=>{this._insertMode=!0},null,this.disposables),A.on(["InsertLeave","CursorMoved"],()=>{this._insertMode=!1},null,this.disposables);let n=async o=>{let s=this.getDocument(o);s&&s.forceSync()};A.on("InsertLeave",n,null,this.disposables),A.on("CursorHold",n,null,this.disposables),A.on("BufEnter",this.onBufEnter,this,this.disposables),A.on("CursorMoved",this.checkCurrentBuffer,this,this.disposables),A.on("CursorMovedI",this.checkCurrentBuffer,this,this.disposables),A.on("DirChanged",this.onDirChanged,this,this.disposables),A.on("BufCreate",this.onBufCreate,this,this.disposables),A.on("BufUnload",this.onBufUnload,this,this.disposables),A.on("TermOpen",this.onBufCreate,this,this.disposables),A.on("TermClose",this.onBufUnload,this,this.disposables),A.on("BufWritePost",this.onBufWritePost,this,this.disposables),A.on("BufWritePre",this.onBufWritePre,this,this.disposables),A.on("FileType",this.onFileTypeChange,this,this.disposables),A.on("CursorHold",this.checkCurrentBuffer,this,this.disposables),A.on("TextChanged",this.checkBuffer,this,this.disposables),A.on("BufReadCmd",this.onBufReadCmd,this,this.disposables),A.on("VimResized",(o,s)=>{Object.assign(this._env,{columns:o,lines:s})},null,this.disposables),await this.attach(),this.attachChangedEvents(),this.configurations.onDidChange(o=>{this._onDidChangeConfiguration.fire(o)},null,this.disposables),this.watchOption("runtimepath",(o,s)=>{let a=Uj.default(o,s);for(let[l,u]of a)if(l==1){let c=u.replace(/,$/,"").split(",");this._onDidRuntimePathChange.fire(c)}this._env.runtimepath=s},this.disposables),this.watchOption("completeopt",async(o,s)=>{if(this.env.completeOpt=s,!!this._attached&&this.insertMode&&this.getConfiguration("suggest").get("autoTrigger")=="always"){let u=(await this.nvim.call("execute",["verbose set completeopt"])).split(/\r?\n/);console.error(`Some plugin change completeopt on insert mode: ${u[u.length-1].trim()}!`)}},this.disposables),this.watchGlobal("coc_sources_disable_map",async(o,s)=>{this.env.disabledSources=s}),this.disposables.push(this.registerTextDocumentContentProvider("output",Qs.getProvider(e)))}getConfigFile(e){return this.configurations.getConfigFile(e)}registerAutocmd(e){this.autocmdMaxId+=1;let t=this.autocmdMaxId;return this.autocmds.set(t,e),this.setupDynamicAutocmd(),le.Disposable.create(()=>{this.autocmds.delete(t),this.setupDynamicAutocmd()})}watchOption(e,t,i){let n=this.watchedOptions.has(e);n||(this.watchedOptions.add(e),this.setupDynamicAutocmd());let o=A.on("OptionSet",async(s,a,l)=>{s==e&&t&&await Promise.resolve(t(a,l))});i&&i.push(le.Disposable.create(()=>{o.dispose(),!n&&(this.watchedOptions.delete(e),this.setupDynamicAutocmd())}))}watchGlobal(e,t,i){let{nvim:n}=this;n.call("coc#_watch",e,!0);let o=A.on("GlobalChange",async(s,a,l)=>{s==e&&t&&await Promise.resolve(t(a,l))});i&&i.push(le.Disposable.create(()=>{o.dispose(),n.call("coc#_unwatch",e,!0)}))}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}get uri(){let{bufnr:e}=this;if(e){let t=this.getDocument(e);if(t&&t.schema=="file")return t.uri}return null}get workspaceFolder(){let{rootPath:e}=this;return e==Qi.default.homedir()?null:{uri:$.file(e).toString(),name:Fe.default.basename(e)}}get textDocuments(){let e=[];for(let t of this.buffers.values())e.push(t.textDocument);return e}get documents(){return Array.from(this.buffers.values())}createNameSpace(e=""){return this.namespaceMap.has(e)?this.namespaceMap.get(e):(hg=hg+1,this.namespaceMap.set(e,hg),hg)}get channelNames(){return Qs.names}get pluginRoot(){return Fe.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(){return this._initialized?Promise.resolve():new Promise(e=>{let t=this.onDidWorkspaceInitialized(()=>{t.dispose(),e()})})}get filetypes(){let e=new Set;for(let t of this.documents)e.add(t.filetype);return e}match(e,t){return Xl(e,t.uri,t.languageId)}async findUp(e){let{cwd:t}=this,i=await this.nvim.call("expand","%:p");i=Fe.default.normalize(i);let n=i&&Fe.default.isAbsolute(i);if(n&&!Xe(t,i,!0))return Gl(e,Fe.default.dirname(i));let o=Gl(e,t);return o&&o!=Qi.default.homedir()?o:n?Gl(e,Fe.default.dirname(i)):null}async resolveRootFolder(e,t){let{cwd:i}=this;if(e.scheme!="file")return i;let n=Fe.default.normalize(e.fsPath),o=Fe.default.dirname(n);return Qf(o,t)||o}createFileSystemWatcher(e,t,i,n){let o=global.hasOwnProperty("__TEST__")?null:this.getWatchmanPath(),s=o?C.createOutputChannel("watchman"):null,a=o?ia.createClient(o,this.root,s):Promise.resolve(null);return new og(a,e,!!t,!!i,!!n)}getWatchmanPath(){let t=this.getConfiguration("coc.preferences").get("watchmanPath","watchman");try{return Wj.default.sync(t)}catch(i){return null}}getConfiguration(e,t){return this.configurations.getConfiguration(e,t)}getDocument(e){if(typeof e=="number")return this.buffers.get(e);let t=Pl.isWindows||Pl.isMacintosh;e=$.parse(e).toString();for(let i of this.buffers.values())if(!!i&&(i.uri===e||t&&i.uri.toLowerCase()===e.toLowerCase()))return i;return null}async applyEdit(e){let{nvim:t}=this,{documentChanges:i,changes:n}=e,[o,s]=await t.eval('[bufnr("%"),coc#util#cursor()]'),a=this.getDocument(o),l=a?a.uri:null,u=null,c=[],f=0,p=this.getConfiguration("coc.preferences"),d=!global.hasOwnProperty("__TEST__")&&p.get("promptWorkspaceEdit",!0),h=p.get("listOfWorkspaceEdit","quickfix");try{if(i&&i.length){let m=this.getChangedUris(i);if(f=m.length,d){let g=m.reduce((w,x)=>w+(this.getDocument(x)==null?1:0),0);if(g&&!await C.showPrompt(`${g} documents on disk would be loaded for change, confirm?`))return}let y=new Map;for(let g of i)if(le.TextDocumentEdit.is(g)){let{textDocument:w,edits:x}=g,E=await this.loadFile(w.uri);w.uri==l&&(u=x),await E.applyEdits(x);for(let P of x)c.push({uri:E.uri,range:P.range})}else if(le.CreateFile.is(g)){let w=$.parse(g.uri).fsPath;await this.createFile(w,g.options)}else le.RenameFile.is(g)?(y.set(g.oldUri,g.newUri),await this.renameFile($.parse(g.oldUri).fsPath,$.parse(g.newUri).fsPath,g.options)):le.DeleteFile.is(g)&&await this.deleteFile($.parse(g.uri).fsPath,g.options);y.size&&c.forEach(g=>{let w=y.get(g.uri);w&&(g.uri=w)})}else if(n){let m=Object.keys(n),y=m.filter(g=>this.getDocument(g)==null);if(y.length){if(d&&!await C.showPrompt(`${y.length} documents on disk would be loaded for change, confirm?`))return;await this.loadFiles(y)}for(let g of Object.keys(n)){let w=this.getDocument(g);$.parse(g).toString()==g&&(u=n[g]);let x=n[g];for(let E of x)c.push({uri:w.uri,range:E.range});await w.applyEdits(x)}f=m.length}if(u){let m=jl({line:s[0],character:s[1]},u);m&&await C.moveTo({line:s[0]+m.line,character:s[1]+m.character})}if(c.length){let m=await Promise.all(c.map(g=>this.getQuickfixItem(g))),y=c.every(g=>g.uri==l);h=="quickfix"?(await this.nvim.call("setqflist",[m]),y||C.showMessage(`changed ${f} buffers, use :wa to save changes to disk and :copen to open quickfix list`,"more")):h=="location"&&(await t.setVar("coc_jump_locations",m),y||C.showMessage(`changed ${f} buffers, use :wa to save changes to disk and :CocList location to manage changed locations`,"more"))}}catch(m){return lp.error(m),C.showMessage(`Error on applyEdits: ${m.message}`,"error"),!1}return await He(50),!0}async getQuickfixItem(e,t,i="",n){le.LocationLink.is(e)&&(e=le.Location.create(e.targetUri,e.targetRange));let o=this.getDocument(e.uri),{uri:s,range:a}=e,{line:l,character:u}=a.start,c=$.parse(s),f=o?o.bufnr:-1;!t&&c.scheme=="file"&&(t=await this.getLine(s,l),u=Kr(t,u));let p={uri:s,filename:c.scheme=="file"?c.fsPath:s,lnum:l+1,col:u+1,text:t||"",range:a};return n&&(p.module=n),i&&(p.type=i),f!=-1&&(p.bufnr=f),p}createMru(e){return new Jl(e)}async getSelectedRange(e,t){let{nvim:i}=this;if(e==="line"){let c=await i.call("line",["."]),f=t.getline(c-1);return f.length?le.Range.create(c-1,0,c-1,f.length):null}if(e==="cursor"){let[c,f]=await i.eval("coc#util#cursor()");return le.Range.create(c,f,c,f)}if(!["v","V","char","line",""].includes(e))throw new Error(`Mode '${e}' not supported`);let n=["v","V",""].includes(e),[,o,s]=await i.call("getpos",n?"'<":"'["),[,a,l]=await i.call("getpos",n?"'>":"']"),u=le.Range.create(t.getPosition(o,s),t.getPosition(a,l));return(e=="v"||e=="")&&(u.end.character=u.end.character+1),u}async selectRange(e){let{nvim:t}=this,{start:i,end:n}=e,[o,s,a]=await t.eval("[bufnr('%'), &virtualedit, &selection, mode()]"),l=this.getDocument(o);if(!l)return;let u=l.getline(i.line),c=u?ue(u.slice(0,i.character)):0,f=l.getline(n.line),p=f?ue(f.slice(0,n.character)):0,d="",h=!1;d+="v",p=await t.eval(`virtcol([${n.line+1}, ${p}])`),a=="inclusive"?n.character==0?d+=`${n.line}G`:d+=`${n.line+1}G${p}|`:a=="old"?d+=`${n.line+1}G${p}|`:d+=`${n.line+1}G${p+1}|`,c=await t.eval(`virtcol([${i.line+1}, ${c}])`),d+=`o${i.line+1}G${c+1}|o`,t.pauseNotification(),s!="onemore"&&(h=!0,t.setOption("virtualedit","onemore",!0)),t.command(`noa call cursor(${i.line+1},${c+(d=="a"?0:1)})`,!0),t.command(`normal! ${d}`,!0),h&&t.setOption("virtualedit",s,!0),this.isVim&&t.command("redraw",!0),await t.resumeNotification()}async showLocations(e){let t=await Promise.all(e.map(o=>this.getQuickfixItem(o))),{nvim:i}=this;if(this.getConfiguration("coc.preferences").get("useQuickfixForLocations",!1)){let o=await i.getVar("coc_quickfix_open_command");typeof o!="string"&&(o=t.length<10?`copen ${t.length}`:"copen"),i.pauseNotification(),i.call("setqflist",[t],!0),i.command(o,!0),i.resumeNotification(!1,!0)}else await i.setVar("coc_jump_locations",t),this.env.locationlist?i.command("CocList --normal --auto-preview location",!0):i.call("coc#util#do_autocmd",["CocLocationsChange"],!0)}async getLine(e,t){let i=this.getDocument(e);if(i)return i.getline(t)||"";if(!e.startsWith("file:"))return"";let n=$.parse(e).fsPath;return St.default.existsSync(n)?await ej(n,t):""}getWorkspaceFolder(e){this.workspaceFolders.sort((i,n)=>n.uri.length-i.uri.length);let t=$.parse(e).fsPath;return this.workspaceFolders.find(i=>Xe($.parse(i.uri).fsPath,t,!0))}async readFile(e){let t=this.getDocument(e);if(t)return await t.patchChange(),t.content;let i=$.parse(e);return i.scheme!="file"?"":(await this.nvim.call("readfile",[i.fsPath])).join(` -`)+` -`}get document(){return new Promise((e,t)=>{this.nvim.buffer.then(i=>{let n=i.id;if(this.bufnr=n,this.buffers.has(n)){e(this.buffers.get(n));return}this.onBufCreate(n).catch(t);let o=this.onDidOpenTextDocument(s=>{o.dispose(),e(this.getDocument(s.uri))})},t)})}async getCurrentState(){let e=await this.document,t=await C.getCursorPosition();return{document:e.textDocument,position:t}}async getFormatOptions(e){let t;e&&(t=this.getDocument(e));let i=t?t.bufnr:0,[n,o]=await this.nvim.call("coc#util#get_format_opts",[i]);return{tabSize:n,insertSpaces:o==1}}async jumpTo(e,t,i){let n=this.getConfiguration("coc.preferences"),o=i||n.get("jumpCommand","edit"),{nvim:s}=this,a=this.getDocument(e),l=a?a.bufnr:-1;if(l!=-1&&o=="edit"){if(s.pauseNotification(),s.command("silent! normal! m'",!0),s.command(`buffer ${l}`,!0),t){let u=a.getline(t.line),c=ue(u.slice(0,t.character))+1;s.call("cursor",[t.line+1,c],!0)}this.isVim&&s.command("redraw",!0),await s.resumeNotification()}else{let{fsPath:u,scheme:c}=$.parse(e),f=t==null?null:[t.line,t.character];if(c=="file"){let p=Zf(Fe.default.normalize(u));await this.nvim.call("coc#util#jump",[o,p,f])}else Qi.default.platform()=="win32"&&(e=e.replace(/\/?/,"?")),await this.nvim.call("coc#util#jump",[o,e,f])}}async createFile(e,t={}){let i=await It(e);if(i&&!t.overwrite&&!t.ignoreIfExists){C.showMessage(`${e} already exists!`,"error");return}if(!i||t.overwrite)if(e.endsWith("/"))try{e=this.expand(e),await St.default.mkdirp(e)}catch(n){C.showMessage(`Can't create ${e}: ${n.message}`,"error")}else{let n=$.file(e).toString();if(this.getDocument(n))return;St.default.existsSync(Fe.default.dirname(e))||St.default.mkdirpSync(Fe.default.dirname(e)),St.default.writeFileSync(e,"","utf8"),await this.loadFile(n)}}async loadFile(e){let t=this.getDocument(e);if(t)return t;let{nvim:i}=this,n=e.startsWith("file")?$.parse(e).fsPath:e;return i.call("coc#util#open_files",[[n]],!0),await new Promise((o,s)=>{let a=this.onDidOpenTextDocument(u=>{let c=$.parse(u.uri).fsPath;(u.uri==e||c==n)&&(clearTimeout(l),a.dispose(),o(this.getDocument(e)))}),l=setTimeout(()=>{a.dispose(),s(new Error(`Create document ${e} timeout after 1s.`))},1e3)})}async loadFiles(e){if(e=e.filter(n=>this.getDocument(n)==null),!(!e.length||!(await this.nvim.call("coc#util#open_files",[e.map(n=>$.parse(n).fsPath)])).filter(n=>this.getDocument(n)==null).length))return new Promise((n,o)=>{let s=setTimeout(()=>{a.dispose(),o(new Error("Create document timeout after 2s."))},2e3),a=this.onDidOpenTextDocument(()=>{e.every(l=>this.getDocument(l)!=null)&&(clearTimeout(s),a.dispose(),n())})})}async renameFile(e,t,i={}){let{overwrite:n,ignoreIfExists:o}=i,{nvim:s}=this;try{let a=await It(t);if(a&&!n&&!o)throw new Error(`${t} already exists`);if(!a||n){let l=$.file(e).toString(),u=$.file(t).toString(),c=this.getDocument(l);if(c!=null){let f=c.bufnr==this.bufnr,p=this.getDocument(u);p&&await this.nvim.command(`silent ${p.bufnr}bwipeout!`);let d=c.getDocumentContent();if(await St.default.writeFile(t,d,"utf8"),!f)await s.call("coc#util#open_files",[[t]]),await s.command(`silent ${c.bufnr}bwipeout!`);else{let h=await s.call("winsaveview");s.pauseNotification(),s.call("coc#util#open_file",["keepalt edit",t],!0),s.command(`silent ${c.bufnr}bwipeout!`,!0),s.call("winrestview",[h],!0),await s.resumeNotification()}await St.default.unlink(e)}else await X3(e,t)}}catch(a){C.showMessage(`Rename error: ${a.message}`,"error")}}async deleteFile(e,t={}){let{ignoreIfNotExists:i,recursive:n}=t,o=await It(e.replace(/\/$/,"")),s=o&&o.isDirectory();if(e.endsWith("/")&&!s){C.showMessage(`${e} is not directory`,"error");return}if(!o&&!i){C.showMessage(`${e} not exists`,"error");return}if(o!=null){if(s&&!n){C.showMessage("Can't remove directory, recursive not set","error");return}try{if(s&&n?await St.default.remove(e):s?await St.default.rmdir(e):await St.default.unlink(e),!s){let a=$.file(e).toString(),l=this.getDocument(a);l&&await this.nvim.command(`silent! bwipeout! ${l.bufnr}`)}}catch(a){C.showMessage(`Error on delete ${e}: ${a.message}`,"error")}}}async openResource(e){let{nvim:t}=this;if(e.startsWith("http")){await t.call("coc#util#open_url",e);return}let i=await t.getOption("wildignore");await t.setOption("wildignore",""),await this.jumpTo(e),await t.setOption("wildignore",i)}async resolveModule(e){return await this.resolver.resolveModule(e)}async runCommand(e,t,i){return t=t||this.cwd,hn(e,{cwd:t},i)}expand(e){if(!e)return e;if(e.startsWith("~")&&(e=Qi.default.homedir()+e.slice(1)),e.includes("$")){let t=this.getDocument(this.bufnr),i=t?$.parse(t.uri).fsPath:"";e=e.replace(/\$\{(.*?)\}/g,(n,o)=>{if(o.startsWith("env:")){let s=o.split(":")[1];return s?process.env[s]:""}switch(o){case"workspace":case"workspaceRoot":case"workspaceFolder":return this.root;case"workspaceFolderBasename":return Fe.default.dirname(this.root);case"cwd":return this.cwd;case"file":return i;case"fileDirname":return i?Fe.default.dirname(i):"";case"fileExtname":return i?Fe.default.extname(i):"";case"fileBasename":return i?Fe.default.basename(i):"";case"fileBasenameNoExtension":{let s=i?Fe.default.basename(i):"";return s?s.slice(0,s.length-Fe.default.extname(s).length):""}default:return n}}),e=e.replace(/\$[\w]+/g,n=>n=="$HOME"?Qi.default.homedir():process.env[n.slice(1)]||n)}return e}async createTerminal(e){let t=e.shellPath,i=e.shellArgs;t||(t=await this.nvim.getOption("shell"));let n=new hj(t,i||[],this.nvim,e.name);return await n.start(e.cwd||this.cwd,e.env),this.terminals.set(n.bufnr,n),this._onDidOpenTerminal.fire(n),n}async callAsync(e,t){return this.isNvim?await this.nvim.call(e,t):await this.nvim.callAsync("coc#util#with_callback",[e,t])}registerTextDocumentContentProvider(e,t){this.schemeProviderMap.set(e,t),this.setupDynamicAutocmd();let i=[];return t.onDidChange&&t.onDidChange(async n=>{let o=this.getDocument(n.toString());if(o){let{buffer:s}=o,a=new le.CancellationTokenSource,l=await Promise.resolve(t.provideTextDocumentContent(n,a.token));await s.setLines(l.split(/\r?\n/),{start:0,end:-1,strictIndexing:!1})}},null,i),le.Disposable.create(()=>{this.schemeProviderMap.delete(e),z(i),this.setupDynamicAutocmd()})}registerKeymap(e,t,i,n={}){if(!t)throw new Error(`Invalid key ${t} of registerKeymap`);if(this.keymaps.has(t))throw new Error(`${t} already exists.`);n=Object.assign({sync:!0,cancel:!0,silent:!0,repeat:!1},n);let{nvim:o}=this;this.keymaps.set(t,[i,!!n.repeat]);let s=n.sync?"request":"notify",a=n.silent?"":"";for(let l of e)if(l=="i")o.command(`inoremap ${a} (coc-${t}) coc#_insert_key('${s}', '${t}', ${n.cancel?1:0})`,!0);else{let u=Lx(l);o.command(`${l}noremap ${a} (coc-${t}) :${u}call coc#rpc#${s}('doKeymap', ['${t}'])`,!0)}return le.Disposable.create(()=>{this.keymaps.delete(t);for(let l of e)o.command(`${l}unmap (coc-${t})`,!0)})}registerExprKeymap(e,t,i,n=!1){if(!t)return;let o=`${e}${global.Buffer.from(t).toString("base64")}${n?"1":"0"}`,{nvim:s}=this;return this.keymaps.set(o,[i,!1]),e=="i"?s.command(`inoremap ${n?"":""} ${t} coc#_insert_key('request', '${o}')`,!0):s.command(`${e}noremap ${n?"":""} ${t} coc#rpc#request('doKeymap', ['${o}'])`,!0),le.Disposable.create(()=>{this.keymaps.delete(o),s.command(`${e}unmap ${n?"":""} ${t}`,!0)})}registerLocalKeymap(e,t,i,n=!1){let o=$o(),{nvim:s}=this;this.keymaps.set(o,[i,!1]);let a=this.nvim.createBuffer(this.bufnr),l=n?"notify":"request",u=Lx(e),c=t.startsWith("<")&&t.endsWith(">")?`{${t.slice(1,-1)}}`:t;if(this.isNvim&&!global.hasOwnProperty("__TEST__"))a.notify("nvim_buf_set_keymap",[e,t,`:${u}call coc#rpc#${l}('doKeymap', ['${o}', '', '${c}'])`,{silent:!0,nowait:!0}]);else{let f=`${e}noremap ${t} :${u}call coc#rpc#${l}('doKeymap', ['${o}', '', '${c}'])`;s.command(f,!0)}return le.Disposable.create(()=>{this.keymaps.delete(o),s.call("coc#compat#buf_del_keymap",[a.id,e,t],!0)})}createDatabase(e){let t;global.hasOwnProperty("__TEST__")?(t=Fe.default.join(Qi.default.tmpdir(),`coc-${process.pid}`),St.default.mkdirpSync(t)):t=Fe.default.dirname(this.env.extensionRoot);let i=Fe.default.join(t,e+".json");return new eg(i)}createTask(e){return new dj(this.nvim,e)}registerBufferSync(e){return new mj(e,this)}setupDynamicAutocmd(e=!1){if(!e&&!this._dynAutocmd)return;this._dynAutocmd=!0;let t=this.schemeProviderMap.keys(),i=[];for(let o of t)i.push(`autocmd BufReadCmd,FileReadCmd,SourceCmd ${o}:/* call coc#rpc#request('CocAutocmd', ['BufReadCmd','${o}', expand('')])`);for(let[o,s]of this.autocmds.entries()){let a=s.arglist&&s.arglist.length?", "+s.arglist.join(", "):"",l=Array.isArray(s.event)?s.event.join(","):s.event,u=s.pattern!=null?s.pattern:"*";/\buser\b/i.test(l)&&(u=""),i.push(`autocmd ${l} ${u} call coc#rpc#${s.request?"request":"notify"}('doAutocmd', [${o}${a}])`)}for(let o of this.watchedOptions)i.push(`autocmd OptionSet ${o} call coc#rpc#notify('OptionSet',[expand(''), v:option_old, v:option_new])`);let n=` +(function () { + var v = process.version + var parts = v.slice(1).split('.') + var major = parseInt(parts[0], 10) + var minor = parseInt(parts[1], 10) + if (major < 12 || (major == 12 && minor < 12)) { + throw new Error('coc.nvim requires node >= v12.12.0, current version: ' + v) + } +})(); +var __create = Object.create; +var __defProp = Object.defineProperty; +var __defProps = Object.defineProperties; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropDescs = Object.getOwnPropertyDescriptors; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getOwnPropSymbols = Object.getOwnPropertySymbols; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __propIsEnum = Object.prototype.propertyIsEnumerable; +var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; +var __spreadValues = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + if (__getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(b)) { + if (__propIsEnum.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + } + return a; +}; +var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); +var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); +var __esm = (fn, res) => function __init() { + return fn && (res = (0, fn[Object.keys(fn)[0]])(fn = 0)), res; +}; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __export = (target, all) => { + __markAsModule(target); + for (var name2 in all) + __defProp(target, name2, { get: all[name2], enumerable: true }); +}; +var __reExport = (target, module2, desc) => { + if (module2 && typeof module2 === "object" || typeof module2 === "function") { + for (let key of __getOwnPropNames(module2)) + if (!__hasOwnProp.call(target, key) && key !== "default") + __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); + } + return target; +}; +var __toModule = (module2) => { + return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); +}; +var __decorateClass = (decorators, target, key, kind) => { + var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; + for (var i = decorators.length - 1, decorator; i >= 0; i--) + if (decorator = decorators[i]) + result = (kind ? decorator(target, key, result) : decorator(result)) || result; + if (kind && result) + __defProp(target, key, result); + return result; +}; + +// node_modules/ms/index.js +var require_ms = __commonJS({ + "node_modules/ms/index.js"(exports2, module2) { + var s = 1e3; + var m = s * 60; + var h = m * 60; + var d = h * 24; + var w = d * 7; + var y = d * 365.25; + module2.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === "string" && val.length > 0) { + return parse5(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)); + }; + function parse5(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 void 0; + } + } + 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"; + } + 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"; + } + function plural(ms, msAbs, n, name2) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + " " + name2 + (isPlural ? "s" : ""); + } + } +}); + +// node_modules/debug/src/common.js +var require_common = __commonJS({ + "node_modules/debug/src/common.js"(exports2, module2) { + function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = require_ms(); + createDebug.destroy = destroy; + Object.keys(env).forEach((key) => { + createDebug[key] = env[key]; + }); + createDebug.names = []; + createDebug.skips = []; + createDebug.formatters = {}; + function selectColor(namespace) { + let hash = 0; + for (let i = 0; i < namespace.length; i++) { + hash = (hash << 5) - hash + namespace.charCodeAt(i); + hash |= 0; + } + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + function debug(...args) { + if (!debug.enabled) { + return; + } + const self2 = debug; + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self2.diff = ms; + self2.prev = prevTime; + self2.curr = curr; + prevTime = curr; + args[0] = createDebug.coerce(args[0]); + if (typeof args[0] !== "string") { + args.unshift("%O"); + } + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format2) => { + if (match === "%%") { + return "%"; + } + index++; + const formatter2 = createDebug.formatters[format2]; + if (typeof formatter2 === "function") { + const val = args[index]; + match = formatter2.call(self2, val); + args.splice(index, 1); + index--; + } + return match; + }); + createDebug.formatArgs.call(self2, args); + const logFn = self2.log || createDebug.log; + logFn.apply(self2, args); + } + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; + Object.defineProperty(debug, "enabled", { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + return enabledCache; + }, + set: (v) => { + enableOverride = v; + } + }); + if (typeof createDebug.init === "function") { + createDebug.init(debug); + } + return debug; + } + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = 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]) { + continue; + } + namespaces = split[i].replace(/\*/g, ".*?"); + if (namespaces[0] === "-") { + createDebug.skips.push(new RegExp("^" + namespaces.substr(1) + "$")); + } else { + createDebug.names.push(new RegExp("^" + namespaces + "$")); + } + } + } + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map((namespace) => "-" + namespace) + ].join(","); + createDebug.enable(""); + return namespaces; + } + function enabled(name2) { + if (name2[name2.length - 1] === "*") { + return true; + } + let i; + let len; + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name2)) { + return false; + } + } + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name2)) { + return true; + } + } + return false; + } + function toNamespace(regexp) { + return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\.\*\?$/, "*"); + } + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + function destroy() { + console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); + } + createDebug.enable(createDebug.load()); + return createDebug; + } + module2.exports = setup; + } +}); + +// node_modules/debug/src/browser.js +var require_browser = __commonJS({ + "node_modules/debug/src/browser.js"(exports2, module2) { + exports2.formatArgs = formatArgs; + exports2.save = save; + exports2.load = load; + exports2.useColors = useColors; + exports2.storage = localstorage(); + exports2.destroy = (() => { + let warned = false; + return () => { + if (!warned) { + warned = true; + console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); + } + }; + })(); + exports2.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" + ]; + function useColors() { + if (typeof window !== "undefined" && window.process && (window.process.type === "renderer" || window.process.__nwjs)) { + return true; + } + if (typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/); + } + function formatArgs(args) { + args[0] = (this.useColors ? "%c" : "") + this.namespace + (this.useColors ? " %c" : " ") + args[0] + (this.useColors ? "%c " : " ") + "+" + module2.exports.humanize(this.diff); + if (!this.useColors) { + return; + } + const c = "color: " + this.color; + args.splice(1, 0, c, "color: inherit"); + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, (match) => { + if (match === "%%") { + return; + } + index++; + if (match === "%c") { + lastC = index; + } + }); + args.splice(lastC, 0, c); + } + exports2.log = console.debug || console.log || (() => { + }); + function save(namespaces) { + try { + if (namespaces) { + exports2.storage.setItem("debug", namespaces); + } else { + exports2.storage.removeItem("debug"); + } + } catch (error) { + } + } + function load() { + let r; + try { + r = exports2.storage.getItem("debug"); + } catch (error) { + } + if (!r && typeof process !== "undefined" && "env" in process) { + r = process.env.DEBUG; + } + return r; + } + function localstorage() { + try { + return localStorage; + } catch (error) { + } + } + module2.exports = require_common()(exports2); + var { formatters } = module2.exports; + formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (error) { + return "[UnexpectedJSONParseError]: " + error.message; + } + }; + } +}); + +// node_modules/has-flag/index.js +var require_has_flag = __commonJS({ + "node_modules/has-flag/index.js"(exports2, module2) { + "use strict"; + module2.exports = (flag, argv = process.argv) => { + const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--"; + const position = argv.indexOf(prefix + flag); + const terminatorPosition = argv.indexOf("--"); + return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); + }; + } +}); + +// node_modules/supports-color/index.js +var require_supports_color = __commonJS({ + "node_modules/supports-color/index.js"(exports2, module2) { + "use strict"; + var os10 = require("os"); + var tty = require("tty"); + var hasFlag = require_has_flag(); + var { env } = process; + var 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") { + forceColor = 1; + } else if (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(haveStream, streamIsTTY) { + if (forceColor === 0) { + return 0; + } + if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) { + return 3; + } + if (hasFlag("color=256")) { + return 2; + } + if (haveStream && !streamIsTTY && forceColor === void 0) { + return 0; + } + const min = forceColor || 0; + if (env.TERM === "dumb") { + return min; + } + if (process.platform === "win32") { + const osRelease = os10.release().split("."); + if (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", "GITHUB_ACTIONS", "BUILDKITE"].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 version2 = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10); + switch (env.TERM_PROGRAM) { + case "iTerm.app": + return version2 >= 3 ? 3 : 2; + case "Apple_Terminal": + return 2; + } + } + 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, stream && stream.isTTY); + return translateLevel(level); + } + module2.exports = { + supportsColor: getSupportLevel, + stdout: translateLevel(supportsColor(true, tty.isatty(1))), + stderr: translateLevel(supportsColor(true, tty.isatty(2))) + }; + } +}); + +// node_modules/debug/src/node.js +var require_node = __commonJS({ + "node_modules/debug/src/node.js"(exports2, module2) { + var tty = require("tty"); + var util4 = require("util"); + exports2.init = init; + exports2.log = log; + exports2.formatArgs = formatArgs; + exports2.save = save; + exports2.load = load; + exports2.useColors = useColors; + exports2.destroy = util4.deprecate(() => { + }, "Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); + exports2.colors = [6, 2, 3, 4, 5, 1]; + try { + const supportsColor = require_supports_color(); + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports2.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) { + } + exports2.inspectOpts = Object.keys(process.env).filter((key) => { + return /^debug_/i.test(key); + }).reduce((obj, key) => { + const prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + 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; + }, {}); + function useColors() { + return "colors" in exports2.inspectOpts ? Boolean(exports2.inspectOpts.colors) : tty.isatty(process.stderr.fd); + } + function formatArgs(args) { + const { namespace: name2, useColors: useColors2 } = this; + if (useColors2) { + const c = this.color; + const colorCode = "[3" + (c < 8 ? c : "8;5;" + c); + const prefix = ` ${colorCode};1m${name2} `; + args[0] = prefix + args[0].split("\n").join("\n" + prefix); + args.push(colorCode + "m+" + module2.exports.humanize(this.diff) + ""); + } else { + args[0] = getDate() + name2 + " " + args[0]; + } + } + function getDate() { + if (exports2.inspectOpts.hideDate) { + return ""; + } + return new Date().toISOString() + " "; + } + function log(...args) { + return process.stderr.write(util4.format(...args) + "\n"); + } + function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + delete process.env.DEBUG; + } + } + function load() { + return process.env.DEBUG; + } + function init(debug) { + debug.inspectOpts = {}; + const keys = Object.keys(exports2.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]]; + } + } + module2.exports = require_common()(exports2); + var { formatters } = module2.exports; + formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util4.inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" "); + }; + formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util4.inspect(v, this.inspectOpts); + }; + } +}); + +// node_modules/debug/src/index.js +var require_src = __commonJS({ + "node_modules/debug/src/index.js"(exports2, module2) { + if (typeof process === "undefined" || process.type === "renderer" || process.browser === true || process.__nwjs) { + module2.exports = require_browser(); + } else { + module2.exports = require_node(); + } + } +}); + +// node_modules/rfdc/index.js +var require_rfdc = __commonJS({ + "node_modules/rfdc/index.js"(exports2, module2) { + "use strict"; + module2.exports = rfdc; + function copyBuffer(cur) { + if (cur instanceof Buffer) { + return Buffer.from(cur); + } + return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length); + } + 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 if (ArrayBuffer.isView(cur)) { + a2[k] = copyBuffer(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); + if (o instanceof Map) + return new Map(cloneArray(Array.from(o), clone)); + if (o instanceof Set) + return new Set(cloneArray(Array.from(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 if (cur instanceof Map) { + o2[k] = new Map(cloneArray(Array.from(cur), clone)); + } else if (cur instanceof Set) { + o2[k] = new Set(cloneArray(Array.from(cur), clone)); + } else if (ArrayBuffer.isView(cur)) { + o2[k] = copyBuffer(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); + if (o instanceof Map) + return new Map(cloneArray(Array.from(o), cloneProto)); + if (o instanceof Set) + return new Set(cloneArray(Array.from(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 if (cur instanceof Map) { + o2[k] = new Map(cloneArray(Array.from(cur), cloneProto)); + } else if (cur instanceof Set) { + o2[k] = new Set(cloneArray(Array.from(cur), cloneProto)); + } else if (ArrayBuffer.isView(cur)) { + o2[k] = copyBuffer(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 if (ArrayBuffer.isView(cur)) { + a2[k] = copyBuffer(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); + if (o instanceof Map) + return new Map(cloneArray(Array.from(o), clone)); + if (o instanceof Set) + return new Set(cloneArray(Array.from(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 if (cur instanceof Map) { + o2[k] = new Map(cloneArray(Array.from(cur), clone)); + } else if (cur instanceof Set) { + o2[k] = new Set(cloneArray(Array.from(cur), clone)); + } else if (ArrayBuffer.isView(cur)) { + o2[k] = copyBuffer(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); + if (o instanceof Map) + return new Map(cloneArray(Array.from(o), cloneProto)); + if (o instanceof Set) + return new Set(cloneArray(Array.from(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 if (cur instanceof Map) { + o2[k] = new Map(cloneArray(Array.from(cur), cloneProto)); + } else if (cur instanceof Set) { + o2[k] = new Set(cloneArray(Array.from(cur), cloneProto)); + } else if (ArrayBuffer.isView(cur)) { + o2[k] = copyBuffer(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; + } + } + } +}); + +// node_modules/log4js/lib/configuration.js +var require_configuration = __commonJS({ + "node_modules/log4js/lib/configuration.js"(exports2, module2) { + var util4 = require("util"); + var debug = require_src()("log4js:configuration"); + var preProcessingListeners = []; + var listeners = []; + var not = (thing) => !thing; + var anObject = (thing) => thing && typeof thing === "object" && !Array.isArray(thing); + var validIdentifier = (thing) => /^[A-Za-z][A-Za-z0-9_]*$/g.test(thing); + var anInteger = (thing) => thing && typeof thing === "number" && Number.isInteger(thing); + var addListener = (fn) => { + listeners.push(fn); + debug(`Added listener, now ${listeners.length} listeners`); + }; + var addPreProcessingListener = (fn) => { + preProcessingListeners.push(fn); + debug(`Added pre-processing listener, now ${preProcessingListeners.length} listeners`); + }; + var throwExceptionIf = (config, checks, message) => { + const tests = Array.isArray(checks) ? checks : [checks]; + tests.forEach((test) => { + if (test) { + throw new Error(`Problem with log4js configuration: (${util4.inspect(config, { depth: 5 })}) - ${message}`); + } + }); + }; + var 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."); + }; + module2.exports = { + configure, + addListener, + addPreProcessingListener, + throwExceptionIf, + anObject, + anInteger, + validIdentifier, + not + }; + } +}); + +// node_modules/date-format/lib/index.js +var require_lib = __commonJS({ + "node_modules/date-format/lib/index.js"(exports2, module2) { + "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); + } + function offset(timezoneOffset) { + var os10 = Math.abs(timezoneOffset); + var h = String(Math.floor(os10 / 60)); + var m = String(os10 % 60); + if (h.length === 1) { + h = "0" + h; + } + if (m.length === 1) { + m = "0" + m; + } + return timezoneOffset < 0 ? "+" + h + m : "-" + h + m; + } + function asString(format2, date) { + if (typeof format2 !== "string") { + date = format2; + format2 = module2.exports.ISO8601_FORMAT; + } + if (!date) { + date = module2.exports.now(); + } + var vDay = addZero(date.getDate()); + var vMonth = addZero(date.getMonth() + 1); + var vYearLong = addZero(date.getFullYear()); + var vYearShort = addZero(vYearLong.substring(2, 4)); + var vYear = format2.indexOf("yyyy") > -1 ? vYearLong : vYearShort; + var vHour = addZero(date.getHours()); + var vMinute = addZero(date.getMinutes()); + var vSecond = addZero(date.getSeconds()); + var vMillisecond = padWithZeros(date.getMilliseconds(), 3); + var vTimeZone = offset(date.getTimezoneOffset()); + var formatted = format2.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 setDatePart(date, part, value, local) { + date["set" + (local ? "" : "UTC") + part](value); + } + function extractDateParts(pattern, str, missingValuesDate) { + var local = pattern.indexOf("O") < 0; + var matchers = [ + { + pattern: /y{1,4}/, + regexp: "\\d{1,4}", + fn: function(date2, value) { + setDatePart(date2, "FullYear", value, local); + } + }, + { + pattern: /MM/, + regexp: "\\d{1,2}", + fn: function(date2, value) { + setDatePart(date2, "Month", value - 1, local); + } + }, + { + pattern: /dd/, + regexp: "\\d{1,2}", + fn: function(date2, value) { + setDatePart(date2, "Date", value, local); + } + }, + { + pattern: /hh/, + regexp: "\\d{1,2}", + fn: function(date2, value) { + setDatePart(date2, "Hours", value, local); + } + }, + { + pattern: /mm/, + regexp: "\\d\\d", + fn: function(date2, value) { + setDatePart(date2, "Minutes", value, local); + } + }, + { + pattern: /ss/, + regexp: "\\d\\d", + fn: function(date2, value) { + setDatePart(date2, "Seconds", value, local); + } + }, + { + pattern: /SSS/, + regexp: "\\d\\d\\d", + fn: function(date2, value) { + setDatePart(date2, "Milliseconds", value, local); + } + }, + { + pattern: /O/, + regexp: "[+-]\\d{3,4}|Z", + fn: function(date2, value) { + if (value === "Z") { + value = 0; + } + var offset2 = Math.abs(value); + var timezoneOffset = (value > 0 ? -1 : 1) * (offset2 % 100 + Math.floor(offset2 / 100) * 60); + date2.setUTCMinutes(date2.getUTCMinutes() + timezoneOffset); + } + } + ]; + 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 || module2.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 parse5(pattern, str, missingValuesDate) { + if (!pattern) { + throw new Error("pattern must be supplied"); + } + return extractDateParts(pattern, str, missingValuesDate); + } + function now() { + return new Date(); + } + module2.exports = asString; + module2.exports.asString = asString; + module2.exports.parse = parse5; + module2.exports.now = now; + module2.exports.ISO8601_FORMAT = "yyyy-MM-ddThh:mm:ss.SSS"; + module2.exports.ISO8601_WITH_TZ_OFFSET_FORMAT = "yyyy-MM-ddThh:mm:ss.SSSO"; + module2.exports.DATETIME_FORMAT = "dd MM yyyy hh:mm:ss.SSS"; + module2.exports.ABSOLUTETIME_FORMAT = "hh:mm:ss.SSS"; + } +}); + +// node_modules/log4js/lib/layouts.js +var require_layouts = __commonJS({ + "node_modules/log4js/lib/layouts.js"(exports2, module2) { + var dateFormat = require_lib(); + var os10 = require("os"); + var util4 = require("util"); + var path36 = require("path"); + var styles3 = { + bold: [1, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + white: [37, 39], + grey: [90, 39], + black: [90, 39], + blue: [34, 39], + cyan: [36, 39], + green: [32, 39], + magenta: [35, 39], + red: [91, 39], + yellow: [33, 39] + }; + function colorizeStart(style2) { + return style2 ? `[${styles3[style2][0]}m` : ""; + } + function colorizeEnd(style2) { + return style2 ? `[${styles3[style2][1]}m` : ""; + } + function colorize(str, style2) { + return colorizeStart(style2) + str + colorizeEnd(style2); + } + function timestampLevelAndCategory(loggingEvent, colour) { + return colorize(util4.format("[%s] [%s] %s - ", dateFormat.asString(loggingEvent.startTime), loggingEvent.level.toString(), loggingEvent.categoryName), colour); + } + function basicLayout(loggingEvent) { + return timestampLevelAndCategory(loggingEvent) + util4.format(...loggingEvent.data); + } + function colouredLayout(loggingEvent) { + return timestampLevelAndCategory(loggingEvent, loggingEvent.level.colour) + util4.format(...loggingEvent.data); + } + function messagePassThroughLayout(loggingEvent) { + return util4.format(...loggingEvent.data); + } + function dummyLayout(loggingEvent) { + return loggingEvent.data[0]; + } + 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 format2 = dateFormat.ISO8601_FORMAT; + if (specifier) { + format2 = specifier; + if (format2 === "ISO8601") { + format2 = dateFormat.ISO8601_FORMAT; + } else if (format2 === "ISO8601_WITH_TZ_OFFSET") { + format2 = dateFormat.ISO8601_WITH_TZ_OFFSET_FORMAT; + } else if (format2 === "ABSOLUTE") { + format2 = dateFormat.ABSOLUTETIME_FORMAT; + } else if (format2 === "DATE") { + format2 = dateFormat.DATETIME_FORMAT; + } + } + return dateFormat.asString(format2, loggingEvent.startTime); + } + function hostname() { + return os10.hostname().toString(); + } + function formatMessage(loggingEvent) { + return util4.format(...loggingEvent.data); + } + function endOfLine() { + return os10.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() { + 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(path36.sep); + if (fileList.length > fileDepth) { + filename = fileList.slice(-fileDepth).join(path36.sep); + } + } + return filename; + } + function lineNumber(loggingEvent) { + return loggingEvent.lineNumber ? `${loggingEvent.lineNumber}` : ""; + } + function columnNumber(loggingEvent) { + return loggingEvent.columnNumber ? `${loggingEvent.columnNumber}` : ""; + } + function callStack(loggingEvent) { + return loggingEvent.callStack || ""; + } + 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 len > 0 ? toTruncate.slice(0, len) : toTruncate.slice(len); + } + return toTruncate; + } + function pad2(padding, toPad) { + let len; + if (padding) { + if (padding.charAt(0) === "-") { + len = parseInt(padding.substr(1), 10); + while (toPad.length < len) { + toPad += " "; + } + } else { + len = parseInt(padding, 10); + while (toPad.length < len) { + toPad = ` ${toPad}`; + } + } + } + return toPad; + } + function truncateAndPad(toTruncAndPad, truncation, padding) { + let replacement = toTruncAndPad; + replacement = truncate(truncation, replacement); + replacement = pad2(padding, replacement); + return replacement; + } + return function(loggingEvent) { + let formattedString = ""; + let result; + let searchString = pattern; + while ((result = regex.exec(searchString)) !== null) { + const padding = result[1]; + const truncation = result[2]; + const conversionCharacter = result[3]; + const specifier = result[5]; + const text = result[6]; + if (text) { + formattedString += text.toString(); + } else { + const replacement = replaceToken(conversionCharacter, loggingEvent, specifier); + formattedString += truncateAndPad(replacement, truncation, padding); + } + searchString = searchString.substr(result.index + result[0].length); + } + return formattedString; + }; + } + var 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; + } + }; + module2.exports = { + basicLayout, + messagePassThroughLayout, + patternLayout, + colouredLayout, + coloredLayout: colouredLayout, + dummyLayout, + addLayout(name2, serializerGenerator) { + layoutMakers[name2] = serializerGenerator; + }, + layout(name2, config) { + return layoutMakers[name2] && layoutMakers[name2](config); + } + }; + } +}); + +// node_modules/log4js/lib/levels.js +var require_levels = __commonJS({ + "node_modules/log4js/lib/levels.js"(exports2, module2) { + var configuration = require_configuration(); + var validColours = [ + "white", + "grey", + "black", + "blue", + "cyan", + "green", + "magenta", + "red", + "yellow" + ]; + var Level = class { + constructor(level, levelStr, colour) { + this.level = level; + this.levelStr = levelStr; + this.colour = colour; + } + toString() { + return this.levelStr; + } + static getLevel(sArg, defaultLevel) { + if (!sArg) { + return defaultLevel; + } + if (sArg instanceof Level) { + return sArg; + } + 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: 5e3, colour: "blue" }, + DEBUG: { value: 1e4, colour: "cyan" }, + INFO: { value: 2e4, colour: "green" }, + WARN: { value: 3e4, colour: "yellow" }, + ERROR: { value: 4e4, colour: "red" }, + FATAL: { value: 5e4, colour: "magenta" }, + MARK: { value: 9007199254740992, colour: "grey" }, + 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); + }); + module2.exports = Level; + } +}); + +// node_modules/flatted/esm/index.js +var esm_exports = {}; +__export(esm_exports, { + default: () => esm_default, + parse: () => parse, + stringify: () => stringify +}); +var Flatted, esm_default, parse, stringify; +var init_esm = __esm({ + "node_modules/flatted/esm/index.js"() { + Flatted = function(Primitive, primitive) { + var Flatted2 = { + parse: function parse5(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 stringify3(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, value2) { + if (firstRun) { + firstRun = !firstRun; + return value2; + } + var after = $.call(this, key, value2); + 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 Flatted2; + function noop(key, value) { + return value; + } + function revive(input, parsed, output, $) { + return Object.keys(output).reduce(function(output2, key) { + var value = output2[key]; + if (value instanceof Primitive) { + var tmp = input[value]; + if (typeof tmp === "object" && !parsed.has(tmp)) { + parsed.add(tmp); + output2[key] = $.call(output2, key, revive(input, parsed, tmp, $)); + } else { + output2[key] = $.call(output2, key, tmp); + } + } else + output2[key] = $.call(output2, key, value); + return output2; + }, output); + } + function set(known, input, value) { + var index = Primitive(input.push(value) - 1); + known.set(value, index); + return index; + } + function primitives(value) { + return value instanceof Primitive ? Primitive(value) : value; + } + function Primitives(key, value) { + return typeof value === primitive ? new Primitive(value) : value; + } + }(String, "string"); + esm_default = Flatted; + parse = Flatted.parse; + stringify = Flatted.stringify; + } +}); + +// node_modules/log4js/lib/LoggingEvent.js +var require_LoggingEvent = __commonJS({ + "node_modules/log4js/lib/LoggingEvent.js"(exports2, module2) { + var flatted = (init_esm(), esm_exports); + var levels = require_levels(); + var LoggingEvent = class { + 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) => { + 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; + } + }; + module2.exports = LoggingEvent; + } +}); + +// node_modules/log4js/lib/clustering.js +var require_clustering = __commonJS({ + "node_modules/log4js/lib/clustering.js"(exports2, module2) { + var debug = require_src()("log4js:clustering"); + var LoggingEvent = require_LoggingEvent(); + var configuration = require_configuration(); + var disabled = false; + var cluster = null; + try { + cluster = require("cluster"); + } catch (e) { + debug("cluster module not present"); + disabled = true; + } + var listeners = []; + var pm2 = false; + var pm2InstanceVar = "NODE_APP_INSTANCE"; + var isPM2Master = () => pm2 && process.env[pm2InstanceVar] === "0"; + var isMaster = () => disabled || cluster.isMaster || isPM2Master(); + var sendToListeners = (logEvent) => { + listeners.forEach((l) => l(logEvent)); + }; + var receiver = (worker, message) => { + debug("cluster message received from worker ", worker, ": ", message); + if (worker.topic && worker.data) { + message = worker; + worker = void 0; + } + 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) => { + 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]}`); + 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()) { + 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"); + } + }); + } + module2.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); + } + }; + } +}); + +// node_modules/log4js/lib/appenders/adapters.js +var require_adapters = __commonJS({ + "node_modules/log4js/lib/appenders/adapters.js"(exports2, module2) { + 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); + } + var adapters = { + file: fileAppenderAdapter, + fileSync: fileAppenderAdapter + }; + module2.exports.modifyConfig = (config) => adapters[config.type] ? adapters[config.type](config) : config; + } +}); + +// node_modules/log4js/lib/appenders/console.js +var require_console = __commonJS({ + "node_modules/log4js/lib/appenders/console.js"(exports2, module2) { + var 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); + } + module2.exports.configure = configure; + } +}); + +// node_modules/log4js/lib/appenders/stdout.js +var require_stdout = __commonJS({ + "node_modules/log4js/lib/appenders/stdout.js"(exports2) { + function stdoutAppender(layout, timezoneOffset) { + return (loggingEvent) => { + process.stdout.write(`${layout(loggingEvent, timezoneOffset)} +`); + }; + } + function configure(config, layouts) { + let layout = layouts.colouredLayout; + if (config.layout) { + layout = layouts.layout(config.layout.type, config.layout); + } + return stdoutAppender(layout, config.timezoneOffset); + } + exports2.configure = configure; + } +}); + +// node_modules/log4js/lib/appenders/stderr.js +var require_stderr = __commonJS({ + "node_modules/log4js/lib/appenders/stderr.js"(exports2, module2) { + function stderrAppender(layout, timezoneOffset) { + return (loggingEvent) => { + process.stderr.write(`${layout(loggingEvent, timezoneOffset)} +`); + }; + } + function configure(config, layouts) { + let layout = layouts.colouredLayout; + if (config.layout) { + layout = layouts.layout(config.layout.type, config.layout); + } + return stderrAppender(layout, config.timezoneOffset); + } + module2.exports.configure = configure; + } +}); + +// node_modules/log4js/lib/appenders/logLevelFilter.js +var require_logLevelFilter = __commonJS({ + "node_modules/log4js/lib/appenders/logLevelFilter.js"(exports2, module2) { + 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); + } + module2.exports.configure = configure; + } +}); + +// node_modules/log4js/lib/appenders/categoryFilter.js +var require_categoryFilter = __commonJS({ + "node_modules/log4js/lib/appenders/categoryFilter.js"(exports2, module2) { + var debug = require_src()("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); + } + module2.exports.configure = configure; + } +}); + +// node_modules/log4js/lib/appenders/noLogFilter.js +var require_noLogFilter = __commonJS({ + "node_modules/log4js/lib/appenders/noLogFilter.js"(exports2, module2) { + var debug = require_src()("log4js:noLogFilter"); + function removeNullOrEmptyRegexp(regexp) { + const filtered = regexp.filter((el) => el != null && el !== ""); + return filtered; + } + 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); + } + module2.exports.configure = configure; + } +}); + +// node_modules/universalify/index.js +var require_universalify = __commonJS({ + "node_modules/universalify/index.js"(exports2) { + "use strict"; + exports2.fromCallback = function(fn) { + return Object.defineProperty(function() { + if (typeof arguments[arguments.length - 1] === "function") + fn.apply(this, arguments); + else { + return new Promise((resolve3, reject) => { + arguments[arguments.length] = (err, res) => { + if (err) + return reject(err); + resolve3(res); + }; + arguments.length++; + fn.apply(this, arguments); + }); + } + }, "name", { value: fn.name }); + }; + exports2.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 }); + }; + } +}); + +// node_modules/graceful-fs/polyfills.js +var require_polyfills = __commonJS({ + "node_modules/graceful-fs/polyfills.js"(exports2, module2) { + var constants = require("constants"); + var origCwd = process.cwd; + var cwd = null; + var platform3 = process.env.GRACEFUL_FS_PLATFORM || process.platform; + process.cwd = function() { + if (!cwd) + cwd = origCwd.call(process); + return cwd; + }; + try { + process.cwd(); + } catch (er) { + } + if (typeof process.chdir === "function") { + chdir = process.chdir; + process.chdir = function(d) { + cwd = null; + chdir.call(process, d); + }; + if (Object.setPrototypeOf) + Object.setPrototypeOf(process.chdir, chdir); + } + var chdir; + module2.exports = patch; + function patch(fs27) { + if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + patchLchmod(fs27); + } + if (!fs27.lutimes) { + patchLutimes(fs27); + } + fs27.chown = chownFix(fs27.chown); + fs27.fchown = chownFix(fs27.fchown); + fs27.lchown = chownFix(fs27.lchown); + fs27.chmod = chmodFix(fs27.chmod); + fs27.fchmod = chmodFix(fs27.fchmod); + fs27.lchmod = chmodFix(fs27.lchmod); + fs27.chownSync = chownFixSync(fs27.chownSync); + fs27.fchownSync = chownFixSync(fs27.fchownSync); + fs27.lchownSync = chownFixSync(fs27.lchownSync); + fs27.chmodSync = chmodFixSync(fs27.chmodSync); + fs27.fchmodSync = chmodFixSync(fs27.fchmodSync); + fs27.lchmodSync = chmodFixSync(fs27.lchmodSync); + fs27.stat = statFix(fs27.stat); + fs27.fstat = statFix(fs27.fstat); + fs27.lstat = statFix(fs27.lstat); + fs27.statSync = statFixSync(fs27.statSync); + fs27.fstatSync = statFixSync(fs27.fstatSync); + fs27.lstatSync = statFixSync(fs27.lstatSync); + if (!fs27.lchmod) { + fs27.lchmod = function(path36, mode, cb) { + if (cb) + process.nextTick(cb); + }; + fs27.lchmodSync = function() { + }; + } + if (!fs27.lchown) { + fs27.lchown = function(path36, uid, gid, cb) { + if (cb) + process.nextTick(cb); + }; + fs27.lchownSync = function() { + }; + } + if (platform3 === "win32") { + fs27.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 < 6e4) { + setTimeout(function() { + fs27.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); + }); + }; + }(fs27.rename); + } + fs27.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(fs27, fd, buffer, offset, length, position, callback); + } + callback_.apply(this, arguments); + }; + } + return fs$read.call(fs27, fd, buffer, offset, length, position, callback); + } + if (Object.setPrototypeOf) + Object.setPrototypeOf(read, fs$read); + return read; + }(fs27.read); + fs27.readSync = function(fs$readSync) { + return function(fd, buffer, offset, length, position) { + var eagCounter = 0; + while (true) { + try { + return fs$readSync.call(fs27, fd, buffer, offset, length, position); + } catch (er) { + if (er.code === "EAGAIN" && eagCounter < 10) { + eagCounter++; + continue; + } + throw er; + } + } + }; + }(fs27.readSync); + function patchLchmod(fs28) { + fs28.lchmod = function(path36, mode, callback) { + fs28.open(path36, constants.O_WRONLY | constants.O_SYMLINK, mode, function(err, fd) { + if (err) { + if (callback) + callback(err); + return; + } + fs28.fchmod(fd, mode, function(err2) { + fs28.close(fd, function(err22) { + if (callback) + callback(err2 || err22); + }); + }); + }); + }; + fs28.lchmodSync = function(path36, mode) { + var fd = fs28.openSync(path36, constants.O_WRONLY | constants.O_SYMLINK, mode); + var threw = true; + var ret; + try { + ret = fs28.fchmodSync(fd, mode); + threw = false; + } finally { + if (threw) { + try { + fs28.closeSync(fd); + } catch (er) { + } + } else { + fs28.closeSync(fd); + } + } + return ret; + }; + } + function patchLutimes(fs28) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs28.lutimes = function(path36, at, mt, cb) { + fs28.open(path36, constants.O_SYMLINK, function(er, fd) { + if (er) { + if (cb) + cb(er); + return; + } + fs28.futimes(fd, at, mt, function(er2) { + fs28.close(fd, function(er22) { + if (cb) + cb(er2 || er22); + }); + }); + }); + }; + fs28.lutimesSync = function(path36, at, mt) { + var fd = fs28.openSync(path36, constants.O_SYMLINK); + var ret; + var threw = true; + try { + ret = fs28.futimesSync(fd, at, mt); + threw = false; + } finally { + if (threw) { + try { + fs28.closeSync(fd); + } catch (er) { + } + } else { + fs28.closeSync(fd); + } + } + return ret; + }; + } else { + fs28.lutimes = function(_a2, _b, _c, cb) { + if (cb) + process.nextTick(cb); + }; + fs28.lutimesSync = function() { + }; + } + } + function chmodFix(orig) { + if (!orig) + return orig; + return function(target, mode, cb) { + return orig.call(fs27, 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(fs27, 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(fs27, 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(fs27, target, uid, gid); + } catch (er) { + if (!chownErOk(er)) + throw er; + } + }; + } + function statFix(orig) { + if (!orig) + return orig; + 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 += 4294967296; + if (stats.gid < 0) + stats.gid += 4294967296; + } + if (cb) + cb.apply(this, arguments); + } + return options ? orig.call(fs27, target, options, callback) : orig.call(fs27, target, callback); + }; + } + function statFixSync(orig) { + if (!orig) + return orig; + return function(target, options) { + var stats = options ? orig.call(fs27, target, options) : orig.call(fs27, target); + if (stats.uid < 0) + stats.uid += 4294967296; + if (stats.gid < 0) + stats.gid += 4294967296; + return stats; + }; + } + 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; + } + } + } +}); + +// node_modules/graceful-fs/legacy-streams.js +var require_legacy_streams = __commonJS({ + "node_modules/graceful-fs/legacy-streams.js"(exports2, module2) { + var Stream = require("stream").Stream; + module2.exports = legacy; + function legacy(fs27) { + return { + ReadStream, + WriteStream + }; + function ReadStream(path36, options) { + if (!(this instanceof ReadStream)) + return new ReadStream(path36, options); + Stream.call(this); + var self2 = this; + this.path = path36; + this.fd = null; + this.readable = true; + this.paused = false; + this.flags = "r"; + this.mode = 438; + this.bufferSize = 64 * 1024; + options = options || {}; + 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 !== void 0) { + if (typeof this.start !== "number") { + throw TypeError("start must be a Number"); + } + if (this.end === void 0) { + this.end = Infinity; + } else if (typeof this.end !== "number") { + 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() { + self2._read(); + }); + return; + } + fs27.open(this.path, this.flags, this.mode, function(err, fd) { + if (err) { + self2.emit("error", err); + self2.readable = false; + return; + } + self2.fd = fd; + self2.emit("open", fd); + self2._read(); + }); + } + function WriteStream(path36, options) { + if (!(this instanceof WriteStream)) + return new WriteStream(path36, options); + Stream.call(this); + this.path = path36; + this.fd = null; + this.writable = true; + this.flags = "w"; + this.encoding = "binary"; + this.mode = 438; + this.bytesWritten = 0; + options = options || {}; + 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 !== void 0) { + if (typeof this.start !== "number") { + 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 = fs27.open; + this._queue.push([this._open, this.path, this.flags, this.mode, void 0]); + this.flush(); + } + } + } + } +}); + +// node_modules/graceful-fs/clone.js +var require_clone = __commonJS({ + "node_modules/graceful-fs/clone.js"(exports2, module2) { + "use strict"; + module2.exports = clone; + var getPrototypeOf = Object.getPrototypeOf || function(obj) { + return obj.__proto__; + }; + function clone(obj) { + if (obj === null || typeof obj !== "object") + return obj; + if (obj instanceof Object) + var copy = { __proto__: getPrototypeOf(obj) }; + else + var copy = Object.create(null); + Object.getOwnPropertyNames(obj).forEach(function(key) { + Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key)); + }); + return copy; + } + } +}); + +// node_modules/graceful-fs/graceful-fs.js +var require_graceful_fs = __commonJS({ + "node_modules/graceful-fs/graceful-fs.js"(exports2, module2) { + var fs27 = require("fs"); + var polyfills = require_polyfills(); + var legacy = require_legacy_streams(); + var clone = require_clone(); + var util4 = require("util"); + var gracefulQueue; + var previousSymbol; + if (typeof Symbol === "function" && typeof Symbol.for === "function") { + gracefulQueue = Symbol.for("graceful-fs.queue"); + previousSymbol = Symbol.for("graceful-fs.previous"); + } else { + gracefulQueue = "___graceful-fs.queue"; + previousSymbol = "___graceful-fs.previous"; + } + function noop() { + } + function publishQueue(context, queue2) { + Object.defineProperty(context, gracefulQueue, { + get: function() { + return queue2; + } + }); + } + var debug = noop; + if (util4.debuglog) + debug = util4.debuglog("gfs4"); + else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) + debug = function() { + var m = util4.format.apply(util4, arguments); + m = "GFS4: " + m.split(/\n/).join("\nGFS4: "); + console.error(m); + }; + if (!fs27[gracefulQueue]) { + queue = global[gracefulQueue] || []; + publishQueue(fs27, queue); + fs27.close = function(fs$close) { + function close(fd, cb) { + return fs$close.call(fs27, fd, function(err) { + if (!err) { + retry(); + } + if (typeof cb === "function") + cb.apply(this, arguments); + }); + } + Object.defineProperty(close, previousSymbol, { + value: fs$close + }); + return close; + }(fs27.close); + fs27.closeSync = function(fs$closeSync) { + function closeSync(fd) { + fs$closeSync.apply(fs27, arguments); + retry(); + } + Object.defineProperty(closeSync, previousSymbol, { + value: fs$closeSync + }); + return closeSync; + }(fs27.closeSync); + if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) { + process.on("exit", function() { + debug(fs27[gracefulQueue]); + require("assert").equal(fs27[gracefulQueue].length, 0); + }); + } + } + var queue; + if (!global[gracefulQueue]) { + publishQueue(global, fs27[gracefulQueue]); + } + module2.exports = patch(clone(fs27)); + if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs27.__patched) { + module2.exports = patch(fs27); + fs27.__patched = true; + } + function patch(fs28) { + polyfills(fs28); + fs28.gracefulify = patch; + fs28.createReadStream = createReadStream; + fs28.createWriteStream = createWriteStream; + var fs$readFile = fs28.readFile; + fs28.readFile = readFile2; + function readFile2(path36, options, cb) { + if (typeof options === "function") + cb = options, options = null; + return go$readFile(path36, options, cb); + function go$readFile(path37, options2, cb2) { + return fs$readFile(path37, options2, function(err) { + if (err && (err.code === "EMFILE" || err.code === "ENFILE")) + enqueue([go$readFile, [path37, options2, cb2]]); + else { + if (typeof cb2 === "function") + cb2.apply(this, arguments); + retry(); + } + }); + } + } + var fs$writeFile = fs28.writeFile; + fs28.writeFile = writeFile2; + function writeFile2(path36, data, options, cb) { + if (typeof options === "function") + cb = options, options = null; + return go$writeFile(path36, data, options, cb); + function go$writeFile(path37, data2, options2, cb2) { + return fs$writeFile(path37, data2, options2, function(err) { + if (err && (err.code === "EMFILE" || err.code === "ENFILE")) + enqueue([go$writeFile, [path37, data2, options2, cb2]]); + else { + if (typeof cb2 === "function") + cb2.apply(this, arguments); + retry(); + } + }); + } + } + var fs$appendFile = fs28.appendFile; + if (fs$appendFile) + fs28.appendFile = appendFile; + function appendFile(path36, data, options, cb) { + if (typeof options === "function") + cb = options, options = null; + return go$appendFile(path36, data, options, cb); + function go$appendFile(path37, data2, options2, cb2) { + return fs$appendFile(path37, data2, options2, function(err) { + if (err && (err.code === "EMFILE" || err.code === "ENFILE")) + enqueue([go$appendFile, [path37, data2, options2, cb2]]); + else { + if (typeof cb2 === "function") + cb2.apply(this, arguments); + retry(); + } + }); + } + } + var fs$copyFile = fs28.copyFile; + if (fs$copyFile) + fs28.copyFile = copyFile; + function copyFile(src, dest, flags, cb) { + if (typeof flags === "function") { + cb = flags; + flags = 0; + } + return fs$copyFile(src, dest, flags, function(err) { + if (err && (err.code === "EMFILE" || err.code === "ENFILE")) + enqueue([fs$copyFile, [src, dest, flags, cb]]); + else { + if (typeof cb === "function") + cb.apply(this, arguments); + retry(); + } + }); + } + var fs$readdir = fs28.readdir; + fs28.readdir = readdir; + function readdir(path36, options, cb) { + var args = [path36]; + 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(fs28, args); + } + if (process.version.substr(0, 4) === "v0.8") { + var legStreams = legacy(fs28); + ReadStream = legStreams.ReadStream; + WriteStream = legStreams.WriteStream; + } + var fs$ReadStream = fs28.ReadStream; + if (fs$ReadStream) { + ReadStream.prototype = Object.create(fs$ReadStream.prototype); + ReadStream.prototype.open = ReadStream$open; + } + var fs$WriteStream = fs28.WriteStream; + if (fs$WriteStream) { + WriteStream.prototype = Object.create(fs$WriteStream.prototype); + WriteStream.prototype.open = WriteStream$open; + } + Object.defineProperty(fs28, "ReadStream", { + get: function() { + return ReadStream; + }, + set: function(val) { + ReadStream = val; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(fs28, "WriteStream", { + get: function() { + return WriteStream; + }, + set: function(val) { + WriteStream = val; + }, + enumerable: true, + configurable: true + }); + var FileReadStream = ReadStream; + Object.defineProperty(fs28, "FileReadStream", { + get: function() { + return FileReadStream; + }, + set: function(val) { + FileReadStream = val; + }, + enumerable: true, + configurable: true + }); + var FileWriteStream = WriteStream; + Object.defineProperty(fs28, "FileWriteStream", { + get: function() { + return FileWriteStream; + }, + set: function(val) { + FileWriteStream = val; + }, + enumerable: true, + configurable: true + }); + function ReadStream(path36, 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(path36, 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(path36, options) { + return new fs28.ReadStream(path36, options); + } + function createWriteStream(path36, options) { + return new fs28.WriteStream(path36, options); + } + var fs$open = fs28.open; + fs28.open = open; + function open(path36, flags, mode, cb) { + if (typeof mode === "function") + cb = mode, mode = null; + return go$open(path36, flags, mode, cb); + function go$open(path37, flags2, mode2, cb2) { + return fs$open(path37, flags2, mode2, function(err, fd) { + if (err && (err.code === "EMFILE" || err.code === "ENFILE")) + enqueue([go$open, [path37, flags2, mode2, cb2]]); + else { + if (typeof cb2 === "function") + cb2.apply(this, arguments); + retry(); + } + }); + } + } + return fs28; + } + function enqueue(elem) { + debug("ENQUEUE", elem[0].name, elem[1]); + fs27[gracefulQueue].push(elem); + } + function retry() { + var elem = fs27[gracefulQueue].shift(); + if (elem) { + debug("RETRY", elem[0].name, elem[1]); + elem[0].apply(null, elem[1]); + } + } + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/fs/index.js +var require_fs = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/fs/index.js"(exports2) { + "use strict"; + var u = require_universalify().fromCallback; + var fs27 = require_graceful_fs(); + var 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) => { + return typeof fs27[key] === "function"; + }); + Object.keys(fs27).forEach((key) => { + if (key === "promises") { + return; + } + exports2[key] = fs27[key]; + }); + api.forEach((method) => { + exports2[method] = u(fs27[method]); + }); + exports2.exists = function(filename, callback) { + if (typeof callback === "function") { + return fs27.exists(filename, callback); + } + return new Promise((resolve3) => { + return fs27.exists(filename, resolve3); + }); + }; + exports2.read = function(fd, buffer, offset, length, position, callback) { + if (typeof callback === "function") { + return fs27.read(fd, buffer, offset, length, position, callback); + } + return new Promise((resolve3, reject) => { + fs27.read(fd, buffer, offset, length, position, (err, bytesRead, buffer2) => { + if (err) + return reject(err); + resolve3({ bytesRead, buffer: buffer2 }); + }); + }); + }; + exports2.write = function(fd, buffer, ...args) { + if (typeof args[args.length - 1] === "function") { + return fs27.write(fd, buffer, ...args); + } + return new Promise((resolve3, reject) => { + fs27.write(fd, buffer, ...args, (err, bytesWritten, buffer2) => { + if (err) + return reject(err); + resolve3({ bytesWritten, buffer: buffer2 }); + }); + }); + }; + if (typeof fs27.realpath.native === "function") { + exports2.realpath.native = u(fs27.realpath.native); + } + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/mkdirs/win32.js +var require_win32 = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/mkdirs/win32.js"(exports2, module2) { + "use strict"; + var path36 = require("path"); + function getRootPath(p) { + p = path36.normalize(path36.resolve(p)).split(path36.sep); + if (p.length > 0) + return p[0]; + return null; + } + var INVALID_PATH_CHARS = /[<>:"|?*]/; + function invalidWin32Path(p) { + const rp = getRootPath(p); + p = p.replace(rp, ""); + return INVALID_PATH_CHARS.test(p); + } + module2.exports = { + getRootPath, + invalidWin32Path + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/mkdirs/mkdirs.js +var require_mkdirs = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/mkdirs/mkdirs.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var invalidWin32Path = require_win32().invalidWin32Path; + var 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 || fs27; + if (mode === void 0) { + mode = o777 & ~process.umask(); + } + if (!made) + made = null; + callback = callback || function() { + }; + p = path36.resolve(p); + xfs.mkdir(p, mode, (er) => { + if (!er) { + made = made || p; + return callback(null, made); + } + switch (er.code) { + case "ENOENT": + if (path36.dirname(p) === p) + return callback(er); + mkdirs(path36.dirname(p), opts, (er2, made2) => { + if (er2) + callback(er2, made2); + else + mkdirs(p, opts, callback, made2); + }); + break; + default: + xfs.stat(p, (er2, stat) => { + if (er2 || !stat.isDirectory()) + callback(er, made); + else + callback(null, made); + }); + break; + } + }); + } + module2.exports = mkdirs; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/mkdirs/mkdirs-sync.js +var require_mkdirs_sync = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/mkdirs/mkdirs-sync.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var invalidWin32Path = require_win32().invalidWin32Path; + var 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 || fs27; + if (process.platform === "win32" && invalidWin32Path(p)) { + const errInval = new Error(p + " contains invalid WIN32 path characters."); + errInval.code = "EINVAL"; + throw errInval; + } + if (mode === void 0) { + mode = o777 & ~process.umask(); + } + if (!made) + made = null; + p = path36.resolve(p); + try { + xfs.mkdirSync(p, mode); + made = made || p; + } catch (err0) { + if (err0.code === "ENOENT") { + if (path36.dirname(p) === p) + throw err0; + made = mkdirsSync(path36.dirname(p), opts, made); + mkdirsSync(p, opts, made); + } else { + let stat; + try { + stat = xfs.statSync(p); + } catch (err1) { + throw err0; + } + if (!stat.isDirectory()) + throw err0; + } + } + return made; + } + module2.exports = mkdirsSync; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/mkdirs/index.js +var require_mkdirs2 = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/mkdirs/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var mkdirs = u(require_mkdirs()); + var mkdirsSync = require_mkdirs_sync(); + module2.exports = { + mkdirs, + mkdirsSync, + mkdirp: mkdirs, + mkdirpSync: mkdirsSync, + ensureDir: mkdirs, + ensureDirSync: mkdirsSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/util/utimes.js +var require_utimes = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/util/utimes.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var os10 = require("os"); + var path36 = require("path"); + function hasMillisResSync() { + let tmpfile = path36.join("millis-test-sync" + Date.now().toString() + Math.random().toString().slice(2)); + tmpfile = path36.join(os10.tmpdir(), tmpfile); + const d = new Date(1435410243862); + fs27.writeFileSync(tmpfile, "https://github.com/jprichardson/node-fs-extra/pull/141"); + const fd = fs27.openSync(tmpfile, "r+"); + fs27.futimesSync(fd, d, d); + fs27.closeSync(fd); + return fs27.statSync(tmpfile).mtime > 1435410243e3; + } + function hasMillisRes(callback) { + let tmpfile = path36.join("millis-test" + Date.now().toString() + Math.random().toString().slice(2)); + tmpfile = path36.join(os10.tmpdir(), tmpfile); + const d = new Date(1435410243862); + fs27.writeFile(tmpfile, "https://github.com/jprichardson/node-fs-extra/pull/141", (err) => { + if (err) + return callback(err); + fs27.open(tmpfile, "r+", (err2, fd) => { + if (err2) + return callback(err2); + fs27.futimes(fd, d, d, (err3) => { + if (err3) + return callback(err3); + fs27.close(fd, (err4) => { + if (err4) + return callback(err4); + fs27.stat(tmpfile, (err5, stats) => { + if (err5) + return callback(err5); + callback(null, stats.mtime > 1435410243e3); + }); + }); + }); + }); + }); + } + function timeRemoveMillis(timestamp) { + if (typeof timestamp === "number") { + return Math.floor(timestamp / 1e3) * 1e3; + } else if (timestamp instanceof Date) { + return new Date(Math.floor(timestamp.getTime() / 1e3) * 1e3); + } else { + throw new Error("fs-extra: timeRemoveMillis() unknown parameter type"); + } + } + function utimesMillis(path37, atime, mtime, callback) { + fs27.open(path37, "r+", (err, fd) => { + if (err) + return callback(err); + fs27.futimes(fd, atime, mtime, (futimesErr) => { + fs27.close(fd, (closeErr) => { + if (callback) + callback(futimesErr || closeErr); + }); + }); + }); + } + function utimesMillisSync(path37, atime, mtime) { + const fd = fs27.openSync(path37, "r+"); + fs27.futimesSync(fd, atime, mtime); + return fs27.closeSync(fd); + } + module2.exports = { + hasMillisRes, + hasMillisResSync, + timeRemoveMillis, + utimesMillis, + utimesMillisSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/util/stat.js +var require_stat = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/util/stat.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var NODE_VERSION_MAJOR_WITH_BIGINT = 10; + var NODE_VERSION_MINOR_WITH_BIGINT = 5; + var NODE_VERSION_PATCH_WITH_BIGINT = 0; + var nodeVersion = process.versions.node.split("."); + var nodeVersionMajor = Number.parseInt(nodeVersion[0], 10); + var nodeVersionMinor = Number.parseInt(nodeVersion[1], 10); + var 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()) { + fs27.stat(src, { bigint: true }, (err, srcStat) => { + if (err) + return cb(err); + fs27.stat(dest, { bigint: true }, (err2, destStat) => { + if (err2) { + if (err2.code === "ENOENT") + return cb(null, { srcStat, destStat: null }); + return cb(err2); + } + return cb(null, { srcStat, destStat }); + }); + }); + } else { + fs27.stat(src, (err, srcStat) => { + if (err) + return cb(err); + fs27.stat(dest, (err2, destStat) => { + if (err2) { + if (err2.code === "ENOENT") + return cb(null, { srcStat, destStat: null }); + return cb(err2); + } + return cb(null, { srcStat, destStat }); + }); + }); + } + } + function getStatsSync(src, dest) { + let srcStat, destStat; + if (nodeSupportsBigInt()) { + srcStat = fs27.statSync(src, { bigint: true }); + } else { + srcStat = fs27.statSync(src); + } + try { + if (nodeSupportsBigInt()) { + destStat = fs27.statSync(dest, { bigint: true }); + } else { + destStat = fs27.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 }; + } + function checkParentPaths(src, srcStat, dest, funcName, cb) { + const srcParent = path36.resolve(path36.dirname(src)); + const destParent = path36.resolve(path36.dirname(dest)); + if (destParent === srcParent || destParent === path36.parse(destParent).root) + return cb(); + if (nodeSupportsBigInt()) { + fs27.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 { + fs27.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 = path36.resolve(path36.dirname(src)); + const destParent = path36.resolve(path36.dirname(dest)); + if (destParent === srcParent || destParent === path36.parse(destParent).root) + return; + let destStat; + try { + if (nodeSupportsBigInt()) { + destStat = fs27.statSync(destParent, { bigint: true }); + } else { + destStat = fs27.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); + } + function isSrcSubdir(src, dest) { + const srcArr = path36.resolve(src).split(path36.sep).filter((i) => i); + const destArr = path36.resolve(dest).split(path36.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}'.`; + } + module2.exports = { + checkPaths, + checkPathsSync, + checkParentPaths, + checkParentPathsSync, + isSrcSubdir + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/util/buffer.js +var require_buffer = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/util/buffer.js"(exports2, module2) { + "use strict"; + module2.exports = function(size) { + if (typeof Buffer.allocUnsafe === "function") { + try { + return Buffer.allocUnsafe(size); + } catch (e) { + return new Buffer(size); + } + } + return new Buffer(size); + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/copy-sync/copy-sync.js +var require_copy_sync = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/copy-sync/copy-sync.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdirpSync = require_mkdirs2().mkdirsSync; + var utimesSync = require_utimes().utimesMillisSync; + var stat = require_stat(); + function copySync(src, dest, opts) { + if (typeof opts === "function") { + opts = { filter: opts }; + } + opts = opts || {}; + opts.clobber = "clobber" in opts ? !!opts.clobber : true; + opts.overwrite = "overwrite" in opts ? !!opts.overwrite : opts.clobber; + if (opts.preserveTimestamps && process.arch === "ia32") { + console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended; + + 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 = path36.dirname(dest); + if (!fs27.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 ? fs27.statSync : fs27.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) { + fs27.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 fs27.copyFileSync === "function") { + fs27.copyFileSync(src, dest); + fs27.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 = require_buffer()(BUF_LENGTH); + const fdr = fs27.openSync(src, "r"); + const fdw = fs27.openSync(dest, "w", srcStat.mode); + let pos = 0; + while (pos < srcStat.size) { + const bytesRead = fs27.readSync(fdr, _buff, 0, BUF_LENGTH, pos); + fs27.writeSync(fdw, _buff, 0, bytesRead); + pos += bytesRead; + } + if (opts.preserveTimestamps) + fs27.futimesSync(fdw, srcStat.atime, srcStat.mtime); + fs27.closeSync(fdr); + fs27.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) { + fs27.mkdirSync(dest); + copyDir(src, dest, opts); + return fs27.chmodSync(dest, srcStat.mode); + } + function copyDir(src, dest, opts) { + fs27.readdirSync(src).forEach((item) => copyDirItem(item, src, dest, opts)); + } + function copyDirItem(item, src, dest, opts) { + const srcItem = path36.join(src, item); + const destItem = path36.join(dest, item); + const { destStat } = stat.checkPathsSync(srcItem, destItem, "copy"); + return startCopy(destStat, srcItem, destItem, opts); + } + function onLink(destStat, src, dest, opts) { + let resolvedSrc = fs27.readlinkSync(src); + if (opts.dereference) { + resolvedSrc = path36.resolve(process.cwd(), resolvedSrc); + } + if (!destStat) { + return fs27.symlinkSync(resolvedSrc, dest); + } else { + let resolvedDest; + try { + resolvedDest = fs27.readlinkSync(dest); + } catch (err) { + if (err.code === "EINVAL" || err.code === "UNKNOWN") + return fs27.symlinkSync(resolvedSrc, dest); + throw err; + } + if (opts.dereference) { + resolvedDest = path36.resolve(process.cwd(), resolvedDest); + } + if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) { + throw new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`); + } + if (fs27.statSync(dest).isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) { + throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`); + } + return copyLink(resolvedSrc, dest); + } + } + function copyLink(resolvedSrc, dest) { + fs27.unlinkSync(dest); + return fs27.symlinkSync(resolvedSrc, dest); + } + module2.exports = copySync; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/copy-sync/index.js +var require_copy_sync2 = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/copy-sync/index.js"(exports2, module2) { + "use strict"; + module2.exports = { + copySync: require_copy_sync() + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/path-exists/index.js +var require_path_exists = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/path-exists/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromPromise; + var fs27 = require_fs(); + function pathExists(path36) { + return fs27.access(path36).then(() => true).catch(() => false); + } + module2.exports = { + pathExists: u(pathExists), + pathExistsSync: fs27.existsSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/copy/copy.js +var require_copy = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/copy/copy.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdirp = require_mkdirs2().mkdirs; + var pathExists = require_path_exists().pathExists; + var utimes = require_utimes().utimesMillis; + var stat = require_stat(); + 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; + opts.overwrite = "overwrite" in opts ? !!opts.overwrite : opts.clobber; + if (opts.preserveTimestamps && process.arch === "ia32") { + console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended; + + 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", (err2) => { + if (err2) + return cb(err2); + 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 = path36.dirname(dest); + pathExists(destParent, (err, dirExists) => { + if (err) + return cb(err); + if (dirExists) + return startCopy(destStat, src, dest, opts, cb); + mkdirp(destParent, (err2) => { + if (err2) + return cb(err2); + 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 stat2 = opts.dereference ? fs27.stat : fs27.lstat; + stat2(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) { + fs27.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 fs27.copyFile === "function") { + return fs27.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 = fs27.createReadStream(src); + rs.on("error", (err) => cb(err)).once("open", () => { + const ws = fs27.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) { + fs27.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) { + fs27.mkdir(dest, (err) => { + if (err) + return cb(err); + copyDir(src, dest, opts, (err2) => { + if (err2) + return cb(err2); + return fs27.chmod(dest, srcStat.mode, cb); + }); + }); + } + function copyDir(src, dest, opts, cb) { + fs27.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 = path36.join(src, item); + const destItem = path36.join(dest, item); + stat.checkPaths(srcItem, destItem, "copy", (err, stats) => { + if (err) + return cb(err); + const { destStat } = stats; + startCopy(destStat, srcItem, destItem, opts, (err2) => { + if (err2) + return cb(err2); + return copyDirItems(items, src, dest, opts, cb); + }); + }); + } + function onLink(destStat, src, dest, opts, cb) { + fs27.readlink(src, (err, resolvedSrc) => { + if (err) + return cb(err); + if (opts.dereference) { + resolvedSrc = path36.resolve(process.cwd(), resolvedSrc); + } + if (!destStat) { + return fs27.symlink(resolvedSrc, dest, cb); + } else { + fs27.readlink(dest, (err2, resolvedDest) => { + if (err2) { + if (err2.code === "EINVAL" || err2.code === "UNKNOWN") + return fs27.symlink(resolvedSrc, dest, cb); + return cb(err2); + } + if (opts.dereference) { + resolvedDest = path36.resolve(process.cwd(), resolvedDest); + } + if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) { + return cb(new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`)); + } + 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) { + fs27.unlink(dest, (err) => { + if (err) + return cb(err); + return fs27.symlink(resolvedSrc, dest, cb); + }); + } + module2.exports = copy; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/copy/index.js +var require_copy2 = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/copy/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + module2.exports = { + copy: u(require_copy()) + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/remove/rimraf.js +var require_rimraf = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/remove/rimraf.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var assert = require("assert"); + var isWindows4 = process.platform === "win32"; + function defaults2(options) { + const methods2 = [ + "unlink", + "chmod", + "stat", + "lstat", + "rmdir", + "readdir" + ]; + methods2.forEach((m) => { + options[m] = options[m] || fs27[m]; + m = m + "Sync"; + options[m] = options[m] || fs27[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"); + defaults2(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; + return setTimeout(() => rimraf_(p, options, CB), time); + } + if (er.code === "ENOENT") + er = null; + } + cb(er); + }); + } + function rimraf_(p, options, cb) { + assert(p); + assert(options); + assert(typeof cb === "function"); + options.lstat(p, (er, st) => { + if (er && er.code === "ENOENT") { + return cb(null); + } + if (er && er.code === "EPERM" && isWindows4) { + return fixWinEPERM(p, options, er, cb); + } + if (st && st.isDirectory()) { + return rmdir(p, options, er, cb); + } + options.unlink(p, (er2) => { + if (er2) { + if (er2.code === "ENOENT") { + return cb(null); + } + if (er2.code === "EPERM") { + return isWindows4 ? fixWinEPERM(p, options, er2, cb) : rmdir(p, options, er2, cb); + } + if (er2.code === "EISDIR") { + return rmdir(p, options, er2, cb); + } + } + return cb(er2); + }); + }); + } + function fixWinEPERM(p, options, er, cb) { + assert(p); + assert(options); + assert(typeof cb === "function"); + if (er) { + assert(er instanceof Error); + } + options.chmod(p, 438, (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, 438); + } 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"); + 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(path36.join(p, f), options, (er2) => { + if (errState) { + return; + } + if (er2) + return cb(errState = er2); + if (--n === 0) { + options.rmdir(p, cb); + } + }); + }); + }); + } + function rimrafSync(p, options) { + let st; + options = options || {}; + defaults2(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; + } + if (er.code === "EPERM" && isWindows4) { + fixWinEPERMSync(p, options, er); + } + } + try { + 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 isWindows4 ? 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(path36.join(p, f), options)); + if (isWindows4) { + const startTime = Date.now(); + do { + try { + const ret = options.rmdirSync(p, options); + return ret; + } catch (er) { + } + } while (Date.now() - startTime < 500); + } else { + const ret = options.rmdirSync(p, options); + return ret; + } + } + module2.exports = rimraf; + rimraf.sync = rimrafSync; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/remove/index.js +var require_remove = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/remove/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var rimraf = require_rimraf(); + module2.exports = { + remove: u(rimraf), + removeSync: rimraf.sync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/empty/index.js +var require_empty = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/empty/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdir = require_mkdirs2(); + var remove = require_remove(); + var emptyDir = u(function emptyDir2(dir, callback) { + callback = callback || function() { + }; + fs27.readdir(dir, (err, items) => { + if (err) + return mkdir.mkdirs(dir, callback); + items = items.map((item) => path36.join(dir, item)); + deleteItem(); + function deleteItem() { + const item = items.pop(); + if (!item) + return callback(); + remove.remove(item, (err2) => { + if (err2) + return callback(err2); + deleteItem(); + }); + } + }); + }); + function emptyDirSync(dir) { + let items; + try { + items = fs27.readdirSync(dir); + } catch (err) { + return mkdir.mkdirsSync(dir); + } + items.forEach((item) => { + item = path36.join(dir, item); + remove.removeSync(item); + }); + } + module2.exports = { + emptyDirSync, + emptydirSync: emptyDirSync, + emptyDir, + emptydir: emptyDir + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/ensure/file.js +var require_file = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/ensure/file.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var path36 = require("path"); + var fs27 = require_graceful_fs(); + var mkdir = require_mkdirs2(); + var pathExists = require_path_exists().pathExists; + function createFile(file, callback) { + function makeFile() { + fs27.writeFile(file, "", (err) => { + if (err) + return callback(err); + callback(); + }); + } + fs27.stat(file, (err, stats) => { + if (!err && stats.isFile()) + return callback(); + const dir = path36.dirname(file); + pathExists(dir, (err2, dirExists) => { + if (err2) + return callback(err2); + if (dirExists) + return makeFile(); + mkdir.mkdirs(dir, (err3) => { + if (err3) + return callback(err3); + makeFile(); + }); + }); + }); + } + function createFileSync(file) { + let stats; + try { + stats = fs27.statSync(file); + } catch (e) { + } + if (stats && stats.isFile()) + return; + const dir = path36.dirname(file); + if (!fs27.existsSync(dir)) { + mkdir.mkdirsSync(dir); + } + fs27.writeFileSync(file, ""); + } + module2.exports = { + createFile: u(createFile), + createFileSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/ensure/link.js +var require_link = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/ensure/link.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var path36 = require("path"); + var fs27 = require_graceful_fs(); + var mkdir = require_mkdirs2(); + var pathExists = require_path_exists().pathExists; + function createLink(srcpath, dstpath, callback) { + function makeLink(srcpath2, dstpath2) { + fs27.link(srcpath2, dstpath2, (err) => { + if (err) + return callback(err); + callback(null); + }); + } + pathExists(dstpath, (err, destinationExists) => { + if (err) + return callback(err); + if (destinationExists) + return callback(null); + fs27.lstat(srcpath, (err2) => { + if (err2) { + err2.message = err2.message.replace("lstat", "ensureLink"); + return callback(err2); + } + const dir = path36.dirname(dstpath); + pathExists(dir, (err3, dirExists) => { + if (err3) + return callback(err3); + if (dirExists) + return makeLink(srcpath, dstpath); + mkdir.mkdirs(dir, (err4) => { + if (err4) + return callback(err4); + makeLink(srcpath, dstpath); + }); + }); + }); + }); + } + function createLinkSync(srcpath, dstpath) { + const destinationExists = fs27.existsSync(dstpath); + if (destinationExists) + return void 0; + try { + fs27.lstatSync(srcpath); + } catch (err) { + err.message = err.message.replace("lstat", "ensureLink"); + throw err; + } + const dir = path36.dirname(dstpath); + const dirExists = fs27.existsSync(dir); + if (dirExists) + return fs27.linkSync(srcpath, dstpath); + mkdir.mkdirsSync(dir); + return fs27.linkSync(srcpath, dstpath); + } + module2.exports = { + createLink: u(createLink), + createLinkSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/ensure/symlink-paths.js +var require_symlink_paths = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/ensure/symlink-paths.js"(exports2, module2) { + "use strict"; + var path36 = require("path"); + var fs27 = require_graceful_fs(); + var pathExists = require_path_exists().pathExists; + function symlinkPaths(srcpath, dstpath, callback) { + if (path36.isAbsolute(srcpath)) { + return fs27.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 = path36.dirname(dstpath); + const relativeToDst = path36.join(dstdir, srcpath); + return pathExists(relativeToDst, (err, exists) => { + if (err) + return callback(err); + if (exists) { + return callback(null, { + "toCwd": relativeToDst, + "toDst": srcpath + }); + } else { + return fs27.lstat(srcpath, (err2) => { + if (err2) { + err2.message = err2.message.replace("lstat", "ensureSymlink"); + return callback(err2); + } + return callback(null, { + "toCwd": srcpath, + "toDst": path36.relative(dstdir, srcpath) + }); + }); + } + }); + } + } + function symlinkPathsSync(srcpath, dstpath) { + let exists; + if (path36.isAbsolute(srcpath)) { + exists = fs27.existsSync(srcpath); + if (!exists) + throw new Error("absolute srcpath does not exist"); + return { + "toCwd": srcpath, + "toDst": srcpath + }; + } else { + const dstdir = path36.dirname(dstpath); + const relativeToDst = path36.join(dstdir, srcpath); + exists = fs27.existsSync(relativeToDst); + if (exists) { + return { + "toCwd": relativeToDst, + "toDst": srcpath + }; + } else { + exists = fs27.existsSync(srcpath); + if (!exists) + throw new Error("relative srcpath does not exist"); + return { + "toCwd": srcpath, + "toDst": path36.relative(dstdir, srcpath) + }; + } + } + } + module2.exports = { + symlinkPaths, + symlinkPathsSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/ensure/symlink-type.js +var require_symlink_type = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/ensure/symlink-type.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + function symlinkType(srcpath, type, callback) { + callback = typeof type === "function" ? type : callback; + type = typeof type === "function" ? false : type; + if (type) + return callback(null, type); + fs27.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 = fs27.lstatSync(srcpath); + } catch (e) { + return "file"; + } + return stats && stats.isDirectory() ? "dir" : "file"; + } + module2.exports = { + symlinkType, + symlinkTypeSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/ensure/symlink.js +var require_symlink = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/ensure/symlink.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var path36 = require("path"); + var fs27 = require_graceful_fs(); + var _mkdirs = require_mkdirs2(); + var mkdirs = _mkdirs.mkdirs; + var mkdirsSync = _mkdirs.mkdirsSync; + var _symlinkPaths = require_symlink_paths(); + var symlinkPaths = _symlinkPaths.symlinkPaths; + var symlinkPathsSync = _symlinkPaths.symlinkPathsSync; + var _symlinkType = require_symlink_type(); + var symlinkType = _symlinkType.symlinkType; + var symlinkTypeSync = _symlinkType.symlinkTypeSync; + var pathExists = require_path_exists().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, (err2, relative) => { + if (err2) + return callback(err2); + srcpath = relative.toDst; + symlinkType(relative.toCwd, type, (err3, type2) => { + if (err3) + return callback(err3); + const dir = path36.dirname(dstpath); + pathExists(dir, (err4, dirExists) => { + if (err4) + return callback(err4); + if (dirExists) + return fs27.symlink(srcpath, dstpath, type2, callback); + mkdirs(dir, (err5) => { + if (err5) + return callback(err5); + fs27.symlink(srcpath, dstpath, type2, callback); + }); + }); + }); + }); + }); + } + function createSymlinkSync(srcpath, dstpath, type) { + const destinationExists = fs27.existsSync(dstpath); + if (destinationExists) + return void 0; + const relative = symlinkPathsSync(srcpath, dstpath); + srcpath = relative.toDst; + type = symlinkTypeSync(relative.toCwd, type); + const dir = path36.dirname(dstpath); + const exists = fs27.existsSync(dir); + if (exists) + return fs27.symlinkSync(srcpath, dstpath, type); + mkdirsSync(dir); + return fs27.symlinkSync(srcpath, dstpath, type); + } + module2.exports = { + createSymlink: u(createSymlink), + createSymlinkSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/ensure/index.js +var require_ensure = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/ensure/index.js"(exports2, module2) { + "use strict"; + var file = require_file(); + var link = require_link(); + var symlink = require_symlink(); + module2.exports = { + createFile: file.createFile, + createFileSync: file.createFileSync, + ensureFile: file.createFile, + ensureFileSync: file.createFileSync, + createLink: link.createLink, + createLinkSync: link.createLinkSync, + ensureLink: link.createLink, + ensureLinkSync: link.createLinkSync, + createSymlink: symlink.createSymlink, + createSymlinkSync: symlink.createSymlinkSync, + ensureSymlink: symlink.createSymlink, + ensureSymlinkSync: symlink.createSymlinkSync + }; + } +}); + +// node_modules/streamroller/node_modules/jsonfile/index.js +var require_jsonfile = __commonJS({ + "node_modules/streamroller/node_modules/jsonfile/index.js"(exports2, module2) { + var _fs; + try { + _fs = require_graceful_fs(); + } catch (_) { + _fs = require("fs"); + } + function readFile2(file, options, callback) { + if (callback == null) { + callback = options; + options = {}; + } + if (typeof options === "string") { + options = { encoding: options }; + } + options = options || {}; + var fs27 = options.fs || _fs; + var shouldThrow = true; + if ("throws" in options) { + shouldThrow = options.throws; + } + fs27.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 fs27 = options.fs || _fs; + var shouldThrow = true; + if ("throws" in options) { + shouldThrow = options.throws; + } + try { + var content = fs27.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 stringify3(obj, options) { + var spaces; + var EOL2 = "\n"; + if (typeof options === "object" && options !== null) { + if (options.spaces) { + spaces = options.spaces; + } + if (options.EOL) { + EOL2 = options.EOL; + } + } + var str = JSON.stringify(obj, options ? options.replacer : null, spaces); + return str.replace(/\n/g, EOL2) + EOL2; + } + function writeFile2(file, obj, options, callback) { + if (callback == null) { + callback = options; + options = {}; + } + options = options || {}; + var fs27 = options.fs || _fs; + var str = ""; + try { + str = stringify3(obj, options); + } catch (err) { + if (callback) + callback(err, null); + return; + } + fs27.writeFile(file, str, options, callback); + } + function writeFileSync(file, obj, options) { + options = options || {}; + var fs27 = options.fs || _fs; + var str = stringify3(obj, options); + return fs27.writeFileSync(file, str, options); + } + function stripBom(content) { + if (Buffer.isBuffer(content)) + content = content.toString("utf8"); + content = content.replace(/^\uFEFF/, ""); + return content; + } + var jsonfile = { + readFile: readFile2, + readFileSync, + writeFile: writeFile2, + writeFileSync + }; + module2.exports = jsonfile; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/json/jsonfile.js +var require_jsonfile2 = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/json/jsonfile.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var jsonFile = require_jsonfile(); + module2.exports = { + readJson: u(jsonFile.readFile), + readJsonSync: jsonFile.readFileSync, + writeJson: u(jsonFile.writeFile), + writeJsonSync: jsonFile.writeFileSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/json/output-json.js +var require_output_json = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/json/output-json.js"(exports2, module2) { + "use strict"; + var path36 = require("path"); + var mkdir = require_mkdirs2(); + var pathExists = require_path_exists().pathExists; + var jsonFile = require_jsonfile2(); + function outputJson(file, data, options, callback) { + if (typeof options === "function") { + callback = options; + options = {}; + } + const dir = path36.dirname(file); + pathExists(dir, (err, itDoes) => { + if (err) + return callback(err); + if (itDoes) + return jsonFile.writeJson(file, data, options, callback); + mkdir.mkdirs(dir, (err2) => { + if (err2) + return callback(err2); + jsonFile.writeJson(file, data, options, callback); + }); + }); + } + module2.exports = outputJson; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/json/output-json-sync.js +var require_output_json_sync = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/json/output-json-sync.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdir = require_mkdirs2(); + var jsonFile = require_jsonfile2(); + function outputJsonSync(file, data, options) { + const dir = path36.dirname(file); + if (!fs27.existsSync(dir)) { + mkdir.mkdirsSync(dir); + } + jsonFile.writeJsonSync(file, data, options); + } + module2.exports = outputJsonSync; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/json/index.js +var require_json = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/json/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var jsonFile = require_jsonfile2(); + jsonFile.outputJson = u(require_output_json()); + jsonFile.outputJsonSync = require_output_json_sync(); + jsonFile.outputJSON = jsonFile.outputJson; + jsonFile.outputJSONSync = jsonFile.outputJsonSync; + jsonFile.writeJSON = jsonFile.writeJson; + jsonFile.writeJSONSync = jsonFile.writeJsonSync; + jsonFile.readJSON = jsonFile.readJson; + jsonFile.readJSONSync = jsonFile.readJsonSync; + module2.exports = jsonFile; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/move-sync/move-sync.js +var require_move_sync = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/move-sync/move-sync.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var copySync = require_copy_sync2().copySync; + var removeSync = require_remove().removeSync; + var mkdirpSync = require_mkdirs2().mkdirpSync; + var stat = require_stat(); + 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(path36.dirname(dest)); + return doRename(src, dest, overwrite); + } + function doRename(src, dest, overwrite) { + if (overwrite) { + removeSync(dest); + return rename(src, dest, overwrite); + } + if (fs27.existsSync(dest)) + throw new Error("dest already exists."); + return rename(src, dest, overwrite); + } + function rename(src, dest, overwrite) { + try { + fs27.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); + } + module2.exports = moveSync; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/move-sync/index.js +var require_move_sync2 = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/move-sync/index.js"(exports2, module2) { + "use strict"; + module2.exports = { + moveSync: require_move_sync() + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/move/move.js +var require_move = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/move/move.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var copy = require_copy2().copy; + var remove = require_remove().remove; + var mkdirp = require_mkdirs2().mkdirp; + var pathExists = require_path_exists().pathExists; + var stat = require_stat(); + 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", (err2) => { + if (err2) + return cb(err2); + mkdirp(path36.dirname(dest), (err3) => { + if (err3) + return cb(err3); + 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) { + fs27.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); + }); + } + module2.exports = move; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/move/index.js +var require_move2 = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/move/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + module2.exports = { + move: u(require_move()) + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/output/index.js +var require_output = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/output/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify().fromCallback; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdir = require_mkdirs2(); + var pathExists = require_path_exists().pathExists; + function outputFile(file, data, encoding, callback) { + if (typeof encoding === "function") { + callback = encoding; + encoding = "utf8"; + } + const dir = path36.dirname(file); + pathExists(dir, (err, itDoes) => { + if (err) + return callback(err); + if (itDoes) + return fs27.writeFile(file, data, encoding, callback); + mkdir.mkdirs(dir, (err2) => { + if (err2) + return callback(err2); + fs27.writeFile(file, data, encoding, callback); + }); + }); + } + function outputFileSync(file, ...args) { + const dir = path36.dirname(file); + if (fs27.existsSync(dir)) { + return fs27.writeFileSync(file, ...args); + } + mkdir.mkdirsSync(dir); + fs27.writeFileSync(file, ...args); + } + module2.exports = { + outputFile: u(outputFile), + outputFileSync + }; + } +}); + +// node_modules/streamroller/node_modules/fs-extra/lib/index.js +var require_lib2 = __commonJS({ + "node_modules/streamroller/node_modules/fs-extra/lib/index.js"(exports2, module2) { + "use strict"; + module2.exports = Object.assign({}, require_fs(), require_copy_sync2(), require_copy2(), require_empty(), require_ensure(), require_json(), require_mkdirs2(), require_move_sync2(), require_move2(), require_output(), require_path_exists(), require_remove()); + var fs27 = require("fs"); + if (Object.getOwnPropertyDescriptor(fs27, "promises")) { + Object.defineProperty(module2.exports, "promises", { + get() { + return fs27.promises; + } + }); + } + } +}); + +// node_modules/streamroller/lib/now.js +var require_now = __commonJS({ + "node_modules/streamroller/lib/now.js"(exports2, module2) { + module2.exports = () => new Date(); + } +}); + +// node_modules/streamroller/node_modules/date-format/lib/index.js +var require_lib3 = __commonJS({ + "node_modules/streamroller/node_modules/date-format/lib/index.js"(exports2, module2) { + "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); + } + function offset(timezoneOffset) { + var os10 = Math.abs(timezoneOffset); + var h = String(Math.floor(os10 / 60)); + var m = String(os10 % 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(format2, date) { + if (typeof format2 !== "string") { + date = format2; + format2 = module2.exports.ISO8601_FORMAT; + } + if (!date) { + date = module2.exports.now(); + } + var displayUTC = format2.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 = format2.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 = format2.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(date2, value) { + date2.setFullYear(value); + } + }, + { + pattern: /MM/, + regexp: "\\d{1,2}", + fn: function(date2, value) { + date2.setMonth(value - 1); + } + }, + { + pattern: /dd/, + regexp: "\\d{1,2}", + fn: function(date2, value) { + date2.setDate(value); + } + }, + { + pattern: /hh/, + regexp: "\\d{1,2}", + fn: function(date2, value) { + date2.setHours(value); + } + }, + { + pattern: /mm/, + regexp: "\\d\\d", + fn: function(date2, value) { + date2.setMinutes(value); + } + }, + { + pattern: /ss/, + regexp: "\\d\\d", + fn: function(date2, value) { + date2.setSeconds(value); + } + }, + { + pattern: /SSS/, + regexp: "\\d\\d\\d", + fn: function(date2, value) { + date2.setMilliseconds(value); + } + }, + { + pattern: /O/, + regexp: "[+-]\\d{3,4}|Z", + fn: function(date2, value) { + if (value === "Z") { + value = 0; + } + var offset2 = Math.abs(value); + var minutes = offset2 % 100 + Math.floor(offset2 / 100) * 60; + date2.setMinutes(date2.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 || module2.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 parse5(pattern, str, missingValuesDate) { + if (!pattern) { + throw new Error("pattern must be supplied"); + } + return extractDateParts(pattern, str, missingValuesDate); + } + function now() { + return new Date(); + } + module2.exports = asString; + module2.exports.asString = asString; + module2.exports.parse = parse5; + module2.exports.now = now; + module2.exports.ISO8601_FORMAT = "yyyy-MM-ddThh:mm:ss.SSS"; + module2.exports.ISO8601_WITH_TZ_OFFSET_FORMAT = "yyyy-MM-ddThh:mm:ss.SSSO"; + module2.exports.DATETIME_FORMAT = "dd MM yyyy hh:mm:ss.SSS"; + module2.exports.ABSOLUTETIME_FORMAT = "hh:mm:ss.SSS"; + } +}); + +// node_modules/streamroller/lib/fileNameFormatter.js +var require_fileNameFormatter = __commonJS({ + "node_modules/streamroller/lib/fileNameFormatter.js"(exports2, module2) { + var debug = require_src()("streamroller:fileNameFormatter"); + var path36 = require("path"); + var FILENAME_SEP = "."; + var ZIP_EXT = ".gz"; + module2.exports = ({ + file, + keepFileExt, + needsIndex, + alwaysIncludeDate, + compress + }) => { + const dirAndName = path36.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: date2, index: index2 }) => { + debug(`_formatFileName: date=${date2}, index=${index2}`); + return parts.reduce((filename, part) => part(filename, index2, date2), dirAndName); + }; + }; + } +}); + +// node_modules/streamroller/lib/fileNameParser.js +var require_fileNameParser = __commonJS({ + "node_modules/streamroller/lib/fileNameParser.js"(exports2, module2) { + var debug = require_src()("streamroller:fileNameParser"); + var FILENAME_SEP = "."; + var ZIP_EXT = ".gz"; + var format2 = require_lib3(); + module2.exports = ({ file, keepFileExt, pattern }) => { + 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 __NOT_MATCHING__ = "__NOT_MATCHING__"; + 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 __NOT_MATCHING__; + }; + const extInMiddle = (f) => { + if (f.startsWith(file.base)) { + debug("it starts with the right things"); + return f.slice(file.base.length + 1); + } + return __NOT_MATCHING__; + }; + 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 !== void 0 && indexStr.match(/^\d+$/)) { + dateStr = f.slice(0, -1 * (indexStr.length + 1)); + debug(`dateStr is ${dateStr}`); + if (pattern && !dateStr) { + dateStr = indexStr; + indexStr = "0"; + } + } else { + indexStr = "0"; + } + try { + const date = format2.parse(pattern, dateStr, new Date(0, 0)); + if (format2.asString(pattern, date) !== dateStr) + return f; + p.index = parseInt(indexStr, 10); + p.date = dateStr; + p.timestamp = date.getTime(); + return ""; + } catch (e) { + 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 }; + let whatsLeftOver = parts.reduce((remains, part) => part(remains, result), filename); + return whatsLeftOver ? null : result; + }; + }; + } +}); + +// node_modules/streamroller/lib/moveAndMaybeCompressFile.js +var require_moveAndMaybeCompressFile = __commonJS({ + "node_modules/streamroller/lib/moveAndMaybeCompressFile.js"(exports2, module2) { + var debug = require_src()("streamroller:moveAndMaybeCompressFile"); + var fs27 = require_lib2(); + var zlib = require("zlib"); + var moveAndMaybeCompressFile = async (sourceFilePath, targetFilePath, needCompress) => { + if (sourceFilePath === targetFilePath) { + debug(`moveAndMaybeCompressFile: source and target are the same, not doing anything`); + return; + } + if (await fs27.pathExists(sourceFilePath)) { + debug(`moveAndMaybeCompressFile: moving file from ${sourceFilePath} to ${targetFilePath} ${needCompress ? "with" : "without"} compress`); + if (needCompress) { + await new Promise((resolve3, reject) => { + fs27.createReadStream(sourceFilePath).pipe(zlib.createGzip()).pipe(fs27.createWriteStream(targetFilePath)).on("finish", () => { + debug(`moveAndMaybeCompressFile: finished compressing ${targetFilePath}, deleting ${sourceFilePath}`); + fs27.unlink(sourceFilePath).then(resolve3).catch(() => { + debug(`Deleting ${sourceFilePath} failed, truncating instead`); + fs27.truncate(sourceFilePath).then(resolve3).catch(reject); + }); + }); + }); + } else { + debug(`moveAndMaybeCompressFile: deleting file=${targetFilePath}, renaming ${sourceFilePath} to ${targetFilePath}`); + try { + await fs27.move(sourceFilePath, targetFilePath, { overwrite: true }); + } catch (e) { + debug(`moveAndMaybeCompressFile: error moving ${sourceFilePath} to ${targetFilePath}`, e); + debug(`Trying copy+truncate instead`); + await fs27.copy(sourceFilePath, targetFilePath, { overwrite: true }); + await fs27.truncate(sourceFilePath); + } + } + } + }; + module2.exports = moveAndMaybeCompressFile; + } +}); + +// node_modules/streamroller/lib/RollingFileWriteStream.js +var require_RollingFileWriteStream = __commonJS({ + "node_modules/streamroller/lib/RollingFileWriteStream.js"(exports2, module2) { + var debug = require_src()("streamroller:RollingFileWriteStream"); + var fs27 = require_lib2(); + var path36 = require("path"); + var newNow = require_now(); + var format2 = require_lib3(); + var { Writable } = require("stream"); + var fileNameFormatter = require_fileNameFormatter(); + var fileNameParser = require_fileNameParser(); + var moveAndMaybeCompressFile = require_moveAndMaybeCompressFile(); + var RollingFileWriteStream = class extends Writable { + constructor(filePath, options) { + debug(`constructor: creating RollingFileWriteStream. path=${filePath}`); + super(options); + this.options = this._parseOption(options); + this.fileObject = path36.parse(filePath); + if (this.fileObject.dir === "") { + this.fileObject = path36.parse(path36.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 = format2(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 = fs27.statSync(this.filename); + this.state.currentSize = stats.size; + if (this.options.pattern) { + this.state.currentDate = format2(this.options.pattern, stats.mtime); + } + } catch (e) { + return; + } + } + _parseOption(rawOptions) { + const defaultOptions2 = { + 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({}, defaultOptions2, 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 !== format2(this.options.pattern, newNow()); + } + _tooBig() { + return this.state.currentSize >= this.options.maxSize; + } + _roll() { + debug(`_roll: closing the current stream`); + return new Promise((resolve3, reject) => { + this.currentFileStream.end("", this.options.encoding, () => { + this._moveOldFiles().then(resolve3).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 ? format2(this.options.pattern, newNow()) : null; + debug(`_moveOldFiles: finished rolling files. state=${JSON.stringify(this.state)}`); + this._renewWriteStream(); + await new Promise((resolve3, reject) => { + this.currentFileStream.write("", "utf8", () => { + this._clean().then(resolve3).catch(reject); + }); + }); + } + async _getExistingFiles() { + const files = await fs27.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() { + fs27.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 = fs27.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.slice(0, existingFileDetails.length - this.options.numToKeep - 1).map((f) => path36.format({ dir: this.fileObject.dir, base: f.filename })); + await deleteFiles(fileNamesToRemove); + } + } + _tooManyFiles(numFiles) { + return this.options.numToKeep > 0 && numFiles > this.options.numToKeep; + } + }; + var deleteFiles = (fileNames) => { + debug(`deleteFiles: files to delete: ${fileNames}`); + return Promise.all(fileNames.map((f) => fs27.unlink(f).catch((e) => { + debug(`deleteFiles: error when unlinking ${f}, ignoring. Error was ${e}`); + }))); + }; + module2.exports = RollingFileWriteStream; + } +}); + +// node_modules/streamroller/lib/RollingFileStream.js +var require_RollingFileStream = __commonJS({ + "node_modules/streamroller/lib/RollingFileStream.js"(exports2, module2) { + var RollingFileWriteStream = require_RollingFileWriteStream(); + var RollingFileStream = class 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; + } + }; + module2.exports = RollingFileStream; + } +}); + +// node_modules/streamroller/lib/DateRollingFileStream.js +var require_DateRollingFileStream = __commonJS({ + "node_modules/streamroller/lib/DateRollingFileStream.js"(exports2, module2) { + var RollingFileWriteStream = require_RollingFileWriteStream(); + var DateRollingFileStream = class 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; + } + }; + module2.exports = DateRollingFileStream; + } +}); + +// node_modules/streamroller/lib/index.js +var require_lib4 = __commonJS({ + "node_modules/streamroller/lib/index.js"(exports2, module2) { + module2.exports = { + RollingFileWriteStream: require_RollingFileWriteStream(), + RollingFileStream: require_RollingFileStream(), + DateRollingFileStream: require_DateRollingFileStream() + }; + } +}); + +// node_modules/log4js/lib/appenders/file.js +var require_file2 = __commonJS({ + "node_modules/log4js/lib/appenders/file.js"(exports2, module2) { + var debug = require_src()("log4js:file"); + var path36 = require("path"); + var streams = require_lib4(); + var os10 = require("os"); + var eol = os10.EOL; + 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); + }); + stream.on("drain", () => { + process.emit("log4js:pause", false); + }); + return stream; + } + function fileAppender(file, layout, logSize, numBackups, options, timezoneOffset) { + file = path36.normalize(file); + numBackups = numBackups === void 0 ? 5 : numBackups; + 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) { + if (options.removeColor === true) { + const regex = /\x1b[[0-9;]*m/g; + loggingEvent.data = loggingEvent.data.map((d) => { + if (typeof d === "string") + return d.replace(regex, ""); + return d; + }); + } + if (!writer.write(layout(loggingEvent, timezoneOffset) + eol, "utf8")) { + process.emit("log4js:pause", true); + } + }; + 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); + }; + 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); + } + module2.exports.configure = configure; + } +}); + +// node_modules/log4js/lib/appenders/dateFile.js +var require_dateFile = __commonJS({ + "node_modules/log4js/lib/appenders/dateFile.js"(exports2, module2) { + var streams = require_lib4(); + var os10 = require("os"); + var eol = os10.EOL; + function appender(filename, pattern, layout, options, timezoneOffset) { + options.maxSize = options.maxLogSize; + const logFile = new streams.DateRollingFileStream(filename, pattern, options); + logFile.on("drain", () => { + process.emit("log4js:pause", false); + }); + const app = function(logEvent) { + if (!logFile.write(layout(logEvent, timezoneOffset) + eol, "utf8")) { + process.emit("log4js:pause", true); + } + }; + 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); + } + module2.exports.configure = configure; + } +}); + +// node_modules/log4js/lib/appenders/fileSync.js +var require_fileSync = __commonJS({ + "node_modules/log4js/lib/appenders/fileSync.js"(exports2, module2) { + var debug = require_src()("log4js:fileSync"); + var path36 = require("path"); + var fs27 = require("fs"); + var os10 = require("os"); + var eol = os10.EOL || "\n"; + function touchFile(file, options) { + if (fs27.existsSync(file)) { + return; + } + const id = fs27.openSync(file, options.flags, options.mode); + fs27.closeSync(id); + } + var RollingFileSync = class { + constructor(filename, size, backups, options) { + debug("In RollingFileStream"); + function throwErrorIfArgumentsAreNotValid() { + if (!filename || !size || size <= 0) { + throw new Error("You must specify a filename and file size"); + } + } + throwErrorIfArgumentsAreNotValid(); + this.filename = filename; + this.size = size; + this.backups = backups || 1; + this.options = options; + this.currentSize = 0; + function currentFileSize(file) { + let fileSize = 0; + try { + fileSize = fs27.statSync(file).size; + } catch (e) { + touchFile(file, options); + } + return fileSize; + } + this.currentSize = currentFileSize(this.filename); + } + shouldRoll() { + debug("should roll with current size %d, and max size %d", this.currentSize, this.size); + return this.currentSize >= this.size; + } + roll(filename) { + const that = this; + const nameMatcher = new RegExp(`^${path36.basename(filename)}`); + function justTheseFiles(item) { + return nameMatcher.test(item); + } + function index(filename_) { + return parseInt(filename_.substring(`${path36.basename(filename)}.`.length), 10) || 0; + } + function byIndex(a, b) { + if (index(a) > index(b)) { + return 1; + } + if (index(a) < index(b)) { + return -1; + } + return 0; + } + function increaseFileIndex(fileToRename) { + const idx = index(fileToRename); + debug(`Index of ${fileToRename} is ${idx}`); + if (idx < that.backups) { + try { + fs27.unlinkSync(`${filename}.${idx + 1}`); + } catch (e) { + } + debug(`Renaming ${fileToRename} -> ${filename}.${idx + 1}`); + fs27.renameSync(path36.join(path36.dirname(filename), fileToRename), `${filename}.${idx + 1}`); + } + } + function renameTheFiles() { + debug("Renaming the old files"); + const files = fs27.readdirSync(path36.dirname(filename)); + files.filter(justTheseFiles).sort(byIndex).reverse().forEach(increaseFileIndex); + } + debug("Rolling, rolling, rolling"); + renameTheFiles(); + } + write(chunk, encoding) { + const that = this; + function writeTheChunk() { + debug("writing the chunk to the file"); + that.currentSize += chunk.length; + fs27.appendFileSync(that.filename, chunk); + } + debug("in write"); + if (this.shouldRoll()) { + this.currentSize = 0; + this.roll(this.filename); + } + writeTheChunk(); + } + }; + function fileAppender(file, layout, logSize, numBackups, timezoneOffset, options) { + debug("fileSync appender created"); + file = path36.normalize(file); + numBackups = numBackups === void 0 ? 5 : numBackups; + numBackups = numBackups === 0 ? 1 : numBackups; + function openTheStream(filePath, fileSize, numFiles) { + let stream; + if (fileSize) { + stream = new RollingFileSync(filePath, fileSize, numFiles, options); + } else { + stream = ((f) => { + touchFile(f, options); + return { + write(data) { + fs27.appendFileSync(f, data); + } + }; + })(filePath); + } + return stream; + } + const logFile = openTheStream(file, logSize, numBackups); + return (loggingEvent) => { + logFile.write(layout(loggingEvent, timezoneOffset) + eol); + }; + } + function configure(config, layouts) { + let layout = layouts.basicLayout; + if (config.layout) { + layout = layouts.layout(config.layout.type, config.layout); + } + const options = { + flags: config.flags || "a", + encoding: config.encoding || "utf8", + mode: config.mode || 420 + }; + return fileAppender(config.filename, layout, config.maxLogSize, config.backups, config.timezoneOffset, options); + } + module2.exports.configure = configure; + } +}); + +// env-ns:node_modules/log4js/lib/appenders +var require_appenders = __commonJS({ + "env-ns:node_modules/log4js/lib/appenders"(exports2, module2) { + var path36 = require("path"); + var debug = require_src()("log4js:appenders"); + var configuration = require_configuration(); + var clustering = require_clustering(); + var levels = require_levels(); + var layouts = require_layouts(); + var adapters = require_adapters(); + var coreAppenders = new Map(); + coreAppenders.set("console", require_console()); + coreAppenders.set("stdout", require_stdout()); + coreAppenders.set("stderr", require_stderr()); + coreAppenders.set("logLevelFilter", require_logLevelFilter()); + coreAppenders.set("categoryFilter", require_categoryFilter()); + coreAppenders.set("noLogFilter", require_noLogFilter()); + coreAppenders.set("file", require_file2()); + coreAppenders.set("dateFile", require_dateFile()); + coreAppenders.set("fileSync", require_fileSync()); + var appenders = new Map(); + var tryLoading = (modulePath, config) => { + debug("Loading module from ", modulePath); + try { + return require(modulePath); + } catch (e) { + configuration.throwExceptionIf(config, e.code !== "MODULE_NOT_FOUND", `appender "${modulePath}" could not be loaded (error was: ${e})`); + return void 0; + } + }; + var loadAppenderModule = (type, config) => coreAppenders.get(type) || tryLoading(`./${type}`, config) || tryLoading(type, config) || "" || tryLoading(path36.join(process.cwd(), type), config); + var appendersLoading = new Set(); + var getAppender = (name2, config) => { + if (appenders.has(name2)) + return appenders.get(name2); + if (!config.appenders[name2]) + return false; + if (appendersLoading.has(name2)) + throw new Error(`Dependency loop detected for appender ${name2}.`); + appendersLoading.add(name2); + debug(`Creating appender ${name2}`); + const appender = createAppender(name2, config); + appendersLoading.delete(name2); + appenders.set(name2, appender); + return appender; + }; + var createAppender = (name2, config) => { + const appenderConfig = config.appenders[name2]; + const appenderModule = appenderConfig.type.configure ? appenderConfig.type : loadAppenderModule(appenderConfig.type, config); + configuration.throwExceptionIf(config, configuration.not(appenderModule), `appender "${name2}" 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(`${name2}: clustering.isMaster ? ${clustering.isMaster()}`); + debug(`${name2}: appenderModule is ${require("util").inspect(appenderModule)}`); + return clustering.onlyOnMaster(() => { + debug(`calling appenderModule.configure for ${name2} / ${appenderConfig.type}`); + return appenderModule.configure(adapters.modifyConfig(appenderConfig), layouts, (appender) => getAppender(appender, config), levels); + }, () => { + }); + }; + var setup = (config) => { + appenders.clear(); + appendersLoading.clear(); + const usedAppenders = []; + Object.values(config.categories).forEach((category) => { + usedAppenders.push(...category.appenders); + }); + Object.keys(config.appenders).forEach((name2) => { + if (usedAppenders.includes(name2) || config.appenders[name2].type === "tcp-server") { + getAppender(name2, config); + } + }); + }; + setup({ appenders: { out: { type: "stdout" } }, categories: { default: { appenders: ["out"], level: "trace" } } }); + 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((name2) => { + configuration.throwExceptionIf(config, configuration.not(config.appenders[name2].type), `appender "${name2}" is not valid (must be an object with property "type")`); + }); + }); + configuration.addListener(setup); + module2.exports = appenders; + } +}); + +// node_modules/log4js/lib/categories.js +var require_categories = __commonJS({ + "node_modules/log4js/lib/categories.js"(exports2, module2) { + var debug = require_src()("log4js:categories"); + var configuration = require_configuration(); + var levels = require_levels(); + var appenders = require_appenders(); + var categories = new Map(); + function inheritFromParent(config, category, categoryName) { + if (category.inherit === false) + return; + const lastDotIndex = categoryName.lastIndexOf("."); + if (lastDotIndex < 0) + return; + const parentCategoryName = categoryName.substring(0, lastDotIndex); + let parentCategory = config.categories[parentCategoryName]; + if (!parentCategory) { + parentCategory = { inherit: true, appenders: [] }; + } + inheritFromParent(config, parentCategory, parentCategoryName); + 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; + parentCategory.appenders.forEach((ap) => { + if (!category.appenders.includes(ap)) { + category.appenders.push(ap); + } + }); + category.parent = parentCategory; + } + function addCategoryInheritance(config) { + if (!config.categories) + return; + const categoryNames = Object.keys(config.categories); + categoryNames.forEach((name2) => { + const category = config.categories[name2]; + inheritFromParent(config, category, name2); + }); + } + 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((name2) => { + const category = config.categories[name2]; + configuration.throwExceptionIf(config, [ + configuration.not(category.appenders), + configuration.not(category.level) + ], `category "${name2}" is not valid (must be an object with properties "appenders" and "level")`); + configuration.throwExceptionIf(config, configuration.not(Array.isArray(category.appenders)), `category "${name2}" is not valid (appenders must be an array of appender names)`); + configuration.throwExceptionIf(config, configuration.not(category.appenders.length), `category "${name2}" 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 "${name2}" is not valid (enableCallStack must be boolean type)`); + } + category.appenders.forEach((appender) => { + configuration.throwExceptionIf(config, configuration.not(appenders.get(appender)), `category "${name2}" is not valid (appender "${appender}" is not defined)`); + }); + configuration.throwExceptionIf(config, configuration.not(levels.getLevel(category.level)), `category "${name2}" 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.'); + }); + var setup = (config) => { + categories.clear(); + const categoryNames = Object.keys(config.categories); + categoryNames.forEach((name2) => { + const category = config.categories[name2]; + const categoryAppenders = []; + category.appenders.forEach((appender) => { + categoryAppenders.push(appenders.get(appender)); + debug(`Creating category ${name2}`); + categories.set(name2, { + appenders: categoryAppenders, + level: levels.getLevel(category.level), + enableCallStack: category.enableCallStack || false + }); + }); + }); + }; + setup({ categories: { default: { appenders: ["out"], level: "OFF" } } }); + configuration.addListener(setup); + var 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"); + }; + var appendersForCategory = (category) => configForCategory(category).appenders; + var getLevelForCategory = (category) => configForCategory(category).level; + var 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); + }; + var getEnableCallStackForCategory = (category) => configForCategory(category).enableCallStack === true; + var setEnableCallStackForCategory = (category, useCallStack) => { + configForCategory(category).enableCallStack = useCallStack; + }; + module2.exports = { + appendersForCategory, + getLevelForCategory, + setLevelForCategory, + getEnableCallStackForCategory, + setEnableCallStackForCategory + }; + } +}); + +// node_modules/log4js/lib/logger.js +var require_logger = __commonJS({ + "node_modules/log4js/lib/logger.js"(exports2, module2) { + var debug = require_src()("log4js:logger"); + var LoggingEvent = require_LoggingEvent(); + var levels = require_levels(); + var clustering = require_clustering(); + var categories = require_categories(); + var configuration = require_configuration(); + var 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; + } + var Logger2 = class { + constructor(name2) { + if (!name2) { + throw new Error("No category provided."); + } + this.category = name2; + 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); + Logger2.prototype[`is${isLevelMethod}Enabled`] = function() { + return this.isLevelEnabled(level); + }; + Logger2.prototype[levelMethod] = function(...args) { + this.log(level, ...args); + }; + } + levels.levels.forEach(addLevelMethods); + configuration.addListener(() => { + levels.levels.forEach(addLevelMethods); + }); + module2.exports = Logger2; + } +}); + +// node_modules/log4js/lib/connect-logger.js +var require_connect_logger = __commonJS({ + "node_modules/log4js/lib/connect-logger.js"(exports2, module2) { + var levels = require_levels(); + var DEFAULT_FORMAT = ':remote-addr - - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"'; + function getUrl(req) { + return req.originalUrl || req.url; + } + 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) { + 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)); + } + function format2(str, tokens) { + for (let i = 0; i < tokens.length; i++) { + str = str.replace(tokens[i].token, tokens[i].replacement); + } + return str; + } + function createNoLogCondition(nolog) { + let regexp = null; + if (nolog instanceof RegExp) { + regexp = nolog; + } + if (typeof nolog === "string") { + regexp = new RegExp(nolog); + } + if (Array.isArray(nolog)) { + const regexpsAsStrings = nolog.map((reg) => reg.source ? reg.source : reg); + regexp = new RegExp(regexpsAsStrings.join("|")); + } + return regexp; + } + 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; + } + module2.exports = function getLogger(logger4js, options) { + 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) => { + if (req._logging) + return next(); + if (nolog && nolog.test(req.originalUrl)) + return next(); + if (thisLogger.isLevelEnabled(level) || options.level === "auto") { + const start = new Date(); + const { writeHead } = res; + req._logging = true; + res.writeHead = (code, headers) => { + res.writeHead = writeHead; + res.writeHead(code, headers); + res.__statusCode = code; + res.__headers = headers || {}; + }; + res.on("finish", () => { + res.responseTime = new Date() - start; + 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) => format2(str, combinedTokens)); + if (line) + thisLogger.log(level, line); + } else { + thisLogger.log(level, format2(fmt, combinedTokens)); + } + if (options.context) + thisLogger.removeContext("res"); + }); + } + return next(); + }; + }; + } +}); + +// node_modules/log4js/lib/log4js.js +var require_log4js = __commonJS({ + "node_modules/log4js/lib/log4js.js"(exports2, module2) { + var debug = require_src()("log4js:main"); + var fs27 = require("fs"); + var deepClone2 = require_rfdc()({ proto: true }); + var configuration = require_configuration(); + var layouts = require_layouts(); + var levels = require_levels(); + var appenders = require_appenders(); + var categories = require_categories(); + var Logger2 = require_logger(); + var clustering = require_clustering(); + var connectLogger = require_connect_logger(); + var 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(fs27.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(deepClone2(configObject)); + clustering.onMessage(sendLogEventToAppender); + enabled = true; + return log4js2; + } + function shutdown(cb) { + debug("Shutdown called. Disabling all log writing."); + enabled = false; + 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."); + if (cb) { + cb(error); + } + } + } + if (shutdownFunctions === 0) { + debug("No appenders with shutdown functions found."); + return cb !== void 0 && cb(); + } + appendersToCheck.filter((a) => a.shutdown).forEach((a) => a.shutdown(complete)); + return null; + } + function getLogger(category) { + if (!enabled) { + configure(process.env.LOG4JS_CONFIG || { + appenders: { out: { type: "stdout" } }, + categories: { default: { appenders: ["out"], level: "OFF" } } + }); + } + return new Logger2(category || "default"); + } + var log4js2 = { + getLogger, + configure, + shutdown, + connectLogger, + levels, + addLayout: layouts.addLayout + }; + module2.exports = log4js2; + } +}); + +// node_modules/fs-extra/node_modules/universalify/index.js +var require_universalify2 = __commonJS({ + "node_modules/fs-extra/node_modules/universalify/index.js"(exports2) { + "use strict"; + exports2.fromCallback = function(fn) { + return Object.defineProperty(function(...args) { + if (typeof args[args.length - 1] === "function") + fn.apply(this, args); + else { + return new Promise((resolve3, reject) => { + fn.call(this, ...args, (err, res) => err != null ? reject(err) : resolve3(res)); + }); + } + }, "name", { value: fn.name }); + }; + exports2.fromPromise = function(fn) { + return Object.defineProperty(function(...args) { + const cb = args[args.length - 1]; + if (typeof cb !== "function") + return fn.apply(this, args); + else + fn.apply(this, args.slice(0, -1)).then((r) => cb(null, r), cb); + }, "name", { value: fn.name }); + }; + } +}); + +// node_modules/fs-extra/lib/fs/index.js +var require_fs2 = __commonJS({ + "node_modules/fs-extra/lib/fs/index.js"(exports2) { + "use strict"; + var u = require_universalify2().fromCallback; + var fs27 = require_graceful_fs(); + var api = [ + "access", + "appendFile", + "chmod", + "chown", + "close", + "copyFile", + "fchmod", + "fchown", + "fdatasync", + "fstat", + "fsync", + "ftruncate", + "futimes", + "lchmod", + "lchown", + "link", + "lstat", + "mkdir", + "mkdtemp", + "open", + "opendir", + "readdir", + "readFile", + "readlink", + "realpath", + "rename", + "rm", + "rmdir", + "stat", + "symlink", + "truncate", + "unlink", + "utimes", + "writeFile" + ].filter((key) => { + return typeof fs27[key] === "function"; + }); + Object.keys(fs27).forEach((key) => { + if (key === "promises") { + return; + } + exports2[key] = fs27[key]; + }); + api.forEach((method) => { + exports2[method] = u(fs27[method]); + }); + exports2.exists = function(filename, callback) { + if (typeof callback === "function") { + return fs27.exists(filename, callback); + } + return new Promise((resolve3) => { + return fs27.exists(filename, resolve3); + }); + }; + exports2.read = function(fd, buffer, offset, length, position, callback) { + if (typeof callback === "function") { + return fs27.read(fd, buffer, offset, length, position, callback); + } + return new Promise((resolve3, reject) => { + fs27.read(fd, buffer, offset, length, position, (err, bytesRead, buffer2) => { + if (err) + return reject(err); + resolve3({ bytesRead, buffer: buffer2 }); + }); + }); + }; + exports2.write = function(fd, buffer, ...args) { + if (typeof args[args.length - 1] === "function") { + return fs27.write(fd, buffer, ...args); + } + return new Promise((resolve3, reject) => { + fs27.write(fd, buffer, ...args, (err, bytesWritten, buffer2) => { + if (err) + return reject(err); + resolve3({ bytesWritten, buffer: buffer2 }); + }); + }); + }; + if (typeof fs27.writev === "function") { + exports2.writev = function(fd, buffers, ...args) { + if (typeof args[args.length - 1] === "function") { + return fs27.writev(fd, buffers, ...args); + } + return new Promise((resolve3, reject) => { + fs27.writev(fd, buffers, ...args, (err, bytesWritten, buffers2) => { + if (err) + return reject(err); + resolve3({ bytesWritten, buffers: buffers2 }); + }); + }); + }; + } + if (typeof fs27.realpath.native === "function") { + exports2.realpath.native = u(fs27.realpath.native); + } + } +}); + +// node_modules/at-least-node/index.js +var require_at_least_node = __commonJS({ + "node_modules/at-least-node/index.js"(exports2, module2) { + module2.exports = (r) => { + const n = process.versions.node.split(".").map((x) => parseInt(x, 10)); + r = r.split(".").map((x) => parseInt(x, 10)); + return n[0] > r[0] || n[0] === r[0] && (n[1] > r[1] || n[1] === r[1] && n[2] >= r[2]); + }; + } +}); + +// node_modules/fs-extra/lib/mkdirs/make-dir.js +var require_make_dir = __commonJS({ + "node_modules/fs-extra/lib/mkdirs/make-dir.js"(exports2, module2) { + "use strict"; + var fs27 = require_fs2(); + var path36 = require("path"); + var atLeastNode = require_at_least_node(); + var useNativeRecursiveOption = atLeastNode("10.12.0"); + var checkPath = (pth) => { + if (process.platform === "win32") { + const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path36.parse(pth).root, "")); + if (pathHasInvalidWinCharacters) { + const error = new Error(`Path contains invalid characters: ${pth}`); + error.code = "EINVAL"; + throw error; + } + } + }; + var processOptions = (options) => { + const defaults2 = { mode: 511 }; + if (typeof options === "number") + options = { mode: options }; + return __spreadValues(__spreadValues({}, defaults2), options); + }; + var permissionError = (pth) => { + const error = new Error(`operation not permitted, mkdir '${pth}'`); + error.code = "EPERM"; + error.errno = -4048; + error.path = pth; + error.syscall = "mkdir"; + return error; + }; + module2.exports.makeDir = async (input, options) => { + checkPath(input); + options = processOptions(options); + if (useNativeRecursiveOption) { + const pth = path36.resolve(input); + return fs27.mkdir(pth, { + mode: options.mode, + recursive: true + }); + } + const make = async (pth) => { + try { + await fs27.mkdir(pth, options.mode); + } catch (error) { + if (error.code === "EPERM") { + throw error; + } + if (error.code === "ENOENT") { + if (path36.dirname(pth) === pth) { + throw permissionError(pth); + } + if (error.message.includes("null bytes")) { + throw error; + } + await make(path36.dirname(pth)); + return make(pth); + } + try { + const stats = await fs27.stat(pth); + if (!stats.isDirectory()) { + throw new Error("The path is not a directory"); + } + } catch { + throw error; + } + } + }; + return make(path36.resolve(input)); + }; + module2.exports.makeDirSync = (input, options) => { + checkPath(input); + options = processOptions(options); + if (useNativeRecursiveOption) { + const pth = path36.resolve(input); + return fs27.mkdirSync(pth, { + mode: options.mode, + recursive: true + }); + } + const make = (pth) => { + try { + fs27.mkdirSync(pth, options.mode); + } catch (error) { + if (error.code === "EPERM") { + throw error; + } + if (error.code === "ENOENT") { + if (path36.dirname(pth) === pth) { + throw permissionError(pth); + } + if (error.message.includes("null bytes")) { + throw error; + } + make(path36.dirname(pth)); + return make(pth); + } + try { + if (!fs27.statSync(pth).isDirectory()) { + throw new Error("The path is not a directory"); + } + } catch { + throw error; + } + } + }; + return make(path36.resolve(input)); + }; + } +}); + +// node_modules/fs-extra/lib/mkdirs/index.js +var require_mkdirs3 = __commonJS({ + "node_modules/fs-extra/lib/mkdirs/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromPromise; + var { makeDir: _makeDir, makeDirSync } = require_make_dir(); + var makeDir = u(_makeDir); + module2.exports = { + mkdirs: makeDir, + mkdirsSync: makeDirSync, + mkdirp: makeDir, + mkdirpSync: makeDirSync, + ensureDir: makeDir, + ensureDirSync: makeDirSync + }; + } +}); + +// node_modules/fs-extra/lib/util/utimes.js +var require_utimes2 = __commonJS({ + "node_modules/fs-extra/lib/util/utimes.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + function utimesMillis(path36, atime, mtime, callback) { + fs27.open(path36, "r+", (err, fd) => { + if (err) + return callback(err); + fs27.futimes(fd, atime, mtime, (futimesErr) => { + fs27.close(fd, (closeErr) => { + if (callback) + callback(futimesErr || closeErr); + }); + }); + }); + } + function utimesMillisSync(path36, atime, mtime) { + const fd = fs27.openSync(path36, "r+"); + fs27.futimesSync(fd, atime, mtime); + return fs27.closeSync(fd); + } + module2.exports = { + utimesMillis, + utimesMillisSync + }; + } +}); + +// node_modules/fs-extra/lib/util/stat.js +var require_stat2 = __commonJS({ + "node_modules/fs-extra/lib/util/stat.js"(exports2, module2) { + "use strict"; + var fs27 = require_fs2(); + var path36 = require("path"); + var util4 = require("util"); + var atLeastNode = require_at_least_node(); + var nodeSupportsBigInt = atLeastNode("10.5.0"); + var stat = (file) => nodeSupportsBigInt ? fs27.stat(file, { bigint: true }) : fs27.stat(file); + var statSync = (file) => nodeSupportsBigInt ? fs27.statSync(file, { bigint: true }) : fs27.statSync(file); + function getStats(src, dest) { + return Promise.all([ + stat(src), + stat(dest).catch((err) => { + if (err.code === "ENOENT") + return null; + throw err; + }) + ]).then(([srcStat, destStat]) => ({ srcStat, destStat })); + } + function getStatsSync(src, dest) { + let destStat; + const srcStat = statSync(src); + try { + destStat = statSync(dest); + } catch (err) { + if (err.code === "ENOENT") + return { srcStat, destStat: null }; + throw err; + } + return { srcStat, destStat }; + } + function checkPaths(src, dest, funcName, cb) { + util4.callbackify(getStats)(src, dest, (err, stats) => { + if (err) + return cb(err); + const { srcStat, destStat } = stats; + if (destStat && areIdentical(srcStat, destStat)) { + 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 && areIdentical(srcStat, destStat)) { + 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 }; + } + function checkParentPaths(src, srcStat, dest, funcName, cb) { + const srcParent = path36.resolve(path36.dirname(src)); + const destParent = path36.resolve(path36.dirname(dest)); + if (destParent === srcParent || destParent === path36.parse(destParent).root) + return cb(); + const callback = (err, destStat) => { + if (err) { + if (err.code === "ENOENT") + return cb(); + return cb(err); + } + if (areIdentical(srcStat, destStat)) { + return cb(new Error(errMsg(src, dest, funcName))); + } + return checkParentPaths(src, srcStat, destParent, funcName, cb); + }; + if (nodeSupportsBigInt) + fs27.stat(destParent, { bigint: true }, callback); + else + fs27.stat(destParent, callback); + } + function checkParentPathsSync(src, srcStat, dest, funcName) { + const srcParent = path36.resolve(path36.dirname(src)); + const destParent = path36.resolve(path36.dirname(dest)); + if (destParent === srcParent || destParent === path36.parse(destParent).root) + return; + let destStat; + try { + destStat = statSync(destParent); + } catch (err) { + if (err.code === "ENOENT") + return; + throw err; + } + if (areIdentical(srcStat, destStat)) { + throw new Error(errMsg(src, dest, funcName)); + } + return checkParentPathsSync(src, srcStat, destParent, funcName); + } + function areIdentical(srcStat, destStat) { + if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) { + if (nodeSupportsBigInt || destStat.ino < Number.MAX_SAFE_INTEGER) { + return true; + } + if (destStat.size === srcStat.size && destStat.mode === srcStat.mode && destStat.nlink === srcStat.nlink && destStat.atimeMs === srcStat.atimeMs && destStat.mtimeMs === srcStat.mtimeMs && destStat.ctimeMs === srcStat.ctimeMs && destStat.birthtimeMs === srcStat.birthtimeMs) { + return true; + } + } + return false; + } + function isSrcSubdir(src, dest) { + const srcArr = path36.resolve(src).split(path36.sep).filter((i) => i); + const destArr = path36.resolve(dest).split(path36.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}'.`; + } + module2.exports = { + checkPaths, + checkPathsSync, + checkParentPaths, + checkParentPathsSync, + isSrcSubdir + }; + } +}); + +// node_modules/fs-extra/lib/copy-sync/copy-sync.js +var require_copy_sync3 = __commonJS({ + "node_modules/fs-extra/lib/copy-sync/copy-sync.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdirsSync = require_mkdirs3().mkdirsSync; + var utimesMillisSync = require_utimes2().utimesMillisSync; + var stat = require_stat2(); + function copySync(src, dest, opts) { + if (typeof opts === "function") { + opts = { filter: opts }; + } + opts = opts || {}; + opts.clobber = "clobber" in opts ? !!opts.clobber : true; + opts.overwrite = "overwrite" in opts ? !!opts.overwrite : opts.clobber; + if (opts.preserveTimestamps && process.arch === "ia32") { + console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended; + + 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 = path36.dirname(dest); + if (!fs27.existsSync(destParent)) + mkdirsSync(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 ? fs27.statSync : fs27.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) { + fs27.unlinkSync(dest); + return copyFile(srcStat, src, dest, opts); + } else if (opts.errorOnExist) { + throw new Error(`'${dest}' already exists`); + } + } + function copyFile(srcStat, src, dest, opts) { + fs27.copyFileSync(src, dest); + if (opts.preserveTimestamps) + handleTimestamps(srcStat.mode, src, dest); + return setDestMode(dest, srcStat.mode); + } + function handleTimestamps(srcMode, src, dest) { + if (fileIsNotWritable(srcMode)) + makeFileWritable(dest, srcMode); + return setDestTimestamps(src, dest); + } + function fileIsNotWritable(srcMode) { + return (srcMode & 128) === 0; + } + function makeFileWritable(dest, srcMode) { + return setDestMode(dest, srcMode | 128); + } + function setDestMode(dest, srcMode) { + return fs27.chmodSync(dest, srcMode); + } + function setDestTimestamps(src, dest) { + const updatedSrcStat = fs27.statSync(src); + return utimesMillisSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime); + } + function onDir(srcStat, destStat, src, dest, opts) { + if (!destStat) + return mkDirAndCopy(srcStat.mode, 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(srcMode, src, dest, opts) { + fs27.mkdirSync(dest); + copyDir(src, dest, opts); + return setDestMode(dest, srcMode); + } + function copyDir(src, dest, opts) { + fs27.readdirSync(src).forEach((item) => copyDirItem(item, src, dest, opts)); + } + function copyDirItem(item, src, dest, opts) { + const srcItem = path36.join(src, item); + const destItem = path36.join(dest, item); + const { destStat } = stat.checkPathsSync(srcItem, destItem, "copy"); + return startCopy(destStat, srcItem, destItem, opts); + } + function onLink(destStat, src, dest, opts) { + let resolvedSrc = fs27.readlinkSync(src); + if (opts.dereference) { + resolvedSrc = path36.resolve(process.cwd(), resolvedSrc); + } + if (!destStat) { + return fs27.symlinkSync(resolvedSrc, dest); + } else { + let resolvedDest; + try { + resolvedDest = fs27.readlinkSync(dest); + } catch (err) { + if (err.code === "EINVAL" || err.code === "UNKNOWN") + return fs27.symlinkSync(resolvedSrc, dest); + throw err; + } + if (opts.dereference) { + resolvedDest = path36.resolve(process.cwd(), resolvedDest); + } + if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) { + throw new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`); + } + if (fs27.statSync(dest).isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) { + throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`); + } + return copyLink(resolvedSrc, dest); + } + } + function copyLink(resolvedSrc, dest) { + fs27.unlinkSync(dest); + return fs27.symlinkSync(resolvedSrc, dest); + } + module2.exports = copySync; + } +}); + +// node_modules/fs-extra/lib/copy-sync/index.js +var require_copy_sync4 = __commonJS({ + "node_modules/fs-extra/lib/copy-sync/index.js"(exports2, module2) { + "use strict"; + module2.exports = { + copySync: require_copy_sync3() + }; + } +}); + +// node_modules/fs-extra/lib/path-exists/index.js +var require_path_exists2 = __commonJS({ + "node_modules/fs-extra/lib/path-exists/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromPromise; + var fs27 = require_fs2(); + function pathExists(path36) { + return fs27.access(path36).then(() => true).catch(() => false); + } + module2.exports = { + pathExists: u(pathExists), + pathExistsSync: fs27.existsSync + }; + } +}); + +// node_modules/fs-extra/lib/copy/copy.js +var require_copy3 = __commonJS({ + "node_modules/fs-extra/lib/copy/copy.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdirs = require_mkdirs3().mkdirs; + var pathExists = require_path_exists2().pathExists; + var utimesMillis = require_utimes2().utimesMillis; + var stat = require_stat2(); + 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; + opts.overwrite = "overwrite" in opts ? !!opts.overwrite : opts.clobber; + if (opts.preserveTimestamps && process.arch === "ia32") { + console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended; + + 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", (err2) => { + if (err2) + return cb(err2); + 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 = path36.dirname(dest); + pathExists(destParent, (err, dirExists) => { + if (err) + return cb(err); + if (dirExists) + return startCopy(destStat, src, dest, opts, cb); + mkdirs(destParent, (err2) => { + if (err2) + return cb(err2); + 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 stat2 = opts.dereference ? fs27.stat : fs27.lstat; + stat2(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) { + fs27.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) { + fs27.copyFile(src, dest, (err) => { + if (err) + return cb(err); + if (opts.preserveTimestamps) + return handleTimestampsAndMode(srcStat.mode, src, dest, cb); + return setDestMode(dest, srcStat.mode, cb); + }); + } + function handleTimestampsAndMode(srcMode, src, dest, cb) { + if (fileIsNotWritable(srcMode)) { + return makeFileWritable(dest, srcMode, (err) => { + if (err) + return cb(err); + return setDestTimestampsAndMode(srcMode, src, dest, cb); + }); + } + return setDestTimestampsAndMode(srcMode, src, dest, cb); + } + function fileIsNotWritable(srcMode) { + return (srcMode & 128) === 0; + } + function makeFileWritable(dest, srcMode, cb) { + return setDestMode(dest, srcMode | 128, cb); + } + function setDestTimestampsAndMode(srcMode, src, dest, cb) { + setDestTimestamps(src, dest, (err) => { + if (err) + return cb(err); + return setDestMode(dest, srcMode, cb); + }); + } + function setDestMode(dest, srcMode, cb) { + return fs27.chmod(dest, srcMode, cb); + } + function setDestTimestamps(src, dest, cb) { + fs27.stat(src, (err, updatedSrcStat) => { + if (err) + return cb(err); + return utimesMillis(dest, updatedSrcStat.atime, updatedSrcStat.mtime, cb); + }); + } + function onDir(srcStat, destStat, src, dest, opts, cb) { + if (!destStat) + return mkDirAndCopy(srcStat.mode, 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(srcMode, src, dest, opts, cb) { + fs27.mkdir(dest, (err) => { + if (err) + return cb(err); + copyDir(src, dest, opts, (err2) => { + if (err2) + return cb(err2); + return setDestMode(dest, srcMode, cb); + }); + }); + } + function copyDir(src, dest, opts, cb) { + fs27.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 = path36.join(src, item); + const destItem = path36.join(dest, item); + stat.checkPaths(srcItem, destItem, "copy", (err, stats) => { + if (err) + return cb(err); + const { destStat } = stats; + startCopy(destStat, srcItem, destItem, opts, (err2) => { + if (err2) + return cb(err2); + return copyDirItems(items, src, dest, opts, cb); + }); + }); + } + function onLink(destStat, src, dest, opts, cb) { + fs27.readlink(src, (err, resolvedSrc) => { + if (err) + return cb(err); + if (opts.dereference) { + resolvedSrc = path36.resolve(process.cwd(), resolvedSrc); + } + if (!destStat) { + return fs27.symlink(resolvedSrc, dest, cb); + } else { + fs27.readlink(dest, (err2, resolvedDest) => { + if (err2) { + if (err2.code === "EINVAL" || err2.code === "UNKNOWN") + return fs27.symlink(resolvedSrc, dest, cb); + return cb(err2); + } + if (opts.dereference) { + resolvedDest = path36.resolve(process.cwd(), resolvedDest); + } + if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) { + return cb(new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`)); + } + 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) { + fs27.unlink(dest, (err) => { + if (err) + return cb(err); + return fs27.symlink(resolvedSrc, dest, cb); + }); + } + module2.exports = copy; + } +}); + +// node_modules/fs-extra/lib/copy/index.js +var require_copy4 = __commonJS({ + "node_modules/fs-extra/lib/copy/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromCallback; + module2.exports = { + copy: u(require_copy3()) + }; + } +}); + +// node_modules/fs-extra/lib/remove/rimraf.js +var require_rimraf2 = __commonJS({ + "node_modules/fs-extra/lib/remove/rimraf.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var assert = require("assert"); + var isWindows4 = process.platform === "win32"; + function defaults2(options) { + const methods2 = [ + "unlink", + "chmod", + "stat", + "lstat", + "rmdir", + "readdir" + ]; + methods2.forEach((m) => { + options[m] = options[m] || fs27[m]; + m = m + "Sync"; + options[m] = options[m] || fs27[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"); + defaults2(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; + return setTimeout(() => rimraf_(p, options, CB), time); + } + if (er.code === "ENOENT") + er = null; + } + cb(er); + }); + } + function rimraf_(p, options, cb) { + assert(p); + assert(options); + assert(typeof cb === "function"); + options.lstat(p, (er, st) => { + if (er && er.code === "ENOENT") { + return cb(null); + } + if (er && er.code === "EPERM" && isWindows4) { + return fixWinEPERM(p, options, er, cb); + } + if (st && st.isDirectory()) { + return rmdir(p, options, er, cb); + } + options.unlink(p, (er2) => { + if (er2) { + if (er2.code === "ENOENT") { + return cb(null); + } + if (er2.code === "EPERM") { + return isWindows4 ? fixWinEPERM(p, options, er2, cb) : rmdir(p, options, er2, cb); + } + if (er2.code === "EISDIR") { + return rmdir(p, options, er2, cb); + } + } + return cb(er2); + }); + }); + } + function fixWinEPERM(p, options, er, cb) { + assert(p); + assert(options); + assert(typeof cb === "function"); + options.chmod(p, 438, (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); + try { + options.chmodSync(p, 438); + } 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); + assert(typeof cb === "function"); + 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(path36.join(p, f), options, (er2) => { + if (errState) { + return; + } + if (er2) + return cb(errState = er2); + if (--n === 0) { + options.rmdir(p, cb); + } + }); + }); + }); + } + function rimrafSync(p, options) { + let st; + options = options || {}; + defaults2(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; + } + if (er.code === "EPERM" && isWindows4) { + fixWinEPERMSync(p, options, er); + } + } + try { + 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 isWindows4 ? 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); + 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(path36.join(p, f), options)); + if (isWindows4) { + const startTime = Date.now(); + do { + try { + const ret = options.rmdirSync(p, options); + return ret; + } catch { + } + } while (Date.now() - startTime < 500); + } else { + const ret = options.rmdirSync(p, options); + return ret; + } + } + module2.exports = rimraf; + rimraf.sync = rimrafSync; + } +}); + +// node_modules/fs-extra/lib/remove/index.js +var require_remove2 = __commonJS({ + "node_modules/fs-extra/lib/remove/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromCallback; + var rimraf = require_rimraf2(); + module2.exports = { + remove: u(rimraf), + removeSync: rimraf.sync + }; + } +}); + +// node_modules/fs-extra/lib/empty/index.js +var require_empty2 = __commonJS({ + "node_modules/fs-extra/lib/empty/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromCallback; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdir = require_mkdirs3(); + var remove = require_remove2(); + var emptyDir = u(function emptyDir2(dir, callback) { + callback = callback || function() { + }; + fs27.readdir(dir, (err, items) => { + if (err) + return mkdir.mkdirs(dir, callback); + items = items.map((item) => path36.join(dir, item)); + deleteItem(); + function deleteItem() { + const item = items.pop(); + if (!item) + return callback(); + remove.remove(item, (err2) => { + if (err2) + return callback(err2); + deleteItem(); + }); + } + }); + }); + function emptyDirSync(dir) { + let items; + try { + items = fs27.readdirSync(dir); + } catch { + return mkdir.mkdirsSync(dir); + } + items.forEach((item) => { + item = path36.join(dir, item); + remove.removeSync(item); + }); + } + module2.exports = { + emptyDirSync, + emptydirSync: emptyDirSync, + emptyDir, + emptydir: emptyDir + }; + } +}); + +// node_modules/fs-extra/lib/ensure/file.js +var require_file3 = __commonJS({ + "node_modules/fs-extra/lib/ensure/file.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromCallback; + var path36 = require("path"); + var fs27 = require_graceful_fs(); + var mkdir = require_mkdirs3(); + function createFile(file, callback) { + function makeFile() { + fs27.writeFile(file, "", (err) => { + if (err) + return callback(err); + callback(); + }); + } + fs27.stat(file, (err, stats) => { + if (!err && stats.isFile()) + return callback(); + const dir = path36.dirname(file); + fs27.stat(dir, (err2, stats2) => { + if (err2) { + if (err2.code === "ENOENT") { + return mkdir.mkdirs(dir, (err3) => { + if (err3) + return callback(err3); + makeFile(); + }); + } + return callback(err2); + } + if (stats2.isDirectory()) + makeFile(); + else { + fs27.readdir(dir, (err3) => { + if (err3) + return callback(err3); + }); + } + }); + }); + } + function createFileSync(file) { + let stats; + try { + stats = fs27.statSync(file); + } catch { + } + if (stats && stats.isFile()) + return; + const dir = path36.dirname(file); + try { + if (!fs27.statSync(dir).isDirectory()) { + fs27.readdirSync(dir); + } + } catch (err) { + if (err && err.code === "ENOENT") + mkdir.mkdirsSync(dir); + else + throw err; + } + fs27.writeFileSync(file, ""); + } + module2.exports = { + createFile: u(createFile), + createFileSync + }; + } +}); + +// node_modules/fs-extra/lib/ensure/link.js +var require_link2 = __commonJS({ + "node_modules/fs-extra/lib/ensure/link.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromCallback; + var path36 = require("path"); + var fs27 = require_graceful_fs(); + var mkdir = require_mkdirs3(); + var pathExists = require_path_exists2().pathExists; + function createLink(srcpath, dstpath, callback) { + function makeLink(srcpath2, dstpath2) { + fs27.link(srcpath2, dstpath2, (err) => { + if (err) + return callback(err); + callback(null); + }); + } + pathExists(dstpath, (err, destinationExists) => { + if (err) + return callback(err); + if (destinationExists) + return callback(null); + fs27.lstat(srcpath, (err2) => { + if (err2) { + err2.message = err2.message.replace("lstat", "ensureLink"); + return callback(err2); + } + const dir = path36.dirname(dstpath); + pathExists(dir, (err3, dirExists) => { + if (err3) + return callback(err3); + if (dirExists) + return makeLink(srcpath, dstpath); + mkdir.mkdirs(dir, (err4) => { + if (err4) + return callback(err4); + makeLink(srcpath, dstpath); + }); + }); + }); + }); + } + function createLinkSync(srcpath, dstpath) { + const destinationExists = fs27.existsSync(dstpath); + if (destinationExists) + return void 0; + try { + fs27.lstatSync(srcpath); + } catch (err) { + err.message = err.message.replace("lstat", "ensureLink"); + throw err; + } + const dir = path36.dirname(dstpath); + const dirExists = fs27.existsSync(dir); + if (dirExists) + return fs27.linkSync(srcpath, dstpath); + mkdir.mkdirsSync(dir); + return fs27.linkSync(srcpath, dstpath); + } + module2.exports = { + createLink: u(createLink), + createLinkSync + }; + } +}); + +// node_modules/fs-extra/lib/ensure/symlink-paths.js +var require_symlink_paths2 = __commonJS({ + "node_modules/fs-extra/lib/ensure/symlink-paths.js"(exports2, module2) { + "use strict"; + var path36 = require("path"); + var fs27 = require_graceful_fs(); + var pathExists = require_path_exists2().pathExists; + function symlinkPaths(srcpath, dstpath, callback) { + if (path36.isAbsolute(srcpath)) { + return fs27.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 = path36.dirname(dstpath); + const relativeToDst = path36.join(dstdir, srcpath); + return pathExists(relativeToDst, (err, exists) => { + if (err) + return callback(err); + if (exists) { + return callback(null, { + toCwd: relativeToDst, + toDst: srcpath + }); + } else { + return fs27.lstat(srcpath, (err2) => { + if (err2) { + err2.message = err2.message.replace("lstat", "ensureSymlink"); + return callback(err2); + } + return callback(null, { + toCwd: srcpath, + toDst: path36.relative(dstdir, srcpath) + }); + }); + } + }); + } + } + function symlinkPathsSync(srcpath, dstpath) { + let exists; + if (path36.isAbsolute(srcpath)) { + exists = fs27.existsSync(srcpath); + if (!exists) + throw new Error("absolute srcpath does not exist"); + return { + toCwd: srcpath, + toDst: srcpath + }; + } else { + const dstdir = path36.dirname(dstpath); + const relativeToDst = path36.join(dstdir, srcpath); + exists = fs27.existsSync(relativeToDst); + if (exists) { + return { + toCwd: relativeToDst, + toDst: srcpath + }; + } else { + exists = fs27.existsSync(srcpath); + if (!exists) + throw new Error("relative srcpath does not exist"); + return { + toCwd: srcpath, + toDst: path36.relative(dstdir, srcpath) + }; + } + } + } + module2.exports = { + symlinkPaths, + symlinkPathsSync + }; + } +}); + +// node_modules/fs-extra/lib/ensure/symlink-type.js +var require_symlink_type2 = __commonJS({ + "node_modules/fs-extra/lib/ensure/symlink-type.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + function symlinkType(srcpath, type, callback) { + callback = typeof type === "function" ? type : callback; + type = typeof type === "function" ? false : type; + if (type) + return callback(null, type); + fs27.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 = fs27.lstatSync(srcpath); + } catch { + return "file"; + } + return stats && stats.isDirectory() ? "dir" : "file"; + } + module2.exports = { + symlinkType, + symlinkTypeSync + }; + } +}); + +// node_modules/fs-extra/lib/ensure/symlink.js +var require_symlink2 = __commonJS({ + "node_modules/fs-extra/lib/ensure/symlink.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromCallback; + var path36 = require("path"); + var fs27 = require_graceful_fs(); + var _mkdirs = require_mkdirs3(); + var mkdirs = _mkdirs.mkdirs; + var mkdirsSync = _mkdirs.mkdirsSync; + var _symlinkPaths = require_symlink_paths2(); + var symlinkPaths = _symlinkPaths.symlinkPaths; + var symlinkPathsSync = _symlinkPaths.symlinkPathsSync; + var _symlinkType = require_symlink_type2(); + var symlinkType = _symlinkType.symlinkType; + var symlinkTypeSync = _symlinkType.symlinkTypeSync; + var pathExists = require_path_exists2().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, (err2, relative) => { + if (err2) + return callback(err2); + srcpath = relative.toDst; + symlinkType(relative.toCwd, type, (err3, type2) => { + if (err3) + return callback(err3); + const dir = path36.dirname(dstpath); + pathExists(dir, (err4, dirExists) => { + if (err4) + return callback(err4); + if (dirExists) + return fs27.symlink(srcpath, dstpath, type2, callback); + mkdirs(dir, (err5) => { + if (err5) + return callback(err5); + fs27.symlink(srcpath, dstpath, type2, callback); + }); + }); + }); + }); + }); + } + function createSymlinkSync(srcpath, dstpath, type) { + const destinationExists = fs27.existsSync(dstpath); + if (destinationExists) + return void 0; + const relative = symlinkPathsSync(srcpath, dstpath); + srcpath = relative.toDst; + type = symlinkTypeSync(relative.toCwd, type); + const dir = path36.dirname(dstpath); + const exists = fs27.existsSync(dir); + if (exists) + return fs27.symlinkSync(srcpath, dstpath, type); + mkdirsSync(dir); + return fs27.symlinkSync(srcpath, dstpath, type); + } + module2.exports = { + createSymlink: u(createSymlink), + createSymlinkSync + }; + } +}); + +// node_modules/fs-extra/lib/ensure/index.js +var require_ensure2 = __commonJS({ + "node_modules/fs-extra/lib/ensure/index.js"(exports2, module2) { + "use strict"; + var file = require_file3(); + var link = require_link2(); + var symlink = require_symlink2(); + module2.exports = { + createFile: file.createFile, + createFileSync: file.createFileSync, + ensureFile: file.createFile, + ensureFileSync: file.createFileSync, + createLink: link.createLink, + createLinkSync: link.createLinkSync, + ensureLink: link.createLink, + ensureLinkSync: link.createLinkSync, + createSymlink: symlink.createSymlink, + createSymlinkSync: symlink.createSymlinkSync, + ensureSymlink: symlink.createSymlink, + ensureSymlinkSync: symlink.createSymlinkSync + }; + } +}); + +// node_modules/jsonfile/node_modules/universalify/index.js +var require_universalify3 = __commonJS({ + "node_modules/jsonfile/node_modules/universalify/index.js"(exports2) { + "use strict"; + exports2.fromCallback = function(fn) { + return Object.defineProperty(function(...args) { + if (typeof args[args.length - 1] === "function") + fn.apply(this, args); + else { + return new Promise((resolve3, reject) => { + fn.call(this, ...args, (err, res) => err != null ? reject(err) : resolve3(res)); + }); + } + }, "name", { value: fn.name }); + }; + exports2.fromPromise = function(fn) { + return Object.defineProperty(function(...args) { + const cb = args[args.length - 1]; + if (typeof cb !== "function") + return fn.apply(this, args); + else + fn.apply(this, args.slice(0, -1)).then((r) => cb(null, r), cb); + }, "name", { value: fn.name }); + }; + } +}); + +// node_modules/jsonfile/utils.js +var require_utils = __commonJS({ + "node_modules/jsonfile/utils.js"(exports2, module2) { + function stringify3(obj, { EOL: EOL2 = "\n", finalEOL = true, replacer = null, spaces } = {}) { + const EOF = finalEOL ? EOL2 : ""; + const str = JSON.stringify(obj, replacer, spaces); + return str.replace(/\n/g, EOL2) + EOF; + } + function stripBom(content) { + if (Buffer.isBuffer(content)) + content = content.toString("utf8"); + return content.replace(/^\uFEFF/, ""); + } + module2.exports = { stringify: stringify3, stripBom }; + } +}); + +// node_modules/jsonfile/index.js +var require_jsonfile3 = __commonJS({ + "node_modules/jsonfile/index.js"(exports2, module2) { + var _fs; + try { + _fs = require_graceful_fs(); + } catch (_) { + _fs = require("fs"); + } + var universalify = require_universalify3(); + var { stringify: stringify3, stripBom } = require_utils(); + async function _readFile(file, options = {}) { + if (typeof options === "string") { + options = { encoding: options }; + } + const fs27 = options.fs || _fs; + const shouldThrow = "throws" in options ? options.throws : true; + let data = await universalify.fromCallback(fs27.readFile)(file, options); + data = stripBom(data); + let obj; + try { + obj = JSON.parse(data, options ? options.reviver : null); + } catch (err) { + if (shouldThrow) { + err.message = `${file}: ${err.message}`; + throw err; + } else { + return null; + } + } + return obj; + } + var readFile2 = universalify.fromPromise(_readFile); + function readFileSync(file, options = {}) { + if (typeof options === "string") { + options = { encoding: options }; + } + const fs27 = options.fs || _fs; + const shouldThrow = "throws" in options ? options.throws : true; + try { + let content = fs27.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; + } + } + } + async function _writeFile(file, obj, options = {}) { + const fs27 = options.fs || _fs; + const str = stringify3(obj, options); + await universalify.fromCallback(fs27.writeFile)(file, str, options); + } + var writeFile2 = universalify.fromPromise(_writeFile); + function writeFileSync(file, obj, options = {}) { + const fs27 = options.fs || _fs; + const str = stringify3(obj, options); + return fs27.writeFileSync(file, str, options); + } + var jsonfile = { + readFile: readFile2, + readFileSync, + writeFile: writeFile2, + writeFileSync + }; + module2.exports = jsonfile; + } +}); + +// node_modules/fs-extra/lib/json/jsonfile.js +var require_jsonfile4 = __commonJS({ + "node_modules/fs-extra/lib/json/jsonfile.js"(exports2, module2) { + "use strict"; + var jsonFile = require_jsonfile3(); + module2.exports = { + readJson: jsonFile.readFile, + readJsonSync: jsonFile.readFileSync, + writeJson: jsonFile.writeFile, + writeJsonSync: jsonFile.writeFileSync + }; + } +}); + +// node_modules/fs-extra/lib/output/index.js +var require_output2 = __commonJS({ + "node_modules/fs-extra/lib/output/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromCallback; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var mkdir = require_mkdirs3(); + var pathExists = require_path_exists2().pathExists; + function outputFile(file, data, encoding, callback) { + if (typeof encoding === "function") { + callback = encoding; + encoding = "utf8"; + } + const dir = path36.dirname(file); + pathExists(dir, (err, itDoes) => { + if (err) + return callback(err); + if (itDoes) + return fs27.writeFile(file, data, encoding, callback); + mkdir.mkdirs(dir, (err2) => { + if (err2) + return callback(err2); + fs27.writeFile(file, data, encoding, callback); + }); + }); + } + function outputFileSync(file, ...args) { + const dir = path36.dirname(file); + if (fs27.existsSync(dir)) { + return fs27.writeFileSync(file, ...args); + } + mkdir.mkdirsSync(dir); + fs27.writeFileSync(file, ...args); + } + module2.exports = { + outputFile: u(outputFile), + outputFileSync + }; + } +}); + +// node_modules/fs-extra/lib/json/output-json.js +var require_output_json2 = __commonJS({ + "node_modules/fs-extra/lib/json/output-json.js"(exports2, module2) { + "use strict"; + var { stringify: stringify3 } = require_utils(); + var { outputFile } = require_output2(); + async function outputJson(file, data, options = {}) { + const str = stringify3(data, options); + await outputFile(file, str, options); + } + module2.exports = outputJson; + } +}); + +// node_modules/fs-extra/lib/json/output-json-sync.js +var require_output_json_sync2 = __commonJS({ + "node_modules/fs-extra/lib/json/output-json-sync.js"(exports2, module2) { + "use strict"; + var { stringify: stringify3 } = require_utils(); + var { outputFileSync } = require_output2(); + function outputJsonSync(file, data, options) { + const str = stringify3(data, options); + outputFileSync(file, str, options); + } + module2.exports = outputJsonSync; + } +}); + +// node_modules/fs-extra/lib/json/index.js +var require_json2 = __commonJS({ + "node_modules/fs-extra/lib/json/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromPromise; + var jsonFile = require_jsonfile4(); + jsonFile.outputJson = u(require_output_json2()); + jsonFile.outputJsonSync = require_output_json_sync2(); + jsonFile.outputJSON = jsonFile.outputJson; + jsonFile.outputJSONSync = jsonFile.outputJsonSync; + jsonFile.writeJSON = jsonFile.writeJson; + jsonFile.writeJSONSync = jsonFile.writeJsonSync; + jsonFile.readJSON = jsonFile.readJson; + jsonFile.readJSONSync = jsonFile.readJsonSync; + module2.exports = jsonFile; + } +}); + +// node_modules/fs-extra/lib/move-sync/move-sync.js +var require_move_sync3 = __commonJS({ + "node_modules/fs-extra/lib/move-sync/move-sync.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var copySync = require_copy_sync4().copySync; + var removeSync = require_remove2().removeSync; + var mkdirpSync = require_mkdirs3().mkdirpSync; + var stat = require_stat2(); + 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(path36.dirname(dest)); + return doRename(src, dest, overwrite); + } + function doRename(src, dest, overwrite) { + if (overwrite) { + removeSync(dest); + return rename(src, dest, overwrite); + } + if (fs27.existsSync(dest)) + throw new Error("dest already exists."); + return rename(src, dest, overwrite); + } + function rename(src, dest, overwrite) { + try { + fs27.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); + } + module2.exports = moveSync; + } +}); + +// node_modules/fs-extra/lib/move-sync/index.js +var require_move_sync4 = __commonJS({ + "node_modules/fs-extra/lib/move-sync/index.js"(exports2, module2) { + "use strict"; + module2.exports = { + moveSync: require_move_sync3() + }; + } +}); + +// node_modules/fs-extra/lib/move/move.js +var require_move3 = __commonJS({ + "node_modules/fs-extra/lib/move/move.js"(exports2, module2) { + "use strict"; + var fs27 = require_graceful_fs(); + var path36 = require("path"); + var copy = require_copy4().copy; + var remove = require_remove2().remove; + var mkdirp = require_mkdirs3().mkdirp; + var pathExists = require_path_exists2().pathExists; + var stat = require_stat2(); + 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", (err2) => { + if (err2) + return cb(err2); + mkdirp(path36.dirname(dest), (err3) => { + if (err3) + return cb(err3); + 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) { + fs27.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); + }); + } + module2.exports = move; + } +}); + +// node_modules/fs-extra/lib/move/index.js +var require_move4 = __commonJS({ + "node_modules/fs-extra/lib/move/index.js"(exports2, module2) { + "use strict"; + var u = require_universalify2().fromCallback; + module2.exports = { + move: u(require_move3()) + }; + } +}); + +// node_modules/fs-extra/lib/index.js +var require_lib5 = __commonJS({ + "node_modules/fs-extra/lib/index.js"(exports2, module2) { + "use strict"; + module2.exports = __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, require_fs2()), require_copy_sync4()), require_copy4()), require_empty2()), require_ensure2()), require_json2()), require_mkdirs3()), require_move_sync4()), require_move4()), require_output2()), require_path_exists2()), require_remove2()); + var fs27 = require("fs"); + if (Object.getOwnPropertyDescriptor(fs27, "promises")) { + Object.defineProperty(module2.exports, "promises", { + get() { + return fs27.promises; + } + }); + } + } +}); + +// src/util/logger.ts +var require_logger2 = __commonJS({ + "src/util/logger.ts"(exports2, module2) { + var import_fs38 = __toModule(require("fs")); + var import_log4js2 = __toModule(require_log4js()); + var import_path38 = __toModule(require("path")); + var import_os10 = __toModule(require("os")); + var import_fs_extra10 = __toModule(require_lib5()); + function getLogFile() { + let file = process.env.NVIM_COC_LOG_FILE; + if (file) + return file; + let dir = process.env.XDG_RUNTIME_DIR; + if (dir) { + try { + import_fs38.default.accessSync(dir, import_fs38.default.constants.R_OK | import_fs38.default.constants.W_OK); + return import_path38.default.join(dir, `coc-nvim-${process.pid}.log`); + } catch (err) { + } + } + let tmpdir = import_os10.default.tmpdir(); + dir = import_path38.default.join(tmpdir, `coc.nvim-${process.pid}`); + if (!import_fs38.default.existsSync(dir)) + (0, import_fs_extra10.mkdirpSync)(dir); + return import_path38.default.join(dir, `coc-nvim.log`); + } + var MAX_LOG_SIZE = 1024 * 1024; + var MAX_LOG_BACKUPS = 10; + var logfile = getLogFile(); + var level = process.env.NVIM_COC_LOG_LEVEL || "info"; + if (import_fs38.default.existsSync(logfile)) { + try { + import_fs38.default.writeFileSync(logfile, "", { encoding: "utf8", mode: 438 }); + } catch (e) { + } + } + import_log4js2.default.configure({ + disableClustering: true, + appenders: { + out: { + type: "file", + mode: 438, + filename: logfile, + maxLogSize: MAX_LOG_SIZE, + backups: MAX_LOG_BACKUPS, + layout: { + type: "pattern", + pattern: `%d{ISO8601} %p (pid:${process.pid}) [%c] - %m` + } + } + }, + categories: { + default: { appenders: ["out"], level } + } + }); + module2.exports = (name2 = "coc-nvim") => { + let logger113 = import_log4js2.default.getLogger(name2); + logger113.getLogFile = () => logfile; + return logger113; + }; + } +}); + +// src/util/extensions.ts +var require_extensions = __commonJS({ + "src/util/extensions.ts"() { + Promise.prototype.logError = function() { + this.catch((e) => { + require_logger2()("extensions").error(e); + }); + }; + } +}); + +// node_modules/msgpack-lite/lib/buffer-global.js +var require_buffer_global = __commonJS({ + "node_modules/msgpack-lite/lib/buffer-global.js"(exports2, module2) { + module2.exports = c(typeof Buffer !== "undefined" && Buffer) || c(exports2.Buffer) || c(typeof window !== "undefined" && window.Buffer) || exports2.Buffer; + function c(B) { + return B && B.isBuffer && B; + } + } +}); + +// node_modules/isarray/index.js +var require_isarray = __commonJS({ + "node_modules/isarray/index.js"(exports2, module2) { + var toString = {}.toString; + module2.exports = Array.isArray || function(arr) { + return toString.call(arr) == "[object Array]"; + }; + } +}); + +// node_modules/msgpack-lite/lib/bufferish-array.js +var require_bufferish_array = __commonJS({ + "node_modules/msgpack-lite/lib/bufferish-array.js"(exports2, module2) { + var Bufferish = require_bufferish(); + var exports2 = module2.exports = alloc(0); + exports2.alloc = alloc; + exports2.concat = Bufferish.concat; + exports2.from = from; + function alloc(size) { + return new Array(size); + } + function from(value) { + if (!Bufferish.isBuffer(value) && Bufferish.isView(value)) { + value = Bufferish.Uint8Array.from(value); + } else if (Bufferish.isArrayBuffer(value)) { + value = new Uint8Array(value); + } else if (typeof value === "string") { + return Bufferish.from.call(exports2, value); + } else if (typeof value === "number") { + throw new TypeError('"value" argument must not be a number'); + } + return Array.prototype.slice.call(value); + } + } +}); + +// node_modules/msgpack-lite/lib/bufferish-buffer.js +var require_bufferish_buffer = __commonJS({ + "node_modules/msgpack-lite/lib/bufferish-buffer.js"(exports2, module2) { + var Bufferish = require_bufferish(); + var Buffer4 = Bufferish.global; + var exports2 = module2.exports = Bufferish.hasBuffer ? alloc(0) : []; + exports2.alloc = Bufferish.hasBuffer && Buffer4.alloc || alloc; + exports2.concat = Bufferish.concat; + exports2.from = from; + function alloc(size) { + return new Buffer4(size); + } + function from(value) { + if (!Bufferish.isBuffer(value) && Bufferish.isView(value)) { + value = Bufferish.Uint8Array.from(value); + } else if (Bufferish.isArrayBuffer(value)) { + value = new Uint8Array(value); + } else if (typeof value === "string") { + return Bufferish.from.call(exports2, value); + } else if (typeof value === "number") { + throw new TypeError('"value" argument must not be a number'); + } + if (Buffer4.from && Buffer4.from.length !== 1) { + return Buffer4.from(value); + } else { + return new Buffer4(value); + } + } + } +}); + +// node_modules/msgpack-lite/lib/bufferish-uint8array.js +var require_bufferish_uint8array = __commonJS({ + "node_modules/msgpack-lite/lib/bufferish-uint8array.js"(exports2, module2) { + var Bufferish = require_bufferish(); + var exports2 = module2.exports = Bufferish.hasArrayBuffer ? alloc(0) : []; + exports2.alloc = alloc; + exports2.concat = Bufferish.concat; + exports2.from = from; + function alloc(size) { + return new Uint8Array(size); + } + function from(value) { + if (Bufferish.isView(value)) { + var byteOffset = value.byteOffset; + var byteLength2 = value.byteLength; + value = value.buffer; + if (value.byteLength !== byteLength2) { + if (value.slice) { + value = value.slice(byteOffset, byteOffset + byteLength2); + } else { + value = new Uint8Array(value); + if (value.byteLength !== byteLength2) { + value = Array.prototype.slice.call(value, byteOffset, byteOffset + byteLength2); + } + } + } + } else if (typeof value === "string") { + return Bufferish.from.call(exports2, value); + } else if (typeof value === "number") { + throw new TypeError('"value" argument must not be a number'); + } + return new Uint8Array(value); + } + } +}); + +// node_modules/msgpack-lite/lib/buffer-lite.js +var require_buffer_lite = __commonJS({ + "node_modules/msgpack-lite/lib/buffer-lite.js"(exports2) { + exports2.copy = copy; + exports2.toString = toString; + exports2.write = write; + function write(string2, offset) { + var buffer = this; + var index = offset || (offset |= 0); + var length = string2.length; + var chr = 0; + var i = 0; + while (i < length) { + chr = string2.charCodeAt(i++); + if (chr < 128) { + buffer[index++] = chr; + } else if (chr < 2048) { + buffer[index++] = 192 | chr >>> 6; + buffer[index++] = 128 | chr & 63; + } else if (chr < 55296 || chr > 57343) { + buffer[index++] = 224 | chr >>> 12; + buffer[index++] = 128 | chr >>> 6 & 63; + buffer[index++] = 128 | chr & 63; + } else { + chr = (chr - 55296 << 10 | string2.charCodeAt(i++) - 56320) + 65536; + buffer[index++] = 240 | chr >>> 18; + buffer[index++] = 128 | chr >>> 12 & 63; + buffer[index++] = 128 | chr >>> 6 & 63; + buffer[index++] = 128 | chr & 63; + } + } + return index - offset; + } + function toString(encoding, start, end) { + var buffer = this; + var index = start | 0; + if (!end) + end = buffer.length; + var string2 = ""; + var chr = 0; + while (index < end) { + chr = buffer[index++]; + if (chr < 128) { + string2 += String.fromCharCode(chr); + continue; + } + if ((chr & 224) === 192) { + chr = (chr & 31) << 6 | buffer[index++] & 63; + } else if ((chr & 240) === 224) { + chr = (chr & 15) << 12 | (buffer[index++] & 63) << 6 | buffer[index++] & 63; + } else if ((chr & 248) === 240) { + chr = (chr & 7) << 18 | (buffer[index++] & 63) << 12 | (buffer[index++] & 63) << 6 | buffer[index++] & 63; + } + if (chr >= 65536) { + chr -= 65536; + string2 += String.fromCharCode((chr >>> 10) + 55296, (chr & 1023) + 56320); + } else { + string2 += String.fromCharCode(chr); + } + } + return string2; + } + 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) { + for (i = len - 1; i >= 0; i--) { + target[i + targetStart] = this[i + start]; + } + } else { + for (i = 0; i < len; i++) { + target[i + targetStart] = this[i + start]; + } + } + return len; + } + } +}); + +// node_modules/msgpack-lite/lib/bufferish-proto.js +var require_bufferish_proto = __commonJS({ + "node_modules/msgpack-lite/lib/bufferish-proto.js"(exports2) { + var BufferLite = require_buffer_lite(); + exports2.copy = copy; + exports2.slice = slice; + exports2.toString = toString; + exports2.write = gen("write"); + var Bufferish = require_bufferish(); + var Buffer4 = Bufferish.global; + var isBufferShim = Bufferish.hasBuffer && "TYPED_ARRAY_SUPPORT" in Buffer4; + var brokenTypedArray = isBufferShim && !Buffer4.TYPED_ARRAY_SUPPORT; + function copy(target, targetStart, start, end) { + var thisIsBuffer = Bufferish.isBuffer(this); + var targetIsBuffer = Bufferish.isBuffer(target); + if (thisIsBuffer && targetIsBuffer) { + return this.copy(target, targetStart, start, end); + } else if (!brokenTypedArray && !thisIsBuffer && !targetIsBuffer && Bufferish.isView(this) && Bufferish.isView(target)) { + var buffer = start || end != null ? slice.call(this, start, end) : this; + target.set(buffer, targetStart); + return buffer.length; + } else { + return BufferLite.copy.call(this, target, targetStart, start, end); + } + } + function slice(start, end) { + var f = this.slice || !brokenTypedArray && this.subarray; + if (f) + return f.call(this, start, end); + var target = Bufferish.alloc.call(this, end - start); + copy.call(this, target, 0, start, end); + return target; + } + function toString(encoding, start, end) { + var f = !isBufferShim && Bufferish.isBuffer(this) ? this.toString : BufferLite.toString; + return f.apply(this, arguments); + } + function gen(method) { + return wrap; + function wrap() { + var f = this[method] || BufferLite[method]; + return f.apply(this, arguments); + } + } + } +}); + +// node_modules/msgpack-lite/lib/bufferish.js +var require_bufferish = __commonJS({ + "node_modules/msgpack-lite/lib/bufferish.js"(exports2) { + var Buffer4 = exports2.global = require_buffer_global(); + var hasBuffer = exports2.hasBuffer = Buffer4 && !!Buffer4.isBuffer; + var hasArrayBuffer = exports2.hasArrayBuffer = typeof ArrayBuffer !== "undefined"; + var isArray = exports2.isArray = require_isarray(); + exports2.isArrayBuffer = hasArrayBuffer ? isArrayBuffer : _false; + var isBuffer = exports2.isBuffer = hasBuffer ? Buffer4.isBuffer : _false; + var isView = exports2.isView = hasArrayBuffer ? ArrayBuffer.isView || _is("ArrayBuffer", "buffer") : _false; + exports2.alloc = alloc; + exports2.concat = concat; + exports2.from = from; + var BufferArray = exports2.Array = require_bufferish_array(); + var BufferBuffer = exports2.Buffer = require_bufferish_buffer(); + var BufferUint8Array = exports2.Uint8Array = require_bufferish_uint8array(); + var BufferProto = exports2.prototype = require_bufferish_proto(); + function from(value) { + if (typeof value === "string") { + return fromString.call(this, value); + } else { + return auto(this).from(value); + } + } + function alloc(size) { + return auto(this).alloc(size); + } + function concat(list2, length) { + if (!length) { + length = 0; + Array.prototype.forEach.call(list2, dryrun); + } + var ref = this !== exports2 && this || list2[0]; + var result = alloc.call(ref, length); + var offset = 0; + Array.prototype.forEach.call(list2, 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); + } + 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(name2, key) { + name2 = "[object " + name2 + "]"; + return function(value) { + return value != null && {}.toString.call(key ? value[key] : value) === name2; + }; + } + } +}); + +// node_modules/msgpack-lite/lib/ext-buffer.js +var require_ext_buffer = __commonJS({ + "node_modules/msgpack-lite/lib/ext-buffer.js"(exports2) { + exports2.ExtBuffer = ExtBuffer; + var Bufferish = require_bufferish(); + function ExtBuffer(buffer, type) { + if (!(this instanceof ExtBuffer)) + return new ExtBuffer(buffer, type); + this.buffer = Bufferish.from(buffer); + this.type = type; + } + } +}); + +// node_modules/msgpack-lite/lib/ext-packer.js +var require_ext_packer = __commonJS({ + "node_modules/msgpack-lite/lib/ext-packer.js"(exports2) { + exports2.setExtPackers = setExtPackers; + var Bufferish = require_bufferish(); + var Buffer4 = 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(14, Error, [packError, encode]); + codec.addExtPacker(1, EvalError, [packError, encode]); + codec.addExtPacker(2, RangeError, [packError, encode]); + codec.addExtPacker(3, ReferenceError, [packError, encode]); + codec.addExtPacker(4, SyntaxError, [packError, encode]); + codec.addExtPacker(5, TypeError, [packError, encode]); + codec.addExtPacker(6, URIError, [packError, encode]); + codec.addExtPacker(10, RegExp, [packRegExp, encode]); + codec.addExtPacker(11, Boolean, [packValueOf, encode]); + codec.addExtPacker(12, String, [packValueOf, encode]); + codec.addExtPacker(13, Date, [Number, encode]); + codec.addExtPacker(15, Number, [packValueOf, encode]); + if (typeof Uint8Array !== "undefined") { + codec.addExtPacker(17, Int8Array, packTypedArray); + codec.addExtPacker(18, Uint8Array, packTypedArray); + codec.addExtPacker(19, Int16Array, packTypedArray); + codec.addExtPacker(20, Uint16Array, packTypedArray); + codec.addExtPacker(21, Int32Array, packTypedArray); + codec.addExtPacker(22, Uint32Array, packTypedArray); + codec.addExtPacker(23, Float32Array, packTypedArray); + if (typeof Float64Array !== "undefined") { + codec.addExtPacker(24, Float64Array, packTypedArray); + } + if (typeof Uint8ClampedArray !== "undefined") { + codec.addExtPacker(25, Uint8ClampedArray, packTypedArray); + } + codec.addExtPacker(26, ArrayBuffer, packTypedArray); + codec.addExtPacker(29, DataView, packTypedArray); + } + if (Bufferish.hasBuffer) { + codec.addExtPacker(27, Buffer4, Bufferish.from); + } + } + function encode(input) { + if (!_encode) + _encode = require_encode().encode; + 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; + } + } +}); + +// node_modules/int64-buffer/int64-buffer.js +var require_int64_buffer = __commonJS({ + "node_modules/int64-buffer/int64-buffer.js"(exports2) { + var Uint64BE; + var Int64BE; + var Uint64LE; + var Int64LE; + !function(exports3) { + 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; + var storage; + Uint64BE = factory("Uint64BE", true, true); + Int64BE = factory("Int64BE", true, false); + Uint64LE = factory("Uint64LE", false, true); + Int64LE = factory("Int64LE", false, false); + function factory(name2, 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" + name2; + var _isInt64 = "_" + isName; + proto.buffer = void 0; + proto.offset = 0; + proto[_isInt64] = true; + proto.toNumber = toNumber; + proto.toString = toString; + proto.toJSON = toNumber; + proto.toArray = toArray; + if (BUFFER) + proto.toBuffer = toBuffer; + if (UINT8ARRAY) + proto.toArrayBuffer = toArrayBuffer; + Int64[isName] = isInt64; + exports3[name2] = Int64; + return Int64; + function Int64(buffer, offset, value, raddix) { + if (!(this instanceof Int64)) + return new Int64(buffer, offset, value, raddix); + return init(this, buffer, offset, value, raddix); + } + function isInt64(b) { + return !!(b && b[_isInt64]); + } + 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); + } + if (!buffer && !offset && !value && !storage) { + that.buffer = newArray(ZERO, 0); + return; + } + 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; + if (UNDEFINED === typeof value) + return; + if (typeof value === "string") { + fromString(buffer, offset, value, raddix || 10); + } else if (isValidBuffer(value, raddix)) { + fromArray(buffer, offset, value, raddix); + } else if (typeof raddix === "number") { + writeInt32(buffer, offset + posH, value); + writeInt32(buffer, offset + posL, raddix); + } else if (value > 0) { + fromPositive(buffer, offset, value); + } else if (value < 0) { + fromNegative(buffer, offset, value); + } else { + fromArray(buffer, offset, ZERO, 0); + } + } + 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; + 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; + 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 & 2147483648; + 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; + 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 && typeof buffer[offset] !== "string"; + } + 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; + } + } + function _isArray(val) { + return !!val && Object.prototype.toString.call(val) == "[object Array]"; + } + }(typeof exports2 === "object" && typeof exports2.nodeName !== "string" ? exports2 : exports2 || {}); + } +}); + +// node_modules/ieee754/index.js +var require_ieee754 = __commonJS({ + "node_modules/ieee754/index.js"(exports2) { + exports2.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); + }; + exports2.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 & 255, i += d, m /= 256, mLen -= 8) { + } + e = e << mLen | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 255, i += d, e /= 256, eLen -= 8) { + } + buffer[offset + i - d] |= s * 128; + }; + } +}); + +// node_modules/msgpack-lite/lib/write-uint8.js +var require_write_uint8 = __commonJS({ + "node_modules/msgpack-lite/lib/write-uint8.js"(exports2) { + var constant = exports2.uint8 = new Array(256); + for (var i = 0; i <= 255; i++) { + constant[i] = write0(i); + } + function write0(type) { + return function(encoder) { + var offset = encoder.reserve(1); + encoder.buffer[offset] = type; + }; + } + } +}); + +// node_modules/msgpack-lite/lib/write-token.js +var require_write_token = __commonJS({ + "node_modules/msgpack-lite/lib/write-token.js"(exports2) { + var ieee754 = require_ieee754(); + var Int64Buffer = require_int64_buffer(); + var Uint64BE = Int64Buffer.Uint64BE; + var Int64BE = Int64Buffer.Int64BE; + var uint8 = require_write_uint8().uint8; + var Bufferish = require_bufferish(); + var Buffer4 = Bufferish.global; + var IS_BUFFER_SHIM = Bufferish.hasBuffer && "TYPED_ARRAY_SUPPORT" in Buffer4; + var NO_TYPED_ARRAY = IS_BUFFER_SHIM && !Buffer4.TYPED_ARRAY_SUPPORT; + var Buffer_prototype = Bufferish.hasBuffer && Buffer4.prototype || {}; + exports2.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(); + token[202] = writeN(202, 4, writeFloatBE); + token[203] = writeN(203, 8, writeDoubleBE); + return token; + } + function init_token() { + var token = uint8.slice(); + token[196] = write1(196); + token[197] = write2(197); + token[198] = write4(198); + token[199] = write1(199); + token[200] = write2(200); + token[201] = write4(201); + token[202] = writeN(202, 4, Buffer_prototype.writeFloatBE || writeFloatBE, true); + token[203] = writeN(203, 8, Buffer_prototype.writeDoubleBE || writeDoubleBE, true); + token[204] = write1(204); + token[205] = write2(205); + token[206] = write4(206); + token[207] = writeN(207, 8, writeUInt64BE); + token[208] = write1(208); + token[209] = write2(209); + token[210] = write4(210); + token[211] = writeN(211, 8, writeInt64BE); + token[217] = write1(217); + token[218] = write2(218); + token[219] = write4(219); + token[220] = write2(220); + token[221] = write4(221); + token[222] = write2(222); + token[223] = write4(223); + return token; + } + function init_safe() { + var token = uint8.slice(); + token[196] = writeN(196, 1, Buffer4.prototype.writeUInt8); + token[197] = writeN(197, 2, Buffer4.prototype.writeUInt16BE); + token[198] = writeN(198, 4, Buffer4.prototype.writeUInt32BE); + token[199] = writeN(199, 1, Buffer4.prototype.writeUInt8); + token[200] = writeN(200, 2, Buffer4.prototype.writeUInt16BE); + token[201] = writeN(201, 4, Buffer4.prototype.writeUInt32BE); + token[202] = writeN(202, 4, Buffer4.prototype.writeFloatBE); + token[203] = writeN(203, 8, Buffer4.prototype.writeDoubleBE); + token[204] = writeN(204, 1, Buffer4.prototype.writeUInt8); + token[205] = writeN(205, 2, Buffer4.prototype.writeUInt16BE); + token[206] = writeN(206, 4, Buffer4.prototype.writeUInt32BE); + token[207] = writeN(207, 8, writeUInt64BE); + token[208] = writeN(208, 1, Buffer4.prototype.writeInt8); + token[209] = writeN(209, 2, Buffer4.prototype.writeInt16BE); + token[210] = writeN(210, 4, Buffer4.prototype.writeInt32BE); + token[211] = writeN(211, 8, writeInt64BE); + token[217] = writeN(217, 1, Buffer4.prototype.writeUInt8); + token[218] = writeN(218, 2, Buffer4.prototype.writeUInt16BE); + token[219] = writeN(219, 4, Buffer4.prototype.writeUInt32BE); + token[220] = writeN(220, 2, Buffer4.prototype.writeUInt16BE); + token[221] = writeN(221, 4, Buffer4.prototype.writeUInt32BE); + token[222] = writeN(222, 2, Buffer4.prototype.writeUInt16BE); + token[223] = writeN(223, 4, Buffer4.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); + } + } +}); + +// node_modules/msgpack-lite/lib/write-type.js +var require_write_type = __commonJS({ + "node_modules/msgpack-lite/lib/write-type.js"(exports2) { + var IS_ARRAY = require_isarray(); + var Int64Buffer = require_int64_buffer(); + var Uint64BE = Int64Buffer.Uint64BE; + var Int64BE = Int64Buffer.Int64BE; + var Bufferish = require_bufferish(); + var BufferProto = require_bufferish_proto(); + var WriteToken = require_write_token(); + var uint8 = require_write_uint8().uint8; + var ExtBuffer = require_ext_buffer().ExtBuffer; + var HAS_UINT8ARRAY = typeof Uint8Array !== "undefined"; + var HAS_MAP = typeof Map !== "undefined"; + var extmap = []; + extmap[1] = 212; + extmap[2] = 213; + extmap[4] = 214; + extmap[8] = 215; + extmap[16] = 216; + exports2.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": number2, + "object": useraw ? object_raw : object, + "string": _string(useraw ? raw_head_size : str_head_size), + "symbol": nil, + "undefined": nil + }; + return writeType; + function bool(encoder, value) { + var type = value ? 195 : 194; + token[type](encoder, value); + } + function number2(encoder, value) { + var ivalue = value | 0; + var type; + if (value !== ivalue) { + type = 203; + token[type](encoder, value); + return; + } else if (-32 <= ivalue && ivalue <= 127) { + type = ivalue & 255; + } else if (0 <= ivalue) { + type = ivalue <= 255 ? 204 : ivalue <= 65535 ? 205 : 206; + } else { + type = -128 <= ivalue ? 208 : -32768 <= ivalue ? 209 : 210; + } + token[type](encoder, ivalue); + } + function uint64(encoder, value) { + var type = 207; + token[type](encoder, value.toArray()); + } + function int64(encoder, value) { + var type = 211; + token[type](encoder, value.toArray()); + } + function str_head_size(length) { + return length < 32 ? 1 : length <= 255 ? 2 : length <= 65535 ? 3 : 5; + } + function raw_head_size(length) { + return length < 32 ? 1 : length <= 65535 ? 3 : 5; + } + function _string(head_size) { + return string2; + function string2(encoder, value) { + var length = value.length; + var maxsize = 5 + length * 3; + encoder.offset = encoder.reserve(maxsize); + var buffer = encoder.buffer; + var expected = head_size(length); + var start = encoder.offset + expected; + length = BufferProto.write.call(buffer, value, start); + var actual = head_size(length); + if (expected !== actual) { + var targetStart = start + actual - expected; + var end = start + length; + BufferProto.copy.call(buffer, buffer, targetStart, start, end); + } + var type = actual === 1 ? 160 + length : actual <= 3 ? 215 + actual : 219; + token[type](encoder, length); + encoder.offset += length; + } + } + function object(encoder, value) { + if (value === null) + return nil(encoder, value); + if (isBuffer(value)) + return bin(encoder, value); + if (IS_ARRAY(value)) + return array(encoder, value); + if (Uint64BE.isUint64BE(value)) + return uint64(encoder, value); + if (Int64BE.isInt64BE(value)) + return int64(encoder, value); + var packer = encoder.codec.getExtPacker(value); + if (packer) + value = packer(value); + if (value instanceof ExtBuffer) + return ext(encoder, value); + map(encoder, value); + } + function object_raw(encoder, value) { + if (isBuffer(value)) + return raw(encoder, value); + object(encoder, value); + } + function nil(encoder, value) { + var type = 192; + token[type](encoder, value); + } + function array(encoder, value) { + var length = value.length; + var type = length < 16 ? 144 + length : length <= 65535 ? 220 : 221; + token[type](encoder, length); + var encode = encoder.codec.encode; + for (var i = 0; i < length; i++) { + encode(encoder, value[i]); + } + } + function bin_buffer(encoder, value) { + var length = value.length; + var type = length < 255 ? 196 : length <= 65535 ? 197 : 198; + token[type](encoder, length); + encoder.send(value); + } + function bin_arraybuffer(encoder, value) { + bin_buffer(encoder, new Uint8Array(value)); + } + function ext(encoder, value) { + var buffer = value.buffer; + var length = buffer.length; + var type = extmap[length] || (length < 255 ? 199 : length <= 65535 ? 200 : 201); + token[type](encoder, length); + uint8[value.type](encoder); + encoder.send(buffer); + } + function obj_to_map(encoder, value) { + var keys = Object.keys(value); + var length = keys.length; + var type = length < 16 ? 128 + length : length <= 65535 ? 222 : 223; + token[type](encoder, length); + var encode = encoder.codec.encode; + keys.forEach(function(key) { + encode(encoder, key); + encode(encoder, value[key]); + }); + } + function map_to_map(encoder, value) { + if (!(value instanceof Map)) + return obj_to_map(encoder, value); + var length = value.size; + var type = length < 16 ? 128 + length : length <= 65535 ? 222 : 223; + token[type](encoder, length); + var encode = encoder.codec.encode; + value.forEach(function(val, key, m) { + encode(encoder, key); + encode(encoder, val); + }); + } + function raw(encoder, value) { + var length = value.length; + var type = length < 32 ? 160 + length : length <= 65535 ? 218 : 219; + token[type](encoder, length); + encoder.send(value); + } + } + } +}); + +// node_modules/msgpack-lite/lib/codec-base.js +var require_codec_base = __commonJS({ + "node_modules/msgpack-lite/lib/codec-base.js"(exports2) { + var IS_ARRAY = require_isarray(); + exports2.createCodec = createCodec; + exports2.install = install; + exports2.filter = filter; + var Bufferish = require_bufferish(); + 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 join2(filters) { + filters = filters.slice(); + return function(value) { + return filters.reduce(iterator, value); + }; + function iterator(value, filter2) { + return filter2(value); + } + } + function filter(filter2) { + return IS_ARRAY(filter2) ? join2(filter2) : filter2; + } + function createCodec(options) { + return new Codec(options); + } + exports2.preset = createCodec({ preset: true }); + } +}); + +// node_modules/msgpack-lite/lib/write-core.js +var require_write_core = __commonJS({ + "node_modules/msgpack-lite/lib/write-core.js"(exports2) { + var ExtBuffer = require_ext_buffer().ExtBuffer; + var ExtPacker = require_ext_packer(); + var WriteType = require_write_type(); + var CodecBase = require_codec_base(); + CodecBase.install({ + addExtPacker, + getExtPacker, + init + }); + exports2.preset = init.call(CodecBase.preset); + function getEncoder(options) { + var writeType = WriteType.getWriteType(options); + return encode; + function encode(encoder, value) { + var func2 = writeType[typeof value]; + if (!func2) + throw new Error('Unsupported type "' + typeof value + '": ' + value); + func2(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 name2 = Class.name; + if (name2 && name2 !== "Object") { + var packers = this.extPackers || (this.extPackers = {}); + packers[name2] = extPacker; + } else { + var list2 = this.extEncoderList || (this.extEncoderList = []); + list2.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; + var list2 = this.extEncoderList || (this.extEncoderList = []); + var len = list2.length; + for (var i = 0; i < len; i++) { + var pair = list2[i]; + if (c === pair[0]) + return pair[1]; + } + } + } +}); + +// node_modules/msgpack-lite/lib/flex-buffer.js +var require_flex_buffer = __commonJS({ + "node_modules/msgpack-lite/lib/flex-buffer.js"(exports2) { + exports2.FlexDecoder = FlexDecoder; + exports2.FlexEncoder = FlexEncoder; + var Bufferish = require_bufferish(); + 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: write2, + fetch: fetch2, + flush, + push, + pull, + read, + reserve, + offset: 0 + }; + function write2(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; + 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, + fetch: fetch3, + flush, + push, + pull: pull2, + read, + reserve, + send, + maxBufferSize: MAX_BUFFER_SIZE, + minBufferSize: MIN_BUFFER_SIZE, + offset: 0, + start: 0 + }; + function fetch3() { + 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 pull2() { + var buffers = this.buffers || (this.buffers = []); + var chunk = buffers.length > 1 ? this.bufferish.concat(buffers) : buffers[0]; + buffers.length = 0; + 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; + if (end < size) { + this.offset = end; + return start; + } + this.flush(); + length = Math.max(length, Math.min(size * 2, this.maxBufferSize)); + } + length = Math.max(length, this.minBufferSize); + 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); + } + } + } + function write() { + throw new Error("method not implemented: write()"); + } + function fetch2() { + throw new Error("method not implemented: fetch()"); + } + function read() { + var length = this.buffers && this.buffers.length; + if (!length) + return this.fetch(); + this.flush(); + 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 mixin2; + function mixin2(target) { + for (var key in source) { + target[key] = source[key]; + } + return target; + } + } + } +}); + +// node_modules/msgpack-lite/lib/encode-buffer.js +var require_encode_buffer = __commonJS({ + "node_modules/msgpack-lite/lib/encode-buffer.js"(exports2) { + exports2.EncodeBuffer = EncodeBuffer; + var preset = require_write_core().preset; + var FlexEncoder = require_flex_buffer().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); + }; + } +}); + +// node_modules/msgpack-lite/lib/encode.js +var require_encode = __commonJS({ + "node_modules/msgpack-lite/lib/encode.js"(exports2) { + exports2.encode = encode; + var EncodeBuffer = require_encode_buffer().EncodeBuffer; + function encode(input, options) { + var encoder = new EncodeBuffer(options); + encoder.write(input); + return encoder.read(); + } + } +}); + +// node_modules/msgpack-lite/lib/ext-unpacker.js +var require_ext_unpacker = __commonJS({ + "node_modules/msgpack-lite/lib/ext-unpacker.js"(exports2) { + exports2.setExtUnpackers = setExtUnpackers; + var Bufferish = require_bufferish(); + var Buffer4 = Bufferish.global; + var _decode; + var ERROR_COLUMNS = { name: 1, message: 1, stack: 1, columnNumber: 1, fileName: 1, lineNumber: 1 }; + function setExtUnpackers(codec) { + codec.addExtUnpacker(14, [decode, unpackError(Error)]); + codec.addExtUnpacker(1, [decode, unpackError(EvalError)]); + codec.addExtUnpacker(2, [decode, unpackError(RangeError)]); + codec.addExtUnpacker(3, [decode, unpackError(ReferenceError)]); + codec.addExtUnpacker(4, [decode, unpackError(SyntaxError)]); + codec.addExtUnpacker(5, [decode, unpackError(TypeError)]); + codec.addExtUnpacker(6, [decode, unpackError(URIError)]); + codec.addExtUnpacker(10, [decode, unpackRegExp]); + codec.addExtUnpacker(11, [decode, unpackClass(Boolean)]); + codec.addExtUnpacker(12, [decode, unpackClass(String)]); + codec.addExtUnpacker(13, [decode, unpackClass(Date)]); + codec.addExtUnpacker(15, [decode, unpackClass(Number)]); + if (typeof Uint8Array !== "undefined") { + codec.addExtUnpacker(17, unpackClass(Int8Array)); + codec.addExtUnpacker(18, unpackClass(Uint8Array)); + codec.addExtUnpacker(19, [unpackArrayBuffer, unpackClass(Int16Array)]); + codec.addExtUnpacker(20, [unpackArrayBuffer, unpackClass(Uint16Array)]); + codec.addExtUnpacker(21, [unpackArrayBuffer, unpackClass(Int32Array)]); + codec.addExtUnpacker(22, [unpackArrayBuffer, unpackClass(Uint32Array)]); + codec.addExtUnpacker(23, [unpackArrayBuffer, unpackClass(Float32Array)]); + if (typeof Float64Array !== "undefined") { + codec.addExtUnpacker(24, [unpackArrayBuffer, unpackClass(Float64Array)]); + } + if (typeof Uint8ClampedArray !== "undefined") { + codec.addExtUnpacker(25, unpackClass(Uint8ClampedArray)); + } + codec.addExtUnpacker(26, unpackArrayBuffer); + codec.addExtUnpacker(29, [unpackArrayBuffer, unpackClass(DataView)]); + } + if (Bufferish.hasBuffer) { + codec.addExtUnpacker(27, unpackClass(Buffer4)); + } + } + function decode(input) { + if (!_decode) + _decode = require_decode().decode; + 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; + } + } +}); + +// node_modules/msgpack-lite/lib/read-format.js +var require_read_format = __commonJS({ + "node_modules/msgpack-lite/lib/read-format.js"(exports2) { + var ieee754 = require_ieee754(); + var Int64Buffer = require_int64_buffer(); + var Uint64BE = Int64Buffer.Uint64BE; + var Int64BE = Int64Buffer.Int64BE; + exports2.getReadFormat = getReadFormat; + exports2.readUint8 = uint8; + var Bufferish = require_bufferish(); + var BufferProto = require_bufferish_proto(); + var HAS_MAP = typeof Map !== "undefined"; + 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, + str, + bin: binarraybuffer ? bin_arraybuffer : bin_buffer, + ext, + uint8, + uint16, + uint32, + uint64: read(8, int64 ? readUInt64BE_int64 : readUInt64BE), + int8, + int16, + 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 & 128 ? value - 256 : 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 & 32768 ? value - 65536 : 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); + } + } +}); + +// node_modules/msgpack-lite/lib/read-token.js +var require_read_token = __commonJS({ + "node_modules/msgpack-lite/lib/read-token.js"(exports2) { + var ReadFormat = require_read_format(); + exports2.getReadToken = getReadToken; + function getReadToken(options) { + var format2 = ReadFormat.getReadFormat(options); + if (options && options.useraw) { + return init_useraw(format2); + } else { + return init_token(format2); + } + } + function init_token(format2) { + var i; + var token = new Array(256); + for (i = 0; i <= 127; i++) { + token[i] = constant(i); + } + for (i = 128; i <= 143; i++) { + token[i] = fix(i - 128, format2.map); + } + for (i = 144; i <= 159; i++) { + token[i] = fix(i - 144, format2.array); + } + for (i = 160; i <= 191; i++) { + token[i] = fix(i - 160, format2.str); + } + token[192] = constant(null); + token[193] = null; + token[194] = constant(false); + token[195] = constant(true); + token[196] = flex(format2.uint8, format2.bin); + token[197] = flex(format2.uint16, format2.bin); + token[198] = flex(format2.uint32, format2.bin); + token[199] = flex(format2.uint8, format2.ext); + token[200] = flex(format2.uint16, format2.ext); + token[201] = flex(format2.uint32, format2.ext); + token[202] = format2.float32; + token[203] = format2.float64; + token[204] = format2.uint8; + token[205] = format2.uint16; + token[206] = format2.uint32; + token[207] = format2.uint64; + token[208] = format2.int8; + token[209] = format2.int16; + token[210] = format2.int32; + token[211] = format2.int64; + token[212] = fix(1, format2.ext); + token[213] = fix(2, format2.ext); + token[214] = fix(4, format2.ext); + token[215] = fix(8, format2.ext); + token[216] = fix(16, format2.ext); + token[217] = flex(format2.uint8, format2.str); + token[218] = flex(format2.uint16, format2.str); + token[219] = flex(format2.uint32, format2.str); + token[220] = flex(format2.uint16, format2.array); + token[221] = flex(format2.uint32, format2.array); + token[222] = flex(format2.uint16, format2.map); + token[223] = flex(format2.uint32, format2.map); + for (i = 224; i <= 255; i++) { + token[i] = constant(i - 256); + } + return token; + } + function init_useraw(format2) { + var i; + var token = init_token(format2).slice(); + token[217] = token[196]; + token[218] = token[197]; + token[219] = token[198]; + for (i = 160; i <= 191; i++) { + token[i] = fix(i - 160, format2.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); + }; + } + } +}); + +// node_modules/msgpack-lite/lib/read-core.js +var require_read_core = __commonJS({ + "node_modules/msgpack-lite/lib/read-core.js"(exports2) { + var ExtBuffer = require_ext_buffer().ExtBuffer; + var ExtUnpacker = require_ext_unpacker(); + var readUint8 = require_read_format().readUint8; + var ReadToken = require_read_token(); + var CodecBase = require_codec_base(); + CodecBase.install({ + addExtUnpacker, + getExtUnpacker, + init + }); + exports2.preset = init.call(CodecBase.preset); + function getDecoder(options) { + var readToken = ReadToken.getReadToken(options); + return decode; + function decode(decoder) { + var type = readUint8(decoder); + var func2 = readToken[type]; + if (!func2) + throw new Error("Invalid type: " + (type ? "0x" + type.toString(16) : type)); + return func2(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); + } + } + } +}); + +// node_modules/msgpack-lite/lib/decode-buffer.js +var require_decode_buffer = __commonJS({ + "node_modules/msgpack-lite/lib/decode-buffer.js"(exports2) { + exports2.DecodeBuffer = DecodeBuffer; + var preset = require_read_core().preset; + var FlexDecoder = require_flex_buffer().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); + }; + } +}); + +// node_modules/msgpack-lite/lib/decode.js +var require_decode = __commonJS({ + "node_modules/msgpack-lite/lib/decode.js"(exports2) { + exports2.decode = decode; + var DecodeBuffer = require_decode_buffer().DecodeBuffer; + function decode(input, options) { + var decoder = new DecodeBuffer(options); + decoder.write(input); + return decoder.read(); + } + } +}); + +// node_modules/event-lite/event-lite.js +var require_event_lite = __commonJS({ + "node_modules/event-lite/event-lite.js"(exports2, module2) { + function EventLite() { + if (!(this instanceof EventLite)) + return new EventLite(); + } + (function(EventLite2) { + if (typeof module2 !== "undefined") + module2.exports = EventLite2; + var LISTENERS = "listeners"; + var methods2 = { + on, + once, + off, + emit + }; + mixin2(EventLite2.prototype); + EventLite2.mixin = mixin2; + function mixin2(target) { + for (var key in methods2) { + target[key] = methods2[key]; + } + return target; + } + function on(type, func2) { + getListeners(this, type).push(func2); + return this; + } + function once(type, func2) { + var that = this; + wrap.originalListener = func2; + getListeners(that, type).push(wrap); + return that; + function wrap() { + off.call(that, type, wrap); + func2.apply(this, arguments); + } + } + function off(type, func2) { + var that = this; + var listners; + if (!arguments.length) { + delete that[LISTENERS]; + } else if (!func2) { + 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 !== func2 && test.originalListener !== func2; + } + } + 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(func2) { + func2.call(that); + } + function onearg(func2) { + func2.call(that, value); + } + function moreargs(func2) { + func2.apply(that, args); + } + } + function getListeners(that, type, readonly) { + if (readonly && !that[LISTENERS]) + return; + var listeners = that[LISTENERS] || (that[LISTENERS] = {}); + return listeners[type] || (listeners[type] = []); + } + })(EventLite); + } +}); + +// node_modules/msgpack-lite/lib/encoder.js +var require_encoder = __commonJS({ + "node_modules/msgpack-lite/lib/encoder.js"(exports2) { + exports2.Encoder = Encoder; + var EventLite = require_event_lite(); + var EncodeBuffer = require_encode_buffer().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"); + }; + } +}); + +// node_modules/msgpack-lite/lib/decoder.js +var require_decoder = __commonJS({ + "node_modules/msgpack-lite/lib/decoder.js"(exports2) { + exports2.Decoder = Decoder; + var EventLite = require_event_lite(); + var DecodeBuffer = require_decode_buffer().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"); + }; + } +}); + +// node_modules/msgpack-lite/lib/encode-stream.js +var require_encode_stream = __commonJS({ + "node_modules/msgpack-lite/lib/encode-stream.js"(exports2) { + exports2.createEncodeStream = EncodeStream; + var util4 = require("util"); + var Transform2 = require("stream").Transform; + var EncodeBuffer = require_encode_buffer().EncodeBuffer; + util4.inherits(EncodeStream, Transform2); + 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; + } + Transform2.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(); + }; + } +}); + +// node_modules/msgpack-lite/lib/decode-stream.js +var require_decode_stream = __commonJS({ + "node_modules/msgpack-lite/lib/decode-stream.js"(exports2) { + exports2.createDecodeStream = DecodeStream; + var util4 = require("util"); + var Transform2 = require("stream").Transform; + var DecodeBuffer = require_decode_buffer().DecodeBuffer; + util4.inherits(DecodeStream, Transform2); + 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; + } + Transform2.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(); + }; + } +}); + +// node_modules/msgpack-lite/lib/ext.js +var require_ext = __commonJS({ + "node_modules/msgpack-lite/lib/ext.js"(exports2) { + require_read_core(); + require_write_core(); + exports2.createCodec = require_codec_base().createCodec; + } +}); + +// node_modules/msgpack-lite/lib/codec.js +var require_codec = __commonJS({ + "node_modules/msgpack-lite/lib/codec.js"(exports2) { + require_read_core(); + require_write_core(); + exports2.codec = { + preset: require_codec_base().preset + }; + } +}); + +// node_modules/msgpack-lite/index.js +var require_msgpack_lite = __commonJS({ + "node_modules/msgpack-lite/index.js"(exports2) { + exports2.encode = require_encode().encode; + exports2.decode = require_decode().decode; + exports2.Encoder = require_encoder().Encoder; + exports2.Decoder = require_decoder().Decoder; + exports2.createEncodeStream = require_encode_stream().createEncodeStream; + exports2.createDecodeStream = require_decode_stream().createDecodeStream; + exports2.createCodec = require_ext().createCodec; + exports2.codec = require_codec().codec; + } +}); + +// node_modules/@chemzqm/neovim/lib/utils/buffered.js +var require_buffered = __commonJS({ + "node_modules/@chemzqm/neovim/lib/utils/buffered.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var stream_1 = require("stream"); + var Buffered = class 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); + } + } + _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(); + } + } + }; + exports2.default = Buffered; + } +}); + +// node_modules/@chemzqm/neovim/lib/api/Base.js +var require_Base = __commonJS({ + "node_modules/@chemzqm/neovim/lib/api/Base.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.BaseApi = void 0; + var events_1 = require("events"); + var isVim7 = process.env.VIM_NODE_RPC == "1"; + var BaseApi = class 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; + } + } + async request(name2, args = []) { + let stack = Error().stack; + return new Promise((resolve3, reject) => { + this.transport.request(name2, this.getArgsByPrefix(args), (err, res) => { + if (err) { + let e = new Error(`request error ${name2} - ${err[1]}`); + e.stack = stack; + if (!name2.endsWith("get_var")) { + this.client.logError(`request error on "${name2}"`, args, err[1], stack); + } + reject(e); + } else { + resolve3(res); + } + }); + }); + } + getArgsByPrefix(args) { + if (this.prefix !== "nvim_" && args[0] != this) { + let id = isVim7 ? this.data : this; + return [id, ...args]; + } + return args; + } + getVar(name2) { + return this.request(`${this.prefix}get_var`, [name2]).then((res) => res, (_err) => { + return null; + }); + } + setVar(name2, value, isNotify = false) { + if (isNotify) { + this.notify(`${this.prefix}set_var`, [name2, value]); + return; + } + return this.request(`${this.prefix}set_var`, [name2, value]); + } + deleteVar(name2) { + this.notify(`${this.prefix}del_var`, [name2]); + } + getOption(name2) { + return this.request(`${this.prefix}get_option`, [name2]); + } + setOption(name2, value, isNotify) { + if (isNotify) { + this.notify(`${this.prefix}set_option`, [name2, value]); + return; + } + return this.request(`${this.prefix}set_option`, [name2, value]); + } + notify(name2, args = []) { + this.transport.notify(name2, this.getArgsByPrefix(args)); + } + }; + exports2.BaseApi = BaseApi; + } +}); + +// node_modules/@chemzqm/neovim/lib/api/Buffer.js +var require_Buffer = __commonJS({ + "node_modules/@chemzqm/neovim/lib/api/Buffer.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Buffer = void 0; + var Base_1 = require_Base(); + var Buffer4 = class extends Base_1.BaseApi { + constructor() { + super(...arguments); + this.prefix = "nvim_buf_"; + } + async attach(sendBuffer = false, options = {}) { + return await this.request(`${this.prefix}attach`, [sendBuffer, options]); + } + async detach() { + return await this.request(`${this.prefix}detach`, []); + } + get id() { + return this.data; + } + get length() { + return this.request(`${this.prefix}line_count`, []); + } + get lines() { + return this.getLines(); + } + get changedtick() { + return this.request(`${this.prefix}get_changedtick`, []); + } + get commands() { + return this.getCommands(); + } + getCommands(options = {}) { + return this.request(`${this.prefix}get_commands`, [options]); + } + 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 + ]); + } + setLines(_lines, { start: _start, end: _end, strictIndexing } = { + strictIndexing: true + }, notify = false) { + 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 + ]); + } + 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, start) { + return this.setLines(lines, { + start, + end: start, + strictIndexing: true + }); + } + replace(_lines, start) { + const lines = typeof _lines === "string" ? [_lines] : _lines; + return this.setLines(lines, { + start, + end: start + lines.length, + strictIndexing: false + }); + } + remove(start, end, strictIndexing = false) { + return this.setLines([], { start, end, strictIndexing }); + } + append(lines) { + return this.setLines(lines, { + start: -1, + end: -1, + strictIndexing: false + }); + } + get name() { + return this.request(`${this.prefix}get_name`, []); + } + setName(value) { + return this.request(`${this.prefix}set_name`, [value]); + } + get valid() { + return this.request(`${this.prefix}is_valid`, []); + } + mark(name2) { + return this.request(`${this.prefix}get_mark`, [name2]); + } + getKeymap(mode) { + return this.request(`${this.prefix}get_keymap`, [mode]); + } + setKeymap(mode, lhs, rhs, opts = {}) { + this.client.call("coc#compat#buf_add_keymap", [this.id, mode, lhs, rhs, opts], true); + } + get loaded() { + return this.request(`${this.prefix}is_loaded`, []); + } + getOffset(index) { + return this.request(`${this.prefix}get_offset`, [index]); + } + addHighlight({ hlGroup, line, colStart: _start, colEnd: _end, srcId: _srcId }) { + if (!hlGroup) + throw new Error("hlGroup should not empty"); + const colEnd = typeof _end !== "undefined" ? _end : -1; + const colStart = typeof _start !== "undefined" ? _start : -0; + const srcId = typeof _srcId !== "undefined" ? _srcId : -1; + const method = srcId == 0 ? "request" : "notify"; + let res = this[method](`${this.prefix}add_highlight`, [ + srcId, + hlGroup, + line, + colStart, + colEnd + ]); + return method === "request" ? res : Promise.resolve(null); + } + clearHighlight(args = {}) { + const defaults2 = { + srcId: -1, + lineStart: 0, + lineEnd: -1 + }; + const { srcId, lineStart, lineEnd } = Object.assign({}, defaults2, args); + return this.notify(`${this.prefix}clear_highlight`, [ + srcId, + lineStart, + lineEnd + ]); + } + highlightRanges(srcId, hlGroup, ranges) { + this.client.call("coc#highlight#ranges", [this.id, srcId, hlGroup, ranges], true); + } + clearNamespace(key, lineStart = 0, lineEnd = -1) { + this.client.call("coc#highlight#clear_highlight", [this.id, key, lineStart, lineEnd], true); + } + placeSign(sign) { + let opts = { lnum: sign.lnum }; + if (typeof sign.priority === "number") + opts.priority = sign.priority; + this.client.call("sign_place", [sign.id || 0, sign.group || "", sign.name, this.id, opts], true); + } + unplaceSign(opts) { + let details = { buffer: this.id }; + if (opts.id != null) + details.id = opts.id; + this.client.call("sign_unplace", [opts.group || "", details], true); + } + async getSigns(opts) { + let res = await this.client.call("sign_getplaced", [this.id, opts || {}]); + return res[0].signs; + } + async getHighlights(ns, start = 0, end = -1) { + let res = []; + let obj = await this.client.call("coc#highlight#get", [this.id, ns, start, end]); + for (let arr of Object.values(obj)) { + if (Array.isArray(arr)) { + res.push(...arr); + } + } + return res; + } + updateHighlights(ns, highlights, start = 0, end = -1) { + this.client.call("coc#highlight#update_highlights", [this.id, ns, highlights, start, end], true); + } + listen(eventName, cb, disposables) { + this.client.attachBufferEvent(this, eventName, cb); + if (disposables) { + disposables.push({ + dispose: () => { + this.client.detachBufferEvent(this, eventName, cb); + } + }); + } + } + }; + exports2.Buffer = Buffer4; + } +}); + +// node_modules/@chemzqm/neovim/lib/api/Window.js +var require_Window = __commonJS({ + "node_modules/@chemzqm/neovim/lib/api/Window.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Window = void 0; + var Base_1 = require_Base(); + var timers_1 = require("timers"); + var Window3 = class extends Base_1.BaseApi { + constructor() { + super(...arguments); + this.prefix = "nvim_win_"; + } + get id() { + return this.data; + } + get buffer() { + return this.request(`${this.prefix}get_buf`, []); + } + get tabpage() { + return this.request(`${this.prefix}get_tabpage`, []); + } + 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 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 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 position() { + return this.request(`${this.prefix}get_position`, []); + } + get row() { + return this.request(`${this.prefix}get_position`, []).then((position) => position[0]); + } + get col() { + return this.request(`${this.prefix}get_position`, []).then((position) => position[1]); + } + get valid() { + return this.request(`${this.prefix}is_valid`, []); + } + 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]); + } + highlightRanges(hlGroup, ranges, priority = 10, isNotify) { + if (isNotify) { + this.client.call("coc#highlight#match_ranges", [this.id, 0, ranges, hlGroup, priority], true); + return void 0; + } + return this.client.call("coc#highlight#match_ranges", [this.id, 0, ranges, hlGroup, priority]); + } + clearMatchGroup(hlGroup) { + this.client.call("coc#highlight#clear_match_group", [this.id, hlGroup], true); + } + clearMatches(ids) { + this.client.call("coc#highlight#clear_matches", [this.id, ids], true); + } + }; + exports2.Window = Window3; + } +}); + +// node_modules/@chemzqm/neovim/lib/api/Tabpage.js +var require_Tabpage = __commonJS({ + "node_modules/@chemzqm/neovim/lib/api/Tabpage.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Tabpage = void 0; + var Base_1 = require_Base(); + var Tabpage = class extends Base_1.BaseApi { + constructor() { + super(...arguments); + this.prefix = "nvim_tabpage_"; + } + get windows() { + return this.request(`${this.prefix}list_wins`, []); + } + get window() { + return this.request(`${this.prefix}get_win`, []); + } + get valid() { + return this.request(`${this.prefix}is_valid`, []); + } + get number() { + return this.request(`${this.prefix}get_number`, []); + } + getOption() { + throw new Error("Tabpage does not have `getOption`"); + } + setOption() { + throw new Error("Tabpage does not have `setOption`"); + } + }; + exports2.Tabpage = Tabpage; + } +}); + +// node_modules/@chemzqm/neovim/lib/api/types.js +var require_types = __commonJS({ + "node_modules/@chemzqm/neovim/lib/api/types.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Metadata = exports2.ExtType = void 0; + var Buffer_1 = require_Buffer(); + var Window_1 = require_Window(); + var Tabpage_1 = require_Tabpage(); + var ExtType; + (function(ExtType2) { + ExtType2[ExtType2["Buffer"] = 0] = "Buffer"; + ExtType2[ExtType2["Window"] = 1] = "Window"; + ExtType2[ExtType2["Tabpage"] = 2] = "Tabpage"; + })(ExtType = exports2.ExtType || (exports2.ExtType = {})); + exports2.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_" + } + ]; + } +}); + +// node_modules/@chemzqm/neovim/lib/utils/logger.js +var require_logger3 = __commonJS({ + "node_modules/@chemzqm/neovim/lib/utils/logger.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createLogger = void 0; + var fs_1 = __importDefault(require("fs")); + var os_1 = __importDefault(require("os")); + var path_1 = __importDefault(require("path")); + 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`); + } + var LOG_FILE_PATH = getLogFile(); + var level = process.env.NODE_CLIENT_LOG_LEVEL || "info"; + var 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: 438 }); + } 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); + } + function toTimeString(d) { + return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}`; + } + var Logger2 = class { + constructor(name2) { + this.name = name2; + } + get stream() { + if (invalid) + return null; + if (this._stream) + return this._stream; + this._stream = fs_1.default.createWriteStream(LOG_FILE_PATH, { encoding: "utf8" }); + return this._stream; + } + getText(level2, data, meta) { + let more = ""; + if (meta.length) { + let arr = toObject(meta); + more = " " + arr.map((o) => toString(o)); + } + return `${toTimeString(new Date())} ${level2.toUpperCase()} [${this.name}] - ${data}${more} +`; + } + debug(data, ...meta) { + if (level != "debug" || this.stream == null) + return; + this.stream.write(this.getText("debug", data, meta)); + } + info(data, ...meta) { + if (this.stream == null) + return; + this.stream.write(this.getText("info", data, meta)); + } + error(data, ...meta) { + if (this.stream == null) + return; + this.stream.write(this.getText("error", data, meta)); + } + trace(data, ...meta) { + if (level != "trace" || this.stream == null) + return; + this.stream.write(this.getText("trace", data, meta)); + } + }; + function createLogger3(name2) { + return new Logger2(name2); + } + exports2.createLogger = createLogger3; + } +}); + +// node_modules/@chemzqm/neovim/lib/transport/base.js +var require_base = __commonJS({ + "node_modules/@chemzqm/neovim/lib/transport/base.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var events_1 = require("events"); + var logger_1 = require_logger3(); + var debug = process.env.NODE_CLIENT_LOG_LEVEL == "debug"; + var logger113 = logger_1.createLogger("transport"); + var Transport3 = class extends events_1.EventEmitter { + constructor(logger114) { + super(); + this.logger = logger114; + this.pauseLevel = 0; + this.paused = new Map(); + } + debug(key, ...meta) { + if (!debug) + return; + logger113.debug(key, ...meta); + } + info(key, ...meta) { + logger113.info(key, ...meta); + } + debugMessage(msg) { + if (!debug) + return; + const msgType = msg[0]; + if (msgType == 0) { + logger113.debug("receive request:", msg.slice(1)); + } else if (msgType == 1) { + } else if (msgType == 2) { + logger113.debug("receive notification:", msg.slice(1)); + } else { + logger113.debug("unknown message:", msg); + } + } + pauseNotification() { + this.pauseLevel = this.pauseLevel + 1; + this.paused.set(this.pauseLevel, []); + } + cancelNotification() { + let { pauseLevel } = this; + if (pauseLevel > 0) { + this.paused.delete(pauseLevel); + this.pauseLevel = pauseLevel - 1; + } + } + resumeNotification(isNotify = false) { + let { pauseLevel } = this; + if (pauseLevel == 0) + return isNotify ? null : Promise.resolve([null, null]); + let stack = Error().stack; + this.pauseLevel = pauseLevel - 1; + let list2 = this.paused.get(pauseLevel); + this.paused.delete(pauseLevel); + if (list2 && list2.length) { + return new Promise((resolve3, reject) => { + if (!isNotify) { + return this.request("nvim_call_atomic", [list2], (err, res) => { + if (err) { + let e = new Error(`call_atomic error: ${err[1]}`); + e.stack = stack; + return reject(e); + } + if (Array.isArray(res) && res[1] != null) { + let [index, errType, message] = res[1]; + let [fname, args] = list2[index]; + this.logger.error(`request error ${errType} on "${fname}"`, args, message, stack); + } + resolve3(res); + }); + } + this.notify("nvim_call_atomic", [list2]); + resolve3(); + }); + } + return isNotify ? null : Promise.resolve([[], void 0]); + } + }; + exports2.default = Transport3; + } +}); + +// node_modules/@chemzqm/neovim/lib/transport/nvim.js +var require_nvim = __commonJS({ + "node_modules/@chemzqm/neovim/lib/transport/nvim.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { + return m[k]; + } }); + } : function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } : function(o, v) { + o["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) + __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.NvimTransport = void 0; + var msgpack = __importStar(require_msgpack_lite()); + var buffered_1 = __importDefault(require_buffered()); + var types_1 = require_types(); + var base_1 = __importDefault(require_base()); + var NvimTransport = class extends base_1.default { + constructor(logger113) { + super(logger113); + 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) { + this.emit("request", msg[2].toString(), msg[3], this.createResponse(msg[1])); + } else if (msgType === 1) { + 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) { + this.emit("notification", msg[1].toString(), msg[2]); + } else { + 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; + let id = this.nextRequestId; + this.nextRequestId = this.nextRequestId + 1; + let startTs = Date.now(); + this.debug("request to nvim:", id, method, args); + this.encodeStream.write(msgpack.encode([0, id, method, args], { + codec: this.codec + })); + let stack = Error().stack; + let timer = setTimeout(() => { + this.debug(`request to vim blocked more than 1s: ${method}`, args, stack); + }, 1e3); + this.pending.set(id, (err, res) => { + clearTimeout(timer); + this.debug("response of nvim:", id, `${Date.now() - startTs}ms`, res, err); + cb(err, res); + }); + } + notify(method, args) { + if (!this.attached) + return; + if (this.pauseLevel != 0) { + let arr = this.paused.get(this.pauseLevel); + if (arr) { + arr.push([method, args]); + return; + } + } + this.debug("nvim notification:", method, args); + this.encodeStream.write(msgpack.encode([2, method, args], { + codec: this.codec + })); + } + send(arr) { + this.encodeStream.write(msgpack.encode(arr, { + codec: this.codec + })); + } + createResponse(requestId) { + let { encodeStream } = this; + let startTs = Date.now(); + let called = false; + let timer = setTimeout(() => { + this.debug(`request to client cost more than 1s`, requestId); + }, 1e3); + return { + send: (resp, isError) => { + clearTimeout(timer); + if (called || !this.attached) + return; + this.debug("response of client:", requestId, `${Date.now() - startTs}ms`, resp, isError == true); + called = true; + encodeStream.write(msgpack.encode([ + 1, + requestId, + isError ? resp : null, + !isError ? resp : null + ])); + } + }; + } + }; + exports2.NvimTransport = NvimTransport; + } +}); + +// node_modules/@chemzqm/neovim/lib/transport/connection.js +var require_connection = __commonJS({ + "node_modules/@chemzqm/neovim/lib/transport/connection.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var events_1 = __importDefault(require("events")); + var readline_1 = __importDefault(require("readline")); + var logger_1 = require_logger3(); + var logger113 = logger_1.createLogger("connection"); + var Connection = class 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", () => { + logger113.error("connection closed"); + process.exit(0); + }); + } + parseData(str) { + if (str.length == 0) + return; + let arr; + try { + arr = JSON.parse(str); + } catch (e) { + console.error(`Invalid data from vim: ${str}`); + return; + } + let [id, obj] = arr; + if (id > 0) { + logger113.debug("received request:", id, obj); + this.emit("request", id, obj); + } else if (id == 0) { + logger113.debug("received notification:", obj); + this.emit("notification", obj); + } else { + logger113.debug("received response:", id, obj); + this.emit("response", id, obj); + } + } + response(requestId, data) { + this.send([requestId, data || null]); + } + notify(event, data) { + this.send([0, [event, data || null]]); + } + send(arr) { + logger113.debug("send to vim:", arr); + try { + this.writeable.write(JSON.stringify(arr) + "\n"); + } catch (e) { + logger113.error("Send error:", arr); + } + } + redraw(force = false) { + this.send(["redraw", force ? "force" : ""]); + } + command(cmd) { + this.send(["ex", cmd]); + } + expr(expr) { + this.send(["expr", expr]); + } + call(func2, args, requestId) { + if (!requestId) { + this.send(["call", func2, args]); + return; + } + this.send(["call", func2, args, requestId]); + } + dispose() { + this.removeAllListeners(); + } + }; + exports2.default = Connection; + } +}); + +// node_modules/@chemzqm/neovim/lib/transport/request.js +var require_request = __commonJS({ + "node_modules/@chemzqm/neovim/lib/transport/request.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var logger_1 = require_logger3(); + var logger113 = logger_1.createLogger("request"); + var debug = process.env.NODE_CLIENT_LOG_LEVEL == "debug"; + var func2 = process.env.COC_NVIM == "1" ? "coc#api#call" : "nvim#api#call"; + var Request = class { + 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(func2, [method.slice(5), args], this.id); + } + callback(client, err, result) { + let { method, cb } = this; + if (debug && err) { + logger113.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); + } + } + }; + exports2.default = Request; + } +}); + +// node_modules/@chemzqm/neovim/lib/transport/vim.js +var require_vim = __commonJS({ + "node_modules/@chemzqm/neovim/lib/transport/vim.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.VimTransport = void 0; + var base_1 = __importDefault(require_base()); + var connection_1 = __importDefault(require_connection()); + var request_1 = __importDefault(require_request()); + var VimTransport = class extends base_1.default { + constructor(logger113) { + super(logger113); + this.pending = new Map(); + this.nextRequestId = -1; + this.attached = false; + this.errText = ""; + this.outText = ""; + 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); + } + }); + } + send(arr) { + this.connection.send(arr); + } + detach() { + if (!this.attached) + return; + this.attached = false; + this.connection.dispose(); + } + request(method, args, cb) { + if (!this.attached) + return cb([0, "transport disconnected"]); + let id = this.nextRequestId; + this.nextRequestId = this.nextRequestId - 1; + let startTs = Date.now(); + this.debug("request to vim:", id, method, args); + let timer = setTimeout(() => { + this.debug(`request to vim cost more than 1s`, method, args); + }, 1e3); + let req = new request_1.default(this.connection, (err, res) => { + clearTimeout(timer); + this.debug(`response from vim cost:`, id, `${Date.now() - startTs}ms`); + cb(err, res); + }, id); + this.pending.set(id, req); + req.request(method, args); + } + notify(method, args) { + if (!this.attached) + return; + if (this.pauseLevel != 0) { + let arr = this.paused.get(this.pauseLevel); + if (arr) { + arr.push([method, args]); + return; + } + } + let fname = method.slice(5); + if (fname == "err_write") { + this.errText = this.errText + args[0].toString(); + return; + } + if (fname == "out_write") { + let msg = args[0].toString() || ""; + if (!msg.includes("\n")) { + this.outText = this.outText + msg; + } else { + let text = this.outText + args[0].toString(); + this.outText = ""; + this.connection.call(this.notifyMethod, [fname, [text]]); + } + return; + } + if (fname == "err_writeln") { + let text = this.errText + args[0].toString(); + this.errText = ""; + this.connection.call(this.notifyMethod, [fname, [text]]); + return; + } + this.connection.call(this.notifyMethod, [fname, args]); + } + createResponse(requestId) { + let called = false; + let { connection } = this; + let startTs = Date.now(); + let timer = setTimeout(() => { + this.debug(`request to client cost more than 1s`, requestId); + }, 1e3); + return { + send: (resp, isError) => { + clearTimeout(timer); + if (called || !this.attached) + return; + called = true; + let err = null; + if (isError) + err = typeof resp === "string" ? resp : resp.toString(); + this.debug("response of client cost:", requestId, `${Date.now() - startTs}ms`); + connection.response(requestId, [err, isError ? null : resp]); + } + }; + } + }; + exports2.VimTransport = VimTransport; + } +}); + +// node_modules/@chemzqm/neovim/lib/api/Neovim.js +var require_Neovim = __commonJS({ + "node_modules/@chemzqm/neovim/lib/api/Neovim.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Neovim = void 0; + var Base_1 = require_Base(); + var Buffer_1 = require_Buffer(); + var Tabpage_1 = require_Tabpage(); + var Window_1 = require_Window(); + var isVim7 = process.env.VIM_NODE_RPC == "1"; + var Neovim2 = class 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 buffers() { + return this.request(`${this.prefix}list_bufs`); + } + get buffer() { + return this.request(`${this.prefix}get_current_buf`); + } + async setBuffer(buffer) { + await 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(name2 = "") { + return this.request(`${this.prefix}create_namespace`, [name2]); + } + get namespaces() { + return this.request(`${this.prefix}get_namespaces`, []); + } + get commands() { + return this.getCommands(); + } + getCommands(options = {}) { + return this.request(`${this.prefix}get_commands`, [options]); + } + get tabpages() { + return this.request(`${this.prefix}list_tabpages`); + } + get tabpage() { + return this.request(`${this.prefix}get_current_tabpage`); + } + async setTabpage(tabpage) { + await this.request(`${this.prefix}set_current_tabpage`, [tabpage]); + } + get windows() { + return this.getWindows(); + } + get window() { + return this.request(`${this.prefix}get_current_win`); + } + getWindows() { + return this.request(`${this.prefix}list_wins`); + } + async setWindow(win) { + await this.request(`${this.prefix}set_current_win`, [win]); + } + get runtimePaths() { + return this.request(`${this.prefix}list_runtime_paths`); + } + setDirectory(dir) { + return this.request(`${this.prefix}set_current_dir`, [dir]); + } + 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`); + } + setLine(line) { + return this.request(`${this.prefix}set_current_line`, [line]); + } + getKeymap(mode) { + return this.request(`${this.prefix}get_keymap`, [mode]); + } + get mode() { + return this.request(`${this.prefix}get_mode`); + } + get colorMap() { + return this.request(`${this.prefix}get_color_map`); + } + getColorByName(name2) { + return this.request(`${this.prefix}get_color_by_name`, [name2]); + } + getHighlight(nameOrId, isRgb = true) { + const functionName = typeof nameOrId === "string" ? "by_name" : "by_id"; + return this.request(`${this.prefix}get_hl_${functionName}`, [ + nameOrId, + isRgb + ]); + } + getHighlightByName(name2, isRgb = true) { + return this.request(`${this.prefix}get_hl_by_name`, [name2, isRgb]); + } + getHighlightById(id, isRgb = true) { + return this.request(`${this.prefix}get_hl_by_id`, [id, isRgb]); + } + deleteCurrentLine() { + return this.request(`${this.prefix}del_current_line`); + } + eval(expr) { + return this.request(`${this.prefix}eval`, [expr]); + } + lua(code, args = []) { + const _args = this.getArgs(args); + return this.request(`${this.prefix}execute_lua`, [code, _args]); + } + 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 (isVim7) { + this.notify(`${this.prefix}call_function`, ["coc#util#timer", [fname, _args]]); + return new Promise((resolve3) => { + setTimeout(() => { + resolve3(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); + } + callFunction(fname, args = []) { + return this.call(fname, args); + } + 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]); + } + commandOutput(arg) { + return this.request(`${this.prefix}command_output`, [arg]); + } + getVvar(name2) { + return this.request(`${this.prefix}get_vvar`, [name2]); + } + feedKeys(keys, mode, escapeCsi) { + return this.request(`${this.prefix}feedkeys`, [keys, mode, escapeCsi]); + } + input(keys) { + return this.request(`${this.prefix}input`, [keys]); + } + 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]); + } + replaceTermcodes(str, fromPart, doIt, special) { + return this.request(`${this.prefix}replace_termcodes`, [ + str, + fromPart, + doIt, + special + ]); + } + strWidth(str) { + return this.request(`${this.prefix}strwidth`, [str]); + } + outWrite(str) { + this.notify(`${this.prefix}out_write`, [str]); + } + outWriteLine(str) { + this.outWrite(`${str} +`); + } + errWrite(str) { + this.notify(`${this.prefix}err_write`, [str]); + } + errWriteLine(str) { + this.notify(`${this.prefix}err_writeln`, [str]); + } + 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]); + } + uiSetOption(name2, value) { + return this.request(`${this.prefix}ui_set_option`, [name2, value]); + } + subscribe(event) { + return this.request(`${this.prefix}subscribe`, [event]); + } + unsubscribe(event) { + return this.request(`${this.prefix}unsubscribe`, [event]); + } + setClientInfo(name2, version2, type, methods2, attributes) { + this.notify(`${this.prefix}set_client_info`, [ + name2, + version2, + type, + methods2, + attributes + ]); + } + async quit() { + this.command("qa!", true); + if (this.transport) { + this.transport.detach(); + } + } + }; + exports2.Neovim = Neovim2; + } +}); + +// node_modules/@chemzqm/neovim/lib/api/client.js +var require_client = __commonJS({ + "node_modules/@chemzqm/neovim/lib/api/client.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.NeovimClient = exports2.AsyncResponse = void 0; + var nvim_1 = require_nvim(); + var vim_1 = require_vim(); + var Neovim_1 = require_Neovim(); + var Buffer_1 = require_Buffer(); + var Window_1 = require_Window(); + var Tabpage_1 = require_Tabpage(); + var logger_1 = require_logger3(); + var logger113 = logger_1.createLogger("client"); + var isVim7 = process.env.VIM_NODE_RPC == "1"; + var AsyncResponse = class { + 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); + } + }; + exports2.AsyncResponse = AsyncResponse; + var NeovimClient2 = class extends Neovim_1.Neovim { + constructor(logger114) { + super({}); + this.logger = logger114; + this.requestId = 1; + this.responses = new Map(); + this.attachedBuffers = new Map(); + Object.defineProperty(this, "client", { + value: this + }); + let transport = isVim7 ? new vim_1.VimTransport(logger114) : new nvim_1.NvimTransport(logger114); + this.setTransport(transport); + this.transportAttached = false; + this.handleRequest = this.handleRequest.bind(this); + this.handleNotification = this.handleNotification.bind(this); + } + echoError(msg) { + let prefix = process.env.COC_NVIM == "1" ? "[coc.nvim] " : ""; + if (typeof msg === "string") { + this.errWriteLine(prefix + msg); + this.logError(msg, Error().stack); + } else { + this.errWriteLine(prefix + msg.message + " use :CocOpenLog for details"); + this.logError(msg.message || "Unknown error", msg.stack); + } + } + logError(msg, ...args) { + if (!this.logger) + return; + this.logger.error(msg, ...args); + } + 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 + }); + } + send(arr) { + this.transport.send(arr); + } + redrawVim(force) { + if (!isVim7) + return; + this.transport.send(["redraw", force ? "force" : ""]); + } + attach({ reader, writer }, requestApi = true) { + this.transport.attach(writer, reader, this); + this.transportAttached = true; + this.setupTransport(requestApi); + } + 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((resolve3, reject) => { + let response = new AsyncResponse(id, (err, res) => { + if (err) + return reject(err); + resolve3(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 { id } = args[0]; + if (!this.attachedBuffers.has(id)) + return; + const bufferMap = this.attachedBuffers.get(id); + const cbs = bufferMap.get(shortName) || []; + cbs.forEach((cb) => cb(...args)); + if (shortName === "detach") { + this.attachedBuffers.delete(id); + } + return; + } + if (method.startsWith("nvim_async_request")) { + const [id, method2, arr] = args; + this.handleRequest(method2, arr, { + send: (resp, isError) => { + this.notify("nvim_call_function", ["coc#rpc#async_response", [id, resp, isError]]); + } + }); + } + if (method.startsWith("nvim_async_response")) { + const [id, err, res] = args; + const response = this.responses.get(id); + if (!response) { + console.error(`Response not found for request ${id}`); + return; + } + this.responses.delete(id); + response.finish(err, res); + return; + } + } else { + this.emit("notification", method, args); + } + } + handleNotification(method, args) { + this.emitNotification(method, args); + } + 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((resolve3, 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 { + resolve3(res); + } + }); + }); + } + async generateApi() { + let results; + try { + results = await this.requestApi(); + } catch (err) { + console.error("Could not get vim api results"); + logger113.error(err); + } + if (results) { + try { + const [channelId, metadata] = results; + this.functions = metadata.functions.map((f) => f.name); + this._channelId = channelId; + return true; + } catch (err) { + logger113.error(err.stack); + return null; + } + } + return null; + } + attachBufferEvent(buffer, eventName, cb) { + const bufferMap = this.attachedBuffers.get(buffer.id) || new Map(); + const cbs = bufferMap.get(eventName) || []; + if (cbs.includes(cb)) + return; + cbs.push(cb); + bufferMap.set(eventName, cbs); + this.attachedBuffers.set(buffer.id, bufferMap); + return; + } + detachBufferEvent(buffer, eventName, cb) { + const bufferMap = this.attachedBuffers.get(buffer.id); + if (!bufferMap || !bufferMap.has(eventName)) + return; + const handlers = bufferMap.get(eventName).filter((handler) => handler !== cb); + bufferMap.set(eventName, handlers); + } + pauseNotification() { + this.transport.pauseNotification(); + let stack = Error().stack; + process.nextTick(() => { + if (this.transport.pauseLevel > 0) { + this.logError(`resumeNotification not called within same tick:`, stack); + } + }); + } + resumeNotification(cancel, notify) { + if (cancel) + return Promise.resolve(this.transport.cancelNotification()); + if (notify) { + return Promise.resolve(this.transport.resumeNotification(true)); + } + return Promise.resolve(this.transport.resumeNotification()); + } + hasFunction(name2) { + if (!this.functions) + return true; + return this.functions.indexOf(name2) !== -1; + } + }; + exports2.NeovimClient = NeovimClient2; + } +}); + +// node_modules/@chemzqm/neovim/lib/attach/attach.js +var require_attach = __commonJS({ + "node_modules/@chemzqm/neovim/lib/attach/attach.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.attach = void 0; + var net_1 = require("net"); + var client_1 = require_client(); + function attach3({ reader: _reader, writer: _writer, proc, socket }, logger113 = 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(logger113); + neovim.attach({ + writer, + reader + }, requestApi); + return neovim; + } + throw new Error("Invalid arguments, could not attach"); + } + exports2.attach = attach3; + } +}); + +// node_modules/@chemzqm/neovim/lib/api/index.js +var require_api = __commonJS({ + "node_modules/@chemzqm/neovim/lib/api/index.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Tabpage = exports2.Window = exports2.Buffer = exports2.NeovimClient = exports2.Neovim = void 0; + var client_1 = require_client(); + Object.defineProperty(exports2, "Neovim", { enumerable: true, get: function() { + return client_1.NeovimClient; + } }); + var client_2 = require_client(); + Object.defineProperty(exports2, "NeovimClient", { enumerable: true, get: function() { + return client_2.NeovimClient; + } }); + var Buffer_1 = require_Buffer(); + Object.defineProperty(exports2, "Buffer", { enumerable: true, get: function() { + return Buffer_1.Buffer; + } }); + var Window_1 = require_Window(); + Object.defineProperty(exports2, "Window", { enumerable: true, get: function() { + return Window_1.Window; + } }); + var Tabpage_1 = require_Tabpage(); + Object.defineProperty(exports2, "Tabpage", { enumerable: true, get: function() { + return Tabpage_1.Tabpage; + } }); + } +}); + +// node_modules/@chemzqm/neovim/lib/index.js +var require_lib6 = __commonJS({ + "node_modules/@chemzqm/neovim/lib/index.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Window = exports2.Tabpage = exports2.Buffer = exports2.NeovimClient = exports2.Neovim = exports2.attach = void 0; + var attach_1 = require_attach(); + Object.defineProperty(exports2, "attach", { enumerable: true, get: function() { + return attach_1.attach; + } }); + var index_1 = require_api(); + Object.defineProperty(exports2, "Neovim", { enumerable: true, get: function() { + return index_1.Neovim; + } }); + Object.defineProperty(exports2, "NeovimClient", { enumerable: true, get: function() { + return index_1.NeovimClient; + } }); + Object.defineProperty(exports2, "Buffer", { enumerable: true, get: function() { + return index_1.Buffer; + } }); + Object.defineProperty(exports2, "Tabpage", { enumerable: true, get: function() { + return index_1.Tabpage; + } }); + Object.defineProperty(exports2, "Window", { enumerable: true, get: function() { + return index_1.Window; + } }); + } +}); + +// node_modules/vscode-jsonrpc/lib/common/ral.js +var require_ral = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/ral.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var _ral; + function RAL2() { + if (_ral === void 0) { + throw new Error(`No runtime abstraction layer installed`); + } + return _ral; + } + (function(RAL3) { + function install(ral) { + if (ral === void 0) { + throw new Error(`No runtime abstraction layer provided`); + } + _ral = ral; + } + RAL3.install = install; + })(RAL2 || (RAL2 = {})); + exports2.default = RAL2; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/disposable.js +var require_disposable = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/disposable.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Disposable = void 0; + var Disposable80; + (function(Disposable81) { + function create(func2) { + return { + dispose: func2 + }; + } + Disposable81.create = create; + })(Disposable80 = exports2.Disposable || (exports2.Disposable = {})); + } +}); + +// node_modules/vscode-jsonrpc/lib/common/messageBuffer.js +var require_messageBuffer = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/messageBuffer.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.AbstractMessageBuffer = void 0; + var CR = 13; + var LF = 10; + var CRLF = "\r\n"; + var AbstractMessageBuffer = class { + constructor(encoding = "utf-8") { + this._encoding = encoding; + this._chunks = []; + this._totalLength = 0; + } + get encoding() { + return this._encoding; + } + append(chunk) { + const toAppend = typeof chunk === "string" ? this.fromString(chunk, this._encoding) : chunk; + this._chunks.push(toAppend); + this._totalLength += toAppend.byteLength; + } + tryReadHeaders() { + if (this._chunks.length === 0) { + return void 0; + } + let state = 0; + let chunkIndex = 0; + let offset = 0; + let chunkBytesRead = 0; + row: + while (chunkIndex < this._chunks.length) { + const chunk = this._chunks[chunkIndex]; + offset = 0; + column: + while (offset < chunk.length) { + const value = chunk[offset]; + switch (value) { + case CR: + switch (state) { + case 0: + state = 1; + break; + case 2: + state = 3; + break; + default: + state = 0; + } + break; + case LF: + switch (state) { + case 1: + state = 2; + break; + case 3: + state = 4; + offset++; + break row; + default: + state = 0; + } + break; + default: + state = 0; + } + offset++; + } + chunkBytesRead += chunk.byteLength; + chunkIndex++; + } + if (state !== 4) { + return void 0; + } + const buffer = this._read(chunkBytesRead + offset); + const result = new Map(); + const headers = this.toString(buffer, "ascii").split(CRLF); + if (headers.length < 2) { + return result; + } + for (let i = 0; i < headers.length - 2; i++) { + const header = headers[i]; + const index = header.indexOf(":"); + if (index === -1) { + throw new Error("Message header must separate key and value using :"); + } + const key = header.substr(0, index); + const value = header.substr(index + 1).trim(); + result.set(key, value); + } + return result; + } + tryReadBody(length) { + if (this._totalLength < length) { + return void 0; + } + return this._read(length); + } + get numberOfBytes() { + return this._totalLength; + } + _read(byteCount) { + if (byteCount === 0) { + return this.emptyBuffer(); + } + if (byteCount > this._totalLength) { + throw new Error(`Cannot read so many bytes!`); + } + if (this._chunks[0].byteLength === byteCount) { + const chunk = this._chunks[0]; + this._chunks.shift(); + this._totalLength -= byteCount; + return this.asNative(chunk); + } + if (this._chunks[0].byteLength > byteCount) { + const chunk = this._chunks[0]; + const result2 = this.asNative(chunk, byteCount); + this._chunks[0] = chunk.slice(byteCount); + this._totalLength -= byteCount; + return result2; + } + const result = this.allocNative(byteCount); + let resultOffset = 0; + let chunkIndex = 0; + while (byteCount > 0) { + const chunk = this._chunks[chunkIndex]; + if (chunk.byteLength > byteCount) { + const chunkPart = chunk.slice(0, byteCount); + result.set(chunkPart, resultOffset); + resultOffset += byteCount; + this._chunks[chunkIndex] = chunk.slice(byteCount); + this._totalLength -= byteCount; + byteCount -= byteCount; + } else { + result.set(chunk, resultOffset); + resultOffset += chunk.byteLength; + this._chunks.shift(); + this._totalLength -= chunk.byteLength; + byteCount -= chunk.byteLength; + } + } + return result; + } + }; + exports2.AbstractMessageBuffer = AbstractMessageBuffer; + } +}); + +// node_modules/vscode-jsonrpc/lib/node/ril.js +var require_ril = __commonJS({ + "node_modules/vscode-jsonrpc/lib/node/ril.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var ral_1 = require_ral(); + var util_1 = require("util"); + var disposable_1 = require_disposable(); + var messageBuffer_1 = require_messageBuffer(); + var MessageBuffer = class extends messageBuffer_1.AbstractMessageBuffer { + constructor(encoding = "utf-8") { + super(encoding); + } + emptyBuffer() { + return MessageBuffer.emptyBuffer; + } + fromString(value, encoding) { + return Buffer.from(value, encoding); + } + toString(value, encoding) { + if (value instanceof Buffer) { + return value.toString(encoding); + } else { + return new util_1.TextDecoder(encoding).decode(value); + } + } + asNative(buffer, length) { + if (length === void 0) { + return buffer instanceof Buffer ? buffer : Buffer.from(buffer); + } else { + return buffer instanceof Buffer ? buffer.slice(0, length) : Buffer.from(buffer, 0, length); + } + } + allocNative(length) { + return Buffer.allocUnsafe(length); + } + }; + MessageBuffer.emptyBuffer = Buffer.allocUnsafe(0); + var ReadableStreamWrapper = class { + constructor(stream) { + this.stream = stream; + } + onClose(listener) { + this.stream.on("close", listener); + return disposable_1.Disposable.create(() => this.stream.off("close", listener)); + } + onError(listener) { + this.stream.on("error", listener); + return disposable_1.Disposable.create(() => this.stream.off("error", listener)); + } + onEnd(listener) { + this.stream.on("end", listener); + return disposable_1.Disposable.create(() => this.stream.off("end", listener)); + } + onData(listener) { + this.stream.on("data", listener); + return disposable_1.Disposable.create(() => this.stream.off("data", listener)); + } + }; + var WritableStreamWrapper = class { + constructor(stream) { + this.stream = stream; + } + onClose(listener) { + this.stream.on("close", listener); + return disposable_1.Disposable.create(() => this.stream.off("close", listener)); + } + onError(listener) { + this.stream.on("error", listener); + return disposable_1.Disposable.create(() => this.stream.off("error", listener)); + } + onEnd(listener) { + this.stream.on("end", listener); + return disposable_1.Disposable.create(() => this.stream.off("end", listener)); + } + write(data, encoding) { + return new Promise((resolve3, reject) => { + const callback = (error) => { + if (error === void 0 || error === null) { + resolve3(); + } else { + reject(error); + } + }; + if (typeof data === "string") { + this.stream.write(data, encoding, callback); + } else { + this.stream.write(data, callback); + } + }); + } + end() { + this.stream.end(); + } + }; + var _ril = Object.freeze({ + messageBuffer: Object.freeze({ + create: (encoding) => new MessageBuffer(encoding) + }), + applicationJson: Object.freeze({ + encoder: Object.freeze({ + name: "application/json", + encode: (msg, options) => { + try { + return Promise.resolve(Buffer.from(JSON.stringify(msg, void 0, 0), options.charset)); + } catch (err) { + return Promise.reject(err); + } + } + }), + decoder: Object.freeze({ + name: "application/json", + decode: (buffer, options) => { + try { + if (buffer instanceof Buffer) { + return Promise.resolve(JSON.parse(buffer.toString(options.charset))); + } else { + return Promise.resolve(JSON.parse(new util_1.TextDecoder(options.charset).decode(buffer))); + } + } catch (err) { + return Promise.reject(err); + } + } + }) + }), + stream: Object.freeze({ + asReadableStream: (stream) => new ReadableStreamWrapper(stream), + asWritableStream: (stream) => new WritableStreamWrapper(stream) + }), + console, + timer: Object.freeze({ + setTimeout(callback, ms, ...args) { + return setTimeout(callback, ms, ...args); + }, + clearTimeout(handle) { + clearTimeout(handle); + }, + setImmediate(callback, ...args) { + return setImmediate(callback, ...args); + }, + clearImmediate(handle) { + clearImmediate(handle); + } + }) + }); + function RIL() { + return _ril; + } + (function(RIL2) { + function install() { + ral_1.default.install(_ril); + } + RIL2.install = install; + })(RIL || (RIL = {})); + exports2.default = RIL; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/is.js +var require_is = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/is.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.stringArray = exports2.array = exports2.func = exports2.error = exports2.number = exports2.string = exports2.boolean = void 0; + function boolean2(value) { + return value === true || value === false; + } + exports2.boolean = boolean2; + function string2(value) { + return typeof value === "string" || value instanceof String; + } + exports2.string = string2; + function number2(value) { + return typeof value === "number" || value instanceof Number; + } + exports2.number = number2; + function error(value) { + return value instanceof Error; + } + exports2.error = error; + function func2(value) { + return typeof value === "function"; + } + exports2.func = func2; + function array(value) { + return Array.isArray(value); + } + exports2.array = array; + function stringArray(value) { + return array(value) && value.every((elem) => string2(elem)); + } + exports2.stringArray = stringArray; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/messages.js +var require_messages = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/messages.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.isResponseMessage = exports2.isNotificationMessage = exports2.isRequestMessage = exports2.NotificationType9 = exports2.NotificationType8 = exports2.NotificationType7 = exports2.NotificationType6 = exports2.NotificationType5 = exports2.NotificationType4 = exports2.NotificationType3 = exports2.NotificationType2 = exports2.NotificationType1 = exports2.NotificationType0 = exports2.NotificationType = exports2.RequestType9 = exports2.RequestType8 = exports2.RequestType7 = exports2.RequestType6 = exports2.RequestType5 = exports2.RequestType4 = exports2.RequestType3 = exports2.RequestType2 = exports2.RequestType1 = exports2.RequestType = exports2.RequestType0 = exports2.AbstractMessageSignature = exports2.ParameterStructures = exports2.ResponseError = exports2.ErrorCodes = void 0; + var is = require_is(); + var ErrorCodes; + (function(ErrorCodes2) { + ErrorCodes2.ParseError = -32700; + ErrorCodes2.InvalidRequest = -32600; + ErrorCodes2.MethodNotFound = -32601; + ErrorCodes2.InvalidParams = -32602; + ErrorCodes2.InternalError = -32603; + ErrorCodes2.jsonrpcReservedErrorRangeStart = -32099; + ErrorCodes2.serverErrorStart = ErrorCodes2.jsonrpcReservedErrorRangeStart; + ErrorCodes2.MessageWriteError = -32099; + ErrorCodes2.MessageReadError = -32098; + ErrorCodes2.ServerNotInitialized = -32002; + ErrorCodes2.UnknownErrorCode = -32001; + ErrorCodes2.jsonrpcReservedErrorRangeEnd = -32e3; + ErrorCodes2.serverErrorEnd = ErrorCodes2.jsonrpcReservedErrorRangeEnd; + })(ErrorCodes = exports2.ErrorCodes || (exports2.ErrorCodes = {})); + var ResponseError2 = class extends Error { + constructor(code, message, data) { + super(message); + this.code = is.number(code) ? code : ErrorCodes.UnknownErrorCode; + this.data = data; + Object.setPrototypeOf(this, ResponseError2.prototype); + } + toJson() { + return { + code: this.code, + message: this.message, + data: this.data + }; + } + }; + exports2.ResponseError = ResponseError2; + var ParameterStructures = class { + constructor(kind) { + this.kind = kind; + } + static is(value) { + return value === ParameterStructures.auto || value === ParameterStructures.byName || value === ParameterStructures.byPosition; + } + toString() { + return this.kind; + } + }; + exports2.ParameterStructures = ParameterStructures; + ParameterStructures.auto = new ParameterStructures("auto"); + ParameterStructures.byPosition = new ParameterStructures("byPosition"); + ParameterStructures.byName = new ParameterStructures("byName"); + var AbstractMessageSignature = class { + constructor(method, numberOfParams) { + this.method = method; + this.numberOfParams = numberOfParams; + } + get parameterStructures() { + return ParameterStructures.auto; + } + }; + exports2.AbstractMessageSignature = AbstractMessageSignature; + var RequestType03 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 0); + } + }; + exports2.RequestType0 = RequestType03; + var RequestType3 = class extends AbstractMessageSignature { + constructor(method, _parameterStructures = ParameterStructures.auto) { + super(method, 1); + this._parameterStructures = _parameterStructures; + } + get parameterStructures() { + return this._parameterStructures; + } + }; + exports2.RequestType = RequestType3; + var RequestType1 = class extends AbstractMessageSignature { + constructor(method, _parameterStructures = ParameterStructures.auto) { + super(method, 1); + this._parameterStructures = _parameterStructures; + } + get parameterStructures() { + return this._parameterStructures; + } + }; + exports2.RequestType1 = RequestType1; + var RequestType22 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 2); + } + }; + exports2.RequestType2 = RequestType22; + var RequestType32 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 3); + } + }; + exports2.RequestType3 = RequestType32; + var RequestType4 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 4); + } + }; + exports2.RequestType4 = RequestType4; + var RequestType5 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 5); + } + }; + exports2.RequestType5 = RequestType5; + var RequestType6 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 6); + } + }; + exports2.RequestType6 = RequestType6; + var RequestType7 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 7); + } + }; + exports2.RequestType7 = RequestType7; + var RequestType8 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 8); + } + }; + exports2.RequestType8 = RequestType8; + var RequestType9 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 9); + } + }; + exports2.RequestType9 = RequestType9; + var NotificationType3 = class extends AbstractMessageSignature { + constructor(method, _parameterStructures = ParameterStructures.auto) { + super(method, 1); + this._parameterStructures = _parameterStructures; + } + get parameterStructures() { + return this._parameterStructures; + } + }; + exports2.NotificationType = NotificationType3; + var NotificationType03 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 0); + } + }; + exports2.NotificationType0 = NotificationType03; + var NotificationType1 = class extends AbstractMessageSignature { + constructor(method, _parameterStructures = ParameterStructures.auto) { + super(method, 1); + this._parameterStructures = _parameterStructures; + } + get parameterStructures() { + return this._parameterStructures; + } + }; + exports2.NotificationType1 = NotificationType1; + var NotificationType22 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 2); + } + }; + exports2.NotificationType2 = NotificationType22; + var NotificationType32 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 3); + } + }; + exports2.NotificationType3 = NotificationType32; + var NotificationType4 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 4); + } + }; + exports2.NotificationType4 = NotificationType4; + var NotificationType5 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 5); + } + }; + exports2.NotificationType5 = NotificationType5; + var NotificationType6 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 6); + } + }; + exports2.NotificationType6 = NotificationType6; + var NotificationType7 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 7); + } + }; + exports2.NotificationType7 = NotificationType7; + var NotificationType8 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 8); + } + }; + exports2.NotificationType8 = NotificationType8; + var NotificationType9 = class extends AbstractMessageSignature { + constructor(method) { + super(method, 9); + } + }; + exports2.NotificationType9 = NotificationType9; + function isRequestMessage(message) { + const candidate = message; + return candidate && is.string(candidate.method) && (is.string(candidate.id) || is.number(candidate.id)); + } + exports2.isRequestMessage = isRequestMessage; + function isNotificationMessage(message) { + const candidate = message; + return candidate && is.string(candidate.method) && message.id === void 0; + } + exports2.isNotificationMessage = isNotificationMessage; + function isResponseMessage(message) { + const candidate = message; + return candidate && (candidate.result !== void 0 || !!candidate.error) && (is.string(candidate.id) || is.number(candidate.id) || candidate.id === null); + } + exports2.isResponseMessage = isResponseMessage; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/events.js +var require_events = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/events.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Emitter = exports2.Event = void 0; + var ral_1 = require_ral(); + var Event27; + (function(Event28) { + const _disposable = { dispose() { + } }; + Event28.None = function() { + return _disposable; + }; + })(Event27 = exports2.Event || (exports2.Event = {})); + var CallbackList = class { + 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; + } + let foundCallbackWithDifferentContext = false; + for (let i = 0, len = this._callbacks.length; i < len; i++) { + if (this._callbacks[i] === callback) { + if (this._contexts[i] === context) { + 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 []; + } + const ret = [], callbacks = this._callbacks.slice(0), contexts = this._contexts.slice(0); + for (let i = 0, len = callbacks.length; i < len; i++) { + try { + ret.push(callbacks[i].apply(contexts[i], args)); + } catch (e) { + ral_1.default().console.error(e); + } + } + return ret; + } + isEmpty() { + return !this._callbacks || this._callbacks.length === 0; + } + dispose() { + this._callbacks = void 0; + this._contexts = void 0; + } + }; + var Emitter28 = class { + constructor(_options) { + this._options = _options; + } + 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); + const result = { + dispose: () => { + if (!this._callbacks) { + return; + } + this._callbacks.remove(listener, thisArgs); + result.dispose = Emitter28._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; + } + fire(event) { + if (this._callbacks) { + this._callbacks.invoke.call(this._callbacks, event); + } + } + dispose() { + if (this._callbacks) { + this._callbacks.dispose(); + this._callbacks = void 0; + } + } + }; + exports2.Emitter = Emitter28; + Emitter28._noop = function() { + }; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/cancellation.js +var require_cancellation = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/cancellation.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.CancellationTokenSource = exports2.CancellationToken = void 0; + var ral_1 = require_ral(); + var Is7 = require_is(); + var events_1 = require_events(); + var CancellationToken53; + (function(CancellationToken54) { + CancellationToken54.None = Object.freeze({ + isCancellationRequested: false, + onCancellationRequested: events_1.Event.None + }); + CancellationToken54.Cancelled = Object.freeze({ + isCancellationRequested: true, + onCancellationRequested: events_1.Event.None + }); + function is(value) { + const candidate = value; + return candidate && (candidate === CancellationToken54.None || candidate === CancellationToken54.Cancelled || Is7.boolean(candidate.isCancellationRequested) && !!candidate.onCancellationRequested); + } + CancellationToken54.is = is; + })(CancellationToken53 = exports2.CancellationToken || (exports2.CancellationToken = {})); + var shortcutEvent = Object.freeze(function(callback, context) { + const handle = ral_1.default().timer.setTimeout(callback.bind(context), 0); + return { dispose() { + ral_1.default().timer.clearTimeout(handle); + } }; + }); + var MutableToken = class { + constructor() { + this._isCancelled = false; + } + cancel() { + if (!this._isCancelled) { + this._isCancelled = true; + if (this._emitter) { + this._emitter.fire(void 0); + 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 = void 0; + } + } + }; + var CancellationTokenSource26 = class { + get token() { + if (!this._token) { + this._token = new MutableToken(); + } + return this._token; + } + cancel() { + if (!this._token) { + this._token = CancellationToken53.Cancelled; + } else { + this._token.cancel(); + } + } + dispose() { + if (!this._token) { + this._token = CancellationToken53.None; + } else if (this._token instanceof MutableToken) { + this._token.dispose(); + } + } + }; + exports2.CancellationTokenSource = CancellationTokenSource26; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/messageReader.js +var require_messageReader = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/messageReader.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ReadableStreamMessageReader = exports2.AbstractMessageReader = exports2.MessageReader = void 0; + var ral_1 = require_ral(); + var Is7 = require_is(); + var events_1 = require_events(); + var MessageReader2; + (function(MessageReader3) { + function is(value) { + let candidate = value; + return candidate && Is7.func(candidate.listen) && Is7.func(candidate.dispose) && Is7.func(candidate.onError) && Is7.func(candidate.onClose) && Is7.func(candidate.onPartialMessage); + } + MessageReader3.is = is; + })(MessageReader2 = exports2.MessageReader || (exports2.MessageReader = {})); + var AbstractMessageReader = class { + 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(void 0); + } + 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: ${Is7.string(error.message) ? error.message : "unknown"}`); + } + } + }; + exports2.AbstractMessageReader = AbstractMessageReader; + var ResolvedMessageReaderOptions; + (function(ResolvedMessageReaderOptions2) { + function fromOptions(options) { + var _a2; + let charset; + let result; + let contentDecoder; + const contentDecoders = new Map(); + let contentTypeDecoder; + const contentTypeDecoders = new Map(); + if (options === void 0 || typeof options === "string") { + charset = options !== null && options !== void 0 ? options : "utf-8"; + } else { + charset = (_a2 = options.charset) !== null && _a2 !== void 0 ? _a2 : "utf-8"; + if (options.contentDecoder !== void 0) { + contentDecoder = options.contentDecoder; + contentDecoders.set(contentDecoder.name, contentDecoder); + } + if (options.contentDecoders !== void 0) { + for (const decoder of options.contentDecoders) { + contentDecoders.set(decoder.name, decoder); + } + } + if (options.contentTypeDecoder !== void 0) { + contentTypeDecoder = options.contentTypeDecoder; + contentTypeDecoders.set(contentTypeDecoder.name, contentTypeDecoder); + } + if (options.contentTypeDecoders !== void 0) { + for (const decoder of options.contentTypeDecoders) { + contentTypeDecoders.set(decoder.name, decoder); + } + } + } + if (contentTypeDecoder === void 0) { + contentTypeDecoder = ral_1.default().applicationJson.decoder; + contentTypeDecoders.set(contentTypeDecoder.name, contentTypeDecoder); + } + return { charset, contentDecoder, contentDecoders, contentTypeDecoder, contentTypeDecoders }; + } + ResolvedMessageReaderOptions2.fromOptions = fromOptions; + })(ResolvedMessageReaderOptions || (ResolvedMessageReaderOptions = {})); + var ReadableStreamMessageReader = class extends AbstractMessageReader { + constructor(readable, options) { + super(); + this.readable = readable; + this.options = ResolvedMessageReaderOptions.fromOptions(options); + this.buffer = ral_1.default().messageBuffer.create(this.options.charset); + this._partialMessageTimeout = 1e4; + this.nextMessageLength = -1; + this.messageToken = 0; + } + set partialMessageTimeout(timeout) { + this._partialMessageTimeout = timeout; + } + get partialMessageTimeout() { + return this._partialMessageTimeout; + } + listen(callback) { + this.nextMessageLength = -1; + this.messageToken = 0; + this.partialMessageTimer = void 0; + this.callback = callback; + const result = this.readable.onData((data) => { + this.onData(data); + }); + this.readable.onError((error) => this.fireError(error)); + this.readable.onClose(() => this.fireClose()); + return result; + } + onData(data) { + this.buffer.append(data); + while (true) { + if (this.nextMessageLength === -1) { + const headers = this.buffer.tryReadHeaders(); + if (!headers) { + return; + } + const contentLength = headers.get("Content-Length"); + if (!contentLength) { + throw new Error("Header must provide a Content-Length property."); + } + const length = parseInt(contentLength); + if (isNaN(length)) { + throw new Error("Content-Length value must be a number."); + } + this.nextMessageLength = length; + } + const body = this.buffer.tryReadBody(this.nextMessageLength); + if (body === void 0) { + this.setPartialMessageTimer(); + return; + } + this.clearPartialMessageTimer(); + this.nextMessageLength = -1; + let p; + if (this.options.contentDecoder !== void 0) { + p = this.options.contentDecoder.decode(body); + } else { + p = Promise.resolve(body); + } + p.then((value) => { + this.options.contentTypeDecoder.decode(value, this.options).then((msg) => { + this.callback(msg); + }, (error) => { + this.fireError(error); + }); + }, (error) => { + this.fireError(error); + }); + } + } + clearPartialMessageTimer() { + if (this.partialMessageTimer) { + ral_1.default().timer.clearTimeout(this.partialMessageTimer); + this.partialMessageTimer = void 0; + } + } + setPartialMessageTimer() { + this.clearPartialMessageTimer(); + if (this._partialMessageTimeout <= 0) { + return; + } + this.partialMessageTimer = ral_1.default().timer.setTimeout((token, timeout) => { + this.partialMessageTimer = void 0; + if (token === this.messageToken) { + this.firePartialMessage({ messageToken: token, waitingTime: timeout }); + this.setPartialMessageTimer(); + } + }, this._partialMessageTimeout, this.messageToken, this._partialMessageTimeout); + } + }; + exports2.ReadableStreamMessageReader = ReadableStreamMessageReader; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/semaphore.js +var require_semaphore = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/semaphore.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Semaphore = void 0; + var ral_1 = require_ral(); + var Semaphore = class { + constructor(capacity = 1) { + if (capacity <= 0) { + throw new Error("Capacity must be greater than 0"); + } + this._capacity = capacity; + this._active = 0; + this._waiting = []; + } + lock(thunk) { + return new Promise((resolve3, reject) => { + this._waiting.push({ thunk, resolve: resolve3, reject }); + this.runNext(); + }); + } + get active() { + return this._active; + } + runNext() { + if (this._waiting.length === 0 || this._active === this._capacity) { + return; + } + ral_1.default().timer.setImmediate(() => this.doRunNext()); + } + doRunNext() { + if (this._waiting.length === 0 || this._active === this._capacity) { + return; + } + const next = this._waiting.shift(); + this._active++; + if (this._active > this._capacity) { + throw new Error(`To many thunks active`); + } + try { + const result = next.thunk(); + if (result instanceof Promise) { + result.then((value) => { + this._active--; + next.resolve(value); + this.runNext(); + }, (err) => { + this._active--; + next.reject(err); + this.runNext(); + }); + } else { + this._active--; + next.resolve(result); + this.runNext(); + } + } catch (err) { + this._active--; + next.reject(err); + this.runNext(); + } + } + }; + exports2.Semaphore = Semaphore; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/messageWriter.js +var require_messageWriter = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/messageWriter.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WriteableStreamMessageWriter = exports2.AbstractMessageWriter = exports2.MessageWriter = void 0; + var ral_1 = require_ral(); + var Is7 = require_is(); + var semaphore_1 = require_semaphore(); + var events_1 = require_events(); + var ContentLength = "Content-Length: "; + var CRLF = "\r\n"; + var MessageWriter2; + (function(MessageWriter3) { + function is(value) { + let candidate = value; + return candidate && Is7.func(candidate.dispose) && Is7.func(candidate.onClose) && Is7.func(candidate.onError) && Is7.func(candidate.write); + } + MessageWriter3.is = is; + })(MessageWriter2 = exports2.MessageWriter || (exports2.MessageWriter = {})); + var AbstractMessageWriter = class { + 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(void 0); + } + asError(error) { + if (error instanceof Error) { + return error; + } else { + return new Error(`Writer received error. Reason: ${Is7.string(error.message) ? error.message : "unknown"}`); + } + } + }; + exports2.AbstractMessageWriter = AbstractMessageWriter; + var ResolvedMessageWriterOptions; + (function(ResolvedMessageWriterOptions2) { + function fromOptions(options) { + var _a2, _b; + if (options === void 0 || typeof options === "string") { + return { charset: options !== null && options !== void 0 ? options : "utf-8", contentTypeEncoder: ral_1.default().applicationJson.encoder }; + } else { + return { charset: (_a2 = options.charset) !== null && _a2 !== void 0 ? _a2 : "utf-8", contentEncoder: options.contentEncoder, contentTypeEncoder: (_b = options.contentTypeEncoder) !== null && _b !== void 0 ? _b : ral_1.default().applicationJson.encoder }; + } + } + ResolvedMessageWriterOptions2.fromOptions = fromOptions; + })(ResolvedMessageWriterOptions || (ResolvedMessageWriterOptions = {})); + var WriteableStreamMessageWriter = class extends AbstractMessageWriter { + constructor(writable, options) { + super(); + this.writable = writable; + this.options = ResolvedMessageWriterOptions.fromOptions(options); + this.errorCount = 0; + this.writeSemaphore = new semaphore_1.Semaphore(1); + this.writable.onError((error) => this.fireError(error)); + this.writable.onClose(() => this.fireClose()); + } + async write(msg) { + return this.writeSemaphore.lock(async () => { + const payload = this.options.contentTypeEncoder.encode(msg, this.options).then((buffer) => { + if (this.options.contentEncoder !== void 0) { + return this.options.contentEncoder.encode(buffer); + } else { + return buffer; + } + }); + return payload.then((buffer) => { + const headers = []; + headers.push(ContentLength, buffer.byteLength.toString(), CRLF); + headers.push(CRLF); + return this.doWrite(msg, headers, buffer); + }, (error) => { + this.fireError(error); + throw error; + }); + }); + } + async doWrite(msg, headers, data) { + try { + await this.writable.write(headers.join(""), "ascii"); + return this.writable.write(data); + } catch (error) { + this.handleError(error, msg); + return Promise.reject(error); + } + } + handleError(error, msg) { + this.errorCount++; + this.fireError(error, msg, this.errorCount); + } + end() { + this.writable.end(); + } + }; + exports2.WriteableStreamMessageWriter = WriteableStreamMessageWriter; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/linkedMap.js +var require_linkedMap = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/linkedMap.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.LRUCache = exports2.LinkedMap = exports2.Touch = void 0; + var Touch; + (function(Touch2) { + Touch2.None = 0; + Touch2.First = 1; + Touch2.AsOld = Touch2.First; + Touch2.Last = 2; + Touch2.AsNew = Touch2.Last; + })(Touch = exports2.Touch || (exports2.Touch = {})); + var LinkedMap = class { + constructor() { + this[Symbol.toStringTag] = "LinkedMap"; + this._map = new Map(); + this._head = void 0; + this._tail = void 0; + this._size = 0; + this._state = 0; + } + clear() { + this._map.clear(); + this._head = void 0; + this._tail = void 0; + this._size = 0; + this._state++; + } + isEmpty() { + return !this._head && !this._tail; + } + get size() { + return this._size; + } + get first() { + var _a2; + return (_a2 = this._head) === null || _a2 === void 0 ? void 0 : _a2.value; + } + get last() { + var _a2; + return (_a2 = this._tail) === null || _a2 === void 0 ? void 0 : _a2.value; + } + has(key) { + return this._map.has(key); + } + get(key, touch = Touch.None) { + const item = this._map.get(key); + if (!item) { + return void 0; + } + if (touch !== Touch.None) { + this.touch(item, touch); + } + 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: void 0, previous: void 0 }; + 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++; + } + return this; + } + delete(key) { + return !!this.remove(key); + } + remove(key) { + const item = this._map.get(key); + if (!item) { + return void 0; + } + this._map.delete(key); + this.removeItem(item); + this._size--; + return item.value; + } + shift() { + if (!this._head && !this._tail) { + return void 0; + } + 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) { + const state = this._state; + let current = this._head; + while (current) { + if (thisArg) { + callbackfn.bind(thisArg)(current.value, current.key, this); + } else { + callbackfn(current.value, current.key, this); + } + if (this._state !== state) { + throw new Error(`LinkedMap got modified during iteration.`); + } + current = current.next; + } + } + keys() { + const map = this; + const state = this._state; + let current = this._head; + const iterator = { + [Symbol.iterator]() { + return iterator; + }, + next() { + if (map._state !== state) { + throw new Error(`LinkedMap got modified during iteration.`); + } + if (current) { + const result = { value: current.key, done: false }; + current = current.next; + return result; + } else { + return { value: void 0, done: true }; + } + } + }; + return iterator; + } + values() { + const map = this; + const state = this._state; + let current = this._head; + const iterator = { + [Symbol.iterator]() { + return iterator; + }, + next() { + if (map._state !== state) { + throw new Error(`LinkedMap got modified during iteration.`); + } + if (current) { + const result = { value: current.value, done: false }; + current = current.next; + return result; + } else { + return { value: void 0, done: true }; + } + } + }; + return iterator; + } + entries() { + const map = this; + const state = this._state; + let current = this._head; + const iterator = { + [Symbol.iterator]() { + return iterator; + }, + next() { + if (map._state !== state) { + throw new Error(`LinkedMap got modified during iteration.`); + } + if (current) { + const result = { value: [current.key, current.value], done: false }; + current = current.next; + return result; + } else { + return { value: void 0, done: true }; + } + } + }; + return iterator; + } + [Symbol.iterator]() { + return this.entries(); + } + trimOld(newSize) { + if (newSize >= this.size) { + return; + } + if (newSize === 0) { + this.clear(); + return; + } + let current = this._head; + let currentSize = this.size; + while (current && currentSize > newSize) { + this._map.delete(current.key); + current = current.next; + currentSize--; + } + this._head = current; + this._size = currentSize; + if (current) { + current.previous = void 0; + } + this._state++; + } + addItemFirst(item) { + 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; + this._state++; + } + addItemLast(item) { + 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; + this._state++; + } + removeItem(item) { + if (item === this._head && item === this._tail) { + this._head = void 0; + this._tail = void 0; + } else if (item === this._head) { + if (!item.next) { + throw new Error("Invalid list"); + } + item.next.previous = void 0; + this._head = item.next; + } else if (item === this._tail) { + if (!item.previous) { + throw new Error("Invalid list"); + } + item.previous.next = void 0; + 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; + } + item.next = void 0; + item.previous = void 0; + this._state++; + } + 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; + if (item === this._tail) { + previous.next = void 0; + this._tail = previous; + } else { + next.previous = previous; + previous.next = next; + } + item.previous = void 0; + item.next = this._head; + this._head.previous = item; + this._head = item; + this._state++; + } else if (touch === Touch.Last) { + if (item === this._tail) { + return; + } + const next = item.next; + const previous = item.previous; + if (item === this._head) { + next.previous = void 0; + this._head = next; + } else { + next.previous = previous; + previous.next = next; + } + item.next = void 0; + item.previous = this._tail; + this._tail.next = item; + this._tail = item; + this._state++; + } + } + toJSON() { + const data = []; + this.forEach((value, key) => { + data.push([key, value]); + }); + return data; + } + fromJSON(data) { + this.clear(); + for (const [key, value] of data) { + this.set(key, value); + } + } + }; + exports2.LinkedMap = LinkedMap; + var LRUCache = class extends LinkedMap { + constructor(limit, ratio = 1) { + super(); + this._limit = limit; + this._ratio = Math.min(Math.max(0, ratio), 1); + } + get limit() { + return this._limit; + } + set limit(limit) { + this._limit = limit; + this.checkTrim(); + } + get ratio() { + return this._ratio; + } + set ratio(ratio) { + this._ratio = Math.min(Math.max(0, ratio), 1); + this.checkTrim(); + } + get(key, touch = Touch.AsNew) { + return super.get(key, touch); + } + peek(key) { + return super.get(key, Touch.None); + } + set(key, value) { + super.set(key, value, Touch.Last); + this.checkTrim(); + return this; + } + checkTrim() { + if (this.size > this._limit) { + this.trimOld(Math.round(this._limit * this._ratio)); + } + } + }; + exports2.LRUCache = LRUCache; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/connection.js +var require_connection2 = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/connection.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createMessageConnection = exports2.ConnectionOptions = exports2.CancellationStrategy = exports2.CancellationSenderStrategy = exports2.CancellationReceiverStrategy = exports2.ConnectionStrategy = exports2.ConnectionError = exports2.ConnectionErrors = exports2.LogTraceNotification = exports2.SetTraceNotification = exports2.TraceFormat = exports2.Trace = exports2.NullLogger = exports2.ProgressType = void 0; + var ral_1 = require_ral(); + var Is7 = require_is(); + var messages_1 = require_messages(); + var linkedMap_1 = require_linkedMap(); + var events_1 = require_events(); + var cancellation_1 = require_cancellation(); + var CancelNotification; + (function(CancelNotification2) { + CancelNotification2.type = new messages_1.NotificationType("$/cancelRequest"); + })(CancelNotification || (CancelNotification = {})); + var ProgressNotification2; + (function(ProgressNotification3) { + ProgressNotification3.type = new messages_1.NotificationType("$/progress"); + })(ProgressNotification2 || (ProgressNotification2 = {})); + var ProgressType4 = class { + constructor() { + } + }; + exports2.ProgressType = ProgressType4; + var StarRequestHandler; + (function(StarRequestHandler2) { + function is(value) { + return Is7.func(value); + } + StarRequestHandler2.is = is; + })(StarRequestHandler || (StarRequestHandler = {})); + exports2.NullLogger = Object.freeze({ + error: () => { + }, + warn: () => { + }, + info: () => { + }, + log: () => { + } + }); + var Trace2; + (function(Trace3) { + Trace3[Trace3["Off"] = 0] = "Off"; + Trace3[Trace3["Messages"] = 1] = "Messages"; + Trace3[Trace3["Verbose"] = 2] = "Verbose"; + })(Trace2 = exports2.Trace || (exports2.Trace = {})); + (function(Trace3) { + function fromString(value) { + if (!Is7.string(value)) { + return Trace3.Off; + } + value = value.toLowerCase(); + switch (value) { + case "off": + return Trace3.Off; + case "messages": + return Trace3.Messages; + case "verbose": + return Trace3.Verbose; + default: + return Trace3.Off; + } + } + Trace3.fromString = fromString; + function toString(value) { + switch (value) { + case Trace3.Off: + return "off"; + case Trace3.Messages: + return "messages"; + case Trace3.Verbose: + return "verbose"; + default: + return "off"; + } + } + Trace3.toString = toString; + })(Trace2 = exports2.Trace || (exports2.Trace = {})); + var TraceFormat2; + (function(TraceFormat3) { + TraceFormat3["Text"] = "text"; + TraceFormat3["JSON"] = "json"; + })(TraceFormat2 = exports2.TraceFormat || (exports2.TraceFormat = {})); + (function(TraceFormat3) { + function fromString(value) { + value = value.toLowerCase(); + if (value === "json") { + return TraceFormat3.JSON; + } else { + return TraceFormat3.Text; + } + } + TraceFormat3.fromString = fromString; + })(TraceFormat2 = exports2.TraceFormat || (exports2.TraceFormat = {})); + var SetTraceNotification; + (function(SetTraceNotification2) { + SetTraceNotification2.type = new messages_1.NotificationType("$/setTrace"); + })(SetTraceNotification = exports2.SetTraceNotification || (exports2.SetTraceNotification = {})); + var LogTraceNotification; + (function(LogTraceNotification2) { + LogTraceNotification2.type = new messages_1.NotificationType("$/logTrace"); + })(LogTraceNotification = exports2.LogTraceNotification || (exports2.LogTraceNotification = {})); + var ConnectionErrors; + (function(ConnectionErrors2) { + ConnectionErrors2[ConnectionErrors2["Closed"] = 1] = "Closed"; + ConnectionErrors2[ConnectionErrors2["Disposed"] = 2] = "Disposed"; + ConnectionErrors2[ConnectionErrors2["AlreadyListening"] = 3] = "AlreadyListening"; + })(ConnectionErrors = exports2.ConnectionErrors || (exports2.ConnectionErrors = {})); + var ConnectionError = class extends Error { + constructor(code, message) { + super(message); + this.code = code; + Object.setPrototypeOf(this, ConnectionError.prototype); + } + }; + exports2.ConnectionError = ConnectionError; + var ConnectionStrategy; + (function(ConnectionStrategy2) { + function is(value) { + const candidate = value; + return candidate && Is7.func(candidate.cancelUndispatched); + } + ConnectionStrategy2.is = is; + })(ConnectionStrategy = exports2.ConnectionStrategy || (exports2.ConnectionStrategy = {})); + var CancellationReceiverStrategy; + (function(CancellationReceiverStrategy2) { + CancellationReceiverStrategy2.Message = Object.freeze({ + createCancellationTokenSource(_) { + return new cancellation_1.CancellationTokenSource(); + } + }); + function is(value) { + const candidate = value; + return candidate && Is7.func(candidate.createCancellationTokenSource); + } + CancellationReceiverStrategy2.is = is; + })(CancellationReceiverStrategy = exports2.CancellationReceiverStrategy || (exports2.CancellationReceiverStrategy = {})); + var CancellationSenderStrategy; + (function(CancellationSenderStrategy2) { + CancellationSenderStrategy2.Message = Object.freeze({ + sendCancellation(conn, id) { + conn.sendNotification(CancelNotification.type, { id }); + }, + cleanup(_) { + } + }); + function is(value) { + const candidate = value; + return candidate && Is7.func(candidate.sendCancellation) && Is7.func(candidate.cleanup); + } + CancellationSenderStrategy2.is = is; + })(CancellationSenderStrategy = exports2.CancellationSenderStrategy || (exports2.CancellationSenderStrategy = {})); + var CancellationStrategy2; + (function(CancellationStrategy3) { + CancellationStrategy3.Message = Object.freeze({ + receiver: CancellationReceiverStrategy.Message, + sender: CancellationSenderStrategy.Message + }); + function is(value) { + const candidate = value; + return candidate && CancellationReceiverStrategy.is(candidate.receiver) && CancellationSenderStrategy.is(candidate.sender); + } + CancellationStrategy3.is = is; + })(CancellationStrategy2 = exports2.CancellationStrategy || (exports2.CancellationStrategy = {})); + var ConnectionOptions; + (function(ConnectionOptions2) { + function is(value) { + const candidate = value; + return candidate && (CancellationStrategy2.is(candidate.cancellationStrategy) || ConnectionStrategy.is(candidate.connectionStrategy)); + } + ConnectionOptions2.is = is; + })(ConnectionOptions = exports2.ConnectionOptions || (exports2.ConnectionOptions = {})); + var ConnectionState; + (function(ConnectionState2) { + ConnectionState2[ConnectionState2["New"] = 1] = "New"; + ConnectionState2[ConnectionState2["Listening"] = 2] = "Listening"; + ConnectionState2[ConnectionState2["Closed"] = 3] = "Closed"; + ConnectionState2[ConnectionState2["Disposed"] = 4] = "Disposed"; + })(ConnectionState || (ConnectionState = {})); + function createMessageConnection(messageReader, messageWriter, _logger, options) { + const logger113 = _logger !== void 0 ? _logger : exports2.NullLogger; + let sequenceNumber = 0; + let notificationSquenceNumber = 0; + let unknownResponseSquenceNumber = 0; + const version2 = "2.0"; + let starRequestHandler = void 0; + const requestHandlers = Object.create(null); + let starNotificationHandler = void 0; + const notificationHandlers = Object.create(null); + const progressHandlers = new Map(); + let timer; + let messageQueue = new linkedMap_1.LinkedMap(); + let responsePromises = Object.create(null); + let requestTokens = Object.create(null); + let trace = Trace2.Off; + let traceFormat = TraceFormat2.Text; + let tracer; + let state = ConnectionState.New; + const errorEmitter = new events_1.Emitter(); + const closeEmitter = new events_1.Emitter(); + const unhandledNotificationEmitter = new events_1.Emitter(); + const unhandledProgressEmitter = new events_1.Emitter(); + const disposeEmitter = new events_1.Emitter(); + const cancellationStrategy = options && options.cancellationStrategy ? options.cancellationStrategy : CancellationStrategy2.Message; + function createRequestQueueKey(id) { + if (id === null) { + throw new Error(`Can't send requests with id null since the response can't be correlated.`); + } + 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 void 0; + } + 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(void 0); + } + } + function readErrorHandler(error) { + errorEmitter.fire([error, void 0, void 0]); + } + 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 = ral_1.default().timer.setImmediate(() => { + timer = void 0; + processMessageQueue(); + }); + } + function processMessageQueue() { + if (messageQueue.size === 0) { + return; + } + const 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(); + } + } + const callback = (message) => { + try { + if (messages_1.isNotificationMessage(message) && message.method === CancelNotification.type.method) { + const key = createRequestQueueKey(message.params.id); + const toCancel = messageQueue.get(key); + if (messages_1.isRequestMessage(toCancel)) { + const strategy = options === null || options === void 0 ? void 0 : options.connectionStrategy; + const 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()) { + return; + } + function reply(resultOrError, method, startTime2) { + const message = { + jsonrpc: version2, + id: requestMessage.id + }; + if (resultOrError instanceof messages_1.ResponseError) { + message.error = resultOrError.toJson(); + } else { + message.result = resultOrError === void 0 ? null : resultOrError; + } + traceSendingResponse(message, method, startTime2); + messageWriter.write(message); + } + function replyError(error, method, startTime2) { + const message = { + jsonrpc: version2, + id: requestMessage.id, + error: error.toJson() + }; + traceSendingResponse(message, method, startTime2); + messageWriter.write(message); + } + function replySuccess(result, method, startTime2) { + if (result === void 0) { + result = null; + } + const message = { + jsonrpc: version2, + id: requestMessage.id, + result + }; + traceSendingResponse(message, method, startTime2); + messageWriter.write(message); + } + traceReceivedRequest(requestMessage); + const element = requestHandlers[requestMessage.method]; + let type; + let requestHandler; + if (element) { + type = element.type; + requestHandler = element.handler; + } + const startTime = Date.now(); + if (requestHandler || starRequestHandler) { + const tokenKey = String(requestMessage.id); + const cancellationSource = cancellationStrategy.receiver.createCancellationTokenSource(tokenKey); + requestTokens[tokenKey] = cancellationSource; + try { + let handlerResult; + if (requestHandler) { + if (requestMessage.params === void 0) { + if (type !== void 0 && type.numberOfParams !== 0) { + replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines ${type.numberOfParams} params but recevied none.`), requestMessage.method, startTime); + return; + } + handlerResult = requestHandler(cancellationSource.token); + } else if (Array.isArray(requestMessage.params)) { + if (type !== void 0 && type.parameterStructures === messages_1.ParameterStructures.byName) { + replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines parameters by name but received parameters by position`), requestMessage.method, startTime); + return; + } + handlerResult = requestHandler(...requestMessage.params, cancellationSource.token); + } else { + if (type !== void 0 && type.parameterStructures === messages_1.ParameterStructures.byPosition) { + replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines parameters by position but received parameters by name`), requestMessage.method, startTime); + return; + } + handlerResult = requestHandler(requestMessage.params, cancellationSource.token); + } + } else if (starRequestHandler) { + handlerResult = starRequestHandler(requestMessage.method, requestMessage.params, cancellationSource.token); + } + const 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 && Is7.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 && Is7.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()) { + return; + } + if (responseMessage.id === null) { + if (responseMessage.error) { + logger113.error(`Received response message without id: Error is: +${JSON.stringify(responseMessage.error, void 0, 4)}`); + } else { + logger113.error(`Received response message without id. No further error information provided.`); + } + } else { + const key = String(responseMessage.id); + const responsePromise = responsePromises[key]; + traceReceivedResponse(responseMessage, responsePromise); + if (responsePromise) { + delete responsePromises[key]; + try { + if (responseMessage.error) { + const 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) { + logger113.error(`Response handler '${responsePromise.method}' failed with message: ${error.message}`); + } else { + logger113.error(`Response handler '${responsePromise.method}' failed unexpectedly.`); + } + } + } + } + } + function handleNotification(message) { + if (isDisposed()) { + return; + } + let type = void 0; + let notificationHandler; + if (message.method === CancelNotification.type.method) { + notificationHandler = (params) => { + const id = params.id; + const source = requestTokens[String(id)]; + if (source) { + source.cancel(); + } + }; + } else { + const element = notificationHandlers[message.method]; + if (element) { + notificationHandler = element.handler; + type = element.type; + } + } + if (notificationHandler || starNotificationHandler) { + try { + traceReceivedNotification(message); + if (notificationHandler) { + if (message.params === void 0) { + if (type !== void 0) { + if (type.numberOfParams !== 0 && type.parameterStructures !== messages_1.ParameterStructures.byName) { + logger113.error(`Notification ${message.method} defines ${type.numberOfParams} params but recevied none.`); + } + } + notificationHandler(); + } else if (Array.isArray(message.params)) { + if (type !== void 0) { + if (type.parameterStructures === messages_1.ParameterStructures.byName) { + logger113.error(`Notification ${message.method} defines parameters by name but received parameters by position`); + } + if (type.numberOfParams !== message.params.length) { + logger113.error(`Notification ${message.method} defines ${type.numberOfParams} params but received ${message.params.length} argumennts`); + } + } + notificationHandler(...message.params); + } else { + if (type !== void 0 && type.parameterStructures === messages_1.ParameterStructures.byPosition) { + logger113.error(`Notification ${message.method} defines parameters by position but received parameters by name`); + } + notificationHandler(message.params); + } + } else if (starNotificationHandler) { + starNotificationHandler(message.method, message.params); + } + } catch (error) { + if (error.message) { + logger113.error(`Notification handler '${message.method}' failed with message: ${error.message}`); + } else { + logger113.error(`Notification handler '${message.method}' failed unexpectedly.`); + } + } + } else { + unhandledNotificationEmitter.fire(message); + } + } + function handleInvalidMessage(message) { + if (!message) { + logger113.error("Received empty message."); + return; + } + logger113.error(`Received message which is neither a response nor a notification message: +${JSON.stringify(message, null, 4)}`); + const responseMessage = message; + if (Is7.string(responseMessage.id) || Is7.number(responseMessage.id)) { + const key = String(responseMessage.id); + const 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 === Trace2.Off || !tracer) { + return; + } + if (traceFormat === TraceFormat2.Text) { + let data = void 0; + if (trace === Trace2.Verbose && message.params) { + data = `Params: ${JSON.stringify(message.params, null, 4)} + +`; + } + tracer.log(`Sending request '${message.method} - (${message.id})'.`, data); + } else { + logLSPMessage("send-request", message); + } + } + function traceSendingNotification(message) { + if (trace === Trace2.Off || !tracer) { + return; + } + if (traceFormat === TraceFormat2.Text) { + let data = void 0; + if (trace === Trace2.Verbose) { + if (message.params) { + data = `Params: ${JSON.stringify(message.params, null, 4)} + +`; + } 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 === Trace2.Off || !tracer) { + return; + } + if (traceFormat === TraceFormat2.Text) { + let data = void 0; + if (trace === Trace2.Verbose) { + if (message.error && message.error.data) { + data = `Error data: ${JSON.stringify(message.error.data, null, 4)} + +`; + } else { + if (message.result) { + data = `Result: ${JSON.stringify(message.result, null, 4)} + +`; + } 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 === Trace2.Off || !tracer) { + return; + } + if (traceFormat === TraceFormat2.Text) { + let data = void 0; + if (trace === Trace2.Verbose && message.params) { + data = `Params: ${JSON.stringify(message.params, null, 4)} + +`; + } + tracer.log(`Received request '${message.method} - (${message.id})'.`, data); + } else { + logLSPMessage("receive-request", message); + } + } + function traceReceivedNotification(message) { + if (trace === Trace2.Off || !tracer || message.method === LogTraceNotification.type.method) { + return; + } + if (traceFormat === TraceFormat2.Text) { + let data = void 0; + if (trace === Trace2.Verbose) { + if (message.params) { + data = `Params: ${JSON.stringify(message.params, null, 4)} + +`; + } 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 === Trace2.Off || !tracer) { + return; + } + if (traceFormat === TraceFormat2.Text) { + let data = void 0; + if (trace === Trace2.Verbose) { + if (message.error && message.error.data) { + data = `Error data: ${JSON.stringify(message.error.data, null, 4)} + +`; + } else { + if (message.result) { + data = `Result: ${JSON.stringify(message.result, null, 4)} + +`; + } else if (message.error === void 0) { + data = "No result returned.\n\n"; + } + } + } + if (responsePromise) { + const 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 === Trace2.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 nullToUndefined(param) { + if (param === null) { + return void 0; + } else { + return param; + } + } + function isNamedParam(param) { + return param !== void 0 && param !== null && !Array.isArray(param) && typeof param === "object"; + } + function computeSingleParam(parameterStructures, param) { + switch (parameterStructures) { + case messages_1.ParameterStructures.auto: + if (isNamedParam(param)) { + return nullToUndefined(param); + } else { + return [undefinedToNull(param)]; + } + break; + case messages_1.ParameterStructures.byName: + if (!isNamedParam(param)) { + throw new Error(`Recevied parameters by name but param is not an object literal.`); + } + return nullToUndefined(param); + case messages_1.ParameterStructures.byPosition: + return [undefinedToNull(param)]; + default: + throw new Error(`Unknown parameter structure ${parameterStructures.toString()}`); + } + } + function computeMessageParams(type, params) { + let result; + const numberOfParams = type.numberOfParams; + switch (numberOfParams) { + case 0: + result = void 0; + break; + case 1: + result = computeSingleParam(type.parameterStructures, 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; + } + const connection = { + sendNotification: (type, ...args) => { + throwIfClosedOrDisposed(); + let method; + let messageParams; + if (Is7.string(type)) { + method = type; + const first = args[0]; + let paramStart = 0; + let parameterStructures = messages_1.ParameterStructures.auto; + if (messages_1.ParameterStructures.is(first)) { + paramStart = 1; + parameterStructures = first; + } + let paramEnd = args.length; + const numberOfParams = paramEnd - paramStart; + switch (numberOfParams) { + case 0: + messageParams = void 0; + break; + case 1: + messageParams = computeSingleParam(parameterStructures, args[paramStart]); + break; + default: + if (parameterStructures === messages_1.ParameterStructures.byName) { + throw new Error(`Recevied ${numberOfParams} parameters for 'by Name' notification parameter structure.`); + } + messageParams = args.slice(paramStart, paramEnd).map((value) => undefinedToNull(value)); + break; + } + } else { + const params = args; + method = type.method; + messageParams = computeMessageParams(type, params); + } + const notificationMessage = { + jsonrpc: version2, + method, + params: messageParams + }; + traceSendingNotification(notificationMessage); + messageWriter.write(notificationMessage); + }, + onNotification: (type, handler) => { + throwIfClosedOrDisposed(); + let method; + if (Is7.func(type)) { + starNotificationHandler = type; + } else if (handler) { + if (Is7.string(type)) { + method = type; + notificationHandlers[type] = { type: void 0, handler }; + } else { + method = type.method; + notificationHandlers[type.method] = { type, handler }; + } + } + return { + dispose: () => { + if (method !== void 0) { + delete notificationHandlers[method]; + } else { + starNotificationHandler = void 0; + } + } + }; + }, + onProgress: (_type, token, handler) => { + if (progressHandlers.has(token)) { + throw new Error(`Progress handler for token ${token} already registered`); + } + progressHandlers.set(token, handler); + return { + dispose: () => { + progressHandlers.delete(token); + } + }; + }, + sendProgress: (_type, token, value) => { + connection.sendNotification(ProgressNotification2.type, { token, value }); + }, + onUnhandledProgress: unhandledProgressEmitter.event, + sendRequest: (type, ...args) => { + throwIfClosedOrDisposed(); + throwIfNotListening(); + let method; + let messageParams; + let token = void 0; + if (Is7.string(type)) { + method = type; + const first = args[0]; + const last = args[args.length - 1]; + let paramStart = 0; + let parameterStructures = messages_1.ParameterStructures.auto; + if (messages_1.ParameterStructures.is(first)) { + paramStart = 1; + parameterStructures = first; + } + let paramEnd = args.length; + if (cancellation_1.CancellationToken.is(last)) { + paramEnd = paramEnd - 1; + token = last; + } + const numberOfParams = paramEnd - paramStart; + switch (numberOfParams) { + case 0: + messageParams = void 0; + break; + case 1: + messageParams = computeSingleParam(parameterStructures, args[paramStart]); + break; + default: + if (parameterStructures === messages_1.ParameterStructures.byName) { + throw new Error(`Recevied ${numberOfParams} parameters for 'by Name' request parameter structure.`); + } + messageParams = args.slice(paramStart, paramEnd).map((value) => undefinedToNull(value)); + break; + } + } else { + const params = args; + method = type.method; + messageParams = computeMessageParams(type, params); + const numberOfParams = type.numberOfParams; + token = cancellation_1.CancellationToken.is(params[numberOfParams]) ? params[numberOfParams] : void 0; + } + const id = sequenceNumber++; + let disposable; + if (token) { + disposable = token.onCancellationRequested(() => { + cancellationStrategy.sender.sendCancellation(connection, id); + }); + } + const result = new Promise((resolve3, reject) => { + const requestMessage = { + jsonrpc: version2, + id, + method, + params: messageParams + }; + const resolveWithCleanup = (r) => { + resolve3(r); + cancellationStrategy.sender.cleanup(id); + disposable === null || disposable === void 0 ? void 0 : disposable.dispose(); + }; + const rejectWithCleanup = (r) => { + reject(r); + cancellationStrategy.sender.cleanup(id); + disposable === null || disposable === void 0 ? void 0 : disposable.dispose(); + }; + let responsePromise = { method, timerStart: Date.now(), resolve: resolveWithCleanup, reject: rejectWithCleanup }; + traceSendingRequest(requestMessage); + try { + messageWriter.write(requestMessage); + } catch (e) { + responsePromise.reject(new messages_1.ResponseError(messages_1.ErrorCodes.MessageWriteError, e.message ? e.message : "Unknown reason")); + responsePromise = null; + } + if (responsePromise) { + responsePromises[String(id)] = responsePromise; + } + }); + return result; + }, + onRequest: (type, handler) => { + throwIfClosedOrDisposed(); + let method = null; + if (StarRequestHandler.is(type)) { + method = void 0; + starRequestHandler = type; + } else if (Is7.string(type)) { + method = null; + if (handler !== void 0) { + method = type; + requestHandlers[type] = { handler, type: void 0 }; + } + } else { + if (handler !== void 0) { + method = type.method; + requestHandlers[type.method] = { type, handler }; + } + } + return { + dispose: () => { + if (method === null) { + return; + } + if (method !== void 0) { + delete requestHandlers[method]; + } else { + starRequestHandler = void 0; + } + } + }; + }, + trace: (_value, _tracer, sendNotificationOrTraceOptions) => { + let _sendNotification = false; + let _traceFormat = TraceFormat2.Text; + if (sendNotificationOrTraceOptions !== void 0) { + if (Is7.boolean(sendNotificationOrTraceOptions)) { + _sendNotification = sendNotificationOrTraceOptions; + } else { + _sendNotification = sendNotificationOrTraceOptions.sendNotification || false; + _traceFormat = sendNotificationOrTraceOptions.traceFormat || TraceFormat2.Text; + } + } + trace = _value; + traceFormat = _traceFormat; + if (trace === Trace2.Off) { + tracer = void 0; + } else { + tracer = _tracer; + } + if (_sendNotification && !isClosed() && !isDisposed()) { + connection.sendNotification(SetTraceNotification.type, { value: Trace2.toString(_value) }); + } + }, + onError: errorEmitter.event, + onClose: closeEmitter.event, + onUnhandledNotification: unhandledNotificationEmitter.event, + onDispose: disposeEmitter.event, + end: () => { + messageWriter.end(); + }, + dispose: () => { + if (isDisposed()) { + return; + } + state = ConnectionState.Disposed; + disposeEmitter.fire(void 0); + const 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(); + if (Is7.func(messageWriter.dispose)) { + messageWriter.dispose(); + } + if (Is7.func(messageReader.dispose)) { + messageReader.dispose(); + } + }, + listen: () => { + throwIfClosedOrDisposed(); + throwIfListening(); + state = ConnectionState.Listening; + messageReader.listen(callback); + }, + inspect: () => { + ral_1.default().console.log("inspect"); + } + }; + connection.onNotification(LogTraceNotification.type, (params) => { + if (trace === Trace2.Off || !tracer) { + return; + } + tracer.log(params.message, trace === Trace2.Verbose ? params.verbose : void 0); + }); + connection.onNotification(ProgressNotification2.type, (params) => { + const handler = progressHandlers.get(params.token); + if (handler) { + handler(params.value); + } else { + unhandledProgressEmitter.fire(params); + } + }); + return connection; + } + exports2.createMessageConnection = createMessageConnection; + } +}); + +// node_modules/vscode-jsonrpc/lib/common/api.js +var require_api2 = __commonJS({ + "node_modules/vscode-jsonrpc/lib/common/api.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.CancellationSenderStrategy = exports2.CancellationReceiverStrategy = exports2.ConnectionError = exports2.ConnectionErrors = exports2.LogTraceNotification = exports2.SetTraceNotification = exports2.TraceFormat = exports2.Trace = exports2.ProgressType = exports2.createMessageConnection = exports2.NullLogger = exports2.ConnectionOptions = exports2.ConnectionStrategy = exports2.WriteableStreamMessageWriter = exports2.AbstractMessageWriter = exports2.MessageWriter = exports2.ReadableStreamMessageReader = exports2.AbstractMessageReader = exports2.MessageReader = exports2.CancellationToken = exports2.CancellationTokenSource = exports2.Emitter = exports2.Event = exports2.Disposable = exports2.ParameterStructures = exports2.NotificationType9 = exports2.NotificationType8 = exports2.NotificationType7 = exports2.NotificationType6 = exports2.NotificationType5 = exports2.NotificationType4 = exports2.NotificationType3 = exports2.NotificationType2 = exports2.NotificationType1 = exports2.NotificationType0 = exports2.NotificationType = exports2.ErrorCodes = exports2.ResponseError = exports2.RequestType9 = exports2.RequestType8 = exports2.RequestType7 = exports2.RequestType6 = exports2.RequestType5 = exports2.RequestType4 = exports2.RequestType3 = exports2.RequestType2 = exports2.RequestType1 = exports2.RequestType0 = exports2.RequestType = exports2.RAL = void 0; + exports2.CancellationStrategy = void 0; + var messages_1 = require_messages(); + Object.defineProperty(exports2, "RequestType", { enumerable: true, get: function() { + return messages_1.RequestType; + } }); + Object.defineProperty(exports2, "RequestType0", { enumerable: true, get: function() { + return messages_1.RequestType0; + } }); + Object.defineProperty(exports2, "RequestType1", { enumerable: true, get: function() { + return messages_1.RequestType1; + } }); + Object.defineProperty(exports2, "RequestType2", { enumerable: true, get: function() { + return messages_1.RequestType2; + } }); + Object.defineProperty(exports2, "RequestType3", { enumerable: true, get: function() { + return messages_1.RequestType3; + } }); + Object.defineProperty(exports2, "RequestType4", { enumerable: true, get: function() { + return messages_1.RequestType4; + } }); + Object.defineProperty(exports2, "RequestType5", { enumerable: true, get: function() { + return messages_1.RequestType5; + } }); + Object.defineProperty(exports2, "RequestType6", { enumerable: true, get: function() { + return messages_1.RequestType6; + } }); + Object.defineProperty(exports2, "RequestType7", { enumerable: true, get: function() { + return messages_1.RequestType7; + } }); + Object.defineProperty(exports2, "RequestType8", { enumerable: true, get: function() { + return messages_1.RequestType8; + } }); + Object.defineProperty(exports2, "RequestType9", { enumerable: true, get: function() { + return messages_1.RequestType9; + } }); + Object.defineProperty(exports2, "ResponseError", { enumerable: true, get: function() { + return messages_1.ResponseError; + } }); + Object.defineProperty(exports2, "ErrorCodes", { enumerable: true, get: function() { + return messages_1.ErrorCodes; + } }); + Object.defineProperty(exports2, "NotificationType", { enumerable: true, get: function() { + return messages_1.NotificationType; + } }); + Object.defineProperty(exports2, "NotificationType0", { enumerable: true, get: function() { + return messages_1.NotificationType0; + } }); + Object.defineProperty(exports2, "NotificationType1", { enumerable: true, get: function() { + return messages_1.NotificationType1; + } }); + Object.defineProperty(exports2, "NotificationType2", { enumerable: true, get: function() { + return messages_1.NotificationType2; + } }); + Object.defineProperty(exports2, "NotificationType3", { enumerable: true, get: function() { + return messages_1.NotificationType3; + } }); + Object.defineProperty(exports2, "NotificationType4", { enumerable: true, get: function() { + return messages_1.NotificationType4; + } }); + Object.defineProperty(exports2, "NotificationType5", { enumerable: true, get: function() { + return messages_1.NotificationType5; + } }); + Object.defineProperty(exports2, "NotificationType6", { enumerable: true, get: function() { + return messages_1.NotificationType6; + } }); + Object.defineProperty(exports2, "NotificationType7", { enumerable: true, get: function() { + return messages_1.NotificationType7; + } }); + Object.defineProperty(exports2, "NotificationType8", { enumerable: true, get: function() { + return messages_1.NotificationType8; + } }); + Object.defineProperty(exports2, "NotificationType9", { enumerable: true, get: function() { + return messages_1.NotificationType9; + } }); + Object.defineProperty(exports2, "ParameterStructures", { enumerable: true, get: function() { + return messages_1.ParameterStructures; + } }); + var disposable_1 = require_disposable(); + Object.defineProperty(exports2, "Disposable", { enumerable: true, get: function() { + return disposable_1.Disposable; + } }); + var events_1 = require_events(); + Object.defineProperty(exports2, "Event", { enumerable: true, get: function() { + return events_1.Event; + } }); + Object.defineProperty(exports2, "Emitter", { enumerable: true, get: function() { + return events_1.Emitter; + } }); + var cancellation_1 = require_cancellation(); + Object.defineProperty(exports2, "CancellationTokenSource", { enumerable: true, get: function() { + return cancellation_1.CancellationTokenSource; + } }); + Object.defineProperty(exports2, "CancellationToken", { enumerable: true, get: function() { + return cancellation_1.CancellationToken; + } }); + var messageReader_1 = require_messageReader(); + Object.defineProperty(exports2, "MessageReader", { enumerable: true, get: function() { + return messageReader_1.MessageReader; + } }); + Object.defineProperty(exports2, "AbstractMessageReader", { enumerable: true, get: function() { + return messageReader_1.AbstractMessageReader; + } }); + Object.defineProperty(exports2, "ReadableStreamMessageReader", { enumerable: true, get: function() { + return messageReader_1.ReadableStreamMessageReader; + } }); + var messageWriter_1 = require_messageWriter(); + Object.defineProperty(exports2, "MessageWriter", { enumerable: true, get: function() { + return messageWriter_1.MessageWriter; + } }); + Object.defineProperty(exports2, "AbstractMessageWriter", { enumerable: true, get: function() { + return messageWriter_1.AbstractMessageWriter; + } }); + Object.defineProperty(exports2, "WriteableStreamMessageWriter", { enumerable: true, get: function() { + return messageWriter_1.WriteableStreamMessageWriter; + } }); + var connection_1 = require_connection2(); + Object.defineProperty(exports2, "ConnectionStrategy", { enumerable: true, get: function() { + return connection_1.ConnectionStrategy; + } }); + Object.defineProperty(exports2, "ConnectionOptions", { enumerable: true, get: function() { + return connection_1.ConnectionOptions; + } }); + Object.defineProperty(exports2, "NullLogger", { enumerable: true, get: function() { + return connection_1.NullLogger; + } }); + Object.defineProperty(exports2, "createMessageConnection", { enumerable: true, get: function() { + return connection_1.createMessageConnection; + } }); + Object.defineProperty(exports2, "ProgressType", { enumerable: true, get: function() { + return connection_1.ProgressType; + } }); + Object.defineProperty(exports2, "Trace", { enumerable: true, get: function() { + return connection_1.Trace; + } }); + Object.defineProperty(exports2, "TraceFormat", { enumerable: true, get: function() { + return connection_1.TraceFormat; + } }); + Object.defineProperty(exports2, "SetTraceNotification", { enumerable: true, get: function() { + return connection_1.SetTraceNotification; + } }); + Object.defineProperty(exports2, "LogTraceNotification", { enumerable: true, get: function() { + return connection_1.LogTraceNotification; + } }); + Object.defineProperty(exports2, "ConnectionErrors", { enumerable: true, get: function() { + return connection_1.ConnectionErrors; + } }); + Object.defineProperty(exports2, "ConnectionError", { enumerable: true, get: function() { + return connection_1.ConnectionError; + } }); + Object.defineProperty(exports2, "CancellationReceiverStrategy", { enumerable: true, get: function() { + return connection_1.CancellationReceiverStrategy; + } }); + Object.defineProperty(exports2, "CancellationSenderStrategy", { enumerable: true, get: function() { + return connection_1.CancellationSenderStrategy; + } }); + Object.defineProperty(exports2, "CancellationStrategy", { enumerable: true, get: function() { + return connection_1.CancellationStrategy; + } }); + var ral_1 = require_ral(); + exports2.RAL = ral_1.default; + } +}); + +// node_modules/vscode-jsonrpc/lib/node/main.js +var require_main = __commonJS({ + "node_modules/vscode-jsonrpc/lib/node/main.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { + return m[k]; + } }); + } : function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + o[k2] = m[k]; + }); + var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) { + for (var p in m) + if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) + __createBinding(exports3, m, p); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createMessageConnection = exports2.createServerSocketTransport = exports2.createClientSocketTransport = exports2.createServerPipeTransport = exports2.createClientPipeTransport = exports2.generateRandomPipeName = exports2.StreamMessageWriter = exports2.StreamMessageReader = exports2.SocketMessageWriter = exports2.SocketMessageReader = exports2.IPCMessageWriter = exports2.IPCMessageReader = void 0; + var ril_1 = require_ril(); + ril_1.default.install(); + var api_1 = require_api2(); + var path36 = require("path"); + var os10 = require("os"); + var crypto_1 = require("crypto"); + var net_1 = require("net"); + __exportStar(require_api2(), exports2); + var IPCMessageReader2 = class extends api_1.AbstractMessageReader { + constructor(process2) { + super(); + this.process = process2; + let eventEmitter = this.process; + eventEmitter.on("error", (error) => this.fireError(error)); + eventEmitter.on("close", () => this.fireClose()); + } + listen(callback) { + this.process.on("message", callback); + return api_1.Disposable.create(() => this.process.off("message", callback)); + } + }; + exports2.IPCMessageReader = IPCMessageReader2; + var IPCMessageWriter2 = class extends api_1.AbstractMessageWriter { + constructor(process2) { + super(); + this.process = process2; + this.errorCount = 0; + let eventEmitter = this.process; + eventEmitter.on("error", (error) => this.fireError(error)); + eventEmitter.on("close", () => this.fireClose); + } + write(msg) { + try { + if (typeof this.process.send === "function") { + this.process.send(msg, void 0, void 0, (error) => { + if (error) { + this.errorCount++; + this.handleError(error, msg); + } else { + this.errorCount = 0; + } + }); + } + return Promise.resolve(); + } catch (error) { + this.handleError(error, msg); + return Promise.reject(error); + } + } + handleError(error, msg) { + this.errorCount++; + this.fireError(error, msg, this.errorCount); + } + end() { + } + }; + exports2.IPCMessageWriter = IPCMessageWriter2; + var SocketMessageReader = class extends api_1.ReadableStreamMessageReader { + constructor(socket, encoding = "utf-8") { + super(ril_1.default().stream.asReadableStream(socket), encoding); + } + }; + exports2.SocketMessageReader = SocketMessageReader; + var SocketMessageWriter = class extends api_1.WriteableStreamMessageWriter { + constructor(socket, options) { + super(ril_1.default().stream.asWritableStream(socket), options); + this.socket = socket; + } + dispose() { + super.dispose(); + this.socket.destroy(); + } + }; + exports2.SocketMessageWriter = SocketMessageWriter; + var StreamMessageReader2 = class extends api_1.ReadableStreamMessageReader { + constructor(readble, encoding) { + super(ril_1.default().stream.asReadableStream(readble), encoding); + } + }; + exports2.StreamMessageReader = StreamMessageReader2; + var StreamMessageWriter2 = class extends api_1.WriteableStreamMessageWriter { + constructor(writable, options) { + super(ril_1.default().stream.asWritableStream(writable), options); + } + }; + exports2.StreamMessageWriter = StreamMessageWriter2; + var XDG_RUNTIME_DIR = process.env["XDG_RUNTIME_DIR"]; + var safeIpcPathLengths = new Map([ + ["linux", 107], + ["darwin", 103] + ]); + function generateRandomPipeName2() { + const randomSuffix = crypto_1.randomBytes(21).toString("hex"); + if (process.platform === "win32") { + return `\\\\.\\pipe\\vscode-jsonrpc-${randomSuffix}-sock`; + } + let result; + if (XDG_RUNTIME_DIR) { + result = path36.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`); + } else { + result = path36.join(os10.tmpdir(), `vscode-${randomSuffix}.sock`); + } + const limit = safeIpcPathLengths.get(process.platform); + if (limit !== void 0 && result.length >= limit) { + ril_1.default().console.warn(`WARNING: IPC handle "${result}" is longer than ${limit} characters.`); + } + return result; + } + exports2.generateRandomPipeName = generateRandomPipeName2; + function createClientPipeTransport2(pipeName, encoding = "utf-8") { + let connectResolve; + const connected = new Promise((resolve3, _reject) => { + connectResolve = resolve3; + }); + return new Promise((resolve3, reject) => { + let server = net_1.createServer((socket) => { + server.close(); + connectResolve([ + new SocketMessageReader(socket, encoding), + new SocketMessageWriter(socket, encoding) + ]); + }); + server.on("error", reject); + server.listen(pipeName, () => { + server.removeListener("error", reject); + resolve3({ + onConnected: () => { + return connected; + } + }); + }); + }); + } + exports2.createClientPipeTransport = createClientPipeTransport2; + function createServerPipeTransport(pipeName, encoding = "utf-8") { + const socket = net_1.createConnection(pipeName); + return [ + new SocketMessageReader(socket, encoding), + new SocketMessageWriter(socket, encoding) + ]; + } + exports2.createServerPipeTransport = createServerPipeTransport; + function createClientSocketTransport2(port, encoding = "utf-8") { + let connectResolve; + const connected = new Promise((resolve3, _reject) => { + connectResolve = resolve3; + }); + return new Promise((resolve3, reject) => { + const server = net_1.createServer((socket) => { + server.close(); + connectResolve([ + new SocketMessageReader(socket, encoding), + new SocketMessageWriter(socket, encoding) + ]); + }); + server.on("error", reject); + server.listen(port, "127.0.0.1", () => { + server.removeListener("error", reject); + resolve3({ + onConnected: () => { + return connected; + } + }); + }); + }); + } + exports2.createClientSocketTransport = createClientSocketTransport2; + function createServerSocketTransport(port, encoding = "utf-8") { + const socket = net_1.createConnection(port, "127.0.0.1"); + return [ + new SocketMessageReader(socket, encoding), + new SocketMessageWriter(socket, encoding) + ]; + } + exports2.createServerSocketTransport = createServerSocketTransport; + function isReadableStream(value) { + const candidate = value; + return candidate.read !== void 0 && candidate.addListener !== void 0; + } + function isWritableStream(value) { + const candidate = value; + return candidate.write !== void 0 && candidate.addListener !== void 0; + } + function createMessageConnection(input, output, logger113, options) { + if (!logger113) { + logger113 = api_1.NullLogger; + } + const reader = isReadableStream(input) ? new StreamMessageReader2(input) : input; + const writer = isWritableStream(output) ? new StreamMessageWriter2(output) : output; + if (api_1.ConnectionStrategy.is(options)) { + options = { connectionStrategy: options }; + } + return api_1.createMessageConnection(reader, writer, logger113, options); + } + exports2.createMessageConnection = createMessageConnection; + } +}); + +// node_modules/vscode-jsonrpc/node.js +var require_node2 = __commonJS({ + "node_modules/vscode-jsonrpc/node.js"(exports2, module2) { + "use strict"; + module2.exports = require_main(); + } +}); + +// node_modules/vscode-languageserver-types/lib/esm/main.js +var main_exports = {}; +__export(main_exports, { + AnnotatedTextEdit: () => AnnotatedTextEdit, + ChangeAnnotation: () => ChangeAnnotation, + ChangeAnnotationIdentifier: () => ChangeAnnotationIdentifier, + CodeAction: () => CodeAction, + CodeActionContext: () => CodeActionContext, + CodeActionKind: () => CodeActionKind, + CodeDescription: () => CodeDescription, + CodeLens: () => CodeLens, + Color: () => Color, + ColorInformation: () => ColorInformation, + ColorPresentation: () => ColorPresentation, + Command: () => Command, + CompletionItem: () => CompletionItem, + CompletionItemKind: () => CompletionItemKind, + CompletionItemTag: () => CompletionItemTag, + CompletionList: () => CompletionList, + CreateFile: () => CreateFile, + DeleteFile: () => DeleteFile, + Diagnostic: () => Diagnostic, + DiagnosticRelatedInformation: () => DiagnosticRelatedInformation, + DiagnosticSeverity: () => DiagnosticSeverity, + DiagnosticTag: () => DiagnosticTag, + DocumentHighlight: () => DocumentHighlight, + DocumentHighlightKind: () => DocumentHighlightKind, + DocumentLink: () => DocumentLink, + DocumentSymbol: () => DocumentSymbol, + EOL: () => EOL, + FoldingRange: () => FoldingRange, + FoldingRangeKind: () => FoldingRangeKind, + FormattingOptions: () => FormattingOptions, + Hover: () => Hover, + InsertReplaceEdit: () => InsertReplaceEdit, + InsertTextFormat: () => InsertTextFormat, + InsertTextMode: () => InsertTextMode, + Location: () => Location, + LocationLink: () => LocationLink, + MarkedString: () => MarkedString, + MarkupContent: () => MarkupContent, + MarkupKind: () => MarkupKind, + OptionalVersionedTextDocumentIdentifier: () => OptionalVersionedTextDocumentIdentifier, + ParameterInformation: () => ParameterInformation, + Position: () => Position, + Range: () => Range, + RenameFile: () => RenameFile, + SelectionRange: () => SelectionRange, + SignatureInformation: () => SignatureInformation, + SymbolInformation: () => SymbolInformation, + SymbolKind: () => SymbolKind, + SymbolTag: () => SymbolTag, + TextDocument: () => TextDocument, + TextDocumentEdit: () => TextDocumentEdit, + TextDocumentIdentifier: () => TextDocumentIdentifier, + TextDocumentItem: () => TextDocumentItem, + TextEdit: () => TextEdit, + VersionedTextDocumentIdentifier: () => VersionedTextDocumentIdentifier, + WorkspaceChange: () => WorkspaceChange, + WorkspaceEdit: () => WorkspaceEdit, + integer: () => integer, + uinteger: () => uinteger +}); +var integer, uinteger, Position, Range, Location, LocationLink, Color, ColorInformation, ColorPresentation, FoldingRangeKind, FoldingRange, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, CodeDescription, Diagnostic, Command, TextEdit, ChangeAnnotation, ChangeAnnotationIdentifier, AnnotatedTextEdit, TextDocumentEdit, CreateFile, RenameFile, DeleteFile, WorkspaceEdit, TextEditChangeImpl, ChangeAnnotations, WorkspaceChange, TextDocumentIdentifier, VersionedTextDocumentIdentifier, OptionalVersionedTextDocumentIdentifier, TextDocumentItem, MarkupKind, MarkupContent, CompletionItemKind, InsertTextFormat, CompletionItemTag, InsertReplaceEdit, InsertTextMode, CompletionItem, CompletionList, MarkedString, Hover, ParameterInformation, SignatureInformation, DocumentHighlightKind, DocumentHighlight, SymbolKind, SymbolTag, SymbolInformation, DocumentSymbol, CodeActionKind, CodeActionContext, CodeAction, CodeLens, FormattingOptions, DocumentLink, SelectionRange, EOL, TextDocument, FullTextDocument, Is; +var init_main = __esm({ + "node_modules/vscode-languageserver-types/lib/esm/main.js"() { + "use strict"; + (function(integer2) { + integer2.MIN_VALUE = -2147483648; + integer2.MAX_VALUE = 2147483647; + })(integer || (integer = {})); + (function(uinteger3) { + uinteger3.MIN_VALUE = 0; + uinteger3.MAX_VALUE = 2147483647; + })(uinteger || (uinteger = {})); + (function(Position45) { + function create(line, character) { + if (line === Number.MAX_VALUE) { + line = uinteger.MAX_VALUE; + } + if (character === Number.MAX_VALUE) { + character = uinteger.MAX_VALUE; + } + return { line, character }; + } + Position45.create = create; + function is(value) { + var candidate = value; + return Is.objectLiteral(candidate) && Is.uinteger(candidate.line) && Is.uinteger(candidate.character); + } + Position45.is = is; + })(Position || (Position = {})); + (function(Range39) { + function create(one, two, three, four) { + if (Is.uinteger(one) && Is.uinteger(two) && Is.uinteger(three) && Is.uinteger(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 + "]"); + } + } + Range39.create = create; + function is(value) { + var candidate = value; + return Is.objectLiteral(candidate) && Position.is(candidate.start) && Position.is(candidate.end); + } + Range39.is = is; + })(Range || (Range = {})); + (function(Location18) { + function create(uri, range) { + return { uri, range }; + } + Location18.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Range.is(candidate.range) && (Is.string(candidate.uri) || Is.undefined(candidate.uri)); + } + Location18.is = is; + })(Location || (Location = {})); + (function(LocationLink9) { + function create(targetUri, targetRange, targetSelectionRange, originSelectionRange) { + return { targetUri, targetRange, targetSelectionRange, originSelectionRange }; + } + LocationLink9.create = create; + 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)); + } + LocationLink9.is = is; + })(LocationLink || (LocationLink = {})); + (function(Color4) { + function create(red, green, blue2, alpha) { + return { + red, + green, + blue: blue2, + alpha + }; + } + Color4.create = create; + function is(value) { + var candidate = value; + return Is.numberRange(candidate.red, 0, 1) && Is.numberRange(candidate.green, 0, 1) && Is.numberRange(candidate.blue, 0, 1) && Is.numberRange(candidate.alpha, 0, 1); + } + Color4.is = is; + })(Color || (Color = {})); + (function(ColorInformation7) { + function create(range, color) { + return { + range, + color + }; + } + ColorInformation7.create = create; + function is(value) { + var candidate = value; + return Range.is(candidate.range) && Color.is(candidate.color); + } + ColorInformation7.is = is; + })(ColorInformation || (ColorInformation = {})); + (function(ColorPresentation5) { + function create(label, textEdit, additionalTextEdits) { + return { + label, + textEdit, + additionalTextEdits + }; + } + ColorPresentation5.create = create; + 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)); + } + ColorPresentation5.is = is; + })(ColorPresentation || (ColorPresentation = {})); + (function(FoldingRangeKind2) { + FoldingRangeKind2["Comment"] = "comment"; + FoldingRangeKind2["Imports"] = "imports"; + FoldingRangeKind2["Region"] = "region"; + })(FoldingRangeKind || (FoldingRangeKind = {})); + (function(FoldingRange5) { + function create(startLine, endLine, startCharacter, endCharacter, kind) { + var result = { + startLine, + endLine + }; + if (Is.defined(startCharacter)) { + result.startCharacter = startCharacter; + } + if (Is.defined(endCharacter)) { + result.endCharacter = endCharacter; + } + if (Is.defined(kind)) { + result.kind = kind; + } + return result; + } + FoldingRange5.create = create; + function is(value) { + var candidate = value; + return Is.uinteger(candidate.startLine) && Is.uinteger(candidate.startLine) && (Is.undefined(candidate.startCharacter) || Is.uinteger(candidate.startCharacter)) && (Is.undefined(candidate.endCharacter) || Is.uinteger(candidate.endCharacter)) && (Is.undefined(candidate.kind) || Is.string(candidate.kind)); + } + FoldingRange5.is = is; + })(FoldingRange || (FoldingRange = {})); + (function(DiagnosticRelatedInformation2) { + function create(location, message) { + return { + location, + message + }; + } + DiagnosticRelatedInformation2.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Location.is(candidate.location) && Is.string(candidate.message); + } + DiagnosticRelatedInformation2.is = is; + })(DiagnosticRelatedInformation || (DiagnosticRelatedInformation = {})); + (function(DiagnosticSeverity7) { + DiagnosticSeverity7.Error = 1; + DiagnosticSeverity7.Warning = 2; + DiagnosticSeverity7.Information = 3; + DiagnosticSeverity7.Hint = 4; + })(DiagnosticSeverity || (DiagnosticSeverity = {})); + (function(DiagnosticTag6) { + DiagnosticTag6.Unnecessary = 1; + DiagnosticTag6.Deprecated = 2; + })(DiagnosticTag || (DiagnosticTag = {})); + (function(CodeDescription2) { + function is(value) { + var candidate = value; + return candidate !== void 0 && candidate !== null && Is.string(candidate.href); + } + CodeDescription2.is = is; + })(CodeDescription || (CodeDescription = {})); + (function(Diagnostic8) { + function create(range, message, severity, code, source, relatedInformation) { + var result = { range, 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; + } + Diagnostic8.create = create; + function is(value) { + var _a2; + var candidate = value; + return Is.defined(candidate) && Range.is(candidate.range) && Is.string(candidate.message) && (Is.number(candidate.severity) || Is.undefined(candidate.severity)) && (Is.integer(candidate.code) || Is.string(candidate.code) || Is.undefined(candidate.code)) && (Is.undefined(candidate.codeDescription) || Is.string((_a2 = candidate.codeDescription) === null || _a2 === void 0 ? void 0 : _a2.href)) && (Is.string(candidate.source) || Is.undefined(candidate.source)) && (Is.undefined(candidate.relatedInformation) || Is.typedArray(candidate.relatedInformation, DiagnosticRelatedInformation.is)); + } + Diagnostic8.is = is; + })(Diagnostic || (Diagnostic = {})); + (function(Command5) { + function create(title, command) { + var args = []; + for (var _i = 2; _i < arguments.length; _i++) { + args[_i - 2] = arguments[_i]; + } + var result = { title, command }; + if (Is.defined(args) && args.length > 0) { + result.arguments = args; + } + return result; + } + Command5.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Is.string(candidate.title) && Is.string(candidate.command); + } + Command5.is = is; + })(Command || (Command = {})); + (function(TextEdit20) { + function replace(range, newText) { + return { range, newText }; + } + TextEdit20.replace = replace; + function insert(position, newText) { + return { range: { start: position, end: position }, newText }; + } + TextEdit20.insert = insert; + function del(range) { + return { range, newText: "" }; + } + TextEdit20.del = del; + function is(value) { + var candidate = value; + return Is.objectLiteral(candidate) && Is.string(candidate.newText) && Range.is(candidate.range); + } + TextEdit20.is = is; + })(TextEdit || (TextEdit = {})); + (function(ChangeAnnotation2) { + function create(label, needsConfirmation, description) { + var result = { label }; + if (needsConfirmation !== void 0) { + result.needsConfirmation = needsConfirmation; + } + if (description !== void 0) { + result.description = description; + } + return result; + } + ChangeAnnotation2.create = create; + function is(value) { + var candidate = value; + return candidate !== void 0 && Is.objectLiteral(candidate) && Is.string(candidate.label) && (Is.boolean(candidate.needsConfirmation) || candidate.needsConfirmation === void 0) && (Is.string(candidate.description) || candidate.description === void 0); + } + ChangeAnnotation2.is = is; + })(ChangeAnnotation || (ChangeAnnotation = {})); + (function(ChangeAnnotationIdentifier2) { + function is(value) { + var candidate = value; + return typeof candidate === "string"; + } + ChangeAnnotationIdentifier2.is = is; + })(ChangeAnnotationIdentifier || (ChangeAnnotationIdentifier = {})); + (function(AnnotatedTextEdit2) { + function replace(range, newText, annotation) { + return { range, newText, annotationId: annotation }; + } + AnnotatedTextEdit2.replace = replace; + function insert(position, newText, annotation) { + return { range: { start: position, end: position }, newText, annotationId: annotation }; + } + AnnotatedTextEdit2.insert = insert; + function del(range, annotation) { + return { range, newText: "", annotationId: annotation }; + } + AnnotatedTextEdit2.del = del; + function is(value) { + var candidate = value; + return TextEdit.is(candidate) && (ChangeAnnotation.is(candidate.annotationId) || ChangeAnnotationIdentifier.is(candidate.annotationId)); + } + AnnotatedTextEdit2.is = is; + })(AnnotatedTextEdit || (AnnotatedTextEdit = {})); + (function(TextDocumentEdit6) { + function create(textDocument, edits) { + return { textDocument, edits }; + } + TextDocumentEdit6.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && OptionalVersionedTextDocumentIdentifier.is(candidate.textDocument) && Array.isArray(candidate.edits); + } + TextDocumentEdit6.is = is; + })(TextDocumentEdit || (TextDocumentEdit = {})); + (function(CreateFile3) { + function create(uri, options, annotation) { + var result = { + kind: "create", + uri + }; + if (options !== void 0 && (options.overwrite !== void 0 || options.ignoreIfExists !== void 0)) { + result.options = options; + } + if (annotation !== void 0) { + result.annotationId = annotation; + } + return result; + } + CreateFile3.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))) && (candidate.annotationId === void 0 || ChangeAnnotationIdentifier.is(candidate.annotationId)); + } + CreateFile3.is = is; + })(CreateFile || (CreateFile = {})); + (function(RenameFile3) { + function create(oldUri, newUri, options, annotation) { + var result = { + kind: "rename", + oldUri, + newUri + }; + if (options !== void 0 && (options.overwrite !== void 0 || options.ignoreIfExists !== void 0)) { + result.options = options; + } + if (annotation !== void 0) { + result.annotationId = annotation; + } + return result; + } + RenameFile3.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))) && (candidate.annotationId === void 0 || ChangeAnnotationIdentifier.is(candidate.annotationId)); + } + RenameFile3.is = is; + })(RenameFile || (RenameFile = {})); + (function(DeleteFile3) { + function create(uri, options, annotation) { + var result = { + kind: "delete", + uri + }; + if (options !== void 0 && (options.recursive !== void 0 || options.ignoreIfNotExists !== void 0)) { + result.options = options; + } + if (annotation !== void 0) { + result.annotationId = annotation; + } + return result; + } + DeleteFile3.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))) && (candidate.annotationId === void 0 || ChangeAnnotationIdentifier.is(candidate.annotationId)); + } + DeleteFile3.is = is; + })(DeleteFile || (DeleteFile = {})); + (function(WorkspaceEdit10) { + 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); + } + })); + } + WorkspaceEdit10.is = is; + })(WorkspaceEdit || (WorkspaceEdit = {})); + TextEditChangeImpl = function() { + function TextEditChangeImpl2(edits, changeAnnotations) { + this.edits = edits; + this.changeAnnotations = changeAnnotations; + } + TextEditChangeImpl2.prototype.insert = function(position, newText, annotation) { + var edit2; + var id; + if (annotation === void 0) { + edit2 = TextEdit.insert(position, newText); + } else if (ChangeAnnotationIdentifier.is(annotation)) { + id = annotation; + edit2 = AnnotatedTextEdit.insert(position, newText, annotation); + } else { + this.assertChangeAnnotations(this.changeAnnotations); + id = this.changeAnnotations.manage(annotation); + edit2 = AnnotatedTextEdit.insert(position, newText, id); + } + this.edits.push(edit2); + if (id !== void 0) { + return id; + } + }; + TextEditChangeImpl2.prototype.replace = function(range, newText, annotation) { + var edit2; + var id; + if (annotation === void 0) { + edit2 = TextEdit.replace(range, newText); + } else if (ChangeAnnotationIdentifier.is(annotation)) { + id = annotation; + edit2 = AnnotatedTextEdit.replace(range, newText, annotation); + } else { + this.assertChangeAnnotations(this.changeAnnotations); + id = this.changeAnnotations.manage(annotation); + edit2 = AnnotatedTextEdit.replace(range, newText, id); + } + this.edits.push(edit2); + if (id !== void 0) { + return id; + } + }; + TextEditChangeImpl2.prototype.delete = function(range, annotation) { + var edit2; + var id; + if (annotation === void 0) { + edit2 = TextEdit.del(range); + } else if (ChangeAnnotationIdentifier.is(annotation)) { + id = annotation; + edit2 = AnnotatedTextEdit.del(range, annotation); + } else { + this.assertChangeAnnotations(this.changeAnnotations); + id = this.changeAnnotations.manage(annotation); + edit2 = AnnotatedTextEdit.del(range, id); + } + this.edits.push(edit2); + if (id !== void 0) { + return id; + } + }; + TextEditChangeImpl2.prototype.add = function(edit2) { + this.edits.push(edit2); + }; + TextEditChangeImpl2.prototype.all = function() { + return this.edits; + }; + TextEditChangeImpl2.prototype.clear = function() { + this.edits.splice(0, this.edits.length); + }; + TextEditChangeImpl2.prototype.assertChangeAnnotations = function(value) { + if (value === void 0) { + throw new Error("Text edit change is not configured to manage change annotations."); + } + }; + return TextEditChangeImpl2; + }(); + ChangeAnnotations = function() { + function ChangeAnnotations2(annotations) { + this._annotations = annotations === void 0 ? Object.create(null) : annotations; + this._counter = 0; + this._size = 0; + } + ChangeAnnotations2.prototype.all = function() { + return this._annotations; + }; + Object.defineProperty(ChangeAnnotations2.prototype, "size", { + get: function() { + return this._size; + }, + enumerable: false, + configurable: true + }); + ChangeAnnotations2.prototype.manage = function(idOrAnnotation, annotation) { + var id; + if (ChangeAnnotationIdentifier.is(idOrAnnotation)) { + id = idOrAnnotation; + } else { + id = this.nextId(); + annotation = idOrAnnotation; + } + if (this._annotations[id] !== void 0) { + throw new Error("Id " + id + " is already in use."); + } + if (annotation === void 0) { + throw new Error("No annotation provided for id " + id); + } + this._annotations[id] = annotation; + this._size++; + return id; + }; + ChangeAnnotations2.prototype.nextId = function() { + this._counter++; + return this._counter.toString(); + }; + return ChangeAnnotations2; + }(); + WorkspaceChange = function() { + function WorkspaceChange2(workspaceEdit) { + var _this = this; + this._textEditChanges = Object.create(null); + if (workspaceEdit !== void 0) { + this._workspaceEdit = workspaceEdit; + if (workspaceEdit.documentChanges) { + this._changeAnnotations = new ChangeAnnotations(workspaceEdit.changeAnnotations); + workspaceEdit.changeAnnotations = this._changeAnnotations.all(); + workspaceEdit.documentChanges.forEach(function(change) { + if (TextDocumentEdit.is(change)) { + var textEditChange = new TextEditChangeImpl(change.edits, _this._changeAnnotations); + _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; + }); + } + } else { + this._workspaceEdit = {}; + } + } + Object.defineProperty(WorkspaceChange2.prototype, "edit", { + get: function() { + this.initDocumentChanges(); + if (this._changeAnnotations !== void 0) { + if (this._changeAnnotations.size === 0) { + this._workspaceEdit.changeAnnotations = void 0; + } else { + this._workspaceEdit.changeAnnotations = this._changeAnnotations.all(); + } + } + return this._workspaceEdit; + }, + enumerable: false, + configurable: true + }); + WorkspaceChange2.prototype.getTextEditChange = function(key) { + if (OptionalVersionedTextDocumentIdentifier.is(key)) { + this.initDocumentChanges(); + if (this._workspaceEdit.documentChanges === void 0) { + throw new Error("Workspace edit is not configured for document changes."); + } + var textDocument = { uri: key.uri, version: key.version }; + var result = this._textEditChanges[textDocument.uri]; + if (!result) { + var edits = []; + var textDocumentEdit = { + textDocument, + edits + }; + this._workspaceEdit.documentChanges.push(textDocumentEdit); + result = new TextEditChangeImpl(edits, this._changeAnnotations); + this._textEditChanges[textDocument.uri] = result; + } + return result; + } else { + this.initChanges(); + if (this._workspaceEdit.changes === void 0) { + 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; + } + }; + WorkspaceChange2.prototype.initDocumentChanges = function() { + if (this._workspaceEdit.documentChanges === void 0 && this._workspaceEdit.changes === void 0) { + this._changeAnnotations = new ChangeAnnotations(); + this._workspaceEdit.documentChanges = []; + this._workspaceEdit.changeAnnotations = this._changeAnnotations.all(); + } + }; + WorkspaceChange2.prototype.initChanges = function() { + if (this._workspaceEdit.documentChanges === void 0 && this._workspaceEdit.changes === void 0) { + this._workspaceEdit.changes = Object.create(null); + } + }; + WorkspaceChange2.prototype.createFile = function(uri, optionsOrAnnotation, options) { + this.initDocumentChanges(); + if (this._workspaceEdit.documentChanges === void 0) { + throw new Error("Workspace edit is not configured for document changes."); + } + var annotation; + if (ChangeAnnotation.is(optionsOrAnnotation) || ChangeAnnotationIdentifier.is(optionsOrAnnotation)) { + annotation = optionsOrAnnotation; + } else { + options = optionsOrAnnotation; + } + var operation; + var id; + if (annotation === void 0) { + operation = CreateFile.create(uri, options); + } else { + id = ChangeAnnotationIdentifier.is(annotation) ? annotation : this._changeAnnotations.manage(annotation); + operation = CreateFile.create(uri, options, id); + } + this._workspaceEdit.documentChanges.push(operation); + if (id !== void 0) { + return id; + } + }; + WorkspaceChange2.prototype.renameFile = function(oldUri, newUri, optionsOrAnnotation, options) { + this.initDocumentChanges(); + if (this._workspaceEdit.documentChanges === void 0) { + throw new Error("Workspace edit is not configured for document changes."); + } + var annotation; + if (ChangeAnnotation.is(optionsOrAnnotation) || ChangeAnnotationIdentifier.is(optionsOrAnnotation)) { + annotation = optionsOrAnnotation; + } else { + options = optionsOrAnnotation; + } + var operation; + var id; + if (annotation === void 0) { + operation = RenameFile.create(oldUri, newUri, options); + } else { + id = ChangeAnnotationIdentifier.is(annotation) ? annotation : this._changeAnnotations.manage(annotation); + operation = RenameFile.create(oldUri, newUri, options, id); + } + this._workspaceEdit.documentChanges.push(operation); + if (id !== void 0) { + return id; + } + }; + WorkspaceChange2.prototype.deleteFile = function(uri, optionsOrAnnotation, options) { + this.initDocumentChanges(); + if (this._workspaceEdit.documentChanges === void 0) { + throw new Error("Workspace edit is not configured for document changes."); + } + var annotation; + if (ChangeAnnotation.is(optionsOrAnnotation) || ChangeAnnotationIdentifier.is(optionsOrAnnotation)) { + annotation = optionsOrAnnotation; + } else { + options = optionsOrAnnotation; + } + var operation; + var id; + if (annotation === void 0) { + operation = DeleteFile.create(uri, options); + } else { + id = ChangeAnnotationIdentifier.is(annotation) ? annotation : this._changeAnnotations.manage(annotation); + operation = DeleteFile.create(uri, options, id); + } + this._workspaceEdit.documentChanges.push(operation); + if (id !== void 0) { + return id; + } + }; + return WorkspaceChange2; + }(); + (function(TextDocumentIdentifier2) { + function create(uri) { + return { uri }; + } + TextDocumentIdentifier2.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Is.string(candidate.uri); + } + TextDocumentIdentifier2.is = is; + })(TextDocumentIdentifier || (TextDocumentIdentifier = {})); + (function(VersionedTextDocumentIdentifier2) { + function create(uri, version2) { + return { uri, version: version2 }; + } + VersionedTextDocumentIdentifier2.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Is.string(candidate.uri) && Is.integer(candidate.version); + } + VersionedTextDocumentIdentifier2.is = is; + })(VersionedTextDocumentIdentifier || (VersionedTextDocumentIdentifier = {})); + (function(OptionalVersionedTextDocumentIdentifier2) { + function create(uri, version2) { + return { uri, version: version2 }; + } + OptionalVersionedTextDocumentIdentifier2.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Is.string(candidate.uri) && (candidate.version === null || Is.integer(candidate.version)); + } + OptionalVersionedTextDocumentIdentifier2.is = is; + })(OptionalVersionedTextDocumentIdentifier || (OptionalVersionedTextDocumentIdentifier = {})); + (function(TextDocumentItem2) { + function create(uri, languageId, version2, text) { + return { uri, languageId, version: version2, text }; + } + TextDocumentItem2.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Is.string(candidate.uri) && Is.string(candidate.languageId) && Is.integer(candidate.version) && Is.string(candidate.text); + } + TextDocumentItem2.is = is; + })(TextDocumentItem || (TextDocumentItem = {})); + (function(MarkupKind6) { + MarkupKind6.PlainText = "plaintext"; + MarkupKind6.Markdown = "markdown"; + })(MarkupKind || (MarkupKind = {})); + (function(MarkupKind6) { + function is(value) { + var candidate = value; + return candidate === MarkupKind6.PlainText || candidate === MarkupKind6.Markdown; + } + MarkupKind6.is = is; + })(MarkupKind || (MarkupKind = {})); + (function(MarkupContent7) { + function is(value) { + var candidate = value; + return Is.objectLiteral(value) && MarkupKind.is(candidate.kind) && Is.string(candidate.value); + } + MarkupContent7.is = is; + })(MarkupContent || (MarkupContent = {})); + (function(CompletionItemKind6) { + CompletionItemKind6.Text = 1; + CompletionItemKind6.Method = 2; + CompletionItemKind6.Function = 3; + CompletionItemKind6.Constructor = 4; + CompletionItemKind6.Field = 5; + CompletionItemKind6.Variable = 6; + CompletionItemKind6.Class = 7; + CompletionItemKind6.Interface = 8; + CompletionItemKind6.Module = 9; + CompletionItemKind6.Property = 10; + CompletionItemKind6.Unit = 11; + CompletionItemKind6.Value = 12; + CompletionItemKind6.Enum = 13; + CompletionItemKind6.Keyword = 14; + CompletionItemKind6.Snippet = 15; + CompletionItemKind6.Color = 16; + CompletionItemKind6.File = 17; + CompletionItemKind6.Reference = 18; + CompletionItemKind6.Folder = 19; + CompletionItemKind6.EnumMember = 20; + CompletionItemKind6.Constant = 21; + CompletionItemKind6.Struct = 22; + CompletionItemKind6.Event = 23; + CompletionItemKind6.Operator = 24; + CompletionItemKind6.TypeParameter = 25; + })(CompletionItemKind || (CompletionItemKind = {})); + (function(InsertTextFormat4) { + InsertTextFormat4.PlainText = 1; + InsertTextFormat4.Snippet = 2; + })(InsertTextFormat || (InsertTextFormat = {})); + (function(CompletionItemTag3) { + CompletionItemTag3.Deprecated = 1; + })(CompletionItemTag || (CompletionItemTag = {})); + (function(InsertReplaceEdit3) { + function create(newText, insert, replace) { + return { newText, insert, replace }; + } + InsertReplaceEdit3.create = create; + function is(value) { + var candidate = value; + return candidate && Is.string(candidate.newText) && Range.is(candidate.insert) && Range.is(candidate.replace); + } + InsertReplaceEdit3.is = is; + })(InsertReplaceEdit || (InsertReplaceEdit = {})); + (function(InsertTextMode4) { + InsertTextMode4.asIs = 1; + InsertTextMode4.adjustIndentation = 2; + })(InsertTextMode || (InsertTextMode = {})); + (function(CompletionItem4) { + function create(label) { + return { label }; + } + CompletionItem4.create = create; + })(CompletionItem || (CompletionItem = {})); + (function(CompletionList4) { + function create(items, isIncomplete) { + return { items: items ? items : [], isIncomplete: !!isIncomplete }; + } + CompletionList4.create = create; + })(CompletionList || (CompletionList = {})); + (function(MarkedString3) { + function fromPlainText(plainText) { + return plainText.replace(/[\\`*_{}[\]()#+\-.!]/g, "\\$&"); + } + MarkedString3.fromPlainText = fromPlainText; + function is(value) { + var candidate = value; + return Is.string(candidate) || Is.objectLiteral(candidate) && Is.string(candidate.language) && Is.string(candidate.value); + } + MarkedString3.is = is; + })(MarkedString || (MarkedString = {})); + (function(Hover6) { + 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)); + } + Hover6.is = is; + })(Hover || (Hover = {})); + (function(ParameterInformation2) { + function create(label, documentation) { + return documentation ? { label, documentation } : { label }; + } + ParameterInformation2.create = create; + })(ParameterInformation || (ParameterInformation = {})); + (function(SignatureInformation2) { + function create(label, documentation) { + var parameters = []; + for (var _i = 2; _i < arguments.length; _i++) { + parameters[_i - 2] = arguments[_i]; + } + var result = { label }; + if (Is.defined(documentation)) { + result.documentation = documentation; + } + if (Is.defined(parameters)) { + result.parameters = parameters; + } else { + result.parameters = []; + } + return result; + } + SignatureInformation2.create = create; + })(SignatureInformation || (SignatureInformation = {})); + (function(DocumentHighlightKind4) { + DocumentHighlightKind4.Text = 1; + DocumentHighlightKind4.Read = 2; + DocumentHighlightKind4.Write = 3; + })(DocumentHighlightKind || (DocumentHighlightKind = {})); + (function(DocumentHighlight6) { + function create(range, kind) { + var result = { range }; + if (Is.number(kind)) { + result.kind = kind; + } + return result; + } + DocumentHighlight6.create = create; + })(DocumentHighlight || (DocumentHighlight = {})); + (function(SymbolKind7) { + SymbolKind7.File = 1; + SymbolKind7.Module = 2; + SymbolKind7.Namespace = 3; + SymbolKind7.Package = 4; + SymbolKind7.Class = 5; + SymbolKind7.Method = 6; + SymbolKind7.Property = 7; + SymbolKind7.Field = 8; + SymbolKind7.Constructor = 9; + SymbolKind7.Enum = 10; + SymbolKind7.Interface = 11; + SymbolKind7.Function = 12; + SymbolKind7.Variable = 13; + SymbolKind7.Constant = 14; + SymbolKind7.String = 15; + SymbolKind7.Number = 16; + SymbolKind7.Boolean = 17; + SymbolKind7.Array = 18; + SymbolKind7.Object = 19; + SymbolKind7.Key = 20; + SymbolKind7.Null = 21; + SymbolKind7.EnumMember = 22; + SymbolKind7.Struct = 23; + SymbolKind7.Event = 24; + SymbolKind7.Operator = 25; + SymbolKind7.TypeParameter = 26; + })(SymbolKind || (SymbolKind = {})); + (function(SymbolTag6) { + SymbolTag6.Deprecated = 1; + })(SymbolTag || (SymbolTag = {})); + (function(SymbolInformation8) { + function create(name2, kind, range, uri, containerName) { + var result = { + name: name2, + kind, + location: { uri, range } + }; + if (containerName) { + result.containerName = containerName; + } + return result; + } + SymbolInformation8.create = create; + })(SymbolInformation || (SymbolInformation = {})); + (function(DocumentSymbol8) { + function create(name2, detail, kind, range, selectionRange, children) { + var result = { + name: name2, + detail, + kind, + range, + selectionRange + }; + if (children !== void 0) { + result.children = children; + } + return result; + } + DocumentSymbol8.create = create; + 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)) && (candidate.tags === void 0 || Array.isArray(candidate.tags)); + } + DocumentSymbol8.is = is; + })(DocumentSymbol || (DocumentSymbol = {})); + (function(CodeActionKind10) { + CodeActionKind10.Empty = ""; + CodeActionKind10.QuickFix = "quickfix"; + CodeActionKind10.Refactor = "refactor"; + CodeActionKind10.RefactorExtract = "refactor.extract"; + CodeActionKind10.RefactorInline = "refactor.inline"; + CodeActionKind10.RefactorRewrite = "refactor.rewrite"; + CodeActionKind10.Source = "source"; + CodeActionKind10.SourceOrganizeImports = "source.organizeImports"; + CodeActionKind10.SourceFixAll = "source.fixAll"; + })(CodeActionKind || (CodeActionKind = {})); + (function(CodeActionContext6) { + function create(diagnostics, only) { + var result = { diagnostics }; + if (only !== void 0 && only !== null) { + result.only = only; + } + return result; + } + CodeActionContext6.create = create; + 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)); + } + CodeActionContext6.is = is; + })(CodeActionContext || (CodeActionContext = {})); + (function(CodeAction9) { + function create(title, kindOrCommandOrEdit, kind) { + var result = { title }; + var checkKind = true; + if (typeof kindOrCommandOrEdit === "string") { + checkKind = false; + result.kind = kindOrCommandOrEdit; + } else if (Command.is(kindOrCommandOrEdit)) { + result.command = kindOrCommandOrEdit; + } else { + result.edit = kindOrCommandOrEdit; + } + if (checkKind && kind !== void 0) { + result.kind = kind; + } + return result; + } + CodeAction9.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.isPreferred === void 0 || Is.boolean(candidate.isPreferred)) && (candidate.edit === void 0 || WorkspaceEdit.is(candidate.edit)); + } + CodeAction9.is = is; + })(CodeAction || (CodeAction = {})); + (function(CodeLens6) { + function create(range, data) { + var result = { range }; + if (Is.defined(data)) { + result.data = data; + } + return result; + } + CodeLens6.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Range.is(candidate.range) && (Is.undefined(candidate.command) || Command.is(candidate.command)); + } + CodeLens6.is = is; + })(CodeLens || (CodeLens = {})); + (function(FormattingOptions7) { + function create(tabSize, insertSpaces) { + return { tabSize, insertSpaces }; + } + FormattingOptions7.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Is.uinteger(candidate.tabSize) && Is.boolean(candidate.insertSpaces); + } + FormattingOptions7.is = is; + })(FormattingOptions || (FormattingOptions = {})); + (function(DocumentLink7) { + function create(range, target, data) { + return { range, target, data }; + } + DocumentLink7.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Range.is(candidate.range) && (Is.undefined(candidate.target) || Is.string(candidate.target)); + } + DocumentLink7.is = is; + })(DocumentLink || (DocumentLink = {})); + (function(SelectionRange6) { + function create(range, parent) { + return { range, parent }; + } + SelectionRange6.create = create; + function is(value) { + var candidate = value; + return candidate !== void 0 && Range.is(candidate.range) && (candidate.parent === void 0 || SelectionRange6.is(candidate.parent)); + } + SelectionRange6.is = is; + })(SelectionRange || (SelectionRange = {})); + EOL = ["\n", "\r\n", "\r"]; + (function(TextDocument5) { + function create(uri, languageId, version2, content) { + return new FullTextDocument(uri, languageId, version2, content); + } + TextDocument5.create = create; + function is(value) { + var candidate = value; + return Is.defined(candidate) && Is.string(candidate.uri) && (Is.undefined(candidate.languageId) || Is.string(candidate.languageId)) && Is.uinteger(candidate.lineCount) && Is.func(candidate.getText) && Is.func(candidate.positionAt) && Is.func(candidate.offsetAt) ? true : false; + } + TextDocument5.is = is; + function applyEdits2(document2, edits) { + var text = document2.getText(); + var sortedEdits = mergeSort2(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 = document2.offsetAt(e.range.start); + var endOffset = document2.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; + } + TextDocument5.applyEdits = applyEdits2; + function mergeSort2(data, compare) { + if (data.length <= 1) { + return data; + } + var p = data.length / 2 | 0; + var left = data.slice(0, p); + var right = data.slice(p); + mergeSort2(left, compare); + mergeSort2(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) { + data[i++] = left[leftIdx++]; + } else { + data[i++] = right[rightIdx++]; + } + } + while (leftIdx < left.length) { + data[i++] = left[leftIdx++]; + } + while (rightIdx < right.length) { + data[i++] = right[rightIdx++]; + } + return data; + } + })(TextDocument || (TextDocument = {})); + FullTextDocument = function() { + function FullTextDocument3(uri, languageId, version2, content) { + this._uri = uri; + this._languageId = languageId; + this._version = version2; + this._content = content; + this._lineOffsets = void 0; + } + Object.defineProperty(FullTextDocument3.prototype, "uri", { + get: function() { + return this._uri; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(FullTextDocument3.prototype, "languageId", { + get: function() { + return this._languageId; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(FullTextDocument3.prototype, "version", { + get: function() { + return this._version; + }, + enumerable: false, + configurable: true + }); + FullTextDocument3.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; + }; + FullTextDocument3.prototype.update = function(event, version2) { + this._content = event.text; + this._version = version2; + this._lineOffsets = void 0; + }; + FullTextDocument3.prototype.getLineOffsets = function() { + if (this._lineOffsets === void 0) { + 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; + }; + FullTextDocument3.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; + } + } + var line = low - 1; + return Position.create(line, offset - lineOffsets[line]); + }; + FullTextDocument3.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(FullTextDocument3.prototype, "lineCount", { + get: function() { + return this.getLineOffsets().length; + }, + enumerable: false, + configurable: true + }); + return FullTextDocument3; + }(); + (function(Is7) { + var toString = Object.prototype.toString; + function defined(value) { + return typeof value !== "undefined"; + } + Is7.defined = defined; + function undefined2(value) { + return typeof value === "undefined"; + } + Is7.undefined = undefined2; + function boolean2(value) { + return value === true || value === false; + } + Is7.boolean = boolean2; + function string2(value) { + return toString.call(value) === "[object String]"; + } + Is7.string = string2; + function number2(value) { + return toString.call(value) === "[object Number]"; + } + Is7.number = number2; + function numberRange(value, min, max) { + return toString.call(value) === "[object Number]" && min <= value && value <= max; + } + Is7.numberRange = numberRange; + function integer2(value) { + return toString.call(value) === "[object Number]" && -2147483648 <= value && value <= 2147483647; + } + Is7.integer = integer2; + function uinteger3(value) { + return toString.call(value) === "[object Number]" && 0 <= value && value <= 2147483647; + } + Is7.uinteger = uinteger3; + function func2(value) { + return toString.call(value) === "[object Function]"; + } + Is7.func = func2; + function objectLiteral2(value) { + return value !== null && typeof value === "object"; + } + Is7.objectLiteral = objectLiteral2; + function typedArray(value, check) { + return Array.isArray(value) && value.every(check); + } + Is7.typedArray = typedArray; + })(Is || (Is = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/messages.js +var require_messages2 = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/messages.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ProtocolNotificationType = exports2.ProtocolNotificationType0 = exports2.ProtocolRequestType = exports2.ProtocolRequestType0 = exports2.RegistrationType = void 0; + var vscode_jsonrpc_1 = require_main(); + var RegistrationType4 = class { + constructor(method) { + this.method = method; + } + }; + exports2.RegistrationType = RegistrationType4; + var ProtocolRequestType02 = class extends vscode_jsonrpc_1.RequestType0 { + constructor(method) { + super(method); + } + }; + exports2.ProtocolRequestType0 = ProtocolRequestType02; + var ProtocolRequestType3 = class extends vscode_jsonrpc_1.RequestType { + constructor(method) { + super(method, vscode_jsonrpc_1.ParameterStructures.byName); + } + }; + exports2.ProtocolRequestType = ProtocolRequestType3; + var ProtocolNotificationType02 = class extends vscode_jsonrpc_1.NotificationType0 { + constructor(method) { + super(method); + } + }; + exports2.ProtocolNotificationType0 = ProtocolNotificationType02; + var ProtocolNotificationType4 = class extends vscode_jsonrpc_1.NotificationType { + constructor(method) { + super(method, vscode_jsonrpc_1.ParameterStructures.byName); + } + }; + exports2.ProtocolNotificationType = ProtocolNotificationType4; + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/utils/is.js +var require_is2 = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/utils/is.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.objectLiteral = exports2.typedArray = exports2.stringArray = exports2.array = exports2.func = exports2.error = exports2.number = exports2.string = exports2.boolean = void 0; + function boolean2(value) { + return value === true || value === false; + } + exports2.boolean = boolean2; + function string2(value) { + return typeof value === "string" || value instanceof String; + } + exports2.string = string2; + function number2(value) { + return typeof value === "number" || value instanceof Number; + } + exports2.number = number2; + function error(value) { + return value instanceof Error; + } + exports2.error = error; + function func2(value) { + return typeof value === "function"; + } + exports2.func = func2; + function array(value) { + return Array.isArray(value); + } + exports2.array = array; + function stringArray(value) { + return array(value) && value.every((elem) => string2(elem)); + } + exports2.stringArray = stringArray; + function typedArray(value, check) { + return Array.isArray(value) && value.every(check); + } + exports2.typedArray = typedArray; + function objectLiteral2(value) { + return value !== null && typeof value === "object"; + } + exports2.objectLiteral = objectLiteral2; + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.implementation.js +var require_protocol_implementation = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.implementation.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ImplementationRequest = void 0; + var messages_1 = require_messages2(); + var ImplementationRequest3; + (function(ImplementationRequest4) { + ImplementationRequest4.method = "textDocument/implementation"; + ImplementationRequest4.type = new messages_1.ProtocolRequestType(ImplementationRequest4.method); + })(ImplementationRequest3 = exports2.ImplementationRequest || (exports2.ImplementationRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.typeDefinition.js +var require_protocol_typeDefinition = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.typeDefinition.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.TypeDefinitionRequest = void 0; + var messages_1 = require_messages2(); + var TypeDefinitionRequest3; + (function(TypeDefinitionRequest4) { + TypeDefinitionRequest4.method = "textDocument/typeDefinition"; + TypeDefinitionRequest4.type = new messages_1.ProtocolRequestType(TypeDefinitionRequest4.method); + })(TypeDefinitionRequest3 = exports2.TypeDefinitionRequest || (exports2.TypeDefinitionRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.workspaceFolders.js +var require_protocol_workspaceFolders = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.workspaceFolders.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.DidChangeWorkspaceFoldersNotification = exports2.WorkspaceFoldersRequest = void 0; + var messages_1 = require_messages2(); + var WorkspaceFoldersRequest2; + (function(WorkspaceFoldersRequest3) { + WorkspaceFoldersRequest3.type = new messages_1.ProtocolRequestType0("workspace/workspaceFolders"); + })(WorkspaceFoldersRequest2 = exports2.WorkspaceFoldersRequest || (exports2.WorkspaceFoldersRequest = {})); + var DidChangeWorkspaceFoldersNotification2; + (function(DidChangeWorkspaceFoldersNotification3) { + DidChangeWorkspaceFoldersNotification3.type = new messages_1.ProtocolNotificationType("workspace/didChangeWorkspaceFolders"); + })(DidChangeWorkspaceFoldersNotification2 = exports2.DidChangeWorkspaceFoldersNotification || (exports2.DidChangeWorkspaceFoldersNotification = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.configuration.js +var require_protocol_configuration = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.configuration.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ConfigurationRequest = void 0; + var messages_1 = require_messages2(); + var ConfigurationRequest2; + (function(ConfigurationRequest3) { + ConfigurationRequest3.type = new messages_1.ProtocolRequestType("workspace/configuration"); + })(ConfigurationRequest2 = exports2.ConfigurationRequest || (exports2.ConfigurationRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.colorProvider.js +var require_protocol_colorProvider = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.colorProvider.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ColorPresentationRequest = exports2.DocumentColorRequest = void 0; + var messages_1 = require_messages2(); + var DocumentColorRequest3; + (function(DocumentColorRequest4) { + DocumentColorRequest4.method = "textDocument/documentColor"; + DocumentColorRequest4.type = new messages_1.ProtocolRequestType(DocumentColorRequest4.method); + })(DocumentColorRequest3 = exports2.DocumentColorRequest || (exports2.DocumentColorRequest = {})); + var ColorPresentationRequest2; + (function(ColorPresentationRequest3) { + ColorPresentationRequest3.type = new messages_1.ProtocolRequestType("textDocument/colorPresentation"); + })(ColorPresentationRequest2 = exports2.ColorPresentationRequest || (exports2.ColorPresentationRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.foldingRange.js +var require_protocol_foldingRange = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.foldingRange.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.FoldingRangeRequest = exports2.FoldingRangeKind = void 0; + var messages_1 = require_messages2(); + var FoldingRangeKind2; + (function(FoldingRangeKind3) { + FoldingRangeKind3["Comment"] = "comment"; + FoldingRangeKind3["Imports"] = "imports"; + FoldingRangeKind3["Region"] = "region"; + })(FoldingRangeKind2 = exports2.FoldingRangeKind || (exports2.FoldingRangeKind = {})); + var FoldingRangeRequest3; + (function(FoldingRangeRequest4) { + FoldingRangeRequest4.method = "textDocument/foldingRange"; + FoldingRangeRequest4.type = new messages_1.ProtocolRequestType(FoldingRangeRequest4.method); + })(FoldingRangeRequest3 = exports2.FoldingRangeRequest || (exports2.FoldingRangeRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.declaration.js +var require_protocol_declaration = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.declaration.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.DeclarationRequest = void 0; + var messages_1 = require_messages2(); + var DeclarationRequest3; + (function(DeclarationRequest4) { + DeclarationRequest4.method = "textDocument/declaration"; + DeclarationRequest4.type = new messages_1.ProtocolRequestType(DeclarationRequest4.method); + })(DeclarationRequest3 = exports2.DeclarationRequest || (exports2.DeclarationRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.selectionRange.js +var require_protocol_selectionRange = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.selectionRange.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.SelectionRangeRequest = void 0; + var messages_1 = require_messages2(); + var SelectionRangeRequest3; + (function(SelectionRangeRequest4) { + SelectionRangeRequest4.method = "textDocument/selectionRange"; + SelectionRangeRequest4.type = new messages_1.ProtocolRequestType(SelectionRangeRequest4.method); + })(SelectionRangeRequest3 = exports2.SelectionRangeRequest || (exports2.SelectionRangeRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.progress.js +var require_protocol_progress = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.progress.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WorkDoneProgressCancelNotification = exports2.WorkDoneProgressCreateRequest = exports2.WorkDoneProgress = void 0; + var vscode_jsonrpc_1 = require_main(); + var messages_1 = require_messages2(); + var WorkDoneProgress3; + (function(WorkDoneProgress4) { + WorkDoneProgress4.type = new vscode_jsonrpc_1.ProgressType(); + function is(value) { + return value === WorkDoneProgress4.type; + } + WorkDoneProgress4.is = is; + })(WorkDoneProgress3 = exports2.WorkDoneProgress || (exports2.WorkDoneProgress = {})); + var WorkDoneProgressCreateRequest2; + (function(WorkDoneProgressCreateRequest3) { + WorkDoneProgressCreateRequest3.type = new messages_1.ProtocolRequestType("window/workDoneProgress/create"); + })(WorkDoneProgressCreateRequest2 = exports2.WorkDoneProgressCreateRequest || (exports2.WorkDoneProgressCreateRequest = {})); + var WorkDoneProgressCancelNotification; + (function(WorkDoneProgressCancelNotification2) { + WorkDoneProgressCancelNotification2.type = new messages_1.ProtocolNotificationType("window/workDoneProgress/cancel"); + })(WorkDoneProgressCancelNotification = exports2.WorkDoneProgressCancelNotification || (exports2.WorkDoneProgressCancelNotification = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.callHierarchy.js +var require_protocol_callHierarchy = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.callHierarchy.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.CallHierarchyOutgoingCallsRequest = exports2.CallHierarchyIncomingCallsRequest = exports2.CallHierarchyPrepareRequest = void 0; + var messages_1 = require_messages2(); + var CallHierarchyPrepareRequest3; + (function(CallHierarchyPrepareRequest4) { + CallHierarchyPrepareRequest4.method = "textDocument/prepareCallHierarchy"; + CallHierarchyPrepareRequest4.type = new messages_1.ProtocolRequestType(CallHierarchyPrepareRequest4.method); + })(CallHierarchyPrepareRequest3 = exports2.CallHierarchyPrepareRequest || (exports2.CallHierarchyPrepareRequest = {})); + var CallHierarchyIncomingCallsRequest2; + (function(CallHierarchyIncomingCallsRequest3) { + CallHierarchyIncomingCallsRequest3.method = "callHierarchy/incomingCalls"; + CallHierarchyIncomingCallsRequest3.type = new messages_1.ProtocolRequestType(CallHierarchyIncomingCallsRequest3.method); + })(CallHierarchyIncomingCallsRequest2 = exports2.CallHierarchyIncomingCallsRequest || (exports2.CallHierarchyIncomingCallsRequest = {})); + var CallHierarchyOutgoingCallsRequest2; + (function(CallHierarchyOutgoingCallsRequest3) { + CallHierarchyOutgoingCallsRequest3.method = "callHierarchy/outgoingCalls"; + CallHierarchyOutgoingCallsRequest3.type = new messages_1.ProtocolRequestType(CallHierarchyOutgoingCallsRequest3.method); + })(CallHierarchyOutgoingCallsRequest2 = exports2.CallHierarchyOutgoingCallsRequest || (exports2.CallHierarchyOutgoingCallsRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.semanticTokens.js +var require_protocol_semanticTokens = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.semanticTokens.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.SemanticTokensRefreshRequest = exports2.SemanticTokensRangeRequest = exports2.SemanticTokensDeltaRequest = exports2.SemanticTokensRequest = exports2.SemanticTokensRegistrationType = exports2.TokenFormat = exports2.SemanticTokens = exports2.SemanticTokenModifiers = exports2.SemanticTokenTypes = void 0; + var messages_1 = require_messages2(); + var SemanticTokenTypes2; + (function(SemanticTokenTypes3) { + SemanticTokenTypes3["namespace"] = "namespace"; + SemanticTokenTypes3["type"] = "type"; + SemanticTokenTypes3["class"] = "class"; + SemanticTokenTypes3["enum"] = "enum"; + SemanticTokenTypes3["interface"] = "interface"; + SemanticTokenTypes3["struct"] = "struct"; + SemanticTokenTypes3["typeParameter"] = "typeParameter"; + SemanticTokenTypes3["parameter"] = "parameter"; + SemanticTokenTypes3["variable"] = "variable"; + SemanticTokenTypes3["property"] = "property"; + SemanticTokenTypes3["enumMember"] = "enumMember"; + SemanticTokenTypes3["event"] = "event"; + SemanticTokenTypes3["function"] = "function"; + SemanticTokenTypes3["method"] = "method"; + SemanticTokenTypes3["macro"] = "macro"; + SemanticTokenTypes3["keyword"] = "keyword"; + SemanticTokenTypes3["modifier"] = "modifier"; + SemanticTokenTypes3["comment"] = "comment"; + SemanticTokenTypes3["string"] = "string"; + SemanticTokenTypes3["number"] = "number"; + SemanticTokenTypes3["regexp"] = "regexp"; + SemanticTokenTypes3["operator"] = "operator"; + })(SemanticTokenTypes2 = exports2.SemanticTokenTypes || (exports2.SemanticTokenTypes = {})); + var SemanticTokenModifiers2; + (function(SemanticTokenModifiers3) { + SemanticTokenModifiers3["declaration"] = "declaration"; + SemanticTokenModifiers3["definition"] = "definition"; + SemanticTokenModifiers3["readonly"] = "readonly"; + SemanticTokenModifiers3["static"] = "static"; + SemanticTokenModifiers3["deprecated"] = "deprecated"; + SemanticTokenModifiers3["abstract"] = "abstract"; + SemanticTokenModifiers3["async"] = "async"; + SemanticTokenModifiers3["modification"] = "modification"; + SemanticTokenModifiers3["documentation"] = "documentation"; + SemanticTokenModifiers3["defaultLibrary"] = "defaultLibrary"; + })(SemanticTokenModifiers2 = exports2.SemanticTokenModifiers || (exports2.SemanticTokenModifiers = {})); + var SemanticTokens6; + (function(SemanticTokens7) { + function is(value) { + const candidate = value; + return candidate !== void 0 && (candidate.resultId === void 0 || typeof candidate.resultId === "string") && Array.isArray(candidate.data) && (candidate.data.length === 0 || typeof candidate.data[0] === "number"); + } + SemanticTokens7.is = is; + })(SemanticTokens6 = exports2.SemanticTokens || (exports2.SemanticTokens = {})); + var TokenFormat2; + (function(TokenFormat3) { + TokenFormat3.Relative = "relative"; + })(TokenFormat2 = exports2.TokenFormat || (exports2.TokenFormat = {})); + var SemanticTokensRegistrationType3; + (function(SemanticTokensRegistrationType4) { + SemanticTokensRegistrationType4.method = "textDocument/semanticTokens"; + SemanticTokensRegistrationType4.type = new messages_1.RegistrationType(SemanticTokensRegistrationType4.method); + })(SemanticTokensRegistrationType3 = exports2.SemanticTokensRegistrationType || (exports2.SemanticTokensRegistrationType = {})); + var SemanticTokensRequest2; + (function(SemanticTokensRequest3) { + SemanticTokensRequest3.method = "textDocument/semanticTokens/full"; + SemanticTokensRequest3.type = new messages_1.ProtocolRequestType(SemanticTokensRequest3.method); + })(SemanticTokensRequest2 = exports2.SemanticTokensRequest || (exports2.SemanticTokensRequest = {})); + var SemanticTokensDeltaRequest2; + (function(SemanticTokensDeltaRequest3) { + SemanticTokensDeltaRequest3.method = "textDocument/semanticTokens/full/delta"; + SemanticTokensDeltaRequest3.type = new messages_1.ProtocolRequestType(SemanticTokensDeltaRequest3.method); + })(SemanticTokensDeltaRequest2 = exports2.SemanticTokensDeltaRequest || (exports2.SemanticTokensDeltaRequest = {})); + var SemanticTokensRangeRequest2; + (function(SemanticTokensRangeRequest3) { + SemanticTokensRangeRequest3.method = "textDocument/semanticTokens/range"; + SemanticTokensRangeRequest3.type = new messages_1.ProtocolRequestType(SemanticTokensRangeRequest3.method); + })(SemanticTokensRangeRequest2 = exports2.SemanticTokensRangeRequest || (exports2.SemanticTokensRangeRequest = {})); + var SemanticTokensRefreshRequest2; + (function(SemanticTokensRefreshRequest3) { + SemanticTokensRefreshRequest3.method = `workspace/semanticTokens/refresh`; + SemanticTokensRefreshRequest3.type = new messages_1.ProtocolRequestType0(SemanticTokensRefreshRequest3.method); + })(SemanticTokensRefreshRequest2 = exports2.SemanticTokensRefreshRequest || (exports2.SemanticTokensRefreshRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.showDocument.js +var require_protocol_showDocument = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.showDocument.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ShowDocumentRequest = void 0; + var messages_1 = require_messages2(); + var ShowDocumentRequest2; + (function(ShowDocumentRequest3) { + ShowDocumentRequest3.method = "window/showDocument"; + ShowDocumentRequest3.type = new messages_1.ProtocolRequestType(ShowDocumentRequest3.method); + })(ShowDocumentRequest2 = exports2.ShowDocumentRequest || (exports2.ShowDocumentRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.linkedEditingRange.js +var require_protocol_linkedEditingRange = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.linkedEditingRange.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.LinkedEditingRangeRequest = void 0; + var messages_1 = require_messages2(); + var LinkedEditingRangeRequest3; + (function(LinkedEditingRangeRequest4) { + LinkedEditingRangeRequest4.method = "textDocument/linkedEditingRange"; + LinkedEditingRangeRequest4.type = new messages_1.ProtocolRequestType(LinkedEditingRangeRequest4.method); + })(LinkedEditingRangeRequest3 = exports2.LinkedEditingRangeRequest || (exports2.LinkedEditingRangeRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.fileOperations.js +var require_protocol_fileOperations = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.fileOperations.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WillDeleteFilesRequest = exports2.DidDeleteFilesNotification = exports2.DidRenameFilesNotification = exports2.WillRenameFilesRequest = exports2.DidCreateFilesNotification = exports2.WillCreateFilesRequest = exports2.FileOperationPatternKind = void 0; + var messages_1 = require_messages2(); + var FileOperationPatternKind2; + (function(FileOperationPatternKind3) { + FileOperationPatternKind3.file = "file"; + FileOperationPatternKind3.folder = "folder"; + })(FileOperationPatternKind2 = exports2.FileOperationPatternKind || (exports2.FileOperationPatternKind = {})); + var WillCreateFilesRequest3; + (function(WillCreateFilesRequest4) { + WillCreateFilesRequest4.method = "workspace/willCreateFiles"; + WillCreateFilesRequest4.type = new messages_1.ProtocolRequestType(WillCreateFilesRequest4.method); + })(WillCreateFilesRequest3 = exports2.WillCreateFilesRequest || (exports2.WillCreateFilesRequest = {})); + var DidCreateFilesNotification3; + (function(DidCreateFilesNotification4) { + DidCreateFilesNotification4.method = "workspace/didCreateFiles"; + DidCreateFilesNotification4.type = new messages_1.ProtocolNotificationType(DidCreateFilesNotification4.method); + })(DidCreateFilesNotification3 = exports2.DidCreateFilesNotification || (exports2.DidCreateFilesNotification = {})); + var WillRenameFilesRequest3; + (function(WillRenameFilesRequest4) { + WillRenameFilesRequest4.method = "workspace/willRenameFiles"; + WillRenameFilesRequest4.type = new messages_1.ProtocolRequestType(WillRenameFilesRequest4.method); + })(WillRenameFilesRequest3 = exports2.WillRenameFilesRequest || (exports2.WillRenameFilesRequest = {})); + var DidRenameFilesNotification3; + (function(DidRenameFilesNotification4) { + DidRenameFilesNotification4.method = "workspace/didRenameFiles"; + DidRenameFilesNotification4.type = new messages_1.ProtocolNotificationType(DidRenameFilesNotification4.method); + })(DidRenameFilesNotification3 = exports2.DidRenameFilesNotification || (exports2.DidRenameFilesNotification = {})); + var DidDeleteFilesNotification3; + (function(DidDeleteFilesNotification4) { + DidDeleteFilesNotification4.method = "workspace/didDeleteFiles"; + DidDeleteFilesNotification4.type = new messages_1.ProtocolNotificationType(DidDeleteFilesNotification4.method); + })(DidDeleteFilesNotification3 = exports2.DidDeleteFilesNotification || (exports2.DidDeleteFilesNotification = {})); + var WillDeleteFilesRequest3; + (function(WillDeleteFilesRequest4) { + WillDeleteFilesRequest4.method = "workspace/willDeleteFiles"; + WillDeleteFilesRequest4.type = new messages_1.ProtocolRequestType(WillDeleteFilesRequest4.method); + })(WillDeleteFilesRequest3 = exports2.WillDeleteFilesRequest || (exports2.WillDeleteFilesRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.moniker.js +var require_protocol_moniker = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.moniker.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.MonikerRequest = exports2.MonikerKind = exports2.UniquenessLevel = void 0; + var messages_1 = require_messages2(); + var UniquenessLevel; + (function(UniquenessLevel2) { + UniquenessLevel2["document"] = "document"; + UniquenessLevel2["project"] = "project"; + UniquenessLevel2["group"] = "group"; + UniquenessLevel2["scheme"] = "scheme"; + UniquenessLevel2["global"] = "global"; + })(UniquenessLevel = exports2.UniquenessLevel || (exports2.UniquenessLevel = {})); + var MonikerKind; + (function(MonikerKind2) { + MonikerKind2["import"] = "import"; + MonikerKind2["export"] = "export"; + MonikerKind2["local"] = "local"; + })(MonikerKind = exports2.MonikerKind || (exports2.MonikerKind = {})); + var MonikerRequest; + (function(MonikerRequest2) { + MonikerRequest2.method = "textDocument/moniker"; + MonikerRequest2.type = new messages_1.ProtocolRequestType(MonikerRequest2.method); + })(MonikerRequest = exports2.MonikerRequest || (exports2.MonikerRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/protocol.js +var require_protocol = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/protocol.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.DocumentLinkRequest = exports2.CodeLensRefreshRequest = exports2.CodeLensResolveRequest = exports2.CodeLensRequest = exports2.WorkspaceSymbolRequest = exports2.CodeActionResolveRequest = exports2.CodeActionRequest = exports2.DocumentSymbolRequest = exports2.DocumentHighlightRequest = exports2.ReferencesRequest = exports2.DefinitionRequest = exports2.SignatureHelpRequest = exports2.SignatureHelpTriggerKind = exports2.HoverRequest = exports2.CompletionResolveRequest = exports2.CompletionRequest = exports2.CompletionTriggerKind = exports2.PublishDiagnosticsNotification = exports2.WatchKind = exports2.FileChangeType = exports2.DidChangeWatchedFilesNotification = exports2.WillSaveTextDocumentWaitUntilRequest = exports2.WillSaveTextDocumentNotification = exports2.TextDocumentSaveReason = exports2.DidSaveTextDocumentNotification = exports2.DidCloseTextDocumentNotification = exports2.DidChangeTextDocumentNotification = exports2.TextDocumentContentChangeEvent = exports2.DidOpenTextDocumentNotification = exports2.TextDocumentSyncKind = exports2.TelemetryEventNotification = exports2.LogMessageNotification = exports2.ShowMessageRequest = exports2.ShowMessageNotification = exports2.MessageType = exports2.DidChangeConfigurationNotification = exports2.ExitNotification = exports2.ShutdownRequest = exports2.InitializedNotification = exports2.InitializeError = exports2.InitializeRequest = exports2.WorkDoneProgressOptions = exports2.TextDocumentRegistrationOptions = exports2.StaticRegistrationOptions = exports2.FailureHandlingKind = exports2.ResourceOperationKind = exports2.UnregistrationRequest = exports2.RegistrationRequest = exports2.DocumentSelector = exports2.DocumentFilter = void 0; + exports2.MonikerRequest = exports2.MonikerKind = exports2.UniquenessLevel = exports2.WillDeleteFilesRequest = exports2.DidDeleteFilesNotification = exports2.WillRenameFilesRequest = exports2.DidRenameFilesNotification = exports2.WillCreateFilesRequest = exports2.DidCreateFilesNotification = exports2.FileOperationPatternKind = exports2.LinkedEditingRangeRequest = exports2.ShowDocumentRequest = exports2.SemanticTokensRegistrationType = exports2.SemanticTokensRefreshRequest = exports2.SemanticTokensRangeRequest = exports2.SemanticTokensDeltaRequest = exports2.SemanticTokensRequest = exports2.TokenFormat = exports2.SemanticTokens = exports2.SemanticTokenModifiers = exports2.SemanticTokenTypes = exports2.CallHierarchyPrepareRequest = exports2.CallHierarchyOutgoingCallsRequest = exports2.CallHierarchyIncomingCallsRequest = exports2.WorkDoneProgressCancelNotification = exports2.WorkDoneProgressCreateRequest = exports2.WorkDoneProgress = exports2.SelectionRangeRequest = exports2.DeclarationRequest = exports2.FoldingRangeRequest = exports2.ColorPresentationRequest = exports2.DocumentColorRequest = exports2.ConfigurationRequest = exports2.DidChangeWorkspaceFoldersNotification = exports2.WorkspaceFoldersRequest = exports2.TypeDefinitionRequest = exports2.ImplementationRequest = exports2.ApplyWorkspaceEditRequest = exports2.ExecuteCommandRequest = exports2.PrepareRenameRequest = exports2.RenameRequest = exports2.PrepareSupportDefaultBehavior = exports2.DocumentOnTypeFormattingRequest = exports2.DocumentRangeFormattingRequest = exports2.DocumentFormattingRequest = exports2.DocumentLinkResolveRequest = void 0; + var Is7 = require_is2(); + var messages_1 = require_messages2(); + var protocol_implementation_1 = require_protocol_implementation(); + Object.defineProperty(exports2, "ImplementationRequest", { enumerable: true, get: function() { + return protocol_implementation_1.ImplementationRequest; + } }); + var protocol_typeDefinition_1 = require_protocol_typeDefinition(); + Object.defineProperty(exports2, "TypeDefinitionRequest", { enumerable: true, get: function() { + return protocol_typeDefinition_1.TypeDefinitionRequest; + } }); + var protocol_workspaceFolders_1 = require_protocol_workspaceFolders(); + Object.defineProperty(exports2, "WorkspaceFoldersRequest", { enumerable: true, get: function() { + return protocol_workspaceFolders_1.WorkspaceFoldersRequest; + } }); + Object.defineProperty(exports2, "DidChangeWorkspaceFoldersNotification", { enumerable: true, get: function() { + return protocol_workspaceFolders_1.DidChangeWorkspaceFoldersNotification; + } }); + var protocol_configuration_1 = require_protocol_configuration(); + Object.defineProperty(exports2, "ConfigurationRequest", { enumerable: true, get: function() { + return protocol_configuration_1.ConfigurationRequest; + } }); + var protocol_colorProvider_1 = require_protocol_colorProvider(); + Object.defineProperty(exports2, "DocumentColorRequest", { enumerable: true, get: function() { + return protocol_colorProvider_1.DocumentColorRequest; + } }); + Object.defineProperty(exports2, "ColorPresentationRequest", { enumerable: true, get: function() { + return protocol_colorProvider_1.ColorPresentationRequest; + } }); + var protocol_foldingRange_1 = require_protocol_foldingRange(); + Object.defineProperty(exports2, "FoldingRangeRequest", { enumerable: true, get: function() { + return protocol_foldingRange_1.FoldingRangeRequest; + } }); + var protocol_declaration_1 = require_protocol_declaration(); + Object.defineProperty(exports2, "DeclarationRequest", { enumerable: true, get: function() { + return protocol_declaration_1.DeclarationRequest; + } }); + var protocol_selectionRange_1 = require_protocol_selectionRange(); + Object.defineProperty(exports2, "SelectionRangeRequest", { enumerable: true, get: function() { + return protocol_selectionRange_1.SelectionRangeRequest; + } }); + var protocol_progress_1 = require_protocol_progress(); + Object.defineProperty(exports2, "WorkDoneProgress", { enumerable: true, get: function() { + return protocol_progress_1.WorkDoneProgress; + } }); + Object.defineProperty(exports2, "WorkDoneProgressCreateRequest", { enumerable: true, get: function() { + return protocol_progress_1.WorkDoneProgressCreateRequest; + } }); + Object.defineProperty(exports2, "WorkDoneProgressCancelNotification", { enumerable: true, get: function() { + return protocol_progress_1.WorkDoneProgressCancelNotification; + } }); + var protocol_callHierarchy_1 = require_protocol_callHierarchy(); + Object.defineProperty(exports2, "CallHierarchyIncomingCallsRequest", { enumerable: true, get: function() { + return protocol_callHierarchy_1.CallHierarchyIncomingCallsRequest; + } }); + Object.defineProperty(exports2, "CallHierarchyOutgoingCallsRequest", { enumerable: true, get: function() { + return protocol_callHierarchy_1.CallHierarchyOutgoingCallsRequest; + } }); + Object.defineProperty(exports2, "CallHierarchyPrepareRequest", { enumerable: true, get: function() { + return protocol_callHierarchy_1.CallHierarchyPrepareRequest; + } }); + var protocol_semanticTokens_1 = require_protocol_semanticTokens(); + Object.defineProperty(exports2, "SemanticTokenTypes", { enumerable: true, get: function() { + return protocol_semanticTokens_1.SemanticTokenTypes; + } }); + Object.defineProperty(exports2, "SemanticTokenModifiers", { enumerable: true, get: function() { + return protocol_semanticTokens_1.SemanticTokenModifiers; + } }); + Object.defineProperty(exports2, "SemanticTokens", { enumerable: true, get: function() { + return protocol_semanticTokens_1.SemanticTokens; + } }); + Object.defineProperty(exports2, "TokenFormat", { enumerable: true, get: function() { + return protocol_semanticTokens_1.TokenFormat; + } }); + Object.defineProperty(exports2, "SemanticTokensRequest", { enumerable: true, get: function() { + return protocol_semanticTokens_1.SemanticTokensRequest; + } }); + Object.defineProperty(exports2, "SemanticTokensDeltaRequest", { enumerable: true, get: function() { + return protocol_semanticTokens_1.SemanticTokensDeltaRequest; + } }); + Object.defineProperty(exports2, "SemanticTokensRangeRequest", { enumerable: true, get: function() { + return protocol_semanticTokens_1.SemanticTokensRangeRequest; + } }); + Object.defineProperty(exports2, "SemanticTokensRefreshRequest", { enumerable: true, get: function() { + return protocol_semanticTokens_1.SemanticTokensRefreshRequest; + } }); + Object.defineProperty(exports2, "SemanticTokensRegistrationType", { enumerable: true, get: function() { + return protocol_semanticTokens_1.SemanticTokensRegistrationType; + } }); + var protocol_showDocument_1 = require_protocol_showDocument(); + Object.defineProperty(exports2, "ShowDocumentRequest", { enumerable: true, get: function() { + return protocol_showDocument_1.ShowDocumentRequest; + } }); + var protocol_linkedEditingRange_1 = require_protocol_linkedEditingRange(); + Object.defineProperty(exports2, "LinkedEditingRangeRequest", { enumerable: true, get: function() { + return protocol_linkedEditingRange_1.LinkedEditingRangeRequest; + } }); + var protocol_fileOperations_1 = require_protocol_fileOperations(); + Object.defineProperty(exports2, "FileOperationPatternKind", { enumerable: true, get: function() { + return protocol_fileOperations_1.FileOperationPatternKind; + } }); + Object.defineProperty(exports2, "DidCreateFilesNotification", { enumerable: true, get: function() { + return protocol_fileOperations_1.DidCreateFilesNotification; + } }); + Object.defineProperty(exports2, "WillCreateFilesRequest", { enumerable: true, get: function() { + return protocol_fileOperations_1.WillCreateFilesRequest; + } }); + Object.defineProperty(exports2, "DidRenameFilesNotification", { enumerable: true, get: function() { + return protocol_fileOperations_1.DidRenameFilesNotification; + } }); + Object.defineProperty(exports2, "WillRenameFilesRequest", { enumerable: true, get: function() { + return protocol_fileOperations_1.WillRenameFilesRequest; + } }); + Object.defineProperty(exports2, "DidDeleteFilesNotification", { enumerable: true, get: function() { + return protocol_fileOperations_1.DidDeleteFilesNotification; + } }); + Object.defineProperty(exports2, "WillDeleteFilesRequest", { enumerable: true, get: function() { + return protocol_fileOperations_1.WillDeleteFilesRequest; + } }); + var protocol_moniker_1 = require_protocol_moniker(); + Object.defineProperty(exports2, "UniquenessLevel", { enumerable: true, get: function() { + return protocol_moniker_1.UniquenessLevel; + } }); + Object.defineProperty(exports2, "MonikerKind", { enumerable: true, get: function() { + return protocol_moniker_1.MonikerKind; + } }); + Object.defineProperty(exports2, "MonikerRequest", { enumerable: true, get: function() { + return protocol_moniker_1.MonikerRequest; + } }); + var DocumentFilter; + (function(DocumentFilter2) { + function is(value) { + const candidate = value; + return Is7.string(candidate.language) || Is7.string(candidate.scheme) || Is7.string(candidate.pattern); + } + DocumentFilter2.is = is; + })(DocumentFilter = exports2.DocumentFilter || (exports2.DocumentFilter = {})); + var DocumentSelector40; + (function(DocumentSelector41) { + function is(value) { + if (!Array.isArray(value)) { + return false; + } + for (let elem of value) { + if (!Is7.string(elem) && !DocumentFilter.is(elem)) { + return false; + } + } + return true; + } + DocumentSelector41.is = is; + })(DocumentSelector40 = exports2.DocumentSelector || (exports2.DocumentSelector = {})); + var RegistrationRequest2; + (function(RegistrationRequest3) { + RegistrationRequest3.type = new messages_1.ProtocolRequestType("client/registerCapability"); + })(RegistrationRequest2 = exports2.RegistrationRequest || (exports2.RegistrationRequest = {})); + var UnregistrationRequest2; + (function(UnregistrationRequest3) { + UnregistrationRequest3.type = new messages_1.ProtocolRequestType("client/unregisterCapability"); + })(UnregistrationRequest2 = exports2.UnregistrationRequest || (exports2.UnregistrationRequest = {})); + var ResourceOperationKind2; + (function(ResourceOperationKind3) { + ResourceOperationKind3.Create = "create"; + ResourceOperationKind3.Rename = "rename"; + ResourceOperationKind3.Delete = "delete"; + })(ResourceOperationKind2 = exports2.ResourceOperationKind || (exports2.ResourceOperationKind = {})); + var FailureHandlingKind2; + (function(FailureHandlingKind3) { + FailureHandlingKind3.Abort = "abort"; + FailureHandlingKind3.Transactional = "transactional"; + FailureHandlingKind3.TextOnlyTransactional = "textOnlyTransactional"; + FailureHandlingKind3.Undo = "undo"; + })(FailureHandlingKind2 = exports2.FailureHandlingKind || (exports2.FailureHandlingKind = {})); + var StaticRegistrationOptions2; + (function(StaticRegistrationOptions3) { + function hasId(value) { + const candidate = value; + return candidate && Is7.string(candidate.id) && candidate.id.length > 0; + } + StaticRegistrationOptions3.hasId = hasId; + })(StaticRegistrationOptions2 = exports2.StaticRegistrationOptions || (exports2.StaticRegistrationOptions = {})); + var TextDocumentRegistrationOptions2; + (function(TextDocumentRegistrationOptions3) { + function is(value) { + const candidate = value; + return candidate && (candidate.documentSelector === null || DocumentSelector40.is(candidate.documentSelector)); + } + TextDocumentRegistrationOptions3.is = is; + })(TextDocumentRegistrationOptions2 = exports2.TextDocumentRegistrationOptions || (exports2.TextDocumentRegistrationOptions = {})); + var WorkDoneProgressOptions2; + (function(WorkDoneProgressOptions3) { + function is(value) { + const candidate = value; + return Is7.objectLiteral(candidate) && (candidate.workDoneProgress === void 0 || Is7.boolean(candidate.workDoneProgress)); + } + WorkDoneProgressOptions3.is = is; + function hasWorkDoneProgress(value) { + const candidate = value; + return candidate && Is7.boolean(candidate.workDoneProgress); + } + WorkDoneProgressOptions3.hasWorkDoneProgress = hasWorkDoneProgress; + })(WorkDoneProgressOptions2 = exports2.WorkDoneProgressOptions || (exports2.WorkDoneProgressOptions = {})); + var InitializeRequest2; + (function(InitializeRequest3) { + InitializeRequest3.type = new messages_1.ProtocolRequestType("initialize"); + })(InitializeRequest2 = exports2.InitializeRequest || (exports2.InitializeRequest = {})); + var InitializeError2; + (function(InitializeError3) { + InitializeError3.unknownProtocolVersion = 1; + })(InitializeError2 = exports2.InitializeError || (exports2.InitializeError = {})); + var InitializedNotification2; + (function(InitializedNotification3) { + InitializedNotification3.type = new messages_1.ProtocolNotificationType("initialized"); + })(InitializedNotification2 = exports2.InitializedNotification || (exports2.InitializedNotification = {})); + var ShutdownRequest2; + (function(ShutdownRequest3) { + ShutdownRequest3.type = new messages_1.ProtocolRequestType0("shutdown"); + })(ShutdownRequest2 = exports2.ShutdownRequest || (exports2.ShutdownRequest = {})); + var ExitNotification2; + (function(ExitNotification3) { + ExitNotification3.type = new messages_1.ProtocolNotificationType0("exit"); + })(ExitNotification2 = exports2.ExitNotification || (exports2.ExitNotification = {})); + var DidChangeConfigurationNotification2; + (function(DidChangeConfigurationNotification3) { + DidChangeConfigurationNotification3.type = new messages_1.ProtocolNotificationType("workspace/didChangeConfiguration"); + })(DidChangeConfigurationNotification2 = exports2.DidChangeConfigurationNotification || (exports2.DidChangeConfigurationNotification = {})); + var MessageType2; + (function(MessageType3) { + MessageType3.Error = 1; + MessageType3.Warning = 2; + MessageType3.Info = 3; + MessageType3.Log = 4; + })(MessageType2 = exports2.MessageType || (exports2.MessageType = {})); + var ShowMessageNotification2; + (function(ShowMessageNotification3) { + ShowMessageNotification3.type = new messages_1.ProtocolNotificationType("window/showMessage"); + })(ShowMessageNotification2 = exports2.ShowMessageNotification || (exports2.ShowMessageNotification = {})); + var ShowMessageRequest2; + (function(ShowMessageRequest3) { + ShowMessageRequest3.type = new messages_1.ProtocolRequestType("window/showMessageRequest"); + })(ShowMessageRequest2 = exports2.ShowMessageRequest || (exports2.ShowMessageRequest = {})); + var LogMessageNotification2; + (function(LogMessageNotification3) { + LogMessageNotification3.type = new messages_1.ProtocolNotificationType("window/logMessage"); + })(LogMessageNotification2 = exports2.LogMessageNotification || (exports2.LogMessageNotification = {})); + var TelemetryEventNotification2; + (function(TelemetryEventNotification3) { + TelemetryEventNotification3.type = new messages_1.ProtocolNotificationType("telemetry/event"); + })(TelemetryEventNotification2 = exports2.TelemetryEventNotification || (exports2.TelemetryEventNotification = {})); + var TextDocumentSyncKind2; + (function(TextDocumentSyncKind3) { + TextDocumentSyncKind3.None = 0; + TextDocumentSyncKind3.Full = 1; + TextDocumentSyncKind3.Incremental = 2; + })(TextDocumentSyncKind2 = exports2.TextDocumentSyncKind || (exports2.TextDocumentSyncKind = {})); + var DidOpenTextDocumentNotification2; + (function(DidOpenTextDocumentNotification3) { + DidOpenTextDocumentNotification3.method = "textDocument/didOpen"; + DidOpenTextDocumentNotification3.type = new messages_1.ProtocolNotificationType(DidOpenTextDocumentNotification3.method); + })(DidOpenTextDocumentNotification2 = exports2.DidOpenTextDocumentNotification || (exports2.DidOpenTextDocumentNotification = {})); + var TextDocumentContentChangeEvent2; + (function(TextDocumentContentChangeEvent3) { + function isIncremental(event) { + let candidate = event; + return candidate !== void 0 && candidate !== null && typeof candidate.text === "string" && candidate.range !== void 0 && (candidate.rangeLength === void 0 || typeof candidate.rangeLength === "number"); + } + TextDocumentContentChangeEvent3.isIncremental = isIncremental; + function isFull(event) { + let candidate = event; + return candidate !== void 0 && candidate !== null && typeof candidate.text === "string" && candidate.range === void 0 && candidate.rangeLength === void 0; + } + TextDocumentContentChangeEvent3.isFull = isFull; + })(TextDocumentContentChangeEvent2 = exports2.TextDocumentContentChangeEvent || (exports2.TextDocumentContentChangeEvent = {})); + var DidChangeTextDocumentNotification2; + (function(DidChangeTextDocumentNotification3) { + DidChangeTextDocumentNotification3.method = "textDocument/didChange"; + DidChangeTextDocumentNotification3.type = new messages_1.ProtocolNotificationType(DidChangeTextDocumentNotification3.method); + })(DidChangeTextDocumentNotification2 = exports2.DidChangeTextDocumentNotification || (exports2.DidChangeTextDocumentNotification = {})); + var DidCloseTextDocumentNotification2; + (function(DidCloseTextDocumentNotification3) { + DidCloseTextDocumentNotification3.method = "textDocument/didClose"; + DidCloseTextDocumentNotification3.type = new messages_1.ProtocolNotificationType(DidCloseTextDocumentNotification3.method); + })(DidCloseTextDocumentNotification2 = exports2.DidCloseTextDocumentNotification || (exports2.DidCloseTextDocumentNotification = {})); + var DidSaveTextDocumentNotification2; + (function(DidSaveTextDocumentNotification3) { + DidSaveTextDocumentNotification3.method = "textDocument/didSave"; + DidSaveTextDocumentNotification3.type = new messages_1.ProtocolNotificationType(DidSaveTextDocumentNotification3.method); + })(DidSaveTextDocumentNotification2 = exports2.DidSaveTextDocumentNotification || (exports2.DidSaveTextDocumentNotification = {})); + var TextDocumentSaveReason2; + (function(TextDocumentSaveReason3) { + TextDocumentSaveReason3.Manual = 1; + TextDocumentSaveReason3.AfterDelay = 2; + TextDocumentSaveReason3.FocusOut = 3; + })(TextDocumentSaveReason2 = exports2.TextDocumentSaveReason || (exports2.TextDocumentSaveReason = {})); + var WillSaveTextDocumentNotification2; + (function(WillSaveTextDocumentNotification3) { + WillSaveTextDocumentNotification3.method = "textDocument/willSave"; + WillSaveTextDocumentNotification3.type = new messages_1.ProtocolNotificationType(WillSaveTextDocumentNotification3.method); + })(WillSaveTextDocumentNotification2 = exports2.WillSaveTextDocumentNotification || (exports2.WillSaveTextDocumentNotification = {})); + var WillSaveTextDocumentWaitUntilRequest2; + (function(WillSaveTextDocumentWaitUntilRequest3) { + WillSaveTextDocumentWaitUntilRequest3.method = "textDocument/willSaveWaitUntil"; + WillSaveTextDocumentWaitUntilRequest3.type = new messages_1.ProtocolRequestType(WillSaveTextDocumentWaitUntilRequest3.method); + })(WillSaveTextDocumentWaitUntilRequest2 = exports2.WillSaveTextDocumentWaitUntilRequest || (exports2.WillSaveTextDocumentWaitUntilRequest = {})); + var DidChangeWatchedFilesNotification2; + (function(DidChangeWatchedFilesNotification3) { + DidChangeWatchedFilesNotification3.type = new messages_1.ProtocolNotificationType("workspace/didChangeWatchedFiles"); + })(DidChangeWatchedFilesNotification2 = exports2.DidChangeWatchedFilesNotification || (exports2.DidChangeWatchedFilesNotification = {})); + var FileChangeType3; + (function(FileChangeType4) { + FileChangeType4.Created = 1; + FileChangeType4.Changed = 2; + FileChangeType4.Deleted = 3; + })(FileChangeType3 = exports2.FileChangeType || (exports2.FileChangeType = {})); + var WatchKind2; + (function(WatchKind3) { + WatchKind3.Create = 1; + WatchKind3.Change = 2; + WatchKind3.Delete = 4; + })(WatchKind2 = exports2.WatchKind || (exports2.WatchKind = {})); + var PublishDiagnosticsNotification2; + (function(PublishDiagnosticsNotification3) { + PublishDiagnosticsNotification3.type = new messages_1.ProtocolNotificationType("textDocument/publishDiagnostics"); + })(PublishDiagnosticsNotification2 = exports2.PublishDiagnosticsNotification || (exports2.PublishDiagnosticsNotification = {})); + var CompletionTriggerKind3; + (function(CompletionTriggerKind4) { + CompletionTriggerKind4.Invoked = 1; + CompletionTriggerKind4.TriggerCharacter = 2; + CompletionTriggerKind4.TriggerForIncompleteCompletions = 3; + })(CompletionTriggerKind3 = exports2.CompletionTriggerKind || (exports2.CompletionTriggerKind = {})); + var CompletionRequest2; + (function(CompletionRequest3) { + CompletionRequest3.method = "textDocument/completion"; + CompletionRequest3.type = new messages_1.ProtocolRequestType(CompletionRequest3.method); + })(CompletionRequest2 = exports2.CompletionRequest || (exports2.CompletionRequest = {})); + var CompletionResolveRequest2; + (function(CompletionResolveRequest3) { + CompletionResolveRequest3.method = "completionItem/resolve"; + CompletionResolveRequest3.type = new messages_1.ProtocolRequestType(CompletionResolveRequest3.method); + })(CompletionResolveRequest2 = exports2.CompletionResolveRequest || (exports2.CompletionResolveRequest = {})); + var HoverRequest2; + (function(HoverRequest3) { + HoverRequest3.method = "textDocument/hover"; + HoverRequest3.type = new messages_1.ProtocolRequestType(HoverRequest3.method); + })(HoverRequest2 = exports2.HoverRequest || (exports2.HoverRequest = {})); + var SignatureHelpTriggerKind3; + (function(SignatureHelpTriggerKind4) { + SignatureHelpTriggerKind4.Invoked = 1; + SignatureHelpTriggerKind4.TriggerCharacter = 2; + SignatureHelpTriggerKind4.ContentChange = 3; + })(SignatureHelpTriggerKind3 = exports2.SignatureHelpTriggerKind || (exports2.SignatureHelpTriggerKind = {})); + var SignatureHelpRequest2; + (function(SignatureHelpRequest3) { + SignatureHelpRequest3.method = "textDocument/signatureHelp"; + SignatureHelpRequest3.type = new messages_1.ProtocolRequestType(SignatureHelpRequest3.method); + })(SignatureHelpRequest2 = exports2.SignatureHelpRequest || (exports2.SignatureHelpRequest = {})); + var DefinitionRequest2; + (function(DefinitionRequest3) { + DefinitionRequest3.method = "textDocument/definition"; + DefinitionRequest3.type = new messages_1.ProtocolRequestType(DefinitionRequest3.method); + })(DefinitionRequest2 = exports2.DefinitionRequest || (exports2.DefinitionRequest = {})); + var ReferencesRequest2; + (function(ReferencesRequest3) { + ReferencesRequest3.method = "textDocument/references"; + ReferencesRequest3.type = new messages_1.ProtocolRequestType(ReferencesRequest3.method); + })(ReferencesRequest2 = exports2.ReferencesRequest || (exports2.ReferencesRequest = {})); + var DocumentHighlightRequest2; + (function(DocumentHighlightRequest3) { + DocumentHighlightRequest3.method = "textDocument/documentHighlight"; + DocumentHighlightRequest3.type = new messages_1.ProtocolRequestType(DocumentHighlightRequest3.method); + })(DocumentHighlightRequest2 = exports2.DocumentHighlightRequest || (exports2.DocumentHighlightRequest = {})); + var DocumentSymbolRequest2; + (function(DocumentSymbolRequest3) { + DocumentSymbolRequest3.method = "textDocument/documentSymbol"; + DocumentSymbolRequest3.type = new messages_1.ProtocolRequestType(DocumentSymbolRequest3.method); + })(DocumentSymbolRequest2 = exports2.DocumentSymbolRequest || (exports2.DocumentSymbolRequest = {})); + var CodeActionRequest2; + (function(CodeActionRequest3) { + CodeActionRequest3.method = "textDocument/codeAction"; + CodeActionRequest3.type = new messages_1.ProtocolRequestType(CodeActionRequest3.method); + })(CodeActionRequest2 = exports2.CodeActionRequest || (exports2.CodeActionRequest = {})); + var CodeActionResolveRequest2; + (function(CodeActionResolveRequest3) { + CodeActionResolveRequest3.method = "codeAction/resolve"; + CodeActionResolveRequest3.type = new messages_1.ProtocolRequestType(CodeActionResolveRequest3.method); + })(CodeActionResolveRequest2 = exports2.CodeActionResolveRequest || (exports2.CodeActionResolveRequest = {})); + var WorkspaceSymbolRequest2; + (function(WorkspaceSymbolRequest3) { + WorkspaceSymbolRequest3.method = "workspace/symbol"; + WorkspaceSymbolRequest3.type = new messages_1.ProtocolRequestType(WorkspaceSymbolRequest3.method); + })(WorkspaceSymbolRequest2 = exports2.WorkspaceSymbolRequest || (exports2.WorkspaceSymbolRequest = {})); + var CodeLensRequest2; + (function(CodeLensRequest3) { + CodeLensRequest3.method = "textDocument/codeLens"; + CodeLensRequest3.type = new messages_1.ProtocolRequestType(CodeLensRequest3.method); + })(CodeLensRequest2 = exports2.CodeLensRequest || (exports2.CodeLensRequest = {})); + var CodeLensResolveRequest2; + (function(CodeLensResolveRequest3) { + CodeLensResolveRequest3.method = "codeLens/resolve"; + CodeLensResolveRequest3.type = new messages_1.ProtocolRequestType(CodeLensResolveRequest3.method); + })(CodeLensResolveRequest2 = exports2.CodeLensResolveRequest || (exports2.CodeLensResolveRequest = {})); + var CodeLensRefreshRequest2; + (function(CodeLensRefreshRequest3) { + CodeLensRefreshRequest3.method = `workspace/codeLens/refresh`; + CodeLensRefreshRequest3.type = new messages_1.ProtocolRequestType0(CodeLensRefreshRequest3.method); + })(CodeLensRefreshRequest2 = exports2.CodeLensRefreshRequest || (exports2.CodeLensRefreshRequest = {})); + var DocumentLinkRequest2; + (function(DocumentLinkRequest3) { + DocumentLinkRequest3.method = "textDocument/documentLink"; + DocumentLinkRequest3.type = new messages_1.ProtocolRequestType(DocumentLinkRequest3.method); + })(DocumentLinkRequest2 = exports2.DocumentLinkRequest || (exports2.DocumentLinkRequest = {})); + var DocumentLinkResolveRequest2; + (function(DocumentLinkResolveRequest3) { + DocumentLinkResolveRequest3.method = "documentLink/resolve"; + DocumentLinkResolveRequest3.type = new messages_1.ProtocolRequestType(DocumentLinkResolveRequest3.method); + })(DocumentLinkResolveRequest2 = exports2.DocumentLinkResolveRequest || (exports2.DocumentLinkResolveRequest = {})); + var DocumentFormattingRequest2; + (function(DocumentFormattingRequest3) { + DocumentFormattingRequest3.method = "textDocument/formatting"; + DocumentFormattingRequest3.type = new messages_1.ProtocolRequestType(DocumentFormattingRequest3.method); + })(DocumentFormattingRequest2 = exports2.DocumentFormattingRequest || (exports2.DocumentFormattingRequest = {})); + var DocumentRangeFormattingRequest2; + (function(DocumentRangeFormattingRequest3) { + DocumentRangeFormattingRequest3.method = "textDocument/rangeFormatting"; + DocumentRangeFormattingRequest3.type = new messages_1.ProtocolRequestType(DocumentRangeFormattingRequest3.method); + })(DocumentRangeFormattingRequest2 = exports2.DocumentRangeFormattingRequest || (exports2.DocumentRangeFormattingRequest = {})); + var DocumentOnTypeFormattingRequest2; + (function(DocumentOnTypeFormattingRequest3) { + DocumentOnTypeFormattingRequest3.method = "textDocument/onTypeFormatting"; + DocumentOnTypeFormattingRequest3.type = new messages_1.ProtocolRequestType(DocumentOnTypeFormattingRequest3.method); + })(DocumentOnTypeFormattingRequest2 = exports2.DocumentOnTypeFormattingRequest || (exports2.DocumentOnTypeFormattingRequest = {})); + var PrepareSupportDefaultBehavior; + (function(PrepareSupportDefaultBehavior2) { + PrepareSupportDefaultBehavior2.Identifier = 1; + })(PrepareSupportDefaultBehavior = exports2.PrepareSupportDefaultBehavior || (exports2.PrepareSupportDefaultBehavior = {})); + var RenameRequest2; + (function(RenameRequest3) { + RenameRequest3.method = "textDocument/rename"; + RenameRequest3.type = new messages_1.ProtocolRequestType(RenameRequest3.method); + })(RenameRequest2 = exports2.RenameRequest || (exports2.RenameRequest = {})); + var PrepareRenameRequest2; + (function(PrepareRenameRequest3) { + PrepareRenameRequest3.method = "textDocument/prepareRename"; + PrepareRenameRequest3.type = new messages_1.ProtocolRequestType(PrepareRenameRequest3.method); + })(PrepareRenameRequest2 = exports2.PrepareRenameRequest || (exports2.PrepareRenameRequest = {})); + var ExecuteCommandRequest2; + (function(ExecuteCommandRequest3) { + ExecuteCommandRequest3.type = new messages_1.ProtocolRequestType("workspace/executeCommand"); + })(ExecuteCommandRequest2 = exports2.ExecuteCommandRequest || (exports2.ExecuteCommandRequest = {})); + var ApplyWorkspaceEditRequest2; + (function(ApplyWorkspaceEditRequest3) { + ApplyWorkspaceEditRequest3.type = new messages_1.ProtocolRequestType("workspace/applyEdit"); + })(ApplyWorkspaceEditRequest2 = exports2.ApplyWorkspaceEditRequest || (exports2.ApplyWorkspaceEditRequest = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/connection.js +var require_connection3 = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/connection.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createProtocolConnection = void 0; + var vscode_jsonrpc_1 = require_main(); + function createProtocolConnection2(input, output, logger113, options) { + if (vscode_jsonrpc_1.ConnectionStrategy.is(options)) { + options = { connectionStrategy: options }; + } + return vscode_jsonrpc_1.createMessageConnection(input, output, logger113, options); + } + exports2.createProtocolConnection = createProtocolConnection2; + } +}); + +// node_modules/vscode-languageserver-protocol/lib/common/api.js +var require_api3 = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/common/api.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { + return m[k]; + } }); + } : function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + o[k2] = m[k]; + }); + var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) { + for (var p in m) + if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) + __createBinding(exports3, m, p); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.LSPErrorCodes = exports2.createProtocolConnection = void 0; + __exportStar(require_main(), exports2); + __exportStar((init_main(), main_exports), exports2); + __exportStar(require_messages2(), exports2); + __exportStar(require_protocol(), exports2); + var connection_1 = require_connection3(); + Object.defineProperty(exports2, "createProtocolConnection", { enumerable: true, get: function() { + return connection_1.createProtocolConnection; + } }); + var LSPErrorCodes2; + (function(LSPErrorCodes3) { + LSPErrorCodes3.lspReservedErrorRangeStart = -32899; + LSPErrorCodes3.ContentModified = -32801; + LSPErrorCodes3.RequestCancelled = -32800; + LSPErrorCodes3.lspReservedErrorRangeEnd = -32800; + })(LSPErrorCodes2 = exports2.LSPErrorCodes || (exports2.LSPErrorCodes = {})); + } +}); + +// node_modules/vscode-languageserver-protocol/lib/node/main.js +var require_main2 = __commonJS({ + "node_modules/vscode-languageserver-protocol/lib/node/main.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { + return m[k]; + } }); + } : function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + o[k2] = m[k]; + }); + var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) { + for (var p in m) + if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) + __createBinding(exports3, m, p); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createProtocolConnection = void 0; + var node_1 = require_node2(); + __exportStar(require_node2(), exports2); + __exportStar(require_api3(), exports2); + function createProtocolConnection2(input, output, logger113, options) { + return node_1.createMessageConnection(input, output, logger113, options); + } + exports2.createProtocolConnection = createProtocolConnection2; + } +}); + +// node_modules/debounce/index.js +var require_debounce = __commonJS({ + "node_modules/debounce/index.js"(exports2, module2) { + function debounce15(func2, wait2, immediate) { + var timeout, args, context, timestamp, result; + if (wait2 == null) + wait2 = 100; + function later() { + var last = Date.now() - timestamp; + if (last < wait2 && last >= 0) { + timeout = setTimeout(later, wait2 - last); + } else { + timeout = null; + if (!immediate) { + result = func2.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, wait2); + if (callNow) { + result = func2.apply(context, args); + context = args = null; + } + return result; + }; + debounced.clear = function() { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + }; + debounced.flush = function() { + if (timeout) { + result = func2.apply(context, args); + context = args = null; + clearTimeout(timeout); + timeout = null; + } + }; + return debounced; + } + debounce15.debounce = debounce15; + module2.exports = debounce15; + } +}); + +// node_modules/rfc-3986/index.js +var require_rfc_3986 = __commonJS({ + "node_modules/rfc-3986/index.js"(exports2, module2) { + "use strict"; + var internals = { + rfc3986: {} + }; + internals.generate = function() { + var or = "|"; + var digit = "0-9"; + var digitOnly = "[" + digit + "]"; + var alpha = "a-zA-Z"; + var alphaOnly = "[" + alpha + "]"; + internals.rfc3986.cidr = digitOnly + or + "[1-2]" + digitOnly + or + "3[0-2]"; + var hexDigit = digit + "A-Fa-f"; + var hexDigitOnly = "[" + hexDigit + "]"; + var unreserved = alpha + digit + "-\\._~"; + var subDelims = "!\\$&'\\(\\)\\*\\+,;="; + var pctEncoded = "%" + hexDigit; + var pchar = unreserved + pctEncoded + subDelims + ":@"; + var pcharOnly = "[" + pchar + "]"; + var zeroPad = "0?"; + var decOctect = "(?:" + zeroPad + zeroPad + digitOnly + or + zeroPad + "[1-9]" + digitOnly + or + "1" + digitOnly + digitOnly + or + "2[0-4]" + digitOnly + or + "25[0-5])"; + internals.rfc3986.IPv4address = "(?:" + decOctect + "\\.){3}" + decOctect; + 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 + ")"; + internals.rfc3986.IPvFuture = "v" + hexDigitOnly + "+\\.[" + unreserved + subDelims + ":]+"; + internals.rfc3986.scheme = alphaOnly + "[" + alpha + digit + "+-\\.]*"; + var userinfo = "[" + unreserved + pctEncoded + subDelims + ":]*"; + internals.rfc3986.IPLiteral = "\\[(?:" + internals.rfc3986.IPv6address + or + internals.rfc3986.IPvFuture + ")\\]"; + var regName = "[" + unreserved + pctEncoded + subDelims + "]{0,255}"; + var host = "(?:" + internals.rfc3986.IPLiteral + or + internals.rfc3986.IPv4address + or + regName + ")"; + var port = digitOnly + "*"; + var authority = "(?:" + userinfo + "@)?" + host + "(?::" + port + ")?"; + var segment = pcharOnly + "*"; + var segmentNz = pcharOnly + "+"; + var pathAbEmpty = "(?:\\/" + segment + ")*"; + var pathAbsolute = "\\/(?:" + segmentNz + pathAbEmpty + ")?"; + var pathRootless = segmentNz + pathAbEmpty; + internals.rfc3986.hierPart = "(?:(?:\\/\\/" + authority + pathAbEmpty + ")" + or + pathAbsolute + or + pathRootless + ")"; + internals.rfc3986.query = "[" + pchar + "\\/\\?]*(?=#|$)"; + internals.rfc3986.fragment = "[" + pchar + "\\/\\?]*"; + internals.rfc3986.uri = "^(?:" + internals.rfc3986.scheme + ":" + internals.rfc3986.hierPart + ")(?:\\?" + internals.rfc3986.query + ")?(?:#" + internals.rfc3986.fragment + ")?$"; + }; + internals.generate(); + module2.exports = internals.rfc3986; + } +}); + +// node_modules/isuri/index.js +var require_isuri = __commonJS({ + "node_modules/isuri/index.js"(exports2, module2) { + "use strict"; + var rfc3986 = require_rfc_3986(); + function escapeRegex(string2) { + return string2.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 (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"); + } + customScheme = customScheme + (customScheme ? "|" : ""); + 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); + } + } + } + var scheme = "(?:" + (customScheme || rfc3986.scheme) + ")"; + 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); + }; + module2.exports = { + createUriRegex: internals.Uri.createUriRegex, + uriRegex: internals.Uri.uriRegex, + isValid: internals.Uri.isValid + }; + } +}); + +// node_modules/vscode-uri/lib/esm/index.js +function _validateUri(ret, _strict) { + if (!ret.scheme && _strict) { + throw new Error('[UriError]: Scheme is missing: {scheme: "", authority: "' + ret.authority + '", path: "' + ret.path + '", query: "' + ret.query + '", fragment: "' + ret.fragment + '"}'); + } + if (ret.scheme && !_schemePattern.test(ret.scheme)) { + throw new Error("[UriError]: Scheme contains illegal 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 ("//")'); + } + } + } +} +function _schemeFix(scheme, _strict) { + if (!scheme && !_strict) { + return "file"; + } + return scheme; +} +function _referenceResolution(scheme, path36) { + switch (scheme) { + case "https": + case "http": + case "file": + if (!path36) { + path36 = _slash; + } else if (path36[0] !== _slash) { + path36 = _slash + path36; + } + break; + } + return path36; +} +function encodeURIComponentFast(uriComponent, allowSlash) { + var res = void 0; + var nativeEncodePos = -1; + for (var pos = 0; pos < uriComponent.length; pos++) { + var code = uriComponent.charCodeAt(pos); + if (code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 45 || code === 46 || code === 95 || code === 126 || allowSlash && code === 47) { + if (nativeEncodePos !== -1) { + res += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos)); + nativeEncodePos = -1; + } + if (res !== void 0) { + res += uriComponent.charAt(pos); + } + } else { + if (res === void 0) { + res = uriComponent.substr(0, pos); + } + var escaped = encodeTable[code]; + if (escaped !== void 0) { + if (nativeEncodePos !== -1) { + res += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos)); + nativeEncodePos = -1; + } + res += escaped; + } else if (nativeEncodePos === -1) { + nativeEncodePos = pos; + } + } + } + if (nativeEncodePos !== -1) { + res += encodeURIComponent(uriComponent.substring(nativeEncodePos)); + } + return res !== void 0 ? res : uriComponent; +} +function encodeURIComponentMinimal(path36) { + var res = void 0; + for (var pos = 0; pos < path36.length; pos++) { + var code = path36.charCodeAt(pos); + if (code === 35 || code === 63) { + if (res === void 0) { + res = path36.substr(0, pos); + } + res += encodeTable[code]; + } else { + if (res !== void 0) { + res += path36[pos]; + } + } + } + return res !== void 0 ? res : path36; +} +function uriToFsPath(uri, keepDriveLetterCasing) { + var value; + if (uri.authority && uri.path.length > 1 && uri.scheme === "file") { + value = "//" + uri.authority + uri.path; + } else if (uri.path.charCodeAt(0) === 47 && (uri.path.charCodeAt(1) >= 65 && uri.path.charCodeAt(1) <= 90 || uri.path.charCodeAt(1) >= 97 && uri.path.charCodeAt(1) <= 122) && uri.path.charCodeAt(2) === 58) { + if (!keepDriveLetterCasing) { + value = uri.path[1].toLowerCase() + uri.path.substr(2); + } else { + value = uri.path.substr(1); + } + } else { + value = uri.path; + } + if (isWindows) { + value = value.replace(/\//g, "\\"); + } + return value; +} +function _asFormatted(uri, skipEncoding) { + var encoder = !skipEncoding ? encodeURIComponentFast : encodeURIComponentMinimal; + var res = ""; + var scheme = uri.scheme, authority = uri.authority, path36 = 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) { + var userinfo = authority.substr(0, idx); + authority = authority.substr(idx + 1); + idx = userinfo.indexOf(":"); + if (idx === -1) { + res += encoder(userinfo, false); + } else { + 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 { + res += encoder(authority.substr(0, idx), false); + res += authority.substr(idx); + } + } + if (path36) { + if (path36.length >= 3 && path36.charCodeAt(0) === 47 && path36.charCodeAt(2) === 58) { + var code = path36.charCodeAt(1); + if (code >= 65 && code <= 90) { + path36 = "/" + String.fromCharCode(code + 32) + ":" + path36.substr(3); + } + } else if (path36.length >= 2 && path36.charCodeAt(1) === 58) { + var code = path36.charCodeAt(0); + if (code >= 65 && code <= 90) { + path36 = String.fromCharCode(code + 32) + ":" + path36.substr(2); + } + } + res += encoder(path36, true); + } + if (query) { + res += "?"; + res += encoder(query, false); + } + if (fragment) { + res += "#"; + res += !skipEncoding ? encodeURIComponentFast(fragment, false) : fragment; + } + return res; +} +function decodeURIComponentGraceful(str) { + try { + return decodeURIComponent(str); + } catch (_a2) { + if (str.length > 3) { + return str.substr(0, 3) + decodeURIComponentGraceful(str.substr(3)); + } else { + return str; + } + } +} +function percentDecode(str) { + if (!str.match(_rEncodedAsHex)) { + return str; + } + return str.replace(_rEncodedAsHex, function(match) { + return decodeURIComponentGraceful(match); + }); +} +var __extends, _a, isWindows, userAgent, _schemePattern, _singleSlashStart, _doubleSlashStart, _empty, _slash, _regexp, URI, _pathSepMarker, _URI, encodeTable, _rEncodedAsHex; +var init_esm2 = __esm({ + "node_modules/vscode-uri/lib/esm/index.js"() { + "use strict"; + __extends = function() { + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) { + d2.__proto__ = b2; + } || function(d2, b2) { + for (var p in b2) + if (b2.hasOwnProperty(p)) + d2[p] = b2[p]; + }; + return extendStatics(d, b); + }; + return function(d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + }(); + if (typeof process === "object") { + isWindows = process.platform === "win32"; + } else if (typeof navigator === "object") { + userAgent = navigator.userAgent; + isWindows = userAgent.indexOf("Windows") >= 0; + } + _schemePattern = /^\w[\w\d+.-]*$/; + _singleSlashStart = /^\//; + _doubleSlashStart = /^\/\//; + _empty = ""; + _slash = "/"; + _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; + URI = function() { + function URI2(schemeOrData, authority, path36, 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; + } else { + this.scheme = _schemeFix(schemeOrData, _strict); + this.authority = authority || _empty; + this.path = _referenceResolution(this.scheme, path36 || _empty); + this.query = query || _empty; + this.fragment = fragment || _empty; + _validateUri(this, _strict); + } + } + URI2.isUri = function(thing) { + if (thing instanceof URI2) { + 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(URI2.prototype, "fsPath", { + get: function() { + return uriToFsPath(this, false); + }, + enumerable: true, + configurable: true + }); + URI2.prototype.with = function(change) { + if (!change) { + return this; + } + var scheme = change.scheme, authority = change.authority, path36 = change.path, query = change.query, fragment = change.fragment; + if (scheme === void 0) { + scheme = this.scheme; + } else if (scheme === null) { + scheme = _empty; + } + if (authority === void 0) { + authority = this.authority; + } else if (authority === null) { + authority = _empty; + } + if (path36 === void 0) { + path36 = this.path; + } else if (path36 === null) { + path36 = _empty; + } + if (query === void 0) { + query = this.query; + } else if (query === null) { + query = _empty; + } + if (fragment === void 0) { + fragment = this.fragment; + } else if (fragment === null) { + fragment = _empty; + } + if (scheme === this.scheme && authority === this.authority && path36 === this.path && query === this.query && fragment === this.fragment) { + return this; + } + return new _URI(scheme, authority, path36, query, fragment); + }; + URI2.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, percentDecode(match[4] || _empty), percentDecode(match[5] || _empty), percentDecode(match[7] || _empty), percentDecode(match[9] || _empty), _strict); + }; + URI2.file = function(path36) { + var authority = _empty; + if (isWindows) { + path36 = path36.replace(/\\/g, _slash); + } + if (path36[0] === _slash && path36[1] === _slash) { + var idx = path36.indexOf(_slash, 2); + if (idx === -1) { + authority = path36.substring(2); + path36 = _slash; + } else { + authority = path36.substring(2, idx); + path36 = path36.substring(idx) || _slash; + } + } + return new _URI("file", authority, path36, _empty, _empty); + }; + URI2.from = function(components) { + return new _URI(components.scheme, components.authority, components.path, components.query, components.fragment); + }; + URI2.prototype.toString = function(skipEncoding) { + if (skipEncoding === void 0) { + skipEncoding = false; + } + return _asFormatted(this, skipEncoding); + }; + URI2.prototype.toJSON = function() { + return this; + }; + URI2.revive = function(data) { + if (!data) { + return data; + } else if (data instanceof URI2) { + return data; + } else { + var result = new _URI(data); + result._formatted = data.external; + result._fsPath = data._sep === _pathSepMarker ? data.fsPath : null; + return result; + } + }; + return URI2; + }(); + _pathSepMarker = isWindows ? 1 : void 0; + _URI = function(_super) { + __extends(_URI2, _super); + function _URI2() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this._formatted = null; + _this._fsPath = null; + return _this; + } + Object.defineProperty(_URI2.prototype, "fsPath", { + get: function() { + if (!this._fsPath) { + this._fsPath = uriToFsPath(this, false); + } + return this._fsPath; + }, + enumerable: true, + configurable: true + }); + _URI2.prototype.toString = function(skipEncoding) { + if (skipEncoding === void 0) { + skipEncoding = false; + } + if (!skipEncoding) { + if (!this._formatted) { + this._formatted = _asFormatted(this, false); + } + return this._formatted; + } else { + return _asFormatted(this, true); + } + }; + _URI2.prototype.toJSON = function() { + var res = { + $mid: 1 + }; + if (this._fsPath) { + res.fsPath = this._fsPath; + res._sep = _pathSepMarker; + } + if (this._formatted) { + res.external = this._formatted; + } + 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 _URI2; + }(URI); + encodeTable = (_a = {}, _a[58] = "%3A", _a[47] = "%2F", _a[63] = "%3F", _a[35] = "%23", _a[91] = "%5B", _a[93] = "%5D", _a[64] = "%40", _a[33] = "%21", _a[36] = "%24", _a[38] = "%26", _a[39] = "%27", _a[40] = "%28", _a[41] = "%29", _a[42] = "%2A", _a[43] = "%2B", _a[44] = "%2C", _a[59] = "%3B", _a[61] = "%3D", _a[32] = "%20", _a); + _rEncodedAsHex = /(%[0-9A-Za-z][0-9A-Za-z])+/g; + } +}); + +// node_modules/isexe/windows.js +var require_windows = __commonJS({ + "node_modules/isexe/windows.js"(exports2, module2) { + module2.exports = isexe; + isexe.sync = sync; + var fs27 = require("fs"); + function checkPathExt(path36, options) { + var pathext = options.pathExt !== void 0 ? 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 && path36.substr(-p.length).toLowerCase() === p) { + return true; + } + } + return false; + } + function checkStat(stat, path36, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false; + } + return checkPathExt(path36, options); + } + function isexe(path36, options, cb) { + fs27.stat(path36, function(er, stat) { + cb(er, er ? false : checkStat(stat, path36, options)); + }); + } + function sync(path36, options) { + return checkStat(fs27.statSync(path36), path36, options); + } + } +}); + +// node_modules/isexe/mode.js +var require_mode = __commonJS({ + "node_modules/isexe/mode.js"(exports2, module2) { + module2.exports = isexe; + isexe.sync = sync; + var fs27 = require("fs"); + function isexe(path36, options, cb) { + fs27.stat(path36, function(er, stat) { + cb(er, er ? false : checkStat(stat, options)); + }); + } + function sync(path36, options) { + return checkStat(fs27.statSync(path36), 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 !== void 0 ? options.uid : process.getuid && process.getuid(); + var myGid = options.gid !== void 0 ? 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; + } + } +}); + +// node_modules/isexe/index.js +var require_isexe = __commonJS({ + "node_modules/isexe/index.js"(exports2, module2) { + var fs27 = require("fs"); + var core; + if (process.platform === "win32" || global.TESTING_WINDOWS) { + core = require_windows(); + } else { + core = require_mode(); + } + module2.exports = isexe; + isexe.sync = sync; + function isexe(path36, 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(resolve3, reject) { + isexe(path36, options || {}, function(er, is) { + if (er) { + reject(er); + } else { + resolve3(is); + } + }); + }); + } + core(path36, options || {}, function(er, is) { + if (er) { + if (er.code === "EACCES" || options && options.ignoreErrors) { + er = null; + is = false; + } + } + cb(er, is); + }); + } + function sync(path36, options) { + try { + return core.sync(path36, options || {}); + } catch (er) { + if (options && options.ignoreErrors || er.code === "EACCES") { + return false; + } else { + throw er; + } + } + } + } +}); + +// node_modules/which/which.js +var require_which = __commonJS({ + "node_modules/which/which.js"(exports2, module2) { + var isWindows4 = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys"; + var path36 = require("path"); + var COLON = isWindows4 ? ";" : ":"; + var isexe = require_isexe(); + var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" }); + var getPathInfo = (cmd, opt) => { + const colon = opt.colon || COLON; + const pathEnv = cmd.match(/\//) || isWindows4 && cmd.match(/\\/) ? [""] : [ + ...isWindows4 ? [process.cwd()] : [], + ...(opt.path || process.env.PATH || "").split(colon) + ]; + const pathExtExe = isWindows4 ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : ""; + const pathExt = isWindows4 ? pathExtExe.split(colon) : [""]; + if (isWindows4) { + if (cmd.indexOf(".") !== -1 && pathExt[0] !== "") + pathExt.unshift(""); + } + return { + pathEnv, + pathExt, + pathExtExe + }; + }; + var which5 = (cmd, opt, cb) => { + if (typeof opt === "function") { + cb = opt; + opt = {}; + } + if (!opt) + opt = {}; + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); + const found = []; + const step = (i) => new Promise((resolve3, reject) => { + if (i === pathEnv.length) + return opt.all && found.length ? resolve3(found) : reject(getNotFoundError(cmd)); + const ppRaw = pathEnv[i]; + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw; + const pCmd = path36.join(pathPart, cmd); + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd; + resolve3(subStep(p, i, 0)); + }); + const subStep = (p, i, ii) => new Promise((resolve3, reject) => { + if (ii === pathExt.length) + return resolve3(step(i + 1)); + const ext = pathExt[ii]; + isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { + if (!er && is) { + if (opt.all) + found.push(p + ext); + else + return resolve3(p + ext); + } + return resolve3(subStep(p, i, ii + 1)); + }); + }); + return cb ? step(0).then((res) => cb(null, res), cb) : step(0); + }; + var whichSync = (cmd, opt) => { + opt = opt || {}; + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); + const found = []; + for (let i = 0; i < pathEnv.length; i++) { + const ppRaw = pathEnv[i]; + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw; + const pCmd = path36.join(pathPart, cmd); + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd; + for (let j = 0; j < pathExt.length; j++) { + const cur = p + pathExt[j]; + try { + const 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); + }; + module2.exports = which5; + which5.sync = whichSync; + } +}); + +// src/util/platform.ts +var platform_exports = {}; +__export(platform_exports, { + OS: () => OS, + OperatingSystem: () => OperatingSystem, + Platform: () => Platform, + globals: () => globals, + isLinux: () => isLinux, + isMacintosh: () => isMacintosh, + isNative: () => isNative, + isWeb: () => isWeb, + isWindows: () => isWindows2, + language: () => language, + platform: () => platform +}); +var _isWindows, _isMacintosh, _isLinux, _isNative, _isWeb, language, Platform, _platform, isWindows2, isMacintosh, isLinux, isNative, isWeb, platform, _globals, globals, OperatingSystem, OS; +var init_platform = __esm({ + "src/util/platform.ts"() { + _isWindows = false; + _isMacintosh = false; + _isLinux = false; + _isNative = false; + _isWeb = false; + language = "en"; + 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; + } + (function(Platform2) { + Platform2[Platform2["Web"] = 0] = "Web"; + Platform2[Platform2["Mac"] = 1] = "Mac"; + Platform2[Platform2["Linux"] = 2] = "Linux"; + Platform2[Platform2["Windows"] = 3] = "Windows"; + })(Platform || (Platform = {})); + _platform = 0; + if (_isNative) { + if (_isMacintosh) { + _platform = 1; + } else if (_isWindows) { + _platform = 3; + } else if (_isLinux) { + _platform = 2; + } + } + isWindows2 = _isWindows; + isMacintosh = _isMacintosh; + isLinux = _isLinux; + isNative = _isNative; + isWeb = _isWeb; + platform = _platform; + _globals = typeof self === "object" ? self : typeof global === "object" ? global : {}; + globals = _globals; + (function(OperatingSystem2) { + OperatingSystem2[OperatingSystem2["Windows"] = 1] = "Windows"; + OperatingSystem2[OperatingSystem2["Macintosh"] = 2] = "Macintosh"; + OperatingSystem2[OperatingSystem2["Linux"] = 3] = "Linux"; + })(OperatingSystem || (OperatingSystem = {})); + OS = _isMacintosh ? 2 : _isWindows ? 1 : 3; + } +}); + +// src/util/index.ts +function isMarkdown(content) { + if (import_vscode_languageserver_protocol.MarkupContent.is(content) && content.kind == import_vscode_languageserver_protocol.MarkupKind.Markdown) { + return true; + } + return false; +} +function wait(ms) { + return new Promise((resolve3) => { + setTimeout(() => { + resolve3(void 0); + }, ms); + }); +} +function waitNextTick(fn) { + return new Promise((resolve3) => { + process.nextTick(() => { + fn(); + resolve3(void 0); + }); + }); +} +function getUri(fullpath, id, buftype, isCygwin) { + if (!fullpath) + return `untitled:${id}`; + if (isWindows2 && !isCygwin && !fullpath.startsWith("jdt://")) + fullpath = import_path.default.win32.normalize(fullpath); + if (import_path.default.isAbsolute(fullpath)) + return URI.file(fullpath).toString(); + if (import_isuri.default.isValid(fullpath)) + return URI.parse(fullpath).toString(); + if (buftype != "") + return `${buftype}:${id}`; + return `unknown:${id}`; +} +function disposeAll(disposables) { + while (disposables.length) { + const item = disposables.pop(); + if (item) { + item.dispose(); + } + } +} +function executable(command) { + try { + import_which.default.sync(command); + } catch (e) { + return false; + } + return true; +} +function runCommand(cmd, opts = {}, timeout) { + if (!isWindows2) { + opts.shell = opts.shell || process.env.SHELL; + } + opts.maxBuffer = 500 * 1024; + return new Promise((resolve3, reject) => { + let timer; + if (timeout) { + timer = setTimeout(() => { + reject(new Error(`timeout after ${timeout}s`)); + }, timeout * 1e3); + } + (0, import_child_process.exec)(cmd, opts, (err, stdout, stderr) => { + if (timer) + clearTimeout(timer); + if (err) { + reject(new Error(`exited with ${err.code} +${err} +${stderr}`)); + return; + } + resolve3(stdout); + }); + }); +} +function watchFile(filepath, onChange) { + let callback = (0, import_debounce.default)(onChange, 100); + try { + let watcher = import_fs.default.watch(filepath, { + persistent: true, + recursive: false, + encoding: "utf8" + }, () => { + callback(); + }); + return import_vscode_languageserver_protocol.Disposable.create(() => { + callback.clear(); + watcher.close(); + }); + } catch (e) { + return import_vscode_languageserver_protocol.Disposable.create(() => { + callback.clear(); + }); + } +} +function isRunning(pid) { + try { + let res = process.kill(pid, 0); + return res == true; + } catch (e) { + return e.code === "EPERM"; + } +} +function getKeymapModifier(mode) { + if (mode == "n" || mode == "o" || mode == "x" || mode == "v") + return ""; + if (mode == "i") + return ""; + if (mode == "s") + return ""; + return ""; +} +function concurrent(arr, fn, limit = 3) { + if (arr.length == 0) + return Promise.resolve(); + let finished = 0; + let total = arr.length; + let remain = arr.slice(); + return new Promise((resolve3) => { + let run = (val) => { + let cb = () => { + finished = finished + 1; + if (finished == total) { + resolve3(); + } else if (remain.length) { + let next = remain.shift(); + run(next); + } + }; + fn(val).then(cb, cb); + }; + for (let i = 0; i < Math.min(limit, remain.length); i++) { + let val = remain.shift(); + run(val); + } + }); +} +var import_child_process, import_debounce, import_fs, import_isuri, import_path, import_vscode_languageserver_protocol, import_which, logger, CONFIG_FILE_NAME; +var init_util = __esm({ + "src/util/index.ts"() { + import_child_process = __toModule(require("child_process")); + import_debounce = __toModule(require_debounce()); + import_fs = __toModule(require("fs")); + import_isuri = __toModule(require_isuri()); + import_path = __toModule(require("path")); + import_vscode_languageserver_protocol = __toModule(require_main2()); + init_esm2(); + import_which = __toModule(require_which()); + init_platform(); + logger = require_logger2()("util-index"); + CONFIG_FILE_NAME = "coc-settings.json"; + } +}); + +// src/util/is.ts +function vimCompleteItem(value) { + return value && typeof value.word === "string"; +} +function boolean(value) { + return typeof value === "boolean"; +} +function string(value) { + return typeof value === "string"; +} +function number(value) { + return typeof value === "number"; +} +function func(value) { + return typeof value == "function"; +} +function objectLiteral(obj) { + return obj != null && typeof obj === "object" && !Array.isArray(obj) && !(obj instanceof RegExp) && !(obj instanceof Date); +} +function emptyObject(obj) { + if (!objectLiteral(obj)) { + return false; + } + for (let key in obj) { + if (hasOwnProperty.call(obj, key)) { + return false; + } + } + return true; +} +var hasOwnProperty; +var init_is = __esm({ + "src/util/is.ts"() { + hasOwnProperty = Object.prototype.hasOwnProperty; + } +}); + +// src/util/object.ts +function isEmpty(obj) { + if (!obj) + return true; + if (Array.isArray(obj)) + return obj.length == 0; + return Object.keys(obj).length == 0; +} +function deepClone(obj) { + if (!obj || typeof obj !== "object") { + return obj; + } + if (obj instanceof RegExp) { + 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; +} +function deepFreeze(obj) { + if (!obj || typeof obj !== "object") { + return obj; + } + const stack = [obj]; + while (stack.length > 0) { + let obj2 = stack.shift(); + Object.freeze(obj2); + for (const key in obj2) { + if (_hasOwnProperty.call(obj2, key)) { + let prop = obj2[key]; + if (typeof prop === "object" && !Object.isFrozen(prop)) { + stack.push(prop); + } + } + } + } + return obj; +} +function mixin(destination, source, overwrite = true) { + if (!objectLiteral(destination)) { + return source; + } + if (objectLiteral(source)) { + Object.keys(source).forEach((key) => { + if (key in destination) { + if (overwrite) { + if (objectLiteral(destination[key]) && objectLiteral(source[key])) { + mixin(destination[key], source[key], overwrite); + } else { + destination[key] = source[key]; + } + } + } else { + destination[key] = source[key]; + } + }); + } + return destination; +} +function equals(one, other) { + if (one === other) { + return true; + } + if (one === null || one === void 0 || other === null || other === void 0) { + 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) { + oneKeys.push(key); + } + oneKeys.sort(); + const otherKeys = []; + for (key in other) { + 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; +} +var _hasOwnProperty; +var init_object = __esm({ + "src/util/object.ts"() { + init_is(); + _hasOwnProperty = Object.prototype.hasOwnProperty; + } +}); + +// src/events.ts +var import_vscode_languageserver_protocol2, logger2, Events, events_default; +var init_events = __esm({ + "src/events.ts"() { + import_vscode_languageserver_protocol2 = __toModule(require_main2()); + init_util(); + init_object(); + logger2 = require_logger2()("events"); + Events = class { + constructor() { + this.handlers = new Map(); + this._lastChange = 0; + this._insertMode = false; + this._pumAlignTop = false; + } + get cursor() { + return this._cursor; + } + get pumAlignTop() { + return this._pumAlignTop; + } + get insertMode() { + return this._insertMode; + } + get lastChangeTs() { + return this._lastChange; + } + async fire(event, args) { + let cbs = 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; + void this.fire("InsertEnter", [args[0]]); + } else if (this._insertMode && (event == "CursorHold" || event == "CursorMoved")) { + this._insertMode = false; + this.fire("InsertLeave", [args[0]]).logError(); + } + if (event == "MenuPopupChanged") { + this._pumAlignTop = args[1] > args[0].row; + } + if (event == "InsertCharPre") { + this._latestInsert = { bufnr: args[1], character: args[0], timestamp: Date.now() }; + } + if (event == "TextChanged") { + this._lastChange = Date.now(); + } + if (event == "TextChangedI" || event == "TextChangedP") { + this._lastChange = Date.now(); + if (this._latestInsert) { + let insert = this._latestInsert; + this._latestInsert = void 0; + if (insert.bufnr == args[0] && Date.now() - insert.timestamp < 200 && args[1].pre.length) { + let character = args[1].pre.slice(-1); + process.nextTick(() => { + void this.fire("TextInsert", [...args, character]); + }); + } + } + } + if (event == "CursorMoved" || event == "CursorMovedI") { + let cursor = { + bufnr: args[0], + lnum: args[1][0], + col: args[1][1], + insert: event == "CursorMovedI" + }; + if (this._cursor && equals(this._cursor, cursor)) + return; + this._cursor = cursor; + } + if (cbs) { + try { + await Promise.all(cbs.map((fn) => fn(args))); + } catch (e) { + if (e.message && e.message.indexOf("transport disconnected") == -1) + return; + logger2.error(`Error on event: ${event}`, e.stack); + } + } + } + on(event, handler, thisArg, disposables) { + if (Array.isArray(event)) { + let arr = disposables || []; + for (let ev of event) { + this.on(ev, handler, thisArg, arr); + } + return import_vscode_languageserver_protocol2.Disposable.create(() => { + disposeAll(arr); + }); + } else { + let arr = this.handlers.get(event) || []; + let stack = Error().stack; + let wrappedhandler = (args) => new Promise((resolve3, reject) => { + let timer; + try { + Promise.resolve(handler.apply(thisArg || null, args)).then(() => { + if (timer) + clearTimeout(timer); + resolve3(void 0); + }, (e) => { + if (timer) + clearTimeout(timer); + reject(e); + }); + timer = setTimeout(() => { + logger2.warn(`Handler of ${event} blocked more than 2s:`, stack); + }, 2e3); + } catch (e) { + reject(e); + } + }); + arr.push(wrappedhandler); + this.handlers.set(event, arr); + let disposable = import_vscode_languageserver_protocol2.Disposable.create(() => { + let idx = arr.indexOf(wrappedhandler); + if (idx !== -1) { + arr.splice(idx, 1); + } + }); + if (disposables) { + disposables.push(disposable); + } + return disposable; + } + } + }; + events_default = new Events(); + } +}); + +// node_modules/marked/src/defaults.js +var require_defaults = __commonJS({ + "node_modules/marked/src/defaults.js"(exports2, module2) { + function getDefaults() { + return { + baseUrl: null, + breaks: false, + extensions: null, + gfm: true, + headerIds: true, + headerPrefix: "", + highlight: null, + langPrefix: "language-", + mangle: true, + pedantic: false, + renderer: null, + sanitize: false, + sanitizer: null, + silent: false, + smartLists: false, + smartypants: false, + tokenizer: null, + walkTokens: null, + xhtml: false + }; + } + function changeDefaults(newDefaults) { + module2.exports.defaults = newDefaults; + } + module2.exports = { + defaults: getDefaults(), + getDefaults, + changeDefaults + }; + } +}); + +// node_modules/marked/src/helpers.js +var require_helpers = __commonJS({ + "node_modules/marked/src/helpers.js"(exports2, module2) { + var escapeTest = /[&<>"']/; + var escapeReplace = /[&<>"']/g; + var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/; + var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g; + var escapeReplacements = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'" + }; + var getEscapeReplacement = (ch) => escapeReplacements[ch]; + function escape(html, encode) { + if (encode) { + if (escapeTest.test(html)) { + return html.replace(escapeReplace, getEscapeReplacement); + } + } else { + if (escapeTestNoEncode.test(html)) { + return html.replace(escapeReplaceNoEncode, getEscapeReplacement); + } + } + return html; + } + var unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig; + function unescape2(html) { + return html.replace(unescapeTest, (_, n) => { + n = n.toLowerCase(); + if (n === "colon") + return ":"; + if (n.charAt(0) === "#") { + return n.charAt(1) === "x" ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1)); + } + return ""; + }); + } + var caret = /(^|[^\[])\^/g; + function edit2(regex, opt) { + regex = regex.source || regex; + opt = opt || ""; + const obj = { + replace: (name2, val) => { + val = val.source || val; + val = val.replace(caret, "$1"); + regex = regex.replace(name2, val); + return obj; + }, + getRegex: () => { + return new RegExp(regex, opt); + } + }; + return obj; + } + var nonWordAndColonTest = /[^\w:]/g; + var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; + function cleanUrl(sanitize, base, href) { + if (sanitize) { + let prot; + try { + prot = decodeURIComponent(unescape2(href)).replace(nonWordAndColonTest, "").toLowerCase(); + } catch (e) { + return null; + } + if (prot.indexOf("javascript:") === 0 || prot.indexOf("vbscript:") === 0 || prot.indexOf("data:") === 0) { + return null; + } + } + if (base && !originIndependentUrl.test(href)) { + href = resolveUrl(base, href); + } + try { + href = encodeURI(href).replace(/%25/g, "%"); + } catch (e) { + return null; + } + return href; + } + var baseUrls = {}; + var justDomain = /^[^:]+:\/*[^/]*$/; + var protocol = /^([^:]+:)[\s\S]*$/; + var domain = /^([^:]+:\/*[^/]*)[\s\S]*$/; + function resolveUrl(base, href) { + if (!baseUrls[" " + base]) { + if (justDomain.test(base)) { + baseUrls[" " + base] = base + "/"; + } else { + baseUrls[" " + base] = rtrim(base, "/", true); + } + } + base = baseUrls[" " + base]; + const relativeBase = base.indexOf(":") === -1; + if (href.substring(0, 2) === "//") { + if (relativeBase) { + return href; + } + return base.replace(protocol, "$1") + href; + } else if (href.charAt(0) === "/") { + if (relativeBase) { + return href; + } + return base.replace(domain, "$1") + href; + } else { + return base + href; + } + } + var noopTest = { exec: function noopTest2() { + } }; + function merge(obj) { + let i = 1, target, key; + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + return obj; + } + function splitCells(tableRow, count) { + const row = tableRow.replace(/\|/g, (match, offset, str) => { + let escaped = false, curr = offset; + while (--curr >= 0 && str[curr] === "\\") + escaped = !escaped; + if (escaped) { + return "|"; + } else { + return " |"; + } + }), cells = row.split(/ \|/); + let i = 0; + if (cells.length > count) { + cells.splice(count); + } else { + while (cells.length < count) + cells.push(""); + } + for (; i < cells.length; i++) { + cells[i] = cells[i].trim().replace(/\\\|/g, "|"); + } + return cells; + } + function rtrim(str, c, invert) { + const l = str.length; + if (l === 0) { + return ""; + } + let suffLen = 0; + while (suffLen < l) { + const currChar = str.charAt(l - suffLen - 1); + if (currChar === c && !invert) { + suffLen++; + } else if (currChar !== c && invert) { + suffLen++; + } else { + break; + } + } + return str.substr(0, l - suffLen); + } + function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + const l = str.length; + let level = 0, i = 0; + for (; i < l; i++) { + if (str[i] === "\\") { + i++; + } else if (str[i] === b[0]) { + level++; + } else if (str[i] === b[1]) { + level--; + if (level < 0) { + return i; + } + } + } + return -1; + } + function checkSanitizeDeprecation(opt) { + if (opt && opt.sanitize && !opt.silent) { + console.warn("marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options"); + } + } + function repeatString(pattern, count) { + if (count < 1) { + return ""; + } + let result = ""; + while (count > 1) { + if (count & 1) { + result += pattern; + } + count >>= 1; + pattern += pattern; + } + return result + pattern; + } + module2.exports = { + escape, + unescape: unescape2, + edit: edit2, + cleanUrl, + resolveUrl, + noopTest, + merge, + splitCells, + rtrim, + findClosingBracket, + checkSanitizeDeprecation, + repeatString + }; + } +}); + +// node_modules/marked/src/Tokenizer.js +var require_Tokenizer = __commonJS({ + "node_modules/marked/src/Tokenizer.js"(exports2, module2) { + var { defaults: defaults2 } = require_defaults(); + var { + rtrim, + splitCells, + escape, + findClosingBracket + } = require_helpers(); + function outputLink(cap, link, raw) { + const href = link.href; + const title = link.title ? escape(link.title) : null; + const text = cap[1].replace(/\\([\[\]])/g, "$1"); + if (cap[0].charAt(0) !== "!") { + return { + type: "link", + raw, + href, + title, + text + }; + } else { + return { + type: "image", + raw, + href, + title, + text: escape(text) + }; + } + } + function indentCodeCompensation(raw, text) { + const matchIndentToCode = raw.match(/^(\s+)(?:```)/); + if (matchIndentToCode === null) { + return text; + } + const indentToCode = matchIndentToCode[1]; + return text.split("\n").map((node) => { + const matchIndentInNode = node.match(/^\s+/); + if (matchIndentInNode === null) { + return node; + } + const [indentInNode] = matchIndentInNode; + if (indentInNode.length >= indentToCode.length) { + return node.slice(indentToCode.length); + } + return node; + }).join("\n"); + } + module2.exports = class Tokenizer { + constructor(options) { + this.options = options || defaults2; + } + space(src) { + const cap = this.rules.block.newline.exec(src); + if (cap) { + if (cap[0].length > 1) { + return { + type: "space", + raw: cap[0] + }; + } + return { raw: "\n" }; + } + } + code(src) { + const cap = this.rules.block.code.exec(src); + if (cap) { + const text = cap[0].replace(/^ {1,4}/gm, ""); + return { + type: "code", + raw: cap[0], + codeBlockStyle: "indented", + text: !this.options.pedantic ? rtrim(text, "\n") : text + }; + } + } + fences(src) { + const cap = this.rules.block.fences.exec(src); + if (cap) { + const raw = cap[0]; + const text = indentCodeCompensation(raw, cap[3] || ""); + return { + type: "code", + raw, + lang: cap[2] ? cap[2].trim() : cap[2], + text + }; + } + } + heading(src) { + const cap = this.rules.block.heading.exec(src); + if (cap) { + let text = cap[2].trim(); + if (/#$/.test(text)) { + const trimmed = rtrim(text, "#"); + if (this.options.pedantic) { + text = trimmed.trim(); + } else if (!trimmed || / $/.test(trimmed)) { + text = trimmed.trim(); + } + } + return { + type: "heading", + raw: cap[0], + depth: cap[1].length, + text + }; + } + } + nptable(src) { + const cap = this.rules.block.nptable.exec(src); + if (cap) { + const item = { + type: "table", + header: splitCells(cap[1].replace(/^ *| *\| *$/g, "")), + align: cap[2].replace(/^ *|\| *$/g, "").split(/ *\| */), + cells: cap[3] ? cap[3].replace(/\n$/, "").split("\n") : [], + raw: cap[0] + }; + if (item.header.length === item.align.length) { + let l = item.align.length; + let i; + for (i = 0; i < l; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = "right"; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = "center"; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = "left"; + } else { + item.align[i] = null; + } + } + l = item.cells.length; + for (i = 0; i < l; i++) { + item.cells[i] = splitCells(item.cells[i], item.header.length); + } + return item; + } + } + } + hr(src) { + const cap = this.rules.block.hr.exec(src); + if (cap) { + return { + type: "hr", + raw: cap[0] + }; + } + } + blockquote(src) { + const cap = this.rules.block.blockquote.exec(src); + if (cap) { + const text = cap[0].replace(/^ *> ?/gm, ""); + return { + type: "blockquote", + raw: cap[0], + text + }; + } + } + list(src) { + const cap = this.rules.block.list.exec(src); + if (cap) { + let raw = cap[0]; + const bull = cap[2]; + const isordered = bull.length > 1; + const list2 = { + type: "list", + raw, + ordered: isordered, + start: isordered ? +bull.slice(0, -1) : "", + loose: false, + items: [] + }; + const itemMatch = cap[0].match(this.rules.block.item); + let next = false, item, space, bcurr, bnext, addBack, loose, istask, ischecked, endMatch; + let l = itemMatch.length; + bcurr = this.rules.block.listItemStart.exec(itemMatch[0]); + for (let i = 0; i < l; i++) { + item = itemMatch[i]; + raw = item; + if (!this.options.pedantic) { + endMatch = item.match(new RegExp("\\n\\s*\\n {0," + (bcurr[0].length - 1) + "}\\S")); + if (endMatch) { + addBack = item.length - endMatch.index + itemMatch.slice(i + 1).join("\n").length; + list2.raw = list2.raw.substring(0, list2.raw.length - addBack); + item = item.substring(0, endMatch.index); + raw = item; + l = i + 1; + } + } + if (i !== l - 1) { + bnext = this.rules.block.listItemStart.exec(itemMatch[i + 1]); + if (!this.options.pedantic ? bnext[1].length >= bcurr[0].length || bnext[1].length > 3 : bnext[1].length > bcurr[1].length) { + itemMatch.splice(i, 2, itemMatch[i] + (!this.options.pedantic && bnext[1].length < bcurr[0].length && !itemMatch[i].match(/\n$/) ? "" : "\n") + itemMatch[i + 1]); + i--; + l--; + continue; + } else if (!this.options.pedantic || this.options.smartLists ? bnext[2][bnext[2].length - 1] !== bull[bull.length - 1] : isordered === (bnext[2].length === 1)) { + addBack = itemMatch.slice(i + 1).join("\n").length; + list2.raw = list2.raw.substring(0, list2.raw.length - addBack); + i = l - 1; + } + bcurr = bnext; + } + space = item.length; + item = item.replace(/^ *([*+-]|\d+[.)]) ?/, ""); + if (~item.indexOf("\n ")) { + space -= item.length; + item = !this.options.pedantic ? item.replace(new RegExp("^ {1," + space + "}", "gm"), "") : item.replace(/^ {1,4}/gm, ""); + } + item = rtrim(item, "\n"); + if (i !== l - 1) { + raw = raw + "\n"; + } + loose = next || /\n\n(?!\s*$)/.test(raw); + if (i !== l - 1) { + next = raw.slice(-2) === "\n\n"; + if (!loose) + loose = next; + } + if (loose) { + list2.loose = true; + } + if (this.options.gfm) { + istask = /^\[[ xX]\] /.test(item); + ischecked = void 0; + if (istask) { + ischecked = item[1] !== " "; + item = item.replace(/^\[[ xX]\] +/, ""); + } + } + list2.items.push({ + type: "list_item", + raw, + task: istask, + checked: ischecked, + loose, + text: item + }); + } + return list2; + } + } + html(src) { + const cap = this.rules.block.html.exec(src); + if (cap) { + return { + type: this.options.sanitize ? "paragraph" : "html", + raw: cap[0], + pre: !this.options.sanitizer && (cap[1] === "pre" || cap[1] === "script" || cap[1] === "style"), + text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0] + }; + } + } + def(src) { + const cap = this.rules.block.def.exec(src); + if (cap) { + if (cap[3]) + cap[3] = cap[3].substring(1, cap[3].length - 1); + const tag = cap[1].toLowerCase().replace(/\s+/g, " "); + return { + type: "def", + tag, + raw: cap[0], + href: cap[2], + title: cap[3] + }; + } + } + table(src) { + const cap = this.rules.block.table.exec(src); + if (cap) { + const item = { + type: "table", + header: splitCells(cap[1].replace(/^ *| *\| *$/g, "")), + align: cap[2].replace(/^ *|\| *$/g, "").split(/ *\| */), + cells: cap[3] ? cap[3].replace(/\n$/, "").split("\n") : [] + }; + if (item.header.length === item.align.length) { + item.raw = cap[0]; + let l = item.align.length; + let i; + for (i = 0; i < l; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = "right"; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = "center"; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = "left"; + } else { + item.align[i] = null; + } + } + l = item.cells.length; + for (i = 0; i < l; i++) { + item.cells[i] = splitCells(item.cells[i].replace(/^ *\| *| *\| *$/g, ""), item.header.length); + } + return item; + } + } + } + lheading(src) { + const cap = this.rules.block.lheading.exec(src); + if (cap) { + return { + type: "heading", + raw: cap[0], + depth: cap[2].charAt(0) === "=" ? 1 : 2, + text: cap[1] + }; + } + } + paragraph(src) { + const cap = this.rules.block.paragraph.exec(src); + if (cap) { + return { + type: "paragraph", + raw: cap[0], + text: cap[1].charAt(cap[1].length - 1) === "\n" ? cap[1].slice(0, -1) : cap[1] + }; + } + } + text(src) { + const cap = this.rules.block.text.exec(src); + if (cap) { + return { + type: "text", + raw: cap[0], + text: cap[0] + }; + } + } + escape(src) { + const cap = this.rules.inline.escape.exec(src); + if (cap) { + return { + type: "escape", + raw: cap[0], + text: escape(cap[1]) + }; + } + } + tag(src, inLink, inRawBlock) { + const cap = this.rules.inline.tag.exec(src); + if (cap) { + if (!inLink && /^
    /i.test(cap[0])) { + inLink = false; + } + if (!inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + inRawBlock = true; + } else if (inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + inRawBlock = false; + } + return { + type: this.options.sanitize ? "text" : "html", + raw: cap[0], + inLink, + inRawBlock, + text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0] + }; + } + } + link(src) { + const cap = this.rules.inline.link.exec(src); + if (cap) { + const trimmedUrl = cap[2].trim(); + if (!this.options.pedantic && /^$/.test(trimmedUrl)) { + return; + } + const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), "\\"); + if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) { + return; + } + } else { + const lastParenIndex = findClosingBracket(cap[2], "()"); + if (lastParenIndex > -1) { + const start = cap[0].indexOf("!") === 0 ? 5 : 4; + const linkLen = start + cap[1].length + lastParenIndex; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ""; + } + } + let href = cap[2]; + let title = ""; + if (this.options.pedantic) { + const link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href); + if (link) { + href = link[1]; + title = link[3]; + } + } else { + title = cap[3] ? cap[3].slice(1, -1) : ""; + } + href = href.trim(); + if (/^$/.test(trimmedUrl)) { + href = href.slice(1); + } else { + href = href.slice(1, -1); + } + } + return outputLink(cap, { + href: href ? href.replace(this.rules.inline._escapes, "$1") : href, + title: title ? title.replace(this.rules.inline._escapes, "$1") : title + }, cap[0]); + } + } + reflink(src, links2) { + let cap; + if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) { + let link = (cap[2] || cap[1]).replace(/\s+/g, " "); + link = links2[link.toLowerCase()]; + if (!link || !link.href) { + const text = cap[0].charAt(0); + return { + type: "text", + raw: text, + text + }; + } + return outputLink(cap, link, cap[0]); + } + } + emStrong(src, maskedSrc, prevChar = "") { + let match = this.rules.inline.emStrong.lDelim.exec(src); + if (!match) + return; + if (match[3] && prevChar.match(/[\p{L}\p{N}]/u)) + return; + const nextChar = match[1] || match[2] || ""; + if (!nextChar || nextChar && (prevChar === "" || this.rules.inline.punctuation.exec(prevChar))) { + const lLength = match[0].length - 1; + let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0; + const endReg = match[0][0] === "*" ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd; + endReg.lastIndex = 0; + maskedSrc = maskedSrc.slice(-1 * src.length + lLength); + while ((match = endReg.exec(maskedSrc)) != null) { + rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6]; + if (!rDelim) + continue; + rLength = rDelim.length; + if (match[3] || match[4]) { + delimTotal += rLength; + continue; + } else if (match[5] || match[6]) { + if (lLength % 3 && !((lLength + rLength) % 3)) { + midDelimTotal += rLength; + continue; + } + } + delimTotal -= rLength; + if (delimTotal > 0) + continue; + rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); + if (Math.min(lLength, rLength) % 2) { + return { + type: "em", + raw: src.slice(0, lLength + match.index + rLength + 1), + text: src.slice(1, lLength + match.index + rLength) + }; + } + return { + type: "strong", + raw: src.slice(0, lLength + match.index + rLength + 1), + text: src.slice(2, lLength + match.index + rLength - 1) + }; + } + } + } + codespan(src) { + const cap = this.rules.inline.code.exec(src); + if (cap) { + let text = cap[2].replace(/\n/g, " "); + const hasNonSpaceChars = /[^ ]/.test(text); + const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text); + if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) { + text = text.substring(1, text.length - 1); + } + text = escape(text, true); + return { + type: "codespan", + raw: cap[0], + text + }; + } + } + br(src) { + const cap = this.rules.inline.br.exec(src); + if (cap) { + return { + type: "br", + raw: cap[0] + }; + } + } + del(src) { + const cap = this.rules.inline.del.exec(src); + if (cap) { + return { + type: "del", + raw: cap[0], + text: cap[2] + }; + } + } + autolink(src, mangle) { + const cap = this.rules.inline.autolink.exec(src); + if (cap) { + let text, href; + if (cap[2] === "@") { + text = escape(this.options.mangle ? mangle(cap[1]) : cap[1]); + href = "mailto:" + text; + } else { + text = escape(cap[1]); + href = text; + } + return { + type: "link", + raw: cap[0], + text, + href, + tokens: [ + { + type: "text", + raw: text, + text + } + ] + }; + } + } + url(src, mangle) { + let cap; + if (cap = this.rules.inline.url.exec(src)) { + let text, href; + if (cap[2] === "@") { + text = escape(this.options.mangle ? mangle(cap[0]) : cap[0]); + href = "mailto:" + text; + } else { + let prevCapZero; + do { + prevCapZero = cap[0]; + cap[0] = this.rules.inline._backpedal.exec(cap[0])[0]; + } while (prevCapZero !== cap[0]); + text = escape(cap[0]); + if (cap[1] === "www.") { + href = "http://" + text; + } else { + href = text; + } + } + return { + type: "link", + raw: cap[0], + text, + href, + tokens: [ + { + type: "text", + raw: text, + text + } + ] + }; + } + } + inlineText(src, inRawBlock, smartypants) { + const cap = this.rules.inline.text.exec(src); + if (cap) { + let text; + if (inRawBlock) { + text = this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0]; + } else { + text = escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]); + } + return { + type: "text", + raw: cap[0], + text + }; + } + } + }; + } +}); + +// node_modules/marked/src/rules.js +var require_rules = __commonJS({ + "node_modules/marked/src/rules.js"(exports2, module2) { + var { + noopTest, + edit: edit2, + merge + } = require_helpers(); + var block = { + newline: /^(?: *(?:\n|$))+/, + code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/, + fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/, + hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, + heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/, + blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, + list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/, + html: "^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))", + def: /^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, + nptable: noopTest, + table: noopTest, + lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/, + _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/, + text: /^[^\n]+/ + }; + block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/; + block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/; + block.def = edit2(block.def).replace("label", block._label).replace("title", block._title).getRegex(); + block.bullet = /(?:[*+-]|\d{1,9}[.)])/; + block.item = /^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/; + block.item = edit2(block.item, "gm").replace(/bull/g, block.bullet).getRegex(); + block.listItemStart = edit2(/^( *)(bull) */).replace("bull", block.bullet).getRegex(); + block.list = edit2(block.list).replace(/bull/g, block.bullet).replace("hr", "\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def", "\\n+(?=" + block.def.source + ")").getRegex(); + block._tag = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul"; + block._comment = /|$)/; + block.html = edit2(block.html, "i").replace("comment", block._comment).replace("tag", block._tag).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(); + block.paragraph = edit2(block._paragraph).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("|lheading", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex(); + block.blockquote = edit2(block.blockquote).replace("paragraph", block.paragraph).getRegex(); + block.normal = merge({}, block); + block.gfm = merge({}, block.normal, { + nptable: "^ *([^|\\n ].*\\|.*)\\n {0,3}([-:]+ *\\|[-| :]*)(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)", + table: "^ *\\|(.+)\\n {0,3}\\|?( *[-:]+[-| :]*)(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)" + }); + block.gfm.nptable = edit2(block.gfm.nptable).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("blockquote", " {0,3}>").replace("code", " {4}[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex(); + block.gfm.table = edit2(block.gfm.table).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("blockquote", " {0,3}>").replace("code", " {4}[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex(); + block.pedantic = merge({}, block.normal, { + html: edit2(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", block._comment).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: noopTest, + paragraph: edit2(block.normal._paragraph).replace("hr", block.hr).replace("heading", " *#{1,6} *[^\n]").replace("lheading", block.lheading).replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").getRegex() + }); + var inline = { + escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, + autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, + url: noopTest, + tag: "^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^", + link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/, + reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/, + nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/, + reflinkSearch: "reflink|nolink(?!\\()", + emStrong: { + lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/, + rDelimAst: /\_\_[^_*]*?\*[^_*]*?\_\_|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/, + rDelimUnd: /\*\*[^_*]*?\_[^_*]*?\*\*|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ + }, + code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, + br: /^( {2,}|\\)\n(?!\s*$)/, + del: noopTest, + text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~"; + inline.punctuation = edit2(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex(); + inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g; + inline.escapedEmSt = /\\\*|\\_/g; + inline._comment = edit2(block._comment).replace("(?:-->|$)", "-->").getRegex(); + inline.emStrong.lDelim = edit2(inline.emStrong.lDelim).replace(/punct/g, inline._punctuation).getRegex(); + inline.emStrong.rDelimAst = edit2(inline.emStrong.rDelimAst, "g").replace(/punct/g, inline._punctuation).getRegex(); + inline.emStrong.rDelimUnd = edit2(inline.emStrong.rDelimUnd, "g").replace(/punct/g, inline._punctuation).getRegex(); + inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g; + inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; + inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/; + inline.autolink = edit2(inline.autolink).replace("scheme", inline._scheme).replace("email", inline._email).getRegex(); + inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/; + inline.tag = edit2(inline.tag).replace("comment", inline._comment).replace("attribute", inline._attribute).getRegex(); + inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/; + inline._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/; + inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/; + inline.link = edit2(inline.link).replace("label", inline._label).replace("href", inline._href).replace("title", inline._title).getRegex(); + inline.reflink = edit2(inline.reflink).replace("label", inline._label).getRegex(); + inline.reflinkSearch = edit2(inline.reflinkSearch, "g").replace("reflink", inline.reflink).replace("nolink", inline.nolink).getRegex(); + inline.normal = merge({}, inline); + inline.pedantic = merge({}, inline.normal, { + strong: { + start: /^__|\*\*/, + middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + endAst: /\*\*(?!\*)/g, + endUnd: /__(?!_)/g + }, + em: { + start: /^_|\*/, + middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/, + endAst: /\*(?!\*)/g, + endUnd: /_(?!_)/g + }, + link: edit2(/^!?\[(label)\]\((.*?)\)/).replace("label", inline._label).getRegex(), + reflink: edit2(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", inline._label).getRegex() + }); + inline.gfm = merge({}, inline.normal, { + escape: edit2(inline.escape).replace("])", "~|])").getRegex(), + _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/, + url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, + _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\ 0.5) { + ch = "x" + ch.toString(16); + } + out += "&#" + ch + ";"; + } + return out; + } + module2.exports = class Lexer { + constructor(options) { + this.tokens = []; + this.tokens.links = Object.create(null); + this.options = options || defaults2; + this.options.tokenizer = this.options.tokenizer || new Tokenizer(); + this.tokenizer = this.options.tokenizer; + this.tokenizer.options = this.options; + const rules = { + block: block.normal, + inline: inline.normal + }; + if (this.options.pedantic) { + rules.block = block.pedantic; + rules.inline = inline.pedantic; + } else if (this.options.gfm) { + rules.block = block.gfm; + if (this.options.breaks) { + rules.inline = inline.breaks; + } else { + rules.inline = inline.gfm; + } + } + this.tokenizer.rules = rules; + } + static get rules() { + return { + block, + inline + }; + } + static lex(src, options) { + const lexer = new Lexer(options); + return lexer.lex(src); + } + static lexInline(src, options) { + const lexer = new Lexer(options); + return lexer.inlineTokens(src); + } + lex(src) { + src = src.replace(/\r\n|\r/g, "\n").replace(/\t/g, " "); + this.blockTokens(src, this.tokens, true); + this.inline(this.tokens); + return this.tokens; + } + blockTokens(src, tokens = [], top = true) { + if (this.options.pedantic) { + src = src.replace(/^ +$/gm, ""); + } + let token, i, l, lastToken, cutSrc, lastParagraphClipped; + while (src) { + if (this.options.extensions && this.options.extensions.block && this.options.extensions.block.some((extTokenizer) => { + if (token = extTokenizer.call(this, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + if (token = this.tokenizer.space(src)) { + src = src.substring(token.raw.length); + if (token.type) { + tokens.push(token); + } + continue; + } + if (token = this.tokenizer.code(src)) { + src = src.substring(token.raw.length); + lastToken = tokens[tokens.length - 1]; + if (lastToken && lastToken.type === "paragraph") { + lastToken.raw += "\n" + token.raw; + lastToken.text += "\n" + token.text; + } else { + tokens.push(token); + } + continue; + } + if (token = this.tokenizer.fences(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (token = this.tokenizer.heading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (token = this.tokenizer.nptable(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (token = this.tokenizer.hr(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (token = this.tokenizer.blockquote(src)) { + src = src.substring(token.raw.length); + token.tokens = this.blockTokens(token.text, [], top); + tokens.push(token); + continue; + } + if (token = this.tokenizer.list(src)) { + src = src.substring(token.raw.length); + l = token.items.length; + for (i = 0; i < l; i++) { + token.items[i].tokens = this.blockTokens(token.items[i].text, [], false); + } + tokens.push(token); + continue; + } + if (token = this.tokenizer.html(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (top && (token = this.tokenizer.def(src))) { + src = src.substring(token.raw.length); + if (!this.tokens.links[token.tag]) { + this.tokens.links[token.tag] = { + href: token.href, + title: token.title + }; + } + continue; + } + if (token = this.tokenizer.table(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (token = this.tokenizer.lheading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + cutSrc = src; + if (this.options.extensions && this.options.extensions.startBlock) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startBlock.forEach(function(getStartIndex) { + tempStart = getStartIndex.call(this, tempSrc); + if (typeof tempStart === "number" && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (top && (token = this.tokenizer.paragraph(cutSrc))) { + lastToken = tokens[tokens.length - 1]; + if (lastParagraphClipped && lastToken.type === "paragraph") { + lastToken.raw += "\n" + token.raw; + lastToken.text += "\n" + token.text; + } else { + tokens.push(token); + } + lastParagraphClipped = cutSrc.length !== src.length; + src = src.substring(token.raw.length); + continue; + } + if (token = this.tokenizer.text(src)) { + src = src.substring(token.raw.length); + lastToken = tokens[tokens.length - 1]; + if (lastToken && lastToken.type === "text") { + lastToken.raw += "\n" + token.raw; + lastToken.text += "\n" + token.text; + } else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = "Infinite loop on byte: " + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } else { + throw new Error(errMsg); + } + } + } + return tokens; + } + inline(tokens) { + let i, j, k, l2, row, token; + const l = tokens.length; + for (i = 0; i < l; i++) { + token = tokens[i]; + switch (token.type) { + case "paragraph": + case "text": + case "heading": { + token.tokens = []; + this.inlineTokens(token.text, token.tokens); + break; + } + case "table": { + token.tokens = { + header: [], + cells: [] + }; + l2 = token.header.length; + for (j = 0; j < l2; j++) { + token.tokens.header[j] = []; + this.inlineTokens(token.header[j], token.tokens.header[j]); + } + l2 = token.cells.length; + for (j = 0; j < l2; j++) { + row = token.cells[j]; + token.tokens.cells[j] = []; + for (k = 0; k < row.length; k++) { + token.tokens.cells[j][k] = []; + this.inlineTokens(row[k], token.tokens.cells[j][k]); + } + } + break; + } + case "blockquote": { + this.inline(token.tokens); + break; + } + case "list": { + l2 = token.items.length; + for (j = 0; j < l2; j++) { + this.inline(token.items[j].tokens); + } + break; + } + default: { + } + } + } + return tokens; + } + inlineTokens(src, tokens = [], inLink = false, inRawBlock = false) { + let token, lastToken, cutSrc; + let maskedSrc = src; + let match; + let keepPrevChar, prevChar; + if (this.tokens.links) { + const links2 = Object.keys(this.tokens.links); + if (links2.length > 0) { + while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) { + if (links2.includes(match[0].slice(match[0].lastIndexOf("[") + 1, -1))) { + maskedSrc = maskedSrc.slice(0, match.index) + "[" + repeatString("a", match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex); + } + } + } + } + while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + "[" + repeatString("a", match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + } + while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + "++" + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex); + } + while (src) { + if (!keepPrevChar) { + prevChar = ""; + } + keepPrevChar = false; + if (this.options.extensions && this.options.extensions.inline && this.options.extensions.inline.some((extTokenizer) => { + if (token = extTokenizer.call(this, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + if (token = this.tokenizer.escape(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (token = this.tokenizer.tag(src, inLink, inRawBlock)) { + src = src.substring(token.raw.length); + inLink = token.inLink; + inRawBlock = token.inRawBlock; + lastToken = tokens[tokens.length - 1]; + if (lastToken && token.type === "text" && lastToken.type === "text") { + lastToken.raw += token.raw; + lastToken.text += token.text; + } else { + tokens.push(token); + } + continue; + } + if (token = this.tokenizer.link(src)) { + src = src.substring(token.raw.length); + if (token.type === "link") { + token.tokens = this.inlineTokens(token.text, [], true, inRawBlock); + } + tokens.push(token); + continue; + } + if (token = this.tokenizer.reflink(src, this.tokens.links)) { + src = src.substring(token.raw.length); + lastToken = tokens[tokens.length - 1]; + if (token.type === "link") { + token.tokens = this.inlineTokens(token.text, [], true, inRawBlock); + tokens.push(token); + } else if (lastToken && token.type === "text" && lastToken.type === "text") { + lastToken.raw += token.raw; + lastToken.text += token.text; + } else { + tokens.push(token); + } + continue; + } + if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) { + src = src.substring(token.raw.length); + token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock); + tokens.push(token); + continue; + } + if (token = this.tokenizer.codespan(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (token = this.tokenizer.br(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (token = this.tokenizer.del(src)) { + src = src.substring(token.raw.length); + token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock); + tokens.push(token); + continue; + } + if (token = this.tokenizer.autolink(src, mangle)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + if (!inLink && (token = this.tokenizer.url(src, mangle))) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + cutSrc = src; + if (this.options.extensions && this.options.extensions.startInline) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startInline.forEach(function(getStartIndex) { + tempStart = getStartIndex.call(this, tempSrc); + if (typeof tempStart === "number" && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (token = this.tokenizer.inlineText(cutSrc, inRawBlock, smartypants)) { + src = src.substring(token.raw.length); + if (token.raw.slice(-1) !== "_") { + prevChar = token.raw.slice(-1); + } + keepPrevChar = true; + lastToken = tokens[tokens.length - 1]; + if (lastToken && lastToken.type === "text") { + lastToken.raw += token.raw; + lastToken.text += token.text; + } else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = "Infinite loop on byte: " + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } else { + throw new Error(errMsg); + } + } + } + return tokens; + } + }; + } +}); + +// node_modules/marked/src/Renderer.js +var require_Renderer = __commonJS({ + "node_modules/marked/src/Renderer.js"(exports2, module2) { + var { defaults: defaults2 } = require_defaults(); + var { + cleanUrl, + escape + } = require_helpers(); + module2.exports = class Renderer { + constructor(options) { + this.options = options || defaults2; + } + code(code, infostring, escaped) { + const lang = (infostring || "").match(/\S*/)[0]; + if (this.options.highlight) { + const out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + code = code.replace(/\n$/, "") + "\n"; + if (!lang) { + return "
    " + (escaped ? code : escape(code, true)) + "
    \n"; + } + return '
    ' + (escaped ? code : escape(code, true)) + "
    \n"; + } + blockquote(quote) { + return "
    \n" + quote + "
    \n"; + } + html(html) { + return html; + } + heading(text, level, raw, slugger) { + if (this.options.headerIds) { + return "' + text + "\n"; + } + return "" + text + "\n"; + } + hr() { + return this.options.xhtml ? "
    \n" : "
    \n"; + } + list(body, ordered, start) { + const type = ordered ? "ol" : "ul", startatt = ordered && start !== 1 ? ' start="' + start + '"' : ""; + return "<" + type + startatt + ">\n" + body + "\n"; + } + listitem(text) { + return "
  • " + text + "
  • \n"; + } + checkbox(checked) { + return " "; + } + paragraph(text) { + return "

    " + text + "

    \n"; + } + table(header, body) { + if (body) + body = "" + body + ""; + return "\n\n" + header + "\n" + body + "
    \n"; + } + tablerow(content) { + return "\n" + content + "\n"; + } + tablecell(content, flags) { + const type = flags.header ? "th" : "td"; + const tag = flags.align ? "<" + type + ' align="' + flags.align + '">' : "<" + type + ">"; + return tag + content + "\n"; + } + strong(text) { + return "" + text + ""; + } + em(text) { + return "" + text + ""; + } + codespan(text) { + return "" + text + ""; + } + br() { + return this.options.xhtml ? "
    " : "
    "; + } + del(text) { + return "" + text + ""; + } + link(href, title, text) { + href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + if (href === null) { + return text; + } + let out = '
    "; + return out; + } + image(href, title, text) { + href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + if (href === null) { + return text; + } + let out = '' + text + '" : ">"; + return out; + } + text(text) { + return text; + } + }; + } +}); + +// node_modules/marked/src/TextRenderer.js +var require_TextRenderer = __commonJS({ + "node_modules/marked/src/TextRenderer.js"(exports2, module2) { + module2.exports = class TextRenderer { + strong(text) { + return text; + } + em(text) { + return text; + } + codespan(text) { + return text; + } + del(text) { + return text; + } + html(text) { + return text; + } + text(text) { + return text; + } + link(href, title, text) { + return "" + text; + } + image(href, title, text) { + return "" + text; + } + br() { + return ""; + } + }; + } +}); + +// node_modules/marked/src/Slugger.js +var require_Slugger = __commonJS({ + "node_modules/marked/src/Slugger.js"(exports2, module2) { + module2.exports = class Slugger { + constructor() { + this.seen = {}; + } + serialize(value) { + return value.toLowerCase().trim().replace(/<[!\/a-z].*?>/ig, "").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, "").replace(/\s/g, "-"); + } + getNextSafeSlug(originalSlug, isDryRun) { + let slug = originalSlug; + let occurenceAccumulator = 0; + if (this.seen.hasOwnProperty(slug)) { + occurenceAccumulator = this.seen[originalSlug]; + do { + occurenceAccumulator++; + slug = originalSlug + "-" + occurenceAccumulator; + } while (this.seen.hasOwnProperty(slug)); + } + if (!isDryRun) { + this.seen[originalSlug] = occurenceAccumulator; + this.seen[slug] = 0; + } + return slug; + } + slug(value, options = {}) { + const slug = this.serialize(value); + return this.getNextSafeSlug(slug, options.dryrun); + } + }; + } +}); + +// node_modules/marked/src/Parser.js +var require_Parser = __commonJS({ + "node_modules/marked/src/Parser.js"(exports2, module2) { + var Renderer2 = require_Renderer(); + var TextRenderer = require_TextRenderer(); + var Slugger = require_Slugger(); + var { defaults: defaults2 } = require_defaults(); + var { + unescape: unescape2 + } = require_helpers(); + module2.exports = class Parser { + constructor(options) { + this.options = options || defaults2; + this.options.renderer = this.options.renderer || new Renderer2(); + this.renderer = this.options.renderer; + this.renderer.options = this.options; + this.textRenderer = new TextRenderer(); + this.slugger = new Slugger(); + } + static parse(tokens, options) { + const parser2 = new Parser(options); + return parser2.parse(tokens); + } + static parseInline(tokens, options) { + const parser2 = new Parser(options); + return parser2.parseInline(tokens); + } + parse(tokens, top = true) { + let out = "", i, j, k, l2, l3, row, cell, header, body, token, ordered, start, loose, itemBody, item, checked, task, checkbox, ret; + const l = tokens.length; + for (i = 0; i < l; i++) { + token = tokens[i]; + if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) { + ret = this.options.extensions.renderers[token.type].call(this, token); + if (ret !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "paragraph", "text"].includes(token.type)) { + out += ret || ""; + continue; + } + } + switch (token.type) { + case "space": { + continue; + } + case "hr": { + out += this.renderer.hr(); + continue; + } + case "heading": { + out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape2(this.parseInline(token.tokens, this.textRenderer)), this.slugger); + continue; + } + case "code": { + out += this.renderer.code(token.text, token.lang, token.escaped); + continue; + } + case "table": { + header = ""; + cell = ""; + l2 = token.header.length; + for (j = 0; j < l2; j++) { + cell += this.renderer.tablecell(this.parseInline(token.tokens.header[j]), { header: true, align: token.align[j] }); + } + header += this.renderer.tablerow(cell); + body = ""; + l2 = token.cells.length; + for (j = 0; j < l2; j++) { + row = token.tokens.cells[j]; + cell = ""; + l3 = row.length; + for (k = 0; k < l3; k++) { + cell += this.renderer.tablecell(this.parseInline(row[k]), { header: false, align: token.align[k] }); + } + body += this.renderer.tablerow(cell); + } + out += this.renderer.table(header, body); + continue; + } + case "blockquote": { + body = this.parse(token.tokens); + out += this.renderer.blockquote(body); + continue; + } + case "list": { + ordered = token.ordered; + start = token.start; + loose = token.loose; + l2 = token.items.length; + body = ""; + for (j = 0; j < l2; j++) { + item = token.items[j]; + checked = item.checked; + task = item.task; + itemBody = ""; + if (item.task) { + checkbox = this.renderer.checkbox(checked); + if (loose) { + if (item.tokens.length > 0 && item.tokens[0].type === "text") { + item.tokens[0].text = checkbox + " " + item.tokens[0].text; + if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === "text") { + item.tokens[0].tokens[0].text = checkbox + " " + item.tokens[0].tokens[0].text; + } + } else { + item.tokens.unshift({ + type: "text", + text: checkbox + }); + } + } else { + itemBody += checkbox; + } + } + itemBody += this.parse(item.tokens, loose); + body += this.renderer.listitem(itemBody, task, checked); + } + out += this.renderer.list(body, ordered, start); + continue; + } + case "html": { + out += this.renderer.html(token.text); + continue; + } + case "paragraph": { + out += this.renderer.paragraph(this.parseInline(token.tokens)); + continue; + } + case "text": { + body = token.tokens ? this.parseInline(token.tokens) : token.text; + while (i + 1 < l && tokens[i + 1].type === "text") { + token = tokens[++i]; + body += "\n" + (token.tokens ? this.parseInline(token.tokens) : token.text); + } + out += top ? this.renderer.paragraph(body) : body; + continue; + } + default: { + const errMsg = 'Token with "' + token.type + '" type was not found.'; + if (this.options.silent) { + console.error(errMsg); + return; + } else { + throw new Error(errMsg); + } + } + } + } + return out; + } + parseInline(tokens, renderer) { + renderer = renderer || this.renderer; + let out = "", i, token, ret; + const l = tokens.length; + for (i = 0; i < l; i++) { + token = tokens[i]; + if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) { + ret = this.options.extensions.renderers[token.type].call(this, token); + if (ret !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(token.type)) { + out += ret || ""; + continue; + } + } + switch (token.type) { + case "escape": { + out += renderer.text(token.text); + break; + } + case "html": { + out += renderer.html(token.text); + break; + } + case "link": { + out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer)); + break; + } + case "image": { + out += renderer.image(token.href, token.title, token.text); + break; + } + case "strong": { + out += renderer.strong(this.parseInline(token.tokens, renderer)); + break; + } + case "em": { + out += renderer.em(this.parseInline(token.tokens, renderer)); + break; + } + case "codespan": { + out += renderer.codespan(token.text); + break; + } + case "br": { + out += renderer.br(); + break; + } + case "del": { + out += renderer.del(this.parseInline(token.tokens, renderer)); + break; + } + case "text": { + out += renderer.text(token.text); + break; + } + default: { + const errMsg = 'Token with "' + token.type + '" type was not found.'; + if (this.options.silent) { + console.error(errMsg); + return; + } else { + throw new Error(errMsg); + } + } + } + } + return out; + } + }; + } +}); + +// node_modules/marked/src/marked.js +var require_marked = __commonJS({ + "node_modules/marked/src/marked.js"(exports2, module2) { + var Lexer = require_Lexer(); + var Parser = require_Parser(); + var Tokenizer = require_Tokenizer(); + var Renderer2 = require_Renderer(); + var TextRenderer = require_TextRenderer(); + var Slugger = require_Slugger(); + var { + merge, + checkSanitizeDeprecation, + escape + } = require_helpers(); + var { + getDefaults, + changeDefaults, + defaults: defaults2 + } = require_defaults(); + function marked2(src, opt, callback) { + if (typeof src === "undefined" || src === null) { + throw new Error("marked(): input parameter is undefined or null"); + } + if (typeof src !== "string") { + throw new Error("marked(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected"); + } + if (typeof opt === "function") { + callback = opt; + opt = null; + } + opt = merge({}, marked2.defaults, opt || {}); + checkSanitizeDeprecation(opt); + if (callback) { + const highlight = opt.highlight; + let tokens; + try { + tokens = Lexer.lex(src, opt); + } catch (e) { + return callback(e); + } + const done = function(err) { + let out; + if (!err) { + try { + if (opt.walkTokens) { + marked2.walkTokens(tokens, opt.walkTokens); + } + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + } + opt.highlight = highlight; + return err ? callback(err) : callback(null, out); + }; + if (!highlight || highlight.length < 3) { + return done(); + } + delete opt.highlight; + if (!tokens.length) + return done(); + let pending = 0; + marked2.walkTokens(tokens, function(token) { + if (token.type === "code") { + pending++; + setTimeout(() => { + highlight(token.text, token.lang, function(err, code) { + if (err) { + return done(err); + } + if (code != null && code !== token.text) { + token.text = code; + token.escaped = true; + } + pending--; + if (pending === 0) { + done(); + } + }); + }, 0); + } + }); + if (pending === 0) { + done(); + } + return; + } + try { + const tokens = Lexer.lex(src, opt); + if (opt.walkTokens) { + marked2.walkTokens(tokens, opt.walkTokens); + } + return Parser.parse(tokens, opt); + } catch (e) { + e.message += "\nPlease report this to https://github.com/markedjs/marked."; + if (opt.silent) { + return "

    An error occurred:

    " + escape(e.message + "", true) + "
    "; + } + throw e; + } + } + marked2.options = marked2.setOptions = function(opt) { + merge(marked2.defaults, opt); + changeDefaults(marked2.defaults); + return marked2; + }; + marked2.getDefaults = getDefaults; + marked2.defaults = defaults2; + marked2.use = function(...args) { + const opts = merge({}, ...args); + const extensions = marked2.defaults.extensions || { renderers: {}, childTokens: {} }; + let hasExtensions; + args.forEach((pack) => { + if (pack.extensions) { + hasExtensions = true; + pack.extensions.forEach((ext) => { + if (!ext.name) { + throw new Error("extension name required"); + } + if (ext.renderer) { + const prevRenderer = extensions.renderers ? extensions.renderers[ext.name] : null; + if (prevRenderer) { + extensions.renderers[ext.name] = function(...args2) { + let ret = ext.renderer.apply(this, args2); + if (ret === false) { + ret = prevRenderer.apply(this, args2); + } + return ret; + }; + } else { + extensions.renderers[ext.name] = ext.renderer; + } + } + if (ext.tokenizer) { + if (!ext.level || ext.level !== "block" && ext.level !== "inline") { + throw new Error("extension level must be 'block' or 'inline'"); + } + if (extensions[ext.level]) { + extensions[ext.level].unshift(ext.tokenizer); + } else { + extensions[ext.level] = [ext.tokenizer]; + } + if (ext.start) { + if (ext.level === "block") { + if (extensions.startBlock) { + extensions.startBlock.push(ext.start); + } else { + extensions.startBlock = [ext.start]; + } + } else if (ext.level === "inline") { + if (extensions.startInline) { + extensions.startInline.push(ext.start); + } else { + extensions.startInline = [ext.start]; + } + } + } + } + if (ext.childTokens) { + extensions.childTokens[ext.name] = ext.childTokens; + } + }); + } + if (pack.renderer) { + const renderer = marked2.defaults.renderer || new Renderer2(); + for (const prop in pack.renderer) { + const prevRenderer = renderer[prop]; + renderer[prop] = (...args2) => { + let ret = pack.renderer[prop].apply(renderer, args2); + if (ret === false) { + ret = prevRenderer.apply(renderer, args2); + } + return ret; + }; + } + opts.renderer = renderer; + } + if (pack.tokenizer) { + const tokenizer = marked2.defaults.tokenizer || new Tokenizer(); + for (const prop in pack.tokenizer) { + const prevTokenizer = tokenizer[prop]; + tokenizer[prop] = (...args2) => { + let ret = pack.tokenizer[prop].apply(tokenizer, args2); + if (ret === false) { + ret = prevTokenizer.apply(tokenizer, args2); + } + return ret; + }; + } + opts.tokenizer = tokenizer; + } + if (pack.walkTokens) { + const walkTokens = marked2.defaults.walkTokens; + opts.walkTokens = (token) => { + pack.walkTokens.call(this, token); + if (walkTokens) { + walkTokens(token); + } + }; + } + if (hasExtensions) { + opts.extensions = extensions; + } + marked2.setOptions(opts); + }); + }; + marked2.walkTokens = function(tokens, callback) { + for (const token of tokens) { + callback(token); + switch (token.type) { + case "table": { + for (const cell of token.tokens.header) { + marked2.walkTokens(cell, callback); + } + for (const row of token.tokens.cells) { + for (const cell of row) { + marked2.walkTokens(cell, callback); + } + } + break; + } + case "list": { + marked2.walkTokens(token.items, callback); + break; + } + default: { + if (marked2.defaults.extensions && marked2.defaults.extensions.childTokens && marked2.defaults.extensions.childTokens[token.type]) { + marked2.defaults.extensions.childTokens[token.type].forEach(function(childTokens) { + marked2.walkTokens(token[childTokens], callback); + }); + } else if (token.tokens) { + marked2.walkTokens(token.tokens, callback); + } + } + } + } + }; + marked2.parseInline = function(src, opt) { + if (typeof src === "undefined" || src === null) { + throw new Error("marked.parseInline(): input parameter is undefined or null"); + } + if (typeof src !== "string") { + throw new Error("marked.parseInline(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected"); + } + opt = merge({}, marked2.defaults, opt || {}); + checkSanitizeDeprecation(opt); + try { + const tokens = Lexer.lexInline(src, opt); + if (opt.walkTokens) { + marked2.walkTokens(tokens, opt.walkTokens); + } + return Parser.parseInline(tokens, opt); + } catch (e) { + e.message += "\nPlease report this to https://github.com/markedjs/marked."; + if (opt.silent) { + return "

    An error occurred:

    " + escape(e.message + "", true) + "
    "; + } + throw e; + } + }; + marked2.Parser = Parser; + marked2.parser = Parser.parse; + marked2.Renderer = Renderer2; + marked2.TextRenderer = TextRenderer; + marked2.Lexer = Lexer; + marked2.lexer = Lexer.lex; + marked2.Tokenizer = Tokenizer; + marked2.Slugger = Slugger; + marked2.parse = marked2; + module2.exports = marked2; + } +}); + +// node_modules/colors/lib/styles.js +var require_styles = __commonJS({ + "node_modules/colors/lib/styles.js"(exports2, module2) { + var styles3 = {}; + module2["exports"] = styles3; + var codes = { + reset: [0, 0], + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29], + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + gray: [90, 39], + grey: [90, 39], + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], + blackBG: [40, 49], + redBG: [41, 49], + greenBG: [42, 49], + yellowBG: [43, 49], + blueBG: [44, 49], + magentaBG: [45, 49], + cyanBG: [46, 49], + whiteBG: [47, 49] + }; + Object.keys(codes).forEach(function(key) { + var val = codes[key]; + var style2 = styles3[key] = []; + style2.open = "[" + val[0] + "m"; + style2.close = "[" + val[1] + "m"; + }); + } +}); + +// node_modules/colors/lib/system/supports-colors.js +var require_supports_colors = __commonJS({ + "node_modules/colors/lib/system/supports-colors.js"(exports2, module2) { + var argv = process.argv; + module2.exports = function() { + if (argv.indexOf("--no-color") !== -1 || argv.indexOf("--color=false") !== -1) { + return false; + } + if (argv.indexOf("--color") !== -1 || argv.indexOf("--color=true") !== -1 || argv.indexOf("--color=always") !== -1) { + return true; + } + if (process.stdout && !process.stdout.isTTY) { + return false; + } + if (process.platform === "win32") { + return true; + } + if ("COLORTERM" in process.env) { + return true; + } + if (process.env.TERM === "dumb") { + return false; + } + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { + return true; + } + return false; + }(); + } +}); + +// node_modules/colors/lib/custom/trap.js +var require_trap = __commonJS({ + "node_modules/colors/lib/custom/trap.js"(exports2, module2) { + module2["exports"] = function runTheTrap(text, options) { + var result = ""; + text = text || "Run the trap, drop the bass"; + text = text.split(""); + var trap = { + a: ["@", "\u0104", "\u023A", "\u0245", "\u0394", "\u039B", "\u0414"], + b: ["\xDF", "\u0181", "\u0243", "\u026E", "\u03B2", "\u0E3F"], + c: ["\xA9", "\u023B", "\u03FE"], + d: ["\xD0", "\u018A", "\u0500", "\u0501", "\u0502", "\u0503"], + e: ["\xCB", "\u0115", "\u018E", "\u0258", "\u03A3", "\u03BE", "\u04BC", "\u0A6C"], + f: ["\u04FA"], + g: ["\u0262"], + h: ["\u0126", "\u0195", "\u04A2", "\u04BA", "\u04C7", "\u050A"], + i: ["\u0F0F"], + j: ["\u0134"], + k: ["\u0138", "\u04A0", "\u04C3", "\u051E"], + l: ["\u0139"], + m: ["\u028D", "\u04CD", "\u04CE", "\u0520", "\u0521", "\u0D69"], + n: ["\xD1", "\u014B", "\u019D", "\u0376", "\u03A0", "\u048A"], + o: ["\xD8", "\xF5", "\xF8", "\u01FE", "\u0298", "\u047A", "\u05DD", "\u06DD", "\u0E4F"], + p: ["\u01F7", "\u048E"], + q: ["\u09CD"], + r: ["\xAE", "\u01A6", "\u0210", "\u024C", "\u0280", "\u042F"], + s: ["\xA7", "\u03DE", "\u03DF", "\u03E8"], + t: ["\u0141", "\u0166", "\u0373"], + u: ["\u01B1", "\u054D"], + v: ["\u05D8"], + w: ["\u0428", "\u0460", "\u047C", "\u0D70"], + x: ["\u04B2", "\u04FE", "\u04FC", "\u04FD"], + y: ["\xA5", "\u04B0", "\u04CB"], + z: ["\u01B5", "\u0240"] + }; + text.forEach(function(c) { + c = c.toLowerCase(); + var chars = trap[c] || [" "]; + var rand = Math.floor(Math.random() * chars.length); + if (typeof trap[c] !== "undefined") { + result += trap[c][rand]; + } else { + result += c; + } + }); + return result; + }; + } +}); + +// node_modules/colors/lib/custom/zalgo.js +var require_zalgo = __commonJS({ + "node_modules/colors/lib/custom/zalgo.js"(exports2, module2) { + module2["exports"] = function zalgo(text, options) { + text = text || " he is here "; + var soul = { + "up": [ + "\u030D", + "\u030E", + "\u0304", + "\u0305", + "\u033F", + "\u0311", + "\u0306", + "\u0310", + "\u0352", + "\u0357", + "\u0351", + "\u0307", + "\u0308", + "\u030A", + "\u0342", + "\u0313", + "\u0308", + "\u034A", + "\u034B", + "\u034C", + "\u0303", + "\u0302", + "\u030C", + "\u0350", + "\u0300", + "\u0301", + "\u030B", + "\u030F", + "\u0312", + "\u0313", + "\u0314", + "\u033D", + "\u0309", + "\u0363", + "\u0364", + "\u0365", + "\u0366", + "\u0367", + "\u0368", + "\u0369", + "\u036A", + "\u036B", + "\u036C", + "\u036D", + "\u036E", + "\u036F", + "\u033E", + "\u035B", + "\u0346", + "\u031A" + ], + "down": [ + "\u0316", + "\u0317", + "\u0318", + "\u0319", + "\u031C", + "\u031D", + "\u031E", + "\u031F", + "\u0320", + "\u0324", + "\u0325", + "\u0326", + "\u0329", + "\u032A", + "\u032B", + "\u032C", + "\u032D", + "\u032E", + "\u032F", + "\u0330", + "\u0331", + "\u0332", + "\u0333", + "\u0339", + "\u033A", + "\u033B", + "\u033C", + "\u0345", + "\u0347", + "\u0348", + "\u0349", + "\u034D", + "\u034E", + "\u0353", + "\u0354", + "\u0355", + "\u0356", + "\u0359", + "\u035A", + "\u0323" + ], + "mid": [ + "\u0315", + "\u031B", + "\u0300", + "\u0301", + "\u0358", + "\u0321", + "\u0322", + "\u0327", + "\u0328", + "\u0334", + "\u0335", + "\u0336", + "\u035C", + "\u035D", + "\u035E", + "\u035F", + "\u0360", + "\u0362", + "\u0338", + "\u0337", + "\u0361", + " \u0489" + ] + }, all = [].concat(soul.up, soul.down, soul.mid), zalgo2 = {}; + function randomNumber(range) { + var r = Math.floor(Math.random() * range); + return r; + } + function is_char(character) { + var bool = false; + all.filter(function(i) { + bool = i === character; + }); + return bool; + } + function heComes(text2, options2) { + var result = "", counts, l; + options2 = options2 || {}; + options2["up"] = options2["up"] || true; + options2["mid"] = options2["mid"] || true; + options2["down"] = options2["down"] || true; + options2["size"] = options2["size"] || "maxi"; + text2 = text2.split(""); + for (l in text2) { + if (is_char(l)) { + continue; + } + result = result + text2[l]; + counts = { "up": 0, "down": 0, "mid": 0 }; + switch (options2.size) { + case "mini": + counts.up = randomNumber(8); + counts.min = randomNumber(2); + counts.down = randomNumber(8); + break; + case "maxi": + counts.up = randomNumber(16) + 3; + counts.min = randomNumber(4) + 1; + counts.down = randomNumber(64) + 3; + break; + default: + counts.up = randomNumber(8) + 1; + counts.mid = randomNumber(6) / 2; + counts.down = randomNumber(8) + 1; + break; + } + var arr = ["up", "mid", "down"]; + for (var d in arr) { + var index = arr[d]; + for (var i = 0; i <= counts[index]; i++) { + if (options2[index]) { + result = result + soul[index][randomNumber(soul[index].length)]; + } + } + } + } + return result; + } + return heComes(text); + }; + } +}); + +// node_modules/colors/lib/maps/america.js +var require_america = __commonJS({ + "node_modules/colors/lib/maps/america.js"(exports2, module2) { + var colors = require_colors(); + module2["exports"] = function() { + return function(letter, i, exploded) { + if (letter === " ") + return letter; + switch (i % 3) { + case 0: + return colors.red(letter); + case 1: + return colors.white(letter); + case 2: + return colors.blue(letter); + } + }; + }(); + } +}); + +// node_modules/colors/lib/maps/zebra.js +var require_zebra = __commonJS({ + "node_modules/colors/lib/maps/zebra.js"(exports2, module2) { + var colors = require_colors(); + module2["exports"] = function(letter, i, exploded) { + return i % 2 === 0 ? letter : colors.inverse(letter); + }; + } +}); + +// node_modules/colors/lib/maps/rainbow.js +var require_rainbow = __commonJS({ + "node_modules/colors/lib/maps/rainbow.js"(exports2, module2) { + var colors = require_colors(); + module2["exports"] = function() { + var rainbowColors = ["red", "yellow", "green", "blue", "magenta"]; + return function(letter, i, exploded) { + if (letter === " ") { + return letter; + } else { + return colors[rainbowColors[i++ % rainbowColors.length]](letter); + } + }; + }(); + } +}); + +// node_modules/colors/lib/maps/random.js +var require_random = __commonJS({ + "node_modules/colors/lib/maps/random.js"(exports2, module2) { + var colors = require_colors(); + module2["exports"] = function() { + var available = ["underline", "inverse", "grey", "yellow", "red", "green", "blue", "white", "cyan", "magenta"]; + return function(letter, i, exploded) { + return letter === " " ? letter : colors[available[Math.round(Math.random() * (available.length - 1))]](letter); + }; + }(); + } +}); + +// node_modules/colors/lib/colors.js +var require_colors = __commonJS({ + "node_modules/colors/lib/colors.js"(exports2, module2) { + var colors = {}; + module2["exports"] = colors; + colors.themes = {}; + var ansiStyles = colors.styles = require_styles(); + var defineProps = Object.defineProperties; + colors.supportsColor = require_supports_colors(); + if (typeof colors.enabled === "undefined") { + colors.enabled = colors.supportsColor; + } + colors.stripColors = colors.strip = function(str) { + return ("" + str).replace(/\x1B\[\d+m/g, ""); + }; + var stylize = colors.stylize = function stylize2(str, style2) { + return ansiStyles[style2].open + str + ansiStyles[style2].close; + }; + var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; + var escapeStringRegexp = function(str) { + if (typeof str !== "string") { + throw new TypeError("Expected a string"); + } + return str.replace(matchOperatorsRe, "\\$&"); + }; + function build(_styles) { + var builder = function builder2() { + return applyStyle.apply(builder2, arguments); + }; + builder._styles = _styles; + builder.__proto__ = proto; + return builder; + } + var styles3 = function() { + var ret = {}; + ansiStyles.grey = ansiStyles.gray; + Object.keys(ansiStyles).forEach(function(key) { + ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), "g"); + ret[key] = { + get: function() { + return build(this._styles.concat(key)); + } + }; + }); + return ret; + }(); + var proto = defineProps(function colors2() { + }, styles3); + function applyStyle() { + var args = arguments; + var argsLen = args.length; + var str = argsLen !== 0 && String(arguments[0]); + if (argsLen > 1) { + for (var a = 1; a < argsLen; a++) { + str += " " + args[a]; + } + } + if (!colors.enabled || !str) { + return str; + } + var nestedStyles = this._styles; + var i = nestedStyles.length; + while (i--) { + var code = ansiStyles[nestedStyles[i]]; + str = code.open + str.replace(code.closeRe, code.open) + code.close; + } + return str; + } + function applyTheme(theme) { + for (var style2 in theme) { + (function(style3) { + colors[style3] = function(str) { + return colors[theme[style3]](str); + }; + })(style2); + } + } + colors.setTheme = function(theme) { + if (typeof theme === "string") { + try { + colors.themes[theme] = require(theme); + applyTheme(colors.themes[theme]); + return colors.themes[theme]; + } catch (err) { + console.log(err); + return err; + } + } else { + applyTheme(theme); + } + }; + function init() { + var ret = {}; + Object.keys(styles3).forEach(function(name2) { + ret[name2] = { + get: function() { + return build([name2]); + } + }; + }); + return ret; + } + var sequencer = function sequencer2(map2, str) { + var exploded = str.split(""), i = 0; + exploded = exploded.map(map2); + return exploded.join(""); + }; + colors.trap = require_trap(); + colors.zalgo = require_zalgo(); + colors.maps = {}; + colors.maps.america = require_america(); + colors.maps.zebra = require_zebra(); + colors.maps.rainbow = require_rainbow(); + colors.maps.random = require_random(); + for (var map in colors.maps) { + (function(map2) { + colors[map2] = function(str) { + return sequencer(colors.maps[map2], str); + }; + })(map); + } + defineProps(colors, init()); + } +}); + +// node_modules/colors/safe.js +var require_safe = __commonJS({ + "node_modules/colors/safe.js"(exports2, module2) { + var colors = require_colors(); + module2["exports"] = colors; + } +}); + +// node_modules/cli-table/lib/utils.js +var require_utils2 = __commonJS({ + "node_modules/cli-table/lib/utils.js"(exports2) { + exports2.repeat = function(str, times) { + return Array(times + 1).join(str); + }; + exports2.pad = function(str, len, pad2, dir) { + if (len + 1 >= str.length) + switch (dir) { + case "left": + str = Array(len + 1 - str.length).join(pad2) + str; + break; + case "both": + var right = Math.ceil((padlen = len - str.length) / 2); + var left = padlen - right; + str = Array(left + 1).join(pad2) + str + Array(right + 1).join(pad2); + break; + default: + str = str + Array(len + 1 - str.length).join(pad2); + } + ; + return str; + }; + exports2.truncate = function(str, length, chr) { + chr = chr || "\u2026"; + return str.length >= length ? str.substr(0, length - chr.length) + chr : str; + }; + function options(defaults2, opts) { + for (var p in opts) { + if (p === "__proto__" || p === "constructor" || p === "prototype") { + continue; + } + if (opts[p] && opts[p].constructor && opts[p].constructor === Object) { + defaults2[p] = defaults2[p] || {}; + options(defaults2[p], opts[p]); + } else { + defaults2[p] = opts[p]; + } + } + return defaults2; + } + exports2.options = options; + exports2.strlen = function(str) { + var code = /\u001b\[(?:\d*;){0,5}\d*m/g; + var stripped = ("" + str).replace(code, ""); + var split = stripped.split("\n"); + return split.reduce(function(memo, s) { + return s.length > memo ? s.length : memo; + }, 0); + }; + } +}); + +// node_modules/cli-table/lib/index.js +var require_lib7 = __commonJS({ + "node_modules/cli-table/lib/index.js"(exports2, module2) { + var colors = require_safe(); + var utils = require_utils2(); + var repeat2 = utils.repeat; + var truncate = utils.truncate; + var pad2 = utils.pad; + function Table2(options) { + this.options = utils.options({ + chars: { + "top": "\u2500", + "top-mid": "\u252C", + "top-left": "\u250C", + "top-right": "\u2510", + "bottom": "\u2500", + "bottom-mid": "\u2534", + "bottom-left": "\u2514", + "bottom-right": "\u2518", + "left": "\u2502", + "left-mid": "\u251C", + "mid": "\u2500", + "mid-mid": "\u253C", + "right": "\u2502", + "right-mid": "\u2524", + "middle": "\u2502" + }, + truncate: "\u2026", + colWidths: [], + colAligns: [], + style: { + "padding-left": 1, + "padding-right": 1, + head: ["red"], + border: ["grey"], + compact: false + }, + head: [] + }, options); + } + Table2.prototype.__proto__ = Array.prototype; + Table2.prototype.__defineGetter__("width", function() { + var str = this.toString().split("\n"); + if (str.length) + return str[0].length; + return 0; + }); + Table2.prototype.render; + Table2.prototype.toString = function() { + var ret = "", options = this.options, style2 = options.style, head = options.head, chars = options.chars, truncater = options.truncate, colWidths = options.colWidths || new Array(this.head.length), totalWidth = 0; + if (!head.length && !this.length) + return ""; + if (!colWidths.length) { + var all_rows = this.slice(0); + if (head.length) { + all_rows = all_rows.concat([head]); + } + ; + all_rows.forEach(function(cells) { + if (typeof cells === "object" && cells.length) { + extractColumnWidths(cells); + } else { + var header_cell = Object.keys(cells)[0], value_cell = cells[header_cell]; + colWidths[0] = Math.max(colWidths[0] || 0, get_width(header_cell) || 0); + if (typeof value_cell === "object" && value_cell.length) { + extractColumnWidths(value_cell, 1); + } else { + colWidths[1] = Math.max(colWidths[1] || 0, get_width(value_cell) || 0); + } + } + }); + } + ; + totalWidth = (colWidths.length == 1 ? colWidths[0] : colWidths.reduce(function(a, b) { + return a + b; + })) + colWidths.length + 1; + function extractColumnWidths(arr, offset) { + var offset = offset || 0; + arr.forEach(function(cell, i) { + colWidths[i + offset] = Math.max(colWidths[i + offset] || 0, get_width(cell) || 0); + }); + } + ; + function get_width(obj) { + return typeof obj == "object" && obj.width != void 0 ? obj.width : (typeof obj == "object" ? utils.strlen(obj.text) : utils.strlen(obj)) + (style2["padding-left"] || 0) + (style2["padding-right"] || 0); + } + function line(line2, left, right, intersection) { + var width = 0, line2 = left + repeat2(line2, totalWidth - 2) + right; + colWidths.forEach(function(w, i) { + if (i == colWidths.length - 1) + return; + width += w + 1; + line2 = line2.substr(0, width) + intersection + line2.substr(width + 1); + }); + return applyStyles(options.style.border, line2); + } + ; + function lineTop() { + var l2 = line(chars.top, chars["top-left"] || chars.top, chars["top-right"] || chars.top, chars["top-mid"]); + if (l2) + ret += l2 + "\n"; + } + ; + function generateRow(items, style3) { + var cells = [], max_height = 0; + if (!Array.isArray(items) && typeof items === "object") { + var key = Object.keys(items)[0], value = items[key], first_cell_head = true; + if (Array.isArray(value)) { + items = value; + items.unshift(key); + } else { + items = [key, value]; + } + } + items.forEach(function(item, i) { + var contents = item.toString().split("\n").reduce(function(memo, l2) { + memo.push(string2(l2, i)); + return memo; + }, []); + var height = contents.length; + if (height > max_height) { + max_height = height; + } + ; + cells.push({ contents, height }); + }); + var lines = new Array(max_height); + cells.forEach(function(cell, i) { + cell.contents.forEach(function(line2, j2) { + if (!lines[j2]) { + lines[j2] = []; + } + ; + if (style3 || first_cell_head && i === 0 && options.style.head) { + line2 = applyStyles(options.style.head, line2); + } + lines[j2].push(line2); + }); + for (var j = cell.height, l2 = max_height; j < l2; j++) { + if (!lines[j]) { + lines[j] = []; + } + ; + lines[j].push(string2("", i)); + } + }); + var ret2 = ""; + lines.forEach(function(line2, index) { + if (ret2.length > 0) { + ret2 += "\n" + applyStyles(options.style.border, chars.left); + } + ret2 += line2.join(applyStyles(options.style.border, chars.middle)) + applyStyles(options.style.border, chars.right); + }); + return applyStyles(options.style.border, chars.left) + ret2; + } + ; + function applyStyles(styles3, subject) { + if (!subject) + return ""; + styles3.forEach(function(style3) { + subject = colors[style3](subject); + }); + return subject; + } + ; + function string2(str, index) { + var str = String(typeof str == "object" && str.text ? str.text : str), length = utils.strlen(str), width = colWidths[index] - (style2["padding-left"] || 0) - (style2["padding-right"] || 0), align = options.colAligns[index] || "left"; + return repeat2(" ", style2["padding-left"] || 0) + (length == width ? str : length < width ? pad2(str, width + (str.length - length), " ", align == "left" ? "right" : align == "middle" ? "both" : "left") : truncater ? truncate(str, width, truncater) : str) + repeat2(" ", style2["padding-right"] || 0); + } + ; + if (head.length) { + lineTop(); + ret += generateRow(head, style2.head) + "\n"; + } + if (this.length) + this.forEach(function(cells, i) { + if (!head.length && i == 0) + lineTop(); + else { + if (!style2.compact || i < !!head.length ? 1 : cells.length == 0) { + var l2 = line(chars.mid, chars["left-mid"], chars["right-mid"], chars["mid-mid"]); + if (l2) + ret += l2 + "\n"; + } + } + if (cells.hasOwnProperty("length") && !cells.length) { + return; + } else { + ret += generateRow(cells) + "\n"; + } + ; + }); + var l = line(chars.bottom, chars["bottom-left"] || chars.bottom, chars["bottom-right"] || chars.bottom, chars["bottom-mid"]); + if (l) + ret += l; + else + ret = ret.slice(0, -1); + return ret; + }; + module2.exports = Table2; + module2.exports.version = "0.0.1"; + } +}); + +// node_modules/ansi-styles/index.js +var require_ansi_styles = __commonJS({ + "node_modules/ansi-styles/index.js"(exports2, module2) { + "use strict"; + var ANSI_BACKGROUND_OFFSET = 10; + var wrapAnsi256 = (offset = 0) => (code) => `[${38 + offset};5;${code}m`; + var wrapAnsi16m = (offset = 0) => (red, green, blue2) => `[${38 + offset};2;${red};${green};${blue2}m`; + function assembleStyles() { + const codes = new Map(); + const styles3 = { + modifier: { + reset: [0, 0], + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + overline: [53, 55], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + color: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + blackBright: [90, 39], + redBright: [91, 39], + greenBright: [92, 39], + yellowBright: [93, 39], + blueBright: [94, 39], + magentaBright: [95, 39], + cyanBright: [96, 39], + whiteBright: [97, 39] + }, + bgColor: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], + bgBlackBright: [100, 49], + bgRedBright: [101, 49], + bgGreenBright: [102, 49], + bgYellowBright: [103, 49], + bgBlueBright: [104, 49], + bgMagentaBright: [105, 49], + bgCyanBright: [106, 49], + bgWhiteBright: [107, 49] + } + }; + styles3.color.gray = styles3.color.blackBright; + styles3.bgColor.bgGray = styles3.bgColor.bgBlackBright; + styles3.color.grey = styles3.color.blackBright; + styles3.bgColor.bgGrey = styles3.bgColor.bgBlackBright; + for (const [groupName, group2] of Object.entries(styles3)) { + for (const [styleName, style2] of Object.entries(group2)) { + styles3[styleName] = { + open: `[${style2[0]}m`, + close: `[${style2[1]}m` + }; + group2[styleName] = styles3[styleName]; + codes.set(style2[0], style2[1]); + } + Object.defineProperty(styles3, groupName, { + value: group2, + enumerable: false + }); + } + Object.defineProperty(styles3, "codes", { + value: codes, + enumerable: false + }); + styles3.color.close = ""; + styles3.bgColor.close = ""; + styles3.color.ansi256 = wrapAnsi256(); + styles3.color.ansi16m = wrapAnsi16m(); + styles3.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET); + styles3.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET); + Object.defineProperties(styles3, { + rgbToAnsi256: { + value: (red, green, blue2) => { + if (red === green && green === blue2) { + if (red < 8) { + return 16; + } + if (red > 248) { + return 231; + } + return Math.round((red - 8) / 247 * 24) + 232; + } + return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue2 / 255 * 5); + }, + enumerable: false + }, + hexToRgb: { + value: (hex) => { + const matches = /(?[a-f\d]{6}|[a-f\d]{3})/i.exec(hex.toString(16)); + if (!matches) { + return [0, 0, 0]; + } + let { colorString } = matches.groups; + if (colorString.length === 3) { + colorString = colorString.split("").map((character) => character + character).join(""); + } + const integer2 = Number.parseInt(colorString, 16); + return [ + integer2 >> 16 & 255, + integer2 >> 8 & 255, + integer2 & 255 + ]; + }, + enumerable: false + }, + hexToAnsi256: { + value: (hex) => styles3.rgbToAnsi256(...styles3.hexToRgb(hex)), + enumerable: false + } + }); + return styles3; + } + Object.defineProperty(module2, "exports", { + enumerable: true, + get: assembleStyles + }); + } +}); + +// src/markdown/styles.ts +function gray(str) { + return `${import_ansi_styles.default.gray.open}${str}${import_ansi_styles.default.gray.close}`; +} +function magenta(str) { + return `${import_ansi_styles.default.magenta.open}${str}${import_ansi_styles.default.magenta.close}`; +} +function bold(str) { + return `${import_ansi_styles.default.bold.open}${str}${import_ansi_styles.default.bold.close}`; +} +function underline(str) { + return `${import_ansi_styles.default.underline.open}${str}${import_ansi_styles.default.underline.close}`; +} +function strikethrough(str) { + return `${import_ansi_styles.default.strikethrough.open}${str}${import_ansi_styles.default.strikethrough.close}`; +} +function italic(str) { + return `${import_ansi_styles.default.italic.open}${str}${import_ansi_styles.default.italic.close}`; +} +function yellow(str) { + return `${import_ansi_styles.default.yellow.open}${str}${import_ansi_styles.default.yellow.close}`; +} +function blue(str) { + return `${import_ansi_styles.default.blue.open}${str}${import_ansi_styles.default.blue.close}`; +} +var import_ansi_styles; +var init_styles = __esm({ + "src/markdown/styles.ts"() { + import_ansi_styles = __toModule(require_ansi_styles()); + } +}); + +// src/markdown/renderer.ts +function fixHardReturn(text, reflow) { + return reflow ? text.replace(HARD_RETURN, /\n/g) : text; +} +function sanitizeTab(tab, fallbackTab) { + if (typeof tab === "number") { + return new Array(tab + 1).join(" "); + } else if (typeof tab === "string" && isAllowedTabString(tab)) { + return tab; + } else { + return new Array(fallbackTab + 1).join(" "); + } +} +function isAllowedTabString(str) { + return TAB_ALLOWED_CHARACTERS.some(function(char) { + return str.match("^(" + char + ")+$"); + }); +} +function indentLines(indent, text) { + return text.replace(/(^|\n)(.+)/g, "$1" + indent + "$2"); +} +function indentify(indent, text) { + if (!text) + return text; + return indent + text.split("\n").join("\n" + indent); +} +function fixNestedLists(body, indent) { + let regex = new RegExp("(\\S(?: | )?)((?:" + indent + ")+)(" + POINT_REGEX + "(?:.*)+)$", "gm"); + return body.replace(regex, "$1\n" + indent + "$2$3"); +} +function toSpaces(str) { + return " ".repeat(str.length); +} +function bulletPointLine(indent, line) { + return isPointedLine(line, indent) ? line : toSpaces(BULLET_POINT) + line; +} +function bulletPointLines(lines, indent) { + let transform = bulletPointLine.bind(null, indent); + return lines.split("\n").filter(identity).map(transform).join("\n"); +} +function numberedLine(indent, line, num) { + return isPointedLine(line, indent) ? { + num: num + 1, + line: line.replace(BULLET_POINT, numberedPoint(num + 1)) + } : { + num, + line: toSpaces(numberedPoint(num)) + line + }; +} +function numberedLines(lines, indent) { + let transform = numberedLine.bind(null, indent); + let num = 0; + return lines.split("\n").filter(identity).map((line) => { + const numbered = transform(line, num); + num = numbered.num; + return numbered.line; + }).join("\n"); +} +function list(body, ordered, indent) { + body = body.trim(); + body = ordered ? numberedLines(body, indent) : bulletPointLines(body, indent); + return body; +} +function section(text) { + return text + "\n\n"; +} +function undoColon(str) { + return str.replace(COLON_REPLACER_REGEXP, ":"); +} +function generateTableRow(text, escape = null) { + if (!text) + return []; + escape = escape || identity; + let lines = escape(text).split("\n"); + let data = []; + lines.forEach(function(line) { + if (!line) + return; + let parsed = line.replace(TABLE_ROW_WRAP_REGEXP, "").split(TABLE_CELL_SPLIT); + data.push(parsed.splice(0, parsed.length - 1)); + }); + return data; +} +function escapeRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); +} +function unescapeEntities(html) { + return html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'"); +} +function identity(str) { + return str; +} +var import_cli_table, logger3, TABLE_CELL_SPLIT, TABLE_ROW_WRAP, TABLE_ROW_WRAP_REGEXP, COLON_REPLACER, COLON_REPLACER_REGEXP, TAB_ALLOWED_CHARACTERS, HARD_RETURN, defaultOptions, BULLET_POINT_REGEX, NUMBERED_POINT_REGEX, POINT_REGEX, isPointedLine, BULLET_POINT, numberedPoint, links, Renderer, renderer_default; +var init_renderer = __esm({ + "src/markdown/renderer.ts"() { + import_cli_table = __toModule(require_lib7()); + init_styles(); + logger3 = require_logger2()("markdown-renderer"); + TABLE_CELL_SPLIT = "^*||*^"; + TABLE_ROW_WRAP = "*|*|*|*"; + TABLE_ROW_WRAP_REGEXP = new RegExp(escapeRegExp(TABLE_ROW_WRAP), "g"); + COLON_REPLACER = "*#COLON|*"; + COLON_REPLACER_REGEXP = new RegExp(escapeRegExp(COLON_REPLACER), "g"); + TAB_ALLOWED_CHARACTERS = [" "]; + HARD_RETURN = "\r"; + defaultOptions = { + code: identity, + blockquote: identity, + html: gray, + heading: magenta, + firstHeading: magenta, + hr: identity, + listitem: identity, + list, + table: identity, + paragraph: identity, + strong: bold, + em: italic, + codespan: yellow, + del: strikethrough, + link: underline, + href: underline, + text: identity, + unescape: true, + emoji: false, + width: 80, + showSectionPrefix: true, + tab: 2, + tableOptions: {} + }; + BULLET_POINT_REGEX = "\\*"; + NUMBERED_POINT_REGEX = "\\d+\\."; + POINT_REGEX = "(?:" + [BULLET_POINT_REGEX, NUMBERED_POINT_REGEX].join("|") + ")"; + isPointedLine = function(line, indent) { + return line.match("^(?:" + indent + ")*" + POINT_REGEX); + }; + BULLET_POINT = "* "; + numberedPoint = function(n) { + return n + ". "; + }; + links = new Map(); + Renderer = class { + constructor(options = {}, highlightOptions = {}) { + this.options = options; + this.highlightOptions = highlightOptions; + this.o = Object.assign({}, defaultOptions, options); + this.tab = sanitizeTab(this.o.tab, defaultOptions.tab); + this.tableSettings = this.o.tableOptions; + this.unescape = this.o.unescape ? unescapeEntities : identity; + this.highlightOptions = highlightOptions || {}; + this.transform = this.compose(undoColon, this.unescape); + } + textLength(str) { + return str.replace(/\u001b\[(?:\d{1,3})(?:;\d{1,3})*m/g, "").length; + } + text(t) { + return this.o.text(t); + } + code(code, lang, _escaped) { + return "``` " + lang + "\n" + code + "\n```\n"; + } + blockquote(quote) { + return section(this.o.blockquote(indentify(this.tab, quote.trim()))); + } + html(html) { + return this.o.html(html); + } + heading(text, level, _raw) { + text = this.transform(text); + let prefix = this.o.showSectionPrefix ? new Array(level + 1).join("#") + " " : ""; + text = prefix + text; + return section(level === 1 ? this.o.firstHeading(text) : this.o.heading(text)); + } + hr() { + return `\u2500\u2500\u2500 +`; + } + list(body, ordered) { + body = this.o.list(body, ordered, this.tab); + return section(fixNestedLists(indentLines(this.tab, body), this.tab)); + } + listitem(text) { + let transform = this.compose(this.o.listitem, this.transform); + let isNested = text.indexOf("\n") !== -1; + if (isNested) + text = text.trim(); + return "\n" + BULLET_POINT + transform(text); + } + checkbox(checked) { + return "[" + (checked ? "X" : " ") + "] "; + } + paragraph(text) { + let transform = this.compose(this.o.paragraph, this.transform); + text = transform(text); + return section(text); + } + table(header, body) { + let table = new import_cli_table.default(Object.assign({}, { + head: generateTableRow(header)[0] + }, this.tableSettings)); + generateTableRow(body, this.transform).forEach(function(row) { + table.push(row); + }); + return section(this.o.table(table.toString())); + } + tablerow(content) { + return TABLE_ROW_WRAP + content + TABLE_ROW_WRAP + "\n"; + } + tablecell(content, _flags) { + return content + TABLE_CELL_SPLIT; + } + strong(text) { + return this.o.strong(text); + } + em(text) { + text = fixHardReturn(text, this.o.reflowText); + return this.o.em(text); + } + codespan(text) { + text = fixHardReturn(text, this.o.reflowText); + return this.o.codespan(text.replace(/:/g, COLON_REPLACER)); + } + br() { + return "\n"; + } + del(text) { + return this.o.del(text); + } + link(href, title, text) { + let prot; + if (this.options.sanitize) { + try { + prot = decodeURIComponent(unescape(href)).replace(/[^\w:]/g, "").toLowerCase(); + } catch (e) { + return ""; + } + if (prot.startsWith("javascript:")) { + return ""; + } + } + if (text && href && text != href) { + links.set(text, href); + } + if (text && text != href) + return blue(text); + let out = this.o.href(href); + return this.o.link(out); + } + image(href, title, text) { + if (typeof this.o.image === "function") { + return this.o.image(href, title, text); + } + let out = "![" + text; + if (title) + out += " \u2013 " + title; + return out + "](" + href + ")\n"; + } + compose(...funcs) { + return (...args) => { + for (let i = funcs.length; i-- > 0; ) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + } + static getLinks() { + let res = []; + for (let [text, href] of links.entries()) { + res.push(`${blue(text)}: ${href}`); + } + links.clear(); + return res; + } + }; + renderer_default = Renderer; + } +}); + +// src/util/string.ts +function rangeParts(text, range) { + let { start, end } = range; + let lines = text.split(/\r?\n/); + let before = ""; + let after = ""; + let len = lines.length; + for (let i = 0; i < len; i++) { + let curr = lines[i]; + if (i < start.line) { + before += curr + "\n"; + continue; + } + if (i > end.line) { + after += curr + (i == len - 1 ? "" : "\n"); + continue; + } + if (i == start.line) { + before += curr.slice(0, start.character); + } + if (i == end.line) { + after += curr.slice(end.character) + (i == len - 1 ? "" : "\n"); + } + } + return [before, after]; +} +function byteLength(str) { + return Buffer.byteLength(str); +} +function upperFirst(str) { + return str ? str[0].toUpperCase() + str.slice(1) : ""; +} +function byteIndex(content, index) { + let s = content.slice(0, index); + return Buffer.byteLength(s); +} +function characterIndex(content, byteIndex2) { + let buf = Buffer.from(content, "utf8"); + return buf.slice(0, byteIndex2).toString("utf8").length; +} +function byteSlice(content, start, end) { + let buf = Buffer.from(content, "utf8"); + return buf.slice(start, end).toString("utf8"); +} +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; +} +var init_string = __esm({ + "src/util/string.ts"() { + } +}); + +// src/util/ansiparse.ts +function parseAnsiHighlights(line, markdown = false) { + let items = ansiparse(line); + let highlights = []; + let newLabel = ""; + for (let item of items) { + if (!item.text) + continue; + let { foreground, background, bold: bold2, italic: italic2, underline: underline2 } = item; + let len = byteLength(newLabel); + if (foreground || background || bold2 || italic2 || underline2) { + let span = [len, len + byteLength(item.text)]; + let hlGroup = ""; + if (foreground && background) { + hlGroup = `CocList${upperFirst(foreground)}${upperFirst(background)}`; + } else if (foreground) { + if (markdown) { + if (foreground == "yellow") { + hlGroup = "CocMarkdownCode"; + } else if (foreground == "blue") { + hlGroup = "CocMarkdownLink"; + } else if (foreground == "magenta") { + hlGroup = "CocMarkdownHeader"; + } else { + hlGroup = `CocListFg${upperFirst(foreground)}`; + } + } else { + hlGroup = `CocListFg${upperFirst(foreground)}`; + } + } else if (background) { + hlGroup = `CocListBg${upperFirst(background)}`; + } else if (bold2) { + hlGroup = "CocBold"; + } else if (italic2) { + hlGroup = "CocItalic"; + } else if (underline2) { + hlGroup = "CocUnderline"; + } + highlights.push({ span, hlGroup }); + } + newLabel = newLabel + item.text; + } + return { line: newLabel, highlights }; +} +function ansiparse(str) { + let matchingControl = null; + let matchingData = null; + let matchingText = ""; + let ansiState = []; + let result = []; + let state = {}; + let eraseChar; + 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) { + result.pop(); + } else { + result[index].text = text.substr(0, text.length - 1); + } + } + }; + for (let i = 0; i < str.length; i++) { + if (matchingControl != null) { + if (matchingControl == "" && str[i] == "[") { + 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 { + matchingText += matchingControl + str[i]; + matchingControl = null; + } + continue; + } else if (matchingData != null) { + if (str[i] == ";") { + ansiState.push(matchingData); + matchingData = ""; + } else if (str[i] == "m" || str[i] == "K") { + ansiState.push(matchingData); + matchingData = null; + matchingText = ""; + 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 (styles2[ansiCode]) { + state[styles2[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] == "") { + matchingControl = str[i]; + } else if (str[i] == "\b") { + eraseChar(); + } else { + matchingText += str[i]; + } + } + if (matchingText) { + state.text = matchingText + (matchingControl ? matchingControl : ""); + result.push(state); + } + return result; +} +var foregroundColors, backgroundColors, styles2; +var init_ansiparse = __esm({ + "src/util/ansiparse.ts"() { + init_string(); + foregroundColors = { + 30: "black", + 31: "red", + 32: "green", + 33: "yellow", + 34: "blue", + 35: "magenta", + 36: "cyan", + 37: "white", + 90: "grey" + }; + backgroundColors = { + 40: "black", + 41: "red", + 42: "green", + 43: "yellow", + 44: "blue", + 45: "magenta", + 46: "cyan", + 47: "white" + }; + styles2 = { + 1: "bold", + 3: "italic", + 4: "underline" + }; + } +}); + +// node_modules/ansi-regex/index.js +var require_ansi_regex = __commonJS({ + "node_modules/ansi-regex/index.js"(exports2, module2) { + "use strict"; + module2.exports = ({ onlyFirst = false } = {}) => { + const pattern = [ + "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", + "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))" + ].join("|"); + return new RegExp(pattern, onlyFirst ? void 0 : "g"); + }; + } +}); + +// node_modules/strip-ansi/index.js +var require_strip_ansi = __commonJS({ + "node_modules/strip-ansi/index.js"(exports2, module2) { + "use strict"; + var ansiRegex = require_ansi_regex(); + module2.exports = (string2) => typeof string2 === "string" ? string2.replace(ansiRegex(), "") : string2; + } +}); + +// src/markdown/index.ts +function parseDocuments(docs, opts = {}) { + let lines = []; + let highlights = []; + let codes = []; + let idx = 0; + for (let doc of docs) { + let currline = lines.length; + let { content, filetype } = doc; + if (filetype == "markdown") { + let info = parseMarkdown(content, opts); + codes.push(...info.codes.map((o) => { + o.startLine = o.startLine + currline; + o.endLine = o.endLine + currline; + return o; + })); + highlights.push(...info.highlights.map((o) => { + o.lnum = o.lnum + currline; + return o; + })); + lines.push(...info.lines); + } else { + let parts = content.trim().split(/\r?\n/); + if (diagnosticFiletypes.includes(doc.filetype)) { + codes.push({ hlGroup: `Coc${filetype}Float`, startLine: currline, endLine: currline + parts.length }); + } else { + codes.push({ filetype: doc.filetype, startLine: currline, endLine: currline + parts.length }); + } + lines.push(...parts); + } + if (doc.active) { + let arr = getHighlightItems(content, currline, doc.active); + if (arr.length) + highlights.push(...arr); + } + if (idx != docs.length - 1) { + lines.push("\u2500"); + } + idx = idx + 1; + } + return { lines, highlights, codes }; +} +function getHighlightItems(content, currline, active) { + let res = []; + let [start, end] = active; + let lines = content.split(/\r?\n/); + let used = 0; + let inRange = false; + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + if (!inRange) { + if (used + line.length > start) { + inRange = true; + let colStart = byteLength(line.slice(0, start - used)); + if (used + line.length > end) { + let colEnd = byteLength(line.slice(0, end - used)); + inRange = false; + res.push({ colStart, colEnd, lnum: i + currline, hlGroup: "CocUnderline" }); + break; + } else { + let colEnd = byteLength(line); + res.push({ colStart, colEnd, lnum: i + currline, hlGroup: "CocUnderline" }); + } + } + } else { + if (used + line.length > end) { + let colEnd = byteLength(line.slice(0, end - used)); + res.push({ colStart: 0, colEnd, lnum: i + currline, hlGroup: "CocUnderline" }); + inRange = false; + break; + } else { + let colEnd = byteLength(line); + res.push({ colStart: 0, colEnd, lnum: i + currline, hlGroup: "CocUnderline" }); + } + } + used = used + line.length + 1; + } + return res; +} +function parseMarkdown(content, opts) { + import_marked.default.setOptions({ + renderer: new renderer_default(), + gfm: true + }); + let lines = []; + let highlights = []; + let codes = []; + let currline = 0; + let inCodeBlock = false; + let filetype; + let startLnum = 0; + let parsed = (0, import_marked.default)(content); + let links2 = renderer_default.getLinks(); + if (links2.length) { + parsed = parsed + "\n\n" + links2.join("\n"); + } + parsed = parsed.replace(/\s*$/, ""); + let parsedLines = parsed.split(/\n/); + for (let i = 0; i < parsedLines.length; i++) { + let line = parsedLines[i]; + if (!line.length) { + let pre = lines[lines.length - 1]; + if (pre && pre.length) { + lines.push(line); + currline++; + } + continue; + } + if (opts.excludeImages && line.indexOf("![") !== -1) { + line = line.replace(/\s*!\[.*?\]\(.*?\)/g, ""); + if (!(0, import_strip_ansi.default)(line).trim().length) + continue; + } + if (/\s*```\s*([A-Za-z0-9_,]+)?$/.test(line)) { + if (!inCodeBlock) { + let pre = parsedLines[i - 1]; + if (pre && /^\s*```\s*/.test(pre)) { + lines.push(""); + currline++; + } + inCodeBlock = true; + filetype = line.replace(/^\s*```\s*/, ""); + if (filetype == "js") + filetype = "javascript"; + if (filetype == "ts") + filetype = "typescript"; + if (filetype == "bash") + filetype = "sh"; + startLnum = currline; + } else { + inCodeBlock = false; + codes.push({ + filetype, + startLine: startLnum, + endLine: currline + }); + } + continue; + } + if (inCodeBlock) { + lines.push(line); + currline++; + continue; + } + let res = parseAnsiHighlights(line, true); + if (res.highlights) { + for (let hi of res.highlights) { + let { hlGroup, span } = hi; + highlights.push({ + hlGroup, + lnum: currline, + colStart: span[0], + colEnd: span[1] + }); + } + } + lines.push(res.line); + currline++; + } + return { lines, highlights, codes }; +} +var import_marked, import_strip_ansi, diagnosticFiletypes, logger4; +var init_markdown = __esm({ + "src/markdown/index.ts"() { + import_marked = __toModule(require_marked()); + init_renderer(); + init_ansiparse(); + init_string(); + import_strip_ansi = __toModule(require_strip_ansi()); + diagnosticFiletypes = ["Error", "Warning", "Info", "Hint"]; + logger4 = require_logger2()("markdown-index"); + } +}); + +// src/util/mutex.ts +var Mutex; +var init_mutex = __esm({ + "src/util/mutex.ts"() { + Mutex = class { + constructor() { + this.tasks = []; + this.count = 1; + } + sched() { + if (this.count > 0 && this.tasks.length > 0) { + this.count--; + let next = this.tasks.shift(); + next(); + } + } + get busy() { + return this.count == 0; + } + acquire() { + return new Promise((res) => { + let task = () => { + let released = false; + res(() => { + if (!released) { + released = true; + this.count++; + this.sched(); + } + }); + }; + this.tasks.push(task); + process.nextTick(this.sched.bind(this)); + }); + } + use(f) { + return this.acquire().then((release) => f().then((res) => { + release(); + return res; + }).catch((err) => { + release(); + throw err; + })); + } + }; + } +}); + +// src/model/floatFactory.ts +var import_debounce2, import_vscode_languageserver_protocol3, isVim, logger5, FloatFactory; +var init_floatFactory = __esm({ + "src/model/floatFactory.ts"() { + import_debounce2 = __toModule(require_debounce()); + import_vscode_languageserver_protocol3 = __toModule(require_main2()); + init_events(); + init_markdown(); + init_util(); + init_mutex(); + init_object(); + isVim = process.env.VIM_NODE_RPC == "1"; + logger5 = require_logger2()("model-float"); + FloatFactory = class { + constructor(nvim) { + this.nvim = nvim; + this.winid = 0; + this._bufnr = 0; + this.mutex = new Mutex(); + this.disposables = []; + this.onCursorMoved = (0, import_debounce2.default)(this._onCursorMoved.bind(this), 100); + } + bindEvents(autoHide, alignTop) { + let eventNames = ["InsertLeave", "InsertEnter", "BufEnter"]; + for (let ev of eventNames) { + events_default.on(ev, (bufnr) => { + if (bufnr == this._bufnr) + return; + this.close(); + }, null, this.disposables); + } + events_default.on("MenuPopupChanged", () => { + if (events_default.pumAlignTop == alignTop) { + this.close(); + } + }, null, this.disposables); + this.disposables.push(import_vscode_languageserver_protocol3.Disposable.create(() => { + this.onCursorMoved.clear(); + })); + events_default.on("CursorMoved", this.onCursorMoved.bind(this, autoHide), this, this.disposables); + events_default.on("CursorMovedI", this.onCursorMoved.bind(this, autoHide), this, this.disposables); + } + unbind() { + if (this.disposables.length) { + disposeAll(this.disposables); + this.disposables = []; + } + } + _onCursorMoved(autoHide, bufnr, cursor) { + if (bufnr == this._bufnr) + return; + if (bufnr == this.targetBufnr && equals(cursor, this.cursor)) { + return; + } + if (autoHide || bufnr != this.targetBufnr || !events_default.insertMode) { + this.close(); + return; + } + } + async create(docs, _allowSelection = false, offsetX = 0) { + await this.show(docs, { + offsetX + }); + } + applyFloatConfig(conf, opts) { + for (let key of Object.keys(opts)) { + if (key == "border") { + if (opts.border) + conf.border = [1, 1, 1, 1]; + continue; + } + conf[key] = opts[key]; + } + return conf; + } + async show(docs, config = {}) { + if (docs.length == 0 || docs.every((doc) => doc.content.length == 0)) { + this.close(); + return; + } + let curr = Date.now(); + let release = await this.mutex.acquire(); + try { + await this.createPopup(docs, config, curr); + release(); + } catch (e) { + this.nvim.echoError(e); + release(); + } + } + async createPopup(docs, opts, timestamp) { + docs = docs.filter((o) => o.content.trim().length > 0); + let { lines, codes, highlights } = parseDocuments(docs); + let config = { + pumAlignTop: events_default.pumAlignTop, + preferTop: typeof opts.preferTop === "boolean" ? opts.preferTop : false, + offsetX: opts.offsetX || 0, + title: opts.title || "", + close: opts.close ? 1 : 0, + codes, + highlights, + modes: opts.modes || ["n", "i", "ic", "s"] + }; + if (!isVim) { + if (typeof opts.winblend === "number") + config.winblend = opts.winblend; + if (opts.focusable != null) + config.focusable = opts.focusable ? 1 : 0; + if (opts.shadow) + config.shadow = 1; + } + if (opts.maxHeight) + config.maxHeight = opts.maxHeight; + if (opts.maxWidth) + config.maxWidth = opts.maxWidth; + if (opts.border && !opts.border.every((o) => o == 0)) { + config.border = opts.border; + } + if (opts.title && !config.border) + config.border = [1, 1, 1, 1]; + if (opts.highlight) + config.highlight = opts.highlight; + if (opts.borderhighlight) + config.borderhighlight = [opts.borderhighlight]; + if (opts.cursorline) + config.cursorline = 1; + let autoHide = opts.autoHide == false ? false : true; + if (autoHide) + config.autohide = 1; + this.unbind(); + let arr = await this.nvim.call("coc#float#create_cursor_float", [this.winid, this._bufnr, lines, config]); + this.nvim.redrawVim(); + if (!arr || arr.length == 0 || this.closeTs > timestamp) { + let winid2 = arr && arr.length > 0 ? arr[2] : this.winid; + if (winid2) { + this.winid = 0; + this.nvim.call("coc#float#close", [winid2], true); + this.nvim.redrawVim(); + } + return; + } + let [targetBufnr, cursor, winid, bufnr, alignTop] = arr; + this.winid = winid; + this._bufnr = bufnr; + this.targetBufnr = targetBufnr; + this.cursor = cursor; + this.bindEvents(autoHide, alignTop == 1); + } + close() { + let { winid, nvim } = this; + this.closeTs = Date.now(); + this.unbind(); + if (winid) { + this.winid = 0; + nvim.call("coc#float#close", [winid], true); + nvim.redrawVim(); + } + } + checkRetrigger(bufnr) { + if (this.winid && this.targetBufnr == bufnr) + return true; + return false; + } + get bufnr() { + return this._bufnr; + } + get buffer() { + return this.bufnr ? this.nvim.createBuffer(this.bufnr) : null; + } + get window() { + return this.winid ? this.nvim.createWindow(this.winid) : null; + } + async activated() { + if (!this.winid) + return false; + return await this.nvim.call("coc#float#valid", [this.winid]) != 0; + } + dispose() { + this.cursor = void 0; + this.close(); + } + }; + } +}); + +// src/util/position.ts +function rangeInRange(r, range) { + return positionInRange(r.start, range) === 0 && positionInRange(r.end, range) === 0; +} +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; +} +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; +} +function lineInRange(line, range) { + let { start, end } = range; + return line >= start.line && line <= end.line; +} +function emptyRange(range) { + let { start, end } = range; + return start.line == end.line && start.character == end.character; +} +function positionInRange(position, range) { + let { start, end } = range; + if (comparePosition(position, start) < 0) + return -1; + if (comparePosition(position, end) > 0) + return 1; + return 0; +} +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; +} +function isSingleLine(range) { + return range.start.line == range.end.line; +} +function getChangedPosition(start, edit2) { + let { range, newText } = edit2; + 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 }; +} +function adjustPosition(pos, edit2) { + let { range, newText } = edit2; + 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 + }; +} +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; +} +function editRange(range, text, edit2) { + if (!rangeInRange(edit2.range, range)) + return text; + let { start, end } = edit2.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)}${edit2.newText}${text.slice(endOffset, text.length)}`; +} +function getChangedFromEdits(start, edits) { + let changed = { line: 0, character: 0 }; + for (let edit2 of edits) { + let d = getChangedPosition(start, edit2); + changed = { line: changed.line + d.line, character: changed.character + d.character }; + } + return changed.line == 0 && changed.character == 0 ? null : changed; +} +var init_position = __esm({ + "src/util/position.ts"() { + } +}); + +// src/model/outputChannel.ts +var logger6, BufferChannel; +var init_outputChannel = __esm({ + "src/model/outputChannel.ts"() { + init_util(); + logger6 = require_logger2()("outpubChannel"); + BufferChannel = class { + constructor(name2, nvim, onDispose) { + this.name = name2; + this.nvim = nvim; + this.onDispose = onDispose; + this.lines = [""]; + this.disposables = []; + this._disposed = false; + this.created = false; + } + get content() { + return this.lines.join("\n"); + } + _append(value) { + let { nvim } = this; + let idx = this.lines.length - 1; + let newlines = value.split(/\r?\n/); + let lastline = this.lines[idx] + newlines[0]; + this.lines[idx] = lastline; + let append = newlines.slice(1); + this.lines = this.lines.concat(append); + if (!this.created) + return; + nvim.pauseNotification(); + nvim.call("setbufline", [this.bufname, "$", lastline], true); + if (append.length) { + nvim.call("appendbufline", [this.bufname, "$", append], true); + } + nvim.resumeNotification(false, true); + } + append(value) { + if (!this.validate()) + return; + this._append(value); + } + appendLine(value) { + if (!this.validate()) + return; + this._append(value + "\n"); + } + clear(keep) { + if (!this.validate()) + return; + let { nvim } = this; + this.lines = keep ? this.lines.slice(-keep) : []; + if (!this.created) + return; + nvim.pauseNotification(); + nvim.call("deletebufline", [this.bufname, 1, "$"], true); + if (this.lines.length) { + nvim.call("appendbufline", [this.bufname, "$", this.lines], true); + } + nvim.resumeNotification(false, true); + } + hide() { + this.created = false; + this.nvim.command(`exe 'silent! bd! '.fnameescape('${this.bufname}')`, true); + } + get bufname() { + return `output:///${this.name}`; + } + show(preserveFocus) { + let { nvim } = this; + nvim.pauseNotification(); + nvim.command(`exe 'vsplit '.fnameescape('${this.bufname}')`, true); + if (preserveFocus) { + nvim.command("wincmd p", true); + } + nvim.command("redraw", true); + nvim.resumeNotification(false, true); + this.created = true; + } + validate() { + return !this._disposed; + } + dispose() { + if (this.onDispose) + this.onDispose(); + this._disposed = true; + this.hide(); + this.lines = []; + disposeAll(this.disposables); + } + }; + } +}); + +// src/channels.ts +var logger7, Channels, channels_default; +var init_channels = __esm({ + "src/channels.ts"() { + init_outputChannel(); + init_events(); + logger7 = require_logger2()("channels"); + Channels = class { + constructor() { + this.outputChannels = new Map(); + this.bufnrs = new Map(); + this.disposable = events_default.on("BufUnload", (bufnr) => { + let name2 = this.bufnrs.get(bufnr); + if (name2) { + let channel = this.outputChannels.get(name2); + if (channel) + channel.created = false; + } + }); + } + getProvider(nvim) { + let provider = { + onDidChange: null, + provideTextDocumentContent: async (uri) => { + let channel = this.get(uri.path.slice(1)); + if (!channel) + return ""; + nvim.pauseNotification(); + nvim.call("bufnr", ["%"], true); + nvim.command("setlocal nospell nofoldenable nowrap noswapfile", true); + nvim.command("setlocal buftype=nofile bufhidden=hide", true); + nvim.command("setfiletype log", true); + let res = await nvim.resumeNotification(); + if (!res[1]) { + this.bufnrs.set(res[0][0], channel.name); + channel.created = true; + } + return channel.content; + } + }; + return provider; + } + get names() { + return Array.from(this.outputChannels.keys()); + } + get(channelName) { + return this.outputChannels.get(channelName); + } + create(name2, nvim) { + if (this.outputChannels.has(name2)) + return this.outputChannels.get(name2); + if (!/^[\w\s-.]+$/.test(name2)) + throw new Error(`Invalid channel name "${name2}", only word characters and white space allowed.`); + let channel = new BufferChannel(name2, nvim, () => { + this.outputChannels.delete(name2); + }); + this.outputChannels.set(name2, channel); + return channel; + } + show(name2, preserveFocus) { + let channel = this.outputChannels.get(name2); + if (!channel) + return; + channel.show(preserveFocus); + } + dispose() { + this.disposable.dispose(); + for (let channel of this.outputChannels.values()) { + channel.dispose(); + } + this.outputChannels.clear(); + } + }; + channels_default = new Channels(); + } +}); + +// src/model/dialog.ts +var logger8, Dialog; +var init_dialog = __esm({ + "src/model/dialog.ts"() { + init_events(); + init_util(); + logger8 = require_logger2()("model-dialog"); + Dialog = class { + constructor(nvim, config) { + this.nvim = nvim; + this.config = config; + this.disposables = []; + events_default.on("BufWinLeave", (bufnr) => { + if (bufnr == this.bufnr) { + this.dispose(); + if (config.callback) + config.callback(-1); + } + }, null, this.disposables); + events_default.on("FloatBtnClick", (bufnr, idx) => { + if (bufnr == this.bufnr) { + this.dispose(); + let btns = config == null ? void 0 : config.buttons.filter((o) => o.disabled != true); + if (config.callback) + config.callback(btns[idx].index); + } + }, null, this.disposables); + } + get lines() { + return [...this.config.content.split(/\r?\n/)]; + } + async show(preferences) { + let { nvim } = this; + let { title, close, buttons } = this.config; + let borderhighlight = this.config.borderhighlight || preferences.floatBorderHighlight; + let highlight = this.config.highlight || preferences.floatHighlight; + let opts = { maxwidth: preferences.maxWidth || 80 }; + if (title) + opts.title = title; + if (close || typeof close === "undefined") + opts.close = 1; + if (preferences.maxHeight) + opts.maxHeight = preferences.maxHeight; + if (preferences.maxWidth) + opts.maxWidth = preferences.maxWidth; + if (highlight) + opts.highlight = highlight; + if (borderhighlight) + opts.borderhighlight = [borderhighlight]; + if (buttons) + opts.buttons = buttons.filter((o) => !o.disabled).map((o) => o.text); + let res = await nvim.call("coc#float#create_dialog", [this.lines, opts]); + if (!res[1]) + return; + this.bufnr = res[1]; + nvim.command("redraw", true); + } + get winid() { + if (!this.bufnr) + return Promise.resolve(null); + return this.nvim.call("bufwinid", [this.bufnr]); + } + dispose() { + this.bufnr = void 0; + disposeAll(this.disposables); + this.disposables = []; + } + }; + } +}); + +// src/model/popup.ts +var isVim2, Popup; +var init_popup = __esm({ + "src/model/popup.ts"() { + isVim2 = process.env.VIM_NODE_RPC == "1"; + Popup = class { + constructor(nvim, winid, bufnr) { + this.nvim = nvim; + this.winid = winid; + this.bufnr = bufnr; + } + get valid() { + return this.nvim.call("coc#float#valid", [this.winid]).then((res) => { + return !!res; + }); + } + close() { + this.nvim.call("coc#float#close", [this.winid], true); + } + refreshScrollbar() { + if (!isVim2) + this.nvim.call("coc#float#nvim_scrollbar", [this.winid], true); + } + execute(cmd) { + this.nvim.call("coc#compat#execute", [this.winid, cmd], true); + } + async scrollForward() { + let { nvim, bufnr, winid } = this; + let buf = nvim.createBuffer(bufnr); + let total = await buf.length; + let botline; + if (!isVim2) { + let infos = await nvim.call("getwininfo", [winid]); + if (!infos || !infos.length) + return; + botline = infos[0].botline; + } else { + botline = await nvim.eval(`get(popup_getpos(${winid}), 'lastline', 0)`); + } + if (botline >= total || botline == 0) + return; + nvim.pauseNotification(); + this.setCursor(botline - 1); + this.execute(`silent! noa setl scrolloff=0`); + this.execute(`normal! ${botline}Gzt`); + this.refreshScrollbar(); + nvim.command("redraw", true); + nvim.resumeNotification(false, true); + } + async scrollBackward() { + let { nvim, winid } = this; + let topline; + if (!isVim2) { + let infos = await nvim.call("getwininfo", [winid]); + if (!infos || !infos.length) + return; + topline = infos[0].topline; + } else { + topline = await nvim.eval(`get(popup_getpos(${winid}), 'firstline', 0)`); + } + if (topline == 1) + return; + nvim.pauseNotification(); + this.setCursor(topline - 1); + this.execute(`normal! ${topline}Gzb`); + this.refreshScrollbar(); + nvim.command("redraw", true); + nvim.resumeNotification(false, true); + } + setCursor(index) { + let { nvim, bufnr, winid } = this; + if (isVim2) { + nvim.call("win_execute", [winid, `exe ${index + 1}`], true); + } else { + let win = nvim.createWindow(winid); + win.notify("nvim_win_set_cursor", [[index + 1, 0]]); + nvim.command(`sign unplace 6 buffer=${bufnr}`, true); + nvim.command(`sign place 6 line=${index + 1} name=CocCurrentLine buffer=${bufnr}`, true); + } + } + }; + } +}); + +// src/model/menu.ts +var import_vscode_languageserver_protocol4, logger9, Menu; +var init_menu = __esm({ + "src/model/menu.ts"() { + import_vscode_languageserver_protocol4 = __toModule(require_main2()); + init_events(); + init_util(); + init_popup(); + logger9 = require_logger2()("model-menu"); + Menu = class { + constructor(nvim, config, token) { + this.nvim = nvim; + this.config = config; + this.currIndex = 0; + this.disposables = []; + this.keyMappings = new Map(); + this._onDidClose = new import_vscode_languageserver_protocol4.Emitter(); + this.onDidClose = this._onDidClose.event; + this.total = config.items.length; + if (token) { + token.onCancellationRequested(() => { + var _a2; + (_a2 = this.win) == null ? void 0 : _a2.close(); + }); + } + this.disposables.push(this._onDidClose); + this.addKeymappings(); + } + attachEvents() { + events_default.on("InputChar", this.onInputChar.bind(this), null, this.disposables); + events_default.on("BufWinLeave", (bufnr) => { + if (bufnr == this.bufnr) { + this._onDidClose.fire(-1); + this.bufnr = void 0; + this.win = void 0; + this.dispose(); + } + }, null, this.disposables); + } + addKeymappings() { + let { nvim } = this; + this.addKeys(["", ""], () => { + this._onDidClose.fire(-1); + this.dispose(); + }); + this.addKeys(["\r", ""], () => { + this._onDidClose.fire(this.currIndex); + this.dispose(); + }); + let setCursorIndex = (idx) => { + var _a2; + if (!this.win) + return; + nvim.pauseNotification(); + this.setCursor(idx); + (_a2 = this.win) == null ? void 0 : _a2.refreshScrollbar(); + nvim.command("redraw", true); + nvim.resumeNotification(false, true); + }; + this.addKeys("", async () => { + var _a2; + await ((_a2 = this.win) == null ? void 0 : _a2.scrollForward()); + }); + this.addKeys("", async () => { + var _a2; + await ((_a2 = this.win) == null ? void 0 : _a2.scrollBackward()); + }); + this.addKeys(["j", "", "", ""], () => { + let idx = this.currIndex == this.total - 1 ? 0 : this.currIndex + 1; + setCursorIndex(idx); + }); + this.addKeys(["k", "", "", ""], () => { + let idx = this.currIndex == 0 ? this.total - 1 : this.currIndex - 1; + setCursorIndex(idx); + }); + this.addKeys(["g"], () => { + setCursorIndex(0); + }); + this.addKeys(["G"], () => { + setCursorIndex(this.total - 1); + }); + let timer; + let firstNumber; + this.addKeys(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], (character) => { + if (timer) + clearTimeout(timer); + let n = parseInt(character, 10); + if (isNaN(n) || n > this.total) + return; + if (firstNumber == null && n == 0) + return; + if (firstNumber) { + let count = firstNumber * 10 + n; + firstNumber = void 0; + this._onDidClose.fire(count - 1); + this.dispose(); + return; + } + if (this.total < 10 || n * 10 > this.total) { + this._onDidClose.fire(n - 1); + this.dispose(); + return; + } + timer = setTimeout(async () => { + this._onDidClose.fire(n - 1); + this.dispose(); + }, 200); + firstNumber = n; + }); + } + async show(preferences = {}) { + let { nvim } = this; + let { title, items } = this.config; + let opts = {}; + if (title) + opts.title = title; + if (preferences.maxHeight) + opts.maxHeight = preferences.maxHeight; + if (preferences.maxWidth) + opts.maxWidth = preferences.maxWidth; + if (preferences.floatHighlight) + opts.highlight = preferences.floatHighlight; + if (preferences.floatBorderHighlight) + opts.borderhighlight = [preferences.floatBorderHighlight]; + let lines = items.map((v, i) => { + if (i < 99) + return `${i + 1}. ${v}`; + return v; + }); + if (preferences.confirmKey && preferences.confirmKey != "") { + this.addKeys(preferences.confirmKey, () => { + this._onDidClose.fire(this.currIndex); + this.dispose(); + }); + } + let res = await nvim.call("coc#float#create_menu", [lines, opts]); + this.win = new Popup(nvim, res[0], res[1]); + this.bufnr = res[1]; + this.attachEvents(); + nvim.call("coc#prompt#start_prompt", ["menu"], true); + return res[0]; + } + get buffer() { + return this.bufnr ? this.nvim.createBuffer(this.bufnr) : void 0; + } + dispose() { + var _a2; + disposeAll(this.disposables); + this.disposables = []; + this.nvim.call("coc#prompt#stop_prompt", ["menu"], true); + (_a2 = this.win) == null ? void 0 : _a2.close(); + this.win = void 0; + } + async onInputChar(session, character) { + if (session != "menu" || !this.win) + return; + let fn = this.keyMappings.get(character); + if (fn) { + await Promise.resolve(fn(character)); + } else { + logger9.warn(`Ignored key press: ${character}`); + } + } + setCursor(index) { + if (!this.win) + return; + this.currIndex = index; + this.win.setCursor(index); + } + addKeys(keys, fn) { + if (Array.isArray(keys)) { + for (let key of keys) { + this.keyMappings.set(key, fn); + } + } else { + this.keyMappings.set(keys, fn); + } + } + }; + } +}); + +// src/model/notification.ts +var isVim3, logger10, Notification; +var init_notification = __esm({ + "src/model/notification.ts"() { + init_events(); + init_util(); + isVim3 = process.env.VIM_NODE_RPC == "1"; + logger10 = require_logger2()("model-notification"); + Notification = class { + constructor(nvim, config, attachEvents = true) { + this.nvim = nvim; + this.config = config; + this.disposables = []; + this._disposed = false; + if (attachEvents) { + events_default.on("BufWinLeave", (bufnr) => { + if (bufnr == this.bufnr) { + this.dispose(); + if (config.callback) + config.callback(-1); + } + }, null, this.disposables); + events_default.on("FloatBtnClick", (bufnr, idx) => { + if (bufnr == this.bufnr) { + this.dispose(); + let btns = config == null ? void 0 : config.buttons.filter((o) => o.disabled != true); + if (config.callback) + config.callback(btns[idx].index); + } + }, null, this.disposables); + } + } + get lines() { + return this.config.content.split(/\r?\n/); + } + async show(preferences) { + let { nvim } = this; + let { title, close, timeout, buttons, borderhighlight } = this.config; + let opts = Object.assign({}, preferences); + opts.close = close ? 1 : 0; + if (title) + opts.title = title; + if (borderhighlight) + opts.borderhighlight = borderhighlight; + if (buttons) + opts.buttons = buttons.filter((o) => !o.disabled).map((o) => o.text); + if (timeout) + opts.timeout = timeout; + let res = await nvim.call("coc#float#create_notification", [this.lines, opts]); + if (!res) + return false; + if (this._disposed) { + this.nvim.call("coc#float#close", [res[0]], true); + if (isVim3) + this.nvim.command("redraw", true); + } else { + this._winid = res[0]; + this.bufnr = res[1]; + } + return this._winid != void 0; + } + get winid() { + return this._winid; + } + dispose() { + if (this._disposed) + return; + this._disposed = true; + let { winid } = this; + if (winid) { + this.nvim.call("coc#float#close", [winid], true); + if (isVim3) + this.nvim.command("redraw", true); + } + this.bufnr = void 0; + this._winid = void 0; + disposeAll(this.disposables); + this.disposables = []; + } + }; + } +}); + +// src/model/picker.ts +var import_vscode_languageserver_protocol5, logger11, isVim4, Picker; +var init_picker = __esm({ + "src/model/picker.ts"() { + import_vscode_languageserver_protocol5 = __toModule(require_main2()); + init_events(); + init_util(); + init_string(); + init_popup(); + logger11 = require_logger2()("model-dialog"); + isVim4 = process.env.VIM_NODE_RPC == "1"; + Picker = class { + constructor(nvim, config, token) { + this.nvim = nvim; + this.config = config; + this.picked = new Set(); + this.currIndex = 0; + this.disposables = []; + this.keyMappings = new Map(); + this._onDidClose = new import_vscode_languageserver_protocol5.Emitter(); + this.onDidClose = this._onDidClose.event; + for (let i = 0; i < config.items.length; i++) { + let item = config.items[i]; + if (item.picked) + this.picked.add(i); + } + this.total = config.items.length; + if (token) { + token.onCancellationRequested(() => { + var _a2; + (_a2 = this.win) == null ? void 0 : _a2.close(); + }); + } + this.disposables.push(this._onDidClose); + this.addKeymappings(); + } + attachEvents() { + events_default.on("InputChar", this.onInputChar.bind(this), null, this.disposables); + events_default.on("BufWinLeave", (bufnr) => { + if (bufnr == this.bufnr) { + this._onDidClose.fire(void 0); + this.bufnr = void 0; + this.win = void 0; + this.dispose(); + } + }, null, this.disposables); + events_default.on("FloatBtnClick", (bufnr, idx) => { + if (bufnr == this.bufnr) { + if (idx == 0) { + let selected = Array.from(this.picked); + this._onDidClose.fire(selected.length ? selected : void 0); + } else { + this._onDidClose.fire(void 0); + } + this.dispose(); + } + }, null, this.disposables); + } + addKeymappings() { + let { nvim } = this; + const toggleSelect = (idx) => { + if (this.picked.has(idx)) { + this.picked.delete(idx); + } else { + this.picked.add(idx); + } + }; + this.addKeys("", async () => { + if (isVim4 || !this.win) + return; + let [winid, lnum, col] = await nvim.eval("[v:mouse_winid,v:mouse_lnum,v:mouse_col]"); + if (global.hasOwnProperty("__TEST__")) { + let res = await nvim.getVar("mouse_position"); + winid = res[0]; + lnum = res[1]; + col = res[2]; + } + nvim.pauseNotification(); + if (winid == this.win.winid) { + if (col <= 3) { + toggleSelect(lnum - 1); + this.changeLine(lnum - 1); + } else { + this.setCursor(lnum - 1); + } + } + nvim.call("win_gotoid", [winid], true); + nvim.call("cursor", [lnum, col], true); + nvim.call("coc#float#nvim_float_click", [], true); + nvim.command("redraw", true); + await nvim.resumeNotification(); + }); + this.addKeys(["", ""], () => { + this._onDidClose.fire(void 0); + this.dispose(); + }); + this.addKeys("", () => { + if (this.picked.size == 0) { + this._onDidClose.fire(void 0); + } else { + let selected = Array.from(this.picked); + this._onDidClose.fire(selected); + } + this.dispose(); + }); + let setCursorIndex = (idx) => { + nvim.pauseNotification(); + this.setCursor(idx); + this.win.refreshScrollbar(); + nvim.command("redraw", true); + nvim.resumeNotification(false, true); + }; + this.addKeys(["j", "", "", ""], () => { + let idx = this.currIndex == this.total - 1 ? 0 : this.currIndex + 1; + setCursorIndex(idx); + }); + this.addKeys(["k", "", "", ""], () => { + let idx = this.currIndex == 0 ? this.total - 1 : this.currIndex - 1; + setCursorIndex(idx); + }); + this.addKeys(["g"], () => { + setCursorIndex(0); + }); + this.addKeys(["G"], () => { + setCursorIndex(this.total - 1); + }); + this.addKeys(" ", async () => { + let idx = this.currIndex; + toggleSelect(idx); + nvim.pauseNotification(); + this.changeLine(idx); + if (this.currIndex != this.total - 1) { + this.setCursor(this.currIndex + 1); + } + nvim.command("redraw", true); + await nvim.resumeNotification(); + }); + this.addKeys("", async () => { + var _a2; + await ((_a2 = this.win) == null ? void 0 : _a2.scrollForward()); + }); + this.addKeys("", async () => { + var _a2; + await ((_a2 = this.win) == null ? void 0 : _a2.scrollBackward()); + }); + } + async show(preferences = {}) { + let { nvim } = this; + let { title, items } = this.config; + let opts = { close: 1, cursorline: 1 }; + if (preferences.maxHeight) + opts.maxHeight = preferences.maxHeight; + if (preferences.maxWidth) + opts.maxWidth = preferences.maxWidth; + if (title) + opts.title = title; + opts.close = 1; + opts.cursorline = 1; + if (preferences.floatHighlight) { + opts.highlight = preferences.floatHighlight; + } + if (preferences.floatBorderHighlight) { + opts.borderhighlight = [preferences.floatBorderHighlight]; + } + if (preferences.pickerButtons) { + let shortcut = preferences.pickerButtonShortcut; + opts.buttons = ["Submit" + (shortcut ? " " : ""), "Cancel" + (shortcut ? " " : "")]; + } + if (preferences.confirmKey && preferences.confirmKey != "") { + this.addKeys(preferences.confirmKey, () => { + this._onDidClose.fire(void 0); + this.dispose(); + }); + } + let lines = []; + let positions2 = []; + for (let i = 0; i < items.length; i++) { + let item = items[i]; + let line = `[${item.picked ? "x" : " "}] ${item.label}`; + positions2.push([i, byteLength(line)]); + if (item.description) + line = line + ` ${item.description}`; + lines.push(line); + } + let res = await nvim.call("coc#float#create_dialog", [lines, opts]); + this.win = new Popup(nvim, res[0], res[1]); + this.bufnr = res[1]; + this.attachEvents(); + let buf = nvim.createBuffer(this.bufnr); + nvim.pauseNotification(); + for (let pos of positions2) { + buf.addHighlight({ hlGroup: "Comment", line: pos[0], srcId: 1, colStart: pos[1], colEnd: -1 }); + } + nvim.command("redraw", true); + await nvim.resumeNotification(); + nvim.call("coc#prompt#start_prompt", ["picker"], true); + return res[0]; + } + get buffer() { + return this.bufnr ? this.nvim.createBuffer(this.bufnr) : void 0; + } + dispose() { + var _a2; + this.picked.clear(); + this.keyMappings.clear(); + disposeAll(this.disposables); + this.nvim.call("coc#prompt#stop_prompt", ["picker"], true); + (_a2 = this.win) == null ? void 0 : _a2.close(); + this.win = void 0; + } + async onInputChar(session, character) { + if (session != "picker" || !this.win) + return; + let fn = this.keyMappings.get(character); + if (fn) { + await Promise.resolve(fn(character)); + } else { + logger11.warn(`Ignored key press: ${character}`); + } + } + changeLine(index) { + let { nvim } = this; + let item = this.config.items[index]; + if (!item) + return; + let line = `[${this.picked.has(index) ? "x" : " "}] ${item.label}`; + let col = byteLength(line); + if (item.description) + line = line + ` ${item.description}`; + nvim.call("setbufline", [this.bufnr, index + 1, line], true); + if (!isVim4) { + let buf = nvim.createBuffer(this.bufnr); + buf.addHighlight({ hlGroup: "Comment", line: index, srcId: 1, colStart: col, colEnd: -1 }); + } + } + setCursor(index) { + if (!this.win) + return; + this.currIndex = index; + this.win.setCursor(index); + } + addKeys(keys, fn) { + if (Array.isArray(keys)) { + for (let key of keys) { + this.keyMappings.set(key, fn); + } + } else { + this.keyMappings.set(keys, fn); + } + } + }; + } +}); + +// src/model/progress.ts +var import_vscode_languageserver_protocol6, ProgressNotification; +var init_progress = __esm({ + "src/model/progress.ts"() { + init_notification(); + import_vscode_languageserver_protocol6 = __toModule(require_main2()); + init_events(); + ProgressNotification = class extends Notification { + constructor(nvim, option) { + super(nvim, { + content: "\n", + close: option.cancellable == true, + title: option.title + }, false); + this.option = option; + events_default.on("BufWinLeave", (bufnr) => { + if (bufnr == this.bufnr) { + if (this.tokenSource) { + this.tokenSource.cancel(); + } + this.dispose(); + } + }, null, this.disposables); + } + async show(preferences) { + let { task } = this.option; + let tokenSource = this.tokenSource = new import_vscode_languageserver_protocol6.CancellationTokenSource(); + this.disposables.push(tokenSource); + let total = 0; + let res = await new Promise((resolve3, reject) => { + tokenSource.token.onCancellationRequested(() => { + resolve3(void 0); + }); + super.show(Object.assign({ minWidth: preferences.minProgressWidth || 30, progress: 1 }, preferences)).then((shown) => { + if (!shown) + reject(new Error("Failed to create float window")); + }).catch(reject); + task({ + report: (p) => { + if (!this.bufnr) + return; + let text = ""; + if (p.message) + text += p.message.replace(/\r?\n/g, " "); + if (p.increment) { + total += p.increment; + text = text + (text.length ? ` ${total}%` : `${total}%`); + } + this.nvim.call("setbufline", [this.bufnr, 2, text], true); + } + }, tokenSource.token).then((res2) => { + if (this._disposed) + return; + setTimeout(() => { + this.dispose(); + }, 100); + resolve3(res2); + }, (err) => { + if (this._disposed) + return; + this.dispose(); + if (err instanceof Error) { + reject(err); + } else { + resolve3(void 0); + } + }); + }); + return res; + } + dispose() { + super.dispose(); + this.tokenSource = void 0; + } + }; + } +}); + +// node_modules/uuid/dist/esm-node/rng.js +function rng() { + return import_crypto.default.randomBytes(16); +} +var import_crypto; +var init_rng = __esm({ + "node_modules/uuid/dist/esm-node/rng.js"() { + import_crypto = __toModule(require("crypto")); + } +}); + +// node_modules/uuid/dist/esm-node/bytesToUuid.js +function bytesToUuid(buf, offset) { + var i = offset || 0; + var bth = byteToHex; + 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(""); +} +var byteToHex, bytesToUuid_default; +var init_bytesToUuid = __esm({ + "node_modules/uuid/dist/esm-node/bytesToUuid.js"() { + byteToHex = []; + for (var i = 0; i < 256; ++i) { + byteToHex[i] = (i + 256).toString(16).substr(1); + } + bytesToUuid_default = bytesToUuid; + } +}); + +// node_modules/uuid/dist/esm-node/v1.js +function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + options = options || {}; + var node = options.node || _nodeId; + var clockseq = options.clockseq !== void 0 ? options.clockseq : _clockseq; + if (node == null || clockseq == null) { + var seedBytes = options.random || (options.rng || rng)(); + if (node == null) { + node = _nodeId = [seedBytes[0] | 1, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + if (clockseq == null) { + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 16383; + } + } + var msecs = options.msecs !== void 0 ? options.msecs : new Date().getTime(); + var nsecs = options.nsecs !== void 0 ? options.nsecs : _lastNSecs + 1; + var dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 1e4; + if (dt < 0 && options.clockseq === void 0) { + clockseq = clockseq + 1 & 16383; + } + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === void 0) { + nsecs = 0; + } + if (nsecs >= 1e4) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + msecs += 122192928e5; + var tl = ((msecs & 268435455) * 1e4 + nsecs) % 4294967296; + b[i++] = tl >>> 24 & 255; + b[i++] = tl >>> 16 & 255; + b[i++] = tl >>> 8 & 255; + b[i++] = tl & 255; + var tmh = msecs / 4294967296 * 1e4 & 268435455; + b[i++] = tmh >>> 8 & 255; + b[i++] = tmh & 255; + b[i++] = tmh >>> 24 & 15 | 16; + b[i++] = tmh >>> 16 & 255; + b[i++] = clockseq >>> 8 | 128; + b[i++] = clockseq & 255; + for (var n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + return buf ? buf : bytesToUuid_default(b); +} +var _nodeId, _clockseq, _lastMSecs, _lastNSecs, v1_default; +var init_v1 = __esm({ + "node_modules/uuid/dist/esm-node/v1.js"() { + init_rng(); + init_bytesToUuid(); + _lastMSecs = 0; + _lastNSecs = 0; + v1_default = v1; + } +}); + +// node_modules/uuid/dist/esm-node/v4.js +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)(); + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + if (buf) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; + } + } + return buf || bytesToUuid_default(rnds); +} +var v4_default; +var init_v4 = __esm({ + "node_modules/uuid/dist/esm-node/v4.js"() { + init_rng(); + init_bytesToUuid(); + v4_default = v4; + } +}); + +// node_modules/uuid/dist/esm-node/index.js +var init_esm_node = __esm({ + "node_modules/uuid/dist/esm-node/index.js"() { + init_v1(); + init_v4(); + } +}); + +// src/model/status.ts +var logger12, frames, StatusLine; +var init_status = __esm({ + "src/model/status.ts"() { + init_esm_node(); + logger12 = require_logger2()("model-status"); + frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"]; + StatusLine = class { + 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 = v1_default(); + 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.call("coc#util#do_autocmd", ["CocStatusChange"], true); + await nvim.resumeNotification(false, true); + } + } + }; + } +}); + +// src/types.ts +var PatternType, SourceType, MessageLevel, ConfigurationTarget, ServiceStat, FileType; +var init_types = __esm({ + "src/types.ts"() { + (function(PatternType2) { + PatternType2[PatternType2["Buffer"] = 0] = "Buffer"; + PatternType2[PatternType2["LanguageServer"] = 1] = "LanguageServer"; + PatternType2[PatternType2["Global"] = 2] = "Global"; + })(PatternType || (PatternType = {})); + (function(SourceType2) { + SourceType2[SourceType2["Native"] = 0] = "Native"; + SourceType2[SourceType2["Remote"] = 1] = "Remote"; + SourceType2[SourceType2["Service"] = 2] = "Service"; + })(SourceType || (SourceType = {})); + (function(MessageLevel2) { + MessageLevel2[MessageLevel2["More"] = 0] = "More"; + MessageLevel2[MessageLevel2["Warning"] = 1] = "Warning"; + MessageLevel2[MessageLevel2["Error"] = 2] = "Error"; + })(MessageLevel || (MessageLevel = {})); + (function(ConfigurationTarget3) { + ConfigurationTarget3[ConfigurationTarget3["Global"] = 0] = "Global"; + ConfigurationTarget3[ConfigurationTarget3["User"] = 1] = "User"; + ConfigurationTarget3[ConfigurationTarget3["Workspace"] = 2] = "Workspace"; + })(ConfigurationTarget || (ConfigurationTarget = {})); + (function(ServiceStat2) { + ServiceStat2[ServiceStat2["Initial"] = 0] = "Initial"; + ServiceStat2[ServiceStat2["Starting"] = 1] = "Starting"; + ServiceStat2[ServiceStat2["StartFailed"] = 2] = "StartFailed"; + ServiceStat2[ServiceStat2["Running"] = 3] = "Running"; + ServiceStat2[ServiceStat2["Stopping"] = 4] = "Stopping"; + ServiceStat2[ServiceStat2["Stopped"] = 5] = "Stopped"; + })(ServiceStat || (ServiceStat = {})); + (function(FileType2) { + FileType2[FileType2["Unknown"] = 0] = "Unknown"; + FileType2[FileType2["File"] = 1] = "File"; + FileType2[FileType2["Directory"] = 2] = "Directory"; + FileType2[FileType2["SymbolicLink"] = 64] = "SymbolicLink"; + })(FileType || (FileType = {})); + } +}); + +// node_modules/bytes/index.js +var require_bytes = __commonJS({ + "node_modules/bytes/index.js"(exports2, module2) { + "use strict"; + module2.exports = bytes2; + module2.exports.format = format2; + module2.exports.parse = parse5; + var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g; + var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/; + var map = { + b: 1, + kb: 1 << 10, + mb: 1 << 20, + gb: 1 << 30, + tb: Math.pow(1024, 4), + pb: Math.pow(1024, 5) + }; + var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i; + function bytes2(value, options) { + if (typeof value === "string") { + return parse5(value); + } + if (typeof value === "number") { + return format2(value, options); + } + return null; + } + function format2(value, options) { + if (!Number.isFinite(value)) { + return null; + } + var mag = Math.abs(value); + var thousandsSeparator = options && options.thousandsSeparator || ""; + var unitSeparator = options && options.unitSeparator || ""; + var decimalPlaces = options && options.decimalPlaces !== void 0 ? options.decimalPlaces : 2; + var fixedDecimals = Boolean(options && options.fixedDecimals); + var unit = options && options.unit || ""; + if (!unit || !map[unit.toLowerCase()]) { + if (mag >= map.pb) { + unit = "PB"; + } else if (mag >= map.tb) { + unit = "TB"; + } else if (mag >= map.gb) { + unit = "GB"; + } else if (mag >= map.mb) { + unit = "MB"; + } else if (mag >= map.kb) { + unit = "KB"; + } else { + unit = "B"; + } + } + var val = value / map[unit.toLowerCase()]; + var str = val.toFixed(decimalPlaces); + if (!fixedDecimals) { + str = str.replace(formatDecimalsRegExp, "$1"); + } + if (thousandsSeparator) { + str = str.replace(formatThousandsRegExp, thousandsSeparator); + } + return str + unitSeparator + unit; + } + function parse5(val) { + if (typeof val === "number" && !isNaN(val)) { + return val; + } + if (typeof val !== "string") { + return null; + } + var results = parseRegExp.exec(val); + var floatValue; + var unit = "b"; + if (!results) { + floatValue = parseInt(val, 10); + unit = "b"; + } else { + floatValue = parseFloat(results[1]); + unit = results[4].toLowerCase(); + } + return Math.floor(map[unit] * floatValue); + } + } +}); + +// node_modules/fast-diff/diff.js +var require_diff = __commonJS({ + "node_modules/fast-diff/diff.js"(exports2, module2) { + var DIFF_DELETE = -1; + var DIFF_INSERT = 1; + var DIFF_EQUAL = 0; + function diff_main(text1, text2, cursor_pos, _fix_unicode) { + 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; + } + } + var commonlength = diff_commonPrefix(text1, text2); + var commonprefix = text1.substring(0, commonlength); + text1 = text1.substring(commonlength); + text2 = text2.substring(commonlength); + 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); + var diffs = diff_compute_(text1, text2); + if (commonprefix) { + diffs.unshift([DIFF_EQUAL, commonprefix]); + } + if (commonsuffix) { + diffs.push([DIFF_EQUAL, commonsuffix]); + } + diff_cleanupMerge(diffs, _fix_unicode); + return diffs; + } + function diff_compute_(text1, text2) { + var diffs; + if (!text1) { + return [[DIFF_INSERT, text2]]; + } + if (!text2) { + 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) { + diffs = [ + [DIFF_INSERT, longtext.substring(0, i)], + [DIFF_EQUAL, shorttext], + [DIFF_INSERT, longtext.substring(i + shorttext.length)] + ]; + if (text1.length > text2.length) { + diffs[0][0] = diffs[2][0] = DIFF_DELETE; + } + return diffs; + } + if (shorttext.length === 1) { + return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; + } + var hm = diff_halfMatch_(text1, text2); + if (hm) { + 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]; + var diffs_a = diff_main(text1_a, text2_a); + var diffs_b = diff_main(text1_b, text2_b); + return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b); + } + return diff_bisect_(text1, text2); + } + function diff_bisect_(text1, text2) { + 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 v12 = new Array(v_length); + var v2 = new Array(v_length); + for (var x = 0; x < v_length; x++) { + v12[x] = -1; + v2[x] = -1; + } + v12[v_offset + 1] = 0; + v2[v_offset + 1] = 0; + var delta = text1_length - text2_length; + var front = delta % 2 !== 0; + var k1start = 0; + var k1end = 0; + var k2start = 0; + var k2end = 0; + for (var d = 0; d < max_d; d++) { + for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) { + var k1_offset = v_offset + k1; + var x1; + if (k1 === -d || k1 !== d && v12[k1_offset - 1] < v12[k1_offset + 1]) { + x1 = v12[k1_offset + 1]; + } else { + x1 = v12[k1_offset - 1] + 1; + } + var y1 = x1 - k1; + while (x1 < text1_length && y1 < text2_length && text1.charAt(x1) === text2.charAt(y1)) { + x1++; + y1++; + } + v12[k1_offset] = x1; + if (x1 > text1_length) { + k1end += 2; + } else if (y1 > text2_length) { + k1start += 2; + } else if (front) { + var k2_offset = v_offset + delta - k1; + if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] !== -1) { + var x2 = text1_length - v2[k2_offset]; + if (x1 >= x2) { + return diff_bisectSplit_(text1, text2, x1, y1); + } + } + } + } + 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) { + k2end += 2; + } else if (y2 > text2_length) { + k2start += 2; + } else if (!front) { + var k1_offset = v_offset + delta - k2; + if (k1_offset >= 0 && k1_offset < v_length && v12[k1_offset] !== -1) { + var x1 = v12[k1_offset]; + var y1 = v_offset + x1 - k1_offset; + x2 = text1_length - x2; + if (x1 >= x2) { + return diff_bisectSplit_(text1, text2, x1, y1); + } + } + } + } + } + return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; + } + 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); + var diffs = diff_main(text1a, text2a); + var diffsb = diff_main(text1b, text2b); + return diffs.concat(diffsb); + } + function diff_commonPrefix(text1, text2) { + if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) { + return 0; + } + 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; + } + function diff_commonSuffix(text1, text2) { + if (!text1 || !text2 || text1.slice(-1) !== text2.slice(-1)) { + return 0; + } + 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; + } + 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; + } + function diff_halfMatchI_(longtext2, shorttext2, i) { + var seed = longtext2.substring(i, i + Math.floor(longtext2.length / 4)); + var j = -1; + var best_common = ""; + var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b; + while ((j = shorttext2.indexOf(seed, j + 1)) !== -1) { + var prefixLength = diff_commonPrefix(longtext2.substring(i), shorttext2.substring(j)); + var suffixLength = diff_commonSuffix(longtext2.substring(0, i), shorttext2.substring(0, j)); + if (best_common.length < suffixLength + prefixLength) { + best_common = shorttext2.substring(j - suffixLength, j) + shorttext2.substring(j, j + prefixLength); + best_longtext_a = longtext2.substring(0, i - suffixLength); + best_longtext_b = longtext2.substring(i + prefixLength); + best_shorttext_a = shorttext2.substring(0, j - suffixLength); + best_shorttext_b = shorttext2.substring(j + prefixLength); + } + } + if (best_common.length * 2 >= longtext2.length) { + return [ + best_longtext_a, + best_longtext_b, + best_shorttext_a, + best_shorttext_b, + best_common + ]; + } else { + return null; + } + } + var hm1 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 4)); + 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 { + hm = hm1[4].length > hm2[4].length ? hm1 : hm2; + } + 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]; + } + function diff_cleanupMerge(diffs, fix_unicode) { + diffs.push([DIFF_EQUAL, ""]); + 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) { + 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]) { + 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]) { + diffs.splice(pointer, 1); + break; + } + if (text_delete.length > 0 || text_insert.length > 0) { + if (text_delete.length > 0 && text_insert.length > 0) { + 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); + } + 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); + } + } + 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) { + 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(); + } + var changes = false; + pointer = 1; + while (pointer < diffs.length - 1) { + if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) { + if (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) === diffs[pointer - 1][1]) { + 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]) { + 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 (changes) { + diff_cleanupMerge(diffs, fix_unicode); + } + } + function is_surrogate_pair_start(charCode) { + return charCode >= 55296 && charCode <= 56319; + } + function is_surrogate_pair_end(charCode) { + return charCode >= 56320 && charCode <= 57343; + } + 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) { + var oldRange = typeof cursor_pos === "number" ? { index: cursor_pos, length: 0 } : cursor_pos.oldRange; + var newRange = typeof cursor_pos === "number" ? null : cursor_pos.newRange; + var oldLength = oldText.length; + var newLength = newText.length; + if (oldRange.length === 0 && (newRange === null || newRange.length === 0)) { + var oldCursor = oldRange.index; + var oldBefore = oldText.slice(0, oldCursor); + var oldAfter = oldText.slice(oldCursor); + var maybeNewCursor = newRange ? newRange.index : null; + editBefore: { + 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: { + 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: { + 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) { + return diff_main(text1, text2, cursor_pos, true); + } + diff.INSERT = DIFF_INSERT; + diff.DELETE = DIFF_DELETE; + diff.EQUAL = DIFF_EQUAL; + module2.exports = diff; + } +}); + +// node_modules/vscode-languageserver-textdocument/lib/esm/main.js +function mergeSort(data, compare) { + if (data.length <= 1) { + 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) { + data[i++] = left[leftIdx++]; + } else { + data[i++] = right[rightIdx++]; + } + } + while (leftIdx < left.length) { + data[i++] = left[leftIdx++]; + } + while (rightIdx < right.length) { + data[i++] = right[rightIdx++]; + } + return data; +} +function computeLineOffsets(text, isAtLineStart, textOffset) { + if (textOffset === void 0) { + textOffset = 0; + } + var result = isAtLineStart ? [textOffset] : []; + for (var i = 0; i < text.length; i++) { + var ch = text.charCodeAt(i); + if (ch === 13 || ch === 10) { + if (ch === 13 && i + 1 < text.length && text.charCodeAt(i + 1) === 10) { + i++; + } + result.push(textOffset + i + 1); + } + } + return result; +} +function getWellformedRange(range) { + var start = range.start; + var end = range.end; + if (start.line > end.line || start.line === end.line && start.character > end.character) { + return { start: end, end: start }; + } + return range; +} +function getWellformedEdit(textEdit) { + var range = getWellformedRange(textEdit.range); + if (range !== textEdit.range) { + return { newText: textEdit.newText, range }; + } + return textEdit; +} +var FullTextDocument2, TextDocument2; +var init_main2 = __esm({ + "node_modules/vscode-languageserver-textdocument/lib/esm/main.js"() { + "use strict"; + FullTextDocument2 = function() { + function FullTextDocument3(uri, languageId, version2, content) { + this._uri = uri; + this._languageId = languageId; + this._version = version2; + this._content = content; + this._lineOffsets = void 0; + } + Object.defineProperty(FullTextDocument3.prototype, "uri", { + get: function() { + return this._uri; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(FullTextDocument3.prototype, "languageId", { + get: function() { + return this._languageId; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(FullTextDocument3.prototype, "version", { + get: function() { + return this._version; + }, + enumerable: true, + configurable: true + }); + FullTextDocument3.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; + }; + FullTextDocument3.prototype.update = function(changes, version2) { + for (var _i = 0, changes_1 = changes; _i < changes_1.length; _i++) { + var change = changes_1[_i]; + if (FullTextDocument3.isIncremental(change)) { + var range = getWellformedRange(change.range); + var startOffset = this.offsetAt(range.start); + var endOffset = this.offsetAt(range.end); + this._content = this._content.substring(0, startOffset) + change.text + this._content.substring(endOffset, this._content.length); + var startLine = Math.max(range.start.line, 0); + var endLine = Math.max(range.end.line, 0); + var lineOffsets = this._lineOffsets; + var addedLineOffsets = computeLineOffsets(change.text, false, startOffset); + if (endLine - startLine === addedLineOffsets.length) { + for (var i = 0, len = addedLineOffsets.length; i < len; i++) { + lineOffsets[i + startLine + 1] = addedLineOffsets[i]; + } + } else { + if (addedLineOffsets.length < 1e4) { + lineOffsets.splice.apply(lineOffsets, [startLine + 1, endLine - startLine].concat(addedLineOffsets)); + } else { + this._lineOffsets = lineOffsets = lineOffsets.slice(0, startLine + 1).concat(addedLineOffsets, lineOffsets.slice(endLine + 1)); + } + } + var diff = change.text.length - (endOffset - startOffset); + if (diff !== 0) { + for (var i = startLine + 1 + addedLineOffsets.length, len = lineOffsets.length; i < len; i++) { + lineOffsets[i] = lineOffsets[i] + diff; + } + } + } else if (FullTextDocument3.isFull(change)) { + this._content = change.text; + this._lineOffsets = void 0; + } else { + throw new Error("Unknown change event received"); + } + } + this._version = version2; + }; + FullTextDocument3.prototype.getLineOffsets = function() { + if (this._lineOffsets === void 0) { + this._lineOffsets = computeLineOffsets(this._content, true); + } + return this._lineOffsets; + }; + FullTextDocument3.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 { line: 0, character: offset }; + } + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (lineOffsets[mid] > offset) { + high = mid; + } else { + low = mid + 1; + } + } + var line = low - 1; + return { line, character: offset - lineOffsets[line] }; + }; + FullTextDocument3.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(FullTextDocument3.prototype, "lineCount", { + get: function() { + return this.getLineOffsets().length; + }, + enumerable: true, + configurable: true + }); + FullTextDocument3.isIncremental = function(event) { + var candidate = event; + return candidate !== void 0 && candidate !== null && typeof candidate.text === "string" && candidate.range !== void 0 && (candidate.rangeLength === void 0 || typeof candidate.rangeLength === "number"); + }; + FullTextDocument3.isFull = function(event) { + var candidate = event; + return candidate !== void 0 && candidate !== null && typeof candidate.text === "string" && candidate.range === void 0 && candidate.rangeLength === void 0; + }; + return FullTextDocument3; + }(); + (function(TextDocument5) { + function create(uri, languageId, version2, content) { + return new FullTextDocument2(uri, languageId, version2, content); + } + TextDocument5.create = create; + function update(document2, changes, version2) { + if (document2 instanceof FullTextDocument2) { + document2.update(changes, version2); + return document2; + } else { + throw new Error("TextDocument.update: document must be created by TextDocument.create"); + } + } + TextDocument5.update = update; + function applyEdits2(document2, edits) { + var text = document2.getText(); + var sortedEdits = mergeSort(edits.map(getWellformedEdit), 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 = 0; + var spans = []; + for (var _i = 0, sortedEdits_1 = sortedEdits; _i < sortedEdits_1.length; _i++) { + var e = sortedEdits_1[_i]; + var startOffset = document2.offsetAt(e.range.start); + if (startOffset < lastModifiedOffset) { + throw new Error("Overlapping edit"); + } else if (startOffset > lastModifiedOffset) { + spans.push(text.substring(lastModifiedOffset, startOffset)); + } + if (e.newText.length) { + spans.push(e.newText); + } + lastModifiedOffset = document2.offsetAt(e.range.end); + } + spans.push(text.substr(lastModifiedOffset)); + return spans.join(""); + } + TextDocument5.applyEdits = applyEdits2; + })(TextDocument2 || (TextDocument2 = {})); + } +}); + +// node_modules/jsonc-parser/lib/esm/impl/scanner.js +function createScanner(text, ignoreTrivia) { + if (ignoreTrivia === void 0) { + ignoreTrivia = false; + } + var len = text.length; + var pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0; + function scanHexDigits(count, exact) { + var digits = 0; + var value2 = 0; + while (digits < count || !exact) { + var ch = text.charCodeAt(pos); + if (ch >= 48 && ch <= 57) { + value2 = value2 * 16 + ch - 48; + } else if (ch >= 65 && ch <= 70) { + value2 = value2 * 16 + ch - 65 + 10; + } else if (ch >= 97 && ch <= 102) { + value2 = value2 * 16 + ch - 97 + 10; + } else { + break; + } + pos++; + digits++; + } + if (digits < count) { + value2 = -1; + } + return value2; + } + function setPosition(newPosition) { + pos = newPosition; + value = ""; + tokenOffset = 0; + token = 16; + scanError = 0; + } + function scanNumber() { + var start = pos; + if (text.charCodeAt(pos) === 48) { + pos++; + } else { + pos++; + while (pos < text.length && isDigit(text.charCodeAt(pos))) { + pos++; + } + } + if (pos < text.length && text.charCodeAt(pos) === 46) { + pos++; + if (pos < text.length && isDigit(text.charCodeAt(pos))) { + pos++; + while (pos < text.length && isDigit(text.charCodeAt(pos))) { + pos++; + } + } else { + scanError = 3; + return text.substring(start, pos); + } + } + var end = pos; + if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) { + pos++; + if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) { + pos++; + } + if (pos < text.length && isDigit(text.charCodeAt(pos))) { + pos++; + while (pos < text.length && isDigit(text.charCodeAt(pos))) { + pos++; + } + end = pos; + } else { + scanError = 3; + } + } + return text.substring(start, end); + } + function scanString() { + var result = "", start = pos; + while (true) { + if (pos >= len) { + result += text.substring(start, pos); + scanError = 2; + break; + } + var ch = text.charCodeAt(pos); + if (ch === 34) { + result += text.substring(start, pos); + pos++; + break; + } + if (ch === 92) { + result += text.substring(start, pos); + pos++; + if (pos >= len) { + scanError = 2; + break; + } + var ch2 = text.charCodeAt(pos++); + switch (ch2) { + case 34: + result += '"'; + break; + case 92: + result += "\\"; + break; + case 47: + result += "/"; + break; + case 98: + result += "\b"; + break; + case 102: + result += "\f"; + break; + case 110: + result += "\n"; + break; + case 114: + result += "\r"; + break; + case 116: + result += " "; + break; + case 117: + var ch3 = scanHexDigits(4, true); + if (ch3 >= 0) { + result += String.fromCharCode(ch3); + } else { + scanError = 4; + } + break; + default: + scanError = 5; + } + start = pos; + continue; + } + if (ch >= 0 && ch <= 31) { + if (isLineBreak(ch)) { + result += text.substring(start, pos); + scanError = 2; + break; + } else { + scanError = 6; + } + } + pos++; + } + return result; + } + function scanNext() { + value = ""; + scanError = 0; + tokenOffset = pos; + lineStartOffset = lineNumber; + prevTokenLineStartOffset = tokenLineStartOffset; + if (pos >= len) { + tokenOffset = len; + return token = 17; + } + var code = text.charCodeAt(pos); + if (isWhiteSpace(code)) { + do { + pos++; + value += String.fromCharCode(code); + code = text.charCodeAt(pos); + } while (isWhiteSpace(code)); + return token = 15; + } + if (isLineBreak(code)) { + pos++; + value += String.fromCharCode(code); + if (code === 13 && text.charCodeAt(pos) === 10) { + pos++; + value += "\n"; + } + lineNumber++; + tokenLineStartOffset = pos; + return token = 14; + } + switch (code) { + case 123: + pos++; + return token = 1; + case 125: + pos++; + return token = 2; + case 91: + pos++; + return token = 3; + case 93: + pos++; + return token = 4; + case 58: + pos++; + return token = 6; + case 44: + pos++; + return token = 5; + case 34: + pos++; + value = scanString(); + return token = 10; + case 47: + var start = pos - 1; + if (text.charCodeAt(pos + 1) === 47) { + pos += 2; + while (pos < len) { + if (isLineBreak(text.charCodeAt(pos))) { + break; + } + pos++; + } + value = text.substring(start, pos); + return token = 12; + } + if (text.charCodeAt(pos + 1) === 42) { + pos += 2; + var safeLength = len - 1; + var commentClosed = false; + while (pos < safeLength) { + var ch = text.charCodeAt(pos); + if (ch === 42 && text.charCodeAt(pos + 1) === 47) { + pos += 2; + commentClosed = true; + break; + } + pos++; + if (isLineBreak(ch)) { + if (ch === 13 && text.charCodeAt(pos) === 10) { + pos++; + } + lineNumber++; + tokenLineStartOffset = pos; + } + } + if (!commentClosed) { + pos++; + scanError = 1; + } + value = text.substring(start, pos); + return token = 13; + } + value += String.fromCharCode(code); + pos++; + return token = 16; + case 45: + value += String.fromCharCode(code); + pos++; + if (pos === len || !isDigit(text.charCodeAt(pos))) { + return token = 16; + } + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + value += scanNumber(); + return token = 11; + default: + while (pos < len && isUnknownContentCharacter(code)) { + pos++; + code = text.charCodeAt(pos); + } + if (tokenOffset !== pos) { + value = text.substring(tokenOffset, pos); + switch (value) { + case "true": + return token = 8; + case "false": + return token = 9; + case "null": + return token = 7; + } + return token = 16; + } + value += String.fromCharCode(code); + pos++; + return token = 16; + } + } + function isUnknownContentCharacter(code) { + if (isWhiteSpace(code) || isLineBreak(code)) { + return false; + } + switch (code) { + case 125: + case 93: + case 123: + case 91: + case 34: + case 58: + case 44: + case 47: + return false; + } + return true; + } + function scanNextNonTrivia() { + var result; + do { + result = scanNext(); + } while (result >= 12 && result <= 15); + return result; + } + return { + 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 || ch === 9 || ch === 11 || ch === 12 || ch === 160 || ch === 5760 || ch >= 8192 && ch <= 8203 || ch === 8239 || ch === 8287 || ch === 12288 || ch === 65279; +} +function isLineBreak(ch) { + return ch === 10 || ch === 13 || ch === 8232 || ch === 8233; +} +function isDigit(ch) { + return ch >= 48 && ch <= 57; +} +var init_scanner = __esm({ + "node_modules/jsonc-parser/lib/esm/impl/scanner.js"() { + "use strict"; + } +}); + +// node_modules/jsonc-parser/lib/esm/impl/format.js +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 = " "; + } + var scanner2 = createScanner(formatText, false); + var hasError = false; + function newLineAndIndent() { + return eol + repeat(indentValue, initialIndentLevel + indentLevel); + } + function scanNext() { + var token = scanner2.scan(); + lineBreak = false; + while (token === 15 || token === 14) { + lineBreak = lineBreak || token === 14; + token = scanner2.scan(); + } + hasError = token === 16 || scanner2.getTokenError() !== 0; + return token; + } + var editOperations = []; + function addEdit(text, startOffset, endOffset2) { + if (!hasError && (!range || startOffset < rangeEnd && endOffset2 > rangeStart) && documentText.substring(startOffset, endOffset2) !== text) { + editOperations.push({ offset: startOffset, length: endOffset2 - startOffset, content: text }); + } + } + var firstToken = scanNext(); + if (firstToken !== 17) { + var firstTokenStart = scanner2.getTokenOffset() + formatTextStart; + var initialIndent = repeat(indentValue, initialIndentLevel); + addEdit(initialIndent, formatTextStart, firstTokenStart); + } + while (firstToken !== 17) { + var firstTokenEnd = scanner2.getTokenOffset() + scanner2.getTokenLength() + formatTextStart; + var secondToken = scanNext(); + var replaceContent = ""; + var needsLineBreak = false; + while (!lineBreak && (secondToken === 12 || secondToken === 13)) { + var commentTokenStart = scanner2.getTokenOffset() + formatTextStart; + addEdit(" ", firstTokenEnd, commentTokenStart); + firstTokenEnd = scanner2.getTokenOffset() + scanner2.getTokenLength() + formatTextStart; + needsLineBreak = secondToken === 12; + replaceContent = needsLineBreak ? newLineAndIndent() : ""; + secondToken = scanNext(); + } + if (secondToken === 2) { + if (firstToken !== 1) { + indentLevel--; + replaceContent = newLineAndIndent(); + } + } else if (secondToken === 4) { + if (firstToken !== 3) { + indentLevel--; + replaceContent = newLineAndIndent(); + } + } else { + switch (firstToken) { + case 3: + case 1: + indentLevel++; + replaceContent = newLineAndIndent(); + break; + case 5: + case 12: + replaceContent = newLineAndIndent(); + break; + case 13: + if (lineBreak) { + replaceContent = newLineAndIndent(); + } else if (!needsLineBreak) { + replaceContent = " "; + } + break; + case 6: + if (!needsLineBreak) { + replaceContent = " "; + } + break; + case 10: + if (secondToken === 6) { + if (!needsLineBreak) { + replaceContent = ""; + } + break; + } + case 7: + case 8: + case 9: + case 11: + case 2: + case 4: + if (secondToken === 12 || secondToken === 13) { + if (!needsLineBreak) { + replaceContent = " "; + } + } else if (secondToken !== 5 && secondToken !== 17) { + hasError = true; + } + break; + case 16: + hasError = true; + break; + } + if (lineBreak && (secondToken === 12 || secondToken === 13)) { + replaceContent = newLineAndIndent(); + } + } + if (secondToken === 17) { + replaceContent = options.insertFinalNewline ? eol : ""; + } + var secondTokenStart = scanner2.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 === " ") { + 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; +} +var init_format = __esm({ + "node_modules/jsonc-parser/lib/esm/impl/format.js"() { + init_scanner(); + "use strict"; + } +}); + +// node_modules/jsonc-parser/lib/esm/impl/parser.js +function parse2(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 !== null) { + currentParent[currentProperty] = value; + } + } + var visitor = { + onObjectBegin: function() { + var object = {}; + onValue(object); + previousParents.push(currentParent); + currentParent = object; + currentProperty = null; + }, + onObjectProperty: function(name2) { + currentProperty = name2; + }, + 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, offset, length }); + } + }; + visit(text, visitor, options); + return currentParent[0]; +} +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 }; + 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, length: -1, parent: currentParent, children: [] }); + }, + onObjectProperty: function(name2, offset, length) { + currentParent = onValue({ type: "property", offset, length: -1, parent: currentParent, children: [] }); + currentParent.children.push({ type: "string", value: name2, offset, length, parent: currentParent }); + }, + onObjectEnd: function(offset, length) { + ensurePropertyComplete(offset + length); + currentParent.length = offset + length - currentParent.offset; + currentParent = currentParent.parent; + ensurePropertyComplete(offset + length); + }, + onArrayBegin: function(offset, length) { + currentParent = onValue({ type: "array", 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: getNodeType(value), offset, length, parent: currentParent, 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, offset, length }); + } + }; + visit(text, visitor, options); + var result = currentParent.children[0]; + if (result) { + delete result.parent; + } + return result; +} +function findNodeAtLocation(root, path36) { + if (!root) { + return void 0; + } + var node = root; + for (var _i = 0, path_1 = path36; _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 _a2 = 0, _b = node.children; _a2 < _b.length; _a2++) { + var propertyNode = _b[_a2]; + 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; +} +function visit(text, visitor, options) { + if (options === void 0) { + options = ParseOptions.DEFAULT; + } + var _scanner = 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: + handleError(14); + break; + case 5: + handleError(15); + break; + case 3: + handleError(13); + break; + case 1: + if (!disallowComments) { + handleError(11); + } + break; + case 2: + handleError(12); + break; + case 6: + handleError(16); + break; + } + switch (token) { + case 12: + case 13: + if (disallowComments) { + handleError(10); + } else { + onComment(); + } + break; + case 16: + handleError(1); + break; + case 15: + case 14: + 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) { + 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: + var tokenValue = _scanner.getTokenValue(); + var value = Number(tokenValue); + if (isNaN(value)) { + handleError(2); + value = 0; + } + onLiteralValue(value); + break; + case 7: + onLiteralValue(null); + break; + case 8: + onLiteralValue(true); + break; + case 9: + onLiteralValue(false); + break; + default: + return false; + } + scanNext(); + return true; + } + function parseProperty() { + if (_scanner.getToken() !== 10) { + handleError(3, [], [2, 5]); + return false; + } + parseString(false); + if (_scanner.getToken() === 6) { + onSeparator(":"); + scanNext(); + if (!parseValue()) { + handleError(4, [], [2, 5]); + } + } else { + handleError(5, [], [2, 5]); + } + return true; + } + function parseObject() { + onObjectBegin(); + scanNext(); + var needsComma = false; + while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) { + if (_scanner.getToken() === 5) { + if (!needsComma) { + handleError(4, [], []); + } + onSeparator(","); + scanNext(); + if (_scanner.getToken() === 2 && allowTrailingComma) { + break; + } + } else if (needsComma) { + handleError(6, [], []); + } + if (!parseProperty()) { + handleError(4, [], [2, 5]); + } + needsComma = true; + } + onObjectEnd(); + if (_scanner.getToken() !== 2) { + handleError(7, [2], []); + } else { + scanNext(); + } + return true; + } + function parseArray() { + onArrayBegin(); + scanNext(); + var needsComma = false; + while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) { + if (_scanner.getToken() === 5) { + if (!needsComma) { + handleError(4, [], []); + } + onSeparator(","); + scanNext(); + if (_scanner.getToken() === 4 && allowTrailingComma) { + break; + } + } else if (needsComma) { + handleError(6, [], []); + } + if (!parseValue()) { + handleError(4, [], [4, 5]); + } + needsComma = true; + } + onArrayEnd(); + if (_scanner.getToken() !== 4) { + handleError(8, [4], []); + } else { + scanNext(); + } + return true; + } + function parseValue() { + switch (_scanner.getToken()) { + case 3: + return parseArray(); + case 1: + return parseObject(); + case 10: + return parseString(true); + default: + return parseLiteral(); + } + } + scanNext(); + if (_scanner.getToken() === 17) { + if (options.allowEmptyContent) { + return true; + } + handleError(4, [], []); + return false; + } + if (!parseValue()) { + handleError(4, [], []); + return false; + } + if (_scanner.getToken() !== 17) { + handleError(9, [], []); + } + return true; +} +function getNodeType(value) { + switch (typeof value) { + case "boolean": + return "boolean"; + case "number": + return "number"; + case "string": + return "string"; + case "object": { + if (!value) { + return "null"; + } else if (Array.isArray(value)) { + return "array"; + } + return "object"; + } + default: + return "null"; + } +} +var ParseOptions; +var init_parser = __esm({ + "node_modules/jsonc-parser/lib/esm/impl/parser.js"() { + init_scanner(); + "use strict"; + (function(ParseOptions2) { + ParseOptions2.DEFAULT = { + allowTrailingComma: false + }; + })(ParseOptions || (ParseOptions = {})); + } +}); + +// node_modules/jsonc-parser/lib/esm/impl/edit.js +function setProperty(text, originalPath, value, options) { + var _a2; + var path36 = originalPath.slice(); + var errors = []; + var root = parseTree(text, errors); + var parent = void 0; + var lastSegment = void 0; + while (path36.length > 0) { + lastSegment = path36.pop(); + parent = findNodeAtLocation(root, path36); + if (parent === void 0 && value !== void 0) { + if (typeof lastSegment === "string") { + value = (_a2 = {}, _a2[lastSegment] = value, _a2); + } else { + value = [value]; + } + } else { + break; + } + } + if (!parent) { + if (value === void 0) { + 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) }, options); + } else if (parent.type === "object" && typeof lastSegment === "string" && Array.isArray(parent.children)) { + var existing = findNodeAtLocation(parent, [lastSegment]); + if (existing !== void 0) { + if (value === void 0) { + 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) { + var previous = parent.children[propertyIndex - 1]; + removeBegin = previous.offset + previous.length; + } else { + removeBegin = parent.offset + 1; + if (parent.children.length > 1) { + var next = parent.children[1]; + removeEnd = next.offset; + } + } + return withFormatting(text, { offset: removeBegin, length: removeEnd - removeBegin, content: "" }, options); + } else { + return withFormatting(text, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, options); + } + } else { + if (value === void 0) { + return []; + } + var newProperty = JSON.stringify(lastSegment) + ": " + JSON.stringify(value); + var index = options.getInsertionIndex ? options.getInsertionIndex(parent.children.map(function(p) { + return p.children[0].value; + })) : parent.children.length; + var edit2 = void 0; + if (index > 0) { + var previous = parent.children[index - 1]; + edit2 = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty }; + } else if (parent.children.length === 0) { + edit2 = { offset: parent.offset + 1, length: 0, content: newProperty }; + } else { + edit2 = { offset: parent.offset + 1, length: 0, content: newProperty + "," }; + } + return withFormatting(text, edit2, options); + } + } else if (parent.type === "array" && typeof lastSegment === "number" && Array.isArray(parent.children)) { + var insertIndex = lastSegment; + if (insertIndex === -1) { + var newProperty = "" + JSON.stringify(value); + var edit2 = void 0; + if (parent.children.length === 0) { + edit2 = { offset: parent.offset + 1, length: 0, content: newProperty }; + } else { + var previous = parent.children[parent.children.length - 1]; + edit2 = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty }; + } + return withFormatting(text, edit2, options); + } else if (value === void 0 && parent.children.length >= 0) { + var removalIndex = lastSegment; + var toRemove = parent.children[removalIndex]; + var edit2 = void 0; + if (parent.children.length === 1) { + edit2 = { offset: parent.offset + 1, length: parent.length - 2, content: "" }; + } else if (parent.children.length - 1 === removalIndex) { + var previous = parent.children[removalIndex - 1]; + var offset = previous.offset + previous.length; + var parentEndOffset = parent.offset + parent.length; + edit2 = { offset, length: parentEndOffset - 2 - offset, content: "" }; + } else { + edit2 = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: "" }; + } + return withFormatting(text, edit2, options); + } else if (value !== void 0) { + var edit2 = void 0; + var newProperty = "" + JSON.stringify(value); + if (!options.isArrayInsertion && parent.children.length > lastSegment) { + var toModify = parent.children[lastSegment]; + edit2 = { offset: toModify.offset, length: toModify.length, content: newProperty }; + } else if (parent.children.length === 0 || lastSegment === 0) { + edit2 = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + "," }; + } else { + var index = lastSegment > parent.children.length ? parent.children.length : lastSegment; + var previous = parent.children[index - 1]; + edit2 = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty }; + } + return withFormatting(text, edit2, options); + } else { + throw new Error("Can not " + (value === void 0 ? "remove" : options.isArrayInsertion ? "insert" : "modify") + " Array index " + insertIndex + " as length is not sufficient"); + } + } else { + throw new Error("Can not add " + (typeof lastSegment !== "number" ? "index" : "property") + " to parent of type " + parent.type); + } +} +function withFormatting(text, edit2, options) { + if (!options.formattingOptions) { + return [edit2]; + } + var newText = applyEdit(text, edit2); + var begin = edit2.offset; + var end = edit2.offset + edit2.content.length; + if (edit2.length === 0 || edit2.content.length === 0) { + while (begin > 0 && !isEOL(newText, begin - 1)) { + begin--; + } + while (end < newText.length && !isEOL(newText, end)) { + end++; + } + } + var edits = format(newText, { offset: begin, length: end - begin }, options.formattingOptions); + 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; + } + var editLength = text.length - (newText.length - end) - begin; + return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }]; +} +function applyEdit(text, edit2) { + return text.substring(0, edit2.offset) + edit2.content + text.substring(edit2.offset + edit2.length); +} +var init_edit = __esm({ + "node_modules/jsonc-parser/lib/esm/impl/edit.js"() { + init_format(); + init_parser(); + "use strict"; + } +}); + +// node_modules/jsonc-parser/lib/esm/main.js +function modify(text, path36, value, options) { + return setProperty(text, path36, value, options); +} +function applyEdits(text, edits) { + for (var i = edits.length - 1; i >= 0; i--) { + text = applyEdit(text, edits[i]); + } + return text; +} +var parse3; +var init_main3 = __esm({ + "node_modules/jsonc-parser/lib/esm/main.js"() { + init_format(); + init_edit(); + init_scanner(); + init_parser(); + "use strict"; + parse3 = parse2; + } +}); + +// src/configuration/util.ts +function parseContentFromFile(filepath, onError) { + if (!filepath || !import_fs2.default.existsSync(filepath)) + return { contents: {} }; + let content; + let uri = URI.file(filepath).toString(); + try { + content = import_fs2.default.readFileSync(filepath, "utf8"); + } catch (_e) { + content = ""; + } + let [errors, contents] = parseConfiguration(content); + if (errors && errors.length) { + onError(convertErrors(uri, content, errors)); + } + return { contents }; +} +function parseConfiguration(content) { + if (content.length == 0) + return [[], {}]; + let errors = []; + let data = parse3(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 (!objectLiteral(obj)) + return obj; + if (emptyObject(obj)) + return {}; + let dest = {}; + for (let key of Object.keys(obj)) { + if (split && key.includes(".")) { + 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)]; +} +function convertErrors(uri, content, errors) { + let items = []; + let document2 = TextDocument2.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: document2.positionAt(err.offset), + end: document2.positionAt(err.offset + err.length) + }; + let loc = import_vscode_languageserver_protocol7.Location.create(uri, range); + items.push({ location: loc, message: msg }); + } + return items; +} +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; + } else { + conflictReporter(`Ignoring ${key} as ${segments.join(".")} is ${JSON.stringify(curr)}`); + } +} +function removeFromValueTree(valueTree, key) { + const segments = key.split("."); + doRemoveFromValueTree(valueTree, segments); +} +function doRemoveFromValueTree(valueTree, segments) { + const first = segments.shift(); + if (segments.length === 0) { + delete valueTree[first]; + return; + } + if (Object.keys(valueTree).includes(first)) { + 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(config2, path37) { + let current = config2; + for (let i = 0; i < path37.length; i++) { + if (typeof current !== "object" || current === null) { + return void 0; + } + current = current[path37[i]]; + } + return current; + } + const path36 = settingPath.split("."); + const result = accessSetting(config, path36); + return typeof result === "undefined" ? defaultValue : result; +} +function loadDefaultConfigurations() { + let file = import_path2.default.join(pluginRoot, "data/schema.json"); + if (!import_fs2.default.existsSync(file)) { + console.error("schema.json not found, reinstall coc.nvim to fix this!"); + return { contents: {} }; + } + let content = import_fs2.default.readFileSync(file, "utf8"); + let { properties } = JSON.parse(content); + let config = {}; + Object.keys(properties).forEach((key) => { + let value = properties[key].default; + if (value !== void 0) { + addToValueTree(config, key, value, (message) => { + logger13.error(message); + }); + } + }); + return { contents: config }; +} +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 (objectLiteral(val)) { + keys.push(...getKeys(val, newKey)); + } + } + return keys; +} +function getChangedKeys(from, to) { + let keys = []; + let fromKeys = getKeys(from); + let toKeys = getKeys(to); + const added = toKeys.filter((key) => !fromKeys.includes(key)); + const removed = fromKeys.filter((key) => !toKeys.includes(key)); + keys.push(...added); + keys.push(...removed); + for (const key of fromKeys) { + if (!toKeys.includes(key)) + continue; + const value1 = getConfigurationValue(from, key); + const value2 = getConfigurationValue(to, key); + if (!equals(value1, value2)) { + keys.push(key); + } + } + return keys; +} +var import_vscode_languageserver_protocol7, import_fs2, import_path2, logger13, pluginRoot; +var init_util2 = __esm({ + "src/configuration/util.ts"() { + import_vscode_languageserver_protocol7 = __toModule(require_main2()); + init_main2(); + init_main3(); + init_is(); + init_object(); + import_fs2 = __toModule(require("fs")); + init_esm2(); + import_path2 = __toModule(require("path")); + logger13 = require_logger2()("configuration-util"); + pluginRoot = false ? resolve(__dirname, "../..") : (0, import_path2.dirname)(__dirname); + } +}); + +// src/configuration/model.ts +var ConfigurationModel; +var init_model = __esm({ + "src/configuration/model.ts"() { + init_is(); + init_object(); + init_util2(); + ConfigurationModel = class { + constructor(_contents = {}) { + this._contents = _contents; + } + get contents() { + return this._contents; + } + clone() { + return new ConfigurationModel(deepClone(this._contents)); + } + getValue(section2) { + let res = section2 ? getConfigurationValue(this.contents, section2) : this.contents; + return res; + } + merge(...others) { + const contents = 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 (objectLiteral(source[key]) && objectLiteral(target[key])) { + this.mergeContents(source[key], target[key]); + continue; + } + } + source[key] = deepClone(target[key]); + } + } + setValue(key, value) { + addToValueTree(this.contents, key, value, (message) => { + console.error(message); + }); + } + removeValue(key) { + removeFromValueTree(this.contents, key); + } + }; + } +}); + +// src/configuration/configuration.ts +var Configuration; +var init_configuration = __esm({ + "src/configuration/configuration.ts"() { + init_model(); + Configuration = class { + constructor(_defaultConfiguration, _userConfiguration, _workspaceConfiguration, _memoryConfiguration = new 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(section2) { + let configuration = this.getConsolidateConfiguration(); + return configuration.getValue(section2); + } + 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 + } + }; + } + }; + } +}); + +// node_modules/concat-map/index.js +var require_concat_map = __commonJS({ + "node_modules/concat-map/index.js"(exports2, module2) { + module2.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]"; + }; + } +}); + +// node_modules/balanced-match/index.js +var require_balanced_match = __commonJS({ + "node_modules/balanced-match/index.js"(exports2, module2) { + "use strict"; + module2.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) { + if (a === b) { + return [ai, bi]; + } + 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; + } + } +}); + +// node_modules/brace-expansion/index.js +var require_brace_expansion = __commonJS({ + "node_modules/brace-expansion/index.js"(exports2, module2) { + var concatMap = require_concat_map(); + var balanced = require_balanced_match(); + module2.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("."); + } + 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 []; + if (str.substr(0, 2) === "{}") { + str = "\\{\\}" + str.substr(2); + } + return expand(escapeBraces(str), true).map(unescapeBraces); + } + 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) { + 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) { + 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; + }); + } + } + } + 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 pad2 = 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 (pad2) { + 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; + } + } +}); + +// node_modules/minimatch/minimatch.js +var require_minimatch = __commonJS({ + "node_modules/minimatch/minimatch.js"(exports2, module2) { + module2.exports = minimatch8; + minimatch8.Minimatch = Minimatch2; + var path36 = { sep: "/" }; + try { + path36 = require("path"); + } catch (er) { + } + var GLOBSTAR = minimatch8.GLOBSTAR = Minimatch2.GLOBSTAR = {}; + var expand = require_brace_expansion(); + var plTypes = { + "!": { open: "(?:(?!(?:", close: "))[^/]*?)" }, + "?": { open: "(?:", close: ")?" }, + "+": { open: "(?:", close: ")+" }, + "*": { open: "(?:", close: ")*" }, + "@": { open: "(?:", close: ")" } + }; + var qmark = "[^/]"; + var star = qmark + "*?"; + var twoStarDot = "(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?"; + var twoStarNoDot = "(?:(?!(?:\\/|^)\\.).)*?"; + var reSpecials = charSet("().*{}+?[]^$\\!"); + function charSet(s) { + return s.split("").reduce(function(set, c) { + set[c] = true; + return set; + }, {}); + } + var slashSplit = /\/+/; + minimatch8.filter = filter; + function filter(pattern, options) { + options = options || {}; + return function(p, i, list2) { + return minimatch8(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; + } + minimatch8.defaults = function(def) { + if (!def || !Object.keys(def).length) + return minimatch8; + var orig = minimatch8; + var m = function minimatch9(p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)); + }; + m.Minimatch = function Minimatch3(pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)); + }; + return m; + }; + Minimatch2.defaults = function(def) { + if (!def || !Object.keys(def).length) + return Minimatch2; + return minimatch8.defaults(def).Minimatch; + }; + function minimatch8(p, pattern, options) { + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required"); + } + if (!options) + options = {}; + if (!options.nocomment && pattern.charAt(0) === "#") { + return false; + } + if (pattern.trim() === "") + return p === ""; + return new Minimatch2(pattern, options).match(p); + } + function Minimatch2(pattern, options) { + if (!(this instanceof Minimatch2)) { + return new Minimatch2(pattern, options); + } + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required"); + } + if (!options) + options = {}; + pattern = pattern.trim(); + if (path36.sep !== "/") { + pattern = pattern.split(path36.sep).join("/"); + } + this.options = options; + this.set = []; + this.pattern = pattern; + this.regexp = null; + this.negate = false; + this.comment = false; + this.empty = false; + this.make(); + } + Minimatch2.prototype.debug = function() { + }; + Minimatch2.prototype.make = make; + function make() { + if (this._made) + return; + var pattern = this.pattern; + var options = this.options; + if (!options.nocomment && pattern.charAt(0) === "#") { + this.comment = true; + return; + } + if (!pattern) { + this.empty = true; + return; + } + this.parseNegate(); + var set = this.globSet = this.braceExpand(); + if (options.debug) + this.debug = console.error; + this.debug(this.pattern, set); + set = this.globParts = set.map(function(s) { + return s.split(slashSplit); + }); + this.debug(this.pattern, set); + set = set.map(function(s, si, set2) { + return s.map(this.parse, this); + }, this); + this.debug(this.pattern, set); + set = set.filter(function(s) { + return s.indexOf(false) === -1; + }); + this.debug(this.pattern, set); + this.set = set; + } + Minimatch2.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; + } + minimatch8.braceExpand = function(pattern, options) { + return braceExpand(pattern, options); + }; + Minimatch2.prototype.braceExpand = braceExpand; + function braceExpand(pattern, options) { + if (!options) { + if (this instanceof Minimatch2) { + 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(/\{.*\}/)) { + return [pattern]; + } + return expand(pattern); + } + Minimatch2.prototype.parse = parse5; + var SUBPARSE = {}; + function parse5(pattern, isSub) { + if (pattern.length > 1024 * 64) { + throw new TypeError("pattern is too long"); + } + var options = this.options; + if (!options.noglobstar && pattern === "**") + return GLOBSTAR; + if (pattern === "") + return ""; + var re = ""; + var hasMagic = !!options.nocase; + var escaping = false; + var patternListStack = []; + var negativeLists = []; + var stateChar; + var inClass = false; + var reClassStart = -1; + var classStart = -1; + var patternStart = pattern.charAt(0) === "." ? "" : options.dot ? "(?!(?:^|\\/)\\.{1,2}(?:$|\\/))" : "(?!\\.)"; + var self2 = this; + function clearStateChar() { + if (stateChar) { + switch (stateChar) { + case "*": + re += star; + hasMagic = true; + break; + case "?": + re += qmark; + hasMagic = true; + break; + default: + re += "\\" + stateChar; + break; + } + self2.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 %s %s %j", pattern, i, re, c); + if (escaping && reSpecials[c]) { + re += "\\" + c; + escaping = false; + continue; + } + switch (c) { + case "/": + return false; + case "\\": + clearStateChar(); + escaping = true; + continue; + case "?": + case "*": + case "+": + case "@": + case "!": + this.debug("%s %s %s %j <-- stateChar", pattern, i, re, c); + if (inClass) { + this.debug(" in class"); + if (c === "!" && i === classStart + 1) + c = "^"; + re += c; + continue; + } + self2.debug("call clearStateChar %j", stateChar); + clearStateChar(); + stateChar = c; + 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 + }); + 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(); + 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; + case "[": + clearStateChar(); + if (inClass) { + re += "\\" + c; + continue; + } + inClass = true; + classStart = i; + reClassStart = re.length; + re += c; + continue; + case "]": + if (i === classStart + 1 || !inClass) { + re += "\\" + c; + escaping = false; + continue; + } + if (inClass) { + var cs = pattern.substring(classStart + 1, i); + try { + RegExp("[" + cs + "]"); + } catch (er) { + var sp = this.parse(cs, SUBPARSE); + re = re.substr(0, reClassStart) + "\\[" + sp[0] + "\\]"; + hasMagic = hasMagic || sp[1]; + inClass = false; + continue; + } + } + hasMagic = true; + inClass = false; + re += c; + continue; + default: + clearStateChar(); + if (escaping) { + escaping = false; + } else if (reSpecials[c] && !(c === "^" && inClass)) { + re += "\\"; + } + re += c; + } + } + if (inClass) { + cs = pattern.substr(classStart + 1); + sp = this.parse(cs, SUBPARSE); + re = re.substr(0, reClassStart) + "\\[" + sp[0]; + hasMagic = hasMagic || sp[1]; + } + for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + pl.open.length); + this.debug("setting tail", re, pl); + tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function(_, $1, $2) { + if (!$2) { + $2 = "\\"; + } + 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; + } + clearStateChar(); + if (escaping) { + re += "\\\\"; + } + var addPatternStart = false; + switch (re.charAt(0)) { + case ".": + case "[": + case "(": + addPatternStart = true; + } + 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; + 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 (re !== "" && hasMagic) { + re = "(?=.)" + re; + } + if (addPatternStart) { + re = patternStart + re; + } + if (isSub === SUBPARSE) { + return [re, hasMagic]; + } + if (!hasMagic) { + return globUnescape(pattern); + } + var flags = options.nocase ? "i" : ""; + try { + var regExp = new RegExp("^" + re + "$", flags); + } catch (er) { + return new RegExp("$."); + } + regExp._glob = pattern; + regExp._src = re; + return regExp; + } + minimatch8.makeRe = function(pattern, options) { + return new Minimatch2(pattern, options || {}).makeRe(); + }; + Minimatch2.prototype.makeRe = makeRe; + function makeRe() { + if (this.regexp || this.regexp === false) + return this.regexp; + 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("|"); + re = "^(?:" + re + ")$"; + if (this.negate) + re = "^(?!" + re + ").*$"; + try { + this.regexp = new RegExp(re, flags); + } catch (ex) { + this.regexp = false; + } + return this.regexp; + } + minimatch8.match = function(list2, pattern, options) { + options = options || {}; + var mm = new Minimatch2(pattern, options); + list2 = list2.filter(function(f) { + return mm.match(f); + }); + if (mm.options.nonull && !list2.length) { + list2.push(pattern); + } + return list2; + }; + Minimatch2.prototype.match = match; + function match(f, partial) { + this.debug("match", f, this.pattern); + if (this.comment) + return false; + if (this.empty) + return f === ""; + if (f === "/" && partial) + return true; + var options = this.options; + if (path36.sep !== "/") { + f = f.split(path36.sep).join("/"); + } + f = f.split(slashSplit); + this.debug(this.pattern, "split", f); + var set = this.set; + this.debug(this.pattern, "set", set); + 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; + } + } + if (options.flipNegate) + return false; + return this.negate; + } + Minimatch2.prototype.matchOne = function(file, pattern, partial) { + var options = this.options; + this.debug("matchOne", { "this": this, file, 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); + if (p === false) + return false; + if (p === GLOBSTAR) { + this.debug("GLOBSTAR", [pattern, p, f]); + var fr = fi; + var pr = pi + 1; + if (pr === pl) { + this.debug("** at the end"); + for (; fi < fl; fi++) { + if (file[fi] === "." || file[fi] === ".." || !options.dot && file[fi].charAt(0) === ".") + return false; + } + return true; + } + while (fr < fl) { + var swallowee = file[fr]; + this.debug("\nglobstar while", file, fr, pattern, pr, swallowee); + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug("globstar found match!", fr, fl, swallowee); + return true; + } else { + if (swallowee === "." || swallowee === ".." || !options.dot && swallowee.charAt(0) === ".") { + this.debug("dot detected!", file, fr, pattern, pr); + break; + } + this.debug("globstar swallow a segment, and continue"); + fr++; + } + } + if (partial) { + this.debug("\n>>> no match, partial?", file, fr, pattern, pr); + if (fr === fl) + return true; + } + return false; + } + 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; + } + if (fi === fl && pi === pl) { + return true; + } else if (fi === fl) { + return partial; + } else if (pi === pl) { + var emptyFileEnd = fi === fl - 1 && file[fi] === ""; + return emptyFileEnd; + } + throw new Error("wtf?"); + }; + function globUnescape(s) { + return s.replace(/\\(.)/g, "$1"); + } + function regExpEscape(s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + } + } +}); + +// src/util/fs.ts +async function statAsync(filepath) { + let stat = null; + try { + stat = await import_fs_extra.default.stat(filepath); + } catch (e) { + } + return stat; +} +function renameAsync(oldPath, newPath) { + return new Promise((resolve3, reject) => { + import_fs_extra.default.rename(oldPath, newPath, (err) => { + if (err) + return reject(err); + resolve3(); + }); + }); +} +function resolveRoot(folder, subs, cwd, bottomup = false, checkCwd = true) { + let home = import_os.default.homedir(); + let dir = fixDriver(folder); + if (isParentFolder(dir, home, true)) + return null; + if (checkCwd && cwd && isParentFolder(cwd, dir, true) && inDirectory(cwd, subs)) + return cwd; + let parts = dir.split(import_path3.default.sep); + if (bottomup) { + while (parts.length > 0) { + let dir2 = parts.join(import_path3.default.sep); + if (dir2 == home) { + break; + } + if (dir2 != home && inDirectory(dir2, subs)) { + return dir2; + } + parts.pop(); + } + return null; + } else { + let curr = [parts.shift()]; + for (let part of parts) { + curr.push(part); + let dir2 = curr.join(import_path3.default.sep); + if (dir2 != home && inDirectory(dir2, subs)) { + return dir2; + } + } + return null; + } +} +function inDirectory(dir, subs) { + try { + let files = import_fs_extra.default.readdirSync(dir); + for (let pattern of subs) { + let is_wildcard = pattern.includes("*"); + let res = is_wildcard ? import_minimatch.default.match(files, pattern, { nobrace: true, noext: true, nocomment: true, nonegate: true, dot: true }).length !== 0 : files.includes(pattern); + if (res) + return true; + } + } catch (e) { + } + return false; +} +function findUp(name2, cwd) { + let root = import_path3.default.parse(cwd).root; + let subs = Array.isArray(name2) ? name2 : [name2]; + while (cwd && cwd !== root) { + let find = inDirectory(cwd, subs); + if (find) { + for (let sub of subs) { + let filepath = import_path3.default.join(cwd, sub); + if (import_fs_extra.default.existsSync(filepath)) { + return filepath; + } + } + } + cwd = import_path3.default.dirname(cwd); + } + return null; +} +function readFile(fullpath, encoding) { + return new Promise((resolve3, reject) => { + import_fs_extra.default.readFile(fullpath, encoding, (err, content) => { + if (err) + reject(err); + resolve3(content); + }); + }); +} +function getFileLineCount(filepath) { + let i; + let count = 0; + return new Promise((resolve3, reject) => { + import_fs_extra.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", () => resolve3(count)); + }); +} +function readFileLines(fullpath, start, end) { + if (!import_fs_extra.default.existsSync(fullpath)) { + return Promise.reject(new Error(`file does not exist: ${fullpath}`)); + } + let res = []; + const rl = import_readline.default.createInterface({ + input: import_fs_extra.default.createReadStream(fullpath, { encoding: "utf8" }), + crlfDelay: Infinity, + terminal: false + }); + let n = 0; + return new Promise((resolve3, reject) => { + rl.on("line", (line) => { + if (n == 0 && line.startsWith("\uFEFF")) { + line = line.slice(1); + } + if (n >= start && n <= end) { + res.push(line); + } + if (n == end) { + rl.close(); + } + n = n + 1; + }); + rl.on("close", () => { + resolve3(res); + }); + rl.on("error", reject); + }); +} +function readFileLine(fullpath, count) { + if (!import_fs_extra.default.existsSync(fullpath)) { + return Promise.reject(new Error(`file does not exist: ${fullpath}`)); + } + const rl = import_readline.default.createInterface({ + input: import_fs_extra.default.createReadStream(fullpath, { encoding: "utf8" }), + crlfDelay: Infinity, + terminal: false + }); + let n = 0; + return new Promise((resolve3, reject) => { + rl.on("line", (line) => { + if (n == count) { + if (n == 0 && line.startsWith("\uFEFF")) { + line = line.slice(1); + } + rl.close(); + resolve3(line); + return; + } + n = n + 1; + }); + rl.on("error", reject); + }); +} +async function writeFile(fullpath, content) { + await import_fs_extra.default.writeFile(fullpath, content, { encoding: "utf8" }); +} +function isFile(uri) { + return uri.startsWith("file:"); +} +function isParentFolder(folder, filepath, checkEqual = false) { + let pdir = fixDriver(import_path3.default.resolve(import_path3.default.normalize(folder))); + let dir = fixDriver(import_path3.default.resolve(import_path3.default.normalize(filepath))); + if (pdir == "//") + pdir = "/"; + if (pdir == dir) + return checkEqual ? true : false; + if (pdir.endsWith(import_path3.default.sep)) + return dir.startsWith(pdir); + return dir.startsWith(pdir) && dir[pdir.length] == import_path3.default.sep; +} +function fixDriver(filepath) { + if (import_os.default.platform() != "win32" || filepath[1] != ":") + return filepath; + return filepath[0].toUpperCase() + filepath.slice(1); +} +var import_child_process2, import_fs_extra, import_net, import_os, import_path3, import_readline, import_util9, import_minimatch, logger14; +var init_fs = __esm({ + "src/util/fs.ts"() { + import_child_process2 = __toModule(require("child_process")); + import_fs_extra = __toModule(require_lib5()); + import_net = __toModule(require("net")); + import_os = __toModule(require("os")); + import_path3 = __toModule(require("path")); + import_readline = __toModule(require("readline")); + import_util9 = __toModule(require("util")); + import_minimatch = __toModule(require_minimatch()); + logger14 = require_logger2()("util-fs"); + } +}); + +// src/configuration/index.ts +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; +} +var import_os2, import_fs3, import_path4, import_vscode_languageserver_protocol8, logger15, Configurations; +var init_configuration2 = __esm({ + "src/configuration/index.ts"() { + import_os2 = __toModule(require("os")); + import_fs3 = __toModule(require("fs")); + import_path4 = __toModule(require("path")); + import_vscode_languageserver_protocol8 = __toModule(require_main2()); + init_esm2(); + init_types(); + init_object(); + init_util(); + init_configuration(); + init_model(); + init_util2(); + init_is(); + init_fs(); + logger15 = require_logger2()("configurations"); + Configurations = class { + constructor(userConfigFile, _proxy) { + this.userConfigFile = userConfigFile; + this._proxy = _proxy; + this._errorItems = []; + this._folderConfigurations = new Map(); + this._onError = new import_vscode_languageserver_protocol8.Emitter(); + this._onChange = new import_vscode_languageserver_protocol8.Emitter(); + this.disposables = []; + this.onError = this._onError.event; + this.onDidChange = this._onChange.event; + let user = this.parseContentFromFile(userConfigFile); + let data = { + defaults: loadDefaultConfigurations(), + user, + workspace: { contents: {} } + }; + this._configuration = Configurations.parse(data); + this.watchFile(userConfigFile, ConfigurationTarget.User); + let folderConfigFile = import_path4.default.join(process.cwd(), `.vim/${CONFIG_FILE_NAME}`); + if (folderConfigFile != userConfigFile && import_fs3.default.existsSync(folderConfigFile)) { + this.addFolderFile(folderConfigFile); + } + } + parseContentFromFile(filepath) { + if (!filepath) + return { contents: {} }; + let uri = URI.file(filepath).toString(); + this._errorItems = this._errorItems.filter((o) => o.location.uri != uri); + let res = parseContentFromFile(filepath, (errors) => { + this._errorItems.push(...errors); + }); + this._onError.fire(this._errorItems); + return res; + } + get errorItems() { + return this._errorItems; + } + get foldConfigurations() { + return this._folderConfigurations; + } + extendsDefaults(props) { + let { defaults: defaults2 } = this._configuration; + let { contents } = defaults2; + contents = deepClone(contents); + Object.keys(props).forEach((key) => { + addToValueTree(contents, key, props[key], (msg) => { + logger15.error(msg); + }); + }); + let data = { + defaults: { contents }, + user: this._configuration.user, + workspace: this._configuration.workspace + }; + this._configuration = Configurations.parse(data); + } + 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 === void 0) { + model.removeValue(key); + } else if (objectLiteral(val)) { + for (let k of Object.keys(val)) { + model.setValue(`${key}.${k}`, val[k]); + } + } else { + model.setValue(key, val); + } + }); + this.changeConfiguration(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 (import_path4.default.resolve(filepath, "../..") == import_os2.default.homedir()) + return; + let model = this.parseContentFromFile(filepath); + this.watchFile(filepath, ConfigurationTarget.Workspace); + this.changeConfiguration(ConfigurationTarget.Workspace, model, filepath); + } + watchFile(filepath, target) { + if (!import_fs3.default.existsSync(filepath) || global.hasOwnProperty("__TEST__")) + return; + let disposable = watchFile(filepath, () => { + let model = this.parseContentFromFile(filepath); + this.changeConfiguration(target, model, filepath); + }); + this.disposables.push(disposable); + } + changeConfiguration(target, model, configFile) { + let { defaults: defaults2, user, workspace } = this._configuration; + let { workspaceConfigFile } = this; + let data = { + defaults: target == ConfigurationTarget.Global ? model : defaults2, + user: target == ConfigurationTarget.User ? model : user, + workspace: target == ConfigurationTarget.Workspace ? model : workspace + }; + let configuration = Configurations.parse(data); + let changed = getChangedKeys(this._configuration.getValue(), configuration.getValue()); + if (target == ConfigurationTarget.Workspace && configFile) { + this._folderConfigurations.set(configFile, new ConfigurationModel(model.contents)); + this.workspaceConfigFile = configFile; + } + if (changed.length == 0) + return; + this._configuration = configuration; + this._onChange.fire({ + affectsConfiguration: (section2, resource) => { + if (!resource || target != ConfigurationTarget.Workspace) + return changed.includes(section2); + let u = URI.parse(resource); + if (u.scheme !== "file") + return changed.includes(section2); + let filepath = u.fsPath; + let preRoot = workspaceConfigFile ? import_path4.default.resolve(workspaceConfigFile, "../..") : ""; + if (configFile && !isParentFolder(preRoot, filepath, true) && !isParentFolder(import_path4.default.resolve(configFile, "../.."), filepath)) { + return false; + } + return changed.includes(section2); + } + }); + } + setFolderConfiguration(uri) { + let u = URI.parse(uri); + if (u.scheme != "file") + return; + let filepath = u.fsPath; + for (let [configFile, model] of this.foldConfigurations) { + let root = import_path4.default.resolve(configFile, "../.."); + if (isParentFolder(root, filepath, true) && this.workspaceConfigFile != configFile) { + this.changeConfiguration(ConfigurationTarget.Workspace, model, configFile); + break; + } + } + } + hasFolderConfiguration(filepath) { + let { folders } = this; + return folders.findIndex((f) => isParentFolder(f, filepath, true)) !== -1; + } + getConfigFile(target) { + if (target == ConfigurationTarget.Global) + return null; + if (target == ConfigurationTarget.User) + return this.userConfigFile; + return this.workspaceConfigFile; + } + get folders() { + let res = []; + let { _folderConfigurations } = this; + for (let folder of _folderConfigurations.keys()) { + res.push(import_path4.default.resolve(folder, "../..")); + } + return res; + } + get configuration() { + return this._configuration; + } + getConfiguration(section2, resource) { + let configuration; + if (resource) { + let { defaults: defaults2, user } = this._configuration; + configuration = new Configuration(defaults2, user, this.getFolderConfiguration(resource)); + } else { + configuration = this._configuration; + } + const config = Object.freeze(lookUp(configuration.getValue(null), section2)); + const result = { + has(key) { + return typeof lookUp(config, key) !== "undefined"; + }, + get: (key, defaultValue) => { + let result2 = lookUp(config, key); + if (result2 == null) + return defaultValue; + return result2; + }, + update: (key, value, isUser = false) => { + let s = section2 ? `${section2}.${key}` : key; + let target = isUser ? ConfigurationTarget.User : ConfigurationTarget.Workspace; + let model = target == ConfigurationTarget.User ? this.user.clone() : this.workspace.clone(); + if (value == void 0) { + model.removeValue(s); + } else { + model.setValue(s, value); + } + if (target == ConfigurationTarget.Workspace && !this.workspaceConfigFile && this._proxy) { + let file = this.workspaceConfigFile = this._proxy.workspaceConfigFile; + if (!import_fs3.default.existsSync(file)) { + let folder = import_path4.default.dirname(file); + if (!import_fs3.default.existsSync(folder)) + import_fs3.default.mkdirSync(folder); + import_fs3.default.writeFileSync(file, "{}", { encoding: "utf8" }); + } + } + this.changeConfiguration(target, model, target == ConfigurationTarget.Workspace ? this.workspaceConfigFile : this.userConfigFile); + if (this._proxy && !global.hasOwnProperty("__TEST__")) { + if (value == void 0) { + this._proxy.$removeConfigurationOption(target, s); + } else { + this._proxy.$updateConfigurationOption(target, s, value); + } + } + }, + inspect: (key) => { + key = section2 ? `${section2}.${key}` : key; + const config2 = this._configuration.inspect(key); + if (config2) { + return { + key, + defaultValue: config2.default, + globalValue: config2.user, + workspaceValue: config2.workspace + }; + } + return void 0; + } + }; + 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") { + mixin(result, config, false); + } + return deepFreeze(result); + } + getFolderConfiguration(uri) { + let u = URI.parse(uri); + if (u.scheme != "file") + return new ConfigurationModel(); + let filepath = u.fsPath; + for (let [configFile, model] of this.foldConfigurations) { + let root = import_path4.default.resolve(configFile, "../.."); + if (isParentFolder(root, filepath, true)) + return model; + } + return new ConfigurationModel(); + } + checkFolderConfiguration(uri) { + let u = URI.parse(uri); + if (u.scheme != "file") + return; + let rootPath = import_path4.default.dirname(u.fsPath); + if (!this.hasFolderConfiguration(rootPath)) { + let folder = findUp(".vim", rootPath); + if (folder && folder != import_os2.default.homedir()) { + let file = import_path4.default.join(folder, CONFIG_FILE_NAME); + if (import_fs3.default.existsSync(file)) { + this.addFolderFile(file); + } + } + } else { + this.setFolderConfiguration(uri); + } + } + static parse(data) { + const defaultConfiguration = new ConfigurationModel(data.defaults.contents); + const userConfiguration = new ConfigurationModel(data.user.contents); + const workspaceConfiguration = new ConfigurationModel(data.workspace.contents); + return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, new ConfigurationModel()); + } + dispose() { + disposeAll(this.disposables); + } + }; + } +}); + +// src/configuration/shape.ts +var import_fs5, import_path5, logger16, ConfigurationProxy; +var init_shape = __esm({ + "src/configuration/shape.ts"() { + import_fs5 = __toModule(require("fs")); + init_main3(); + import_path5 = __toModule(require("path")); + init_esm2(); + init_util(); + logger16 = require_logger2()("configuration-shape"); + ConfigurationProxy = class { + 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 = import_fs5.default.readFileSync(file, "utf8"); + value = value == null ? void 0 : value; + let edits = modify(content, [key], value, { formattingOptions }); + content = applyEdits(content, edits); + import_fs5.default.writeFileSync(file, content, "utf8"); + let doc = workspace.getDocument(URI.file(file).toString()); + if (doc) + nvim.command("checktime", true); + return; + } + get workspaceConfigFile() { + let folder = import_path5.default.join(this.workspace.root, ".vim"); + return import_path5.default.join(folder, CONFIG_FILE_NAME); + } + $updateConfigurationOption(target, key, value) { + this.modifyConfiguration(target, key, value).logError(); + } + $removeConfigurationOption(target, key) { + this.modifyConfiguration(target, key).logError(); + } + }; + } +}); + +// src/model/db.ts +var import_fs_extra2, import_path6, DB; +var init_db = __esm({ + "src/model/db.ts"() { + import_fs_extra2 = __toModule(require_lib5()); + import_path6 = __toModule(require("path")); + DB = class { + constructor(filepath) { + this.filepath = filepath; + } + 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 void 0; + } + obj = obj[part]; + } + return obj; + } + 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(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]]; + import_fs_extra2.default.writeFileSync(this.filepath, JSON.stringify(origin, null, 2), "utf8"); + break; + } + obj = obj[parts[i]]; + } + } + push(key, data) { + let origin = this.load() || {}; + let obj = origin; + let parts = key.split("."); + let len = parts.length; + if (obj == null) { + let dir = import_path6.default.dirname(this.filepath); + import_fs_extra2.default.mkdirpSync(dir); + obj = origin; + } + for (let i = 0; i < len; i++) { + let key2 = parts[i]; + if (i == len - 1) { + obj[key2] = data; + import_fs_extra2.default.writeFileSync(this.filepath, JSON.stringify(origin, null, 2)); + break; + } + if (typeof obj[key2] == "undefined") { + obj[key2] = {}; + obj = obj[key2]; + } else { + obj = obj[key2]; + } + } + } + load() { + let dir = import_path6.default.dirname(this.filepath); + let stat = import_fs_extra2.default.statSync(dir); + if (!stat || !stat.isDirectory()) { + import_fs_extra2.default.mkdirpSync(dir); + import_fs_extra2.default.writeFileSync(this.filepath, "{}", "utf8"); + return {}; + } + try { + let content = import_fs_extra2.default.readFileSync(this.filepath, "utf8"); + return JSON.parse(content.trim()); + } catch (e) { + import_fs_extra2.default.writeFileSync(this.filepath, "{}", "utf8"); + return {}; + } + } + clear() { + let stat = import_fs_extra2.default.statSync(this.filepath); + if (!stat || !stat.isFile()) + return; + import_fs_extra2.default.writeFileSync(this.filepath, "{}", "utf8"); + } + destroy() { + if (import_fs_extra2.default.existsSync(this.filepath)) { + import_fs_extra2.default.unlinkSync(this.filepath); + } + } + }; + } +}); + +// src/util/diff.ts +function diffLines(oldLines, newLines, startLine) { + let endOffset = 0; + let startOffset = 0; + let parts = oldLines.slice(startLine + 1); + for (let i = 0; i < Math.min(parts.length, newLines.length); i++) { + if (parts[parts.length - 1 - i] == newLines[newLines.length - 1 - i]) { + endOffset = endOffset + 1; + } else { + break; + } + } + for (let i = 0; i <= Math.min(startLine, newLines.length - 1 - endOffset); i++) { + if (oldLines[i] == newLines[i]) { + startOffset = startOffset + 1; + } else { + break; + } + } + let replacement = newLines.slice(startOffset, newLines.length - endOffset); + let end = oldLines.length - endOffset; + if (end > startOffset && replacement.length) { + let offset = 0; + for (let i = 0; i < Math.min(replacement.length, end - startOffset); i++) { + if (replacement[i] == oldLines[startOffset + i]) { + offset = offset + 1; + } else { + break; + } + } + if (offset) { + return { + start: startOffset + offset, + end, + replacement: replacement.slice(offset) + }; + } + } + return { + start: startOffset, + end, + replacement + }; +} +function getChange(oldStr, newStr, cursorEnd) { + let ol = oldStr.length; + let nl = newStr.length; + let max = Math.min(ol, nl); + let newText = ""; + let startOffset = 0; + let endOffset = -1; + let shouldLimit = false; + for (let i = 0; i <= max; i++) { + if (cursorEnd != null && i == cursorEnd) { + endOffset = i; + shouldLimit = true; + break; + } + if (oldStr[ol - i - 1] != newStr[nl - i - 1]) { + endOffset = i; + break; + } + } + if (endOffset == -1) + return null; + let remain = max - endOffset; + if (remain == 0) { + startOffset = 0; + } else { + for (let i = 0; i <= remain; i++) { + if (oldStr[i] != newStr[i] || i == remain) { + startOffset = i; + break; + } + } + } + remain = remain - startOffset; + if (shouldLimit && remain > 0) { + let end2 = endOffset; + for (let i = 0; i < remain; i++) { + let oc = oldStr[ol - end2 - 1 - i]; + let nc = newStr[nl - end2 - 1 - i]; + if (oc == nc) { + endOffset = endOffset + 1; + } else { + break; + } + } + } + let end = ol - endOffset; + if (ol == nl && startOffset == end) + return null; + newText = newStr.slice(startOffset, nl - endOffset); + if (startOffset == end) { + let pre = startOffset == 0 ? "" : newStr[startOffset - 1]; + if (pre && pre != "\n" && oldStr[startOffset] == "\n" && newText.startsWith("\n")) { + return { start: startOffset + 1, end: end + 1, newText: newText.slice(1) + "\n" }; + } + } + return { start: startOffset, end, newText }; +} +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 = (0, import_fast_diff.default)(from, to); + let str = ""; + for (let item of result) { + if (item[0] == import_fast_diff.default.DELETE) { + return to; + } else if (item[0] == import_fast_diff.default.INSERT) { + str = str + fill.repeat(byteLength(item[1])); + } else { + str = str + item[1]; + } + } + return str; +} +var import_fast_diff, logger17; +var init_diff = __esm({ + "src/util/diff.ts"() { + import_fast_diff = __toModule(require_diff()); + init_string(); + logger17 = require_logger2()("util-diff"); + } +}); + +// src/model/chars.ts +var logger18, Range3, Chars; +var init_chars = __esm({ + "src/model/chars.ts"() { + logger18 = require_logger2()("model-chars"); + Range3 = class { + 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 == "@") { + ranges.push(new Range3(65, 90)); + ranges.push(new Range3(97, 122)); + } else if (part == "@-@") { + ranges.push(new Range3(64)); + } else if (/^([A-Za-z])-([A-Za-z])$/.test(part)) { + let ms = part.match(/^([A-Za-z])-([A-Za-z])$/); + ranges.push(new Range3(ms[1].charCodeAt(0), ms[2].charCodeAt(0))); + } else if (/^\d+-\d+$/.test(part)) { + let ms = part.match(/^(\d+)-(\d+)$/); + ranges.push(new Range3(Number(ms[1]), Number(ms[2]))); + } else if (/^\d+$/.test(part)) { + ranges.push(new Range3(Number(part))); + } else { + let c = part.charCodeAt(0); + if (!ranges.some((o) => o.contains(c))) { + ranges.push(new Range3(c)); + } + } + } + return ranges; + } + contains(c) { + return c >= this.start && c <= this.end; + } + }; + Chars = class { + constructor(keywordOption) { + this.ranges = []; + if (keywordOption) + this.ranges = Range3.fromKeywordOption(keywordOption); + } + addKeyword(ch) { + let c = ch.charCodeAt(0); + let { ranges } = this; + if (!ranges.some((o) => o.contains(c))) { + ranges.push(new Range3(c)); + } + } + clone() { + let chars = new Chars(); + chars.ranges = this.ranges.slice(); + return chars; + } + setKeywordOption(keywordOption) { + this.ranges = Range3.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); + if (ch > 255) + return false; + if (ranges.some((r) => r.contains(ch))) + continue; + return false; + } + return true; + } + }; + } +}); + +// src/model/textdocument.ts +function computeLineOffsets2(text, isAtLineStart, textOffset = 0) { + const result = isAtLineStart ? [textOffset] : []; + for (let i = 0; i < text.length; i++) { + let ch = text.charCodeAt(i); + if (ch === 13 || ch === 10) { + if (ch === 13 && i + 1 < text.length && text.charCodeAt(i + 1) === 10) { + i++; + } + result.push(textOffset + i + 1); + } + } + return result; +} +var LinesTextDocument; +var init_textdocument = __esm({ + "src/model/textdocument.ts"() { + LinesTextDocument = class { + constructor(uri, languageId, version2, lines, eol) { + this.uri = uri; + this.languageId = languageId; + this.version = version2; + this.lines = lines; + this.eol = eol; + } + get _content() { + return this.lines.join("\n") + (this.eol ? "\n" : ""); + } + get lineCount() { + return this.lines.length + (this.eol ? 1 : 0); + } + getText(range) { + if (range) { + const start = this.offsetAt(range.start); + const end = this.offsetAt(range.end); + return this._content.substring(start, end); + } + return this._content; + } + positionAt(offset) { + offset = Math.max(Math.min(offset, this._content.length), 0); + let lineOffsets = this.getLineOffsets(); + let low = 0; + let high = lineOffsets.length; + if (high === 0) { + return { line: 0, character: offset }; + } + while (low < high) { + let mid = Math.floor((low + high) / 2); + if (lineOffsets[mid] > offset) { + high = mid; + } else { + low = mid + 1; + } + } + let line = low - 1; + return { line, character: offset - lineOffsets[line] }; + } + offsetAt(position) { + let lineOffsets = this.getLineOffsets(); + if (position.line >= lineOffsets.length) { + return this._content.length; + } else if (position.line < 0) { + return 0; + } + let lineOffset = lineOffsets[position.line]; + let nextLineOffset = position.line + 1 < lineOffsets.length ? lineOffsets[position.line + 1] : this._content.length; + return Math.max(Math.min(lineOffset + position.character, nextLineOffset), lineOffset); + } + getLineOffsets() { + if (this._lineOffsets === void 0) { + this._lineOffsets = computeLineOffsets2(this._content, true); + } + return this._lineOffsets; + } + }; + } +}); + +// src/model/document.ts +var import_debounce3, import_vscode_languageserver_protocol9, logger19, Document; +var init_document = __esm({ + "src/model/document.ts"() { + import_debounce3 = __toModule(require_debounce()); + import_vscode_languageserver_protocol9 = __toModule(require_main2()); + init_main2(); + init_esm2(); + init_events(); + init_diff(); + init_util(); + init_object(); + init_position(); + init_string(); + init_chars(); + init_textdocument(); + logger19 = require_logger2()("model-document"); + Document = class { + constructor(buffer, env, maxFileSize) { + this.buffer = buffer; + this.env = env; + this.maxFileSize = maxFileSize; + this.isIgnored = false; + this.size = 0; + this.eol = true; + this.lines = []; + this._attached = false; + this._previewwindow = false; + this._winid = -1; + this._words = []; + this._onDocumentChange = new import_vscode_languageserver_protocol9.Emitter(); + this._onDocumentDetach = new import_vscode_languageserver_protocol9.Emitter(); + this.disposables = []; + this.onDocumentChange = this._onDocumentChange.event; + this.onDocumentDetach = this._onDocumentDetach.event; + this.fireContentChanges = (0, import_debounce3.default)(() => { + this._fireContentChanges(); + }, 300); + this.fetchContent = (0, import_debounce3.default)(() => { + void this._fetchContent(); + }, 100); + } + get content() { + return this.syncLines.join("\n") + (this.eol ? "\n" : ""); + } + get attached() { + return this._attached; + } + get bufnr() { + return this.buffer.id; + } + get filetype() { + return this._filetype; + } + get uri() { + return this._uri; + } + get shouldAttach() { + let { buftype, maxFileSize } = this; + if (!this.getVar("enabled", true)) + return false; + if (this.uri.endsWith("%5BCommand%20Line%5D")) + return true; + if (this.size == -2) + return false; + if (maxFileSize && this.size > maxFileSize) + return false; + return buftype == "" || buftype == "acwrite"; + } + get isCommandLine() { + return this.uri && this.uri.endsWith("%5BCommand%20Line%5D"); + } + get enabled() { + return this.getVar("enabled", true); + } + get words() { + return this._words; + } + convertFiletype(filetype) { + switch (filetype) { + case "javascript.jsx": + return "javascriptreact"; + case "typescript.jsx": + case "typescript.tsx": + return "typescriptreact"; + case "tex": + return "latex"; + default: { + let map = this.env.filetypeMap; + return map[filetype] || filetype; + } + } + } + get changedtick() { + return this._changedtick; + } + get schema() { + return URI.parse(this.uri).scheme; + } + get lineCount() { + return this.lines.length; + } + get winid() { + return this._winid; + } + get previewwindow() { + return this._previewwindow; + } + async init(nvim, token) { + this.nvim = nvim; + let opts = await nvim.call("coc#util#get_bufoptions", [this.bufnr, this.maxFileSize]); + if (opts == null) + return false; + let buftype = this.buftype = opts.buftype; + this._previewwindow = opts.previewwindow; + this._winid = opts.winid; + this.size = typeof opts.size == "number" ? opts.size : 0; + this.variables = opts.variables || {}; + this._changedtick = opts.changedtick; + this.eol = opts.eol == 1; + this._uri = getUri(opts.fullpath, this.bufnr, buftype, this.env.isCygwin); + if (token.isCancellationRequested) + return false; + if (this.shouldAttach) { + this.lines = opts.lines; + let res = await this.attach(); + if (!res) + return false; + this._attached = true; + } + this._filetype = this.convertFiletype(opts.filetype); + this.setIskeyword(opts.iskeyword); + this.createTextDocument(1, this.lines); + if (token.isCancellationRequested) { + this.detach(); + return false; + } + return true; + } + async attach() { + let attached = await this.buffer.attach(true); + if (!attached) + return false; + let lines = this.lines; + this.buffer.listen("lines", (buf, tick, firstline, lastline, linedata) => { + if (buf.id !== this.bufnr || !this._attached || tick == null) + return; + if (tick > this._changedtick) { + this._changedtick = tick; + lines = [...lines.slice(0, firstline), ...linedata, ...lines.slice(lastline)]; + this.lines = lines; + this.fireContentChanges(); + } + }, this.disposables); + this.buffer.listen("detach", async (buf) => { + lines = []; + this._onDocumentDetach.fire(buf.id); + }, this.disposables); + return true; + } + get dirty() { + if (this.lines === this.syncLines) + return false; + return !equals(this.lines, this.syncLines); + } + _fireContentChanges() { + let { cursor } = events_default; + if (!this.dirty) + return; + let textDocument = this._textDocument; + let endOffset = null; + if (cursor && cursor.bufnr == this.bufnr) { + endOffset = this.getEndOffset(cursor.lnum, cursor.col, cursor.insert); + } + let content = this.getDocumentContent(); + let change = getChange(textDocument.getText(), content, endOffset); + if (change == null) + return; + let start = textDocument.positionAt(change.start); + let end = textDocument.positionAt(change.end); + let original = textDocument.getText(import_vscode_languageserver_protocol9.Range.create(start, end)); + this.createTextDocument(this.version + 1, this.lines); + let changes = [{ + range: { start, end }, + rangeLength: change.end - change.start, + text: change.newText + }]; + this._onDocumentChange.fire({ + bufnr: this.bufnr, + original, + originalLines: textDocument.lines, + textDocument: { version: this.version, uri: this.uri }, + contentChanges: changes + }); + this._words = this.chars.matchKeywords(content); + } + async applyEdits(edits) { + if (!Array.isArray(arguments[0]) && Array.isArray(arguments[1])) { + edits = arguments[1]; + } + if (edits.length == 0) + return; + let textDocument = TextDocument2.create(this.uri, this.filetype, 1, this.getDocumentContent()); + let applied = TextDocument2.applyEdits(textDocument, edits); + let content; + if (this.eol) { + if (applied.endsWith("\r\n")) { + content = applied.slice(0, -2); + } else { + content = applied.endsWith("\n") ? applied.slice(0, -1) : applied; + } + } else { + content = applied; + } + let lines = this.lines; + let newLines = content.split(/\r?\n/); + if (!equals(lines, newLines)) { + let lnums = edits.map((o) => o.range.start.line); + let d = diffLines(lines, newLines, Math.min.apply(null, lnums)); + let original = lines.slice(d.start, d.end); + this.nvim.call("coc#util#set_lines", [this.bufnr, this._changedtick, original, d.replacement, d.start, d.end], true); + if (this.env.isVim) + this.nvim.command("redraw", true); + await waitNextTick(() => { + this.lines = newLines; + this._forceSync(); + }); + } + } + async changeLines(lines) { + let filtered = []; + let newLines = this.lines.slice(); + for (let [lnum, text] of lines) { + if (newLines[lnum] != text) { + filtered.push([lnum, text]); + newLines[lnum] = text; + } + } + if (!filtered.length) + return; + this.nvim.call("coc#util#change_lines", [this.bufnr, filtered], true); + if (this.env.isVim) + this.nvim.command("redraw", true); + this.lines = newLines; + this._forceSync(); + } + _forceSync() { + this.fireContentChanges.clear(); + this._fireContentChanges(); + } + forceSync() { + if (global.hasOwnProperty("__TEST__")) { + this._forceSync(); + } + } + getOffset(lnum, col) { + return this.textDocument.offsetAt({ + line: lnum - 1, + character: col + }); + } + isWord(word) { + return this.chars.isKeyword(word); + } + getMoreWords() { + let res = []; + let { words, chars } = this; + if (!chars.isKeywordChar("-")) + return res; + for (let word of words) { + word = word.replace(/^-+/, ""); + if (word.includes("-")) { + let parts = word.split("-"); + for (let part of parts) { + if (part.length > 2 && !res.includes(part) && !words.includes(part)) { + res.push(part); + } + } + } + } + return res; + } + 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 import_vscode_languageserver_protocol9.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 import_vscode_languageserver_protocol9.Range.create(position.line, start, position.line, end); + } + get textDocument() { + return this._textDocument; + } + get syncLines() { + return this._textDocument.lines; + } + get version() { + return this._textDocument.version; + } + createTextDocument(version2, lines) { + let { uri, filetype, eol } = this; + this._textDocument = new LinesTextDocument(uri, filetype, version2, lines, eol); + } + async _fetchContent(sync) { + if (!this.env.isVim || !this._attached) + return; + let { nvim, bufnr, changedtick } = this; + let o = await nvim.call("coc#util#get_buf_lines", [bufnr, changedtick]); + if (o) { + this._changedtick = o.changedtick; + this.lines = o.lines; + if (sync) { + this._forceSync(); + } else { + this.fireContentChanges(); + } + } + } + async patchChange(currentLine) { + if (!this._attached) + return; + if (this.env.isVim) { + if (currentLine) { + let change = await this.nvim.call("coc#util#get_changeinfo", []); + if (change.changedtick < this._changedtick) + return; + let { lnum, line, changedtick } = change; + let newLines = this.lines.slice(); + this._changedtick = changedtick; + if (newLines[lnum - 1] == line) + return; + newLines[lnum - 1] = line; + this.lines = newLines; + this._forceSync(); + } else { + this.fetchContent.clear(); + await this._fetchContent(true); + } + } else { + this._changedtick = await this.buffer.getVar("changedtick"); + this._forceSync(); + } + } + getSymbolRanges(word) { + let { version: version2, filetype, uri } = this; + let textDocument = new LinesTextDocument(uri, filetype, version2, this.lines, this.eol); + 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(import_vscode_languageserver_protocol9.Range.create(textDocument.positionAt(i - str.length), textDocument.positionAt(i))); + } + if (!isKeyword) { + str = ""; + } + } + return res; + } + fixStartcol(position, valids) { + let line = this.getline(position.line); + if (!line) + return null; + let { character } = position; + let start = line.slice(0, character); + let col = 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.includes(c)) { + break; + } + col = col - byteLength(c); + } + return col; + } + addHighlights(items, hlGroup, range) { + let { start, end } = range; + if (emptyRange(range)) + return; + for (let line = start.line; line <= end.line; line++) { + const text = this.getline(line, false); + let colStart = line == start.line ? byteIndex(text, start.character) : 0; + let colEnd = line == end.line ? byteIndex(text, end.character) : global.Buffer.byteLength(text); + if (colStart >= colEnd) + continue; + items.push({ hlGroup, lnum: line, colStart, colEnd }); + } + } + getline(line, current = true) { + if (current) + return this.lines[line] || ""; + return this.syncLines[line] || ""; + } + getLines(start, end) { + return this.lines.slice(start, end); + } + getDocumentContent() { + let content = this.lines.join("\n"); + return this.eol ? content + "\n" : content; + } + getVar(key, defaultValue) { + let val = this.variables[`coc_${key}`]; + return val === void 0 ? defaultValue : val; + } + getPosition(lnum, col) { + let line = this.getline(lnum - 1); + if (!line || col == 0) + return { line: lnum - 1, character: 0 }; + let pre = 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]; + let l = line.length; + if (i == lnum - 1 && l != 0) { + let buf = global.Buffer.from(line, "utf8"); + let isEnd = buf.byteLength <= col - 1; + if (!isEnd) { + total = total + buf.slice(col - 1, buf.length).toString("utf8").length; + if (!insert) + total = total - 1; + } + } else { + total = total + l; + } + if (!this.eol && i == len - 1) + break; + total = total + 1; + } + return total; + } + setFiletype(filetype) { + this._filetype = this.convertFiletype(filetype); + let lines = this._textDocument.lines; + this._textDocument = new LinesTextDocument(this.uri, this.filetype, 1, lines, this.eol); + } + setIskeyword(iskeyword) { + let chars = this.chars = new 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 > 3e4 ? this.lines.slice(0, 3e4) : this.lines; + this._words = this.chars.matchKeywords(lines.join("\n")); + } + detach() { + this._attached = false; + disposeAll(this.disposables); + this.disposables = []; + this.fetchContent.clear(); + this.fireContentChanges.clear(); + this._onDocumentChange.dispose(); + this._onDocumentDetach.dispose(); + } + async synchronize() { + let { changedtick } = this; + await this.patchChange(); + if (changedtick != this.changedtick) { + await wait(50); + } + } + 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 = import_vscode_languageserver_protocol9.Position.create(sp.line - startLine, sp.character); + ep = import_vscode_languageserver_protocol9.Position.create(ep.line - startLine, ep.character); + let doc = TextDocument2.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 score5 = res.get(str) || 0; + res.set(str, Math.max(score5, (len - i + (end - start)) / tailCount)); + } + } + preKeyword = iskeyword; + } + return res; + } + }; + } +}); + +// src/util/array.ts +function splitArray(array, fn) { + let res = [[], []]; + for (let item of array) { + if (fn(item)) { + res[0].push(item); + } else { + res[1].push(item); + } + } + return res; +} +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; +} +function distinct(array, keyFn) { + if (!keyFn) { + return array.filter((element, position) => 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; + }); +} +var init_array = __esm({ + "src/util/array.ts"() { + } +}); + +// src/model/fileSystemWatcher.ts +var import_vscode_languageserver_protocol10, import_minimatch2, import_path7, logger20, FileSystemWatcher; +var init_fileSystemWatcher = __esm({ + "src/model/fileSystemWatcher.ts"() { + import_vscode_languageserver_protocol10 = __toModule(require_main2()); + init_esm2(); + import_minimatch2 = __toModule(require_minimatch()); + import_path7 = __toModule(require("path")); + init_util(); + init_array(); + logger20 = require_logger2()("filesystem-watcher"); + FileSystemWatcher = class { + constructor(clientPromise, globPattern, ignoreCreateEvents, ignoreChangeEvents, ignoreDeleteEvents) { + this.globPattern = globPattern; + this.ignoreCreateEvents = ignoreCreateEvents; + this.ignoreChangeEvents = ignoreChangeEvents; + this.ignoreDeleteEvents = ignoreDeleteEvents; + this._onDidCreate = new import_vscode_languageserver_protocol10.Emitter(); + this._onDidChange = new import_vscode_languageserver_protocol10.Emitter(); + this._onDidDelete = new import_vscode_languageserver_protocol10.Emitter(); + this._onDidRename = new import_vscode_languageserver_protocol10.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) => { + logger20.error("watchman initialize failed"); + logger20.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" && (0, import_minimatch2.default)(f.name, globPattern, { dot: true })); + for (let file of files) { + let uri = URI.file(import_path7.default.join(root, file.name)); + if (!file.exists) { + if (!ignoreDeleteEvents) + this._onDidDelete.fire(uri); + } else { + if (file.new === true) { + if (!ignoreCreateEvents) + this._onDidCreate.fire(uri); + } else { + if (!ignoreChangeEvents) + this._onDidChange.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: URI.file(import_path7.default.join(root, oldFile.name)), + newUri: URI.file(import_path7.default.join(root, newFile.name)) + }); + } + } + if (files.length >= 2) { + let [oldFiles, newFiles] = splitArray(files, (o) => o.exists === false); + if (oldFiles.length == newFiles.length) { + for (let oldFile of oldFiles) { + let newFile = newFiles.find((o) => o.size == oldFile.size && o.mtime_ms == oldFile.mtime_ms); + if (newFile) { + this._onDidRename.fire({ + oldUri: URI.file(import_path7.default.join(root, oldFile.name)), + newUri: URI.file(import_path7.default.join(root, newFile.name)) + }); + } + } + } + } + }); + this.disposables.push(disposable); + return disposable; + } + dispose() { + disposeAll(this.disposables); + } + }; + } +}); + +// src/model/mru.ts +var import_path8, import_fs_extra3, Mru; +var init_mru = __esm({ + "src/model/mru.ts"() { + import_path8 = __toModule(require("path")); + import_fs_extra3 = __toModule(require_lib5()); + Mru = class { + constructor(name2, base) { + this.name = name2; + this.file = import_path8.default.join(base || process.env.COC_DATA_HOME, name2); + } + async load() { + let dir = import_path8.default.dirname(this.file); + try { + import_fs_extra3.default.mkdirpSync(dir); + if (!import_fs_extra3.default.existsSync(this.file)) { + import_fs_extra3.default.writeFileSync(this.file, "", "utf8"); + } + let content = await import_fs_extra3.default.readFile(this.file, "utf8"); + content = content.trim(); + return content.length ? content.trim().split("\n") : []; + } catch (e) { + return []; + } + } + async add(item) { + let items = await this.load(); + let idx = items.indexOf(item); + if (idx !== -1) + items.splice(idx, 1); + items.unshift(item); + import_fs_extra3.default.writeFileSync(this.file, items.join("\n"), "utf8"); + } + async remove(item) { + let items = await this.load(); + let idx = items.indexOf(item); + if (idx !== -1) { + items.splice(idx, 1); + import_fs_extra3.default.writeFileSync(this.file, items.join("\n"), "utf8"); + } + } + async clean() { + try { + await import_fs_extra3.default.unlink(this.file); + } catch (e) { + } + } + }; + } +}); + +// src/util/decorator.ts +function memorize(_target, key, descriptor) { + let fn = descriptor.value; + if (typeof fn !== "function") + return; + let memoKey = "$" + key; + descriptor.value = function(...args) { + if (this.hasOwnProperty(memoKey)) + return Promise.resolve(this[memoKey]); + return new Promise((resolve3, reject) => { + Promise.resolve(fn.apply(this, args)).then((res) => { + this[memoKey] = res; + resolve3(res); + }, (e) => { + reject(e); + }); + }); + }; +} +var logger21; +var init_decorator = __esm({ + "src/util/decorator.ts"() { + logger21 = require_logger2()("util-decorator"); + } +}); + +// src/model/resolver.ts +var import_path9, import_fs6, import_strip_ansi2, logger22, Resolver; +var init_resolver = __esm({ + "src/model/resolver.ts"() { + import_path9 = __toModule(require("path")); + import_fs6 = __toModule(require("fs")); + init_util(); + init_fs(); + init_decorator(); + import_strip_ansi2 = __toModule(require_strip_ansi()); + logger22 = require_logger2()("model-resolver"); + Resolver = class { + get nodeFolder() { + if (!executable("npm")) + return Promise.resolve(""); + return runCommand("npm --loglevel silent root -g", {}, 3e3).then((root) => { + return (0, import_strip_ansi2.default)(root).trim(); + }); + } + get yarnFolder() { + if (!executable("yarnpkg")) + return Promise.resolve(""); + return runCommand("yarnpkg global dir", {}, 3e3).then((root) => { + let folder = import_path9.default.join((0, import_strip_ansi2.default)(root).trim(), "node_modules"); + let exists = import_fs6.default.existsSync(folder); + return exists ? folder : ""; + }); + } + async resolveModule(mod) { + let nodeFolder = await this.nodeFolder; + let yarnFolder = await this.yarnFolder; + if (yarnFolder) { + let s = await statAsync(import_path9.default.join(yarnFolder, mod, "package.json")); + if (s && s.isFile()) + return import_path9.default.join(yarnFolder, mod); + } + if (nodeFolder) { + let s = await statAsync(import_path9.default.join(nodeFolder, mod, "package.json")); + if (s && s.isFile()) + return import_path9.default.join(nodeFolder, mod); + } + return null; + } + }; + __decorateClass([ + memorize + ], Resolver.prototype, "nodeFolder", 1); + __decorateClass([ + memorize + ], Resolver.prototype, "yarnFolder", 1); + } +}); + +// src/model/task.ts +var import_vscode_languageserver_protocol11, Task; +var init_task = __esm({ + "src/model/task.ts"() { + init_events(); + import_vscode_languageserver_protocol11 = __toModule(require_main2()); + init_util(); + Task = class { + constructor(nvim, id) { + this.nvim = nvim; + this.id = id; + this.disposables = []; + this._onExit = new import_vscode_languageserver_protocol11.Emitter(); + this._onStderr = new import_vscode_languageserver_protocol11.Emitter(); + this._onStdout = new import_vscode_languageserver_protocol11.Emitter(); + this.onExit = this._onExit.event; + this.onStdout = this._onStdout.event; + this.onStderr = this._onStderr.event; + events_default.on("TaskExit", (id2, code) => { + if (id2 == this.id) { + this._onExit.fire(code); + } + }, null, this.disposables); + events_default.on("TaskStderr", (id2, lines) => { + if (id2 == this.id) { + this._onStderr.fire(lines); + } + }, null, this.disposables); + let stdout = []; + let timer; + events_default.on("TaskStdout", (id2, lines) => { + if (id2 == this.id) { + if (timer) + clearTimeout(timer); + stdout.push(...lines); + timer = setTimeout(() => { + this._onStdout.fire(stdout); + stdout = []; + }, 100); + } + }, null, this.disposables); + } + async start(opts) { + let { nvim } = this; + return await nvim.call("coc#task#start", [this.id, opts]); + } + async stop() { + let { nvim } = this; + await nvim.call("coc#task#stop", [this.id]); + } + get running() { + let { nvim } = this; + return nvim.call("coc#task#running", [this.id]); + } + dispose() { + let { nvim } = this; + nvim.call("coc#task#stop", [this.id], true); + this._onStdout.dispose(); + this._onStderr.dispose(); + this._onExit.dispose(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/model/terminal.ts +var logger23, TerminalModel; +var init_terminal = __esm({ + "src/model/terminal.ts"() { + logger23 = require_logger2()("model-terminal"); + TerminalModel = class { + 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, curr] = await nvim.eval(`[bufloaded(${bufnr}),bufwinid(${bufnr}),win_getid()]`); + if (!loaded) + return false; + if (curr == winid) + return true; + 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); + } + }; + } +}); + +// src/model/bufferSync.ts +var BufferSync; +var init_bufferSync = __esm({ + "src/model/bufferSync.ts"() { + init_util(); + BufferSync = class { + constructor(_create, workspace) { + this._create = _create; + this.workspace = workspace; + this.disposables = []; + this.itemsMap = new Map(); + let { disposables } = this; + for (let doc of workspace.documents) { + this.create(doc); + } + workspace.onDidOpenTextDocument((e) => { + let doc = workspace.getDocument(e.bufnr); + if (doc) + this.create(doc); + }, null, disposables); + workspace.onDidChangeTextDocument((e) => { + this.onChange(e); + }, null, disposables); + workspace.onDidCloseTextDocument((e) => { + this.delete(e.bufnr); + }, null, disposables); + } + get items() { + return Array.from(this.itemsMap.values()).map((x) => x.item); + } + getItem(bufnr) { + var _a2; + if (typeof bufnr === "number") { + return (_a2 = this.itemsMap.get(bufnr)) == null ? void 0 : _a2.item; + } + let o = Array.from(this.itemsMap.values()).find((v) => { + return v.uri == bufnr; + }); + return o ? o.item : void 0; + } + create(doc) { + if (!doc || doc.isCommandLine || !doc.attached) + return; + let o = this.itemsMap.get(doc.bufnr); + if (o) + o.item.dispose(); + let item = this._create(doc); + if (item) + this.itemsMap.set(doc.bufnr, { uri: doc.uri, item }); + } + onChange(e) { + let o = this.itemsMap.get(e.bufnr); + if (o && typeof o.item.onChange == "function") { + o.item.onChange(e); + } + } + delete(bufnr) { + let o = this.itemsMap.get(bufnr); + if (o) { + this.itemsMap.delete(bufnr); + o.item.dispose(); + } + } + reset() { + for (let o of this.itemsMap.values()) { + o.item.dispose(); + } + this.itemsMap.clear(); + } + dispose() { + disposeAll(this.disposables); + for (let o of this.itemsMap.values()) { + o.item.dispose(); + } + this.itemsMap.clear(); + } + }; + } +}); + +// src/util/match.ts +function score(selector, uri, languageId) { + if (Array.isArray(selector)) { + let ret = 0; + for (const filter of selector) { + const value = score(filter, uri, languageId); + if (value === 10) { + return value; + } + if (value > ret) { + ret = value; + } + } + return ret; + } else if (typeof selector === "string") { + if (selector === "*") { + return 5; + } else if (selector === languageId) { + return 10; + } else { + return 0; + } + } else if (selector) { + let u = URI.parse(uri); + const { language: language2, pattern, scheme } = selector; + let ret = 0; + if (scheme) { + if (scheme === u.scheme) { + ret = 5; + } else if (scheme === "*") { + ret = 3; + } else { + return 0; + } + } + if (language2) { + if (language2 === languageId) { + ret = 10; + } else if (language2 === "*") { + ret = Math.max(ret, 5); + } else { + return 0; + } + } + if (pattern) { + let caseInsensitive = isWindows2 || isMacintosh; + let p = caseInsensitive ? pattern.toLowerCase() : pattern; + let f = caseInsensitive ? u.fsPath.toLowerCase() : u.fsPath; + if (p === f || (0, import_minimatch3.default)(f, p, { dot: true })) { + ret = 5; + } else { + return 0; + } + } + return ret; + } else { + return 0; + } +} +var import_minimatch3; +var init_match = __esm({ + "src/util/match.ts"() { + import_minimatch3 = __toModule(require_minimatch()); + init_esm2(); + init_platform(); + } +}); + +// node_modules/node-int64/Int64.js +var require_Int64 = __commonJS({ + "node_modules/node-int64/Int64.js"(exports2, module2) { + var VAL32 = 4294967296; + var _HEX = []; + for (var i = 0; i < 256; i++) { + _HEX[i] = (i > 15 ? "" : "0") + i.toString(16); + } + var Int64 = module2.exports = function(a1, a2) { + if (a1 instanceof Buffer) { + this.buffer = a1; + this.offset = a2 || 0; + } else if (Object.prototype.toString.call(a1) == "[object Uint8Array]") { + 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); + } + }; + Int64.MAX_INT = Math.pow(2, 53); + Int64.MIN_INT = -Math.pow(2, 53); + Int64.prototype = { + constructor: Int64, + _2scomp: function() { + var b = this.buffer, o = this.offset, carry = 1; + for (var i2 = o + 7; i2 >= o; i2--) { + var v = (b[i2] ^ 255) + carry; + b[i2] = v & 255; + carry = v >> 8; + } + }, + setValue: function(hi, lo) { + var negate = false; + if (arguments.length == 1) { + if (typeof hi == "number") { + 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"); + } + } + var b = this.buffer, o = this.offset; + for (var i2 = 7; i2 >= 0; i2--) { + b[o + i2] = lo & 255; + lo = i2 == 4 ? hi : lo >>> 8; + } + if (negate) + this._2scomp(); + }, + toNumber: function(allowImprecise) { + var b = this.buffer, o = this.offset; + var negate = b[o] & 128, x = 0, carry = 1; + for (var i2 = 7, m = 1; i2 >= 0; i2--, m *= 256) { + var v = b[o + i2]; + if (negate) { + v = (v ^ 255) + carry; + carry = v >> 8; + v = v & 255; + } + x += v * m; + } + if (!allowImprecise && x >= Int64.MAX_INT) { + return negate ? -Infinity : Infinity; + } + return negate ? -x : x; + }, + valueOf: function() { + return this.toNumber(false); + }, + toString: function(radix) { + return this.valueOf().toString(radix || 10); + }, + toOctetString: function(sep) { + var out = new Array(8); + var b = this.buffer, o = this.offset; + for (var i2 = 0; i2 < 8; i2++) { + out[i2] = _HEX[b[o + i2]]; + } + return out.join(sep || ""); + }, + 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: function(targetBuffer, targetOffset) { + this.buffer.copy(targetBuffer, targetOffset || 0, this.offset, this.offset + 8); + }, + compare: function(other) { + if ((this.buffer[this.offset] & 128) != (other.buffer[other.offset] & 128)) { + return other.buffer[other.offset] - this.buffer[this.offset]; + } + for (var i2 = 0; i2 < 8; i2++) { + if (this.buffer[this.offset + i2] !== other.buffer[other.offset + i2]) { + return this.buffer[this.offset + i2] - other.buffer[other.offset + i2]; + } + } + return 0; + }, + equals: function(other) { + return this.compare(other) === 0; + }, + inspect: function() { + return "[Int64 value:" + this + " octets:" + this.toOctetString(" ") + "]"; + } + }; + } +}); + +// node_modules/bser/index.js +var require_bser = __commonJS({ + "node_modules/bser/index.js"(exports2) { + var EE = require("events").EventEmitter; + var util4 = require("util"); + var os10 = require("os"); + var assert = require("assert"); + var Int64 = require_Int64(); + var isBigEndian = os10.endianness() == "BE"; + function nextPow2(size) { + return Math.pow(2, Math.ceil(Math.log(size) / Math.LN2)); + } + function Accumulator(initsize) { + this.buf = Buffer.alloc(nextPow2(initsize || 8192)); + this.readOffset = 0; + this.writeOffset = 0; + } + exports2.Accumulator = Accumulator; + Accumulator.prototype.writeAvail = function() { + return this.buf.length - this.writeOffset; + }; + Accumulator.prototype.readAvail = function() { + return this.writeOffset - this.readOffset; + }; + Accumulator.prototype.reserve = function(size) { + if (size < this.writeAvail()) { + return; + } + if (this.readOffset > 0) { + this.buf.copy(this.buf, 0, this.readOffset, this.writeOffset); + this.writeOffset -= this.readOffset; + this.readOffset = 0; + } + if (size < this.writeAvail()) { + return; + } + var buf = Buffer.alloc(nextPow2(this.buf.length + size - this.writeAvail())); + this.buf.copy(buf); + this.buf = buf; + }; + 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) { + return new Int64(big); + } + return new Int64(byteswap64(big)); + default: + throw new Error("invalid integer size " + size); + } + }; + Accumulator.prototype.readInt = function(bytes2) { + var ival = this.peekInt(bytes2); + if (ival instanceof Int64 && isFinite(ival.valueOf())) { + ival = ival.valueOf(); + } + this.readOffset += bytes2; + 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 = 0; + var BSER_OBJECT = 1; + var BSER_STRING = 2; + var BSER_INT8 = 3; + var BSER_INT16 = 4; + var BSER_INT32 = 5; + var BSER_INT64 = 6; + var BSER_REAL = 7; + var BSER_TRUE = 8; + var BSER_FALSE = 9; + var BSER_NULL = 10; + var BSER_TEMPLATE = 11; + var BSER_SKIP = 12; + var ST_NEED_PDU = 0; + var ST_FILL_PDU = 1; + 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; + } + util4.inherits(BunserBuf, EE); + exports2.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; + } + this.processLater(); + }; + BunserBuf.prototype.processLater = function() { + var self2 = this; + process.nextTick(function() { + try { + self2.process(false); + } catch (err) { + self2.emit("error", err); + } + }); + }; + BunserBuf.prototype.process = function(synchronous) { + if (this.state == ST_NEED_PDU) { + if (this.buf.readAvail() < 2) { + return; + } + this.expectCode(0); + this.expectCode(1); + this.pduLen = this.decodeInt(true); + if (this.pduLen === false) { + this.buf.readAdvance(-2); + return; + } + this.buf.reserve(this.pduLen); + this.state = ST_FILL_PDU; + } + if (this.state == ST_FILL_PDU) { + if (this.buf.readAvail() < this.pduLen) { + return; + } + 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); + }; + 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); + }; + 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; + } + exports2.loadFromBuffer = loadFromBuffer; + function byteswap64(buf) { + var swap = Buffer.alloc(buf.length); + for (var i = 0; i < buf.length; i++) { + swap[i] = buf[buf.length - 1 - i]; + } + return swap; + } + function dump_int64(buf, val) { + var be = val.toBuffer(); + if (isBigEndian) { + buf.writeByte(BSER_INT64); + buf.append(be); + return; + } + 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": + 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); + 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") { + 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"); + } + } + function dumpToBuffer(val) { + var buf = new Accumulator(); + buf.writeByte(0); + buf.writeByte(1); + buf.writeByte(BSER_INT32); + buf.writeInt(0, 4); + dump_any(buf, val); + var off = buf.writeOffset; + var len = off - 7; + buf.writeOffset = 3; + buf.writeInt(len, 4); + buf.writeOffset = off; + return buf.buf.slice(0, off); + } + exports2.dumpToBuffer = dumpToBuffer; + } +}); + +// node_modules/fb-watchman/index.js +var require_fb_watchman = __commonJS({ + "node_modules/fb-watchman/index.js"(exports2, module2) { + "use strict"; + var net3 = require("net"); + var EE = require("events").EventEmitter; + var util4 = require("util"); + var childProcess = require("child_process"); + var bser = require_bser(); + var unilateralTags = ["subscription", "log"]; + function Client2(options) { + var self2 = this; + EE.call(this); + this.watchmanBinaryPath = "watchman"; + if (options && options.watchmanBinaryPath) { + this.watchmanBinaryPath = options.watchmanBinaryPath.trim(); + } + ; + this.commands = []; + } + util4.inherits(Client2, EE); + module2.exports.Client = Client2; + Client2.prototype.sendNextCommand = function() { + if (this.currentCommand) { + return; + } + this.currentCommand = this.commands.shift(); + if (!this.currentCommand) { + return; + } + this.socket.write(bser.dumpToBuffer(this.currentCommand.cmd)); + }; + Client2.prototype.cancelCommands = function(why) { + var error = new Error(why); + var cmds = this.commands; + this.commands = []; + if (this.currentCommand) { + cmds.unshift(this.currentCommand); + this.currentCommand = null; + } + cmds.forEach(function(cmd) { + cmd.cb(error); + }); + }; + Client2.prototype.connect = function() { + var self2 = this; + function makeSock(sockname) { + self2.bunser = new bser.BunserBuf(); + self2.bunser.on("value", function(obj) { + var unilateral = false; + for (var i = 0; i < unilateralTags.length; i++) { + var tag = unilateralTags[i]; + if (tag in obj) { + unilateral = tag; + } + } + if (unilateral) { + self2.emit(unilateral, obj); + } else if (self2.currentCommand) { + var cmd = self2.currentCommand; + self2.currentCommand = null; + if ("error" in obj) { + var error = new Error(obj.error); + error.watchmanResponse = obj; + cmd.cb(error); + } else { + cmd.cb(null, obj); + } + } + self2.sendNextCommand(); + }); + self2.bunser.on("error", function(err) { + self2.emit("error", err); + }); + self2.socket = net3.createConnection(sockname); + self2.socket.on("connect", function() { + self2.connecting = false; + self2.emit("connect"); + self2.sendNextCommand(); + }); + self2.socket.on("error", function(err) { + self2.connecting = false; + self2.emit("error", err); + }); + self2.socket.on("data", function(buf) { + if (self2.bunser) { + self2.bunser.append(buf); + } + }); + self2.socket.on("end", function() { + self2.socket = null; + self2.bunser = null; + self2.cancelCommands("The watchman connection was closed"); + self2.emit("end"); + }); + } + if (process.env.WATCHMAN_SOCK) { + makeSock(process.env.WATCHMAN_SOCK); + return; + } + var args = ["--no-pretty", "get-sockname"]; + var proc = null; + var spawnFailed = false; + function spawnError(error) { + if (spawnFailed) { + 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); + self2.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(self2.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; + self2.emit("error", error); + return; + } + makeSock(obj.sockname); + } catch (e) { + self2.emit("error", e); + } + }); + }; + Client2.prototype.command = function(args, done) { + done = done || function() { + }; + this.commands.push({ cmd: args, cb: done }); + if (!this.socket) { + if (!this.connecting) { + this.connecting = true; + this.connect(); + return; + } + return; + } + 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" + }; + 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; + } + function have_cap(vers, name2) { + if (name2 in cap_versions) { + return vers_compare(vers, cap_versions[name2]) >= 0; + } + return false; + } + Client2.prototype._synthesizeCapabilityCheck = function(resp, optional, required) { + resp.capabilities = {}; + var version2 = resp.version; + optional.forEach(function(name2) { + resp.capabilities[name2] = have_cap(version2, name2); + }); + required.forEach(function(name2) { + var have = have_cap(version2, name2); + resp.capabilities[name2] = have; + if (!have) { + resp.error = "client required capability `" + name2 + "` is not supported by this server"; + } + }); + return resp; + }; + Client2.prototype.capabilityCheck = function(caps, done) { + var optional = caps.optional || []; + var required = caps.required || []; + var self2 = this; + this.command(["version", { + optional, + required + }], function(error, resp) { + if (error) { + done(error); + return; + } + if (!("capabilities" in resp)) { + resp = self2._synthesizeCapabilityCheck(resp, optional, required); + if (resp.error) { + error = new Error(resp.error); + error.watchmanResponse = resp; + done(error); + return; + } + } + done(null, resp); + }); + }; + Client2.prototype.end = function() { + this.cancelCommands("The client was ended"); + if (this.socket) { + this.socket.end(); + this.socket = null; + } + this.bunser = null; + }; + } +}); + +// src/watchman.ts +function isValidWatchRoot(root) { + if (root == "/" || root == "/tmp" || root == "/private/tmp") + return false; + if (root.toLowerCase() === import_os3.default.homedir().toLowerCase()) + return false; + if (import_path10.default.parse(root).base == root) + return false; + if (root.startsWith("/tmp/") || root.startsWith("/private/tmp/")) + return false; + if (isParentFolder(import_os3.default.tmpdir(), root, true)) + return false; + return true; +} +var import_fb_watchman, import_os3, import_path10, import_vscode_languageserver_protocol12, import_minimatch4, logger24, requiredCapabilities, clientsMap, Watchman; +var init_watchman = __esm({ + "src/watchman.ts"() { + import_fb_watchman = __toModule(require_fb_watchman()); + import_os3 = __toModule(require("os")); + import_path10 = __toModule(require("path")); + init_esm_node(); + import_vscode_languageserver_protocol12 = __toModule(require_main2()); + import_minimatch4 = __toModule(require_minimatch()); + init_fs(); + logger24 = require_logger2()("watchman"); + requiredCapabilities = ["relative_root", "cmd-watch-project", "wildmatch", "field-new"]; + clientsMap = new Map(); + Watchman = class { + constructor(binaryPath, channel) { + this.channel = channel; + this._disposed = false; + this.client = new import_fb_watchman.default.Client({ + watchmanBinaryPath: binaryPath + }); + this.client.setMaxListeners(300); + } + checkCapability() { + let { client } = this; + return new Promise((resolve3, 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 resolve3(false); + } + resolve3(true); + }); + }); + } + async watchProject(root) { + try { + let resp = await this.command(["watch-project", root]); + let { watch, warning, relative_path } = resp; + if (warning) + logger24.warn(warning); + this.watch = watch; + this.relative_path = relative_path; + logger24.info(`watchman watching project: ${root}`); + this.appendOutput(`watchman watching project: ${root}`); + } catch (e) { + logger24.error(e); + return false; + } + return true; + } + command(args) { + return new Promise((resolve3, reject) => { + this.client.command(args, (error, resp) => { + if (error) + return reject(error); + resolve3(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 = v1_default(); + let sub = { + expression: ["allof", ["match", "**/*", "wholename"]], + fields: ["name", "size", "new", "exists", "type", "mtime_ms", "ctime_ms"], + since: clock + }; + let root = watch; + if (relative_path) { + sub.relative_root = relative_path; + root = import_path10.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; + if (!files) + return; + files = files.filter((f) => f.type == "f" && (0, import_minimatch4.default)(f.name, globPattern, { dot: true })); + if (!files.length) + return; + let ev = Object.assign({}, resp); + if (this.relative_path) + ev.root = import_path10.default.resolve(resp.root, this.relative_path); + this.appendOutput(`file change detected: ${JSON.stringify(ev, null, 2)}`); + cb(ev); + }); + return import_vscode_languageserver_protocol12.Disposable.create(() => 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) => { + logger24.error(e); + }); + } + dispose() { + if (this._disposed) + return; + 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) => { + }); + } + } + static createClient(binaryPath, root, channel) { + if (!isValidWatchRoot(root)) + return null; + let client = clientsMap.get(root); + if (client) + return client; + let promise = new Promise(async (resolve3, reject) => { + try { + let watchman2 = new Watchman(binaryPath, channel); + let valid = await watchman2.checkCapability(); + if (!valid) + return resolve3(null); + let watching = await watchman2.watchProject(root); + if (!watching) + return resolve3(null); + resolve3(watchman2); + } catch (e) { + reject(e); + } + }); + clientsMap.set(root, promise); + return promise; + } + }; + } +}); + +// package.json +var version; +var init_package = __esm({ + "package.json"() { + version = "0.0.80"; + } +}); + +// src/workspace.ts +var import_bytes, import_fast_diff2, import_fs_extra4, import_os4, import_path11, import_vscode_languageserver_protocol13, import_which2, APIVERSION, logger25, NAME_SPACE, methods, Workspace, workspace_default; +var init_workspace = __esm({ + "src/workspace.ts"() { + import_bytes = __toModule(require_bytes()); + import_fast_diff2 = __toModule(require_diff()); + import_fs_extra4 = __toModule(require_lib5()); + import_os4 = __toModule(require("os")); + import_path11 = __toModule(require("path")); + init_esm_node(); + import_vscode_languageserver_protocol13 = __toModule(require_main2()); + init_esm2(); + import_which2 = __toModule(require_which()); + init_channels(); + init_configuration2(); + init_shape(); + init_events(); + init_db(); + init_document(); + init_fileSystemWatcher(); + init_mru(); + init_resolver(); + init_task(); + init_terminal(); + init_bufferSync(); + init_types(); + init_array(); + init_fs(); + init_util(); + init_match(); + init_position(); + init_string(); + init_watchman(); + init_window(); + init_package(); + APIVERSION = 10; + logger25 = require_logger2()("workspace"); + NAME_SPACE = 2e3; + methods = [ + "showMessage", + "runTerminalCommand", + "openTerminal", + "showQuickpick", + "menuPick", + "openLocalConfig", + "showPrompt", + "createStatusBarItem", + "createOutputChannel", + "showOutputChannel", + "requestInput", + "echoLines", + "getCursorPosition", + "moveTo", + "getOffset" + ]; + Workspace = class { + constructor() { + this.keymaps = new Map(); + this.resolver = new Resolver(); + this.rootPatterns = new Map(); + this._workspaceFolders = []; + this._insertMode = false; + this._cwd = process.cwd(); + 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.schemeProviderMap = new Map(); + this.namespaceMap = new Map(); + this.disposables = []; + this.watchedOptions = new Set(); + this._dynAutocmd = false; + this._disposed = false; + this._onDidOpenDocument = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidCloseDocument = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidChangeDocument = new import_vscode_languageserver_protocol13.Emitter(); + this._onWillSaveDocument = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidSaveDocument = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidChangeWorkspaceFolders = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidChangeConfiguration = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidWorkspaceInitialized = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidOpenTerminal = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidCloseTerminal = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidRuntimePathChange = new import_vscode_languageserver_protocol13.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; + this.onDidRuntimePathChange = this._onDidRuntimePathChange.event; + this._onDidCreateFiles = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidRenameFiles = new import_vscode_languageserver_protocol13.Emitter(); + this._onDidDeleteFiles = new import_vscode_languageserver_protocol13.Emitter(); + this._onWillCreateFiles = new import_vscode_languageserver_protocol13.Emitter(); + this._onWillRenameFiles = new import_vscode_languageserver_protocol13.Emitter(); + this._onWillDeleteFiles = new import_vscode_languageserver_protocol13.Emitter(); + this.onDidCreateFiles = this._onDidCreateFiles.event; + this.onDidRenameFiles = this._onDidRenameFiles.event; + this.onDidDeleteFiles = this._onDidDeleteFiles.event; + this.onWillCreateFiles = this._onWillCreateFiles.event; + this.onWillRenameFiles = this._onWillRenameFiles.event; + this.onWillDeleteFiles = this._onWillDeleteFiles.event; + this.version = version; + this.configurations = this.createConfigurations(); + let cwd = process.cwd(); + if (cwd != import_os4.default.homedir() && inDirectory(cwd, [".vim"])) { + this._workspaceFolders.push({ + uri: URI.file(cwd).toString(), + name: import_path11.default.basename(cwd) + }); + } + } + async init() { + let { nvim } = this; + for (let method of methods) { + Object.defineProperty(this, method, { + get: () => { + return (...args) => { + return window_default[method].apply(window_default, args); + }; + } + }); + } + this._env = await nvim.call("coc#util#vim_info"); + if (this._env.apiversion != APIVERSION) { + console.error(`API version ${this._env.apiversion} is not ${APIVERSION}, please build coc.nvim by 'yarn install' after pull source code.`); + process.exit(); + } + this._insertMode = this._env.mode.startsWith("insert"); + if (this._env.workspaceFolders && Array.isArray(this._env.workspaceFolders)) { + this._workspaceFolders = this._env.workspaceFolders.map((f) => ({ + uri: URI.file(f).toString(), + name: import_path11.default.dirname(f) + })); + } + this.configurations.updateUserConfig(this._env.config); + let preferences = this.getConfiguration("coc.preferences"); + let maxFileSize = preferences.get("maxFileSize", "10MB"); + this.maxFileSize = import_bytes.default.parse(maxFileSize); + events_default.on(["InsertEnter", "CursorMovedI"], () => { + this._insertMode = true; + }, null, this.disposables); + events_default.on(["InsertLeave", "CursorMoved"], () => { + this._insertMode = false; + }, null, this.disposables); + events_default.on("BufEnter", this.onBufEnter, this, this.disposables); + events_default.on("CursorMoved", this.checkCurrentBuffer, this, this.disposables); + events_default.on("CursorMovedI", this.checkCurrentBuffer, this, this.disposables); + events_default.on("DirChanged", this.onDirChanged, this, this.disposables); + events_default.on("BufCreate", this.onBufCreate, this, this.disposables); + events_default.on("BufUnload", this.onBufUnload, this, this.disposables); + events_default.on("TermOpen", this.onBufCreate, this, this.disposables); + events_default.on("TermClose", this.onBufUnload, this, this.disposables); + events_default.on("BufWritePost", this.onBufWritePost, this, this.disposables); + events_default.on("BufWritePre", this.onBufWritePre, this, this.disposables); + events_default.on("FileType", this.onFileTypeChange, this, this.disposables); + events_default.on("CursorHold", this.checkCurrentBuffer, this, this.disposables); + events_default.on("TextChanged", this.checkBuffer, this, this.disposables); + events_default.on("BufReadCmd", this.onBufReadCmd, this, this.disposables); + events_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", (oldValue, newValue) => { + let result = (0, import_fast_diff2.default)(oldValue, newValue); + for (let [changeType, value] of result) { + if (changeType == 1) { + let paths = value.replace(/,$/, "").split(","); + this._onDidRuntimePathChange.fire(paths); + } + } + this._env.runtimepath = newValue; + }, this.disposables); + this.watchGlobal("coc_sources_disable_map", async (_, newValue) => { + this.env.disabledSources = newValue; + }); + this.disposables.push(this.registerTextDocumentContentProvider("output", channels_default.getProvider(nvim))); + } + getConfigFile(target) { + return this.configurations.getConfigFile(target); + } + registerAutocmd(autocmd) { + this.autocmdMaxId += 1; + let id = this.autocmdMaxId; + this.autocmds.set(id, autocmd); + this.setupDynamicAutocmd(); + return import_vscode_languageserver_protocol13.Disposable.create(() => { + this.autocmds.delete(id); + this.setupDynamicAutocmd(); + }); + } + watchOption(key, callback, disposables) { + let watching = this.watchedOptions.has(key); + if (!watching) { + this.watchedOptions.add(key); + this.setupDynamicAutocmd(); + } + let disposable = events_default.on("OptionSet", async (changed, oldValue, newValue) => { + if (changed == key && callback) { + await Promise.resolve(callback(oldValue, newValue)); + } + }); + if (disposables) { + disposables.push(import_vscode_languageserver_protocol13.Disposable.create(() => { + disposable.dispose(); + if (watching) + return; + this.watchedOptions.delete(key); + this.setupDynamicAutocmd(); + })); + } + } + watchGlobal(key, callback, disposables) { + let { nvim } = this; + nvim.call("coc#_watch", key, true); + let disposable = events_default.on("GlobalChange", async (changed, oldValue, newValue) => { + if (changed == key && callback) { + await Promise.resolve(callback(oldValue, newValue)); + } + }); + if (disposables) { + disposables.push(import_vscode_languageserver_protocol13.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; + } + get uri() { + let { bufnr } = this; + if (bufnr) { + let document2 = this.getDocument(bufnr); + if (document2 && document2.schema == "file") { + return document2.uri; + } + } + return null; + } + get workspaceFolder() { + let { rootPath } = this; + if (rootPath == import_os4.default.homedir()) + return null; + return { + uri: URI.file(rootPath).toString(), + name: import_path11.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(name2 = "") { + if (this.namespaceMap.has(name2)) + return this.namespaceMap.get(name2); + NAME_SPACE = NAME_SPACE + 1; + this.namespaceMap.set(name2, NAME_SPACE); + return NAME_SPACE; + } + get channelNames() { + return channels_default.names; + } + get pluginRoot() { + return import_path11.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((resolve3) => { + let disposable = this.onDidWorkspaceInitialized(() => { + disposable.dispose(); + resolve3(); + }); + }); + } + get filetypes() { + let res = new Set(); + for (let doc of this.documents) { + res.add(doc.filetype); + } + return res; + } + match(selector, document2) { + return score(selector, document2.uri, document2.languageId); + } + async findUp(filename) { + let { cwd } = this; + let filepath = await this.nvim.call("expand", "%:p"); + filepath = import_path11.default.normalize(filepath); + let isFile2 = filepath && import_path11.default.isAbsolute(filepath); + if (isFile2 && !isParentFolder(cwd, filepath, true)) { + return findUp(filename, import_path11.default.dirname(filepath)); + } + let res = findUp(filename, cwd); + if (res && res != import_os4.default.homedir()) + return res; + if (isFile2) + return findUp(filename, import_path11.default.dirname(filepath)); + return null; + } + async resolveRootFolder(uri, patterns) { + let { cwd } = this; + if (uri.scheme != "file") + return cwd; + let filepath = import_path11.default.normalize(uri.fsPath); + let dir = import_path11.default.dirname(filepath); + return resolveRoot(dir, patterns) || dir; + } + createFileSystemWatcher(globPattern, ignoreCreate, ignoreChange, ignoreDelete) { + let watchmanPath = global.hasOwnProperty("__TEST__") ? null : this.getWatchmanPath(); + let channel = watchmanPath ? window_default.createOutputChannel("watchman") : null; + let promise = watchmanPath ? Watchman.createClient(watchmanPath, this.root, channel) : Promise.resolve(null); + let watcher = new FileSystemWatcher(promise, globPattern, !!ignoreCreate, !!ignoreChange, !!ignoreDelete); + return watcher; + } + getWatchmanPath() { + const preferences = this.getConfiguration("coc.preferences"); + let watchmanPath = preferences.get("watchmanPath", "watchman"); + try { + return import_which2.default.sync(watchmanPath); + } catch (e) { + return null; + } + } + getConfiguration(section2, resource) { + return this.configurations.getConfiguration(section2, resource); + } + getDocument(uri) { + if (typeof uri === "number") { + return this.buffers.get(uri); + } + const caseInsensitive = platform_exports.isWindows || platform_exports.isMacintosh; + uri = URI.parse(uri).toString(); + for (let doc of this.buffers.values()) { + if (!doc) + continue; + if (doc.uri === uri) + return doc; + if (import_path11.default.resolve(doc.uri) === import_path11.default.resolve(uri)) + return doc; + if (caseInsensitive && doc.uri.toLowerCase() === uri.toLowerCase()) + return doc; + } + return null; + } + async applyEdit(edit2) { + let { nvim } = this; + let { documentChanges, changes } = edit2; + let [bufnr, cursor] = await nvim.eval('[bufnr("%"),coc#cursor#position()]'); + let document2 = this.getDocument(bufnr); + let uri = document2 ? document2.uri : null; + let currEdits = null; + let locations = []; + let changeCount = 0; + const preferences = this.getConfiguration("coc.preferences"); + let promptUser = !global.hasOwnProperty("__TEST__") && preferences.get("promptWorkspaceEdit", true); + let listTarget = preferences.get("listOfWorkspaceEdit", "quickfix"); + try { + if (documentChanges && documentChanges.length) { + let changedUris = this.getChangedUris(documentChanges); + changeCount = changedUris.length; + if (promptUser) { + let diskCount = changedUris.reduce((p, c) => { + return p + (this.getDocument(c) == null ? 1 : 0); + }, 0); + if (diskCount) { + let res = await window_default.showPrompt(`${diskCount} documents on disk would be loaded for change, confirm?`); + if (!res) + return; + } + } + let changedMap = new Map(); + for (const change of documentChanges) { + if (import_vscode_languageserver_protocol13.TextDocumentEdit.is(change)) { + let { textDocument, edits } = change; + let doc = await this.loadFile(textDocument.uri); + if (textDocument.uri == uri) + currEdits = edits; + await doc.applyEdits(edits); + for (let edit3 of edits) { + locations.push({ uri: doc.uri, range: edit3.range }); + } + } else if (import_vscode_languageserver_protocol13.CreateFile.is(change)) { + let file = URI.parse(change.uri).fsPath; + await this.createFile(file, change.options); + } else if (import_vscode_languageserver_protocol13.RenameFile.is(change)) { + changedMap.set(change.oldUri, change.newUri); + await this.renameFile(URI.parse(change.oldUri).fsPath, URI.parse(change.newUri).fsPath, change.options); + } else if (import_vscode_languageserver_protocol13.DeleteFile.is(change)) { + await this.deleteFile(URI.parse(change.uri).fsPath, change.options); + } + } + if (changedMap.size) { + locations.forEach((location) => { + let newUri = changedMap.get(location.uri); + if (newUri) + location.uri = newUri; + }); + } + } else if (changes) { + let uris = Object.keys(changes); + let unloaded = uris.filter((uri2) => this.getDocument(uri2) == null); + if (unloaded.length) { + if (promptUser) { + let res = await window_default.showPrompt(`${unloaded.length} documents on disk would be loaded for change, confirm?`); + if (!res) + return; + } + await this.loadFiles(unloaded); + } + for (let uri2 of Object.keys(changes)) { + let document3 = this.getDocument(uri2); + if (URI.parse(uri2).toString() == uri2) + currEdits = changes[uri2]; + let edits = changes[uri2]; + for (let edit3 of edits) { + locations.push({ uri: document3.uri, range: edit3.range }); + } + await document3.applyEdits(edits); + } + changeCount = uris.length; + } + if (currEdits) { + let changed = getChangedFromEdits({ line: cursor[0], character: cursor[1] }, currEdits); + if (changed) + await window_default.moveTo({ + line: cursor[0] + changed.line, + character: cursor[1] + changed.character + }); + } + if (locations.length) { + let items = await Promise.all(locations.map((loc) => this.getQuickfixItem(loc))); + let silent = locations.every((l) => l.uri == uri); + if (listTarget == "quickfix") { + await this.nvim.call("setqflist", [items]); + if (!silent) + window_default.showMessage(`changed ${changeCount} buffers, use :wa to save changes to disk and :copen to open quickfix list`, "more"); + } else if (listTarget == "location") { + await nvim.setVar("coc_jump_locations", items); + if (!silent) + window_default.showMessage(`changed ${changeCount} buffers, use :wa to save changes to disk and :CocList location to manage changed locations`, "more"); + } + } + } catch (e) { + logger25.error("Error on applyEdits:", edit2, e); + window_default.showMessage(`Error on applyEdits: ${e.message}`, "error"); + return false; + } + await wait(50); + return true; + } + async getQuickfixItem(loc, text, type = "", module2) { + if (import_vscode_languageserver_protocol13.LocationLink.is(loc)) { + loc = import_vscode_languageserver_protocol13.Location.create(loc.targetUri, loc.targetRange); + } + let doc = this.getDocument(loc.uri); + let { uri, range } = loc; + let { line, character } = range.start; + let sl = range.start.line; + let sc = range.start.character; + let el = range.end.line; + let ec = range.end.character; + let u = URI.parse(uri); + let bufnr = doc ? doc.bufnr : -1; + if (!text && u.scheme == "file") { + text = await this.getLine(uri, line); + character = byteIndex(text, character); + } + let item = { + uri, + filename: u.scheme == "file" ? u.fsPath : uri, + lnum: sl + 1, + end_lnum: el + 1, + col: sc + 1, + end_col: ec + 1, + text: text || "", + range + }; + if (module2) + item.module = module2; + if (type) + item.type = type; + if (bufnr != -1) + item.bufnr = bufnr; + return item; + } + createMru(name2) { + return new Mru(name2); + } + async getSelectedRange(mode, document2) { + let { nvim } = this; + if (mode === "line") { + let line = await nvim.call("line", ["."]); + let content = document2.getline(line - 1); + if (!content.length) + return null; + return import_vscode_languageserver_protocol13.Range.create(line - 1, 0, line, 0); + } + if (mode === "cursor") { + let [line, character] = await nvim.eval("coc#cursor#position()"); + return import_vscode_languageserver_protocol13.Range.create(line, character, line, character); + } + if (!["v", "V", "char", "line", ""].includes(mode)) { + throw new Error(`Mode '${mode}' not supported`); + } + let isVisual = ["v", "V", ""].includes(mode); + let [, sl, sc] = await nvim.call("getpos", isVisual ? `'<` : `'[`); + let [, el, ec] = await nvim.call("getpos", isVisual ? `'>` : `']`); + let range = import_vscode_languageserver_protocol13.Range.create(document2.getPosition(sl, sc), document2.getPosition(el, ec)); + if (mode == "v" || mode == "") { + range.end.character = range.end.character + 1; + } + return range; + } + async selectRange(range) { + let { nvim } = this; + let { start, end } = range; + let [bufnr, ve, selection] = await nvim.eval(`[bufnr('%'), &virtualedit, &selection]`); + let doc = this.getDocument(bufnr); + if (!doc || !doc.attached) + return; + let line = doc.getline(start.line); + let col = line ? byteLength(line.slice(0, start.character)) : 0; + let endLine = doc.getline(end.line); + let endCol = endLine ? 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.command(`normal! ${move_cmd}`, true); + if (resetVirtualEdit) + nvim.setOption("virtualedit", ve, true); + if (this.isVim) + nvim.command("redraw", true); + await nvim.resumeNotification(); + } + async showLocations(locations) { + let items = await Promise.all(locations.map((loc) => this.getQuickfixItem(loc))); + let { nvim } = this; + const preferences = this.getConfiguration("coc.preferences"); + if (preferences.get("useQuickfixForLocations", false)) { + let openCommand = await nvim.getVar("coc_quickfix_open_command"); + if (typeof openCommand != "string") { + openCommand = items.length < 10 ? `copen ${items.length}` : "copen"; + } + nvim.pauseNotification(); + nvim.call("setqflist", [items], true); + nvim.command(openCommand, true); + nvim.resumeNotification(false, true); + } else { + await nvim.setVar("coc_jump_locations", items); + if (this.env.locationlist) { + nvim.command("CocList --normal --auto-preview location", true); + } else { + nvim.call("coc#util#do_autocmd", ["CocLocationsChange"], true); + } + } + } + async getLine(uri, line) { + let document2 = this.getDocument(uri); + if (document2) + return document2.getline(line) || ""; + if (!uri.startsWith("file:")) + return ""; + let fsPath = URI.parse(uri).fsPath; + if (!import_fs_extra4.default.existsSync(fsPath)) + return ""; + return await readFileLine(fsPath, line); + } + getWorkspaceFolder(uri) { + this.workspaceFolders.sort((a, b) => b.uri.length - a.uri.length); + let filepath = URI.parse(uri).fsPath; + return this.workspaceFolders.find((folder) => isParentFolder(URI.parse(folder.uri).fsPath, filepath, true)); + } + async readFile(uri) { + let document2 = this.getDocument(uri); + if (document2) { + await document2.patchChange(); + return document2.content; + } + let u = URI.parse(uri); + if (u.scheme != "file") + return ""; + let lines = await this.nvim.call("readfile", [u.fsPath]); + return lines.join("\n") + "\n"; + } + get document() { + return new Promise((resolve3, reject) => { + this.nvim.buffer.then((buf) => { + let bufnr = buf.id; + this.bufnr = bufnr; + if (this.buffers.has(bufnr)) { + resolve3(this.buffers.get(bufnr)); + return; + } + this.onBufCreate(bufnr).catch(reject); + let disposable = this.onDidOpenTextDocument((doc) => { + disposable.dispose(); + resolve3(this.getDocument(doc.uri)); + }); + }, reject); + }); + } + async getCurrentState() { + let document2 = await this.document; + let position = await window_default.getCursorPosition(); + return { + document: document2.textDocument, + position + }; + } + async getFormatOptions(uri) { + let doc; + if (uri) + doc = this.getDocument(uri); + let bufnr = doc ? doc.bufnr : 0; + let [tabSize, insertSpaces] = await this.nvim.call("coc#util#get_format_opts", [bufnr]); + return { + tabSize, + insertSpaces: insertSpaces == 1 + }; + } + 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; + if (bufnr != -1 && jumpCommand == "edit") { + nvim.pauseNotification(); + nvim.command(`silent! normal! m'`, true); + nvim.command(`buffer ${bufnr}`, true); + if (position) { + let line = doc.getline(position.line); + let col = byteLength(line.slice(0, position.character)) + 1; + nvim.call("cursor", [position.line + 1, col], true); + } + if (this.isVim) + nvim.command("redraw", true); + await nvim.resumeNotification(); + } else { + let { fsPath, scheme } = URI.parse(uri); + let pos = position == null ? null : [position.line, position.character]; + if (scheme == "file") { + let bufname = fixDriver(import_path11.default.normalize(fsPath)); + await this.nvim.call("coc#util#jump", [jumpCommand, bufname, pos]); + } else { + if (import_os4.default.platform() == "win32") { + uri = uri.replace(/\/?/, "?"); + } + await this.nvim.call("coc#util#jump", [jumpCommand, uri, pos]); + } + } + } + async createFile(filepath, opts = {}) { + let stat = await statAsync(filepath); + if (stat && !opts.overwrite && !opts.ignoreIfExists) { + window_default.showMessage(`${filepath} already exists!`, "error"); + return; + } + if (!stat || opts.overwrite) { + if (filepath.endsWith("/")) { + try { + filepath = this.expand(filepath); + await import_fs_extra4.default.mkdirp(filepath); + } catch (e) { + window_default.showMessage(`Can't create ${filepath}: ${e.message}`, "error"); + } + } else { + let uri = URI.file(filepath).toString(); + let doc = this.getDocument(uri); + if (doc) + return; + if (!import_fs_extra4.default.existsSync(import_path11.default.dirname(filepath))) { + import_fs_extra4.default.mkdirpSync(import_path11.default.dirname(filepath)); + } + import_fs_extra4.default.writeFileSync(filepath, "", "utf8"); + await this.loadFile(uri); + } + } + } + async loadFile(uri) { + let doc = this.getDocument(uri); + if (doc) + return doc; + let { nvim } = this; + let filepath = uri.startsWith("file") ? URI.parse(uri).fsPath : uri; + nvim.call("coc#util#open_files", [[filepath]], true); + return await new Promise((resolve3, reject) => { + let disposable = this.onDidOpenTextDocument((textDocument) => { + let fsPath = URI.parse(textDocument.uri).fsPath; + if (textDocument.uri == uri || fsPath == filepath) { + clearTimeout(timer); + disposable.dispose(); + resolve3(this.getDocument(uri)); + } + }); + let timer = setTimeout(() => { + disposable.dispose(); + reject(new Error(`Create document ${uri} timeout after 1s.`)); + }, 1e3); + }); + } + 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) => URI.parse(u).fsPath)]); + let create = bufnrs.filter((bufnr) => this.getDocument(bufnr) == null); + if (!create.length) + return; + return new Promise((resolve3, reject) => { + let timer = setTimeout(() => { + disposable.dispose(); + reject(new Error(`Create document timeout after 2s.`)); + }, 2e3); + let disposable = this.onDidOpenTextDocument(() => { + if (uris.every((uri) => this.getDocument(uri) != null)) { + clearTimeout(timer); + disposable.dispose(); + resolve3(); + } + }); + }); + } + async renameFile(oldPath, newPath, opts = {}) { + let { overwrite, ignoreIfExists } = opts; + let { nvim } = this; + try { + let stat = await statAsync(newPath); + if (stat && !overwrite && !ignoreIfExists) { + throw new Error(`${newPath} already exists`); + } + if (!stat || overwrite) { + let uri = URI.file(oldPath).toString(); + let newUri = URI.file(newPath).toString(); + let doc = this.getDocument(uri); + if (doc != null) { + let isCurrent = doc.bufnr == this.bufnr; + let newDoc = this.getDocument(newUri); + if (newDoc) + await this.nvim.command(`silent ${newDoc.bufnr}bwipeout!`); + let content = doc.getDocumentContent(); + await import_fs_extra4.default.writeFile(newPath, content, "utf8"); + if (!isCurrent) { + await nvim.call("coc#util#open_files", [[newPath]]); + await nvim.command(`silent ${doc.bufnr}bwipeout!`); + } else { + let view = await nvim.call("winsaveview"); + nvim.pauseNotification(); + nvim.call("coc#util#open_file", ["keepalt edit", newPath], true); + nvim.command(`silent ${doc.bufnr}bwipeout!`, true); + nvim.call("winrestview", [view], true); + await nvim.resumeNotification(); + } + await import_fs_extra4.default.unlink(oldPath); + } else { + await renameAsync(oldPath, newPath); + } + } + } catch (e) { + window_default.showMessage(`Rename error: ${e.message}`, "error"); + } + } + async deleteFile(filepath, opts = {}) { + let { ignoreIfNotExists, recursive } = opts; + let stat = await statAsync(filepath.replace(/\/$/, "")); + let isDir = stat && stat.isDirectory(); + if (filepath.endsWith("/") && !isDir) { + window_default.showMessage(`${filepath} is not directory`, "error"); + return; + } + if (!stat && !ignoreIfNotExists) { + window_default.showMessage(`${filepath} not exists`, "error"); + return; + } + if (stat == null) + return; + if (isDir && !recursive) { + window_default.showMessage(`Can't remove directory, recursive not set`, "error"); + return; + } + try { + if (isDir && recursive) { + await import_fs_extra4.default.remove(filepath); + } else if (isDir) { + await import_fs_extra4.default.rmdir(filepath); + } else { + await import_fs_extra4.default.unlink(filepath); + } + if (!isDir) { + let uri = URI.file(filepath).toString(); + let doc = this.getDocument(uri); + if (doc) + await this.nvim.command(`silent! bwipeout! ${doc.bufnr}`); + } + } catch (e) { + window_default.showMessage(`Error on delete ${filepath}: ${e.message}`, "error"); + } + } + async openResource(uri) { + let { nvim } = this; + 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); + } + async resolveModule(name2) { + return await this.resolver.resolveModule(name2); + } + async runCommand(cmd, cwd, timeout) { + cwd = cwd || this.cwd; + return runCommand(cmd, { cwd }, timeout); + } + expand(filepath) { + if (!filepath) + return filepath; + if (filepath.startsWith("~")) { + filepath = import_os4.default.homedir() + filepath.slice(1); + } + if (filepath.includes("$")) { + let doc = this.getDocument(this.bufnr); + let fsPath = doc ? URI.parse(doc.uri).fsPath : ""; + filepath = filepath.replace(/\$\{(.*?)\}/g, (match, name2) => { + if (name2.startsWith("env:")) { + let key = name2.split(":")[1]; + let val = key ? process.env[key] : ""; + return val; + } + switch (name2) { + case "workspace": + case "workspaceRoot": + case "workspaceFolder": + return this.root; + case "workspaceFolderBasename": + return import_path11.default.dirname(this.root); + case "cwd": + return this.cwd; + case "file": + return fsPath; + case "fileDirname": + return fsPath ? import_path11.default.dirname(fsPath) : ""; + case "fileExtname": + return fsPath ? import_path11.default.extname(fsPath) : ""; + case "fileBasename": + return fsPath ? import_path11.default.basename(fsPath) : ""; + case "fileBasenameNoExtension": { + let basename = fsPath ? import_path11.default.basename(fsPath) : ""; + return basename ? basename.slice(0, basename.length - import_path11.default.extname(basename).length) : ""; + } + default: + return match; + } + }); + filepath = filepath.replace(/\$[\w]+/g, (match) => { + if (match == "$HOME") + return import_os4.default.homedir(); + return process.env[match.slice(1)] || match; + }); + } + return filepath; + } + async createTerminal(opts) { + let cmd = opts.shellPath; + let args = opts.shellArgs; + if (!cmd) + cmd = await this.nvim.getOption("shell"); + let terminal = new TerminalModel(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; + } + 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]); + } + registerTextDocumentContentProvider(scheme, provider) { + this.schemeProviderMap.set(scheme, provider); + this.setupDynamicAutocmd(); + let disposables = []; + if (provider.onDidChange) { + provider.onDidChange(async (uri) => { + let doc = this.getDocument(uri.toString()); + if (doc) { + let { buffer } = doc; + let tokenSource = new import_vscode_languageserver_protocol13.CancellationTokenSource(); + let content = await Promise.resolve(provider.provideTextDocumentContent(uri, tokenSource.token)); + await buffer.setLines(content.split(/\r?\n/), { + start: 0, + end: -1, + strictIndexing: false + }); + } + }, null, disposables); + } + return import_vscode_languageserver_protocol13.Disposable.create(() => { + this.schemeProviderMap.delete(scheme); + disposeAll(disposables); + this.setupDynamicAutocmd(); + }); + } + registerKeymap(modes, key, fn, opts = {}) { + if (!key) + throw new Error(`Invalid key ${key} of registerKeymap`); + if (this.keymaps.has(key)) + throw new Error(`${key} already exists.`); + 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 ? "" : ""; + for (let m of modes) { + if (m == "i") { + nvim.command(`inoremap ${silent} (coc-${key}) coc#_insert_key('${method}', '${key}', ${opts.cancel ? 1 : 0})`, true); + } else { + let modify2 = getKeymapModifier(m); + nvim.command(`${m}noremap ${silent} (coc-${key}) :${modify2}call coc#rpc#${method}('doKeymap', ['${key}'])`, true); + } + } + return import_vscode_languageserver_protocol13.Disposable.create(() => { + this.keymaps.delete(key); + for (let m of modes) { + nvim.command(`${m}unmap (coc-${key})`, true); + } + }); + } + registerExprKeymap(mode, key, fn, buffer = false) { + if (!key) + return; + let id = `${mode}${global.Buffer.from(key).toString("base64")}${buffer ? "1" : "0"}`; + let { nvim } = this; + this.keymaps.set(id, [fn, false]); + if (mode == "i") { + nvim.command(`inoremap ${buffer ? "" : ""} ${key} coc#_insert_key('request', '${id}')`, true); + } else { + nvim.command(`${mode}noremap ${buffer ? "" : ""} ${key} coc#rpc#request('doKeymap', ['${id}'])`, true); + } + return import_vscode_languageserver_protocol13.Disposable.create(() => { + this.keymaps.delete(id); + nvim.command(`${mode}unmap ${buffer ? "" : ""} ${key}`, true); + }); + } + registerLocalKeymap(mode, key, fn, notify = false) { + let id = v1_default(); + let { nvim, bufnr } = this; + this.keymaps.set(id, [fn, false]); + let method = notify ? "notify" : "request"; + let modify2 = getKeymapModifier(mode); + let escaped = key.startsWith("<") && key.endsWith(">") ? `{${key.slice(1, -1)}}` : key; + if (this.isNvim && !global.hasOwnProperty("__TEST__")) { + nvim.call("nvim_buf_set_keymap", [0, mode, key, `:${modify2}call coc#rpc#${method}('doKeymap', ['${id}', '', '${escaped}'])`, { + silent: true, + nowait: true + }], true); + } else { + let cmd = `${mode}noremap ${key} :${modify2}call coc#rpc#${method}('doKeymap', ['${id}', '', '${escaped}'])`; + nvim.command(cmd, true); + } + return import_vscode_languageserver_protocol13.Disposable.create(() => { + this.keymaps.delete(id); + nvim.call("coc#compat#buf_del_keymap", [bufnr, mode, key], true); + }); + } + createDatabase(name2) { + let root; + if (global.hasOwnProperty("__TEST__")) { + root = import_path11.default.join(import_os4.default.tmpdir(), `coc-${process.pid}`); + import_fs_extra4.default.mkdirpSync(root); + } else { + root = import_path11.default.dirname(this.env.extensionRoot); + } + let filepath = import_path11.default.join(root, name2 + ".json"); + return new DB(filepath); + } + createTask(id) { + return new Task(this.nvim, id); + } + registerBufferSync(create) { + return new BufferSync(create, this); + } + setupDynamicAutocmd(initialize = false) { + if (!initialize && !this._dynAutocmd) + return; + this._dynAutocmd = true; + 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('')])`); + } + 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 = autocmd.pattern != null ? autocmd.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(''), v:option_old, v:option_new])`); + } + let content = ` augroup coc_dynamic_autocmd autocmd! - ${i.join(` - `)} -augroup end`;try{let o=Fe.default.join(process.env.TMPDIR,`coc.nvim-${process.pid}`);St.default.existsSync(o)||St.default.mkdirpSync(o);let s=Fe.default.join(o,`coc-${process.pid}.vim`);St.default.writeFileSync(s,n,"utf8");let a=`source ${s}`;this.env.isCygwin&&Pl.isWindows&&(a=`execute "source" . substitute(system('cygpath ${s.replace(/\\/g,"/")}'), '\\n', '', 'g')`),this.nvim.command(a).logError()}catch(o){C.showMessage(`Can't create tmp file: ${o.message}`,"error")}}async onBufReadCmd(e,t){let i=this.schemeProviderMap.get(e);if(!i){C.showMessage(`Provider for ${e} not found`,"error");return}let n=new le.CancellationTokenSource,o=await Promise.resolve(i.provideTextDocumentContent($.parse(t),n.token)),s=await this.nvim.buffer;await s.setLines(o.split(/\r?\n/),{start:0,end:-1,strictIndexing:!1}),setTimeout(async()=>{await A.fire("BufCreate",[s.id])},30)}async attach(){if(this._attached)return;this._attached=!0;let[e,t,i]=await this.nvim.eval(`[map(getbufinfo({'bufloaded': 1}),'v:val["bufnr"]'),bufnr('%'),win_getid()]`);this.bufnr=t,await Promise.all(e.map(n=>this.onBufCreate(n))),this._initialized||(this._onDidWorkspaceInitialized.fire(void 0),this._initialized=!0),await A.fire("BufEnter",[t]),await A.fire("BufWinEnter",[t,i])}getChangedUris(e){let t=new Set,i=new Set;for(let n of e)if(le.TextDocumentEdit.is(n)){let{textDocument:o}=n,{uri:s,version:a}=o;if(t.add(s),a!=null&&a>0){let l=this.getDocument(s);if(!l)throw new Error(`${s} not loaded`);if(l.version!=a)throw new Error(`${s} changed before apply edit`)}}else if(le.CreateFile.is(n)||le.DeleteFile.is(n)){if(!Qm(n.uri))throw new Error(`change of scheme ${n.uri} not supported`);i.add(n.uri),t.add(n.uri)}else if(le.RenameFile.is(n)){if(!Qm(n.oldUri)||!Qm(n.newUri))throw new Error(`change of scheme ${n.oldUri} not supported`);let o=$.parse(n.newUri).fsPath;if(St.default.existsSync(o))throw new Error(`file "${o}" already exists for rename`);t.add(n.oldUri)}else throw new Error(`Invalid document change: ${JSON.stringify(n,null,2)}`);return Array.from(t)}createConfigurations(){let e=Fe.default.normalize(process.env.COC_VIMCONFIG)||Fe.default.join(Qi.default.homedir(),".vim"),t=Fe.default.join(e,Gi);return new rj(t,new ij(this))}attachChangedEvents(){if(this.isVim){let e=t=>{let i=this.getDocument(t);i&&i.attached&&i.fetchContent()};A.on("TextChangedI",e,null,this.disposables),A.on("TextChanged",e,null,this.disposables)}}async onBufCreate(e){let t=typeof e=="number"?this.nvim.createBuffer(e):e,i=t.id;if(this.creatingSources.has(i))return;let n=this.getDocument(i),o=new le.CancellationTokenSource;try{n&&this.onBufUnload(i,!0),n=new rg(t,this._env,this.maxFileSize);let s=o.token;this.creatingSources.set(i,o),await n.init(this.nvim,s)||(n=null)}catch(s){lp.error("Error on create buffer:",s),n=null}if(this.creatingSources.get(i)==o&&(o.dispose(),this.creatingSources.delete(i)),!(!n||!n.textDocument)){if(this.buffers.set(i,n),n.attached&&n.onDocumentDetach(s=>{let a=this.getDocument(s);a&&this.onBufUnload(a.bufnr)}),n.buftype==""&&n.schema=="file"&&(this.configurations.checkFolderConfiguration(n.uri),!this.getConfiguration("workspace").get("ignoredFiletypes",[]).includes(n.filetype))){let l=this.resolveRoot(n);l&&(this.addWorkspaceFolder(l),this.bufnr==t.id&&(this._root=l))}if(n.enabled){let s=Object.assign(n.textDocument,{bufnr:i});this._onDidOpenDocument.fire(s),n.onDocumentChange(a=>this._onDidChangeDocument.fire(a))}lp.debug("buffer created",t.id)}}onBufEnter(e){this.bufnr=e;let t=this.getDocument(e);if(t){this.configurations.setFolderConfiguration(t.uri);let i=this.getWorkspaceFolder(t.uri);i&&(this._root=$.parse(i.uri).fsPath)}}async checkCurrentBuffer(e){this.bufnr=e,await this.checkBuffer(e)}onBufWritePost(e){let t=this.buffers.get(e);!t||this._onDidSaveDocument.fire(t.textDocument)}onBufUnload(e,t=!1){if(lp.debug("buffer unload",e),!t){let n=this.creatingSources.get(e);n&&(n.cancel(),this.creatingSources.delete(e))}if(this.terminals.has(e)){let n=this.terminals.get(e);this._onDidCloseTerminal.fire(n),this.terminals.delete(e)}let i=this.buffers.get(e);if(i){let n=Object.assign(i.textDocument,{bufnr:e});this._onDidCloseDocument.fire(n),this.buffers.delete(e),i.detach()}}async onBufWritePre(e){let t=this.buffers.get(e);if(!t||!t.attached)return;await t.checkDocument();let i=!0,n=[],o={document:t.textDocument,reason:le.TextDocumentSaveReason.Manual,waitUntil:a=>{i?n.push(a):(lp.error("Can't call waitUntil in async manner:",Error().stack),C.showMessage("waitUntil can't be used in async manner, check log for details","error"))}};this._onWillSaveDocument.fire(o),i=!1;let s=n.length;if(s){let l=await new Promise(u=>{let f=this.getConfiguration("coc.preferences").get("willSaveHandlerTimeout",500),p=setTimeout(()=>{C.showMessage(`Will save handler timeout after ${f}ms`,"warning"),u(void 0)},f),d=0,h=!1;for(let m of n){let y=g=>{h||(h=!0,clearTimeout(p),u(g))};m.then(g=>{if(Array.isArray(g)&&g.length&&le.TextEdit.is(g[0]))return y(g);d=d+1,d==s&&y(void 0)},()=>{d=d+1,d==s&&y(void 0)})}});l&&await t.applyEdits(l)}}onDirChanged(e){e!=this._cwd&&(this._cwd=e)}onFileTypeChange(e,t){let i=this.getDocument(t);if(!i||i.convertFiletype(e)==i.filetype)return;let o=Object.assign(i.textDocument,{bufnr:t});this._onDidCloseDocument.fire(o),i.setFiletype(e),this._onDidOpenDocument.fire(Object.assign(i.textDocument,{bufnr:t}))}async checkBuffer(e){if(this._disposed||!e)return;!this.getDocument(e)&&!this.creatingSources.has(e)&&await this.onBufCreate(e)}resolveRoot(e){let t=[Jr.Buffer,Jr.LanguageServer,Jr.Global],i=$.parse(e.uri),n=Fe.default.dirname(i.fsPath),{cwd:o}=this,s=this.getConfiguration("workspace"),a=s.get("bottomUpFiletypes",[]),l=s.get("workspaceFolderCheckCwd",!0);for(let u of t){let c=this.getRootPatterns(e,u);if(c&&c.length){let f=a.includes(e.filetype),p=Qf(n,c,o,f,l);if(p)return p}}return this.cwd!=Qi.default.homedir()&&Xe(this.cwd,n,!0)?this.cwd:null}getRootPatterns(e,t){let{uri:i}=e;return t==Jr.Buffer?e.getVar("root_patterns",[])||[]:t==Jr.LanguageServer?this.getServerRootPatterns(e.filetype):this.getConfiguration("coc.preferences",i).get("rootPatterns",[".git",".hg",".projections.json"]).slice()}async renameCurrent(){let{nvim:e}=this,t=await e.call("bufnr","%"),i=await e.call("getcwd"),n=this.getDocument(t);if(!n||n.buftype!=""||n.schema!="file"){e.errWriteLine("current buffer is not file.");return}let o=$.parse(n.uri).fsPath,s=await e.callAsync("coc#util#with_callback",["input",["New path: ",o,"file"]]);if(s=s?s.trim():null,s==o||!s)return;let a=await n.buffer.lines,l=St.default.existsSync(o);if(l){if(await e.eval("&modified")&&await e.command("noa w"),o.toLowerCase()!=s.toLowerCase()&&St.default.existsSync(s)){if(!await C.showPrompt(`${s} exists, overwrite?`))return;St.default.unlinkSync(s)}St.default.renameSync(o,s)}let u=Xe(i,s)?Fe.default.relative(i,s):s,c=await e.call("winsaveview");e.pauseNotification(),o.toLowerCase()==s.toLowerCase()?(e.command(`keepalt ${t}bwipeout!`,!0),e.call("coc#util#open_file",["keepalt edit",u],!0)):(e.call("coc#util#open_file",["keepalt edit",u],!0),e.command(`${t}bwipeout!`,!0)),!l&&a.join(` -`)!=` -`&&(e.call("append",[0,a],!0),e.command("normal! Gdd",!0)),e.call("winrestview",[c],!0),await e.resumeNotification()}get folderPaths(){return this.workspaceFolders.map(e=>$.parse(e.uri).fsPath)}get floatSupported(){let{env:e}=this;return e.floating||e.textprop}removeWorkspaceFolder(e){let t=this._workspaceFolders.findIndex(i=>$.parse(i.uri).fsPath==e);if(t!=-1){let i=this._workspaceFolders[t];this._workspaceFolders.splice(t,1),this._onDidChangeWorkspaceFolders.fire({removed:[i],added:[]})}}renameWorkspaceFolder(e,t){let i=this._workspaceFolders.findIndex(s=>$.parse(s.uri).fsPath==e);if(i==-1)return;let n=this._workspaceFolders[i],o={uri:$.file(t).toString(),name:Fe.default.dirname(t)};this._workspaceFolders.splice(i,1),this._workspaceFolders.push(o),this._onDidChangeWorkspaceFolders.fire({removed:[n],added:[o]})}addRootPattern(e,t){let i=this.rootPatterns.get(e)||[];for(let n of t)i.includes(n)||i.push(n);this.rootPatterns.set(e,i)}get insertMode(){return this._insertMode}async detach(){if(!!this._attached){this._attached=!1,Qs.dispose();for(let e of this.buffers.keys())await A.fire("BufUnload",[e])}}dispose(){this._disposed=!0;for(let e of this.documents)e.detach();z(this.disposables),ia.dispose(),this.configurations.dispose(),this.buffers.clear()}addWorkspaceFolder(e){if(e==Qi.default.homedir())return;let{_workspaceFolders:t}=this,i=$.file(e).toString(),n={uri:i,name:Fe.default.basename(e)};return t.findIndex(o=>o.uri==i)==-1&&(t.push(n),this._initialized&&this._onDidChangeWorkspaceFolders.fire({added:[n],removed:[]})),n}getServerRootPatterns(e){let t=this.getConfiguration().get("languageserver",{}),i=[];for(let n of Object.keys(t)){let o=t[n],{filetypes:s,rootPatterns:a}=o;s&&a&&s.includes(e)&&i.push(...a)}return i=i.concat(this.rootPatterns.get(e)||[]),i.length?ng(i):null}},b=new zj;var Zl=U()("window"),Kj=class{constructor(){this.mutex=new ar}get nvim(){return b.nvim}dispose(){var e;(e=this.statusLine)==null||e.dispose()}showMessage(e,t="more"){if(this.mutex.busy||!this.nvim)return;let{messageLevel:i}=this,n=process.env.VIM_NODE_RPC=="1"?"callTimer":"call";global.hasOwnProperty("__TEST__")&&Zl.info(e);let o="Error",s=gn.Error;switch(t){case"more":s=gn.More,o="MoreMsg";break;case"warning":s=gn.Warning,o="WarningMsg";break}s>=i&&this.nvim[n]("coc#util#echo_messages",[o,("[coc.nvim] "+e).split(` -`)],!0)}async runTerminalCommand(e,t,i=!1){return t=t||b.cwd,await this.nvim.callAsync("coc#util#run_terminal",{cmd:e,cwd:t,keepfocus:i?1:0})}async openTerminal(e,t={}){return await this.nvim.call("coc#util#open_terminal",{cmd:e,...t})}async showQuickpick(e,t="Choose by number"){let i=await this.mutex.acquire();try{let n=t+":";e=e.map((a,l)=>`${l+1}. ${a}`);let o=await this.nvim.callAsync("coc#util#quickpick",[n,e.map(a=>a.trim())]);i();let s=parseInt(o,10);return isNaN(s)||s<=0||s>e.length?-1:s-1}catch(n){return i(),-1}}async showMenuPicker(e,t,i){if(b.env.dialog){let n=await this.mutex.acquire();if(i&&i.isCancellationRequested){n();return}try{let o=new JB(this.nvim,{items:e.map(l=>l.trim()),title:t},i),s=new Promise(l=>{o.onDidClose(u=>{l(u)})});await o.show(this.dialogPreference);let a=await s;return n(),a}catch(o){Zl.error("Error on showMenuPicker:",o),n()}}return await this.showQuickpick(e)}async openLocalConfig(){let{root:e}=b;if(e==Gj.default.homedir()){this.showMessage("Can't create local config in home directory","warning");return}let t=E0.default.join(e,".vim");if(!S0.default.existsSync(t)){if(!await this.showPrompt(`Would you like to create folder'${e}/.vim'?`))return;S0.default.mkdirSync(t)}await b.jumpTo($.file(E0.default.join(t,Gi)).toString())}async showPrompt(e){let t=await this.mutex.acquire();try{let i=await this.nvim.callAsync("coc#float#prompt_confirm",[e]);return t(),i==1}catch(i){return t(),!1}}async showDialog(e){if(!this.checkDialog())return null;let t=new VB(this.nvim,e);return await t.show(this.dialogPreference),t}async requestInput(e,t){let{nvim:i}=this,n=b.getConfiguration("coc.preferences");if(b.env.dialog&&n.get("promptInput",!0)&&!Hn){let o=await this.mutex.acquire(),s=this.dialogPreference;try{let a={};s.floatHighlight&&(a.highlight=s.floatHighlight),s.floatBorderHighlight&&(a.borderhighlight=s.floatBorderHighlight);let l=await i.call("coc#float#create_prompt_win",[e,t||"",a]),[u,c]=l,f=await new Promise(p=>{let d=[];A.on("BufWinLeave",h=>{h==u&&(z(d),p(null))},null,d),A.on("PromptInsert",async h=>{z(d),await i.call("coc#float#close",[c]),h?p(h):(this.showMessage("Empty word, canceled","warning"),p(null))},null,d)});return o(),f}catch(a){Zl.error("Error on requestInput:",a),o()}}else{let o=await b.callAsync("input",[e+": ",t||""]);return i.command("normal! :",!0),o||(this.showMessage("Empty word, canceled","warning"),null)}}createStatusBarItem(e=0,t={}){if(!b.env){let i=()=>{};return{text:"",show:i,dispose:i,hide:i,priority:0,isProgress:!1}}return this.statusLine||(this.statusLine=new o3(this.nvim)),this.statusLine.createStatusBarItem(e,t.progress||!1)}createOutputChannel(e){return Qs.create(e,this.nvim)}showOutputChannel(e,t){Qs.show(e,t)}async echoLines(e,t=!1){let{nvim:i}=this,n=b.env.cmdheight;e.length>n&&t&&(e=e.slice(0,n));let o=b.env.columns-12;if(e=e.map(s=>(s=s.replace(/\n/g," "),t&&(s=s.slice(0,o)),s)),t&&e.length==n){let s=e[e.length-1];e[n-1]=`${s.length==o?s.slice(0,-4):s} ...`}await i.call("coc#util#echo_lines",[e])}async getCursorPosition(){let[e,t]=await this.nvim.eval("[line('.')-1, strpart(getline('.'), 0, col('.') - 1)]");return Vj.Position.create(e,t.length)}async moveTo(e){await this.nvim.call("coc#util#jumpTo",[e.line,e.character]),b.env.isVim&&this.nvim.command("redraw",!0)}async getOffset(){return await this.nvim.call("coc#util#get_offset")}async getCursorScreenPosition(){let[e,t]=await this.nvim.call("coc#util#cursor_pos");return{row:e,col:t}}async showPickerDialog(e,t,i){if(!this.checkDialog())return;let n=await this.mutex.acquire();if(i&&i.isCancellationRequested){n();return}try{let o=typeof e[0]=="string",s=new QB(this.nvim,{title:t,items:o?e.map(c=>({label:c})):e},i),a=new Promise(c=>{s.onDidClose(f=>{c(f)})});await s.show(this.dialogPreference);let l=await a,u=l==null?void 0:e.filter((c,f)=>l.includes(f));return n(),u}catch(o){Zl.error("Error on showPickerDialog:",o),n()}}async showInformationMessage(e,...t){if(!this.enableMessageDialog)return await this.showConfirm(e,t,"Info");let i=typeof t[0]=="string"?t:t.map(o=>o.title),n=await this.createNotification("CocInfoFloat",e,i);return n==-1?void 0:t[n]}async showWarningMessage(e,...t){if(!this.enableMessageDialog)return await this.showConfirm(e,t,"Warning");let i=typeof t[0]=="string"?t:t.map(o=>o.title),n=await this.createNotification("CocWarningFloat",e,i);return n==-1?void 0:t[n]}async showErrorMessage(e,...t){if(!this.enableMessageDialog)return await this.showConfirm(e,t,"Error");let i=typeof t[0]=="string"?t:t.map(o=>o.title),n=await this.createNotification("CocErrorFloat",e,i);return n==-1?void 0:t[n]}async showNotification(e){return this.checkDialog()?await new Uf(this.nvim,e).show(this.notificationPreference):!1}async showConfirm(e,t,i){if(!t||t.length==0){let a=i=="Info"?"more":i=="Error"?"error":"warning";this.showMessage(e,a);return}let o=(typeof t[0]=="string"?t.slice():t.map(a=>a.title)).map((a,l)=>`${l+1}${a}`),s=await this.nvim.callAsync("coc#util#with_callback",["confirm",[e,o.join(` -`),0,i]]);return t[s-1]}async withProgress(e,t){return this.checkDialog()?await new t3(this.nvim,{task:t,title:e.title,cancellable:e.cancellable}).show(this.notificationPreference):void 0}createNotification(e,t,i){return new Promise(n=>{let o={content:t,borderhighlight:e,close:!0,buttons:i.map((a,l)=>({text:a,index:l})),callback:a=>{n(a)}};new Uf(this.nvim,o).show(this.notificationPreference).then(a=>{a||(Zl.error("Unable to open notification window"),n(-1)),i.length||n(-1)},a=>{Zl.error("Unable to open notification window",a),n(-1)})})}get dialogPreference(){let e=b.getConfiguration("dialog");return{maxWidth:e.get("maxWidth"),maxHeight:e.get("maxHeight"),floatHighlight:e.get("floatHighlight"),floatBorderHighlight:e.get("floatBorderHighlight"),pickerButtons:e.get("pickerButtons"),pickerButtonShortcut:e.get("pickerButtonShortcut"),confirmKey:e.get("confirmKey")}}get notificationPreference(){let e=b.getConfiguration("notification");return{top:e.get("marginTop"),right:e.get("marginRight"),maxWidth:e.get("maxWidth"),maxHeight:e.get("maxHeight"),highlight:e.get("highlightGroup"),minProgressWidth:e.get("minProgressWidth")}}checkDialog(){return b.env.dialog?!0:(this.showMessage("Dialog requires vim >= 8.2.0750 or neovim >= 0.4.0, please upgrade your vim","warning"),!1)}get enableMessageDialog(){return b.env.dialog?b.getConfiguration("coc.preferences").get("enableMessageDialog",!1):!1}get messageLevel(){switch(b.getConfiguration("coc.preferences").get("messageLevel","more")){case"error":return gn.Error;case"warning":return gn.Warning;default:return gn.More}}},C=new Kj;var Yj=S(Vr()),lr=S(W());var Mt=S(W());function up(r){switch(r){case Mt.DiagnosticSeverity.Error:return"Error";case Mt.DiagnosticSeverity.Warning:return"Warning";case Mt.DiagnosticSeverity.Information:return"Information";case Mt.DiagnosticSeverity.Hint:return"Hint";default:return"Error"}}function Jj(r){switch(r){case Mt.DiagnosticSeverity.Error:return"E";case Mt.DiagnosticSeverity.Warning:return"W";case Mt.DiagnosticSeverity.Information:return"I";case Mt.DiagnosticSeverity.Hint:return"I";default:return"Error"}}function C0(r){switch(r){case"hint":return Mt.DiagnosticSeverity.Hint;case"information":return Mt.DiagnosticSeverity.Information;case"warning":return Mt.DiagnosticSeverity.Warning;case"error":return Mt.DiagnosticSeverity.Error;default:return Mt.DiagnosticSeverity.Hint}}function _0(r){switch(r){case Mt.DiagnosticSeverity.Error:return"CocError";case Mt.DiagnosticSeverity.Warning:return"CocWarning";case Mt.DiagnosticSeverity.Information:return"CocInfo";case Mt.DiagnosticSeverity.Hint:return"CocHint";default:return"CocError"}}function mg(r,e){let{start:t}=e.range,i=e.source||"coc.nvim",n=e.message.split(` -`)[0],o=up(e.severity).slice(0,1).toUpperCase();return{bufnr:r,lnum:t.line+1,col:t.character+1,text:`[${i}${e.code?" "+e.code:""}] ${n} [${o}]`,type:o}}var ehe=process.env.VIM_NODE_RPC=="1",the=U()("diagnostic-buffer"),Xj="CocDiagnostic",zo;(function(r){r[r.Enabled=0]="Enabled",r[r.Disabled=1]="Disabled"})(zo||(zo={}));var Jn;(function(r){r.Error="CocErrorHighlight",r.Warning="CocWarningHighlight",r.Information="CocInfoHighlight",r.Hint="CocHintFloat",r.Deprecated="CocStrikeThrough",r.Unused="CocFadeOut"})(Jn||(Jn={}));var rhe=Symbol("CocError"),ihe=Symbol("CocWarning"),nhe=Symbol("CocInformation"),ohe=Symbol("CocHint"),P0=class{constructor(e,t,i,n,o){this.nvim=e;this.bufnr=t;this.uri=i;this.config=n;this.onRefresh=o;this.diagnostics=[];this._disposed=!1;this._state=0;this.refresh=Yj.default(s=>{this._refresh(s).logError()},300)}get displayByAle(){return this.config.displayByAle}onChange(){this.refresh.clear()}changeState(e){this._state=e}get enabled(){return this._state==0}forceRefresh(e){this.refresh.clear(),this._refresh(e).logError()}refreshAle(e){let t=Zj(this.diagnostics);this.diagnostics=e;let i=new Map;e.forEach(n=>{let o=i.get(n.collection)||[];o.push(n),i.set(n.collection,o)});for(let n of t)i.has(n)||i.set(n,[]);this.nvim.pauseNotification();for(let[n,o]of i.entries()){let s=o.map(l=>{let u=l.range||lr.Range.create(0,0,1,0);return{text:l.message,code:l.code,lnum:u.start.line+1,col:u.start.character+1,end_lnum:u.end.line+1,end_col:u.end.character,type:Jj(l.severity)}}),a=global.hasOwnProperty("__TEST__")?"MockAleResults":"ale#other_source#ShowResults";this.nvim.call(a,[this.bufnr,n,s],!0)}this.nvim.resumeNotification().then(n=>{Array.isArray(n)&&n[1]!=null&&the.error("Error on displayByAle:",n[1][2])}).logError()}async _refresh(e){if(qe(this.diagnostics,e))return;let{refreshOnInsertMode:t}=this.config,{nvim:i}=this;if(this._state==1)return;let n=await i.eval(`[coc#util#check_refresh(${this.bufnr}),mode(),line("."),getloclist(bufwinid(${this.bufnr}),{'title':1})]`);if(n[0]==0||this._disposed)return;let o=n[1];if(!(!t&&o.startsWith("i")&&e.length)){if(this.displayByAle)this.refreshAle(e);else{this.diagnostics=e;let s=n[2];i.pauseNotification(),this.setDiagnosticInfo(e),this.addSigns(e),this.addHighlight(e),this.updateLocationList(n[3],e),this.showVirtualText(e,s),ehe&&this.nvim.command("redraw",!0);let a=await this.nvim.resumeNotification();if(Array.isArray(a)&&a[1])throw new Error(a[1])}this.onRefresh(e)}}updateLocationList(e,t){if(!this.config.locationlistUpdate||!e||e.title!=="Diagnostics of coc")return;let i=[];for(let n of t){let o=mg(this.bufnr,n);i.push(o)}this.nvim.call("setloclist",[0,[],"r",{title:"Diagnostics of coc",items:i}],!0)}addSigns(e){if(!this.config.enableSign)return;this.clearSigns();let{nvim:t,bufnr:i}=this,n=new Map;for(let o of e){let{range:s,severity:a}=o,l=s.start.line,u=_0(a),c=n.get(l)||[],f=ahe(a);c.includes(f)||(c.push(f),n.set(l,c),t.call("sign_place",[0,Xj,u,i,{lnum:l+1,priority:14-(a||0)}],!0))}}clearSigns(){let{nvim:e,bufnr:t}=this;e.call("sign_unplace",[Xj,{buffer:t}],!0)}setDiagnosticInfo(e){let t=[0,0,0,0],i={error:0,warning:0,information:0,hint:0,lnums:t};for(let n of e)switch(n.severity){case lr.DiagnosticSeverity.Warning:i.warning=i.warning+1,t[1]=t[1]||n.range.start.line+1;break;case lr.DiagnosticSeverity.Information:i.information=i.information+1,t[2]=t[2]||n.range.start.line+1;break;case lr.DiagnosticSeverity.Hint:i.hint=i.hint+1,t[3]=t[3]||n.range.start.line+1;break;default:t[0]=t[0]||n.range.start.line+1,i.error=i.error+1}this.nvim.call("coc#util#set_buf_var",[this.bufnr,"coc_diagnostic_info",i],!0),this.nvim.call("coc#util#do_autocmd",["CocDiagnosticChange"],!0)}showVirtualText(e,t){let{buffer:i,config:n}=this;if(!n.virtualText)return;let o=this.config.virtualTextSrcId,s=this.config.virtualTextPrefix;this.config.virtualTextCurrentLineOnly&&(e=e.filter(a=>{let{start:l,end:u}=a.range;return l.line<=t-1&&u.line>=t-1})),i.clearNamespace(o);for(let a of[...e].reverse()){let{line:l}=a.range.start,u=_0(a.severity)+"VirtualText",c=a.message.split(/\n/).map(f=>f.trim()).filter(f=>f.length>0).slice(0,this.config.virtualTextLines).join(this.config.virtualTextLineSeparator);i.setVirtualText(o,l,[[s+c,u]],{}).logError()}}addHighlight(e){if(this.clearHighlight(),e.length==0)return;let t=new Map;for(let i of e){let{range:n}=i,o=she(i),s=t.get(o)||[];s.push(n),t.set(o,s)}for(let i of t.keys()){let n=t.get(i)||[];n.length&&this.buffer.highlightRanges("diagnostic",i,n)}}clearHighlight(){this.buffer.clearNamespace("diagnostic")}get buffer(){return this.nvim.createBuffer(this.bufnr)}clear(){this.refresh.clear();let{nvim:e}=this;if(this.displayByAle){let t=Zj(this.diagnostics);if(this.diagnostics=[],t.size>0)for(let i of t){let n=global.hasOwnProperty("__TEST__")?"MockAleResults":"ale#other_source#ShowResults";this.nvim.call(n,[this.bufnr,i,[]],!0)}}else this.diagnostics=[],e.pauseNotification(),this.clearHighlight(),this.config.enableSign&&this.clearSigns(),this.config.virtualText&&this.buffer.clearNamespace(this.config.virtualTextSrcId),this.setDiagnosticInfo([]),e.resumeNotification(!1,!0)}getDiagnosticsAt(e,t){let i=this.diagnostics.slice();return t?i=i.filter(n=>jB(e.line,n.range)):i=i.filter(n=>Ht(e,n.range)==0),i.sort((n,o)=>n.severity-o.severity),i}dispose(){this._disposed=!0,this.clear()}};function she(r){let e=r.tags||[];if(e.includes(lr.DiagnosticTag.Deprecated))return Jn.Deprecated;if(e.includes(lr.DiagnosticTag.Unnecessary))return Jn.Unused;switch(r.severity){case lr.DiagnosticSeverity.Error:return Jn.Error;case lr.DiagnosticSeverity.Warning:return Jn.Warning;case lr.DiagnosticSeverity.Information:return Jn.Information;case lr.DiagnosticSeverity.Hint:return Jn.Hint;default:return Jn.Error}}function Zj(r){let e=new Set;return r.forEach(t=>{e.add(t.collection)}),e}function ahe(r){return r==lr.DiagnosticSeverity.Error?rhe:r==lr.DiagnosticSeverity.Warning?ihe:r==lr.DiagnosticSeverity.Information?nhe:ohe}var Ql=S(W());var fAe=U()("diagnostic-collection"),T0=class{constructor(e){this.diagnosticsMap=new Map;this._onDispose=new Ql.Emitter;this._onDidDiagnosticsChange=new Ql.Emitter;this._onDidDiagnosticsClear=new Ql.Emitter;this.onDispose=this._onDispose.event;this.onDidDiagnosticsChange=this._onDidDiagnosticsChange.event;this.onDidDiagnosticsClear=this._onDidDiagnosticsClear.event;this.name=e}set(e,t){let i=new Map;if(Array.isArray(e))for(let n of e){let[o,s]=n,a=b.getDocument(o);o=a?a.uri:o,s==null?s=[]:s=(i.get(o)||[]).concat(s),i.set(o,s)}else{let n=b.getDocument(e),o=n?n.uri:e;i.set(o,t||[])}for(let n of i){let[o,s]=n;o=$.parse(o).toString(),s.forEach(a=>{a.range=a.range||Ql.Range.create(0,0,1,0),a.message=a.message||"Empty error message",Gn(a.range)&&(a.range.end={line:a.range.end.line,character:a.range.end.character+1});let{start:l,end:u}=a.range;if(u.character==0&&u.line-l.line==1&&l.character>0){let c=b.getDocument(o);if(c){let f=c.getline(l.line);l.character==f.length&&(a.range.start.character=l.character-1)}}a.source=a.source||this.name}),this.diagnosticsMap.set(o,s),this._onDidDiagnosticsChange.fire(o)}}delete(e){this.diagnosticsMap.delete(e)}clear(){let e=Array.from(this.diagnosticsMap.keys());this.diagnosticsMap.clear(),this._onDidDiagnosticsClear.fire(e)}forEach(e,t){for(let i of this.diagnosticsMap.keys()){let n=this.diagnosticsMap.get(i);e.call(t,i,n,this)}}get(e){let t=this.diagnosticsMap.get(e);return t==null?[]:t}has(e){return this.diagnosticsMap.has(e)}dispose(){this.clear(),this._onDispose.fire(void 0),this._onDispose.dispose(),this._onDidDiagnosticsClear.dispose(),this._onDidDiagnosticsChange.dispose()}},Qj=T0;var CAe=U()("diagnostic-manager"),rU=class{constructor(){this.enabled=!0;this._onDidRefresh=new ht.Emitter;this.onDidRefresh=this._onDidRefresh.event;this.lastMessage="";this.collections=[];this.disposables=[]}init(){this.setConfiguration(),b.onDidChangeConfiguration(t=>{this.setConfiguration(t)},null,this.disposables),this.floatFactory=new mn(this.nvim),this.buffers=b.registerBufferSync(t=>{if(t.buftype!=="")return;let i=new P0(this.nvim,t.bufnr,t.uri,this.config,o=>{this._onDidRefresh.fire({diagnostics:o,uri:i.uri,bufnr:i.bufnr}),!["never","jump"].includes(this.config.enableMessage)&&this.echoMessage(!0).logError()}),n=this.getDiagnostics(t.uri);return this.enabled&&i.forceRefresh(n),i}),A.on("CursorMoved",t=>{this.config.enableMessage=="always"&&(this.timer&&clearTimeout(this.timer),t!=this.floatFactory.bufnr&&(this.timer=setTimeout(async()=>{await this.echoMessage(!0)},this.config.messageDelay)))},null,this.disposables);let e=eU.default((t,i)=>{if(!this.config.virtualText||!this.config.virtualTextCurrentLineOnly)return;let n=this.buffers.getItem(t);if(n){let o=this.getDiagnostics(n.uri);n.showVirtualText(o,i[0])}},100);A.on("CursorMoved",e,null,this.disposables),this.disposables.push(ht.Disposable.create(()=>{e.clear()})),A.on("InsertLeave",async t=>{this.config.refreshOnInsertMode||this.refreshBuffer(t)},null,this.disposables),A.on("BufEnter",async()=>{this.timer&&clearTimeout(this.timer)},null,this.disposables),this.setConfigurationErrors(!0),b.configurations.onError(()=>{this.setConfigurationErrors()},null,this.disposables)}defineSigns(){let{nvim:e}=this,{enableHighlightLineNumber:t,enableSign:i}=this.config;if(!!i){e.pauseNotification();for(let n of["Error","Warning","Info","Hint"]){let o=this.config[n.toLowerCase()+"Sign"],s=`sign define Coc${n} linehl=Coc${n}Line`;o&&(s+=` texthl=Coc${n}Sign text=${o}`),t&&(s+=` numhl=Coc${n}Sign`),e.command(s,!0)}e.resumeNotification(!1,!0)}}async setLocationlist(e){let t=this.buffers.getItem(e),i=t?this.getDiagnostics(t.uri):[],n=[];for(let a of i){let l=mg(e,a);n.push(l)}let o=await this.nvim.call("getloclist",[0,{title:1}]),s=o.title&&o.title.indexOf("Diagnostics of coc")!=-1?"r":" ";await this.nvim.call("setloclist",[0,[],s,{title:"Diagnostics of coc",items:n}])}setConfigurationErrors(e){let i=this.collections.find(o=>o.name=="config");i?i.clear():i=this.create("config");let{errorItems:n}=b.configurations;if(n&&n.length){e&&C.showMessage("settings file parse error, run ':CocList diagnostics'","error");let o=new Map;for(let s of n){let{uri:a}=s.location,l=o.get(a)||[];l.push(ht.Diagnostic.create(s.location.range,s.message,ht.DiagnosticSeverity.Error)),o.set(a,l)}i.set(Array.from(o))}}create(e){let t=this.getCollectionByName(e);return t||(t=new Qj(e),this.collections.push(t),t.onDidDiagnosticsChange(i=>{this.refreshBuffer(i)}),t.onDidDiagnosticsClear(i=>{for(let n of i)this.refreshBuffer(n,!0)}),t.onDispose(()=>{let i=this.collections.findIndex(n=>n==t);i!==-1&&this.collections.splice(i,1)}),t)}getSortedRanges(e,t){let i=this.getCollections(e),n=[],o=t?C0(t):0;for(let s of i){let a=s.get(e);o&&(a=a.filter(u=>u.severity==o));let l=a.map(u=>u.range);n.push(...l)}return n.sort((s,a)=>s.start.line!=a.start.line?s.start.line-a.start.line:s.start.character-a.start.character),n}getDiagnostics(e){let t=this.getCollections(e),{level:i,showUnused:n,showDeprecated:o}=this.config,s=[];for(let a of t){let l=a.get(e);!l||(l=l.filter(u=>{var c,f;return!(i&&ii||!n&&((c=u.tags)==null?void 0:c.includes(ht.DiagnosticTag.Unnecessary))||!o&&((f=u.tags)==null?void 0:f.includes(ht.DiagnosticTag.Deprecated)))}),l.forEach(u=>{s.push(Object.assign({collection:a.name},u))}))}return s.sort((a,l)=>{if(a.severity==l.severity){let u=Ne(a.range.start,l.range.start);return u!=0?u:a.source==l.source?a.message>l.message?1:-1:a.source>l.source?1:-1}return a.severity-l.severity}),s}getDiagnosticsInRange(e,t){let i=this.getCollections(e.uri),n=[];for(let o of i){let s=o.get(e.uri);if(!!s)for(let a of s)Bl(a.range,t)&&n.push(a)}return n}async preview(){let[e,t]=await this.nvim.eval('[bufnr("%"),coc#util#cursor()]'),{nvim:i}=this,n=this.getDiagnosticsAt(e,t);if(n.length==0){i.command("pclose",!0),C.showMessage("Empty diagnostics","warning");return}let o=[];for(let s of n){let{source:a,code:l,severity:u,message:c}=s,f=up(u)[0];o.push(`[${a}${l?" "+l:""}] [${f}]`),o.push(...c.split(/\r?\n/)),o.push("")}i.call("coc#util#preview_info",[o,"txt"],!0)}async jumpPrevious(e){let t=await this.nvim.buffer,i=b.getDocument(t.id);if(!i)return;let n=await C.getCursorPosition(),o=this.getSortedRanges(i.uri,e);if(o.length==0){C.showMessage("Empty diagnostics","warning");return}let s;for(let a=o.length-1;a>=0;a--){let l=o[a].end;if(Ne(l,n)<0){s=o[a].start;break}else a==0&&await this.nvim.getOption("wrapscan")&&(s=o[o.length-1].start)}if(s){if(await C.moveTo(s),this.config.enableMessage=="never")return;await this.echoMessage(!1)}}async jumpNext(e){let t=await this.nvim.buffer,i=b.getDocument(t.id),n=await C.getCursorPosition(),o=this.getSortedRanges(i.uri,e);if(o.length==0){C.showMessage("Empty diagnostics","warning");return}let s;for(let a=0;a<=o.length-1;a++){let l=o[a].start;if(Ne(l,n)>0){s=o[a].start;break}else a==o.length-1&&await this.nvim.getOption("wrapscan")&&(s=o[0].start)}if(s){if(await C.moveTo(s),this.config.enableMessage=="never")return;await this.echoMessage(!1)}}getDiagnosticList(){let e=[],{level:t,showUnused:i,showDeprecated:n}=this.config;for(let o of this.collections)o.forEach((s,a)=>{var u,c;let l=$.parse(s).fsPath;for(let f of a){if(f.severity&&f.severity>t||!i&&((u=f.tags)==null?void 0:u.includes(ht.DiagnosticTag.Unnecessary))||!n&&((c=f.tags)==null?void 0:c.includes(ht.DiagnosticTag.Deprecated)))continue;let{start:p}=f.range,d={file:l,lnum:p.line+1,col:p.character+1,code:f.code,source:f.source||o.name,message:f.message,severity:up(f.severity),level:f.severity||0,location:ht.Location.create(s,f.range)};e.push(d)}});return e.sort((o,s)=>o.level!==s.level?o.level-s.level:o.file!==s.file?o.file>s.file?1:-1:o.lnum!=s.lnum?o.lnum-s.lnum:o.col-s.col),e}getDiagnosticsAt(e,t){let i=this.buffers.getItem(e);if(!i)return[];let n=ht.Position.create(t[0],t[1]);return i.getDiagnosticsAt(n,this.config.checkCurrentLine)}async getCurrentDiagnostics(){let[e,t]=await this.nvim.eval('[bufnr("%"),coc#util#cursor()]');return this.getDiagnosticsAt(e,t)}async echoMessage(e=!1){let t=this.config;if(!this.enabled||t.displayByAle)return;this.timer&&clearTimeout(this.timer);let i=t.messageTarget=="float",[n,o,s,a]=await this.nvim.eval('[bufnr("%"),coc#util#cursor(),&filetype,mode()]');if(a!="n")return;let l=this.getDiagnosticsAt(n,o);if(l.length==0){if(i)this.floatFactory.close();else{let f=await this.nvim.call("coc#util#echo_line");this.lastMessage&&f.startsWith(this.lastMessage)&&this.nvim.command('echo ""',!0)}return}if(e&&b.insertMode)return;let u=[],c="";if(Object.keys(t.filetypeMap).length>0){let f=t.filetypeMap.default||"";c=t.filetypeMap[s]||(f=="bufferType"?s:f)}if(l.forEach(f=>{let{source:p,code:d,severity:h,message:m}=f,y=up(h)[0],g=d?" "+d:"",w=t.format.replace("%source",p).replace("%code",g).replace("%severity",y).replace("%message",m),x="Error";if(c==="")switch(h){case ht.DiagnosticSeverity.Hint:x="Hint";break;case ht.DiagnosticSeverity.Warning:x="Warning";break;case ht.DiagnosticSeverity.Information:x="Info";break}else x=c;u.push({filetype:x,content:w})}),i){let{maxWindowHeight:f,maxWindowWidth:p}=this.config;await this.floatFactory.show(u,{maxWidth:p,maxHeight:f,modes:["n"]})}else{let f=u.map(p=>p.content).join(` -`).split(/\r?\n/);f.length&&(await this.nvim.command('echo ""'),this.lastMessage=f[0].slice(0,30),await C.echoLines(f,e))}}async jumpRelated(){let e=await this.getCurrentDiagnostics();if(!e)return;let t=e.find(n=>n.relatedInformation!=null);if(!t)return;let i=t.relatedInformation.map(n=>n.location);i.length==1?await b.jumpTo(i[0].uri,i[0].range.start):i.length>1&&await b.showLocations(i)}reset(){this.timer&&clearTimeout(this.timer),this.buffers.reset();for(let e of this.collections)e.dispose();this.collections=[]}dispose(){var e;this.buffers.dispose(),this.timer&&clearTimeout(this.timer);for(let t of this.collections)t.dispose();(e=this.floatFactory)==null||e.close(),this.collections=[],z(this.disposables)}get nvim(){return b.nvim}setConfiguration(e){if(e&&!e.affectsConfiguration("diagnostic"))return;let t=b.getConfiguration("diagnostic"),i=t.get("messageTarget","float");i=="float"&&!b.env.floating&&!b.env.textprop&&(i="echo");let n=t.get("enableHighlightLineNumber",!0);(!b.isNvim||tU.default.lt(b.env.version,"v0.3.2"))&&(n=!1),this.config={messageTarget:i,enableHighlightLineNumber:n,virtualTextSrcId:b.createNameSpace("diagnostic-virtualText"),checkCurrentLine:t.get("checkCurrentLine",!1),enableSign:b.env.sign&&t.get("enableSign",!0),locationlistUpdate:t.get("locationlistUpdate",!0),maxWindowHeight:t.get("maxWindowHeight",10),maxWindowWidth:t.get("maxWindowWidth",80),enableMessage:t.get("enableMessage","always"),messageDelay:t.get("messageDelay",200),virtualText:t.get("virtualText",!1)&&this.nvim.hasFunction("nvim_buf_set_virtual_text"),virtualTextCurrentLineOnly:t.get("virtualTextCurrentLineOnly",!0),virtualTextPrefix:t.get("virtualTextPrefix"," "),virtualTextLineSeparator:t.get("virtualTextLineSeparator"," \\ "),virtualTextLines:t.get("virtualTextLines",3),displayByAle:t.get("displayByAle",!1),level:C0(t.get("level","hint")),signPriority:t.get("signPriority",10),errorSign:t.get("errorSign",">>"),warningSign:t.get("warningSign",">>"),infoSign:t.get("infoSign",">>"),hintSign:t.get("hintSign",">>"),refreshOnInsertMode:t.get("refreshOnInsertMode",!1),filetypeMap:t.get("filetypeMap",{}),showUnused:t.get("showUnused",!0),showDeprecated:t.get("showDeprecated",!0),format:t.get("format","[%source%code] [%severity] %message")},this.enabled=t.get("enable",!0),this.defineSigns()}getCollectionByName(e){return this.collections.find(t=>t.name==e)}getCollections(e){return this.collections.filter(t=>t.has(e))}toggleDiagnostic(){let{enabled:e}=this;this.enabled=!e;for(let t of this.buffers.items)if(this.enabled){let i=this.getDiagnostics(t.uri);t.forceRefresh(i)}else t.clear()}toggleDiagnosticBuffer(e){if(!this.enabled)return;let t=this.buffers.getItem(e);if(t)if(t.enabled)t.changeState(zo.Disabled),t.clear();else{t.changeState(zo.Enabled);let i=this.getDiagnostics(t.uri);t.forceRefresh(i)}}refreshBuffer(e,t=!1){if(!this.enabled)return!1;let i=this.buffers.getItem(e);if(!i)return!1;let n=this.getDiagnostics(i.uri);return t?i.forceRefresh(n):i.refresh(n),!0}},mt=new rU;var gt;(function(r){r[r.Null=0]="Null",r[r.Backspace=8]="Backspace",r[r.Tab=9]="Tab",r[r.LineFeed=10]="LineFeed",r[r.CarriageReturn=13]="CarriageReturn",r[r.Space=32]="Space",r[r.ExclamationMark=33]="ExclamationMark",r[r.DoubleQuote=34]="DoubleQuote",r[r.Hash=35]="Hash",r[r.DollarSign=36]="DollarSign",r[r.PercentSign=37]="PercentSign",r[r.Ampersand=38]="Ampersand",r[r.SingleQuote=39]="SingleQuote",r[r.OpenParen=40]="OpenParen",r[r.CloseParen=41]="CloseParen",r[r.Asterisk=42]="Asterisk",r[r.Plus=43]="Plus",r[r.Comma=44]="Comma",r[r.Dash=45]="Dash",r[r.Period=46]="Period",r[r.Slash=47]="Slash",r[r.Digit0=48]="Digit0",r[r.Digit1=49]="Digit1",r[r.Digit2=50]="Digit2",r[r.Digit3=51]="Digit3",r[r.Digit4=52]="Digit4",r[r.Digit5=53]="Digit5",r[r.Digit6=54]="Digit6",r[r.Digit7=55]="Digit7",r[r.Digit8=56]="Digit8",r[r.Digit9=57]="Digit9",r[r.Colon=58]="Colon",r[r.Semicolon=59]="Semicolon",r[r.LessThan=60]="LessThan",r[r.Equals=61]="Equals",r[r.GreaterThan=62]="GreaterThan",r[r.QuestionMark=63]="QuestionMark",r[r.AtSign=64]="AtSign",r[r.A=65]="A",r[r.B=66]="B",r[r.C=67]="C",r[r.D=68]="D",r[r.E=69]="E",r[r.F=70]="F",r[r.G=71]="G",r[r.H=72]="H",r[r.I=73]="I",r[r.J=74]="J",r[r.K=75]="K",r[r.L=76]="L",r[r.M=77]="M",r[r.N=78]="N",r[r.O=79]="O",r[r.P=80]="P",r[r.Q=81]="Q",r[r.R=82]="R",r[r.S=83]="S",r[r.T=84]="T",r[r.U=85]="U",r[r.V=86]="V",r[r.W=87]="W",r[r.X=88]="X",r[r.Y=89]="Y",r[r.Z=90]="Z",r[r.OpenSquareBracket=91]="OpenSquareBracket",r[r.Backslash=92]="Backslash",r[r.CloseSquareBracket=93]="CloseSquareBracket",r[r.Caret=94]="Caret",r[r.Underline=95]="Underline",r[r.BackTick=96]="BackTick",r[r.a=97]="a",r[r.b=98]="b",r[r.c=99]="c",r[r.d=100]="d",r[r.e=101]="e",r[r.f=102]="f",r[r.g=103]="g",r[r.h=104]="h",r[r.i=105]="i",r[r.j=106]="j",r[r.k=107]="k",r[r.l=108]="l",r[r.m=109]="m",r[r.n=110]="n",r[r.o=111]="o",r[r.p=112]="p",r[r.q=113]="q",r[r.r=114]="r",r[r.s=115]="s",r[r.t=116]="t",r[r.u=117]="u",r[r.v=118]="v",r[r.w=119]="w",r[r.x=120]="x",r[r.y=121]="y",r[r.z=122]="z",r[r.OpenCurlyBrace=123]="OpenCurlyBrace",r[r.Pipe=124]="Pipe",r[r.CloseCurlyBrace=125]="CloseCurlyBrace",r[r.Tilde=126]="Tilde",r[r.U_Combining_Grave_Accent=768]="U_Combining_Grave_Accent",r[r.U_Combining_Acute_Accent=769]="U_Combining_Acute_Accent",r[r.U_Combining_Circumflex_Accent=770]="U_Combining_Circumflex_Accent",r[r.U_Combining_Tilde=771]="U_Combining_Tilde",r[r.U_Combining_Macron=772]="U_Combining_Macron",r[r.U_Combining_Overline=773]="U_Combining_Overline",r[r.U_Combining_Breve=774]="U_Combining_Breve",r[r.U_Combining_Dot_Above=775]="U_Combining_Dot_Above",r[r.U_Combining_Diaeresis=776]="U_Combining_Diaeresis",r[r.U_Combining_Hook_Above=777]="U_Combining_Hook_Above",r[r.U_Combining_Ring_Above=778]="U_Combining_Ring_Above",r[r.U_Combining_Double_Acute_Accent=779]="U_Combining_Double_Acute_Accent",r[r.U_Combining_Caron=780]="U_Combining_Caron",r[r.U_Combining_Vertical_Line_Above=781]="U_Combining_Vertical_Line_Above",r[r.U_Combining_Double_Vertical_Line_Above=782]="U_Combining_Double_Vertical_Line_Above",r[r.U_Combining_Double_Grave_Accent=783]="U_Combining_Double_Grave_Accent",r[r.U_Combining_Candrabindu=784]="U_Combining_Candrabindu",r[r.U_Combining_Inverted_Breve=785]="U_Combining_Inverted_Breve",r[r.U_Combining_Turned_Comma_Above=786]="U_Combining_Turned_Comma_Above",r[r.U_Combining_Comma_Above=787]="U_Combining_Comma_Above",r[r.U_Combining_Reversed_Comma_Above=788]="U_Combining_Reversed_Comma_Above",r[r.U_Combining_Comma_Above_Right=789]="U_Combining_Comma_Above_Right",r[r.U_Combining_Grave_Accent_Below=790]="U_Combining_Grave_Accent_Below",r[r.U_Combining_Acute_Accent_Below=791]="U_Combining_Acute_Accent_Below",r[r.U_Combining_Left_Tack_Below=792]="U_Combining_Left_Tack_Below",r[r.U_Combining_Right_Tack_Below=793]="U_Combining_Right_Tack_Below",r[r.U_Combining_Left_Angle_Above=794]="U_Combining_Left_Angle_Above",r[r.U_Combining_Horn=795]="U_Combining_Horn",r[r.U_Combining_Left_Half_Ring_Below=796]="U_Combining_Left_Half_Ring_Below",r[r.U_Combining_Up_Tack_Below=797]="U_Combining_Up_Tack_Below",r[r.U_Combining_Down_Tack_Below=798]="U_Combining_Down_Tack_Below",r[r.U_Combining_Plus_Sign_Below=799]="U_Combining_Plus_Sign_Below",r[r.U_Combining_Minus_Sign_Below=800]="U_Combining_Minus_Sign_Below",r[r.U_Combining_Palatalized_Hook_Below=801]="U_Combining_Palatalized_Hook_Below",r[r.U_Combining_Retroflex_Hook_Below=802]="U_Combining_Retroflex_Hook_Below",r[r.U_Combining_Dot_Below=803]="U_Combining_Dot_Below",r[r.U_Combining_Diaeresis_Below=804]="U_Combining_Diaeresis_Below",r[r.U_Combining_Ring_Below=805]="U_Combining_Ring_Below",r[r.U_Combining_Comma_Below=806]="U_Combining_Comma_Below",r[r.U_Combining_Cedilla=807]="U_Combining_Cedilla",r[r.U_Combining_Ogonek=808]="U_Combining_Ogonek",r[r.U_Combining_Vertical_Line_Below=809]="U_Combining_Vertical_Line_Below",r[r.U_Combining_Bridge_Below=810]="U_Combining_Bridge_Below",r[r.U_Combining_Inverted_Double_Arch_Below=811]="U_Combining_Inverted_Double_Arch_Below",r[r.U_Combining_Caron_Below=812]="U_Combining_Caron_Below",r[r.U_Combining_Circumflex_Accent_Below=813]="U_Combining_Circumflex_Accent_Below",r[r.U_Combining_Breve_Below=814]="U_Combining_Breve_Below",r[r.U_Combining_Inverted_Breve_Below=815]="U_Combining_Inverted_Breve_Below",r[r.U_Combining_Tilde_Below=816]="U_Combining_Tilde_Below",r[r.U_Combining_Macron_Below=817]="U_Combining_Macron_Below",r[r.U_Combining_Low_Line=818]="U_Combining_Low_Line",r[r.U_Combining_Double_Low_Line=819]="U_Combining_Double_Low_Line",r[r.U_Combining_Tilde_Overlay=820]="U_Combining_Tilde_Overlay",r[r.U_Combining_Short_Stroke_Overlay=821]="U_Combining_Short_Stroke_Overlay",r[r.U_Combining_Long_Stroke_Overlay=822]="U_Combining_Long_Stroke_Overlay",r[r.U_Combining_Short_Solidus_Overlay=823]="U_Combining_Short_Solidus_Overlay",r[r.U_Combining_Long_Solidus_Overlay=824]="U_Combining_Long_Solidus_Overlay",r[r.U_Combining_Right_Half_Ring_Below=825]="U_Combining_Right_Half_Ring_Below",r[r.U_Combining_Inverted_Bridge_Below=826]="U_Combining_Inverted_Bridge_Below",r[r.U_Combining_Square_Below=827]="U_Combining_Square_Below",r[r.U_Combining_Seagull_Below=828]="U_Combining_Seagull_Below",r[r.U_Combining_X_Above=829]="U_Combining_X_Above",r[r.U_Combining_Vertical_Tilde=830]="U_Combining_Vertical_Tilde",r[r.U_Combining_Double_Overline=831]="U_Combining_Double_Overline",r[r.U_Combining_Grave_Tone_Mark=832]="U_Combining_Grave_Tone_Mark",r[r.U_Combining_Acute_Tone_Mark=833]="U_Combining_Acute_Tone_Mark",r[r.U_Combining_Greek_Perispomeni=834]="U_Combining_Greek_Perispomeni",r[r.U_Combining_Greek_Koronis=835]="U_Combining_Greek_Koronis",r[r.U_Combining_Greek_Dialytika_Tonos=836]="U_Combining_Greek_Dialytika_Tonos",r[r.U_Combining_Greek_Ypogegrammeni=837]="U_Combining_Greek_Ypogegrammeni",r[r.U_Combining_Bridge_Above=838]="U_Combining_Bridge_Above",r[r.U_Combining_Equals_Sign_Below=839]="U_Combining_Equals_Sign_Below",r[r.U_Combining_Double_Vertical_Line_Below=840]="U_Combining_Double_Vertical_Line_Below",r[r.U_Combining_Left_Angle_Below=841]="U_Combining_Left_Angle_Below",r[r.U_Combining_Not_Tilde_Above=842]="U_Combining_Not_Tilde_Above",r[r.U_Combining_Homothetic_Above=843]="U_Combining_Homothetic_Above",r[r.U_Combining_Almost_Equal_To_Above=844]="U_Combining_Almost_Equal_To_Above",r[r.U_Combining_Left_Right_Arrow_Below=845]="U_Combining_Left_Right_Arrow_Below",r[r.U_Combining_Upwards_Arrow_Below=846]="U_Combining_Upwards_Arrow_Below",r[r.U_Combining_Grapheme_Joiner=847]="U_Combining_Grapheme_Joiner",r[r.U_Combining_Right_Arrowhead_Above=848]="U_Combining_Right_Arrowhead_Above",r[r.U_Combining_Left_Half_Ring_Above=849]="U_Combining_Left_Half_Ring_Above",r[r.U_Combining_Fermata=850]="U_Combining_Fermata",r[r.U_Combining_X_Below=851]="U_Combining_X_Below",r[r.U_Combining_Left_Arrowhead_Below=852]="U_Combining_Left_Arrowhead_Below",r[r.U_Combining_Right_Arrowhead_Below=853]="U_Combining_Right_Arrowhead_Below",r[r.U_Combining_Right_Arrowhead_And_Up_Arrowhead_Below=854]="U_Combining_Right_Arrowhead_And_Up_Arrowhead_Below",r[r.U_Combining_Right_Half_Ring_Above=855]="U_Combining_Right_Half_Ring_Above",r[r.U_Combining_Dot_Above_Right=856]="U_Combining_Dot_Above_Right",r[r.U_Combining_Asterisk_Below=857]="U_Combining_Asterisk_Below",r[r.U_Combining_Double_Ring_Below=858]="U_Combining_Double_Ring_Below",r[r.U_Combining_Zigzag_Above=859]="U_Combining_Zigzag_Above",r[r.U_Combining_Double_Breve_Below=860]="U_Combining_Double_Breve_Below",r[r.U_Combining_Double_Breve=861]="U_Combining_Double_Breve",r[r.U_Combining_Double_Macron=862]="U_Combining_Double_Macron",r[r.U_Combining_Double_Macron_Below=863]="U_Combining_Double_Macron_Below",r[r.U_Combining_Double_Tilde=864]="U_Combining_Double_Tilde",r[r.U_Combining_Double_Inverted_Breve=865]="U_Combining_Double_Inverted_Breve",r[r.U_Combining_Double_Rightwards_Arrow_Below=866]="U_Combining_Double_Rightwards_Arrow_Below",r[r.U_Combining_Latin_Small_Letter_A=867]="U_Combining_Latin_Small_Letter_A",r[r.U_Combining_Latin_Small_Letter_E=868]="U_Combining_Latin_Small_Letter_E",r[r.U_Combining_Latin_Small_Letter_I=869]="U_Combining_Latin_Small_Letter_I",r[r.U_Combining_Latin_Small_Letter_O=870]="U_Combining_Latin_Small_Letter_O",r[r.U_Combining_Latin_Small_Letter_U=871]="U_Combining_Latin_Small_Letter_U",r[r.U_Combining_Latin_Small_Letter_C=872]="U_Combining_Latin_Small_Letter_C",r[r.U_Combining_Latin_Small_Letter_D=873]="U_Combining_Latin_Small_Letter_D",r[r.U_Combining_Latin_Small_Letter_H=874]="U_Combining_Latin_Small_Letter_H",r[r.U_Combining_Latin_Small_Letter_M=875]="U_Combining_Latin_Small_Letter_M",r[r.U_Combining_Latin_Small_Letter_R=876]="U_Combining_Latin_Small_Letter_R",r[r.U_Combining_Latin_Small_Letter_T=877]="U_Combining_Latin_Small_Letter_T",r[r.U_Combining_Latin_Small_Letter_V=878]="U_Combining_Latin_Small_Letter_V",r[r.U_Combining_Latin_Small_Letter_X=879]="U_Combining_Latin_Small_Letter_X",r[r.LINE_SEPARATOR_2028=8232]="LINE_SEPARATOR_2028",r[r.U_CIRCUMFLEX=94]="U_CIRCUMFLEX",r[r.U_GRAVE_ACCENT=96]="U_GRAVE_ACCENT",r[r.U_DIAERESIS=168]="U_DIAERESIS",r[r.U_MACRON=175]="U_MACRON",r[r.U_ACUTE_ACCENT=180]="U_ACUTE_ACCENT",r[r.U_CEDILLA=184]="U_CEDILLA",r[r.U_MODIFIER_LETTER_LEFT_ARROWHEAD=706]="U_MODIFIER_LETTER_LEFT_ARROWHEAD",r[r.U_MODIFIER_LETTER_RIGHT_ARROWHEAD=707]="U_MODIFIER_LETTER_RIGHT_ARROWHEAD",r[r.U_MODIFIER_LETTER_UP_ARROWHEAD=708]="U_MODIFIER_LETTER_UP_ARROWHEAD",r[r.U_MODIFIER_LETTER_DOWN_ARROWHEAD=709]="U_MODIFIER_LETTER_DOWN_ARROWHEAD",r[r.U_MODIFIER_LETTER_CENTRED_RIGHT_HALF_RING=722]="U_MODIFIER_LETTER_CENTRED_RIGHT_HALF_RING",r[r.U_MODIFIER_LETTER_CENTRED_LEFT_HALF_RING=723]="U_MODIFIER_LETTER_CENTRED_LEFT_HALF_RING",r[r.U_MODIFIER_LETTER_UP_TACK=724]="U_MODIFIER_LETTER_UP_TACK",r[r.U_MODIFIER_LETTER_DOWN_TACK=725]="U_MODIFIER_LETTER_DOWN_TACK",r[r.U_MODIFIER_LETTER_PLUS_SIGN=726]="U_MODIFIER_LETTER_PLUS_SIGN",r[r.U_MODIFIER_LETTER_MINUS_SIGN=727]="U_MODIFIER_LETTER_MINUS_SIGN",r[r.U_BREVE=728]="U_BREVE",r[r.U_DOT_ABOVE=729]="U_DOT_ABOVE",r[r.U_RING_ABOVE=730]="U_RING_ABOVE",r[r.U_OGONEK=731]="U_OGONEK",r[r.U_SMALL_TILDE=732]="U_SMALL_TILDE",r[r.U_DOUBLE_ACUTE_ACCENT=733]="U_DOUBLE_ACUTE_ACCENT",r[r.U_MODIFIER_LETTER_RHOTIC_HOOK=734]="U_MODIFIER_LETTER_RHOTIC_HOOK",r[r.U_MODIFIER_LETTER_CROSS_ACCENT=735]="U_MODIFIER_LETTER_CROSS_ACCENT",r[r.U_MODIFIER_LETTER_EXTRA_HIGH_TONE_BAR=741]="U_MODIFIER_LETTER_EXTRA_HIGH_TONE_BAR",r[r.U_MODIFIER_LETTER_HIGH_TONE_BAR=742]="U_MODIFIER_LETTER_HIGH_TONE_BAR",r[r.U_MODIFIER_LETTER_MID_TONE_BAR=743]="U_MODIFIER_LETTER_MID_TONE_BAR",r[r.U_MODIFIER_LETTER_LOW_TONE_BAR=744]="U_MODIFIER_LETTER_LOW_TONE_BAR",r[r.U_MODIFIER_LETTER_EXTRA_LOW_TONE_BAR=745]="U_MODIFIER_LETTER_EXTRA_LOW_TONE_BAR",r[r.U_MODIFIER_LETTER_YIN_DEPARTING_TONE_MARK=746]="U_MODIFIER_LETTER_YIN_DEPARTING_TONE_MARK",r[r.U_MODIFIER_LETTER_YANG_DEPARTING_TONE_MARK=747]="U_MODIFIER_LETTER_YANG_DEPARTING_TONE_MARK",r[r.U_MODIFIER_LETTER_UNASPIRATED=749]="U_MODIFIER_LETTER_UNASPIRATED",r[r.U_MODIFIER_LETTER_LOW_DOWN_ARROWHEAD=751]="U_MODIFIER_LETTER_LOW_DOWN_ARROWHEAD",r[r.U_MODIFIER_LETTER_LOW_UP_ARROWHEAD=752]="U_MODIFIER_LETTER_LOW_UP_ARROWHEAD",r[r.U_MODIFIER_LETTER_LOW_LEFT_ARROWHEAD=753]="U_MODIFIER_LETTER_LOW_LEFT_ARROWHEAD",r[r.U_MODIFIER_LETTER_LOW_RIGHT_ARROWHEAD=754]="U_MODIFIER_LETTER_LOW_RIGHT_ARROWHEAD",r[r.U_MODIFIER_LETTER_LOW_RING=755]="U_MODIFIER_LETTER_LOW_RING",r[r.U_MODIFIER_LETTER_MIDDLE_GRAVE_ACCENT=756]="U_MODIFIER_LETTER_MIDDLE_GRAVE_ACCENT",r[r.U_MODIFIER_LETTER_MIDDLE_DOUBLE_GRAVE_ACCENT=757]="U_MODIFIER_LETTER_MIDDLE_DOUBLE_GRAVE_ACCENT",r[r.U_MODIFIER_LETTER_MIDDLE_DOUBLE_ACUTE_ACCENT=758]="U_MODIFIER_LETTER_MIDDLE_DOUBLE_ACUTE_ACCENT",r[r.U_MODIFIER_LETTER_LOW_TILDE=759]="U_MODIFIER_LETTER_LOW_TILDE",r[r.U_MODIFIER_LETTER_RAISED_COLON=760]="U_MODIFIER_LETTER_RAISED_COLON",r[r.U_MODIFIER_LETTER_BEGIN_HIGH_TONE=761]="U_MODIFIER_LETTER_BEGIN_HIGH_TONE",r[r.U_MODIFIER_LETTER_END_HIGH_TONE=762]="U_MODIFIER_LETTER_END_HIGH_TONE",r[r.U_MODIFIER_LETTER_BEGIN_LOW_TONE=763]="U_MODIFIER_LETTER_BEGIN_LOW_TONE",r[r.U_MODIFIER_LETTER_END_LOW_TONE=764]="U_MODIFIER_LETTER_END_LOW_TONE",r[r.U_MODIFIER_LETTER_SHELF=765]="U_MODIFIER_LETTER_SHELF",r[r.U_MODIFIER_LETTER_OPEN_SHELF=766]="U_MODIFIER_LETTER_OPEN_SHELF",r[r.U_MODIFIER_LETTER_LOW_LEFT_ARROW=767]="U_MODIFIER_LETTER_LOW_LEFT_ARROW",r[r.U_GREEK_LOWER_NUMERAL_SIGN=885]="U_GREEK_LOWER_NUMERAL_SIGN",r[r.U_GREEK_TONOS=900]="U_GREEK_TONOS",r[r.U_GREEK_DIALYTIKA_TONOS=901]="U_GREEK_DIALYTIKA_TONOS",r[r.U_GREEK_KORONIS=8125]="U_GREEK_KORONIS",r[r.U_GREEK_PSILI=8127]="U_GREEK_PSILI",r[r.U_GREEK_PERISPOMENI=8128]="U_GREEK_PERISPOMENI",r[r.U_GREEK_DIALYTIKA_AND_PERISPOMENI=8129]="U_GREEK_DIALYTIKA_AND_PERISPOMENI",r[r.U_GREEK_PSILI_AND_VARIA=8141]="U_GREEK_PSILI_AND_VARIA",r[r.U_GREEK_PSILI_AND_OXIA=8142]="U_GREEK_PSILI_AND_OXIA",r[r.U_GREEK_PSILI_AND_PERISPOMENI=8143]="U_GREEK_PSILI_AND_PERISPOMENI",r[r.U_GREEK_DASIA_AND_VARIA=8157]="U_GREEK_DASIA_AND_VARIA",r[r.U_GREEK_DASIA_AND_OXIA=8158]="U_GREEK_DASIA_AND_OXIA",r[r.U_GREEK_DASIA_AND_PERISPOMENI=8159]="U_GREEK_DASIA_AND_PERISPOMENI",r[r.U_GREEK_DIALYTIKA_AND_VARIA=8173]="U_GREEK_DIALYTIKA_AND_VARIA",r[r.U_GREEK_DIALYTIKA_AND_OXIA=8174]="U_GREEK_DIALYTIKA_AND_OXIA",r[r.U_GREEK_VARIA=8175]="U_GREEK_VARIA",r[r.U_GREEK_OXIA=8189]="U_GREEK_OXIA",r[r.U_GREEK_DASIA=8190]="U_GREEK_DASIA",r[r.U_OVERLINE=8254]="U_OVERLINE",r[r.UTF8_BOM=65279]="UTF8_BOM"})(gt||(gt={}));var kAe=U()("snippets-parser"),G;(function(r){r[r.Dollar=0]="Dollar",r[r.Colon=1]="Colon",r[r.Comma=2]="Comma",r[r.CurlyOpen=3]="CurlyOpen",r[r.CurlyClose=4]="CurlyClose",r[r.Backslash=5]="Backslash",r[r.Forwardslash=6]="Forwardslash",r[r.Pipe=7]="Pipe",r[r.Int=8]="Int",r[r.VariableName=9]="VariableName",r[r.Format=10]="Format",r[r.Plus=11]="Plus",r[r.Dash=12]="Dash",r[r.QuestionMark=13]="QuestionMark",r[r.EOF=14]="EOF"})(G||(G={}));var en=class{static isDigitCharacter(e){return e>=gt.Digit0&&e<=gt.Digit9}static isVariableCharacter(e){return e===gt.Underline||e>=gt.a&&e<=gt.z||e>=gt.A&&e<=gt.Z}constructor(){this.text("")}text(e){this.value=e,this.pos=0}tokenText(e){return this.value.substr(e.pos,e.len)}next(){if(this.pos>=this.value.length)return{type:14,pos:this.pos,len:0};let e=this.pos,t=0,i=this.value.charCodeAt(e),n;if(n=en._table[i],typeof n=="number")return this.pos+=1,{type:n,pos:e,len:1};if(en.isDigitCharacter(i)){n=8;do t+=1,i=this.value.charCodeAt(e+t);while(en.isDigitCharacter(i));return this.pos+=t,{type:n,pos:e,len:t}}if(en.isVariableCharacter(i)){n=9;do i=this.value.charCodeAt(e+ ++t);while(en.isVariableCharacter(i)||en.isDigitCharacter(i));return this.pos+=t,{type:n,pos:e,len:t}}n=10;do t+=1,i=this.value.charCodeAt(e+t);while(!isNaN(i)&&typeof en._table[i]=="undefined"&&!en.isDigitCharacter(i)&&!en.isVariableCharacter(i));return this.pos+=t,{type:n,pos:e,len:t}}},R0=en;R0._table={[gt.DollarSign]:0,[gt.Colon]:1,[gt.Comma]:2,[gt.OpenCurlyBrace]:3,[gt.CloseCurlyBrace]:4,[gt.Backslash]:5,[gt.Slash]:6,[gt.Pipe]:7,[gt.Plus]:11,[gt.Dash]:12,[gt.QuestionMark]:13};var na=class{constructor(){this._children=[]}appendChild(e){return e instanceof ct&&this._children[this._children.length-1]instanceof ct?this._children[this._children.length-1].value+=e.value:(e.parent=this,this._children.push(e)),this}setOnlyChild(e){e.parent=this,this._children=[e]}replace(e,t){let{parent:i}=e,n=i.children.indexOf(e),o=i.children.slice(0);o.splice(n,1,...t),i._children=o,function s(a,l){for(let u of a)u.parent=l,s(u.children,u)}(t,i)}get children(){return this._children}get snippet(){let e=this;for(;;){if(!e)return;if(e instanceof cp)return e;e=e.parent}}toString(){return this.children.reduce((e,t)=>e+t.toString(),"")}len(){return 0}get next(){let{parent:e}=this,{children:t}=e,i=t.indexOf(this);return t[i+1]}},ct=class extends na{constructor(e){super();this.value=e}static escape(e){return e.replace(/\$|}|\\/g,"\\$&")}toString(){return this.value}toTextmateString(){return ct.escape(this.value)}len(){return this.value.length}clone(){return new ct(this.value)}},k0=class extends na{},ei=class extends k0{constructor(e){super();this.index=e}static compareByIndex(e,t){return e.index===t.index?0:e.isFinalTabstop?1:t.isFinalTabstop||e.indext.index?1:0}get isFinalTabstop(){return this.index===0}get choice(){return this._children.length===1&&this._children[0]instanceof fp?this._children[0]:void 0}toTextmateString(){let e="";return this.transform&&(e=this.transform.toTextmateString()),this.children.length===0&&!this.transform?`$${this.index}`:this.children.length===0?`\${${this.index}${e}}`:this.choice?`\${${this.index}|${this.choice.toTextmateString()}|${e}}`:`\${${this.index}:${this.children.map(t=>t.toTextmateString()).join("")}${e}}`}clone(){let e=new ei(this.index);return this.transform&&(e.transform=this.transform.clone()),e._children=this.children.map(t=>t.clone()),e}},fp=class extends na{constructor(){super(...arguments);this.options=[]}appendChild(e){return e instanceof ct&&(e.parent=this,this.options.push(e)),this}toString(){return this.options[0].value}toTextmateString(){return this.options.map(e=>e.value.replace(/\||,/g,"\\$&")).join(",")}len(){return this.options[0].len()}clone(){let e=new fp;for(let t of this.options)e.appendChild(t);return e}},gg=class extends na{resolve(e){let t=!1,i=e.replace(this.regexp,(...n)=>(t=!0,this._replace(n.slice(0,-2))));return!t&&this._children.some(n=>n instanceof Pi&&Boolean(n.elseValue))&&(i=this._replace([])),i}_replace(e){let t="";for(let i of this._children)if(i instanceof Pi){let n=e[i.index]||"";n=i.resolve(n),t+=n}else t+=i.toString();return t}toString(){return""}toTextmateString(){return`/${this.regexp.source}/${this.children.map(e=>e.toTextmateString())}/${(this.regexp.ignoreCase?"i":"")+(this.regexp.global?"g":"")}`}clone(){let e=new gg;return e.regexp=new RegExp(this.regexp.source,""+(this.regexp.ignoreCase?"i":"")+(this.regexp.global?"g":"")),e._children=this.children.map(t=>t.clone()),e}},Pi=class extends na{constructor(e,t,i,n){super();this.index=e;this.shorthandName=t;this.ifValue=i;this.elseValue=n}resolve(e){return this.shorthandName==="upcase"?e?e.toLocaleUpperCase():"":this.shorthandName==="downcase"?e?e.toLocaleLowerCase():"":this.shorthandName==="capitalize"?e?e[0].toLocaleUpperCase()+e.substr(1):"":this.shorthandName==="pascalcase"?e?this._toPascalCase(e):"":Boolean(e)&&typeof this.ifValue=="string"?this.ifValue:!e&&typeof this.elseValue=="string"?this.elseValue:e||""}_toPascalCase(e){let t=e.match(/[a-z]+/gi);return t?t.map(i=>i.charAt(0).toUpperCase()+i.substr(1).toLowerCase()).join(""):e}toTextmateString(){let e="${";return e+=this.index,this.shorthandName?e+=`:/${this.shorthandName}`:this.ifValue&&this.elseValue?e+=`:?${this.ifValue}:${this.elseValue}`:this.ifValue?e+=`:+${this.ifValue}`:this.elseValue&&(e+=`:-${this.elseValue}`),e+="}",e}clone(){return new Pi(this.index,this.shorthandName,this.ifValue,this.elseValue)}},yn=class extends k0{constructor(e){super();this.name=e}async resolve(e){let t=await e.resolve(this);if(t&&t.includes(` -`)){let i="";this.snippet.walk(l=>{if(l==this)return!1;if(l instanceof ct){let u=l.toString().split(/\r?\n/);i=u[u.length-1].match(/^\s*/)[0]}return!0});let n=t.split(` -`),o=n.filter(l=>l.length>0).map(l=>l.match(/^\s*/)[0]),s=o.length==0?"":o.reduce((l,u)=>l.lengthu==0||l.length==0||!l.startsWith(s)?l:i+l.slice(s.length)).join(` -`)}return this.transform&&(t=this.transform.resolve(t||"")),t!==void 0?(this._children=[new ct(t)],!0):!1}toTextmateString(){let e="";return this.transform&&(e=this.transform.toTextmateString()),this.children.length===0?`\${${this.name}${e}}`:`\${${this.name}:${this.children.map(t=>t.toTextmateString()).join("")}${e}}`}clone(){let e=new yn(this.name);return this.transform&&(e.transform=this.transform.clone()),e._children=this.children.map(t=>t.clone()),e}};function iU(r,e){let t=[...r];for(;t.length>0;){let i=t.shift();if(!e(i))break;t.unshift(...i.children)}}var cp=class extends na{get placeholderInfo(){if(!this._placeholders){this._variables=[];let e=[],t;this.walk(i=>{if(i instanceof ei)e.push(i),t=!t||t.index90)&&this._variables.push(i)}return!0}),this._placeholders={all:e,last:t}}return this._placeholders}get variables(){return this._variables}get placeholders(){let{all:e}=this.placeholderInfo;return e}get maxIndexNumber(){let{placeholders:e}=this;return e.reduce((t,i)=>Math.max(t,i.index),0)}get minIndexNumber(){let{placeholders:e}=this,t=e.map(i=>i.index);return t.sort((i,n)=>i-n),t.length>1&&t[0]==0?t[1]:t[0]||0}insertSnippet(e,t,i){let n=this.placeholders[t];if(!n)return;let{index:o}=n,s=kt.create("untitled:/1","snippet",0,n.toString());e=kt.applyEdits(s,[{range:i,newText:e}]);let a=new Go().parse(e,!0),l=a.maxIndexNumber+1,u=[];for(let c of a.placeholders)c.isFinalTabstop?c.index=l+o:c.index=c.index+o,u.push(c.index);return this.walk(c=>(c instanceof ei&&c.index>o&&(c.index=c.index+l),!0)),this.replace(n,a.children),Math.min.apply(null,u)}updatePlaceholder(e,t){let i=this.placeholders[e];for(let n of this.placeholders)if(n.index==i.index){let o=n.children[0],s=n.transform?n.transform.resolve(t):t;o?n.setOnlyChild(new ct(s)):n.appendChild(new ct(s))}this._placeholders=void 0}updateVariable(e,t){let i=this.variables[e-this.maxIndexNumber-1];if(i){let n=this.variables.filter(o=>o.name==i.name);for(let o of n){let s=o.transform?o.transform.resolve(t):t;o.setOnlyChild(new ct(s))}}}getPlaceholderText(e,t){let i=this.placeholders[e];return i&&i.transform?i.transform.resolve(t):t}offset(e){let t=0,i=!1;return this.walk(n=>n===e?(i=!0,!1):(t+=n.len(),!0)),i?t:-1}fullLen(e){let t=0;return iU([e],i=>(t+=i.len(),!0)),t}enclosingPlaceholders(e){let t=[],{parent:i}=e;for(;i;)i instanceof ei&&t.push(i),i=i.parent;return t}async resolveVariables(e){let t=[];this.walk(i=>(i instanceof yn&&t.push(i),!0)),await Promise.all(t.map(i=>i.resolve(e)))}appendChild(e){return this._placeholders=void 0,super.appendChild(e)}replace(e,t){return this._placeholders=void 0,super.replace(e,t)}toTextmateString(){return this.children.reduce((e,t)=>e+t.toTextmateString(),"")}clone(){let e=new cp;return this._children=this.children.map(t=>t.clone()),e}walk(e){iU(this.children,e)}},Go=class{constructor(){this._scanner=new R0}static escape(e){return e.replace(/\$|}|\\/g,"\\$&")}text(e){return this.parse(e).toString()}parse(e,t){this._scanner.text(e),this._token=this._scanner.next();let i=new cp;for(;this._parse(i););let n=new Map,o=[];i.walk(s=>(s instanceof ei&&(s.isFinalTabstop?n.set(0,void 0):!n.has(s.index)&&s.children.length>0?n.set(s.index,s.children):o.push(s)),!0));for(let s of o)if(n.has(s.index)){let a=new ei(s.index);a.transform=s.transform;for(let l of n.get(s.index)){let u=l.clone();if(a.transform){if(u instanceof ct)u=new ct(a.transform.resolve(u.value));else for(let c of u.children)if(c instanceof ct){u.replace(c,[new ct(a.transform.resolve(c.value))]);break}}a.appendChild(u)}i.replace(s,[a])}return!n.has(0)&&t&&i.appendChild(new ei(0)),i}_accept(e,t){if(e===void 0||this._token.type===e){let i=t?this._scanner.tokenText(this._token):!0;return this._token=this._scanner.next(),i}return!1}_backTo(e){return this._scanner.pos=e.pos+e.len,this._token=e,!1}_until(e){if(this._token.type===14)return!1;let t=this._token;for(;this._token.type!==e;)if(this._token=this._scanner.next(),this._token.type===14)return!1;let i=this._scanner.value.substring(t.pos,this._token.pos);return this._token=this._scanner.next(),i}_parse(e){return this._parseEscaped(e)||this._parseTabstopOrVariableName(e)||this._parseComplexPlaceholder(e)||this._parseComplexVariable(e)||this._parseAnything(e)}_parseEscaped(e){let t;return(t=this._accept(5,!0))?(t=this._accept(0,!0)||this._accept(4,!0)||this._accept(5,!0)||t,e.appendChild(new ct(t)),!0):!1}_parseTabstopOrVariableName(e){let t,i=this._token;return this._accept(0)&&(t=this._accept(9,!0)||this._accept(8,!0))?(e.appendChild(/^\d+$/.test(t)?new ei(Number(t)):new yn(t)),!0):this._backTo(i)}_parseComplexPlaceholder(e){let t,i=this._token;if(!(this._accept(0)&&this._accept(3)&&(t=this._accept(8,!0))))return this._backTo(i);let o=new ei(Number(t));if(this._accept(1))for(;;){if(this._accept(4))return e.appendChild(o),!0;if(!this._parse(o))return e.appendChild(new ct("${"+t+":")),o.children.forEach(e.appendChild,e),!0}else if(o.index>0&&this._accept(7)){let s=new fp;for(;;){if(this._parseChoiceElement(s)){if(this._accept(2))continue;if(this._accept(7)&&(o.appendChild(s),this._accept(4)))return e.appendChild(o),!0}return this._backTo(i),!1}}else return this._accept(6)?this._parseTransform(o)?(e.appendChild(o),!0):(this._backTo(i),!1):this._accept(4)?(e.appendChild(o),!0):this._backTo(i)}_parseChoiceElement(e){let t=this._token,i=[];for(;!(this._token.type===2||this._token.type===7);){let n;if((n=this._accept(5,!0))?n=this._accept(2,!0)||this._accept(7,!0)||this._accept(5,!0)||n:n=this._accept(void 0,!0),!n)return this._backTo(t),!1;i.push(n)}return i.length===0?(this._backTo(t),!1):(e.appendChild(new ct(i.join(""))),!0)}_parseComplexVariable(e){let t,i=this._token;if(!(this._accept(0)&&this._accept(3)&&(t=this._accept(9,!0))))return this._backTo(i);let o=new yn(t);if(this._accept(1))for(;;){if(this._accept(4))return e.appendChild(o),!0;if(!this._parse(o))return e.appendChild(new ct("${"+t+":")),o.children.forEach(e.appendChild,e),!0}else return this._accept(6)?this._parseTransform(o)?(e.appendChild(o),!0):(this._backTo(i),!1):this._accept(4)?(e.appendChild(o),!0):this._backTo(i)}_parseTransform(e){let t=new gg,i="",n="";for(;!this._accept(6);){let o;if(o=this._accept(5,!0)){o=this._accept(6,!0)||o,i+=o;continue}if(this._token.type!==14){i+=this._accept(void 0,!0);continue}return!1}for(;!this._accept(6);){let o;if(o=this._accept(5,!0)){o=this._accept(6,!0)||o,t.appendChild(new ct(o));continue}if(this._parseFormatString(t)||this._parseAnything(t)){let s=t.children[0];s&&s.value&&s.value.includes("\\n")&&(s.value=s.value.replace(/\\n/g,` -`));continue}return!1}for(;!this._accept(4);){if(this._token.type!==14){n+=this._accept(void 0,!0);continue}return!1}try{t.regexp=new RegExp(i,n)}catch(o){return!1}return e.transform=t,!0}_parseFormatString(e){let t=this._token;if(!this._accept(0))return!1;let i=!1;this._accept(3)&&(i=!0);let n=this._accept(8,!0);if(n)if(i){if(this._accept(4))return e.appendChild(new Pi(Number(n))),!0;if(!this._accept(1))return this._backTo(t),!1}else return e.appendChild(new Pi(Number(n))),!0;else return this._backTo(t),!1;if(this._accept(6)){let o=this._accept(9,!0);return!o||!this._accept(4)?(this._backTo(t),!1):(e.appendChild(new Pi(Number(n),o)),!0)}else if(this._accept(11)){let o=this._until(4);if(o)return e.appendChild(new Pi(Number(n),void 0,o,void 0)),!0}else if(this._accept(12)){let o=this._until(4);if(o)return e.appendChild(new Pi(Number(n),void 0,void 0,o)),!0}else if(this._accept(13)){let o=this._until(1);if(o){let s=this._until(4);if(s)return e.appendChild(new Pi(Number(n),void 0,o,s)),!0}}else{let o=this._until(4);if(o)return e.appendChild(new Pi(Number(n),void 0,void 0,o)),!0}return this._backTo(t),!1}_parseAnything(e){if(this._token.type!==14){let t=this._scanner.tokenText(this._token);return e.appendChild(new ct(t)),this._accept(void 0),!0}return!1}};var $u=S(W());var WC=S(W());var c9=S(Ul()),f9=S(require("fs")),Hv=S(require("path")),p9=S(require("util")),d9=S(W());var Jz=S(Vr());var at=S($i()),Yz=S(Px()),Ie=S(require("path")),Xz=S(If()),$v=S(W());var Zz=S(_l());var nU=S(require("events"));var AAe=U()("model-installBuffer"),tn;(function(r){r[r.Waiting=0]="Waiting",r[r.Faild=1]="Faild",r[r.Progressing=2]="Progressing",r[r.Success=3]="Success"})(tn||(tn={}));var I0=class extends nU.EventEmitter{constructor(e=!1,t=!1,i=void 0){super();this.isUpdate=e;this.isSync=t;this.channel=i;this.statMap=new Map;this.messagesMap=new Map;this.names=[]}setExtensions(e){this.statMap.clear(),this.names=e;for(let t of e)this.statMap.set(t,0)}addMessage(e,t,i=!1){if(i&&this.channel)return;let n=this.messagesMap.get(e)||[];this.messagesMap.set(e,n.concat(t.trim().split(/\r?\n/))),this.channel&&this.channel.appendLine(`[${e}] ${t}`)}startProgress(e){for(let t of e)this.statMap.set(t,2)}finishProgress(e,t=!0){this.channel&&(t?this.channel.appendLine(`[${e}] install succeed!`):this.channel.appendLine(`[${e}] install failed!`)),this.statMap.set(e,t?3:1)}get remains(){let e=0;for(let t of this.names){let i=this.statMap.get(t);[3,1].includes(i)||(e=e+1)}return e}getLines(){let e=[];for(let t of this.names){let i=this.statMap.get(t),n="*";switch(i){case 2:{let s=new Date,a=Math.floor(s.getMilliseconds()/100);n=kD[a];break}case 1:n="\u2717";break;case 3:n="\u2713";break}let o=this.messagesMap.get(t)||[];e.push(`- ${n} ${t} ${o.length?o[o.length-1]:""}`)}return e}getMessages(e){if(e<=1)return[];let t=this.names[e-2];return t?this.messagesMap.get(t):[]}draw(e,t){let{remains:i}=this,o=[i==0?`${this.isUpdate?"Update":"Install"} finished`:`Installing, ${i} remains...`,"",...this.getLines()];t.setLines(o,{start:0,end:-1,strictIndexing:!1},!0),i==0&&this.interval&&(clearInterval(this.interval),this.interval=null),process.env.VIM_NODE_RPC&&e.command("redraw",!0)}highlight(e){e.call("matchadd",["CocListFgCyan","^\\-\\s\\zs\\*"],!0),e.call("matchadd",["CocListFgGreen","^\\-\\s\\zs\u2713"],!0),e.call("matchadd",["CocListFgRed","^\\-\\s\\zs\u2717"],!0),e.call("matchadd",["CocListFgYellow","^-.\\{3\\}\\zs\\S\\+"],!0)}async show(e){let{isSync:t}=this;if(this.channel)return;e.pauseNotification(),e.command(t?"enew":"vs +enew",!0),e.call("bufnr",["%"],!0),e.command("setl buftype=nofile bufhidden=wipe noswapfile nobuflisted wrap undolevels=-1",!0),t||e.command("nnoremap q :q",!0),this.highlight(e);let i=await e.resumeNotification(),n=i&&i[1]==null?i[0][1]:null;if(!n)return;this.bufnr=n;let o=e.createBuffer(n);this.interval=setInterval(()=>{this.draw(e,o)},100)}dispose(){this.interval&&clearInterval(this.interval)}},F0=I0;var W5=S(require("events")),H5=S(require("child_process"));var z5=S(require("readline")),pr=S($i()),G5=S(require("os")),Sn=S(require("path")),V5=S(_U()),mv=S(If());var B5=S(LU()),dv=S(W0()),hv=S($i()),Up=S(require("path")),j5=S(AW()),U5=S(d5());var pv=S(W0()),vE=S(require("url")),O5=S(require("fs"));var L5=S(require("querystring")),M5=S(D5()),N5=S(R5()),q5=S(A5()),$5=U()("model-fetch");function iye(r){let e;r.protocol==="http:"?e=process.env.HTTP_PROXY||process.env.http_proxy||null:r.protocol==="https:"&&(e=process.env.HTTPS_PROXY||process.env.https_proxy||process.env.HTTP_PROXY||process.env.http_proxy||null);let t=process.env.NO_PROXY||process.env.no_proxy;if(t==="*")e=null;else if(t){let i=r.hostname.replace(/^\.*/,".").toLowerCase(),n=r.port||r.protocol.startsWith("https")?"443":"80",o=t.split(",");for(let s=0,a=o.length;s{if(i){let l=i.onCancellationRequested(()=>{l.dispose(),a.destroy(new Error("request aborted"))})}let a=n.request(t,l=>{let u=l;if(l.statusCode>=200&&l.statusCode<300||l.statusCode===1223){let c=l.headers||{},f=[],p=c["content-type"]||"";u=q5.default(l),u.on("data",d=>{f.push(d)}),u.on("end",()=>{let d=Buffer.concat(f);if(!t.buffer&&(p.startsWith("application/json")||p.startsWith("text/"))){let h=p.match(/charset=(\S+)/),m=h?h[1]:"utf8",y=d.toString(m);if(!p.includes("application/json"))o(y);else try{let g=JSON.parse(y);o(g)}catch(g){s(new Error(`Parse response error: ${g}`))}}else o(d)}),u.on("error",d=>{s(new Error(`Unable to connect ${r}: ${d.message}`))})}else s(new Error(`Bad response from ${r}: ${l.statusCode}`))});a.on("error",s),a.on("timeout",()=>{a.destroy(new Error(`Request timeout after ${t.timeout}ms`))}),e&&(typeof e=="string"||Buffer.isBuffer(e)?a.write(e):a.write(JSON.stringify(e))),t.timeout&&a.setTimeout(t.timeout),a.end()})}function oye(r){return r===null?"null":r===void 0?"undefined":typeof r=="string"?"string":Buffer.isBuffer(r)?"buffer":Array.isArray(r)||xt(r)?"object":"unknown"}function Ru(r,e={},t){let i=yE(r,e);return sye(r,e.data,i,t).catch(n=>{if($5.error(`Fetch error for ${r}:`,i,n),i.agent&&i.agent.proxy){let{proxy:o}=i.agent;throw new Error(`Request failed using proxy ${o.host}: ${n.message}`)}else throw n})}var bE=U()("model-download");function Wp(r,e,t){let{dest:i,onProgress:n,extract:o}=e;if(!i||!Up.default.isAbsolute(i))throw new Error("Expect absolute file path for dest option.");let s;try{s=hv.default.statSync(i)}catch(c){hv.default.mkdirpSync(i)}if(s&&!s.isDirectory())throw new Error(`${i} exists, but not directory!`);let a=r.startsWith("https")?dv.https:dv.http,l=yE(r,e),u=Up.default.extname(r);return new Promise((c,f)=>{if(t){let d=t.onCancellationRequested(()=>{d.dispose(),p.destroy(new Error("request aborted"))})}let p=a.request(l,d=>{var h,m;if(d.statusCode>=200&&d.statusCode<300||d.statusCode===1223){let y=d.headers||{},g=y["content-disposition"];if(!u&&g){let P=B5.default.parse(g);((h=P.parameters)==null?void 0:h.filename)&&(u=Up.default.extname(P.parameters.filename))}if(o===!0)if(u===".zip"||y["content-type"]=="application/zip")o="unzip";else if(u==".tgz")o="untar";else{f(new Error(`Unable to extract for ${r}`));return}let w=Number(y["content-length"]),x=0;isNaN(w)||d.on("data",P=>{x+=P.length;let k=(x/w*100).toFixed(1);n?n(k):bE.info(`Download ${r} progress ${k}%`)}),d.on("error",P=>{f(new Error(`Unable to connect ${r}: ${P.message}`))}),d.on("end",()=>{bE.info("Download completed:",r)});let E;o==="untar"?E=d.pipe(j5.default.x({strip:(m=e.strip)!=null?m:1,C:i})):o==="unzip"?E=d.pipe(U5.default.Extract({path:i})):(i=Up.default.join(i,`${$o()}${u}`),E=d.pipe(hv.default.createWriteStream(i))),E.on("finish",()=>{bE.info(`Downloaded ${r} => ${i}`),setTimeout(()=>{c(i)},100)}),E.on("error",f)}else f(new Error(`Invalid response from ${r}: ${d.statusCode}`))});p.on("error",f),p.on("timeout",()=>{p.destroy(new Error(`request timeout after ${e.timeout}ms`))}),e.timeout&&p.setTimeout(e.timeout),p.end()})}var K5=U()("model-installer");function aye(r="coc.nvim"){let e=V5.default("npm",{registry:"https://registry.npmjs.org/"}),t=e[`${r}:registry`]||e.config_registry||e.registry;return t.endsWith("/")?t:t+"/"}var J5=class extends W5.EventEmitter{constructor(e,t,i){super();this.root=e;this.npm=t;this.def=i;if(pr.default.existsSync(e)||pr.default.mkdirpSync(e),/^https?:/.test(i))this.url=i;else if(i.startsWith("@")){let n=i.indexOf("@",1);n>1?(this.name=i.substring(0,n),this.version=i.substring(n+1)):this.name=i}else if(i.includes("@")){let[n,o]=i.split("@",2);this.name=n,this.version=o}else this.name=i}get info(){return{name:this.name,version:this.version}}async install(){this.log(`Using npm from: ${this.npm}`);let e=await this.getInfo();K5.info(`Fetched info of ${this.def}`,e);let{name:t}=e,i=e["engines.coc"]?e["engines.coc"].replace(/^\^/,">="):"";if(i&&!mv.default.satisfies(b.version,i))throw new Error(`${t} ${e.version} requires coc.nvim >= ${i}, please update coc.nvim.`);return await this.doInstall(e),t}async update(e){this.url=e;let t=Sn.default.join(this.root,this.name);if((await pr.default.lstat(t)).isSymbolicLink()){this.log("Skipped update for symbol link");return}let n;if(pr.default.existsSync(Sn.default.join(t,"package.json"))){let l=await pr.default.readFile(Sn.default.join(t,"package.json"),"utf8");n=JSON.parse(l).version}this.log(`Using npm from: ${this.npm}`);let o=await this.getInfo();if(n&&o.version&&mv.default.gte(n,o.version)){this.log(`Current version ${n} is up to date.`);return}let s=o["engines.coc"]?o["engines.coc"].replace(/^\^/,">="):"";if(s&&!mv.default.satisfies(b.version,s))throw new Error(`${o.version} requires coc.nvim ${s}, please update coc.nvim.`);await this.doInstall(o);let a=Sn.default.join(this.root,o.name,"package.json");if(pr.default.existsSync(a))return this.log(`Updated to v${o.version}`),Sn.default.dirname(a);throw new Error(`Package.json not found: ${a}`)}async doInstall(e){let t=Sn.default.join(this.root,e.name);if(pr.default.existsSync(t)&&!pr.default.statSync(t).isDirectory()){this.log(`${t} is not directory skipped install`);return}let i=await pr.default.mkdtemp(Sn.default.join(G5.default.tmpdir(),`${e.name.replace("/","-")}-`)),n=e["dist.tarball"];this.log(`Downloading from ${n}`),await Wp(n,{dest:i,onProgress:p=>this.log(`Download progress ${p}%`,!0),extract:"untar"}),this.log(`Extension download at ${i}`);let o=await pr.default.readFile(Sn.default.join(i,"package.json"),"utf8"),{dependencies:s}=JSON.parse(o);s&&Object.keys(s).length&&await new Promise((d,h)=>{let m=["install","--ignore-scripts","--no-lockfile","--production"];n.startsWith("https://github.com")&&(m=["install"]),(this.npm.endsWith("npm")||this.npm.endsWith("npm.CMD"))&&!this.npm.endsWith("pnpm")&&m.push("--legacy-peer-deps"),this.npm.endsWith("yarn")&&m.push("--ignore-engines"),this.log(`Installing dependencies by: ${this.npm} ${m.join(" ")}.`);let y=H5.spawn(this.npm,m,{cwd:i});z5.default.createInterface({input:y.stdout}).on("line",x=>{this.log(`[npm] ${x}`,!0)}),y.stderr.setEncoding("utf8"),y.stdout.setEncoding("utf8"),y.on("error",h);let w="";y.stderr.on("data",x=>{w+=x}),y.on("exit",x=>{if(x){w&&this.log(w),h(new Error(`${this.npm} install exited with ${x}`));return}d()})});let a=Sn.default.resolve(this.root,global.hasOwnProperty("__TEST__")?"":"..","package.json"),l=[],u=Hl(pr.default.readFileSync(a,"utf8"),l,{allowTrailingComma:!0});if(l&&l.length>0)throw new Error(`Error on load ${a}`);u.dependencies=u.dependencies||{},this.url?u.dependencies[e.name]=this.url:u.dependencies[e.name]=">="+e.version;let c={dependencies:{}};Object.keys(u.dependencies).sort().forEach(p=>{c.dependencies[p]=u.dependencies[p]});let f=await It(t);f&&(f.isDirectory()?pr.default.removeSync(t):pr.default.unlinkSync(t)),await pr.default.move(i,t,{overwrite:!0}),await pr.default.writeFile(a,JSON.stringify(c,null,2),{encoding:"utf8"}),this.log(`Update package.json at ${a}`),this.log(`Installed extension ${this.name}@${e.version} at ${t}`)}async getInfo(){if(this.url)return await this.getInfoFromUri();let e=aye();this.log(`Get info from ${e}`);let t=await Ru(e+this.name,{timeout:1e4,buffer:!0}),i=JSON.parse(t.toString());this.version||(this.version=i["dist-tags"].latest);let n=i.versions[this.version];if(!n)throw new Error(`${this.def} doesn't exists in ${e}.`);let o=n.engines&&n.engines.coc;if(!o)throw new Error(`${this.def} is not valid coc extension, "engines" field with coc property required.`);return{"dist.tarball":n.dist.tarball,"engines.coc":o,version:n.version,name:i.name}}async getInfoFromUri(){let{url:e}=this;if(!e.includes("github.com"))throw new Error(`"${e}" is not supported, coc.nvim support github.com only`);e=e.replace(/\/$/,"");let t="master";if(e.includes("@")){let s=e.indexOf("@");t=e.substr(s+1),e=e.substring(0,s)}let i=e.replace("github.com","raw.githubusercontent.com")+`/${t}/package.json`;this.log(`Get info from ${i}`);let n=await Ru(i,{timeout:1e4}),o=typeof n=="string"?JSON.parse(n):n;return this.name=o.name,{"dist.tarball":`${e}/archive/${t}.tar.gz`,"engines.coc":o.engines?o.engines.coc:null,name:o.name,version:o.version}}log(e,t=!1){K5.info(e),this.emit("message",e,t)}};function gv(r,e){return t=>new J5(e,r,t)}var ku=S(require("fs"));var lye=U()("model-memos"),wE=class{constructor(e){this.filepath=e;ku.default.existsSync(e)||ku.default.writeFileSync(e,"{}","utf8")}fetchContent(e,t){try{let i=ku.default.readFileSync(this.filepath,"utf8"),o=JSON.parse(i)[e];return o?o[t]:void 0}catch(i){return}}async update(e,t,i){let{filepath:n}=this;try{let o=ku.default.readFileSync(n,"utf8"),s=o?JSON.parse(o):{};s[e]=s[e]||{},i!==void 0?s[e][t]=zn(i):delete s[e][t],o=JSON.stringify(s,null,2),ku.default.writeFileSync(n,o,"utf8")}catch(o){lye.error("Error on update memos:",o)}}createMemento(e){return{get:(t,i)=>{let n=this.fetchContent(e,t);return n===void 0?i:n},update:async(t,i)=>{await this.update(e,t,i)}}}},Y5=wE;var M4e=S(bh());var zz=S(require("fs")),Gz=S(require("path")),qv=S(require("vm"));var X5=Object.prototype,uye=X5.hasOwnProperty;function Z5(r,...e){return r=Object(r),e.forEach(t=>{if(t!=null){t=Object(t);for(let i in t){let n=r[i];(n===void 0||n===X5[i]&&!uye.call(r,i))&&(r[i]=t[i])}}}),r}function Sa(r,e){let t={};for(let i of Object.keys(r))e.includes(i)||(t[i]=r[i]);return t}var Vz=U(),h4e=Vz("util-factoroy"),Pn=require("module"),Kye=["reallyExit","abort","umask","setuid","setgid","setgroups","_fatalException","exit","kill"];function Jye(r){return()=>{throw new Error(`process.${r}() is not allowed in extension sandbox`)}}var ce=S(W());var vv=S(W());var Iu=S(W());var WLe=U()("provider-manager"),xE=class{constructor(){this.providers=new Set}hasProvider(e){return this.getProvider(e)!=null}getProvider(e){let t=0,i;for(let n of this.providers){let{selector:o,priority:s}=n,a=b.match(o,e);a!=0&&(typeof s=="number"&&(a=s),!(ai.id==e);return t?t.provider:null}getProviders(e){let t=Array.from(this.providers);return t=t.filter(i=>b.match(i.selector,e)>0),t.sort((i,n)=>b.match(n.selector,e)-b.match(i.selector,e))}toLocations(e){let t=[];for(let i of e)if(!!i)if(Iu.Location.is(i))DE(t,i);else if(Array.isArray(i)){for(let n of i)if(Iu.Location.is(n))DE(t,n);else if(Iu.LocationLink.is(n)){let{targetUri:o,targetSelectionRange:s}=n;DE(t,Iu.Location.create(o,s))}}else C.showMessage(`Bad definition ${JSON.stringify(i)}`,"error");return t}},xe=xE;function DE(r,e){let{range:t,uri:i}=e;r.find(n=>n.uri==i&&qe(n.range,t))==null&&r.push(e)}var QLe=U()("codeActionManager"),SE=class extends xe{register(e,t,i,n){let o={id:he(),selector:e,provider:t,kinds:n,clientId:i};return this.providers.add(o),vv.Disposable.create(()=>{this.providers.delete(o)})}async provideCodeActions(e,t,i,n){let o=this.getProviders(e);if(!o.length)return null;if(i.only){let{only:a}=i;o=o.filter(l=>!(l.kinds&&!l.kinds.some(u=>a.includes(u))))}let s=[];return await Promise.all(o.map(a=>{let{provider:l,clientId:u}=a;return Promise.resolve(l.provideCodeActions(e,t,i,n)).then(c=>{if(!(!c||c.length==0))for(let f of c)if(vv.Command.is(f)){let p={title:f.title,command:f,clientId:u};s.push(p)}else{if(i.only){if(!f.kind)continue;let d=!1;for(let h of i.only)if(f.kind.startsWith(h)){d=!0;break}if(!d)continue}s.findIndex(d=>d.title==f.title)==-1&&s.push(Object.assign({clientId:u},f))}})})),s}dispose(){this.providers=new Set}},Q5=SE;var e4=S(W());var EE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),e4.Disposable.create(()=>{this.providers.delete(i)})}async provideCodeLenses(e,t){let i=this.getProviders(e);if(!i.length)return null;let n=await Promise.all(i.map(o=>{let{provider:s,id:a}=o;return Promise.resolve(s.provideCodeLenses(e,t)).then(l=>{if(Array.isArray(l))for(let u of l)u.source=a;return l||[]})}));return[].concat(...n)}async resolveCodeLens(e,t){if(e.command)return e;let{source:i}=e,n=this.poviderById(i);if(!n||typeof n.resolveCodeLens!="function")return e;let o=await Promise.resolve(n.resolveCodeLens(Sa(e,["source"]),t));return Object.assign(e,o),e}dispose(){this.providers=new Set}},t4=EE;var r4=S(W());var vMe=U()("definitionManager"),CE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),r4.Disposable.create(()=>{this.providers.delete(i)})}async provideDeclaration(e,t,i){let n=this.getProvider(e);if(!n)return null;let{provider:o}=n;return await Promise.resolve(o.provideDeclaration(e,t,i))}dispose(){this.providers=new Set}},i4=CE;var n4=S(W());var _Me=U()("definitionManager"),_E=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),n4.Disposable.create(()=>{this.providers.delete(i)})}async provideDefinition(e,t,i){let n=this.getProviders(e);if(!n.length)return null;let o=await Promise.all(n.map(s=>{let{provider:a}=s;return Promise.resolve(a.provideDefinition(e,t,i))}));return this.toLocations(o)}dispose(){this.providers=new Set}},o4=_E;var s4=S(W());var PE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),s4.Disposable.create(()=>{this.providers.delete(i)})}async provideDocumentColors(e,t){let i=this.getProvider(e);if(!i)return null;let{provider:n}=i;return await Promise.resolve(n.provideDocumentColors(e,t))}async provideColorPresentations(e,t,i){let{range:n,color:o}=e,s=this.getProvider(t);if(!s)return null;let{provider:a}=s;return await Promise.resolve(a.provideColorPresentations(o,{document:t,range:n},i))}dispose(){this.providers=new Set}},a4=PE;var l4=S(W());var TE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),l4.Disposable.create(()=>{this.providers.delete(i)})}async provideDocumentHighlights(e,t,i){let n=this.getProvider(e);if(!n)return null;let{provider:o}=n;return await Promise.resolve(o.provideDocumentHighlights(e,t,i))}dispose(){this.providers=new Set}},u4=TE;var c4=S(W());var RE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),c4.Disposable.create(()=>{this.providers.delete(i)})}async _provideDocumentLinks(e,t,i){let{provider:n,id:o}=e,s=await Promise.resolve(n.provideDocumentLinks(t,i));return!s||!s.length?[]:(s.forEach(a=>{a.data=a.data||{},a.data.source=o}),s)}async provideDocumentLinks(e,t){let i=this.getProviders(e);if(i.length==0)return[];let n=await Promise.all(i.map(o=>this._provideDocumentLinks(o,e,t)));return[].concat(...n)}async resolveDocumentLink(e,t){let{data:i}=e;if(!i||!i.source)return null;for(let n of this.providers)if(n.id==i.source){let{provider:o}=n;return e=await Promise.resolve(o.resolveDocumentLink(e,t)),e}return null}dispose(){this.providers=new Set}},f4=RE;var p4=S(W());var kE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),p4.Disposable.create(()=>{this.providers.delete(i)})}async provideDocumentSymbols(e,t){let i=this.getProvider(e);if(!i)return null;let{provider:n}=i;return await Promise.resolve(n.provideDocumentSymbols(e,t))||[]}dispose(){this.providers=new Set}},d4=kE;var h4=S(W());var IE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),h4.Disposable.create(()=>{this.providers.delete(i)})}async provideFoldingRanges(e,t,i){let n=this.getProvider(e);if(!n)return null;let{provider:o}=n;return await Promise.resolve(o.provideFoldingRanges(e,t,i))||[]}dispose(){this.providers=new Set}},m4=IE;var g4=S(W());var FE=class extends xe{register(e,t,i=0){let n={id:he(),selector:e,priority:i,provider:t};return this.providers.add(n),g4.Disposable.create(()=>{this.providers.delete(n)})}handles(e){return this.getProvider(e)!=null}async provideDocumentFormattingEdits(e,t,i){let n=this.getProvider(e);if(!n)return null;let{provider:o}=n;return await Promise.resolve(o.provideDocumentFormattingEdits(e,t,i))}dispose(){this.providers=new Set}},v4=FE;var y4=S(W());var AE=class extends xe{register(e,t,i=0){let n={id:he(),selector:e,provider:t,priority:i};return this.providers.add(n),y4.Disposable.create(()=>{this.providers.delete(n)})}async provideDocumentRangeFormattingEdits(e,t,i,n){let o=this.getProvider(e);if(!o)return null;let{provider:s}=o;return await Promise.resolve(s.provideDocumentRangeFormattingEdits(e,t,i,n))}dispose(){this.providers=new Set}},b4=AE;var w4=S(W());var OE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),w4.Disposable.create(()=>{this.providers.delete(i)})}async provideHover(e,t,i){let n=this.getProviders(e);if(n.length===0)return null;let o=[];for(let s=0,a=n.length;s{this.providers.delete(i)})}async provideReferences(e,t,i){let n=this.getProviders(e);if(!n.length)return null;let o=await Promise.all(n.map(s=>{let{provider:a}=s;return Promise.resolve(a.provideImplementation(e,t,i))}));return this.toLocations(o)}dispose(){this.providers=new Set}},S4=LE;var E4=S(W());var YNe=U()("onTypeFormatManager"),ME=class{constructor(){this.providers=new Set}register(e,t,i){let n={triggerCharacters:i,selector:e,provider:t};return this.providers.add(n),E4.Disposable.create(()=>{this.providers.delete(n)})}hasProvider(e){for(let t of this.providers){let{selector:i}=t;if(b.match(i,e)>0)return!0}return!1}getProvider(e,t){for(let i of this.providers){let{triggerCharacters:n,selector:o}=i;if(b.match(o,e)>0&&n.includes(t))return i.provider}return null}async onCharacterType(e,t,i,n){let o=this.getProvider(t,e);if(!o)return;let s=await b.getFormatOptions(t.uri);return await Promise.resolve(o.provideOnTypeFormattingEdits(t,i,e,s,n))}dispose(){this.providers=new Set}},C4=ME;var _4=S(W());var NE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),_4.Disposable.create(()=>{this.providers.delete(i)})}async provideSelectionRanges(e,t,i){let n=this.getProvider(e);if(!n)return null;let{provider:o}=n;return await Promise.resolve(o.provideSelectionRanges(e,t,i))||[]}dispose(){this.providers=new Set}},P4=NE;var T4=S(W());var qE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),T4.Disposable.create(()=>{this.providers.delete(i)})}async provideReferences(e,t,i,n){let o=this.getProviders(e);if(!o.length)return null;let s=await Promise.all(o.map(a=>{let{provider:l}=a;return Promise.resolve(l.provideReferences(e,t,i,n))}));return this.toLocations(s)}dispose(){this.providers=new Set}},R4=qE;var k4=S(W());var $E=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),k4.Disposable.create(()=>{this.providers.delete(i)})}async provideRenameEdits(e,t,i,n){let o=this.getProvider(e);if(!o)return null;let{provider:s}=o;return await Promise.resolve(s.provideRenameEdits(e,t,i,n))}async prepareRename(e,t,i){let n=this.getProvider(e);if(!n)return null;let{provider:o}=n;if(o.prepareRename==null)return null;let s=await Promise.resolve(o.prepareRename(e,t,i));return s==null?!1:s}dispose(){this.providers=new Set}},I4=$E;var F4=S(W());var BE=class extends xe{register(e,t,i){let n=i.reduce((s,a)=>s.concat(a.split(/\s*/g)),[]),o={id:he(),selector:e,provider:t,triggerCharacters:n};return this.providers.add(o),F4.Disposable.create(()=>{this.providers.delete(o)})}shouldTrigger(e,t){let i=this.getProvider(e);if(!i)return!1;let{triggerCharacters:n}=i;return n&&n.indexOf(t)!=-1}async provideSignatureHelp(e,t,i,n){let o=this.getProvider(e);if(!o)return null;let s=await Promise.resolve(o.provider.provideSignatureHelp(e,t,i,n));return s&&s.signatures&&s.signatures.length?s:null}dispose(){this.providers=new Set}},A4=BE;var O4=S(W());var jE=class extends xe{register(e,t){let i={id:he(),selector:e,provider:t};return this.providers.add(i),O4.Disposable.create(()=>{this.providers.delete(i)})}async provideTypeDefinition(e,t,i){let n=this.getProviders(e);if(!n.length)return null;let o=await Promise.all(n.map(s=>{let{provider:a}=s;return Promise.resolve(a.provideTypeDefinition(e,t,i))}));return this.toLocations(o)}dispose(){this.providers=new Set}},L4=jE;var M4=S(W()),UE=class{constructor(){this.providers=new Map}register(e){let t=he();return this.providers.set(t,e),M4.Disposable.create(()=>{this.providers.delete(t)})}async provideWorkspaceSymbols(e,t){let i=Array.from(this.providers.entries());if(!i.length)return[];let n=[];return await Promise.all(i.map(o=>{let[s,a]=o;return Promise.resolve(a.provideWorkspaceSymbols(e,t)).then(l=>{l&&(l.source=s,n.push(...l))})})),n}async resolveWorkspaceSymbol(e,t){let i=this.providers.get(e.source);if(!!i)return typeof i.resolveWorkspaceSymbol!="function"?Promise.resolve(e):await Promise.resolve(i.resolveWorkspaceSymbol(e,t))}hasProvider(){return this.providers.size>0}dispose(){this.providers=new Map}},N4=UE;var q4=S(W());var Jqe=U()("util-complete");function $4(r){let{line:e,linenr:t,colnr:i}=r,n=Rt(e,0,i-1);return{line:t-1,character:n.length}}function j4(r,e,t){let{label:i,data:n,insertTextFormat:o,insertText:s,textEdit:a}=r,l,u;if(n&&typeof n.word=="string")return n.word;if(a){let{range:c}=a;if(u=a.newText,c&&c.start.line==c.end.line){let{line:f,col:p,colnr:d}=e,h=Bf(f,p);if(c.start.character>h)u=f.slice(h,c.start.character)+u;else{let m=f.slice(c.start.character,h);m.length&&u.startsWith(m)&&(u=u.slice(m.length))}if(h=Bf(f,d-1),c.end.character>h){let m=f.slice(h,c.end.character);u.endsWith(m)&&(u=u.slice(0,-m.length))}}}else u=s;if(o==q4.InsertTextFormat.Snippet&&u&&u.includes("$")){let f=new Go().text(u);l=f?B4(f,t):i}else l=B4(u,t)||i;return l||""}function U4(r,e,t=""){return e.get(r)||t}function B4(r,e){if(!r)return"";for(let t=0;t{e.affectsConfiguration("suggest")&&this.loadCompleteConfig()},this)}get nvim(){return b.nvim}get detailField(){let{detailField:e,floatEnable:t}=this.completeConfig;return e=="preview"&&(!t||!b.floatSupported)?"menu":"preview"}loadCompleteConfig(){let e=b.getConfiguration("suggest"),t=e.get("completionItemKindLabels",{});this.completionItemKindMap=new Map([[ce.CompletionItemKind.Text,t.text||"v"],[ce.CompletionItemKind.Method,t.method||"f"],[ce.CompletionItemKind.Function,t.function||"f"],[ce.CompletionItemKind.Constructor,typeof t.constructor=="function"?"f":t["constructor"]],[ce.CompletionItemKind.Field,t.field||"m"],[ce.CompletionItemKind.Variable,t.variable||"v"],[ce.CompletionItemKind.Class,t.class||"C"],[ce.CompletionItemKind.Interface,t.interface||"I"],[ce.CompletionItemKind.Module,t.module||"M"],[ce.CompletionItemKind.Property,t.property||"m"],[ce.CompletionItemKind.Unit,t.unit||"U"],[ce.CompletionItemKind.Value,t.value||"v"],[ce.CompletionItemKind.Enum,t.enum||"E"],[ce.CompletionItemKind.Keyword,t.keyword||"k"],[ce.CompletionItemKind.Snippet,t.snippet||"S"],[ce.CompletionItemKind.Color,t.color||"v"],[ce.CompletionItemKind.File,t.file||"F"],[ce.CompletionItemKind.Reference,t.reference||"r"],[ce.CompletionItemKind.Folder,t.folder||"F"],[ce.CompletionItemKind.EnumMember,t.enumMember||"m"],[ce.CompletionItemKind.Constant,t.constant||"v"],[ce.CompletionItemKind.Struct,t.struct||"S"],[ce.CompletionItemKind.Event,t.event||"E"],[ce.CompletionItemKind.Operator,t.operator||"O"],[ce.CompletionItemKind.TypeParameter,t.typeParameter||"T"]]),this.completeConfig={defaultKindText:t.default||"",priority:e.get("languageSourcePriority",99),echodocSupport:e.get("echodocSupport",!1),detailField:e.get("detailField","preview"),detailMaxLength:e.get("detailMaxLength",100),floatEnable:e.get("floatEnable",!0),invalidInsertCharacters:e.get("invalidInsertCharacters",["(","<","{","[","\r",` -`])}}hasFormatProvider(e){return!!(this.formatManager.hasProvider(e)||this.formatRangeManager.hasProvider(e))}registerOnTypeFormattingEditProvider(e,t,i){return this.onTypeFormatManager.register(e,t,i)}registerCompletionItemProvider(e,t,i,n,o=[],s,a){i=typeof i=="string"?[i]:i;let l=this.createCompleteSource(e,t,n,i,o,a||[],s);return Ge.addSource(l),yv.debug("created service source",e),{dispose:()=>{Ge.removeSource(e)}}}registerCodeActionProvider(e,t,i,n){return this.codeActionManager.register(e,t,i,n)}registerHoverProvider(e,t){return this.hoverManager.register(e,t)}registerSelectionRangeProvider(e,t){return this.selectionRangeManager.register(e,t)}registerSignatureHelpProvider(e,t,i){return this.signatureManager.register(e,t,i)}registerDocumentSymbolProvider(e,t){return this.documentSymbolManager.register(e,t)}registerFoldingRangeProvider(e,t){return this.foldingRangeManager.register(e,t)}registerDocumentHighlightProvider(e,t){return this.documentHighlightManager.register(e,t)}registerCodeLensProvider(e,t){return this.codeLensManager.register(e,t)}registerDocumentLinkProvider(e,t){return this.documentLinkManager.register(e,t)}registerDocumentColorProvider(e,t){return this.documentColorManager.register(e,t)}registerDefinitionProvider(e,t){return this.definitionManager.register(e,t)}registerDeclarationProvider(e,t){return this.declarationManager.register(e,t)}registerTypeDefinitionProvider(e,t){return this.typeDefinitionManager.register(e,t)}registerImplementationProvider(e,t){return this.implementationManager.register(e,t)}registerReferencesProvider(e,t){return this.referenceManager.register(e,t)}registerRenameProvider(e,t){return this.renameManager.register(e,t)}registerWorkspaceSymbolProvider(e){return arguments.length>1&&typeof arguments[1].provideWorkspaceSymbols=="function"&&(e=arguments[1]),this.workspaceSymbolsManager.register(e)}registerDocumentFormatProvider(e,t,i=0){return this.formatManager.register(e,t,i)}registerDocumentRangeFormatProvider(e,t,i=0){return this.formatRangeManager.register(e,t,i)}shouldTriggerSignatureHelp(e,t){return this.signatureManager.shouldTrigger(e,t)}async getHover(e,t,i){return await this.hoverManager.provideHover(e,t,i)}async getSignatureHelp(e,t,i,n){return await this.signatureManager.provideSignatureHelp(e,t,i,n)}async getDefinition(e,t,i){return this.definitionManager.hasProvider(e)?await this.definitionManager.provideDefinition(e,t,i):null}async getDeclaration(e,t,i){return this.declarationManager.hasProvider(e)?await this.declarationManager.provideDeclaration(e,t,i):null}async getTypeDefinition(e,t,i){return this.typeDefinitionManager.hasProvider(e)?await this.typeDefinitionManager.provideTypeDefinition(e,t,i):null}async getImplementation(e,t,i){return this.implementationManager.hasProvider(e)?await this.implementationManager.provideReferences(e,t,i):null}async getReferences(e,t,i,n){return this.referenceManager.hasProvider(e)?await this.referenceManager.provideReferences(e,i,t,n):null}async getDocumentSymbol(e,t){return await this.documentSymbolManager.provideDocumentSymbols(e,t)}async getSelectionRanges(e,t,i){return await this.selectionRangeManager.provideSelectionRanges(e,t,i)}async getWorkspaceSymbols(e,t){return e=e||"",await this.workspaceSymbolsManager.provideWorkspaceSymbols(e,t)}async resolveWorkspaceSymbol(e,t){return await this.workspaceSymbolsManager.resolveWorkspaceSymbol(e,t)}async prepareRename(e,t,i){return await this.renameManager.prepareRename(e,t,i)}async provideRenameEdits(e,t,i,n){return await this.renameManager.provideRenameEdits(e,t,i,n)}async provideDocumentFormattingEdits(e,t,i){if(!this.formatManager.hasProvider(e)){if(!this.formatRangeManager.hasProvider(e))return null;let o=e.positionAt(e.getText().length),s=ce.Range.create(ce.Position.create(0,0),o);return await this.provideDocumentRangeFormattingEdits(e,s,t,i)}return await this.formatManager.provideDocumentFormattingEdits(e,t,i)}async provideDocumentRangeFormattingEdits(e,t,i,n){return this.formatRangeManager.hasProvider(e)?await this.formatRangeManager.provideDocumentRangeFormattingEdits(e,t,i,n):null}async getCodeActions(e,t,i,n){return await this.codeActionManager.provideCodeActions(e,t,i,n)}async getDocumentHighLight(e,t,i){return await this.documentHighlightManager.provideDocumentHighlights(e,t,i)}async getDocumentLinks(e,t){return this.documentLinkManager.hasProvider(e)?await this.documentLinkManager.provideDocumentLinks(e,t)||[]:null}async resolveDocumentLink(e){return await this.documentLinkManager.resolveDocumentLink(e,this.token)}async provideDocumentColors(e,t){return await this.documentColorManager.provideDocumentColors(e,t)}async provideFoldingRanges(e,t,i){return this.foldingRangeManager.hasProvider(e)?await this.foldingRangeManager.provideFoldingRanges(e,t,i):null}async provideColorPresentations(e,t,i){return await this.documentColorManager.provideColorPresentations(e,t,i)}async getCodeLens(e,t){return await this.codeLensManager.provideCodeLenses(e,t)}async resolveCodeLens(e,t){return await this.codeLensManager.resolveCodeLens(e,t)}async provideDocumentOnTypeEdits(e,t,i,n){return this.onTypeFormatManager.onCharacterType(e,t,i,n)}hasOnTypeProvider(e,t){return this.onTypeFormatManager.getProvider(t,e)!=null}hasProvider(e,t){switch(e){case"rename":return this.renameManager.hasProvider(t);case"onTypeEdit":return this.onTypeFormatManager.hasProvider(t);case"documentLink":return this.documentLinkManager.hasProvider(t);case"documentColor":return this.documentColorManager.hasProvider(t);case"foldingRange":return this.foldingRangeManager.hasProvider(t);case"format":return this.formatManager.hasProvider(t)||this.formatRangeManager.hasProvider(t);case"codeAction":return this.codeActionManager.hasProvider(t);case"workspaceSymbols":return this.workspaceSymbolsManager.hasProvider();case"formatRange":return this.formatRangeManager.hasProvider(t);case"hover":return this.hoverManager.hasProvider(t);case"signature":return this.signatureManager.hasProvider(t);case"documentSymbol":return this.documentSymbolManager.hasProvider(t);case"documentHighlight":return this.documentHighlightManager.hasProvider(t);case"definition":return this.definitionManager.hasProvider(t);case"declaration":return this.declarationManager.hasProvider(t);case"typeDefinition":return this.typeDefinitionManager.hasProvider(t);case"reference":return this.referenceManager.hasProvider(t);case"implementation":return this.implementationManager.hasProvider(t);case"codeLens":return this.codeLensManager.hasProvider(t);case"selectionRange":return this.selectionRangeManager.hasProvider(t);default:throw new Error(`${e} not supported.`)}}dispose(){}createDiagnosticCollection(e){return mt.create(e)}createCompleteSource(e,t,i,n,o,s,a){let l=[],u=typeof i.resolveCompletionItem=="function";a=a==null?this.completeConfig.priority:a;let c=new Set,f={name:e,priority:a,shortcut:t,enable:!0,sourceType:Xr.Service,documentSelector:n,triggerCharacters:o||[],toggle:()=>{f.enable=!f.enable},doComplete:async(p,d)=>{let{triggerCharacter:h,bufnr:m}=p;c=new Set;let y=o&&o.includes(h),g=ce.CompletionTriggerKind.Invoked;if(p.triggerForInComplete?g=ce.CompletionTriggerKind.TriggerForIncompleteCompletions:y&&(g=ce.CompletionTriggerKind.TriggerCharacter),d.isCancellationRequested)return null;let w=$4(p),x={triggerKind:g,option:p};y&&(x.triggerCharacter=h);let E;try{let I=b.getDocument(m);E=await Promise.resolve(i.provideCompletionItems(I.textDocument,w,d,x))}catch(I){return yv.error(`Complete "${e}" error:`,I),null}if(!E||d.isCancellationRequested||(l=Array.isArray(E)?E:E.items,!l||l.length==0))return null;let P=this.getStartColumn(p.line,l),k=Object.assign({},p),_;P!=null&&(P{let R=this.convertVimCompleteItem(I,t,k,_);return R.index=O,R});return{startcol:P,isIncomplete:!!E.isIncomplete,items:L}},onCompleteResolve:async(p,d)=>{let h=l[p.index];if(!!h){if(u&&!c.has(p.index)){let m=await Promise.resolve(i.resolveCompletionItem(h,d));if(d.isCancellationRequested)return;c.add(p.index),m&&Object.assign(h,m)}if(p.documentation==null){let{documentation:m,detail:y}=h;if(!m&&!y)return;let g=[];if(y&&!p.detailShown&&y!=p.word&&(y=y.replace(/\n\s*/g," "),y.length)){let w=/^[\w-\s.,\t]+$/.test(y),x=w?"txt":await b.nvim.eval("&filetype");g.push({filetype:w?"txt":x,content:y})}m&&(typeof m=="string"?g.push({filetype:"markdown",content:m}):m.value&&g.push({filetype:m.kind=="markdown"?"markdown":"txt",content:m.value})),p.documentation=g}}},onCompleteDone:async(p,d)=>{let h=l[p.index];if(!h)return;let m=d.linenr-1;h.insertText!=null&&!h.textEdit&&(h.textEdit={range:ce.Range.create(m,d.col,m,d.colnr-1),newText:h.insertText}),p.line&&Object.assign(d,{line:p.line});try{let y=await this.applyTextEdit(h,d),{additionalTextEdits:g}=h;if(g&&h.textEdit){let w=h.textEdit.range;g=g.filter(x=>Bm(w,x.range)?(yv.error("Filtered overlap additionalTextEdit:",x),!1):!0)}await this.applyAdditionalEdits(g,d.bufnr,y),y&&await At.selectCurrentPlaceholder(),h.command&&me.has(h.command.command)&&me.execute(h.command)}catch(y){yv.error("Error on CompleteDone:",y)}},shouldCommit:(p,d)=>{let h=l[p.index];return h?(h.commitCharacters||s).includes(d):!1}};return f}get token(){return this.cancelTokenSource=new ce.CancellationTokenSource,this.cancelTokenSource.token}async applyTextEdit(e,t){let{nvim:i}=this,{textEdit:n}=e;if(!n)return!1;let{line:o,bufnr:s,linenr:a}=t,l=b.getDocument(s);if(!l)return!1;let{range:u,newText:c}=n,f=e.insertTextFormat===ce.InsertTextFormat.Snippet,p=o.substr(0,u.start.character),d=o.substr(u.end.character);if(f){let y=l.getline(a-1).length-d.length,g=ce.Range.create(a-1,u.start.character,a-1,y);return await At.insertSnippet(c,!1,g)}let h=`${p}${c}${d}`.split(/\r?\n/);if(h.length==1)await i.call("coc#util#setline",[a,h[0]]),await C.moveTo(ce.Position.create(a-1,(p+c).length));else{await i.createBuffer(s).setLines(h,{start:a-1,end:a,strictIndexing:!1});let y=a-1+h.length-1,g=h[h.length-1].length-d.length;await C.moveTo({line:y,character:g})}return!1}async applyAdditionalEdits(e,t,i){if(!e||e.length==0)return;let n=b.getDocument(t);if(!n)return;await n.patchChange(!0);let o=null,s=await C.getCursorPosition();i||(o=jl(s,e)),await n.applyEdits(e),o&&await C.moveTo(ce.Position.create(s.line+o.line,s.character+o.character))}getStartColumn(e,t){let i=t[0];if(!i.textEdit)return null;let{range:n,newText:o}=i.textEdit,{character:s}=n.start;if(o.length0,c=e.insertTextFormat===ce.InsertTextFormat.Snippet||u,f=e.label.trim(),p={word:j4(e,i,a),abbr:f,menu:`[${t}]`,kind:U4(e.kind,this.completionItemKindMap,this.completeConfig.defaultKindText),sortText:e.sortText||null,sourceScore:e.score||null,filterText:e.filterText||f,isSnippet:c,dup:e.data&&e.data.dup==0?0:1};if(n&&(p.filterText.startsWith(n)||e.textEdit&&e.textEdit.newText.startsWith(n)&&(p.filterText=e.textEdit.newText.split(/\r?\n/)[0]),!e.textEdit&&!p.word.startsWith(n)&&(p.word=`${n}${p.word}`)),e&&e.detail&&l!="preview"){let h=e.detail.replace(/\n\s*/g," ");ue(h)=2&&e.kind<=4){let h=[e.detail||"",p.abbr,p.word];for(let m of h)if(m.includes("(")){p.signature=m;break}}return e.preselect&&(p.preselect=!0),((d=e.data)==null?void 0:d.optional)&&(p.abbr=p.abbr+"?"),p}},B=new W4;var WE=class{constructor(e=-1){this.srcId=e;this.lines=[];this.highlights=[]}addLine(e,t){if(e.includes(` -`)){for(let i of e.split(/\r?\n/))this.addLine(i,t);return}if(t&&this.highlights.push({line:this.lines.length,colStart:e.match(/^\s*/)[0].length,colEnd:ue(e),hlGroup:t}),e.includes("")){let i=$l(e);for(let n of i.highlights){let{span:o,hlGroup:s}=n;o[0]!=o[1]&&this.highlights.push({line:this.lines.length,colStart:o[0],colEnd:o[1],hlGroup:s})}this.lines.push(i.line)}else this.lines.push(e)}addLines(e){this.lines.push(...e)}addText(e,t){let{lines:i}=this,n=i[i.length-1]||"";if(t){let o=ue(n);this.highlights.push({line:i.length?i.length-1:0,colStart:o,colEnd:o+ue(e),hlGroup:t})}i.length?i[i.length-1]=`${n}${e}`:i.push(e)}get length(){return this.lines.length}getline(e){return this.lines[e]||""}render(e,t=0,i=-1){e.setLines(this.lines,{start:t,end:i,strictIndexing:!1},!0);for(let n of this.highlights)e.addHighlight({hlGroup:n.hlGroup,colStart:n.colStart,colEnd:n.colEnd==null?-1:n.colEnd,line:t+n.line,srcId:this.srcId}).logError()}},ls=WE;var UH=S(require("events")),WH=S(require("fs")),HH=S(require("net")),Au=S(W());var Ca=S(require("child_process")),BH=S(require("fs")),lC=S(require("path")),Et=S(W());var Hp=S(require("child_process")),bv=S(require("path")),H4=S(require("fs"));var cye=process.platform==="win32",fye=process.platform==="darwin",pye=process.platform==="linux",dye=bv.dirname(__dirname);function z4(r,e){if(!r.killed)if(cye)try{let t={stdio:["pipe","pipe","ignore"]};return e&&(t.cwd=e),Hp.execFileSync("taskkill",["/T","/F","/PID",r.pid.toString()],t),!0}catch(t){return!1}else if(pye||fye)try{let t=bv.join(dye,"bin/terminateProcess.sh");return H4.default.existsSync(t)?!Hp.spawnSync(t,[r.pid.toString()]).error:(console.error(`"${t}" not found`),!1)}catch(t){return!1}else return r.kill("SIGKILL"),!0}var VE=S(require("path")),D=S(W());var G4=S(W());"use strict";var w$e=U()("language-client-progressPart"),zp=class{constructor(e,t,i){this.client=e;this.token=t;this.disposables=[];this._cancelled=!1;this.statusBarItem=C.createStatusBarItem(99,{progress:!0}),this.disposables.push(e.onProgress(G4.WorkDoneProgress.type,this.token,n=>{switch(n.kind){case"begin":this.begin(n);break;case"report":this.report(n);break;case"end":this.done(n.message),i&&i(this);break}}))}begin(e){typeof this.title!="string"&&(this.title=e.title,this.report(e))}report(e){let t=this.statusBarItem,i=[];this.title&&i.push(this.title),typeof e.percentage=="number"&&i.push(e.percentage.toFixed(0)+"%"),e.message&&i.push(e.message),t.text=i.join(" "),t.show()}cancel(){this._cancelled||(this._cancelled=!0,z(this.disposables))}done(e){if(this._cancelled)return;let t=this.statusBarItem;t.text=`${this.title} ${e||"finished"}`,setTimeout(()=>{t.dispose()},300),this.cancel()}};var HE=class{constructor(e){this.defaultDelay=e;this.timeout=null,this.completionPromise=null,this.doResolve=null,this.task=null}trigger(e,t=this.defaultDelay){return this.task=e,this.cancelTimeout(),this.completionPromise||(this.completionPromise=new Promise((i,n)=>{this.doResolve=i,this.doReject=n}).then(()=>{this.completionPromise=null,this.doResolve=null;let i=this.task;return this.task=null,i()})),this.timeout=setTimeout(()=>{this.timeout=null,this.doResolve(null)},t),this.completionPromise}isTriggered(){return this.timeout!==null}cancel(){this.cancelTimeout(),this.completionPromise&&(this.doReject(new Error("Canceled")),this.completionPromise=null)}cancelTimeout(){this.timeout!==null&&(clearTimeout(this.timeout),this.timeout=null)}dispose(){this.cancelTimeout()}};function V4(r){return{uri:r.uri,languageId:r.languageId,version:r.version,text:r.getText()}}function K4(r){return{textDocument:{uri:r.uri}}}function J4(r){return{textDocument:{uri:r.uri,version:r.version},contentChanges:[{text:r.getText()}]}}function zE(r){return{textDocument:wv(r.document),reason:r.reason}}function wv(r){return{uri:r.uri,version:r.version}}function Y4(r,e){let t={textDocument:wv(r)};return e&&(t.text=r.getText()),t}function Gp(r){return r.toString()}function X4(r,e,t){return{textDocument:{uri:r.uri},position:e,context:Sa(t,["option"])}}function En(r,e){return{textDocument:{uri:r.uri},position:e}}function Z4(r,e,t){return{textDocument:GE(r),position:e,context:t}}function GE(r){return{uri:r.uri}}function Q4(r,e,t){return{textDocument:{uri:r.uri},position:e,context:{includeDeclaration:t.includeDeclaration}}}function eH(r){return{textDocument:{uri:r.uri}}}function tH(r){return{textDocument:{uri:r.uri}}}function Be(){return he()}var us=U()("language-client-client"),rH=class{error(e){us.error(e)}warn(e){us.warn(e)}info(e){us.info(e)}log(e){us.log(e)}},iH=class{error(e){}warn(e){}info(e){}log(e){}};function hye(r,e,t,i){let n=new rH,o=D.createProtocolConnection(r,e,n);return o.onError(a=>{t(a[0],a[1],a[2])}),o.onClose(i),{listen:()=>o.listen(),sendRequest:(a,...l)=>o.sendRequest(wt(a)?a:a.method,...l),onRequest:(a,l)=>o.onRequest(wt(a)?a:a.method,l),sendNotification:(a,l)=>o.sendNotification(wt(a)?a:a.method,l),onNotification:(a,l)=>o.onNotification(wt(a)?a:a.method,l),onProgress:o.onProgress,sendProgress:o.sendProgress,trace:(a,l,u)=>{let c={sendNotification:!1,traceFormat:D.TraceFormat.Text};u===void 0?o.trace(a,l,c):(kl(u),o.trace(a,l,u))},initialize:a=>o.sendRequest(D.InitializeRequest.type,a),shutdown:()=>o.sendRequest(D.ShutdownRequest.type,void 0),exit:()=>o.sendNotification(D.ExitNotification.type),onLogMessage:a=>o.onNotification(D.LogMessageNotification.type,a),onShowMessage:a=>o.onNotification(D.ShowMessageNotification.type,a),onTelemetry:a=>o.onNotification(D.TelemetryEventNotification.type,a),didChangeConfiguration:a=>o.sendNotification(D.DidChangeConfigurationNotification.type,a),didChangeWatchedFiles:a=>o.sendNotification(D.DidChangeWatchedFilesNotification.type,a),didOpenTextDocument:a=>o.sendNotification(D.DidOpenTextDocumentNotification.type,a),didChangeTextDocument:a=>o.sendNotification(D.DidChangeTextDocumentNotification.type,a),didCloseTextDocument:a=>o.sendNotification(D.DidCloseTextDocumentNotification.type,a),didSaveTextDocument:a=>o.sendNotification(D.DidSaveTextDocumentNotification.type,a),onDiagnostics:a=>o.onNotification(D.PublishDiagnosticsNotification.type,a),dispose:()=>o.dispose()}}var Fu;(function(r){r[r.Continue=1]="Continue",r[r.Shutdown=2]="Shutdown"})(Fu||(Fu={}));var no;(function(r){r[r.DoNotRestart=1]="DoNotRestart",r[r.Restart=2]="Restart"})(no||(no={}));var KE=class{constructor(e){this.name=e;this.restarts=[]}error(e,t,i){return i&&i<=3?1:2}closed(){return this.restarts.push(Date.now()),this.restarts.length<5?2:this.restarts[this.restarts.length-1]-this.restarts[0]<=3*60*1e3?(C.showMessage(`The "${this.name}" server crashed 5 times in the last 3 minutes. The server will not be restarted.`,"error"),1):(this.restarts.shift(),2)}},ii;(function(r){r[r.Info=1]="Info",r[r.Warn=2]="Warn",r[r.Error=3]="Error",r[r.Never=4]="Never"})(ii||(ii={}));var ni;(function(r){r[r.Stopped=1]="Stopped",r[r.Running=2]="Running",r[r.Starting=3]="Starting"})(ni||(ni={}));var be;(function(r){r[r.Initial=0]="Initial",r[r.Starting=1]="Starting",r[r.StartFailed=2]="StartFailed",r[r.Running=3]="Running",r[r.Stopping=4]="Stopping",r[r.Stopped=5]="Stopped"})(be||(be={}));var nH=[D.SymbolKind.File,D.SymbolKind.Module,D.SymbolKind.Namespace,D.SymbolKind.Package,D.SymbolKind.Class,D.SymbolKind.Method,D.SymbolKind.Property,D.SymbolKind.Field,D.SymbolKind.Constructor,D.SymbolKind.Enum,D.SymbolKind.Interface,D.SymbolKind.Function,D.SymbolKind.Variable,D.SymbolKind.Constant,D.SymbolKind.String,D.SymbolKind.Number,D.SymbolKind.Boolean,D.SymbolKind.Array,D.SymbolKind.Object,D.SymbolKind.Key,D.SymbolKind.Null,D.SymbolKind.EnumMember,D.SymbolKind.Struct,D.SymbolKind.Event,D.SymbolKind.Operator,D.SymbolKind.TypeParameter],mye=[D.CompletionItemKind.Text,D.CompletionItemKind.Method,D.CompletionItemKind.Function,D.CompletionItemKind.Constructor,D.CompletionItemKind.Field,D.CompletionItemKind.Variable,D.CompletionItemKind.Class,D.CompletionItemKind.Interface,D.CompletionItemKind.Module,D.CompletionItemKind.Property,D.CompletionItemKind.Unit,D.CompletionItemKind.Value,D.CompletionItemKind.Enum,D.CompletionItemKind.Keyword,D.CompletionItemKind.Snippet,D.CompletionItemKind.Color,D.CompletionItemKind.File,D.CompletionItemKind.Reference,D.CompletionItemKind.Folder,D.CompletionItemKind.EnumMember,D.CompletionItemKind.Constant,D.CompletionItemKind.Struct,D.CompletionItemKind.Event,D.CompletionItemKind.Operator,D.CompletionItemKind.TypeParameter],oH=[D.SymbolTag.Deprecated];function re(r,e){return r[e]==null&&(r[e]={}),r[e]}var JE;(function(e){function r(t){let i=t;return i&&No(i.register)&&No(i.unregister)&&No(i.dispose)&&i.messages!==void 0}e.is=r})(JE||(JE={}));var Cn=class{constructor(e,t,i,n,o,s){this._client=e;this._event=t;this._type=i;this._middleware=n;this._createParams=o;this._selectorFilter=s;this._selectors=new Map}static textDocumentFilter(e,t){for(let i of e)if(b.match(i,t)>0)return!0;return!1}register(e,t){!t.registerOptions.documentSelector||(this._listener||(this._listener=this._event(this.callback,this)),this._selectors.set(t.id,t.registerOptions.documentSelector))}callback(e){(!this._selectorFilter||this._selectorFilter(this._selectors.values(),e))&&(this._middleware?this._middleware(e,t=>this._client.sendNotification(this._type,this._createParams(t))):this._client.sendNotification(this._type,this._createParams(e)),this.notificationSent(e))}notificationSent(e){}unregister(e){this._selectors.delete(e),this._selectors.size===0&&this._listener&&(this._listener.dispose(),this._listener=void 0)}dispose(){this._selectors.clear(),this._listener&&(this._listener.dispose(),this._listener=void 0)}getProvider(e){for(let t of this._selectors.values())if(b.match(t,e))return{send:i=>{this.callback(i)}};throw new Error("No provider available for the given text document")}},sH=class extends Cn{constructor(e,t){super(e,b.onDidOpenTextDocument,D.DidOpenTextDocumentNotification.type,e.clientOptions.middleware.didOpen,i=>({textDocument:V4(i)}),Cn.textDocumentFilter);this._syncedDocuments=t}get messages(){return D.DidOpenTextDocumentNotification.type}fillClientCapabilities(e){re(re(e,"textDocument"),"synchronization").dynamicRegistration=!0}initialize(e,t){let i=e.resolvedTextDocumentSync;t&&i&&i.openClose&&this.register(this.messages,{id:Be(),registerOptions:{documentSelector:t}})}register(e,t){if(super.register(e,t),!t.registerOptions.documentSelector)return;let i=t.registerOptions.documentSelector;b.textDocuments.forEach(n=>{let o=n.uri.toString();if(!this._syncedDocuments.has(o)&&b.match(i,n)>0){let s=this._client.clientOptions.middleware,a=l=>{this._client.sendNotification(this._type,this._createParams(l))};s.didOpen?s.didOpen(n,a):a(n),this._syncedDocuments.set(o,n)}})}notificationSent(e){super.notificationSent(e),this._syncedDocuments.set(e.uri.toString(),e)}},aH=class extends Cn{constructor(e,t){super(e,b.onDidCloseTextDocument,D.DidCloseTextDocumentNotification.type,e.clientOptions.middleware.didClose,i=>K4(i),Cn.textDocumentFilter);this._syncedDocuments=t}get messages(){return D.DidCloseTextDocumentNotification.type}fillClientCapabilities(e){re(re(e,"textDocument"),"synchronization").dynamicRegistration=!0}initialize(e,t){let i=e.resolvedTextDocumentSync;t&&i&&i.openClose&&this.register(this.messages,{id:Be(),registerOptions:{documentSelector:t}})}notificationSent(e){super.notificationSent(e),this._syncedDocuments.delete(e.uri.toString())}unregister(e){let t=this._selectors.get(e);super.unregister(e);let i=this._selectors.values();this._syncedDocuments.forEach(n=>{if(b.match(t,n)>0&&!this._selectorFilter(i,n)){let o=this._client.clientOptions.middleware,s=a=>{this._client.sendNotification(this._type,this._createParams(a))};this._syncedDocuments.delete(n.uri.toString()),o.didClose?o.didClose(n,s):s(n)}})}},lH=class{constructor(e){this._client=e;this._changeData=new Map}get messages(){return D.DidChangeTextDocumentNotification.type}fillClientCapabilities(e){re(re(e,"textDocument"),"synchronization").dynamicRegistration=!0}initialize(e,t){let i=e.resolvedTextDocumentSync;t&&i&&i.change!==void 0&&i.change!==D.TextDocumentSyncKind.None&&this.register(this.messages,{id:Be(),registerOptions:Object.assign({},{documentSelector:t},{syncKind:i.change})})}register(e,t){!t.registerOptions.documentSelector||(this._listener||(this._listener=b.onDidChangeTextDocument(this.callback,this)),this._changeData.set(t.id,{documentSelector:t.registerOptions.documentSelector,syncKind:t.registerOptions.syncKind}))}callback(e){if(e.contentChanges.length===0)return;let t=b.getDocument(e.textDocument.uri);if(!t)return;let{textDocument:i}=t;for(let n of this._changeData.values())if(b.match(n.documentSelector,i)>0){let o=this._client.clientOptions.middleware;if(n.syncKind===D.TextDocumentSyncKind.Incremental)o.didChange?o.didChange(e,()=>this._client.sendNotification(D.DidChangeTextDocumentNotification.type,Sa(e,["bufnr","original"]))):this._client.sendNotification(D.DidChangeTextDocumentNotification.type,Sa(e,["bufnr","original"]));else if(n.syncKind===D.TextDocumentSyncKind.Full){let s=a=>{let{textDocument:l}=b.getDocument(a.textDocument.uri);this._client.sendNotification(D.DidChangeTextDocumentNotification.type,J4(l))};o.didChange?o.didChange(e,s):s(e)}}}unregister(e){this._changeData.delete(e),this._changeData.size===0&&this._listener&&(this._listener.dispose(),this._listener=void 0)}dispose(){this._changeData.clear(),this._listener&&(this._listener.dispose(),this._listener=void 0)}getProvider(e){for(let t of this._changeData.values())if(b.match(t.documentSelector,e))return{send:i=>{this.callback(i)}};throw new Error("No provider available for the given text document")}},uH=class extends Cn{constructor(e){super(e,b.onWillSaveTextDocument,D.WillSaveTextDocumentNotification.type,e.clientOptions.middleware.willSave,t=>zE(t),(t,i)=>Cn.textDocumentFilter(t,i.document))}get messages(){return D.WillSaveTextDocumentNotification.type}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"synchronization");t.willSave=!0}initialize(e,t){let i=e.resolvedTextDocumentSync;t&&i&&i.willSave&&this.register(this.messages,{id:Be(),registerOptions:{documentSelector:t}})}},cH=class{constructor(e){this._client=e;this._selectors=new Map}get messages(){return D.WillSaveTextDocumentWaitUntilRequest.type}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"synchronization");t.willSaveWaitUntil=!0}initialize(e,t){let i=e.resolvedTextDocumentSync;t&&i&&i.willSaveWaitUntil&&this.register(this.messages,{id:Be(),registerOptions:{documentSelector:t}})}register(e,t){!t.registerOptions.documentSelector||(this._listener||(this._listener=b.onWillSaveTextDocument(this.callback,this)),this._selectors.set(t.id,t.registerOptions.documentSelector))}callback(e){if(Cn.textDocumentFilter(this._selectors.values(),e.document)){let t=this._client.clientOptions.middleware,i=n=>this._client.sendRequest(D.WillSaveTextDocumentWaitUntilRequest.type,zE(n)).then(o=>o||[],o=>(C.showMessage(`Error on willSaveWaitUntil: ${o}`,"error"),us.error(o),[]));e.waitUntil(t.willSaveWaitUntil?t.willSaveWaitUntil(e,i):i(e))}}unregister(e){this._selectors.delete(e),this._selectors.size===0&&this._listener&&(this._listener.dispose(),this._listener=void 0)}dispose(){this._selectors.clear(),this._listener&&(this._listener.dispose(),this._listener=void 0)}},fH=class extends Cn{constructor(e){super(e,b.onDidSaveTextDocument,D.DidSaveTextDocumentNotification.type,e.clientOptions.middleware.didSave,t=>Y4(t,this._includeText),Cn.textDocumentFilter)}get messages(){return D.DidSaveTextDocumentNotification.type}fillClientCapabilities(e){re(re(e,"textDocument"),"synchronization").didSave=!0}initialize(e,t){let i=e.resolvedTextDocumentSync;t&&i&&i.save&&this.register(this.messages,{id:Be(),registerOptions:Object.assign({},{documentSelector:t},{includeText:!!i.save.includeText})})}register(e,t){this._includeText=!!t.registerOptions.includeText,super.register(e,t)}},pH=class{constructor(e,t){this._notifyFileEvent=t;this._watchers=new Map}get messages(){return D.DidChangeWatchedFilesNotification.type}fillClientCapabilities(e){re(re(e,"workspace"),"didChangeWatchedFiles").dynamicRegistration=!0}initialize(e,t){}register(e,t){if(!Array.isArray(t.registerOptions.watchers))return;let i=[];for(let n of t.registerOptions.watchers){if(!wt(n.globPattern))continue;let o=!0,s=!0,a=!0;n.kind!=null&&(o=(n.kind&D.WatchKind.Create)!=0,s=(n.kind&D.WatchKind.Change)!=0,a=(n.kind&D.WatchKind.Delete)!=0);let l=b.createFileSystemWatcher(n.globPattern,!o,!s,!a);this.hookListeners(l,o,s,a,i),i.push(l)}this._watchers.set(t.id,i)}registerRaw(e,t){let i=[];for(let n of t)i.push(n),this.hookListeners(n,!0,!0,!0,i);this._watchers.set(e,i)}hookListeners(e,t,i,n,o){t&&e.onDidCreate(s=>this._notifyFileEvent({uri:Gp(s),type:D.FileChangeType.Created}),null,o),i&&e.onDidChange(s=>this._notifyFileEvent({uri:Gp(s),type:D.FileChangeType.Changed}),null,o),n&&e.onDidDelete(s=>this._notifyFileEvent({uri:Gp(s),type:D.FileChangeType.Deleted}),null,o)}unregister(e){let t=this._watchers.get(e);if(t)for(let i of t)i.dispose()}dispose(){this._watchers.forEach(e=>{for(let t of e)t.dispose()}),this._watchers.clear()}},Ve=class{constructor(e,t){this._client=e;this._message=t;this._registrations=new Map}get messages(){return this._message}register(e,t){if(e.method!==this.messages.method)throw new Error(`Register called on wrong feature. Requested ${e.method} but reached feature ${this.messages.method}`);if(!t.registerOptions.documentSelector)return;let i=this.registerLanguageProvider(t.registerOptions);this._registrations.set(t.id,{disposable:i[0],data:t,provider:i[1]})}unregister(e){let t=this._registrations.get(e);t&&t.disposable.dispose()}dispose(){this._registrations.forEach(e=>{e.disposable.dispose()}),this._registrations.clear()}getRegistration(e,t){if(t){if(D.TextDocumentRegistrationOptions.is(t)){let i=D.StaticRegistrationOptions.hasId(t)?t.id:Be(),n=t.documentSelector||e;if(n)return[i,Object.assign({},t,{documentSelector:n})]}else if(kl(t)&&t===!0||D.WorkDoneProgressOptions.is(t)){if(!e)return[void 0,void 0];let i=kl(t)&&t===!0?{documentSelector:e}:Object.assign({},t,{documentSelector:e});return[Be(),i]}}else return[void 0,void 0];return[void 0,void 0]}getRegistrationOptions(e,t){if(!(!e||!t))return kl(t)&&t===!0?{documentSelector:e}:Object.assign({},t,{documentSelector:e})}getProvider(e){for(let t of this._registrations.values()){let i=t.data.registerOptions.documentSelector;if(i!==null&&b.match(i,e)>0)return t.provider}throw new Error(`The feature has no registration for the provided text document ${e.uri.toString()}`)}},dH=class{constructor(e,t){this._client=e;this._message=t;this._registrations=new Map}get messages(){return this._message}register(e,t){if(e.method!==this.messages.method)throw new Error(`Register called on wrong feature. Requested ${e.method} but reached feature ${this.messages.method}`);let i=this.registerLanguageProvider(t.registerOptions);this._registrations.set(t.id,i)}unregister(e){let t=this._registrations.get(e);t&&t.dispose()}dispose(){this._registrations.forEach(e=>{e.dispose()}),this._registrations.clear()}},hH=class extends Ve{constructor(e){super(e,D.CompletionRequest.type)}fillClientCapabilities(e){let t=this._client.clientOptions.disableSnippetCompletion!==!0,i=re(re(e,"textDocument"),"completion");i.dynamicRegistration=!0,i.contextSupport=!0,i.completionItem={snippetSupport:t,commitCharactersSupport:!0,documentationFormat:this._client.supporedMarkupKind,deprecatedSupport:!0,preselectSupport:!0,tagSupport:{valueSet:[D.CompletionItemTag.Deprecated]}},i.completionItemKind={valueSet:mye}}initialize(e,t){this.index=0;let i=this.getRegistrationOptions(t,e.completionProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t=e.triggerCharacters||[],i=e.allCommitCharacters||[],n=e.priority,o={provideCompletionItems:(l,u,c,f)=>{let p=this._client,d=this._client.clientOptions.middleware,h=(m,y,g,w)=>p.sendRequest(D.CompletionRequest.type,X4(m,y,g),w).then(x=>x,x=>(p.logFailedRequest(D.CompletionRequest.type,x),Promise.resolve([])));return d.provideCompletionItem?d.provideCompletionItem(l,u,f,c,h):h(l,u,f,c)},resolveCompletionItem:e.resolveProvider?(l,u)=>{let c=this._client,f=this._client.clientOptions.middleware,p=(d,h)=>c.sendRequest(D.CompletionResolveRequest.type,d,h).then(m=>m,m=>(c.logFailedRequest(D.CompletionResolveRequest.type,m),Promise.resolve(d)));return f.resolveCompletionItem?f.resolveCompletionItem(l,u,p):p(l,u)}:void 0},s=this._client.id+(this.index?"-"+this.index:"");Ge.removeSource(s);let a=B.registerCompletionItemProvider(s,"LS",e.documentSelector||this._client.clientOptions.documentSelector,o,t,n,i);return this.index=this.index+1,[a,o]}},mH=class extends Ve{constructor(e){super(e,D.HoverRequest.type)}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"hover");t.dynamicRegistration=!0,t.contentFormat=this._client.supporedMarkupKind}initialize(e,t){let i=this.getRegistrationOptions(t,e.hoverProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideHover:(i,n,o)=>{let s=this._client,a=(u,c,f)=>s.sendRequest(D.HoverRequest.type,En(u,c),f).then(p=>p,p=>(s.logFailedRequest(D.HoverRequest.type,p),Promise.resolve(null))),l=s.clientOptions.middleware;return l.provideHover?l.provideHover(i,n,o,a):a(i,n,o)}};return[B.registerHoverProvider(e.documentSelector,t),t]}},gH=class extends Ve{constructor(e){super(e,D.SignatureHelpRequest.type)}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"signatureHelp");t.dynamicRegistration=!0,t.contextSupport=!0,t.signatureInformation={documentationFormat:this._client.supporedMarkupKind,activeParameterSupport:!0,parameterInformation:{labelOffsetSupport:!0}}}initialize(e,t){let i=this.getRegistrationOptions(t,e.signatureHelpProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideSignatureHelp:(o,s,a,l)=>{let u=this._client,c=(p,d,h,m)=>u.sendRequest(D.SignatureHelpRequest.type,Z4(p,d,h),m).then(y=>y,y=>(u.logFailedRequest(D.SignatureHelpRequest.type,y),Promise.resolve(null))),f=u.clientOptions.middleware;return f.provideSignatureHelp?f.provideSignatureHelp(o,s,l,a,c):c(o,s,l,a)}},i=e.triggerCharacters||[];return[B.registerSignatureHelpProvider(e.documentSelector,t,i),t]}},vH=class extends Ve{constructor(e){super(e,D.DefinitionRequest.type)}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"definition");t.dynamicRegistration=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.definitionProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideDefinition:(i,n,o)=>{let s=this._client,a=(u,c,f)=>s.sendRequest(D.DefinitionRequest.type,En(u,c),f).then(p=>p,p=>(s.logFailedRequest(D.DefinitionRequest.type,p),Promise.resolve(null))),l=s.clientOptions.middleware;return l.provideDefinition?l.provideDefinition(i,n,o,a):a(i,n,o)}};return[B.registerDefinitionProvider(e.documentSelector,t),t]}},yH=class extends Ve{constructor(e){super(e,D.ReferencesRequest.type)}fillClientCapabilities(e){re(re(e,"textDocument"),"references").dynamicRegistration=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.referencesProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideReferences:(i,n,o,s)=>{let a=this._client,l=(c,f,p,d)=>a.sendRequest(D.ReferencesRequest.type,Q4(c,f,p),d).then(h=>h,h=>(a.logFailedRequest(D.ReferencesRequest.type,h),Promise.resolve([]))),u=a.clientOptions.middleware;return u.provideReferences?u.provideReferences(i,n,o,s,l):l(i,n,o,s)}};return[B.registerReferencesProvider(e.documentSelector,t),t]}},bH=class extends Ve{constructor(e){super(e,D.DocumentHighlightRequest.type)}fillClientCapabilities(e){re(re(e,"textDocument"),"documentHighlight").dynamicRegistration=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.documentHighlightProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideDocumentHighlights:(i,n,o)=>{let s=this._client,a=(u,c,f)=>s.sendRequest(D.DocumentHighlightRequest.type,En(u,c),f).then(p=>p,p=>(s.logFailedRequest(D.DocumentHighlightRequest.type,p),Promise.resolve([]))),l=s.clientOptions.middleware;return l.provideDocumentHighlights?l.provideDocumentHighlights(i,n,o,a):a(i,n,o)}};return[B.registerDocumentHighlightProvider(e.documentSelector,t),t]}},wH=class extends Ve{constructor(e){super(e,D.DocumentSymbolRequest.type)}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"documentSymbol");t.dynamicRegistration=!0,t.symbolKind={valueSet:nH},t.hierarchicalDocumentSymbolSupport=!0,t.tagSupport={valueSet:oH}}initialize(e,t){let i=this.getRegistrationOptions(t,e.documentSymbolProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideDocumentSymbols:(i,n)=>{let o=this._client,s=(l,u)=>o.sendRequest(D.DocumentSymbolRequest.type,eH(l),u).then(c=>{if(c!==null){if(c.length===0)return[];{let f=c[0];return D.DocumentSymbol.is(f),c}}},c=>(o.logFailedRequest(D.DocumentSymbolRequest.type,c),Promise.resolve([]))),a=o.clientOptions.middleware;return a.provideDocumentSymbols?a.provideDocumentSymbols(i,n,s):s(i,n)}};return[B.registerDocumentSymbolProvider(e.documentSelector,t),t]}},xH=class extends dH{constructor(e){super(e,D.WorkspaceSymbolRequest.type)}fillClientCapabilities(e){let t=re(re(e,"workspace"),"symbol");t.dynamicRegistration=!0,t.symbolKind={valueSet:nH},t.tagSupport={valueSet:oH}}initialize(e){!e.workspaceSymbolProvider||this.register(this.messages,{id:Be(),registerOptions:e.workspaceSymbolProvider===!0?{workDoneProgress:!1}:e.workspaceSymbolProvider})}registerLanguageProvider(e){let t={provideWorkspaceSymbols:(i,n)=>{let o=this._client,s=(l,u)=>o.sendRequest(D.WorkspaceSymbolRequest.type,{query:l},u).then(c=>c,c=>(o.logFailedRequest(D.WorkspaceSymbolRequest.type,c),Promise.resolve([]))),a=o.clientOptions.middleware;return a.provideWorkspaceSymbols?a.provideWorkspaceSymbols(i,n,s):s(i,n)}};return B.registerWorkspaceSymbolProvider(t)}},DH=class extends Ve{constructor(e){super(e,D.CodeActionRequest.type)}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"codeAction");t.dynamicRegistration=!0,t.isPreferredSupport=!0,t.codeActionLiteralSupport={codeActionKind:{valueSet:[D.CodeActionKind.Empty,D.CodeActionKind.QuickFix,D.CodeActionKind.Refactor,D.CodeActionKind.RefactorExtract,D.CodeActionKind.RefactorInline,D.CodeActionKind.RefactorRewrite,D.CodeActionKind.Source,D.CodeActionKind.SourceOrganizeImports]}}}initialize(e,t){let i=this.getRegistrationOptions(t,e.codeActionProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideCodeActions:(i,n,o,s)=>{let a=this._client,l=(c,f,p,d)=>{let h={textDocument:{uri:c.uri},range:f,context:p};return a.sendRequest(D.CodeActionRequest.type,h,d).then(m=>{if(m!==null)return m},m=>(a.logFailedRequest(D.CodeActionRequest.type,m),Promise.resolve([])))},u=a.clientOptions.middleware;return u.provideCodeActions?u.provideCodeActions(i,n,o,s,l):l(i,n,o,s)}};return[B.registerCodeActionProvider(e.documentSelector,t,this._client.id,e.codeActionKinds),t]}},SH=class extends Ve{constructor(e){super(e,D.CodeLensRequest.type)}fillClientCapabilities(e){re(re(e,"textDocument"),"codeLens").dynamicRegistration=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.codeLensProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideCodeLenses:(i,n)=>{let o=this._client,s=(l,u)=>o.sendRequest(D.CodeLensRequest.type,tH(l),u).then(c=>c,c=>(o.logFailedRequest(D.CodeLensRequest.type,c),Promise.resolve([]))),a=o.clientOptions.middleware;return a.provideCodeLenses?a.provideCodeLenses(i,n,s):s(i,n)},resolveCodeLens:e.resolveProvider?(i,n)=>{let o=this._client,s=(l,u)=>o.sendRequest(D.CodeLensResolveRequest.type,l,u).then(c=>c,c=>(o.logFailedRequest(D.CodeLensResolveRequest.type,c),l)),a=o.clientOptions.middleware;return a.resolveCodeLens?a.resolveCodeLens(i,n,s):s(i,n)}:void 0};return[B.registerCodeLensProvider(e.documentSelector,t),t]}},EH=class extends Ve{constructor(e){super(e,D.DocumentFormattingRequest.type)}fillClientCapabilities(e){re(re(e,"textDocument"),"formatting").dynamicRegistration=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.documentFormattingProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideDocumentFormattingEdits:(i,n,o)=>{let s=this._client,a=(u,c,f)=>{let p={textDocument:{uri:u.uri},options:c};return s.sendRequest(D.DocumentFormattingRequest.type,p,f).then(d=>d,d=>(s.logFailedRequest(D.DocumentFormattingRequest.type,d),Promise.resolve([])))},l=s.clientOptions.middleware;return l.provideDocumentFormattingEdits?l.provideDocumentFormattingEdits(i,n,o,a):a(i,n,o)}};return[B.registerDocumentFormatProvider(e.documentSelector,t,this._client.clientOptions.formatterPriority),t]}},CH=class extends Ve{constructor(e){super(e,D.DocumentRangeFormattingRequest.type)}fillClientCapabilities(e){re(re(e,"textDocument"),"rangeFormatting").dynamicRegistration=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.documentRangeFormattingProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideDocumentRangeFormattingEdits:(i,n,o,s)=>{let a=this._client,l=(c,f,p,d)=>{let h={textDocument:{uri:c.uri},range:f,options:p};return a.sendRequest(D.DocumentRangeFormattingRequest.type,h,d).then(m=>m,m=>(a.logFailedRequest(D.DocumentRangeFormattingRequest.type,m),Promise.resolve([])))},u=a.clientOptions.middleware;return u.provideDocumentRangeFormattingEdits?u.provideDocumentRangeFormattingEdits(i,n,o,s,l):l(i,n,o,s)}};return[B.registerDocumentRangeFormatProvider(e.documentSelector,t),t]}},_H=class extends Ve{constructor(e){super(e,D.DocumentOnTypeFormattingRequest.type)}fillClientCapabilities(e){re(re(e,"textDocument"),"onTypeFormatting").dynamicRegistration=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.documentOnTypeFormattingProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideOnTypeFormattingEdits:(o,s,a,l,u)=>{let c=this._client,f=(d,h,m,y,g)=>{let w={textDocument:wv(d),position:h,ch:m,options:y};return c.sendRequest(D.DocumentOnTypeFormattingRequest.type,w,g).then(x=>x,x=>(c.logFailedRequest(D.DocumentOnTypeFormattingRequest.type,x),Promise.resolve([])))},p=c.clientOptions.middleware;return p.provideOnTypeFormattingEdits?p.provideOnTypeFormattingEdits(o,s,a,l,u,f):f(o,s,a,l,u)}},i=e.moreTriggerCharacter||[],n=[e.firstTriggerCharacter,...i];return[B.registerOnTypeFormattingEditProvider(e.documentSelector,t,n),t]}},PH=class extends Ve{constructor(e){super(e,D.RenameRequest.type)}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"rename");t.dynamicRegistration=!0,t.prepareSupport=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.renameProvider);!i||(kl(e.renameProvider)&&(i.prepareProvider=!1),this.register(this.messages,{id:Be(),registerOptions:i}))}registerLanguageProvider(e){let t={provideRenameEdits:(i,n,o,s)=>{let a=this._client,l=(c,f,p,d)=>{let h={textDocument:{uri:c.uri},position:f,newName:p};return a.sendRequest(D.RenameRequest.type,h,d).then(m=>m,m=>(a.logFailedRequest(D.RenameRequest.type,m),Promise.reject(new Error(m.message))))},u=a.clientOptions.middleware;return u.provideRenameEdits?u.provideRenameEdits(i,n,o,s,l):l(i,n,o,s)},prepareRename:e.prepareProvider?(i,n,o)=>{let s=this._client,a=(u,c,f)=>{let p={textDocument:GE(u),position:c};return s.sendRequest(D.PrepareRenameRequest.type,p,f).then(d=>D.Range.is(d)?d:d&&D.Range.is(d.range)?{range:d.range,placeholder:d.placeholder}:Promise.reject(new Error("The element can't be renamed.")),d=>(s.logFailedRequest(D.PrepareRenameRequest.type,d),Promise.reject(new Error(d.message))))},l=s.clientOptions.middleware;return l.prepareRename?l.prepareRename(i,n,o,a):a(i,n,o)}:void 0};return[B.registerRenameProvider(e.documentSelector,t),t]}},TH=class extends Ve{constructor(e){super(e,D.DocumentLinkRequest.type)}fillClientCapabilities(e){let t=re(re(e,"textDocument"),"documentLink");t.dynamicRegistration=!0,t.tooltipSupport=!0}initialize(e,t){let i=this.getRegistrationOptions(t,e.documentLinkProvider);!i||this.register(this.messages,{id:Be(),registerOptions:i})}registerLanguageProvider(e){let t={provideDocumentLinks:(i,n)=>{let o=this._client,s=(l,u)=>o.sendRequest(D.DocumentLinkRequest.type,{textDocument:{uri:l.uri}},u).then(c=>c,c=>(o.logFailedRequest(D.DocumentLinkRequest.type,c),Promise.resolve([]))),a=o.clientOptions.middleware;return a.provideDocumentLinks?a.provideDocumentLinks(i,n,s):s(i,n)},resolveDocumentLink:e.resolveProvider?(i,n)=>{let o=this._client,s=(l,u)=>o.sendRequest(D.DocumentLinkResolveRequest.type,l,u).then(c=>c,c=>(o.logFailedRequest(D.DocumentLinkResolveRequest.type,c),Promise.resolve(l))),a=o.clientOptions.middleware;return a.resolveDocumentLink?a.resolveDocumentLink(i,n,s):s(i,n)}:void 0};return[B.registerDocumentLinkProvider(e.documentSelector,t),t]}},RH=class{constructor(e){this._client=e;this._listeners=new Map}get messages(){return D.DidChangeConfigurationNotification.type}fillClientCapabilities(e){re(re(e,"workspace"),"didChangeConfiguration").dynamicRegistration=!0}initialize(){var t;let e=(t=this._client.clientOptions.synchronize)==null?void 0:t.configurationSection;e!==void 0&&this.register(this.messages,{id:Be(),registerOptions:{section:e}})}register(e,t){let{section:i}=t.registerOptions,n=b.onDidChangeConfiguration(o=>{typeof i=="string"&&!o.affectsConfiguration(i)||Array.isArray(i)&&!i.some(s=>o.affectsConfiguration(s))||i!=null&&this.onDidChangeConfiguration(t.registerOptions.section)});if(this._listeners.set(t.id,n),wt(i)&&i.endsWith(".settings")){let o=this.getConfiguredSettings(i);if(!o||mm(o))return}i!=null&&this.onDidChangeConfiguration(t.registerOptions.section)}unregister(e){let t=this._listeners.get(e);t&&(this._listeners.delete(e),t.dispose())}dispose(){for(let e of this._listeners.values())e.dispose();this._listeners.clear()}onDidChangeConfiguration(e){let t=typeof e=="string"&&e.startsWith("languageserver."),i;wt(e)?i=[e]:i=e;let n=s=>{if(s===void 0){this._client.sendNotification(D.DidChangeConfigurationNotification.type,{settings:null});return}this._client.sendNotification(D.DidChangeConfigurationNotification.type,{settings:t?this.getConfiguredSettings(s[0]):this.extractSettingsInformation(s)})},o=this.getMiddleware();o?o(i,n):n(i)}getConfiguredSettings(e){let t=".settings".length;return b.getConfiguration(e.slice(0,-t)).get("settings",{})}extractSettingsInformation(e){function t(n,o){let s=n;for(let a=0;a=0?a=b.getConfiguration(o.substr(0,s)).get(o.substr(s+1)):a=b.getConfiguration(o),a){let l=e[n].split(".");t(i,l)[l[l.length-1]]=a}}return i}getMiddleware(){let e=this._client.clientOptions.middleware;if(e.workspace&&e.workspace.didChangeConfiguration)return e.workspace.didChangeConfiguration}},kH=class{constructor(e){this._client=e;this._commands=new Map}get messages(){return D.ExecuteCommandRequest.type}fillClientCapabilities(e){re(re(e,"workspace"),"executeCommand").dynamicRegistration=!0}initialize(e){!e.executeCommandProvider||this.register(this.messages,{id:Be(),registerOptions:Object.assign({},e.executeCommandProvider)})}register(e,t){let i=this._client,n=i.clientOptions.middleware,o=(s,a)=>{let l={command:s,arguments:a};return i.sendRequest(D.ExecuteCommandRequest.type,l).then(void 0,u=>{throw i.logFailedRequest(D.ExecuteCommandRequest.type,u),u})};if(t.registerOptions.commands){let s=[];for(let a of t.registerOptions.commands)s.push(me.registerCommand(a,(...l)=>n.executeCommand?n.executeCommand(a,l,o):o(a,l),null,!0));this._commands.set(t.id,s)}}unregister(e){let t=this._commands.get(e);t&&t.forEach(i=>i.dispose())}dispose(){this._commands.forEach(e=>{e.forEach(t=>t.dispose())}),this._commands.clear()}},Vp;(function(e){function r(t){return t&&D.MessageReader.is(t.reader)&&D.MessageWriter.is(t.writer)}e.is=r})(Vp||(Vp={}));var YE=class{constructor(e,t){this._resolve=e;this._reject=t;this._used=!1}get isUsed(){return this._used}resolve(){this._used=!0,this._resolve()}reject(e){this._used=!0,this._reject(e)}},xv=class{constructor(e,t,i){this._features=[];this._method2Message=new Map;this._dynamicFeatures=new Map;this._id=e,this._name=t,i.outputChannel?this._outputChannel=i.outputChannel:this._outputChannel=void 0,this._clientOptions={disableWorkspaceFolders:i.disableWorkspaceFolders,disableSnippetCompletion:i.disableSnippetCompletion,disableDynamicRegister:i.disableDynamicRegister,disableDiagnostics:i.disableDiagnostics,disableCompletion:i.disableCompletion,formatterPriority:i.formatterPriority,ignoredRootPaths:i.ignoredRootPaths,documentSelector:i.documentSelector||[],synchronize:i.synchronize||{},diagnosticCollectionName:i.diagnosticCollectionName,outputChannelName:i.outputChannelName||this._id,revealOutputChannelOn:i.revealOutputChannelOn||4,stdioEncoding:i.stdioEncoding||"utf8",initializationOptions:i.initializationOptions,initializationFailedHandler:i.initializationFailedHandler,progressOnInitialization:!!i.progressOnInitialization,errorHandler:i.errorHandler||new KE(this._id),middleware:i.middleware||{},workspaceFolder:i.workspaceFolder},this.state=0,this._connectionPromise=void 0,this._resolvedConnection=void 0,this._initializeResult=void 0,this._listeners=void 0,this._providers=void 0,this._diagnostics=void 0,this._fileEvents=[],this._fileEventDelayer=new HE(250),this._onReady=new Promise((o,s)=>{this._onReadyCallbacks=new YE(o,s)}),this._onStop=void 0,this._stateChangeEmitter=new D.Emitter,this._tracer={log:(o,s)=>{wt(o)?this.logTrace(o,s):this.logObjectTrace(o)}},this._syncedDocuments=new Map;let n=b.getConfiguration("coc.preferences");this._markdownSupport=n.get("enableMarkdown",!0),this.registerBuiltinFeatures()}get supporedMarkupKind(){return this._markdownSupport?[D.MarkupKind.Markdown,D.MarkupKind.PlainText]:[D.MarkupKind.PlainText]}get state(){return this._state}get id(){return this._id}get name(){return this._name}set state(e){let t=this.getPublicState();this._state=e;let i=this.getPublicState();i!==t&&this._stateChangeEmitter.fire({oldState:t,newState:i})}getPublicState(){return this.state===3?2:this.state===1?3:1}get initializeResult(){return this._initializeResult}async sendRequest(e,...t){if(!this.isConnectionActive())throw new Error("Language client is not ready yet");try{return this._resolvedConnection.sendRequest(e,...t)}catch(i){throw this.error(`Sending request ${wt(e)?e:e.method} failed.`,i),i}}onRequest(e,t){if(!this.isConnectionActive())throw new Error("Language client is not ready yet");try{this._resolvedConnection.onRequest(e,t)}catch(i){throw this.error(`Registering request handler ${wt(e)?e:e.method} failed.`,i),i}}sendNotification(e,t){if(!this.isConnectionActive())throw new Error("Language client is not ready yet");try{this._resolvedConnection.sendNotification(e,t)}catch(i){throw this.error(`Sending notification ${wt(e)?e:e.method} failed.`,i),i}}onNotification(e,t){if(!this.isConnectionActive())throw new Error("Language client is not ready yet");try{this._resolvedConnection.onNotification(e,t)}catch(i){throw this.error(`Registering notification handler ${wt(e)?e:e.method} failed.`,i),i}}onProgress(e,t,i){if(!this.isConnectionActive())throw new Error("Language client is not ready yet");try{if(e==D.WorkDoneProgress.type){let n=this._clientOptions.middleware.handleWorkDoneProgress;if(n!==void 0)return this._resolvedConnection.onProgress(e,t,o=>{n(t,o,()=>i(o))})}return this._resolvedConnection.onProgress(e,t,i)}catch(n){throw this.error(`Registering progress handler for token ${t} failed.`,n),n}}sendProgress(e,t,i){if(!this.isConnectionActive())throw new Error("Language client is not ready yet");try{this._resolvedConnection.sendProgress(e,t,i)}catch(n){throw this.error(`Sending progress for token ${t} failed.`,n),n}}get clientOptions(){return this._clientOptions}get onDidChangeState(){return this._stateChangeEmitter.event}get outputChannel(){if(!this._outputChannel){let{outputChannelName:e}=this._clientOptions;this._outputChannel=C.createOutputChannel(e||this._name)}return this._outputChannel}get diagnostics(){return this._diagnostics}createDefaultErrorHandler(){return new KE(this._id)}set trace(e){this._trace=e,this.onReady().then(()=>{this.resolveConnection().then(t=>{t.trace(this._trace,this._tracer,{sendNotification:!1,traceFormat:this._traceFormat})})},()=>{})}logObjectTrace(e){e.isLSPMessage&&e.type?this.outputChannel.append(`[LSP - ${new Date().toLocaleTimeString()}] `):this.outputChannel.append(`[Trace - ${new Date().toLocaleTimeString()}] `),e&&this.outputChannel.appendLine(`${JSON.stringify(e)}`)}data2String(e){if(e instanceof D.ResponseError){let t=e;return` Message: ${t.message} - Code: ${t.code} ${t.data?` -`+t.data.toString():""}`}return e instanceof Error?wt(e.stack)?e.stack:e.message:wt(e)?e:e.toString()}_appendOutput(e,t,i){let n=3;switch(e){case"Info":n=1;break;case"Warn":n=2;break}this.outputChannel.appendLine(`[${e} - ${new Date().toLocaleTimeString()}] ${t}`);let o;i&&(o=this.data2String(i),this.outputChannel.appendLine(o)),this._clientOptions.revealOutputChannelOn<=n&&this.outputChannel.show(!0)}info(e,t){this._appendOutput("Info",e,t)}warn(e,t){this._appendOutput("Warn",e,t)}error(e,t){this._appendOutput("Error",e,t)}logTrace(e,t){this.outputChannel.appendLine(`[Trace - ${new Date().toLocaleTimeString()}] ${e}`),t&&this.outputChannel.appendLine(this.data2String(t))}needsStart(){return this.state===0||this.state===4||this.state===5}needsStop(){return this.state===1||this.state===3}onReady(){return this._onReady}get started(){return this.state!=0}isConnectionActive(){return this.state===3&&!!this._resolvedConnection}start(){if(this._onReadyCallbacks.isUsed&&(this._onReady=new Promise((e,t)=>{this._onReadyCallbacks=new YE(e,t)})),this._listeners=[],this._providers=[],!this._diagnostics){let e=this._clientOptions,t=e.diagnosticCollectionName?e.diagnosticCollectionName:this._id;this._diagnostics=B.createDiagnosticCollection(t)}return this.state=1,this.resolveConnection().then(e=>(e.onLogMessage(t=>{let i;switch(t.type){case D.MessageType.Error:i="error",this.error(t.message);break;case D.MessageType.Warning:i="warning",this.warn(t.message);break;case D.MessageType.Info:i="info",this.info(t.message);break;default:i="log",this.outputChannel.appendLine(t.message)}if(global.hasOwnProperty("__TEST__")){console.log(`[${i}] ${t.message}`);return}}),e.onShowMessage(t=>{switch(t.type){case D.MessageType.Error:C.showErrorMessage(t.message);break;case D.MessageType.Warning:C.showWarningMessage(t.message);break;case D.MessageType.Info:C.showInformationMessage(t.message);break;default:C.showInformationMessage(t.message)}}),e.onRequest(D.ShowMessageRequest.type,t=>{let i;switch(t.type){case D.MessageType.Error:i=C.showErrorMessage.bind(C);break;case D.MessageType.Warning:i=C.showWarningMessage.bind(C);break;case D.MessageType.Info:i=C.showInformationMessage.bind(C);break;default:i=C.showInformationMessage.bind(C)}let n=t.actions||[];return i(t.message,...n)}),e.onTelemetry(t=>{}),e.listen(),this.initialize(e))).then(void 0,e=>{this.state=2,this._onReadyCallbacks.reject(e),this.error("Starting client failed ",e)}),D.Disposable.create(()=>{this.needsStop()&&this.stop()})}resolveConnection(){return this._connectionPromise||(this._connectionPromise=this.createConnection()),this._connectionPromise}resolveRootPath(){if(this._clientOptions.workspaceFolder)return $.parse(this._clientOptions.workspaceFolder.uri).fsPath;let{ignoredRootPaths:e}=this._clientOptions,t=b.getConfiguration(this.id),i=t.get("rootPatterns",[]),n=t.get("requireRootPattern",!1),o;if(i&&i.length){let a=b.getDocument(b.bufnr);if(a&&a.schema=="file"){let l=VE.default.dirname($.parse(a.uri).fsPath);o=Qf(l,i,b.cwd)}}if(n&&!o)return null;let s=o||b.rootPath||b.cwd;return e&&e.indexOf(s)!==-1?(C.showMessage(`Ignored rootPath ${s} of client "${this._id}"`,"warning"),null):s}initialize(e){this.refreshTrace(e,!1);let{initializationOptions:t,progressOnInitialization:i}=this._clientOptions,n=this.resolveRootPath();if(!n)return;let o={processId:process.pid,rootPath:n||null,rootUri:n?Gp($.file(n)):null,capabilities:this.computeClientCapabilities(),initializationOptions:No(t)?t():t,trace:D.Trace.toString(this._trace),workspaceFolders:null,clientInfo:{name:"coc.nvim",version:b.version}};if(this.fillInitializeParams(o),i){let s=Be();o.workDoneToken=s;let a=new zp(e,s);return a.begin({title:`initializing ${this.id}`,kind:"begin"}),this.doInitialize(e,o).then(l=>(a.done(),l),l=>{throw a.cancel(),l})}else return this.doInitialize(e,o)}doInitialize(e,t){return e.initialize(t).then(i=>{this._resolvedConnection=e,this._initializeResult=i,this.state=3;let n;return hm(i.capabilities.textDocumentSync)?i.capabilities.textDocumentSync===D.TextDocumentSyncKind.None?n={openClose:!1,change:D.TextDocumentSyncKind.None,save:void 0}:n={openClose:!0,change:i.capabilities.textDocumentSync,save:{includeText:!1}}:i.capabilities.textDocumentSync!=null&&(n=i.capabilities.textDocumentSync),this._capabilities=Object.assign({},i.capabilities,{resolvedTextDocumentSync:n}),this._clientOptions.disableDiagnostics||e.onDiagnostics(o=>this.handleDiagnostics(o)),e.onRequest(D.RegistrationRequest.type,o=>this.handleRegistrationRequest(o)),e.onRequest("client/registerFeature",o=>this.handleRegistrationRequest(o)),e.onRequest(D.UnregistrationRequest.type,o=>this.handleUnregistrationRequest(o)),e.onRequest("client/unregisterFeature",o=>this.handleUnregistrationRequest(o)),e.onRequest(D.ApplyWorkspaceEditRequest.type,o=>this.handleApplyWorkspaceEdit(o)),e.sendNotification(D.InitializedNotification.type,{}),this.hookFileEvents(e),this.hookConfigurationChanged(e),this.initializeFeatures(e),this._onReadyCallbacks.resolve(),i}).then(void 0,i=>{throw this._clientOptions.initializationFailedHandler?this._clientOptions.initializationFailedHandler(i)?this.initialize(e):(this.stop(),this._onReadyCallbacks.reject(i)):i instanceof D.ResponseError&&i.data&&i.data.retry?C.showPrompt(i.message+" Retry?").then(n=>{n?this.initialize(e):(this.stop(),this._onReadyCallbacks.reject(i))}):(i&&i.message&&C.showMessage(i.message,"error"),this.error("Server initialization failed.",i),this.stop(),this._onReadyCallbacks.reject(i)),i})}stop(){return this._initializeResult=void 0,this._connectionPromise?this.state===4&&this._onStop?this._onStop:(this.state=4,this.cleanUp(),this._onStop=this.resolveConnection().then(e=>e.shutdown().then(()=>{e.exit(),e.dispose(),this.state=5,this.cleanUpChannel(),this._onStop=void 0,this._connectionPromise=void 0,this._resolvedConnection=void 0})).catch(e=>{us.error("Error on stop languageserver:",e),this.state=5,this.cleanUpChannel(),this._onStop=void 0,this._connectionPromise=void 0,this._resolvedConnection=void 0})):(this.state=5,Promise.resolve())}cleanUp(e=!0,t=!0){this._listeners&&(this._listeners.forEach(i=>i.dispose()),this._listeners=void 0),this._providers&&(this._providers.forEach(i=>i.dispose()),this._providers=void 0);for(let i of this._features.values())typeof i.dispose=="function"?i.dispose():us.error("Feature can't be disposed",i);this._syncedDocuments&&this._syncedDocuments.clear(),e&&this.cleanUpChannel(),this._diagnostics&&(t?(this._diagnostics.dispose(),this._diagnostics=void 0):this._diagnostics.clear())}cleanUpChannel(){this._outputChannel&&(this._outputChannel.dispose(),this._outputChannel=void 0)}notifyFileEvent(e){var o;let t=this;function i(s){t._fileEvents.push(s),t._fileEventDelayer.trigger(()=>{t.onReady().then(()=>{t.resolveConnection().then(a=>{t.isConnectionActive()&&a.didChangeWatchedFiles({changes:t._fileEvents}),t._fileEvents=[]})},a=>{t.error("Notify file events failed.",a)})})}let n=(o=this.clientOptions.middleware)==null?void 0:o.workspace;(n==null?void 0:n.didChangeWatchedFile)?n.didChangeWatchedFile(e,i):i(e)}handleDiagnostics(e){if(!this._diagnostics)return;let{uri:t,diagnostics:i}=e,n=this.clientOptions.middleware.handleDiagnostics;n?n(t,i,(o,s)=>this.setDiagnostics(o,s)):this.setDiagnostics(t,i)}setDiagnostics(e,t){var n;if(!this._diagnostics)return;if(b.getConfiguration("diagnostic").get("separateRelatedInformationAsDiagnostics")&&t.length>0){let o=new Map;o.set(e,t);for(let s of t){if((n=s.relatedInformation)==null?void 0:n.length){let a=`${s.message} + ${cmds.join("\n ")} +augroup end`; + try { + let dir = import_path11.default.join(process.env.TMPDIR || import_os4.default.tmpdir(), `coc.nvim-${process.pid}`); + if (!import_fs_extra4.default.existsSync(dir)) + import_fs_extra4.default.mkdirpSync(dir); + let filepath = import_path11.default.join(dir, `coc-${process.pid}.vim`); + import_fs_extra4.default.writeFileSync(filepath, content, "utf8"); + let cmd = `source ${filepath}`; + if (this.env.isCygwin && platform_exports.isWindows) { + cmd = `execute "source" . substitute(system('cygpath ${filepath.replace(/\\/g, "/")}'), '\\n', '', 'g')`; + } + this.nvim.command(cmd).logError(); + } catch (e) { + window_default.showMessage(`Can't create tmp file: ${e.message}`, "error"); + } + } + async onBufReadCmd(scheme, uri) { + let provider = this.schemeProviderMap.get(scheme); + if (!provider) { + window_default.showMessage(`Provider for ${scheme} not found`, "error"); + return; + } + let tokenSource = new import_vscode_languageserver_protocol13.CancellationTokenSource(); + let content = await Promise.resolve(provider.provideTextDocumentContent(URI.parse(uri), tokenSource.token)); + let buf = await this.nvim.buffer; + await buf.setLines(content.split(/\r?\n/), { + start: 0, + end: -1, + strictIndexing: false + }); + setTimeout(async () => { + await events_default.fire("BufCreate", [buf.id]); + }, 30); + } + async attach() { + if (this._attached) + return; + this._attached = true; + let [bufs, bufnr, winid] = await this.nvim.eval(`[map(getbufinfo({'bufloaded': 1}),'v:val["bufnr"]'),bufnr('%'),win_getid()]`); + this.bufnr = bufnr; + await Promise.all(bufs.map((buf) => this.onBufCreate(buf))); + if (!this._initialized) { + this._onDidWorkspaceInitialized.fire(void 0); + this._initialized = true; + } + await events_default.fire("BufEnter", [bufnr]); + await events_default.fire("BufWinEnter", [bufnr, winid]); + } + getChangedUris(documentChanges) { + let uris = new Set(); + let createUris = new Set(); + for (let change of documentChanges) { + if (import_vscode_languageserver_protocol13.TextDocumentEdit.is(change)) { + let { textDocument } = change; + let { uri, version: version2 } = textDocument; + uris.add(uri); + if (version2 != null && version2 > 0) { + let doc = this.getDocument(uri); + if (!doc) { + throw new Error(`${uri} not loaded`); + } + if (doc.version != version2) { + throw new Error(`${uri} changed before apply edit`); + } + } + } else if (import_vscode_languageserver_protocol13.CreateFile.is(change) || import_vscode_languageserver_protocol13.DeleteFile.is(change)) { + if (!isFile(change.uri)) { + throw new Error(`change of scheme ${change.uri} not supported`); + } + createUris.add(change.uri); + uris.add(change.uri); + } else if (import_vscode_languageserver_protocol13.RenameFile.is(change)) { + if (!isFile(change.oldUri) || !isFile(change.newUri)) { + throw new Error(`change of scheme ${change.oldUri} not supported`); + } + let newFile = URI.parse(change.newUri).fsPath; + if (import_fs_extra4.default.existsSync(newFile)) { + throw new Error(`file "${newFile}" already exists for rename`); + } + uris.add(change.oldUri); + } else { + throw new Error(`Invalid document change: ${JSON.stringify(change, null, 2)}`); + } + } + return Array.from(uris); + } + createConfigurations() { + let home = import_path11.default.normalize(process.env.COC_VIMCONFIG) || import_path11.default.join(import_os4.default.homedir(), ".vim"); + let userConfigFile = import_path11.default.join(home, CONFIG_FILE_NAME); + return new Configurations(userConfigFile, new ConfigurationProxy(this)); + } + attachChangedEvents() { + if (this.isVim) { + const onChange = (bufnr) => { + let doc = this.getDocument(bufnr); + if (doc && doc.attached) + doc.fetchContent(); + }; + events_default.on("TextChangedP", onChange, null, this.disposables); + events_default.on("TextChangedI", onChange, null, this.disposables); + events_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 document2 = this.getDocument(bufnr); + let source = new import_vscode_languageserver_protocol13.CancellationTokenSource(); + try { + if (document2) + this.onBufUnload(bufnr, true); + document2 = new Document(buffer, this._env, this.maxFileSize); + let token = source.token; + this.creatingSources.set(bufnr, source); + let created = await document2.init(this.nvim, token); + if (!created) + document2 = null; + } catch (e) { + logger25.error("Error on create buffer:", e); + document2 = null; + } + if (this.creatingSources.get(bufnr) == source) { + source.dispose(); + this.creatingSources.delete(bufnr); + } + if (!document2 || !document2.textDocument) + return; + this.buffers.set(bufnr, document2); + if (document2.attached) { + document2.onDocumentDetach((bufnr2) => { + let doc = this.getDocument(bufnr2); + if (doc) + this.onBufUnload(doc.bufnr); + }); + } + if (document2.buftype == "" && document2.schema == "file") { + this.configurations.checkFolderConfiguration(document2.uri); + let config = this.getConfiguration("workspace"); + let filetypes = config.get("ignoredFiletypes", []); + if (!filetypes.includes(document2.filetype)) { + let root = this.resolveRoot(document2); + if (root) { + this.addWorkspaceFolder(root); + if (this.bufnr == buffer.id) { + this._root = root; + } + } + } + } + if (document2.enabled) { + let textDocument = Object.assign(document2.textDocument, { bufnr }); + this._onDidOpenDocument.fire(textDocument); + document2.onDocumentChange((e) => this._onDidChangeDocument.fire(e)); + } + logger25.debug("buffer created", buffer.id); + } + 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 = URI.parse(workspaceFolder.uri).fsPath; + } + } + async checkCurrentBuffer(bufnr) { + this.bufnr = bufnr; + await this.checkBuffer(bufnr); + } + onBufWritePost(bufnr) { + let doc = this.buffers.get(bufnr); + if (!doc) + return; + this._onDidSaveDocument.fire(doc.textDocument); + } + onBufUnload(bufnr, recreate = false) { + logger25.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) { + let textDocument = Object.assign(doc.textDocument, { bufnr }); + this._onDidCloseDocument.fire(textDocument); + this.buffers.delete(bufnr); + doc.detach(); + } + } + async onBufWritePre(bufnr) { + let doc = this.buffers.get(bufnr); + if (!doc || !doc.attached) + return; + await doc.synchronize(); + let firing = true; + let thenables = []; + let event = { + document: doc.textDocument, + reason: import_vscode_languageserver_protocol13.TextDocumentSaveReason.Manual, + waitUntil: (thenable) => { + if (!firing) { + logger25.error(`Can't call waitUntil in async manner:`, Error().stack); + window_default.showMessage(`waitUntil can't be used in async manner, check log for details`, "error"); + } else { + thenables.push(thenable); + } + } + }; + this._onWillSaveDocument.fire(event); + firing = false; + let total = thenables.length; + if (total) { + let promise = new Promise((resolve3) => { + const preferences = this.getConfiguration("coc.preferences"); + const willSaveHandlerTimeout = preferences.get("willSaveHandlerTimeout", 500); + let timer = setTimeout(() => { + window_default.showMessage(`Will save handler timeout after ${willSaveHandlerTimeout}ms`, "warning"); + resolve3(void 0); + }, willSaveHandlerTimeout); + let i = 0; + let called = false; + for (let p of thenables) { + let cb = (res) => { + if (called) + return; + called = true; + clearTimeout(timer); + resolve3(res); + }; + p.then((res) => { + if (Array.isArray(res) && res.length && import_vscode_languageserver_protocol13.TextEdit.is(res[0])) { + return cb(res); + } + i = i + 1; + if (i == total) + cb(void 0); + }, () => { + i = i + 1; + if (i == total) + cb(void 0); + }); + } + }); + let edits = await promise; + if (edits) + await doc.applyEdits(edits); + } + } + 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; + let textDocument = Object.assign(doc.textDocument, { bufnr }); + this._onDidCloseDocument.fire(textDocument); + doc.setFiletype(filetype); + this._onDidOpenDocument.fire(Object.assign(doc.textDocument, { bufnr })); + } + async checkBuffer(bufnr) { + if (this._disposed || !bufnr) + return; + let doc = this.getDocument(bufnr); + if (!doc && !this.creatingSources.has(bufnr)) + await this.onBufCreate(bufnr); + } + resolveRoot(document2) { + let types = [PatternType.Buffer, PatternType.LanguageServer, PatternType.Global]; + let u = URI.parse(document2.uri); + let dir = import_path11.default.dirname(u.fsPath); + let { cwd } = this; + let config = this.getConfiguration("workspace"); + let bottomUpFileTypes = config.get("bottomUpFiletypes", []); + let checkCwd = config.get("workspaceFolderCheckCwd", true); + for (let patternType of types) { + let patterns = this.getRootPatterns(document2, patternType); + if (patterns && patterns.length) { + let isBottomUp = bottomUpFileTypes.includes(document2.filetype); + let root = resolveRoot(dir, patterns, cwd, isBottomUp, checkCwd); + if (root) + return root; + } + } + if (this.cwd != import_os4.default.homedir() && isParentFolder(this.cwd, dir, true)) + return this.cwd; + return null; + } + getRootPatterns(document2, patternType) { + let { uri } = document2; + if (patternType == PatternType.Buffer) + return document2.getVar("root_patterns", []) || []; + if (patternType == PatternType.LanguageServer) + return this.getServerRootPatterns(document2.filetype); + const preferences = this.getConfiguration("coc.preferences", uri); + return preferences.get("rootPatterns", [".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 = URI.parse(doc.uri).fsPath; + let newPath = await nvim.callAsync("coc#util#with_callback", ["input", ["New path: ", oldPath, "file"]]); + newPath = newPath ? newPath.trim() : null; + if (newPath == oldPath || !newPath) + return; + let lines = await doc.buffer.lines; + let exists = import_fs_extra4.default.existsSync(oldPath); + if (exists) { + let modified = await nvim.eval("&modified"); + if (modified) + await nvim.command("noa w"); + if (oldPath.toLowerCase() != newPath.toLowerCase() && import_fs_extra4.default.existsSync(newPath)) { + let overwrite = await window_default.showPrompt(`${newPath} exists, overwrite?`); + if (!overwrite) + return; + import_fs_extra4.default.unlinkSync(newPath); + } + import_fs_extra4.default.renameSync(oldPath, newPath); + } + this._onWillRenameFiles.fire({ + files: [{ newUri: URI.parse(newPath), oldUri: URI.parse(oldPath) }], + waitUntil: async (thenable) => { + const edit2 = await Promise.resolve(thenable); + if (edit2 && import_vscode_languageserver_protocol13.WorkspaceEdit.is(edit2)) { + await this.applyEdit(edit2); + } + } + }); + this._onDidRenameFiles.fire({ + files: [{ newUri: URI.parse(newPath), oldUri: URI.parse(oldPath) }] + }); + let filepath = isParentFolder(cwd, newPath) ? import_path11.default.relative(cwd, newPath) : newPath; + let view = await nvim.call("winsaveview"); + 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("winrestview", [view], true); + await nvim.resumeNotification(); + } + get folderPaths() { + return this.workspaceFolders.map((f) => URI.parse(f.uri).fsPath); + } + get floatSupported() { + let { env } = this; + return env.floating || env.textprop; + } + removeWorkspaceFolder(fsPath) { + let idx = this._workspaceFolders.findIndex((f) => 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) => URI.parse(f.uri).fsPath == oldPath); + if (idx == -1) + return; + let removed = this._workspaceFolders[idx]; + let added = { + uri: URI.file(newPath).toString(), + name: import_path11.default.dirname(newPath) + }; + this._workspaceFolders.splice(idx, 1); + this._workspaceFolders.push(added); + this._onDidChangeWorkspaceFolders.fire({ + removed: [removed], + added: [added] + }); + } + addRootPattern(filetype, rootPatterns) { + let patterns = this.rootPatterns.get(filetype) || []; + for (let p of rootPatterns) { + if (!patterns.includes(p)) { + patterns.push(p); + } + } + this.rootPatterns.set(filetype, patterns); + } + get insertMode() { + return this._insertMode; + } + async detach() { + if (!this._attached) + return; + this._attached = false; + channels_default.dispose(); + for (let bufnr of this.buffers.keys()) { + await events_default.fire("BufUnload", [bufnr]); + } + } + dispose() { + this._disposed = true; + for (let doc of this.documents) { + doc.detach(); + } + disposeAll(this.disposables); + Watchman.dispose(); + this.configurations.dispose(); + this.buffers.clear(); + } + addWorkspaceFolder(rootPath) { + if (rootPath == import_os4.default.homedir()) + return; + let { _workspaceFolders } = this; + let uri = URI.file(rootPath).toString(); + let workspaceFolder = { uri, name: import_path11.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 (Array.isArray(filetypes) && rootPatterns && filetypes.includes(filetype)) { + patterns.push(...rootPatterns); + } + } + patterns = patterns.concat(this.rootPatterns.get(filetype) || []); + return patterns.length ? distinct(patterns) : null; + } + }; + workspace_default = new Workspace(); + } +}); + +// src/util/fzy.ts +function islower(s) { + return s.toLowerCase() === s; +} +function isupper(s) { + return s.toUpperCase() === s; +} +function precompute_bonus(haystack) { + 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); + 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 score5 = SCORE_MIN; + if (!i) { + score5 = j * SCORE_GAP_LEADING + match_bonus[j]; + } else if (j) { + score5 = Math.max(M[i - 1][j - 1] + match_bonus[j], D[i - 1][j - 1] + SCORE_MATCH_CONSECUTIVE); + } + D[i][j] = score5; + M[i][j] = prev_score = Math.max(score5, prev_score + gap_score); + } else { + D[i][j] = SCORE_MIN; + M[i][j] = prev_score = prev_score + gap_score; + } + } + } +} +function score2(needle, haystack) { + let n = needle.length; + let m = haystack.length; + if (!n || !m) + return SCORE_MIN; + if (n === m) { + return SCORE_MAX; + } + if (m > 1024) { + return SCORE_MIN; + } + let D = new Array(n); + let M = new Array(n); + compute(needle, haystack, D, M); + return M[n - 1][m - 1]; +} +function groupPositions(arr) { + let res = []; + for (let i = 0; i < arr.length; i++) { + let last = res.length ? res[res.length - 1] : void 0; + let curr = arr[i]; + if (last && curr == last[1]) { + last[1] = curr + 1; + } else { + res.push([curr, curr + 1]); + } + } + return res; +} +function positions(needle, haystack) { + let n = needle.length; + let m = haystack.length; + let positions2 = new Array(n); + if (!n || !m) + return positions2; + if (n === m) { + for (let i = 0; i < n; i++) + positions2[i] = i; + return positions2; + } + if (m > 1024) { + return positions2; + } + let D = new Array(n); + let M = new Array(n); + compute(needle, haystack, D, M); + let match_required = false; + for (let i = n - 1, j = m - 1; i >= 0; i--) { + for (; j >= 0; j--) { + if (D[i][j] !== SCORE_MIN && (match_required || D[i][j] === M[i][j])) { + match_required = i && j && M[i][j] === D[i - 1][j - 1] + SCORE_MATCH_CONSECUTIVE; + positions2[i] = j--; + break; + } + } + } + return positions2; +} +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; +} +var SCORE_MIN, SCORE_MAX, SCORE_GAP_LEADING, SCORE_GAP_TRAILING, SCORE_GAP_INNER, SCORE_MATCH_CONSECUTIVE, SCORE_MATCH_SLASH, SCORE_MATCH_WORD, SCORE_MATCH_CAPITAL, SCORE_MATCH_DOT; +var init_fzy = __esm({ + "src/util/fzy.ts"() { + SCORE_MIN = -Infinity; + SCORE_MAX = Infinity; + SCORE_GAP_LEADING = -5e-3; + SCORE_GAP_TRAILING = -5e-3; + SCORE_GAP_INNER = -0.01; + SCORE_MATCH_CONSECUTIVE = 1; + SCORE_MATCH_SLASH = 0.9; + SCORE_MATCH_WORD = 0.8; + SCORE_MATCH_CAPITAL = 0.7; + SCORE_MATCH_DOT = 0.6; + } +}); + +// src/tree/filter.ts +var import_vscode_languageserver_protocol14, sessionKey, Filter; +var init_filter = __esm({ + "src/tree/filter.ts"() { + init_events(); + import_vscode_languageserver_protocol14 = __toModule(require_main2()); + init_util(); + sessionKey = "filter"; + Filter = class { + constructor(nvim, keys) { + this.nvim = nvim; + this._activated = false; + this.history = []; + this.disposables = []; + this._onDidUpdate = new import_vscode_languageserver_protocol14.Emitter(); + this._onDidExit = new import_vscode_languageserver_protocol14.Emitter(); + this._onDidKeyPress = new import_vscode_languageserver_protocol14.Emitter(); + this.onDidKeyPress = this._onDidKeyPress.event; + this.onDidUpdate = this._onDidUpdate.event; + this.onDidExit = this._onDidExit.event; + this.text = ""; + events_default.on("InputChar", (session, character) => { + if (session !== sessionKey || !this._activated) + return; + if (!keys.includes(character)) { + if (character.length == 1) { + this.text = this.text + character; + this._onDidUpdate.fire(this.text); + return; + } + if (character == "") { + this.text = this.text.slice(0, -1); + this._onDidUpdate.fire(this.text); + return; + } + if (character == "") { + this.text = ""; + this._onDidUpdate.fire(this.text); + return; + } + if (character == "") { + let idx = this.history.indexOf(this.text); + let text = this.history[idx + 1] || this.history[0]; + if (text) { + this.text = text; + this._onDidUpdate.fire(this.text); + } + return; + } + if (character == "") { + let idx = this.history.indexOf(this.text); + let text = this.history[idx - 1] || this.history[this.history.length - 1]; + if (text) { + this.text = text; + this._onDidUpdate.fire(this.text); + } + } + if (character == "" || character == "") { + this.deactivate(); + return; + } + } + this._onDidKeyPress.fire(character); + }, null, this.disposables); + } + active() { + if (this._activated) + return; + this._activated = true; + this.text = ""; + this.nvim.call("coc#prompt#start_prompt", [sessionKey], true); + } + deactivate(node) { + if (!this._activated) + return; + this.nvim.call("coc#prompt#stop_prompt", [sessionKey], true); + this._activated = false; + let { text } = this; + this.text = ""; + this._onDidExit.fire(node); + if (text && !this.history.includes(text)) { + this.history.push(text); + } + } + get activated() { + return this._activated; + } + dispose() { + this.deactivate(); + this.history = []; + this._onDidKeyPress.dispose(); + this._onDidUpdate.dispose(); + this._onDidExit.dispose(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/tree/TreeItem.ts +var import_path12, TreeItemLabel, TreeItemCollapsibleState, TreeItem; +var init_TreeItem = __esm({ + "src/tree/TreeItem.ts"() { + init_esm2(); + import_path12 = __toModule(require("path")); + (function(TreeItemLabel3) { + function is(obj) { + return typeof obj.label == "string"; + } + TreeItemLabel3.is = is; + })(TreeItemLabel || (TreeItemLabel = {})); + (function(TreeItemCollapsibleState2) { + TreeItemCollapsibleState2[TreeItemCollapsibleState2["None"] = 0] = "None"; + TreeItemCollapsibleState2[TreeItemCollapsibleState2["Collapsed"] = 1] = "Collapsed"; + TreeItemCollapsibleState2[TreeItemCollapsibleState2["Expanded"] = 2] = "Expanded"; + })(TreeItemCollapsibleState || (TreeItemCollapsibleState = {})); + TreeItem = class { + constructor(label, collapsibleState = 0) { + this.collapsibleState = collapsibleState; + if (URI.isUri(label)) { + this.resourceUri = label; + this.label = import_path12.default.basename(label.path); + this.id = label.toString(); + } else { + this.label = label; + } + } + }; + } +}); + +// src/tree/TreeView.ts +var TreeView_exports = {}; +__export(TreeView_exports, { + default: () => BasicTreeView +}); +var import_vscode_languageserver_protocol15, logger26, highlightNamespace, signOffset, globalId, BasicTreeView; +var init_TreeView = __esm({ + "src/tree/TreeView.ts"() { + import_vscode_languageserver_protocol15 = __toModule(require_main2()); + init_commands2(); + init_events(); + init_floatFactory(); + init_util(); + init_mutex(); + init_object(); + init_string(); + init_fzy(); + init_workspace(); + init_window(); + init_filter(); + init_TreeItem(); + logger26 = require_logger2()("BasicTreeView"); + highlightNamespace = "tree"; + signOffset = 3e3; + globalId = 1; + BasicTreeView = class { + constructor(viewId, opts) { + this.viewId = viewId; + this._selection = []; + this._onDidExpandElement = new import_vscode_languageserver_protocol15.Emitter(); + this._onDidCollapseElement = new import_vscode_languageserver_protocol15.Emitter(); + this._onDidChangeSelection = new import_vscode_languageserver_protocol15.Emitter(); + this._onDidChangeVisibility = new import_vscode_languageserver_protocol15.Emitter(); + this.onDidExpandElement = this._onDidExpandElement.event; + this.onDidCollapseElement = this._onDidCollapseElement.event; + this.onDidChangeSelection = this._onDidChangeSelection.event; + this.onDidChangeVisibility = this._onDidChangeVisibility.event; + this.retryTimers = 0; + this.renderedItems = []; + this.nodesMap = new Map(); + this.mutex = new Mutex(); + this.disposables = []; + this.lineState = { titleCount: 0, messageCount: 0 }; + this.loadConfiguration(); + workspace_default.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables); + if (opts.enableFilter) { + this.filter = new Filter(this.nvim, [this.keys.selectNext, this.keys.selectPrevious, this.keys.invoke]); + } + this.tooltipFactory = new FloatFactory(workspace_default.nvim); + this.canSelectMany = !!opts.canSelectMany; + this.provider = opts.treeDataProvider; + this.leafIndent = opts.disableLeafIndent !== true; + this.winfixwidth = opts.winfixwidth !== false; + let message; + Object.defineProperty(this, "message", { + set: (msg) => { + message = msg ? msg.replace(/\r?\n/g, " ") : void 0; + this.updateHeadLines(); + }, + get: () => { + return message; + } + }); + let title = viewId.replace(/\r?\n/g, " "); + Object.defineProperty(this, "title", { + set: (newTitle) => { + title = newTitle ? newTitle.replace(/\r?\n/g, " ") : void 0; + this.updateHeadLines(); + }, + get: () => { + return title; + } + }); + let description; + Object.defineProperty(this, "description", { + set: (desc) => { + description = desc ? desc.replace(/\r?\n/g, " ") : void 0; + this.updateHeadLines(); + }, + get: () => { + return description; + } + }); + let filterText; + Object.defineProperty(this, "filterText", { + set: (text) => { + let { titleCount, messageCount } = this.lineState; + let start = titleCount + messageCount; + if (text != null) { + let highlights = [{ + lnum: start, + colStart: byteLength(text), + colEnd: byteLength(text) + 1, + hlGroup: "Cursor" + }]; + this.renderedItems = []; + this.updateUI([text + " "], highlights, start, -1, true); + void this.doFilter(text); + } else if (filterText != null) { + this.updateUI([], [], start, start + 1); + } + filterText = text; + }, + get: () => { + return filterText; + } + }); + if (this.provider.onDidChangeTreeData) { + this.provider.onDidChangeTreeData(this.onDataChange, this, this.disposables); + } + events_default.on("BufUnload", (bufnr) => { + if (bufnr != this.bufnr) + return; + this.winid = void 0; + this.bufnr = void 0; + this._onDidChangeVisibility.fire({ visible: false }); + this.dispose(); + }, null, this.disposables); + events_default.on("CursorHold", async (bufnr) => { + if (bufnr != this.bufnr) + return; + await this.onHover(); + }, null, this.disposables); + events_default.on(["CursorMoved", "BufEnter"], () => { + this.cancelResolve(); + }, null, this.disposables); + events_default.on("WinEnter", (winid) => { + var _a2; + if (winid != this.windowId || !((_a2 = this.filter) == null ? void 0 : _a2.activated)) + return; + let buf = this.nvim.createBuffer(this.bufnr); + let line = this.startLnum - 1; + let len = this.filterText ? this.filterText.length : 0; + let range = import_vscode_languageserver_protocol15.Range.create(line, len, line, len + 1); + buf.highlightRanges(highlightNamespace, "Cursor", [range]); + this.nvim.call("coc#prompt#start_prompt", [sessionKey], true); + this.redraw(); + }, null, this.disposables); + events_default.on("WinLeave", (winid) => { + var _a2; + if (winid != this.windowId || !((_a2 = this.filter) == null ? void 0 : _a2.activated)) + return; + let buf = this.nvim.createBuffer(this.bufnr); + this.nvim.call("coc#prompt#stop_prompt", [sessionKey], true); + buf.clearNamespace(highlightNamespace, this.startLnum - 1, this.startLnum); + }, null, this.disposables); + this.disposables.push(this._onDidChangeVisibility, this._onDidChangeSelection, this._onDidCollapseElement, this._onDidExpandElement); + if (this.filter) { + this.filter.onDidExit((node) => { + this.nodesMap.clear(); + this.filterText = void 0; + this.itemsToFilter = void 0; + if (node && typeof this.provider.getParent === "function") { + this.renderedItems = []; + void this.reveal(node, { focus: true }); + } else { + this.clearSelection(); + void this.render(); + } + }); + this.filter.onDidUpdate((text) => { + this.filterText = text; + }); + this.filter.onDidKeyPress(async (character) => { + var _a2, _b; + let items = this.renderedItems; + if (!(items == null ? void 0 : items.length)) + return; + let curr = this.selection[0]; + if (character == "" || character == this.keys.selectPrevious) { + let idx = items.findIndex((o) => o.node == curr); + let index = idx == -1 || idx == 0 ? items.length - 1 : idx - 1; + let node = (_a2 = items[index]) == null ? void 0 : _a2.node; + if (node) + this.selectItem(node, true); + } + if (character == "" || character == this.keys.selectNext) { + let idx = items.findIndex((o) => o.node == curr); + let index = idx == -1 || idx == items.length - 1 ? 0 : idx + 1; + let node = (_b = items[index]) == null ? void 0 : _b.node; + if (node) + this.selectItem(node, true); + } + if (character == "" || character == this.keys.invoke) { + if (!curr) + return; + await this.invokeCommand(curr); + this.filter.deactivate(curr); + } + }); + } + } + get windowId() { + return this.winid; + } + get startLnum() { + let filterCount = this.filterText == null ? 0 : 1; + return this.lineState.messageCount + this.lineState.titleCount + filterCount; + } + get nvim() { + return workspace_default.nvim; + } + loadConfiguration(e) { + if (!e || e.affectsConfiguration("tree")) { + let config = workspace_default.getConfiguration("tree"); + this.config = { + openedIcon: config.get("openedIcon", " "), + closedIcon: config.get("closedIcon", " ") + }; + this.keys = { + close: config.get("key.close"), + invoke: config.get("key.invoke"), + toggle: config.get("key.toggle"), + actions: config.get("key.actions"), + collapseAll: config.get("key.collapseAll"), + toggleSelection: config.get("key.toggleSelection"), + activeFilter: config.get("key.activeFilter"), + selectNext: config.get("key.selectNext"), + selectPrevious: config.get("key.selectPrevious") + }; + if (e) { + void this.render(); + } + } + } + async doFilter(text) { + let items = []; + let index = 0; + let release = await this.mutex.acquire(); + try { + if (!this.itemsToFilter) { + let itemsToFilter = []; + const addNodes = async (nodes2) => { + for (let n of nodes2) { + itemsToFilter.push(n); + let arr = await Promise.resolve(this.provider.getChildren(n)); + if (arr == null ? void 0 : arr.length) + await addNodes(arr); + } + }; + let nodes = await Promise.resolve(this.provider.getChildren()); + await addNodes(nodes); + this.itemsToFilter = itemsToFilter; + } + for (let n of this.itemsToFilter) { + let item = await this.getTreeItem(n); + let label = TreeItemLabel.is(item.label) ? item.label.label : item.label; + if (!text || hasMatch(text, label)) { + let idxs = text ? positions(text, label) : []; + item.collapsibleState = TreeItemCollapsibleState.None; + item.label = { label, highlights: text ? groupPositions(idxs) : [] }; + let { line, highlights: highlights2 } = this.getRenderedLine(item, index, 0); + items.push({ + level: 0, + node: n, + line, + index, + score: text ? score2(text, label) : 0, + highlights: highlights2 + }); + index += 1; + } + } + items.sort((a, b) => { + if (a.score != b.score) + return b.score - a.score; + return a.index - b.index; + }); + let lnum = this.startLnum; + let highlights = []; + let renderedItems = this.renderedItems = items.map((o, idx) => { + highlights.push(...o.highlights.map((h) => { + h.lnum = lnum + idx; + return h; + })); + delete o.index; + delete o.score; + delete o.highlights; + return o; + }); + this.updateUI(renderedItems.map((o) => o.line), highlights, lnum, -1, true); + if (renderedItems.length) { + this.selectItem(renderedItems[0].node, true); + } else { + this.clearSelection(); + } + this.redraw(); + release(); + } catch (e) { + release(); + logger26.error(`Error on tree filter: ${e.message}`, e); + } + } + async onHover() { + let { nvim } = this; + let lnum = await nvim.call("line", ["."]); + let element = this.getElementByLnum(lnum - 1); + if (!element) + return; + let obj = this.nodesMap.get(element); + if (!obj) + return; + let item = obj.item; + if (!obj.resolved) { + item = await this.resolveItem(element, item); + if (!item) + return; + } + if (!item.tooltip || !this.bufnr) + return; + let isMarkdown2 = import_vscode_languageserver_protocol15.MarkupContent.is(item.tooltip) && item.tooltip.kind == import_vscode_languageserver_protocol15.MarkupKind.Markdown; + let doc = { + filetype: isMarkdown2 ? "markdown" : "txt", + content: import_vscode_languageserver_protocol15.MarkupContent.is(item.tooltip) ? item.tooltip.value : item.tooltip + }; + await this.tooltipFactory.show([doc], { modes: ["n"] }); + } + async onClick(element) { + let { nvim } = this; + let [line, col] = await nvim.eval(`[getline('.'),col('.')]`); + let pre = byteSlice(line, 0, col - 1); + let character = line[pre.length]; + if (!character) + return; + let { openedIcon, closedIcon } = this.config; + if (/^\s*$/.test(pre) && [openedIcon, closedIcon].includes(character)) { + await this.toggleExpand(element); + } else { + await this.invokeCommand(element); + } + } + async invokeCommand(element) { + let obj = this.nodesMap.get(element); + if (!obj) + return; + this.selectItem(element); + let item = obj.item; + if (!item.command) { + item = await this.resolveItem(element, item); + if (!item) + return; + } + if (!item.command) + throw new Error(`Failed to resolve command from TreeItem.`); + await commands_default.execute(item.command); + } + async invokeActions(element) { + this.selectItem(element); + if (typeof this.provider.resolveActions !== "function") { + await window_default.showWarningMessage("No actions"); + return; + } + let obj = this.nodesMap.get(element); + let actions = await Promise.resolve(this.provider.resolveActions(obj.item, element)); + if (!actions || actions.length == 0) { + await window_default.showWarningMessage("No actions available"); + return; + } + let keys = actions.map((o) => o.title); + let res = await window_default.showMenuPicker(keys, "Choose action"); + if (res == -1) + return; + await Promise.resolve(actions[res].handler(element)); + } + async onDataChange(node) { + var _a2; + if ((_a2 = this.filter) == null ? void 0 : _a2.activated) { + this.itemsToFilter = void 0; + await this.doFilter(this.filterText); + return; + } + this.clearSelection(); + if (!node) { + await this.render(); + return; + } + let release = await this.mutex.acquire(); + try { + let items = this.renderedItems; + let idx = items.findIndex((o) => o.node === node); + if (idx != -1 && this.bufnr) { + let obj = items[idx]; + let level = obj.level; + let removeCount = 0; + for (let i = idx; i < items.length; i++) { + let o = items[i]; + if (i == idx || o && o.level > level) { + removeCount += 1; + } + } + let appendItems = []; + let highlights = []; + let start = idx + this.startLnum; + await this.appendTreeNode(node, level, start, appendItems, highlights); + items.splice(idx, removeCount, ...appendItems); + this.updateUI(appendItems.map((o) => o.line), highlights, start, start + removeCount); + } + release(); + } catch (e) { + let errMsg = `Error on tree refresh: ${e.message}`; + logger26.error(errMsg, e); + this.nvim.errWriteLine("[coc.nvim] " + errMsg); + release(); + } + } + async resolveItem(element, item) { + if (typeof this.provider.resolveTreeItem === "function") { + let tokenSource = this.resolveTokenSource = new import_vscode_languageserver_protocol15.CancellationTokenSource(); + let token = tokenSource.token; + item = await Promise.resolve(this.provider.resolveTreeItem(item, element, token)); + tokenSource.dispose(); + this.resolveTokenSource = void 0; + if (token.isCancellationRequested) + return void 0; + } + this.nodesMap.set(element, { item, resolved: true }); + return item; + } + get visible() { + return this.winid != null; + } + get selection() { + return this._selection.slice(); + } + async checkLines() { + if (!this.bufnr) + return; + let buf = this.nvim.createBuffer(this.bufnr); + let curr = await buf.lines; + let { titleCount, messageCount } = this.lineState; + curr = curr.slice(titleCount + messageCount); + let lines = this.renderedItems.map((o) => o.line); + return equals(curr, lines); + } + async toggleExpand(element) { + let o = this.nodesMap.get(element); + if (!o) + return; + let treeItem = o.item; + let lnum = this.getItemLnum(element); + let nodeIdx = lnum - this.startLnum; + let obj = this.renderedItems[nodeIdx]; + if (!obj || treeItem.collapsibleState == TreeItemCollapsibleState.None) { + if (typeof this.provider.getParent === "function") { + let node = await Promise.resolve(this.provider.getParent(element)); + if (node) { + await this.toggleExpand(node); + this.focusItem(node); + } + } + return; + } + let removeCount = 0; + if (treeItem.collapsibleState == TreeItemCollapsibleState.Expanded) { + let level = obj.level; + for (let i = nodeIdx + 1; i < this.renderedItems.length; i++) { + let o2 = this.renderedItems[i]; + if (!o2 || o2.level <= level) + break; + removeCount += 1; + } + treeItem.collapsibleState = TreeItemCollapsibleState.Collapsed; + } else if (treeItem.collapsibleState == TreeItemCollapsibleState.Collapsed) { + treeItem.collapsibleState = TreeItemCollapsibleState.Expanded; + } + let newItems = []; + let newHighlights = []; + await this.appendTreeNode(obj.node, obj.level, lnum, newItems, newHighlights); + this.renderedItems.splice(nodeIdx, removeCount + 1, ...newItems); + this.updateUI(newItems.map((o2) => o2.line), newHighlights, lnum, lnum + removeCount + 1); + this.refreshSigns(); + if (treeItem.collapsibleState == TreeItemCollapsibleState.Collapsed) { + this._onDidCollapseElement.fire({ element }); + } else { + this._onDidExpandElement.fire({ element }); + } + } + toggleSelection(element) { + let idx = this._selection.findIndex((o) => o === element); + if (idx !== -1) { + this.unselectItem(idx); + } else { + this.selectItem(element); + } + } + clearSelection() { + if (!this.bufnr) + return; + this._selection = []; + let buf = this.nvim.createBuffer(this.bufnr); + buf.unplaceSign({ group: "CocTree" }); + this._onDidChangeSelection.fire({ selection: [] }); + } + selectItem(item, forceSingle, noRedraw) { + let { nvim } = this; + if (!this.bufnr || !workspace_default.env.sign) + return; + let row = this.getItemLnum(item); + if (row == null) + return; + let buf = nvim.createBuffer(this.bufnr); + let exists = this._selection.includes(item); + if (!this.canSelectMany || forceSingle) { + this._selection = [item]; + } else if (!exists) { + this._selection.push(item); + } + nvim.pauseNotification(); + if (!this.canSelectMany || forceSingle) { + buf.unplaceSign({ group: "CocTree" }); + } + nvim.call("coc#compat#execute", [this.winid, `exe ${row + 1}`], true); + buf.placeSign({ id: signOffset + row, lnum: row + 1, name: "CocTreeSelected", group: "CocTree" }); + if (!noRedraw) + this.redraw(); + void nvim.resumeNotification(false, true); + if (!exists) + this._onDidChangeSelection.fire({ selection: this._selection }); + } + unselectItem(idx) { + let item = this._selection[idx]; + let row = this.getItemLnum(item); + if (row == null || !this.bufnr || !workspace_default.env.sign) + return; + this._selection.splice(idx, 1); + let buf = this.nvim.createBuffer(this.bufnr); + buf.unplaceSign({ group: "CocTree", id: signOffset + row }); + this._onDidChangeSelection.fire({ selection: this._selection }); + } + focusItem(element) { + if (!this.winid) + return; + let lnum = this.getItemLnum(element); + if (lnum == null) + return; + this.nvim.call("coc#compat#execute", [this.winid, `exe ${lnum + 1}`], true); + } + getElementByLnum(lnum) { + let item = this.renderedItems[lnum - this.startLnum]; + return item ? item.node : void 0; + } + getItemLnum(item) { + let idx = this.renderedItems.findIndex((o) => o.node === item); + if (idx == -1) + return void 0; + return this.startLnum + idx; + } + async getTreeItem(element) { + let exists; + let resolved = false; + let obj = this.nodesMap.get(element); + if (obj != null) { + exists = obj.item; + resolved = obj.resolved; + } + let item = await Promise.resolve(this.provider.getTreeItem(element)); + if (item.id && !exists) { + for (let obj2 of this.nodesMap.values()) { + if (obj2.item.id === item.id) { + resolved = obj2.resolved; + exists = obj2.item; + break; + } + } + } + if (exists && exists.collapsibleState != TreeItemCollapsibleState.None && item.collapsibleState != TreeItemCollapsibleState.None) { + item.collapsibleState = exists.collapsibleState; + } + this.nodesMap.set(element, { item, resolved }); + return item; + } + getRenderedLine(treeItem, lnum, level) { + let { openedIcon, closedIcon } = this.config; + const highlights = []; + const { label, deprecated, description } = treeItem; + let prefix = " ".repeat(level); + const addHighlight = (text, hlGroup) => { + let colStart = byteLength(prefix); + highlights.push({ + lnum, + hlGroup, + colStart, + colEnd: colStart + byteLength(text) + }); + }; + switch (treeItem.collapsibleState) { + case TreeItemCollapsibleState.Expanded: { + addHighlight(openedIcon, "CocTreeOpenClose"); + prefix += openedIcon + " "; + break; + } + case TreeItemCollapsibleState.Collapsed: { + addHighlight(closedIcon, "CocTreeOpenClose"); + prefix += closedIcon + " "; + break; + } + default: + prefix += this.leafIndent ? " " : ""; + } + if (treeItem.icon) { + let { text, hlGroup } = treeItem.icon; + addHighlight(text, hlGroup); + prefix += text + " "; + } + if (TreeItemLabel.is(label) && Array.isArray(label.highlights)) { + let colStart = byteLength(prefix); + for (let o of label.highlights) { + highlights.push({ + lnum, + hlGroup: "Search", + colStart: colStart + o[0], + colEnd: colStart + o[1] + }); + } + } + let labelText = typeof label === "string" ? label : label.label; + if (deprecated) { + addHighlight(labelText, "CocDeprecatedHighlight"); + } + prefix += labelText; + if (description && description.indexOf("\n") == -1) { + prefix += " "; + addHighlight(description, "CocTreeDescription"); + prefix += description; + } + return { line: prefix, highlights }; + } + async appendTreeNode(element, level, lnum, items, highlights) { + let takes = 1; + let treeItem = await this.getTreeItem(element); + let res = this.getRenderedLine(treeItem, lnum, level); + highlights.push(...res.highlights); + items.push({ level, line: res.line, node: element }); + if (treeItem.collapsibleState == TreeItemCollapsibleState.Expanded) { + let l = level + 1; + let children = await Promise.resolve(this.provider.getChildren(element)) || []; + for (let el of children) { + let n = await this.appendTreeNode(el, l, lnum + takes, items, highlights); + takes = takes + n; + } + } + return takes; + } + updateUI(lines, highlights, start = 0, end = -1, noRedraw = false) { + if (!this.bufnr) + return; + let { nvim } = this; + let buf = nvim.createBuffer(this.bufnr); + nvim.pauseNotification(); + buf.setOption("modifiable", true, true); + void buf.setLines(lines, { start, end, strictIndexing: false }, true); + if (highlights.length) { + let highlightEnd = end == -1 ? -1 : start + lines.length; + nvim.call("coc#highlight#update_highlights", [this.bufnr, highlightNamespace, highlights, start, highlightEnd], true); + } + buf.setOption("modifiable", false, true); + if (!noRedraw) + this.redraw(); + void nvim.resumeNotification(false, true); + } + async reveal(element, options = {}) { + var _a2; + if ((_a2 = this.filter) == null ? void 0 : _a2.activated) + return; + let isShown = this.getItemLnum(element) != null; + let { select, focus, expand } = options; + let curr = element; + if (typeof this.provider.getParent !== "function") { + throw new Error("missing getParent function from provider for reveal."); + } + if (!isShown) { + while (curr) { + let parentNode = await Promise.resolve(this.provider.getParent(curr)); + if (parentNode) { + let item = await this.getTreeItem(parentNode); + item.collapsibleState = TreeItemCollapsibleState.Expanded; + curr = parentNode; + } else { + break; + } + } + } + if (expand) { + let item = await this.getTreeItem(element); + if (item.collapsibleState == TreeItemCollapsibleState.None) + return; + item.collapsibleState = TreeItemCollapsibleState.Expanded; + if (typeof expand === "number" && expand > 1) { + let curr2 = Math.min(expand, 2); + let nodes = await Promise.resolve(this.provider.getChildren(element)); + while ((nodes == null ? void 0 : nodes.length) > 0) { + let arr = []; + for (let n of nodes) { + let item2 = await this.getTreeItem(n); + if (item2.collapsibleState == TreeItemCollapsibleState.None) + continue; + item2.collapsibleState = TreeItemCollapsibleState.Expanded; + if (curr2 > 1) { + let res = await Promise.resolve(this.provider.getChildren(n)); + arr.push(...res); + } + } + nodes = arr; + curr2 = curr2 - 1; + } + } + } + if (!isShown || expand) { + await this.render(); + } + if (select !== false) + this.selectItem(element); + if (focus) + this.focusItem(element); + } + updateHeadLines(initialize = false) { + let { titleCount, messageCount } = this.lineState; + let end = initialize ? -1 : titleCount + messageCount; + let lines = []; + let highlights = []; + try { + if (this.message) { + highlights.push({ hlGroup: "MoreMsg", colStart: 0, colEnd: byteLength(this.message), lnum: 0 }); + lines.push(this.message); + lines.push(""); + } + if (this.title) { + highlights.push({ hlGroup: "CocTreeTitle", colStart: 0, colEnd: byteLength(this.title), lnum: lines.length }); + if (this.description) { + let colStart = byteLength(this.title) + 1; + highlights.push({ hlGroup: "Comment", colStart, colEnd: colStart + byteLength(this.description), lnum: lines.length }); + } + lines.push(this.title + (this.description ? " " + this.description : "")); + } + this.lineState.messageCount = this.message ? 2 : 0; + this.lineState.titleCount = this.title ? 1 : 0; + this.updateUI(lines, highlights, 0, end); + if (!initialize) { + this.refreshSigns(); + } + } catch (e) { + this.nvim.errWriteLine("[coc.nvim] Error on update head lines:" + e.message); + logger26.error("Error on update head lines:", e); + } + } + refreshSigns() { + let { selection, nvim, bufnr } = this; + if (!selection.length || !bufnr || !workspace_default.env.sign) + return; + let buf = nvim.createBuffer(bufnr); + nvim.pauseNotification(); + buf.unplaceSign({ group: "CocTree" }); + for (let n of selection) { + let row = this.getItemLnum(n); + if (row == null) + continue; + buf.placeSign({ id: signOffset + row, lnum: row + 1, name: "CocTreeSelected", group: "CocTree" }); + } + void nvim.resumeNotification(false, true); + } + async render() { + if (!this.bufnr) + return; + let release = await this.mutex.acquire(); + try { + let lines = []; + let highlights = []; + let { startLnum } = this; + let nodes = await Promise.resolve(this.provider.getChildren()); + let level = 0; + let lnum = startLnum; + let renderedItems = []; + if (!(nodes == null ? void 0 : nodes.length)) { + this.message = "No results"; + } else { + for (let node of nodes) { + let n = await this.appendTreeNode(node, level, lnum, renderedItems, highlights); + lnum += n; + } + } + lines.push(...renderedItems.map((o) => o.line)); + this.renderedItems = renderedItems; + let delta = this.startLnum - startLnum; + if (delta) + highlights.forEach((o) => o.lnum = o.lnum + delta); + this.updateUI(lines, highlights, this.startLnum, -1); + this.retryTimers = 0; + release(); + } catch (e) { + this.renderedItems = []; + this.nodesMap.clear(); + this.lineState = { titleCount: 0, messageCount: 1 }; + release(); + let errMsg = `${e.message}`.replace(/\r?\n/g, " "); + this.updateUI([errMsg], [{ hlGroup: "WarningMsg", colStart: 0, colEnd: byteLength(errMsg), lnum: 0 }]); + if (this.retryTimers == 5) + return; + this.timer = setTimeout(() => { + this.retryTimers = this.retryTimers + 1; + void this.render(); + }, 500); + } + } + async show(splitCommand = "belowright 30vs") { + if (this.bufnr || this._creating) + return; + this._creating = true; + let { nvim } = this; + this.originalWin = await nvim.call("win_getid"); + let winid = await nvim.call("coc#window#find", ["cocViewId", this.viewId]); + let id = globalId; + globalId = globalId + 1; + nvim.pauseNotification(); + if (winid != -1) { + nvim.call("win_gotoid", [winid], true); + nvim.command(`silent edit +setl\\ buftype=nofile CocTree${id}`, true); + } else { + nvim.command(`silent keepalt ${splitCommand} +setl\\ buftype=nofile CocTree${id}`, true); + } + nvim.command("setl bufhidden=wipe nolist nonumber norelativenumber foldcolumn=0", true); + nvim.command(`setl signcolumn=${this.canSelectMany ? "yes" : "no"}${this.winfixwidth ? " winfixwidth" : ""}`, true); + nvim.command("setl nocursorline nobuflisted wrap undolevels=-1 filetype=coctree nomodifiable noswapfile", true); + nvim.command(`let w:cocViewId = "${this.viewId.replace(/"/g, '\\"')}"`, true); + nvim.call("bufnr", ["%"], true); + nvim.call("win_getid", [], true); + let res = await nvim.resumeNotification(); + if (res[1]) + throw new Error(`Error on buffer create:` + JSON.stringify(res[1])); + this._onDidChangeVisibility.fire({ visible: true }); + this.registerKeymaps(); + let arr = res[0]; + this.bufnr = arr[arr.length - 2]; + this.winid = arr[arr.length - 1]; + this._creating = false; + this.updateHeadLines(true); + void this.render(); + } + registerKeymaps() { + let { toggleSelection, actions, close, invoke, toggle, collapseAll, activeFilter } = this.keys; + let { nvim } = this; + const regist4 = (mode, key, fn, notify = false) => { + this.disposables.push(workspace_default.registerLocalKeymap(mode, key, async () => { + let lnum = await nvim.call("line", ["."]); + let element = this.getElementByLnum(lnum - 1); + if (element && !this.nodesMap.has(element)) + return; + await Promise.resolve(fn(element)); + }, notify)); + }; + this.disposables.push(workspace_default.registerLocalKeymap("n", "", () => { + nvim.call("win_gotoid", [this.originalWin], true); + }, true)); + regist4("n", "", async (element) => { + if (element) + await this.onClick(element); + }); + this.filter && activeFilter && regist4("n", activeFilter, async () => { + this.nvim.command(`exe ${this.startLnum}`, true); + this.filter.active(); + this.filterText = ""; + }, true); + toggleSelection && regist4("n", toggleSelection, async (element) => { + if (element) + this.toggleSelection(element); + }); + invoke && regist4("n", invoke, async (element) => { + if (element) + await this.invokeCommand(element); + }, true); + actions && regist4("n", actions, async (element) => { + if (element) + await this.invokeActions(element); + }, true); + toggle && regist4("n", toggle, async (element) => { + if (element) + await this.toggleExpand(element); + }, true); + collapseAll && regist4("n", collapseAll, async () => { + for (let obj of this.nodesMap.values()) { + let item = obj.item; + if (item.collapsibleState == TreeItemCollapsibleState.Expanded) { + item.collapsibleState = TreeItemCollapsibleState.Collapsed; + } + } + await this.render(); + }); + close && regist4("n", close, async () => { + this.hide(); + }, true); + } + hide() { + if (!this.bufnr) + return; + this.nvim.command(`bd! ${this.bufnr}`, true); + this.redraw(); + this._onDidChangeVisibility.fire({ visible: false }); + this.bufnr = void 0; + this.winid = void 0; + } + redraw() { + var _a2; + if (workspace_default.isVim || ((_a2 = this.filter) == null ? void 0 : _a2.activated)) { + this.nvim.command("redraw", true); + } + } + cancelResolve() { + if (this.resolveTokenSource) { + this.resolveTokenSource.cancel(); + this.resolveTokenSource = void 0; + } + } + dispose() { + var _a2; + if (!this.provider) + return; + if (this.timer) { + clearTimeout(this.timer); + this.timer = void 0; + } + (_a2 = this.filter) == null ? void 0 : _a2.dispose(); + this._selection = []; + this.hide(); + this.itemsToFilter = []; + this.cancelResolve(); + this.tooltipFactory.dispose(); + this.renderedItems = []; + this.nodesMap.clear(); + this.provider = void 0; + disposeAll(this.disposables); + } + }; + } +}); + +// src/window.ts +var import_fs10, import_os5, import_path13, import_vscode_languageserver_protocol16, logger27, Window, window_default; +var init_window = __esm({ + "src/window.ts"() { + import_fs10 = __toModule(require("fs")); + import_os5 = __toModule(require("os")); + import_path13 = __toModule(require("path")); + import_vscode_languageserver_protocol16 = __toModule(require_main2()); + init_esm2(); + init_channels(); + init_events(); + init_dialog(); + init_menu(); + init_notification(); + init_picker(); + init_progress(); + init_status(); + init_types(); + init_util(); + init_mutex(); + init_platform(); + init_workspace(); + logger27 = require_logger2()("window"); + Window = class { + constructor() { + this.mutex = new Mutex(); + } + get nvim() { + return workspace_default.nvim; + } + dispose() { + var _a2; + (_a2 = this.statusLine) == null ? void 0 : _a2.dispose(); + } + showMessage(msg, messageType = "more") { + if (this.mutex.busy || !this.nvim) + return; + let { messageLevel } = this; + let method = process.env.VIM_NODE_RPC == "1" ? "callTimer" : "call"; + if (global.hasOwnProperty("__TEST__")) + logger27.info(msg); + let hl = "Error"; + let level = MessageLevel.Error; + switch (messageType) { + case "more": + level = MessageLevel.More; + hl = "MoreMsg"; + break; + case "warning": + level = MessageLevel.Warning; + hl = "WarningMsg"; + break; + } + if (level >= messageLevel) { + this.nvim[method]("coc#util#echo_messages", [hl, ("[coc.nvim] " + msg).split("\n")], true); + } + } + async runTerminalCommand(cmd, cwd, keepfocus = false) { + cwd = cwd || workspace_default.cwd; + return await this.nvim.callAsync("coc#util#run_terminal", { cmd, cwd, keepfocus: keepfocus ? 1 : 0 }); + } + async openTerminal(cmd, opts = {}) { + let bufnr = await this.nvim.call("coc#util#open_terminal", __spreadValues({ cmd }, opts)); + return bufnr; + } + async showQuickpick(items, placeholder = "Choose by number") { + let release = await this.mutex.acquire(); + try { + let title = placeholder + ":"; + items = items.map((s, idx) => `${idx + 1}. ${s}`); + let res = await this.nvim.callAsync("coc#util#quickpick", [title, items.map((s) => s.trim())]); + release(); + let n = parseInt(res, 10); + if (isNaN(n) || n <= 0 || n > items.length) + return -1; + return n - 1; + } catch (e) { + release(); + return -1; + } + } + async showMenuPicker(items, title, token) { + if (workspace_default.env.dialog) { + let release = await this.mutex.acquire(); + if (token && token.isCancellationRequested) { + release(); + return -1; + } + try { + let menu = new Menu(this.nvim, { items: items.map((s) => s.trim()), title }, token); + let promise = new Promise((resolve3) => { + menu.onDidClose((selected) => { + resolve3(selected); + }); + }); + await menu.show(this.dialogPreference); + let res = await promise; + release(); + return res; + } catch (e) { + logger27.error(`Error on showMenuPicker:`, e); + release(); + } + } + return await this.showQuickpick(items); + } + async openLocalConfig() { + let { root } = workspace_default; + if (root == import_os5.default.homedir()) { + this.showMessage(`Can't create local config in home directory`, "warning"); + return; + } + let dir = import_path13.default.join(root, ".vim"); + if (!import_fs10.default.existsSync(dir)) { + let res = await this.showPrompt(`Would you like to create folder'${root}/.vim'?`); + if (!res) + return; + import_fs10.default.mkdirSync(dir); + } + await workspace_default.jumpTo(URI.file(import_path13.default.join(dir, CONFIG_FILE_NAME)).toString()); + } + async showPrompt(title) { + let release = await this.mutex.acquire(); + try { + let res = await this.nvim.callAsync("coc#float#prompt_confirm", [title]); + release(); + return res == 1; + } catch (e) { + release(); + return false; + } + } + async showDialog(config) { + if (!this.checkDialog()) + return null; + let dialog = new Dialog(this.nvim, config); + await dialog.show(this.dialogPreference); + return dialog; + } + async requestInput(title, defaultValue) { + let { nvim } = this; + const preferences = workspace_default.getConfiguration("coc.preferences"); + if (workspace_default.env.dialog && preferences.get("promptInput", true) && !isWindows2) { + let release = await this.mutex.acquire(); + let preferences2 = this.dialogPreference; + try { + let opts = {}; + if (preferences2.floatHighlight) + opts.highlight = preferences2.floatHighlight; + if (preferences2.floatBorderHighlight) + opts.borderhighlight = preferences2.floatBorderHighlight; + let arr = await nvim.call("coc#float#create_prompt_win", [title, defaultValue || "", opts]); + let [bufnr, winid] = arr; + let res = await new Promise((resolve3) => { + let disposables = []; + events_default.on("BufWinLeave", (nr) => { + if (nr == bufnr) { + disposeAll(disposables); + resolve3(null); + } + }, null, disposables); + events_default.on("PromptInsert", async (value) => { + disposeAll(disposables); + await nvim.call("coc#float#close", [winid]); + if (!value) { + this.showMessage("Empty word, canceled", "warning"); + resolve3(null); + } else { + resolve3(value); + } + }, null, disposables); + }); + release(); + return res; + } catch (e) { + logger27.error("Error on requestInput:", e); + release(); + } + } else { + let res = await workspace_default.callAsync("input", [title + ": ", defaultValue || ""]); + nvim.command("normal! :", true); + if (!res) { + this.showMessage("Empty word, canceled", "warning"); + return null; + } + return res; + } + } + createStatusBarItem(priority = 0, option = {}) { + if (!workspace_default.env) { + let fn = () => { + }; + return { text: "", show: fn, dispose: fn, hide: fn, priority: 0, isProgress: false }; + } + if (!this.statusLine) { + this.statusLine = new StatusLine(this.nvim); + } + return this.statusLine.createStatusBarItem(priority, option.progress || false); + } + createOutputChannel(name2) { + return channels_default.create(name2, this.nvim); + } + showOutputChannel(name2, preserveFocus) { + channels_default.show(name2, preserveFocus); + } + async echoLines(lines, truncate = false) { + let { nvim } = this; + let cmdHeight = workspace_default.env.cmdheight; + if (lines.length > cmdHeight && truncate) { + lines = lines.slice(0, cmdHeight); + } + let maxLen = workspace_default.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} ...`; + } + await nvim.call("coc#util#echo_lines", [lines]); + } + async getCursorPosition() { + let [line, content] = await this.nvim.eval(`[line('.')-1, strpart(getline('.'), 0, col('.') - 1)]`); + return import_vscode_languageserver_protocol16.Position.create(line, content.length); + } + async moveTo(position) { + await this.nvim.call("coc#cursor#move_to", [position.line, position.character]); + if (workspace_default.env.isVim) + this.nvim.command("redraw", true); + } + async getOffset() { + return await this.nvim.call("coc#cursor#char_offset"); + } + async getCursorScreenPosition() { + let [row, col] = await this.nvim.call("coc#cursor#screen_pos"); + return { row, col }; + } + async showPickerDialog(items, title, token) { + if (!this.checkDialog()) + return void 0; + let release = await this.mutex.acquire(); + if (token && token.isCancellationRequested) { + release(); + return void 0; + } + try { + let useString = typeof items[0] === "string"; + let picker = new Picker(this.nvim, { + title, + items: useString ? items.map((s) => { + return { label: s }; + }) : items + }, token); + let promise = new Promise((resolve3) => { + picker.onDidClose((selected) => { + resolve3(selected); + }); + }); + await picker.show(this.dialogPreference); + let picked = await promise; + let res = picked == void 0 ? void 0 : items.filter((_, i) => picked.includes(i)); + release(); + return res; + } catch (e) { + logger27.error(`Error on showPickerDialog:`, e); + release(); + } + } + async showInformationMessage(message, ...items) { + if (!this.enableMessageDialog) + return await this.showConfirm(message, items, "Info"); + let texts = typeof items[0] === "string" ? items : items.map((s) => s.title); + let idx = await this.createNotification("CocInfoFloat", message, texts); + return idx == -1 ? void 0 : items[idx]; + } + async showWarningMessage(message, ...items) { + if (!this.enableMessageDialog) + return await this.showConfirm(message, items, "Warning"); + let texts = typeof items[0] === "string" ? items : items.map((s) => s.title); + let idx = await this.createNotification("CocWarningFloat", message, texts); + return idx == -1 ? void 0 : items[idx]; + } + async showErrorMessage(message, ...items) { + if (!this.enableMessageDialog) + return await this.showConfirm(message, items, "Error"); + let texts = typeof items[0] === "string" ? items : items.map((s) => s.title); + let idx = await this.createNotification("CocErrorFloat", message, texts); + return idx == -1 ? void 0 : items[idx]; + } + async showNotification(config) { + if (!this.checkDialog()) + return false; + let notification = new Notification(this.nvim, config); + return await notification.show(this.notificationPreference); + } + async showConfirm(message, items, kind) { + if (!items || items.length == 0) { + let msgType = kind == "Info" ? "more" : kind == "Error" ? "error" : "warning"; + this.showMessage(message, msgType); + return void 0; + } + let titles = typeof items[0] === "string" ? items.slice() : items.map((o) => o.title); + let choices = titles.map((s, i) => `${i + 1}${s}`); + let res = await this.nvim.callAsync("coc#util#with_callback", ["confirm", [message, choices.join("\n"), 0, kind]]); + return items[res - 1]; + } + async withProgress(options, task) { + if (!this.checkDialog()) + return void 0; + let progress = new ProgressNotification(this.nvim, { + task, + title: options.title, + cancellable: options.cancellable + }); + return await progress.show(this.notificationPreference); + } + createTreeView(viewId, options) { + const BasicTreeView2 = (init_TreeView(), TreeView_exports).default; + return new BasicTreeView2(viewId, options); + } + createNotification(borderhighlight, message, items) { + return new Promise((resolve3) => { + let config = { + content: message, + borderhighlight, + close: true, + buttons: items.map((s, index) => { + return { text: s, index }; + }), + callback: (idx) => { + resolve3(idx); + } + }; + let notification = new Notification(this.nvim, config); + notification.show(this.notificationPreference).then((shown) => { + if (!shown) { + logger27.error("Unable to open notification window"); + resolve3(-1); + } + if (!items.length) + resolve3(-1); + }, (e) => { + logger27.error("Unable to open notification window", e); + resolve3(-1); + }); + }); + } + get dialogPreference() { + let config = workspace_default.getConfiguration("dialog"); + return { + maxWidth: config.get("maxWidth"), + maxHeight: config.get("maxHeight"), + floatHighlight: config.get("floatHighlight"), + floatBorderHighlight: config.get("floatBorderHighlight"), + pickerButtons: config.get("pickerButtons"), + pickerButtonShortcut: config.get("pickerButtonShortcut"), + confirmKey: config.get("confirmKey") + }; + } + get notificationPreference() { + let config = workspace_default.getConfiguration("notification"); + return { + top: config.get("marginTop"), + right: config.get("marginRight"), + maxWidth: config.get("maxWidth"), + maxHeight: config.get("maxHeight"), + highlight: config.get("highlightGroup"), + minProgressWidth: config.get("minProgressWidth") + }; + } + checkDialog() { + if (workspace_default.env.dialog) + return true; + this.showMessage("Dialog requires vim >= 8.2.0750 or neovim >= 0.4.0, please upgrade your vim", "warning"); + return false; + } + get enableMessageDialog() { + if (!workspace_default.env.dialog) + return false; + let config = workspace_default.getConfiguration("coc.preferences"); + return config.get("enableMessageDialog", false); + } + get messageLevel() { + let config = workspace_default.getConfiguration("coc.preferences"); + let level = config.get("messageLevel", "more"); + switch (level) { + case "error": + return MessageLevel.Error; + case "warning": + return MessageLevel.Warning; + default: + return MessageLevel.More; + } + } + }; + window_default = new Window(); + } +}); + +// src/diagnostic/util.ts +function getSeverityName(severity) { + switch (severity) { + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Warning: + return "Warning"; + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Information: + return "Information"; + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Hint: + return "Hint"; + default: + return "Error"; + } +} +function getSeverityType(severity) { + switch (severity) { + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Warning: + return "W"; + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Information: + return "I"; + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Hint: + return "I"; + default: + return "E"; + } +} +function severityLevel(level) { + switch (level) { + case "hint": + return import_vscode_languageserver_protocol17.DiagnosticSeverity.Hint; + case "information": + return import_vscode_languageserver_protocol17.DiagnosticSeverity.Information; + case "warning": + return import_vscode_languageserver_protocol17.DiagnosticSeverity.Warning; + case "error": + return import_vscode_languageserver_protocol17.DiagnosticSeverity.Error; + default: + return import_vscode_languageserver_protocol17.DiagnosticSeverity.Hint; + } +} +function getNameFromSeverity(severity) { + switch (severity) { + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Error: + return "CocError"; + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Warning: + return "CocWarning"; + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Information: + return "CocInfo"; + case import_vscode_languageserver_protocol17.DiagnosticSeverity.Hint: + return "CocHint"; + default: + return "CocError"; + } +} +function getLocationListItem(bufnr, diagnostic) { + let { start, end } = diagnostic.range; + let owner = diagnostic.source || "coc.nvim"; + let msg = diagnostic.message.split("\n")[0]; + let type = getSeverityName(diagnostic.severity).slice(0, 1).toUpperCase(); + return { + bufnr, + lnum: start.line + 1, + end_lnum: end.line + 1, + col: start.character + 1, + end_col: end.character + 1, + text: `[${owner}${diagnostic.code ? " " + diagnostic.code : ""}] ${msg} [${type}]`, + type + }; +} +var import_vscode_languageserver_protocol17; +var init_util3 = __esm({ + "src/diagnostic/util.ts"() { + import_vscode_languageserver_protocol17 = __toModule(require_main2()); + } +}); + +// src/diagnostic/buffer.ts +function sortDiagnostics(a, b) { + if ((a.severity || 1) != (b.severity || 1)) { + return (a.severity || 1) - (b.severity || 1); + } + let d = comparePosition(a.range.start, b.range.start); + if (d != 0) + return d; + return a.source > b.source ? 1 : -1; +} +function getHighlightGroup(diagnostic) { + let tags = diagnostic.tags || []; + if (tags.includes(import_vscode_languageserver_protocol18.DiagnosticTag.Deprecated)) { + return DiagnosticHighlight.Deprecated; + } + if (tags.includes(import_vscode_languageserver_protocol18.DiagnosticTag.Unnecessary)) { + return DiagnosticHighlight.Unused; + } + switch (diagnostic.severity) { + case import_vscode_languageserver_protocol18.DiagnosticSeverity.Warning: + return DiagnosticHighlight.Warning; + case import_vscode_languageserver_protocol18.DiagnosticSeverity.Information: + return DiagnosticHighlight.Information; + case import_vscode_languageserver_protocol18.DiagnosticSeverity.Hint: + return DiagnosticHighlight.Hint; + default: + return DiagnosticHighlight.Error; + } +} +var import_vscode_languageserver_protocol18, isVim5, logger28, signGroup, highlightNamespace2, hlGroups, DiagnosticHighlight, DiagnosticBuffer; +var init_buffer = __esm({ + "src/diagnostic/buffer.ts"() { + init_mutex(); + import_vscode_languageserver_protocol18 = __toModule(require_main2()); + init_object(); + init_position(); + init_workspace(); + init_events(); + init_util3(); + isVim5 = process.env.VIM_NODE_RPC == "1"; + logger28 = require_logger2()("diagnostic-buffer"); + signGroup = "CocDiagnostic"; + highlightNamespace2 = "diagnostic"; + hlGroups = ["CocErrorHighlight", "CocWarningHighlight", "CocInfoHighlight", "CocHintHighlight", "CocDeprecatedHighlight", "CocUnusedHighlight"]; + (function(DiagnosticHighlight2) { + DiagnosticHighlight2["Error"] = "CocErrorHighlight"; + DiagnosticHighlight2["Warning"] = "CocWarningHighlight"; + DiagnosticHighlight2["Information"] = "CocInfoHighlight"; + DiagnosticHighlight2["Hint"] = "CocHintHighlight"; + DiagnosticHighlight2["Deprecated"] = "CocDeprecatedHighlight"; + DiagnosticHighlight2["Unused"] = "CocUnusedHighlight"; + })(DiagnosticHighlight || (DiagnosticHighlight = {})); + DiagnosticBuffer = class { + constructor(nvim, bufnr, uri, config, onRefresh) { + this.nvim = nvim; + this.bufnr = bufnr; + this.uri = uri; + this.config = config; + this.onRefresh = onRefresh; + this.diagnosticsMap = new Map(); + this.mutex = new Mutex(); + this._disposed = false; + } + get displayByAle() { + return this.config.displayByAle; + } + clearHighlight(collection) { + this.buffer.clearNamespace(highlightNamespace2 + collection); + } + clearSigns(collection) { + this.buffer.unplaceSign({ group: signGroup + collection }); + } + get diagnostics() { + let res = []; + for (let diags of this.diagnosticsMap.values()) { + res.push(...diags); + } + return res; + } + get buffer() { + return this.nvim.createBuffer(this.bufnr); + } + refreshAle(collection, diagnostics) { + let aleItems = diagnostics.map((o) => { + let range = o.range; + 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: getSeverityType(o.severity) + }; + }); + let method = global.hasOwnProperty("__TEST__") ? "MockAleResults" : "ale#other_source#ShowResults"; + this.nvim.call(method, [this.bufnr, "coc" + collection, aleItems], true); + } + async refresh(diagnosticsMap, force) { + let release = await this.mutex.acquire(); + try { + await this._refresh(diagnosticsMap, force === true); + release(); + } catch (e) { + release(); + this.nvim.echoError(e); + } + } + async _refresh(diagnosticsMap, force) { + let { refreshOnInsertMode } = this.config; + let { nvim } = this; + let checkInsert = !this.displayByAle && !refreshOnInsertMode; + if (events_default.insertMode && checkInsert) + return; + let info = await nvim.call("coc#util#diagnostic_info", [this.bufnr, checkInsert]); + if (!info || this._disposed) + return; + if (this.displayByAle) { + nvim.pauseNotification(); + for (let [collection, diagnostics] of Object.entries(diagnosticsMap)) { + this.diagnosticsMap.set(collection, []); + this.refreshAle(collection, diagnostics); + } + await nvim.resumeNotification(); + } else { + let changed = false; + let redraw = false; + nvim.pauseNotification(); + for (let [collection, diagnostics] of Object.entries(diagnosticsMap)) { + let prev = this.diagnosticsMap.get(collection) || []; + this.diagnosticsMap.set(collection, diagnostics); + if (!equals(prev, diagnostics)) { + changed = true; + redraw = true; + this.addSigns(collection, diagnostics); + this.updateHighlights(collection, diagnostics); + } else if (prev.length && force) { + redraw = true; + this.updateHighlights(collection, diagnostics); + } + } + if (changed) { + this.showVirtualText(info.lnum, info.bufnr); + this.updateLocationList(info.winid, info.locationlist); + this.setDiagnosticInfo(); + } + if (isVim5 && redraw) + this.nvim.command("redraw", true); + await this.nvim.resumeNotification(); + } + this.onRefresh(this.diagnostics); + } + updateLocationList(winid, title) { + if (!this.config.locationlistUpdate || winid == -1 || title !== "Diagnostics of coc") + return; + let items = []; + let { diagnostics } = this; + diagnostics.sort(sortDiagnostics); + for (let diagnostic of diagnostics) { + let item = getLocationListItem(this.bufnr, diagnostic); + items.push(item); + } + this.nvim.call("setloclist", [winid, [], "r", { title: "Diagnostics of coc", items }], true); + } + addSigns(collection, diagnostics) { + if (!this.config.enableSign) + return; + let group2 = signGroup + collection; + this.buffer.unplaceSign({ group: group2 }); + let signsMap = new Map(); + for (let diagnostic of diagnostics) { + let { range, severity } = diagnostic; + let line = range.start.line; + let exists = signsMap.get(line) || []; + if (exists.includes(severity)) { + continue; + } + exists.push(severity); + signsMap.set(line, exists); + let priority = this.config.signPriority + 4 - severity; + let name2 = getNameFromSeverity(severity); + this.buffer.placeSign({ name: name2, lnum: line + 1, group: group2, priority }); + } + } + setDiagnosticInfo() { + let lnums = [0, 0, 0, 0]; + let info = { error: 0, warning: 0, information: 0, hint: 0, lnums }; + for (let diagnostics of this.diagnosticsMap.values()) { + for (let diagnostic of diagnostics) { + let lnum = diagnostic.range.start.line + 1; + switch (diagnostic.severity) { + case import_vscode_languageserver_protocol18.DiagnosticSeverity.Warning: + info.warning = info.warning + 1; + lnums[1] = lnums[1] ? Math.min(lnums[1], lnum) : lnum; + break; + case import_vscode_languageserver_protocol18.DiagnosticSeverity.Information: + info.information = info.information + 1; + lnums[2] = lnums[2] ? Math.min(lnums[2], lnum) : lnum; + break; + case import_vscode_languageserver_protocol18.DiagnosticSeverity.Hint: + info.hint = info.hint + 1; + lnums[3] = lnums[3] ? Math.min(lnums[3], lnum) : lnum; + break; + default: + lnums[0] = lnums[0] ? Math.min(lnums[0], lnum) : lnum; + info.error = info.error + 1; + } + } + } + let buf = this.nvim.createBuffer(this.bufnr); + buf.setVar("coc_diagnostic_info", info, true); + this.nvim.call("coc#util#do_autocmd", ["CocDiagnosticChange"], true); + } + showVirtualText(lnum, bufnr) { + if (!this.config.virtualText) + return; + let { virtualTextSrcId, virtualTextPrefix, virtualTextCurrentLineOnly } = this.config; + let { diagnostics, buffer } = this; + if (virtualTextCurrentLineOnly) { + if (bufnr && this.bufnr != bufnr) + return; + diagnostics = diagnostics.filter((d) => { + let { start, end } = d.range; + return start.line <= lnum - 1 && end.line >= lnum - 1; + }); + } + diagnostics.sort(sortDiagnostics); + buffer.clearNamespace(virtualTextSrcId); + for (let i = diagnostics.length - 1; i >= 0; i--) { + let diagnostic = diagnostics[i]; + let { line } = diagnostic.range.start; + let highlight = 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); + void buffer.setVirtualText(virtualTextSrcId, line, [[virtualTextPrefix + msg, highlight]], {}); + } + } + updateHighlights(collection, diagnostics) { + if (!diagnostics.length) { + this.clearHighlight(collection); + } else { + let items = this.getHighlightItems(diagnostics); + this.buffer.updateHighlights(highlightNamespace2 + collection, items); + } + } + getHighlightItems(diagnostics) { + let doc = workspace_default.getDocument(this.bufnr); + if (!doc) + return []; + let res = []; + for (let diagnostic of diagnostics.slice(0, this.config.highlighLimit)) { + let hlGroup = getHighlightGroup(diagnostic); + doc.addHighlights(res, hlGroup, diagnostic.range); + } + res.sort((a, b) => { + if (a.lnum != b.lnum) + return a.lnum - b.lnum; + if (a.colStart != b.colStart) + return a.colStart - b.colStart; + return hlGroups.indexOf(b.hlGroup) - hlGroups.indexOf(a.hlGroup); + }); + return res; + } + clear() { + let { nvim } = this; + let collections = Array.from(this.diagnosticsMap.keys()); + this.diagnosticsMap.clear(); + if (this.displayByAle) { + for (let collection of collections) { + let method = global.hasOwnProperty("__TEST__") ? "MockAleResults" : "ale#other_source#ShowResults"; + this.nvim.call(method, [this.bufnr, collection, []], true); + } + } else { + nvim.pauseNotification(); + for (let collection of collections) { + this.clearHighlight(collection); + this.clearSigns(collection); + } + if (this.config.virtualText) { + this.buffer.clearNamespace(this.config.virtualTextSrcId); + } + this.buffer.deleteVar("coc_diagnostic_info"); + void nvim.resumeNotification(false, true); + } + } + getDiagnosticsAt(pos, checkCurrentLine) { + let diagnostics = []; + for (let diags of this.diagnosticsMap.values()) { + if (checkCurrentLine) { + diagnostics.push(...diags.filter((o) => lineInRange(pos.line, o.range))); + } else { + diagnostics.push(...diags.filter((o) => positionInRange(pos, o.range) == 0)); + } + } + diagnostics.sort(sortDiagnostics); + return diagnostics; + } + async isEnabled() { + if (this._disposed) + return false; + let buf = this.nvim.createBuffer(this.bufnr); + let res = await buf.getVar("coc_diagnostic_disable"); + return res != 1; + } + dispose() { + this._disposed = true; + this.clear(); + } + }; + } +}); + +// src/diagnostic/collection.ts +var import_vscode_languageserver_protocol19, logger29, DiagnosticCollection; +var init_collection = __esm({ + "src/diagnostic/collection.ts"() { + import_vscode_languageserver_protocol19 = __toModule(require_main2()); + init_esm2(); + init_workspace(); + logger29 = require_logger2()("diagnostic-collection"); + DiagnosticCollection = class { + constructor(name2, onDispose) { + this.name = name2; + this.onDispose = onDispose; + this.diagnosticsMap = new Map(); + this._onDidDiagnosticsChange = new import_vscode_languageserver_protocol19.Emitter(); + this.onDidDiagnosticsChange = this._onDidDiagnosticsChange.event; + } + set(entries, diagnostics) { + let diagnosticsPerFile = new Map(); + if (!Array.isArray(entries)) { + let doc = workspace_default.getDocument(entries); + let uri = doc ? doc.uri : entries; + diagnosticsPerFile.set(uri, diagnostics || []); + } else { + for (let item of entries) { + let [uri, diagnostics2] = item; + let doc = workspace_default.getDocument(uri); + uri = doc ? doc.uri : uri; + if (diagnostics2 == null) { + diagnostics2 = []; + } else { + diagnostics2 = (diagnosticsPerFile.get(uri) || []).concat(diagnostics2); + } + diagnosticsPerFile.set(uri, diagnostics2); + } + } + for (let item of diagnosticsPerFile) { + let [uri, diagnostics2] = item; + uri = URI.parse(uri).toString(); + diagnostics2.forEach((o) => { + o.range = o.range || import_vscode_languageserver_protocol19.Range.create(0, 0, 0, 0); + o.message = o.message || ""; + o.source = o.source || this.name; + }); + this.diagnosticsMap.set(uri, diagnostics2); + this._onDidDiagnosticsChange.fire(uri); + } + } + delete(uri) { + this.diagnosticsMap.delete(uri); + this._onDidDiagnosticsChange.fire(uri); + } + clear() { + let uris = this.diagnosticsMap.keys(); + this.diagnosticsMap.clear(); + for (let uri of uris) { + this._onDidDiagnosticsChange.fire(uri); + } + } + 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(); + if (this.onDispose) + this.onDispose(); + this._onDidDiagnosticsChange.dispose(); + } + }; + } +}); + +// src/diagnostic/manager.ts +var import_debounce4, import_vscode_languageserver_protocol20, logger30, DiagnosticManager, manager_default; +var init_manager = __esm({ + "src/diagnostic/manager.ts"() { + import_debounce4 = __toModule(require_debounce()); + import_vscode_languageserver_protocol20 = __toModule(require_main2()); + init_esm2(); + init_events(); + init_floatFactory(); + init_util(); + init_position(); + init_window(); + init_workspace(); + init_buffer(); + init_collection(); + init_util3(); + logger30 = require_logger2()("diagnostic-manager"); + DiagnosticManager = class { + constructor() { + this.enabled = true; + this._onDidRefresh = new import_vscode_languageserver_protocol20.Emitter(); + this.onDidRefresh = this._onDidRefresh.event; + this.collections = []; + this.disposables = []; + } + init() { + this.setConfiguration(); + workspace_default.onDidChangeConfiguration((e) => { + this.setConfiguration(e); + }, null, this.disposables); + this.floatFactory = new FloatFactory(this.nvim); + this.buffers = workspace_default.registerBufferSync((doc) => { + if (doc.buftype !== "") + return void 0; + let buf = new DiagnosticBuffer(this.nvim, doc.bufnr, doc.uri, this.config, (diagnostics) => { + this._onDidRefresh.fire({ diagnostics, uri: buf.uri, bufnr: buf.bufnr }); + if (["never", "jump"].includes(this.config.enableMessage)) + return; + if (events_default.insertMode) + return; + this.echoMessage(true).logError(); + }); + let collections = this.getCollections(doc.uri); + if (this.enabled && collections.length) { + let diagnostics = this.getDiagnostics(doc.uri); + void buf.refresh(diagnostics); + } + return buf; + }); + workspace_default.onDidCloseTextDocument((e) => { + for (let collection of this.collections) { + collection.delete(e.uri); + } + }, null, this.disposables); + events_default.on("CursorMoved", (bufnr) => { + if (this.config.enableMessage != "always") + return; + if (!this.buffers.getItem(bufnr)) + return; + if (this.timer) + clearTimeout(this.timer); + this.timer = setTimeout(async () => { + await this.echoMessage(true); + }, this.config.messageDelay); + }, null, this.disposables); + let fn = (0, import_debounce4.default)((bufnr, cursor) => { + if (!this.config.virtualTextCurrentLineOnly) + return; + let buf = this.buffers.getItem(bufnr); + if (buf) + buf.showVirtualText(cursor[0]); + }, 100); + events_default.on("CursorMoved", fn, null, this.disposables); + this.disposables.push(import_vscode_languageserver_protocol20.Disposable.create(() => { + fn.clear(); + })); + let timer; + events_default.on("InsertLeave", async (bufnr) => { + if (this.config.refreshOnInsertMode || !this.autoRefresh) + return; + let doc = workspace_default.getDocument(bufnr); + if (!(doc == null ? void 0 : doc.attached)) + return; + doc._forceSync(); + timer = setTimeout(() => { + if (events_default.insertMode) + return; + for (let buf of this.buffers.items) { + void buf.refresh(this.getDiagnostics(buf.uri), false); + } + }, Math.max(0, 500 - Date.now() + events_default.lastChangeTs)); + }, null, this.disposables); + let clear = () => { + if (timer) + clearTimeout(timer); + }; + this.disposables.push({ dispose: clear }); + events_default.on("InsertEnter", clear, null, this.disposables); + events_default.on("BufEnter", async () => { + if (this.timer) + clearTimeout(this.timer); + }, null, this.disposables); + let errorItems = workspace_default.configurations.errorItems; + this.setConfigurationErrors(errorItems); + workspace_default.configurations.onError((items) => { + this.setConfigurationErrors(items); + }, null, this.disposables); + } + defineSigns() { + let { nvim } = this; + let { enableHighlightLineNumber, enableSign } = this.config; + if (!enableSign) + return; + nvim.pauseNotification(); + for (let kind of ["Error", "Warning", "Info", "Hint"]) { + let signText = this.config[kind.toLowerCase() + "Sign"]; + let cmd = `sign define Coc${kind} linehl=Coc${kind}Line`; + if (signText) + cmd += ` texthl=Coc${kind}Sign text=${signText}`; + if (enableHighlightLineNumber) + cmd += ` numhl=Coc${kind}Sign`; + nvim.command(cmd, true); + } + void nvim.resumeNotification(false, true); + } + async setLocationlist(bufnr) { + let buf = this.buffers.getItem(bufnr); + let diagnosticsMap = buf ? this.getDiagnostics(buf.uri) : {}; + let items = []; + for (let diagnostics of Object.values(diagnosticsMap)) { + for (let diagnostic of diagnostics) { + let item = getLocationListItem(bufnr, diagnostic); + items.push(item); + } + } + let curr = await this.nvim.call("getloclist", [0, { title: 1 }]); + let action = curr.title && curr.title.indexOf("Diagnostics of coc") != -1 ? "r" : " "; + await this.nvim.call("setloclist", [0, [], action, { title: "Diagnostics of coc", items }]); + } + setConfigurationErrors(errorItems) { + let collection = this.create("config"); + if (errorItems == null ? void 0 : errorItems.length) { + let entries = new Map(); + for (let item of errorItems) { + let { uri } = item.location; + let diagnostics = entries.get(uri) || []; + diagnostics.push(import_vscode_languageserver_protocol20.Diagnostic.create(item.location.range, item.message, import_vscode_languageserver_protocol20.DiagnosticSeverity.Error)); + entries.set(uri, diagnostics); + } + collection.set(Array.from(entries)); + } else { + collection.clear(); + } + } + create(name2) { + let collection = this.getCollectionByName(name2); + if (collection) + return collection; + collection = new DiagnosticCollection(name2, () => { + let idx = this.collections.findIndex((o) => o == collection); + if (idx !== -1) + this.collections.splice(idx, 1); + }); + this.collections.push(collection); + collection.onDidDiagnosticsChange((uri) => { + let buf = this.buffers.getItem(uri); + if (!this.autoRefresh || !buf) + return; + if (events_default.insertMode && !this.config.refreshOnInsertMode) + return; + void buf.refresh(this.getDiagnostics(uri, name2), true); + }); + return collection; + } + getSortedRanges(uri, severity) { + let collections = this.getCollections(uri); + let res = []; + let level = severity ? severityLevel(severity) : 0; + for (let collection of collections) { + let diagnostics = collection.get(uri); + if (level) { + diagnostics = diagnostics.filter((o) => o.severity == level); + } else { + let minLevel = this.config.level; + if (minLevel && minLevel < import_vscode_languageserver_protocol20.DiagnosticSeverity.Hint) { + diagnostics = diagnostics.filter((o) => { + if (o.severity && o.severity > minLevel) { + return false; + } + return true; + }); + } + } + 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; + } + getDiagnostics(uri, collection) { + let res = {}; + let collections = collection ? [this.getCollectionByName(collection)] : this.getCollections(uri); + let { level, showUnused, showDeprecated } = this.config; + for (let collection2 of collections) { + if (!collection2) + continue; + let items = collection2.get(uri) || []; + if (items.length) { + items = items.filter((d) => { + var _a2, _b; + if (level && d.severity && d.severity > level) { + return false; + } + if (!showUnused && ((_a2 = d.tags) == null ? void 0 : _a2.includes(import_vscode_languageserver_protocol20.DiagnosticTag.Unnecessary))) { + return false; + } + if (!showDeprecated && ((_b = d.tags) == null ? void 0 : _b.includes(import_vscode_languageserver_protocol20.DiagnosticTag.Deprecated))) { + return false; + } + return true; + }); + items.sort((a, b) => { + return comparePosition(a.range.start, b.range.start); + }); + } + res[collection2.name] = items; + } + return res; + } + getDiagnosticsInRange(document2, range) { + let collections = this.getCollections(document2.uri); + let res = []; + for (let collection of collections) { + let items = collection.get(document2.uri); + if (!items) + continue; + for (let item of items) { + if (rangeIntersect(item.range, range)) { + res.push(item); + } + } + } + return res; + } + async preview() { + let diagnostics = await this.getCurrentDiagnostics(); + if (diagnostics.length == 0) { + this.nvim.command("pclose", true); + return; + } + let lines = []; + for (let diagnostic of diagnostics) { + let { source, code, severity, message } = diagnostic; + let s = getSeverityName(severity)[0]; + lines.push(`[${source}${code ? " " + code : ""}] [${s}]`); + lines.push(...message.split(/\r?\n/)); + lines.push(""); + } + this.nvim.call("coc#util#preview_info", [lines, "txt"], true); + } + async jumpPrevious(severity) { + let buffer = await this.nvim.buffer; + let document2 = workspace_default.getDocument(buffer.id); + if (!document2) + return; + let curpos = await window_default.getCursorPosition(); + let ranges = this.getSortedRanges(document2.uri, severity); + let pos; + for (let i = ranges.length - 1; i >= 0; i--) { + let end = ranges[i].end; + if (comparePosition(end, curpos) < 0) { + pos = ranges[i].start; + break; + } else if (i == 0) { + let wrapscan = await this.nvim.getOption("wrapscan"); + if (wrapscan) + pos = ranges[ranges.length - 1].start; + } + } + if (pos) { + await window_default.moveTo(pos); + if (this.config.enableMessage == "never") + return; + await this.echoMessage(false); + } + } + async jumpNext(severity) { + let buffer = await this.nvim.buffer; + let document2 = workspace_default.getDocument(buffer.id); + let curpos = await window_default.getCursorPosition(); + let ranges = this.getSortedRanges(document2.uri, severity); + let pos; + for (let i = 0; i <= ranges.length - 1; i++) { + let start = ranges[i].start; + if (comparePosition(start, curpos) > 0) { + pos = ranges[i].start; + break; + } else if (i == ranges.length - 1) { + let wrapscan = await this.nvim.getOption("wrapscan"); + if (wrapscan) + pos = ranges[0].start; + } + } + if (pos) { + await window_default.moveTo(pos); + if (this.config.enableMessage == "never") + return; + await this.echoMessage(false); + } + } + getDiagnosticList() { + let res = []; + const { level, showUnused, showDeprecated } = this.config; + for (let collection of this.collections) { + collection.forEach((uri, diagnostics) => { + var _a2, _b; + let file = URI.parse(uri).fsPath; + for (let diagnostic of diagnostics) { + if (diagnostic.severity && diagnostic.severity > level) { + continue; + } + if (!showUnused && ((_a2 = diagnostic.tags) == null ? void 0 : _a2.includes(import_vscode_languageserver_protocol20.DiagnosticTag.Unnecessary))) { + continue; + } + if (!showDeprecated && ((_b = diagnostic.tags) == null ? void 0 : _b.includes(import_vscode_languageserver_protocol20.DiagnosticTag.Deprecated))) { + continue; + } + let { start, end } = diagnostic.range; + let o = { + file, + lnum: start.line + 1, + end_lnum: end.line + 1, + col: start.character + 1, + end_col: end.character + 1, + code: diagnostic.code, + source: diagnostic.source || collection.name, + message: diagnostic.message, + severity: getSeverityName(diagnostic.severity), + level: diagnostic.severity || 0, + location: import_vscode_languageserver_protocol20.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; + } + getDiagnosticsAt(bufnr, cursor, atEnd = false, lastline = false) { + let buffer = this.buffers.getItem(bufnr); + if (!buffer) + return []; + let pos = import_vscode_languageserver_protocol20.Position.create(cursor[0], cursor[1]); + let res = buffer.getDiagnosticsAt(pos, this.config.checkCurrentLine); + if (this.config.checkCurrentLine || res.length) + return res; + if (atEnd) { + pos = import_vscode_languageserver_protocol20.Position.create(cursor[0], cursor[1] + 1); + res = buffer.getDiagnosticsAt(pos, false); + if (res.length) + return res; + } + if (lastline && cursor[1] == 0) { + pos = import_vscode_languageserver_protocol20.Position.create(cursor[0] + 1, 0); + res = buffer.getDiagnosticsAt(pos, false); + } + return res; + } + async getCurrentDiagnostics() { + let [bufnr, cursor, eol, lastline] = await this.nvim.eval(`[bufnr("%"),coc#cursor#position(),col('.')==col('$')-1,line('.')==line('$')]`); + return this.getDiagnosticsAt(bufnr, cursor, eol == 1, lastline == 1); + } + async echoMessage(truncate = false) { + const config = this.config; + if (!this.enabled || config.displayByAle) + return; + if (this.timer) + clearTimeout(this.timer); + let useFloat = config.messageTarget == "float"; + let [filetype, mode] = await this.nvim.eval(`[&filetype,mode()]`); + if (mode != "n") + return; + let diagnostics = await this.getCurrentDiagnostics(); + if (diagnostics.length == 0) { + if (useFloat) + this.floatFactory.close(); + return; + } + if (truncate && workspace_default.insertMode) + return; + let docs = []; + let ft = ""; + if (Object.keys(config.filetypeMap).length > 0) { + const defaultFiletype = config.filetypeMap["default"] || ""; + ft = config.filetypeMap[filetype] || (defaultFiletype == "bufferType" ? filetype : defaultFiletype); + } + diagnostics.forEach((diagnostic) => { + let { source, code, severity, message } = diagnostic; + let s = getSeverityName(severity)[0]; + const codeStr = code ? " " + code : ""; + const str = config.format.replace("%source", source).replace("%code", codeStr).replace("%severity", s).replace("%message", message); + let filetype2 = "Error"; + if (ft === "") { + switch (severity) { + case import_vscode_languageserver_protocol20.DiagnosticSeverity.Hint: + filetype2 = "Hint"; + break; + case import_vscode_languageserver_protocol20.DiagnosticSeverity.Warning: + filetype2 = "Warning"; + break; + case import_vscode_languageserver_protocol20.DiagnosticSeverity.Information: + filetype2 = "Info"; + break; + } + } else { + filetype2 = ft; + } + docs.push({ filetype: filetype2, content: str }); + }); + if (useFloat) { + let config2 = this.floatFactory.applyFloatConfig({ modes: ["n"], maxWidth: 80 }, this.config.floatConfig); + await this.floatFactory.show(docs, config2); + } else { + let lines = docs.map((d) => d.content).join("\n").split(/\r?\n/); + if (lines.length) { + await this.nvim.command('echo ""'); + await window_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_default.jumpTo(locations[0].uri, locations[0].range.start); + } else if (locations.length > 1) { + await workspace_default.showLocations(locations); + } + } + reset() { + if (this.timer) { + clearTimeout(this.timer); + } + this.buffers.reset(); + for (let collection of this.collections) { + collection.dispose(); + } + this.collections = []; + } + dispose() { + var _a2; + this.buffers.dispose(); + if (this.timer) { + clearTimeout(this.timer); + } + for (let collection of this.collections) { + collection.dispose(); + } + (_a2 = this.floatFactory) == null ? void 0 : _a2.close(); + this.collections = []; + disposeAll(this.disposables); + } + get nvim() { + return workspace_default.nvim; + } + setConfiguration(event) { + if (event && !event.affectsConfiguration("diagnostic")) + return; + let config = workspace_default.getConfiguration("diagnostic"); + let messageTarget = config.get("messageTarget", "float"); + if (messageTarget == "float" && !workspace_default.env.floating && !workspace_default.env.textprop) { + messageTarget = "echo"; + } + let enableHighlightLineNumber = config.get("enableHighlightLineNumber", true); + if (!workspace_default.isNvim) + enableHighlightLineNumber = false; + this.config = { + floatConfig: config.get("floatConfig", {}), + messageTarget, + enableHighlightLineNumber, + highlighLimit: config.get("highlighLimit", 1e3), + autoRefresh: config.get("autoRefresh", true), + virtualTextSrcId: workspace_default.createNameSpace("diagnostic-virtualText"), + checkCurrentLine: config.get("checkCurrentLine", false), + enableSign: workspace_default.env.sign && config.get("enableSign", true), + locationlistUpdate: config.get("locationlistUpdate", true), + enableMessage: config.get("enableMessage", "always"), + messageDelay: config.get("messageDelay", 200), + virtualText: config.get("virtualText", false) && this.nvim.hasFunction("nvim_buf_set_virtual_text"), + virtualTextCurrentLineOnly: config.get("virtualTextCurrentLineOnly", true), + virtualTextPrefix: config.get("virtualTextPrefix", " "), + virtualTextLineSeparator: config.get("virtualTextLineSeparator", " \\ "), + virtualTextLines: config.get("virtualTextLines", 3), + displayByAle: config.get("displayByAle", false), + level: severityLevel(config.get("level", "hint")), + signPriority: config.get("signPriority", 10), + errorSign: config.get("errorSign", ">>"), + warningSign: config.get("warningSign", ">>"), + infoSign: config.get("infoSign", ">>"), + hintSign: config.get("hintSign", ">>"), + refreshOnInsertMode: config.get("refreshOnInsertMode", false), + filetypeMap: config.get("filetypeMap", {}), + showUnused: config.get("showUnused", true), + showDeprecated: config.get("showDeprecated", true), + format: config.get("format", "[%source%code] [%severity] %message") + }; + this.enabled = config.get("enable", true); + this.defineSigns(); + } + getCollectionByName(name2) { + return this.collections.find((o) => o.name == name2); + } + getCollections(uri) { + return this.collections.filter((c) => c.has(uri)); + } + toggleDiagnostic() { + let { enabled } = this; + this.enabled = !enabled; + for (let buf of this.buffers.items) { + if (this.enabled) { + void this.refreshBuffer(buf.uri, true); + } else { + buf.clear(); + } + } + } + async toggleDiagnosticBuffer(bufnr) { + if (!this.enabled) + return; + let buf = this.buffers.getItem(bufnr); + if (buf) { + let isEnabled = await buf.isEnabled(); + await this.nvim.call("setbufvar", [bufnr, "coc_diagnostic_disable", isEnabled ? 1 : 0]); + if (isEnabled) { + buf.clear(); + } else { + void this.refreshBuffer(bufnr, true); + } + } + } + get autoRefresh() { + return this.enabled && this.config.autoRefresh; + } + async refreshBuffer(uri, force = false) { + let buf = this.buffers.getItem(uri); + if (!buf) + return false; + await buf.refresh(this.getDiagnostics(buf.uri), force); + return true; + } + refresh(bufnr) { + if (!bufnr) { + for (let item of this.buffers.items) { + void this.refreshBuffer(item.uri, true); + } + } else { + let item = this.buffers.getItem(bufnr); + if (item) { + void this.refreshBuffer(item.uri, true); + } + } + } + }; + manager_default = new DiagnosticManager(); + } +}); + +// src/util/charCode.ts +var CharCode; +var init_charCode = __esm({ + "src/util/charCode.ts"() { + (function(CharCode2) { + CharCode2[CharCode2["Null"] = 0] = "Null"; + CharCode2[CharCode2["Backspace"] = 8] = "Backspace"; + CharCode2[CharCode2["Tab"] = 9] = "Tab"; + CharCode2[CharCode2["LineFeed"] = 10] = "LineFeed"; + CharCode2[CharCode2["CarriageReturn"] = 13] = "CarriageReturn"; + CharCode2[CharCode2["Space"] = 32] = "Space"; + CharCode2[CharCode2["ExclamationMark"] = 33] = "ExclamationMark"; + CharCode2[CharCode2["DoubleQuote"] = 34] = "DoubleQuote"; + CharCode2[CharCode2["Hash"] = 35] = "Hash"; + CharCode2[CharCode2["DollarSign"] = 36] = "DollarSign"; + CharCode2[CharCode2["PercentSign"] = 37] = "PercentSign"; + CharCode2[CharCode2["Ampersand"] = 38] = "Ampersand"; + CharCode2[CharCode2["SingleQuote"] = 39] = "SingleQuote"; + CharCode2[CharCode2["OpenParen"] = 40] = "OpenParen"; + CharCode2[CharCode2["CloseParen"] = 41] = "CloseParen"; + CharCode2[CharCode2["Asterisk"] = 42] = "Asterisk"; + CharCode2[CharCode2["Plus"] = 43] = "Plus"; + CharCode2[CharCode2["Comma"] = 44] = "Comma"; + CharCode2[CharCode2["Dash"] = 45] = "Dash"; + CharCode2[CharCode2["Period"] = 46] = "Period"; + CharCode2[CharCode2["Slash"] = 47] = "Slash"; + CharCode2[CharCode2["Digit0"] = 48] = "Digit0"; + CharCode2[CharCode2["Digit1"] = 49] = "Digit1"; + CharCode2[CharCode2["Digit2"] = 50] = "Digit2"; + CharCode2[CharCode2["Digit3"] = 51] = "Digit3"; + CharCode2[CharCode2["Digit4"] = 52] = "Digit4"; + CharCode2[CharCode2["Digit5"] = 53] = "Digit5"; + CharCode2[CharCode2["Digit6"] = 54] = "Digit6"; + CharCode2[CharCode2["Digit7"] = 55] = "Digit7"; + CharCode2[CharCode2["Digit8"] = 56] = "Digit8"; + CharCode2[CharCode2["Digit9"] = 57] = "Digit9"; + CharCode2[CharCode2["Colon"] = 58] = "Colon"; + CharCode2[CharCode2["Semicolon"] = 59] = "Semicolon"; + CharCode2[CharCode2["LessThan"] = 60] = "LessThan"; + CharCode2[CharCode2["Equals"] = 61] = "Equals"; + CharCode2[CharCode2["GreaterThan"] = 62] = "GreaterThan"; + CharCode2[CharCode2["QuestionMark"] = 63] = "QuestionMark"; + CharCode2[CharCode2["AtSign"] = 64] = "AtSign"; + CharCode2[CharCode2["A"] = 65] = "A"; + CharCode2[CharCode2["B"] = 66] = "B"; + CharCode2[CharCode2["C"] = 67] = "C"; + CharCode2[CharCode2["D"] = 68] = "D"; + CharCode2[CharCode2["E"] = 69] = "E"; + CharCode2[CharCode2["F"] = 70] = "F"; + CharCode2[CharCode2["G"] = 71] = "G"; + CharCode2[CharCode2["H"] = 72] = "H"; + CharCode2[CharCode2["I"] = 73] = "I"; + CharCode2[CharCode2["J"] = 74] = "J"; + CharCode2[CharCode2["K"] = 75] = "K"; + CharCode2[CharCode2["L"] = 76] = "L"; + CharCode2[CharCode2["M"] = 77] = "M"; + CharCode2[CharCode2["N"] = 78] = "N"; + CharCode2[CharCode2["O"] = 79] = "O"; + CharCode2[CharCode2["P"] = 80] = "P"; + CharCode2[CharCode2["Q"] = 81] = "Q"; + CharCode2[CharCode2["R"] = 82] = "R"; + CharCode2[CharCode2["S"] = 83] = "S"; + CharCode2[CharCode2["T"] = 84] = "T"; + CharCode2[CharCode2["U"] = 85] = "U"; + CharCode2[CharCode2["V"] = 86] = "V"; + CharCode2[CharCode2["W"] = 87] = "W"; + CharCode2[CharCode2["X"] = 88] = "X"; + CharCode2[CharCode2["Y"] = 89] = "Y"; + CharCode2[CharCode2["Z"] = 90] = "Z"; + CharCode2[CharCode2["OpenSquareBracket"] = 91] = "OpenSquareBracket"; + CharCode2[CharCode2["Backslash"] = 92] = "Backslash"; + CharCode2[CharCode2["CloseSquareBracket"] = 93] = "CloseSquareBracket"; + CharCode2[CharCode2["Caret"] = 94] = "Caret"; + CharCode2[CharCode2["Underline"] = 95] = "Underline"; + CharCode2[CharCode2["BackTick"] = 96] = "BackTick"; + CharCode2[CharCode2["a"] = 97] = "a"; + CharCode2[CharCode2["b"] = 98] = "b"; + CharCode2[CharCode2["c"] = 99] = "c"; + CharCode2[CharCode2["d"] = 100] = "d"; + CharCode2[CharCode2["e"] = 101] = "e"; + CharCode2[CharCode2["f"] = 102] = "f"; + CharCode2[CharCode2["g"] = 103] = "g"; + CharCode2[CharCode2["h"] = 104] = "h"; + CharCode2[CharCode2["i"] = 105] = "i"; + CharCode2[CharCode2["j"] = 106] = "j"; + CharCode2[CharCode2["k"] = 107] = "k"; + CharCode2[CharCode2["l"] = 108] = "l"; + CharCode2[CharCode2["m"] = 109] = "m"; + CharCode2[CharCode2["n"] = 110] = "n"; + CharCode2[CharCode2["o"] = 111] = "o"; + CharCode2[CharCode2["p"] = 112] = "p"; + CharCode2[CharCode2["q"] = 113] = "q"; + CharCode2[CharCode2["r"] = 114] = "r"; + CharCode2[CharCode2["s"] = 115] = "s"; + CharCode2[CharCode2["t"] = 116] = "t"; + CharCode2[CharCode2["u"] = 117] = "u"; + CharCode2[CharCode2["v"] = 118] = "v"; + CharCode2[CharCode2["w"] = 119] = "w"; + CharCode2[CharCode2["x"] = 120] = "x"; + CharCode2[CharCode2["y"] = 121] = "y"; + CharCode2[CharCode2["z"] = 122] = "z"; + CharCode2[CharCode2["OpenCurlyBrace"] = 123] = "OpenCurlyBrace"; + CharCode2[CharCode2["Pipe"] = 124] = "Pipe"; + CharCode2[CharCode2["CloseCurlyBrace"] = 125] = "CloseCurlyBrace"; + CharCode2[CharCode2["Tilde"] = 126] = "Tilde"; + CharCode2[CharCode2["U_Combining_Grave_Accent"] = 768] = "U_Combining_Grave_Accent"; + CharCode2[CharCode2["U_Combining_Acute_Accent"] = 769] = "U_Combining_Acute_Accent"; + CharCode2[CharCode2["U_Combining_Circumflex_Accent"] = 770] = "U_Combining_Circumflex_Accent"; + CharCode2[CharCode2["U_Combining_Tilde"] = 771] = "U_Combining_Tilde"; + CharCode2[CharCode2["U_Combining_Macron"] = 772] = "U_Combining_Macron"; + CharCode2[CharCode2["U_Combining_Overline"] = 773] = "U_Combining_Overline"; + CharCode2[CharCode2["U_Combining_Breve"] = 774] = "U_Combining_Breve"; + CharCode2[CharCode2["U_Combining_Dot_Above"] = 775] = "U_Combining_Dot_Above"; + CharCode2[CharCode2["U_Combining_Diaeresis"] = 776] = "U_Combining_Diaeresis"; + CharCode2[CharCode2["U_Combining_Hook_Above"] = 777] = "U_Combining_Hook_Above"; + CharCode2[CharCode2["U_Combining_Ring_Above"] = 778] = "U_Combining_Ring_Above"; + CharCode2[CharCode2["U_Combining_Double_Acute_Accent"] = 779] = "U_Combining_Double_Acute_Accent"; + CharCode2[CharCode2["U_Combining_Caron"] = 780] = "U_Combining_Caron"; + CharCode2[CharCode2["U_Combining_Vertical_Line_Above"] = 781] = "U_Combining_Vertical_Line_Above"; + CharCode2[CharCode2["U_Combining_Double_Vertical_Line_Above"] = 782] = "U_Combining_Double_Vertical_Line_Above"; + CharCode2[CharCode2["U_Combining_Double_Grave_Accent"] = 783] = "U_Combining_Double_Grave_Accent"; + CharCode2[CharCode2["U_Combining_Candrabindu"] = 784] = "U_Combining_Candrabindu"; + CharCode2[CharCode2["U_Combining_Inverted_Breve"] = 785] = "U_Combining_Inverted_Breve"; + CharCode2[CharCode2["U_Combining_Turned_Comma_Above"] = 786] = "U_Combining_Turned_Comma_Above"; + CharCode2[CharCode2["U_Combining_Comma_Above"] = 787] = "U_Combining_Comma_Above"; + CharCode2[CharCode2["U_Combining_Reversed_Comma_Above"] = 788] = "U_Combining_Reversed_Comma_Above"; + CharCode2[CharCode2["U_Combining_Comma_Above_Right"] = 789] = "U_Combining_Comma_Above_Right"; + CharCode2[CharCode2["U_Combining_Grave_Accent_Below"] = 790] = "U_Combining_Grave_Accent_Below"; + CharCode2[CharCode2["U_Combining_Acute_Accent_Below"] = 791] = "U_Combining_Acute_Accent_Below"; + CharCode2[CharCode2["U_Combining_Left_Tack_Below"] = 792] = "U_Combining_Left_Tack_Below"; + CharCode2[CharCode2["U_Combining_Right_Tack_Below"] = 793] = "U_Combining_Right_Tack_Below"; + CharCode2[CharCode2["U_Combining_Left_Angle_Above"] = 794] = "U_Combining_Left_Angle_Above"; + CharCode2[CharCode2["U_Combining_Horn"] = 795] = "U_Combining_Horn"; + CharCode2[CharCode2["U_Combining_Left_Half_Ring_Below"] = 796] = "U_Combining_Left_Half_Ring_Below"; + CharCode2[CharCode2["U_Combining_Up_Tack_Below"] = 797] = "U_Combining_Up_Tack_Below"; + CharCode2[CharCode2["U_Combining_Down_Tack_Below"] = 798] = "U_Combining_Down_Tack_Below"; + CharCode2[CharCode2["U_Combining_Plus_Sign_Below"] = 799] = "U_Combining_Plus_Sign_Below"; + CharCode2[CharCode2["U_Combining_Minus_Sign_Below"] = 800] = "U_Combining_Minus_Sign_Below"; + CharCode2[CharCode2["U_Combining_Palatalized_Hook_Below"] = 801] = "U_Combining_Palatalized_Hook_Below"; + CharCode2[CharCode2["U_Combining_Retroflex_Hook_Below"] = 802] = "U_Combining_Retroflex_Hook_Below"; + CharCode2[CharCode2["U_Combining_Dot_Below"] = 803] = "U_Combining_Dot_Below"; + CharCode2[CharCode2["U_Combining_Diaeresis_Below"] = 804] = "U_Combining_Diaeresis_Below"; + CharCode2[CharCode2["U_Combining_Ring_Below"] = 805] = "U_Combining_Ring_Below"; + CharCode2[CharCode2["U_Combining_Comma_Below"] = 806] = "U_Combining_Comma_Below"; + CharCode2[CharCode2["U_Combining_Cedilla"] = 807] = "U_Combining_Cedilla"; + CharCode2[CharCode2["U_Combining_Ogonek"] = 808] = "U_Combining_Ogonek"; + CharCode2[CharCode2["U_Combining_Vertical_Line_Below"] = 809] = "U_Combining_Vertical_Line_Below"; + CharCode2[CharCode2["U_Combining_Bridge_Below"] = 810] = "U_Combining_Bridge_Below"; + CharCode2[CharCode2["U_Combining_Inverted_Double_Arch_Below"] = 811] = "U_Combining_Inverted_Double_Arch_Below"; + CharCode2[CharCode2["U_Combining_Caron_Below"] = 812] = "U_Combining_Caron_Below"; + CharCode2[CharCode2["U_Combining_Circumflex_Accent_Below"] = 813] = "U_Combining_Circumflex_Accent_Below"; + CharCode2[CharCode2["U_Combining_Breve_Below"] = 814] = "U_Combining_Breve_Below"; + CharCode2[CharCode2["U_Combining_Inverted_Breve_Below"] = 815] = "U_Combining_Inverted_Breve_Below"; + CharCode2[CharCode2["U_Combining_Tilde_Below"] = 816] = "U_Combining_Tilde_Below"; + CharCode2[CharCode2["U_Combining_Macron_Below"] = 817] = "U_Combining_Macron_Below"; + CharCode2[CharCode2["U_Combining_Low_Line"] = 818] = "U_Combining_Low_Line"; + CharCode2[CharCode2["U_Combining_Double_Low_Line"] = 819] = "U_Combining_Double_Low_Line"; + CharCode2[CharCode2["U_Combining_Tilde_Overlay"] = 820] = "U_Combining_Tilde_Overlay"; + CharCode2[CharCode2["U_Combining_Short_Stroke_Overlay"] = 821] = "U_Combining_Short_Stroke_Overlay"; + CharCode2[CharCode2["U_Combining_Long_Stroke_Overlay"] = 822] = "U_Combining_Long_Stroke_Overlay"; + CharCode2[CharCode2["U_Combining_Short_Solidus_Overlay"] = 823] = "U_Combining_Short_Solidus_Overlay"; + CharCode2[CharCode2["U_Combining_Long_Solidus_Overlay"] = 824] = "U_Combining_Long_Solidus_Overlay"; + CharCode2[CharCode2["U_Combining_Right_Half_Ring_Below"] = 825] = "U_Combining_Right_Half_Ring_Below"; + CharCode2[CharCode2["U_Combining_Inverted_Bridge_Below"] = 826] = "U_Combining_Inverted_Bridge_Below"; + CharCode2[CharCode2["U_Combining_Square_Below"] = 827] = "U_Combining_Square_Below"; + CharCode2[CharCode2["U_Combining_Seagull_Below"] = 828] = "U_Combining_Seagull_Below"; + CharCode2[CharCode2["U_Combining_X_Above"] = 829] = "U_Combining_X_Above"; + CharCode2[CharCode2["U_Combining_Vertical_Tilde"] = 830] = "U_Combining_Vertical_Tilde"; + CharCode2[CharCode2["U_Combining_Double_Overline"] = 831] = "U_Combining_Double_Overline"; + CharCode2[CharCode2["U_Combining_Grave_Tone_Mark"] = 832] = "U_Combining_Grave_Tone_Mark"; + CharCode2[CharCode2["U_Combining_Acute_Tone_Mark"] = 833] = "U_Combining_Acute_Tone_Mark"; + CharCode2[CharCode2["U_Combining_Greek_Perispomeni"] = 834] = "U_Combining_Greek_Perispomeni"; + CharCode2[CharCode2["U_Combining_Greek_Koronis"] = 835] = "U_Combining_Greek_Koronis"; + CharCode2[CharCode2["U_Combining_Greek_Dialytika_Tonos"] = 836] = "U_Combining_Greek_Dialytika_Tonos"; + CharCode2[CharCode2["U_Combining_Greek_Ypogegrammeni"] = 837] = "U_Combining_Greek_Ypogegrammeni"; + CharCode2[CharCode2["U_Combining_Bridge_Above"] = 838] = "U_Combining_Bridge_Above"; + CharCode2[CharCode2["U_Combining_Equals_Sign_Below"] = 839] = "U_Combining_Equals_Sign_Below"; + CharCode2[CharCode2["U_Combining_Double_Vertical_Line_Below"] = 840] = "U_Combining_Double_Vertical_Line_Below"; + CharCode2[CharCode2["U_Combining_Left_Angle_Below"] = 841] = "U_Combining_Left_Angle_Below"; + CharCode2[CharCode2["U_Combining_Not_Tilde_Above"] = 842] = "U_Combining_Not_Tilde_Above"; + CharCode2[CharCode2["U_Combining_Homothetic_Above"] = 843] = "U_Combining_Homothetic_Above"; + CharCode2[CharCode2["U_Combining_Almost_Equal_To_Above"] = 844] = "U_Combining_Almost_Equal_To_Above"; + CharCode2[CharCode2["U_Combining_Left_Right_Arrow_Below"] = 845] = "U_Combining_Left_Right_Arrow_Below"; + CharCode2[CharCode2["U_Combining_Upwards_Arrow_Below"] = 846] = "U_Combining_Upwards_Arrow_Below"; + CharCode2[CharCode2["U_Combining_Grapheme_Joiner"] = 847] = "U_Combining_Grapheme_Joiner"; + CharCode2[CharCode2["U_Combining_Right_Arrowhead_Above"] = 848] = "U_Combining_Right_Arrowhead_Above"; + CharCode2[CharCode2["U_Combining_Left_Half_Ring_Above"] = 849] = "U_Combining_Left_Half_Ring_Above"; + CharCode2[CharCode2["U_Combining_Fermata"] = 850] = "U_Combining_Fermata"; + CharCode2[CharCode2["U_Combining_X_Below"] = 851] = "U_Combining_X_Below"; + CharCode2[CharCode2["U_Combining_Left_Arrowhead_Below"] = 852] = "U_Combining_Left_Arrowhead_Below"; + CharCode2[CharCode2["U_Combining_Right_Arrowhead_Below"] = 853] = "U_Combining_Right_Arrowhead_Below"; + CharCode2[CharCode2["U_Combining_Right_Arrowhead_And_Up_Arrowhead_Below"] = 854] = "U_Combining_Right_Arrowhead_And_Up_Arrowhead_Below"; + CharCode2[CharCode2["U_Combining_Right_Half_Ring_Above"] = 855] = "U_Combining_Right_Half_Ring_Above"; + CharCode2[CharCode2["U_Combining_Dot_Above_Right"] = 856] = "U_Combining_Dot_Above_Right"; + CharCode2[CharCode2["U_Combining_Asterisk_Below"] = 857] = "U_Combining_Asterisk_Below"; + CharCode2[CharCode2["U_Combining_Double_Ring_Below"] = 858] = "U_Combining_Double_Ring_Below"; + CharCode2[CharCode2["U_Combining_Zigzag_Above"] = 859] = "U_Combining_Zigzag_Above"; + CharCode2[CharCode2["U_Combining_Double_Breve_Below"] = 860] = "U_Combining_Double_Breve_Below"; + CharCode2[CharCode2["U_Combining_Double_Breve"] = 861] = "U_Combining_Double_Breve"; + CharCode2[CharCode2["U_Combining_Double_Macron"] = 862] = "U_Combining_Double_Macron"; + CharCode2[CharCode2["U_Combining_Double_Macron_Below"] = 863] = "U_Combining_Double_Macron_Below"; + CharCode2[CharCode2["U_Combining_Double_Tilde"] = 864] = "U_Combining_Double_Tilde"; + CharCode2[CharCode2["U_Combining_Double_Inverted_Breve"] = 865] = "U_Combining_Double_Inverted_Breve"; + CharCode2[CharCode2["U_Combining_Double_Rightwards_Arrow_Below"] = 866] = "U_Combining_Double_Rightwards_Arrow_Below"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_A"] = 867] = "U_Combining_Latin_Small_Letter_A"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_E"] = 868] = "U_Combining_Latin_Small_Letter_E"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_I"] = 869] = "U_Combining_Latin_Small_Letter_I"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_O"] = 870] = "U_Combining_Latin_Small_Letter_O"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_U"] = 871] = "U_Combining_Latin_Small_Letter_U"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_C"] = 872] = "U_Combining_Latin_Small_Letter_C"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_D"] = 873] = "U_Combining_Latin_Small_Letter_D"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_H"] = 874] = "U_Combining_Latin_Small_Letter_H"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_M"] = 875] = "U_Combining_Latin_Small_Letter_M"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_R"] = 876] = "U_Combining_Latin_Small_Letter_R"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_T"] = 877] = "U_Combining_Latin_Small_Letter_T"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_V"] = 878] = "U_Combining_Latin_Small_Letter_V"; + CharCode2[CharCode2["U_Combining_Latin_Small_Letter_X"] = 879] = "U_Combining_Latin_Small_Letter_X"; + CharCode2[CharCode2["LINE_SEPARATOR_2028"] = 8232] = "LINE_SEPARATOR_2028"; + CharCode2[CharCode2["U_CIRCUMFLEX"] = 94] = "U_CIRCUMFLEX"; + CharCode2[CharCode2["U_GRAVE_ACCENT"] = 96] = "U_GRAVE_ACCENT"; + CharCode2[CharCode2["U_DIAERESIS"] = 168] = "U_DIAERESIS"; + CharCode2[CharCode2["U_MACRON"] = 175] = "U_MACRON"; + CharCode2[CharCode2["U_ACUTE_ACCENT"] = 180] = "U_ACUTE_ACCENT"; + CharCode2[CharCode2["U_CEDILLA"] = 184] = "U_CEDILLA"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LEFT_ARROWHEAD"] = 706] = "U_MODIFIER_LETTER_LEFT_ARROWHEAD"; + CharCode2[CharCode2["U_MODIFIER_LETTER_RIGHT_ARROWHEAD"] = 707] = "U_MODIFIER_LETTER_RIGHT_ARROWHEAD"; + CharCode2[CharCode2["U_MODIFIER_LETTER_UP_ARROWHEAD"] = 708] = "U_MODIFIER_LETTER_UP_ARROWHEAD"; + CharCode2[CharCode2["U_MODIFIER_LETTER_DOWN_ARROWHEAD"] = 709] = "U_MODIFIER_LETTER_DOWN_ARROWHEAD"; + CharCode2[CharCode2["U_MODIFIER_LETTER_CENTRED_RIGHT_HALF_RING"] = 722] = "U_MODIFIER_LETTER_CENTRED_RIGHT_HALF_RING"; + CharCode2[CharCode2["U_MODIFIER_LETTER_CENTRED_LEFT_HALF_RING"] = 723] = "U_MODIFIER_LETTER_CENTRED_LEFT_HALF_RING"; + CharCode2[CharCode2["U_MODIFIER_LETTER_UP_TACK"] = 724] = "U_MODIFIER_LETTER_UP_TACK"; + CharCode2[CharCode2["U_MODIFIER_LETTER_DOWN_TACK"] = 725] = "U_MODIFIER_LETTER_DOWN_TACK"; + CharCode2[CharCode2["U_MODIFIER_LETTER_PLUS_SIGN"] = 726] = "U_MODIFIER_LETTER_PLUS_SIGN"; + CharCode2[CharCode2["U_MODIFIER_LETTER_MINUS_SIGN"] = 727] = "U_MODIFIER_LETTER_MINUS_SIGN"; + CharCode2[CharCode2["U_BREVE"] = 728] = "U_BREVE"; + CharCode2[CharCode2["U_DOT_ABOVE"] = 729] = "U_DOT_ABOVE"; + CharCode2[CharCode2["U_RING_ABOVE"] = 730] = "U_RING_ABOVE"; + CharCode2[CharCode2["U_OGONEK"] = 731] = "U_OGONEK"; + CharCode2[CharCode2["U_SMALL_TILDE"] = 732] = "U_SMALL_TILDE"; + CharCode2[CharCode2["U_DOUBLE_ACUTE_ACCENT"] = 733] = "U_DOUBLE_ACUTE_ACCENT"; + CharCode2[CharCode2["U_MODIFIER_LETTER_RHOTIC_HOOK"] = 734] = "U_MODIFIER_LETTER_RHOTIC_HOOK"; + CharCode2[CharCode2["U_MODIFIER_LETTER_CROSS_ACCENT"] = 735] = "U_MODIFIER_LETTER_CROSS_ACCENT"; + CharCode2[CharCode2["U_MODIFIER_LETTER_EXTRA_HIGH_TONE_BAR"] = 741] = "U_MODIFIER_LETTER_EXTRA_HIGH_TONE_BAR"; + CharCode2[CharCode2["U_MODIFIER_LETTER_HIGH_TONE_BAR"] = 742] = "U_MODIFIER_LETTER_HIGH_TONE_BAR"; + CharCode2[CharCode2["U_MODIFIER_LETTER_MID_TONE_BAR"] = 743] = "U_MODIFIER_LETTER_MID_TONE_BAR"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LOW_TONE_BAR"] = 744] = "U_MODIFIER_LETTER_LOW_TONE_BAR"; + CharCode2[CharCode2["U_MODIFIER_LETTER_EXTRA_LOW_TONE_BAR"] = 745] = "U_MODIFIER_LETTER_EXTRA_LOW_TONE_BAR"; + CharCode2[CharCode2["U_MODIFIER_LETTER_YIN_DEPARTING_TONE_MARK"] = 746] = "U_MODIFIER_LETTER_YIN_DEPARTING_TONE_MARK"; + CharCode2[CharCode2["U_MODIFIER_LETTER_YANG_DEPARTING_TONE_MARK"] = 747] = "U_MODIFIER_LETTER_YANG_DEPARTING_TONE_MARK"; + CharCode2[CharCode2["U_MODIFIER_LETTER_UNASPIRATED"] = 749] = "U_MODIFIER_LETTER_UNASPIRATED"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LOW_DOWN_ARROWHEAD"] = 751] = "U_MODIFIER_LETTER_LOW_DOWN_ARROWHEAD"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LOW_UP_ARROWHEAD"] = 752] = "U_MODIFIER_LETTER_LOW_UP_ARROWHEAD"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LOW_LEFT_ARROWHEAD"] = 753] = "U_MODIFIER_LETTER_LOW_LEFT_ARROWHEAD"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LOW_RIGHT_ARROWHEAD"] = 754] = "U_MODIFIER_LETTER_LOW_RIGHT_ARROWHEAD"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LOW_RING"] = 755] = "U_MODIFIER_LETTER_LOW_RING"; + CharCode2[CharCode2["U_MODIFIER_LETTER_MIDDLE_GRAVE_ACCENT"] = 756] = "U_MODIFIER_LETTER_MIDDLE_GRAVE_ACCENT"; + CharCode2[CharCode2["U_MODIFIER_LETTER_MIDDLE_DOUBLE_GRAVE_ACCENT"] = 757] = "U_MODIFIER_LETTER_MIDDLE_DOUBLE_GRAVE_ACCENT"; + CharCode2[CharCode2["U_MODIFIER_LETTER_MIDDLE_DOUBLE_ACUTE_ACCENT"] = 758] = "U_MODIFIER_LETTER_MIDDLE_DOUBLE_ACUTE_ACCENT"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LOW_TILDE"] = 759] = "U_MODIFIER_LETTER_LOW_TILDE"; + CharCode2[CharCode2["U_MODIFIER_LETTER_RAISED_COLON"] = 760] = "U_MODIFIER_LETTER_RAISED_COLON"; + CharCode2[CharCode2["U_MODIFIER_LETTER_BEGIN_HIGH_TONE"] = 761] = "U_MODIFIER_LETTER_BEGIN_HIGH_TONE"; + CharCode2[CharCode2["U_MODIFIER_LETTER_END_HIGH_TONE"] = 762] = "U_MODIFIER_LETTER_END_HIGH_TONE"; + CharCode2[CharCode2["U_MODIFIER_LETTER_BEGIN_LOW_TONE"] = 763] = "U_MODIFIER_LETTER_BEGIN_LOW_TONE"; + CharCode2[CharCode2["U_MODIFIER_LETTER_END_LOW_TONE"] = 764] = "U_MODIFIER_LETTER_END_LOW_TONE"; + CharCode2[CharCode2["U_MODIFIER_LETTER_SHELF"] = 765] = "U_MODIFIER_LETTER_SHELF"; + CharCode2[CharCode2["U_MODIFIER_LETTER_OPEN_SHELF"] = 766] = "U_MODIFIER_LETTER_OPEN_SHELF"; + CharCode2[CharCode2["U_MODIFIER_LETTER_LOW_LEFT_ARROW"] = 767] = "U_MODIFIER_LETTER_LOW_LEFT_ARROW"; + CharCode2[CharCode2["U_GREEK_LOWER_NUMERAL_SIGN"] = 885] = "U_GREEK_LOWER_NUMERAL_SIGN"; + CharCode2[CharCode2["U_GREEK_TONOS"] = 900] = "U_GREEK_TONOS"; + CharCode2[CharCode2["U_GREEK_DIALYTIKA_TONOS"] = 901] = "U_GREEK_DIALYTIKA_TONOS"; + CharCode2[CharCode2["U_GREEK_KORONIS"] = 8125] = "U_GREEK_KORONIS"; + CharCode2[CharCode2["U_GREEK_PSILI"] = 8127] = "U_GREEK_PSILI"; + CharCode2[CharCode2["U_GREEK_PERISPOMENI"] = 8128] = "U_GREEK_PERISPOMENI"; + CharCode2[CharCode2["U_GREEK_DIALYTIKA_AND_PERISPOMENI"] = 8129] = "U_GREEK_DIALYTIKA_AND_PERISPOMENI"; + CharCode2[CharCode2["U_GREEK_PSILI_AND_VARIA"] = 8141] = "U_GREEK_PSILI_AND_VARIA"; + CharCode2[CharCode2["U_GREEK_PSILI_AND_OXIA"] = 8142] = "U_GREEK_PSILI_AND_OXIA"; + CharCode2[CharCode2["U_GREEK_PSILI_AND_PERISPOMENI"] = 8143] = "U_GREEK_PSILI_AND_PERISPOMENI"; + CharCode2[CharCode2["U_GREEK_DASIA_AND_VARIA"] = 8157] = "U_GREEK_DASIA_AND_VARIA"; + CharCode2[CharCode2["U_GREEK_DASIA_AND_OXIA"] = 8158] = "U_GREEK_DASIA_AND_OXIA"; + CharCode2[CharCode2["U_GREEK_DASIA_AND_PERISPOMENI"] = 8159] = "U_GREEK_DASIA_AND_PERISPOMENI"; + CharCode2[CharCode2["U_GREEK_DIALYTIKA_AND_VARIA"] = 8173] = "U_GREEK_DIALYTIKA_AND_VARIA"; + CharCode2[CharCode2["U_GREEK_DIALYTIKA_AND_OXIA"] = 8174] = "U_GREEK_DIALYTIKA_AND_OXIA"; + CharCode2[CharCode2["U_GREEK_VARIA"] = 8175] = "U_GREEK_VARIA"; + CharCode2[CharCode2["U_GREEK_OXIA"] = 8189] = "U_GREEK_OXIA"; + CharCode2[CharCode2["U_GREEK_DASIA"] = 8190] = "U_GREEK_DASIA"; + CharCode2[CharCode2["U_OVERLINE"] = 8254] = "U_OVERLINE"; + CharCode2[CharCode2["UTF8_BOM"] = 65279] = "UTF8_BOM"; + })(CharCode || (CharCode = {})); + } +}); + +// src/snippets/parser.ts +function walk(marker, visitor) { + const stack = [...marker]; + while (stack.length > 0) { + const marker2 = stack.shift(); + const recurse = visitor(marker2); + if (!recurse) { + break; + } + stack.unshift(...marker2.children); + } +} +var logger31, TokenType, _Scanner, Scanner, Marker, Text, TransformableMarker, Placeholder, Choice, Transform, FormatString, Variable, TextmateSnippet, SnippetParser; +var init_parser2 = __esm({ + "src/snippets/parser.ts"() { + init_charCode(); + init_string(); + logger31 = require_logger2()("snippets-parser"); + (function(TokenType2) { + TokenType2[TokenType2["Dollar"] = 0] = "Dollar"; + TokenType2[TokenType2["Colon"] = 1] = "Colon"; + TokenType2[TokenType2["Comma"] = 2] = "Comma"; + TokenType2[TokenType2["CurlyOpen"] = 3] = "CurlyOpen"; + TokenType2[TokenType2["CurlyClose"] = 4] = "CurlyClose"; + TokenType2[TokenType2["Backslash"] = 5] = "Backslash"; + TokenType2[TokenType2["Forwardslash"] = 6] = "Forwardslash"; + TokenType2[TokenType2["Pipe"] = 7] = "Pipe"; + TokenType2[TokenType2["Int"] = 8] = "Int"; + TokenType2[TokenType2["VariableName"] = 9] = "VariableName"; + TokenType2[TokenType2["Format"] = 10] = "Format"; + TokenType2[TokenType2["Plus"] = 11] = "Plus"; + TokenType2[TokenType2["Dash"] = 12] = "Dash"; + TokenType2[TokenType2["QuestionMark"] = 13] = "QuestionMark"; + TokenType2[TokenType2["EOF"] = 14] = "EOF"; + })(TokenType || (TokenType = {})); + _Scanner = class { + static isDigitCharacter(ch) { + return ch >= CharCode.Digit0 && ch <= CharCode.Digit9; + } + static isVariableCharacter(ch) { + return ch === CharCode.Underline || ch >= CharCode.a && ch <= CharCode.z || ch >= CharCode.A && ch <= CharCode.Z; + } + constructor() { + this.text(""); + } + 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, pos: this.pos, len: 0 }; + } + let pos = this.pos; + let len = 0; + let ch = this.value.charCodeAt(pos); + let type; + type = _Scanner._table[ch]; + if (typeof type === "number") { + this.pos += 1; + return { type, pos, len: 1 }; + } + if (_Scanner.isDigitCharacter(ch)) { + type = 8; + do { + len += 1; + ch = this.value.charCodeAt(pos + len); + } while (_Scanner.isDigitCharacter(ch)); + this.pos += len; + return { type, pos, len }; + } + if (_Scanner.isVariableCharacter(ch)) { + type = 9; + do { + ch = this.value.charCodeAt(pos + ++len); + } while (_Scanner.isVariableCharacter(ch) || _Scanner.isDigitCharacter(ch)); + this.pos += len; + return { type, pos, len }; + } + type = 10; + do { + len += 1; + ch = this.value.charCodeAt(pos + len); + } while (!isNaN(ch) && typeof _Scanner._table[ch] === "undefined" && !_Scanner.isDigitCharacter(ch) && !_Scanner.isVariableCharacter(ch)); + this.pos += len; + return { type, pos, len }; + } + }; + Scanner = _Scanner; + Scanner._table = { + [CharCode.DollarSign]: 0, + [CharCode.Colon]: 1, + [CharCode.Comma]: 2, + [CharCode.OpenCurlyBrace]: 3, + [CharCode.CloseCurlyBrace]: 4, + [CharCode.Backslash]: 5, + [CharCode.Slash]: 6, + [CharCode.Pipe]: 7, + [CharCode.Plus]: 11, + [CharCode.Dash]: 12, + [CharCode.QuestionMark]: 13 + }; + Marker = class { + constructor() { + this._children = []; + } + appendChild(child) { + if (child instanceof Text && this._children[this._children.length - 1] instanceof Text) { + this._children[this._children.length - 1].value += child.value; + } else { + 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, parent2) { + for (const child2 of children) { + child2.parent = parent2; + _fixParent(child2.children, child2); + } + })(others, parent); + } + get children() { + return this._children; + } + get snippet() { + let candidate = this; + while (true) { + if (!candidate) { + return void 0; + } + 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]; + } + }; + Text = class 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); + } + }; + TransformableMarker = class extends Marker { + }; + Placeholder = class 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] : void 0; + } + 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; + } + }; + Choice = class 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; + } + }; + Transform = class extends Marker { + resolve(value) { + let didMatch = false; + let ret = value.replace(this.regexp, (...args) => { + didMatch = true; + return this._replace(args.slice(0, -2)); + }); + 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; + } + }; + FormatString = class 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 (!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) => 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; + } + }; + Variable = class extends TransformableMarker { + constructor(name2) { + super(); + this.name = name2; + } + async resolve(resolver) { + let value = await resolver.resolve(this); + if (value && value.includes("\n")) { + let indent = ""; + this.snippet.walk((m) => { + if (m == this) { + return false; + } + if (m instanceof Text) { + let lines2 = m.toString().split(/\r?\n/); + indent = lines2[lines2.length - 1].match(/^\s*/)[0]; + } + return true; + }); + let lines = value.split("\n"); + let indents = lines.filter((s) => s.length > 0).map((s) => s.match(/^\s*/)[0]); + let minIndent = indents.length == 0 ? "" : indents.reduce((p, c) => p.length < c.length ? p : c); + let newLines = lines.map((s, i) => i == 0 || s.length == 0 || !s.startsWith(minIndent) ? s : indent + s.slice(minIndent.length)); + value = newLines.join("\n"); + } + if (this.transform) { + value = this.transform.resolve(value || ""); + } + if (value !== void 0) { + 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; + } + }; + TextmateSnippet = class extends Marker { + get placeholderInfo() { + if (!this._placeholders) { + this._variables = []; + let all = []; + let last; + this.walk((candidate) => { + if (candidate instanceof Placeholder) { + all.push(candidate); + last = !last || last.index < candidate.index ? candidate : last; + } else if (candidate instanceof Variable) { + let first = candidate.name.charCodeAt(0); + if (first < 65 || first > 90) { + this._variables.push(candidate); + } + } + return true; + }); + this._placeholders = { all, last }; + } + return this._placeholders; + } + get variables() { + return this._variables; + } + get placeholders() { + const { all } = this.placeholderInfo; + return all; + } + get maxIndexNumber() { + let { placeholders } = this; + return placeholders.reduce((curr, p) => 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; + let [before, after] = rangeParts(placeholder.toString(), range); + let nested = new SnippetParser().parse(snippet, true); + let maxIndexAdded = nested.maxIndexNumber + 1; + let indexes = []; + for (let p of nested.placeholders) { + if (p.isFinalTabstop) { + p.index = maxIndexAdded + index; + } else { + p.index = p.index + index; + } + indexes.push(p.index); + } + this.walk((m) => { + if (m instanceof Placeholder && m.index > index) { + m.index = m.index + maxIndexAdded; + } + return true; + }); + let children = nested.children; + if (before) + children.unshift(new Text(before)); + if (after) + children.push(new Text(after)); + this.replace(placeholder, children); + return Math.min.apply(null, indexes); + } + 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 = void 0; + } + updateVariable(id, val) { + const find = this.variables[id - this.maxIndexNumber - 1]; + if (find) { + let variables = this.variables.filter((o) => o.name == find.name); + for (let variable of variables) { + let newText = variable.transform ? variable.transform.resolve(val) : val; + variable.setOnlyChild(new Text(newText)); + } + } + } + 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], (marker2) => { + ret += marker2.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; + } + async resolveVariables(resolver) { + let items = []; + this.walk((candidate) => { + if (candidate instanceof Variable) { + items.push(candidate); + } + return true; + }); + await Promise.all(items.map((o) => o.resolve(resolver))); + } + appendChild(child) { + this._placeholders = void 0; + return super.appendChild(child); + } + replace(child, others) { + this._placeholders = void 0; + 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); + } + }; + SnippetParser = class { + 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)) { + } + const placeholderDefaultValues = new Map(); + const incompletePlaceholders = []; + snippet.walk((marker) => { + if (marker instanceof Placeholder) { + if (marker.isFinalTabstop) { + placeholderDefaultValues.set(0, void 0); + } 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 child2 of marker.children) { + if (child2 instanceof Text) { + marker.replace(child2, [new Text(clone.transform.resolve(child2.value))]); + break; + } + } + } + } + clone.appendChild(marker); + } + snippet.replace(placeholder, [clone]); + } + } + if (!placeholderDefaultValues.has(0) && insertFinalTabstop) { + snippet.appendChild(new Placeholder(0)); + } + return snippet; + } + _accept(type, value) { + if (type === void 0 || 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) { + return false; + } + let start = this._token; + while (this._token.type !== type) { + this._token = this._scanner.next(); + if (this._token.type === 14) { + 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); + } + _parseEscaped(marker) { + let value; + if (value = this._accept(5, true)) { + value = this._accept(0, true) || this._accept(4, true) || this._accept(5, true) || value; + marker.appendChild(new Text(value)); + return true; + } + return false; + } + _parseTabstopOrVariableName(parent) { + let value; + const token = this._token; + const match = this._accept(0) && (value = this._accept(9, true) || this._accept(8, true)); + if (!match) { + return this._backTo(token); + } + parent.appendChild(/^\d+$/.test(value) ? new Placeholder(Number(value)) : new Variable(value)); + return true; + } + _parseComplexPlaceholder(parent) { + let index; + const token = this._token; + const match = this._accept(0) && this._accept(3) && (index = this._accept(8, true)); + if (!match) { + return this._backTo(token); + } + const placeholder = new Placeholder(Number(index)); + if (this._accept(1)) { + while (true) { + if (this._accept(4)) { + parent.appendChild(placeholder); + return true; + } + if (this._parse(placeholder)) { + continue; + } + parent.appendChild(new Text("${" + index + ":")); + placeholder.children.forEach(parent.appendChild, parent); + return true; + } + } else if (placeholder.index > 0 && this._accept(7)) { + const choice = new Choice(); + while (true) { + if (this._parseChoiceElement(choice)) { + if (this._accept(2)) { + continue; + } + if (this._accept(7)) { + placeholder.appendChild(choice); + if (this._accept(4)) { + parent.appendChild(placeholder); + return true; + } + } + } + this._backTo(token); + return false; + } + } else if (this._accept(6)) { + if (this._parseTransform(placeholder)) { + parent.appendChild(placeholder); + return true; + } + this._backTo(token); + return false; + } else if (this._accept(4)) { + parent.appendChild(placeholder); + return true; + } else { + return this._backTo(token); + } + } + _parseChoiceElement(parent) { + const token = this._token; + const values = []; + while (true) { + if (this._token.type === 2 || this._token.type === 7) { + break; + } + let value; + if (value = this._accept(5, true)) { + value = this._accept(2, true) || this._accept(7, true) || this._accept(5, true) || value; + } else { + value = this._accept(void 0, true); + } + if (!value) { + 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; + } + _parseComplexVariable(parent) { + let name2; + const token = this._token; + const match = this._accept(0) && this._accept(3) && (name2 = this._accept(9, true)); + if (!match) { + return this._backTo(token); + } + const variable = new Variable(name2); + if (this._accept(1)) { + while (true) { + if (this._accept(4)) { + parent.appendChild(variable); + return true; + } + if (this._parse(variable)) { + continue; + } + parent.appendChild(new Text("${" + name2 + ":")); + variable.children.forEach(parent.appendChild, parent); + return true; + } + } else if (this._accept(6)) { + if (this._parseTransform(variable)) { + parent.appendChild(variable); + return true; + } + this._backTo(token); + return false; + } else if (this._accept(4)) { + parent.appendChild(variable); + return true; + } else { + return this._backTo(token); + } + } + _parseTransform(parent) { + let transform = new Transform(); + let regexValue = ""; + let regexOptions = ""; + while (true) { + if (this._accept(6)) { + break; + } + let escaped; + if (escaped = this._accept(5, true)) { + escaped = this._accept(6, true) || escaped; + regexValue += escaped; + continue; + } + if (this._token.type !== 14) { + regexValue += this._accept(void 0, true); + continue; + } + return false; + } + while (true) { + if (this._accept(6)) { + break; + } + let escaped; + if (escaped = this._accept(5, true)) { + escaped = this._accept(6, true) || escaped; + transform.appendChild(new Text(escaped)); + continue; + } + if (this._parseFormatString(transform) || this._parseAnything(transform)) { + let text = transform.children[0]; + if (text && text.value && text.value.includes("\\n")) { + text.value = text.value.replace(/\\n/g, "\n"); + } + continue; + } + return false; + } + while (true) { + if (this._accept(4)) { + break; + } + if (this._token.type !== 14) { + regexOptions += this._accept(void 0, true); + continue; + } + return false; + } + try { + transform.regexp = new RegExp(regexValue, regexOptions); + } catch (e) { + return false; + } + parent.transform = transform; + return true; + } + _parseFormatString(parent) { + const token = this._token; + if (!this._accept(0)) { + return false; + } + let complex = false; + if (this._accept(3)) { + complex = true; + } + let index = this._accept(8, true); + if (!index) { + this._backTo(token); + return false; + } else if (!complex) { + parent.appendChild(new FormatString(Number(index))); + return true; + } else if (this._accept(4)) { + parent.appendChild(new FormatString(Number(index))); + return true; + } else if (!this._accept(1)) { + this._backTo(token); + return false; + } + if (this._accept(6)) { + let shorthand = this._accept(9, true); + if (!shorthand || !this._accept(4)) { + this._backTo(token); + return false; + } else { + parent.appendChild(new FormatString(Number(index), shorthand)); + return true; + } + } else if (this._accept(11)) { + let ifValue = this._until(4); + if (ifValue) { + parent.appendChild(new FormatString(Number(index), void 0, ifValue, void 0)); + return true; + } + } else if (this._accept(12)) { + let elseValue = this._until(4); + if (elseValue) { + parent.appendChild(new FormatString(Number(index), void 0, void 0, elseValue)); + return true; + } + } else if (this._accept(13)) { + let ifValue = this._until(1); + if (ifValue) { + let elseValue = this._until(4); + if (elseValue) { + parent.appendChild(new FormatString(Number(index), void 0, ifValue, elseValue)); + return true; + } + } + } else { + let elseValue = this._until(4); + if (elseValue) { + parent.appendChild(new FormatString(Number(index), void 0, void 0, elseValue)); + return true; + } + } + this._backTo(token); + return false; + } + _parseAnything(marker) { + if (this._token.type !== 14) { + let text = this._scanner.tokenText(this._token); + marker.appendChild(new Text(text)); + this._accept(void 0); + return true; + } + return false; + } + }; + } +}); + +// node_modules/semver/internal/constants.js +var require_constants = __commonJS({ + "node_modules/semver/internal/constants.js"(exports2, module2) { + var SEMVER_SPEC_VERSION = "2.0.0"; + var MAX_LENGTH = 256; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; + var MAX_SAFE_COMPONENT_LENGTH = 16; + module2.exports = { + SEMVER_SPEC_VERSION, + MAX_LENGTH, + MAX_SAFE_INTEGER, + MAX_SAFE_COMPONENT_LENGTH + }; + } +}); + +// node_modules/semver/internal/debug.js +var require_debug = __commonJS({ + "node_modules/semver/internal/debug.js"(exports2, module2) { + var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => { + }; + module2.exports = debug; + } +}); + +// node_modules/semver/internal/re.js +var require_re = __commonJS({ + "node_modules/semver/internal/re.js"(exports2, module2) { + var { MAX_SAFE_COMPONENT_LENGTH } = require_constants(); + var debug = require_debug(); + exports2 = module2.exports = {}; + var re = exports2.re = []; + var src = exports2.src = []; + var t = exports2.t = {}; + var R = 0; + var createToken = (name2, value, isGlobal) => { + const index = R++; + debug(index, value); + t[name2] = index; + src[index] = value; + re[index] = new RegExp(value, isGlobal ? "g" : void 0); + }; + createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*"); + createToken("NUMERICIDENTIFIERLOOSE", "[0-9]+"); + createToken("NONNUMERICIDENTIFIER", "\\d*[a-zA-Z-][a-zA-Z0-9-]*"); + createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`); + createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NUMERICIDENTIFIER]}|${src[t.NONNUMERICIDENTIFIER]})`); + createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NUMERICIDENTIFIERLOOSE]}|${src[t.NONNUMERICIDENTIFIER]})`); + createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + createToken("BUILDIDENTIFIER", "[0-9A-Za-z-]+"); + createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`); + createToken("FULL", `^${src[t.FULLPLAIN]}$`); + createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`); + createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`); + createToken("GTLT", "((?:<|>)?=?)"); + createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); + createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); + createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COERCE", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:$|[^\\d])`); + createToken("COERCERTL", src[t.COERCE], true); + createToken("LONETILDE", "(?:~>?)"); + createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true); + exports2.tildeTrimReplace = "$1~"; + createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); + createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("LONECARET", "(?:\\^)"); + createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true); + exports2.caretTrimReplace = "$1^"; + createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); + createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); + createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); + exports2.comparatorTrimReplace = "$1$2$3"; + createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`); + createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`); + createToken("STAR", "(<|>)?=?\\s*\\*"); + createToken("GTE0", "^\\s*>=\\s*0.0.0\\s*$"); + createToken("GTE0PRE", "^\\s*>=\\s*0.0.0-0\\s*$"); + } +}); + +// node_modules/semver/internal/parse-options.js +var require_parse_options = __commonJS({ + "node_modules/semver/internal/parse-options.js"(exports2, module2) { + var opts = ["includePrerelease", "loose", "rtl"]; + var parseOptions = (options) => !options ? {} : typeof options !== "object" ? { loose: true } : opts.filter((k) => options[k]).reduce((options2, k) => { + options2[k] = true; + return options2; + }, {}); + module2.exports = parseOptions; + } +}); + +// node_modules/semver/internal/identifiers.js +var require_identifiers = __commonJS({ + "node_modules/semver/internal/identifiers.js"(exports2, module2) { + var numeric = /^[0-9]+$/; + var compareIdentifiers = (a, b) => { + const anum = numeric.test(a); + const 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; + }; + var rcompareIdentifiers = (a, b) => compareIdentifiers(b, a); + module2.exports = { + compareIdentifiers, + rcompareIdentifiers + }; + } +}); + +// node_modules/semver/classes/semver.js +var require_semver = __commonJS({ + "node_modules/semver/classes/semver.js"(exports2, module2) { + var debug = require_debug(); + var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants(); + var { re, t } = require_re(); + var parseOptions = require_parse_options(); + var { compareIdentifiers } = require_identifiers(); + var SemVer = class { + constructor(version2, options) { + options = parseOptions(options); + if (version2 instanceof SemVer) { + if (version2.loose === !!options.loose && version2.includePrerelease === !!options.includePrerelease) { + return version2; + } else { + version2 = version2.version; + } + } else if (typeof version2 !== "string") { + throw new TypeError(`Invalid Version: ${version2}`); + } + if (version2.length > MAX_LENGTH) { + throw new TypeError(`version is longer than ${MAX_LENGTH} characters`); + } + debug("SemVer", version2, options); + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + const m = version2.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); + if (!m) { + throw new TypeError(`Invalid Version: ${version2}`); + } + this.raw = version2; + 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"); + } + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split(".").map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num; + } + } + return id; + }); + } + this.build = m[5] ? m[5].split(".") : []; + this.format(); + } + format() { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join(".")}`; + } + return this.version; + } + toString() { + return this.version; + } + compare(other) { + debug("SemVer.compare", this.version, this.options, other); + if (!(other instanceof SemVer)) { + if (typeof other === "string" && other === this.version) { + return 0; + } + other = new SemVer(other, this.options); + } + if (other.version === this.version) { + return 0; + } + return this.compareMain(other) || this.comparePre(other); + } + compareMain(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); + } + comparePre(other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options); + } + 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; + } + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + compareBuild(other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options); + } + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + inc(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": + this.prerelease.length = 0; + this.inc("patch", identifier); + this.inc("pre", identifier); + break; + case "prerelease": + if (this.prerelease.length === 0) { + this.inc("patch", identifier); + } + this.inc("pre", identifier); + break; + case "major": + 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.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break; + case "patch": + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break; + case "pre": + if (this.prerelease.length === 0) { + this.prerelease = [0]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === "number") { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + this.prerelease.push(0); + } + } + if (identifier) { + 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; + } + }; + module2.exports = SemVer; + } +}); + +// node_modules/semver/functions/parse.js +var require_parse = __commonJS({ + "node_modules/semver/functions/parse.js"(exports2, module2) { + var { MAX_LENGTH } = require_constants(); + var { re, t } = require_re(); + var SemVer = require_semver(); + var parseOptions = require_parse_options(); + var parse5 = (version2, options) => { + options = parseOptions(options); + if (version2 instanceof SemVer) { + return version2; + } + if (typeof version2 !== "string") { + return null; + } + if (version2.length > MAX_LENGTH) { + return null; + } + const r = options.loose ? re[t.LOOSE] : re[t.FULL]; + if (!r.test(version2)) { + return null; + } + try { + return new SemVer(version2, options); + } catch (er) { + return null; + } + }; + module2.exports = parse5; + } +}); + +// node_modules/semver/functions/valid.js +var require_valid = __commonJS({ + "node_modules/semver/functions/valid.js"(exports2, module2) { + var parse5 = require_parse(); + var valid = (version2, options) => { + const v = parse5(version2, options); + return v ? v.version : null; + }; + module2.exports = valid; + } +}); + +// node_modules/semver/functions/clean.js +var require_clean = __commonJS({ + "node_modules/semver/functions/clean.js"(exports2, module2) { + var parse5 = require_parse(); + var clean = (version2, options) => { + const s = parse5(version2.trim().replace(/^[=v]+/, ""), options); + return s ? s.version : null; + }; + module2.exports = clean; + } +}); + +// node_modules/semver/functions/inc.js +var require_inc = __commonJS({ + "node_modules/semver/functions/inc.js"(exports2, module2) { + var SemVer = require_semver(); + var inc = (version2, release, options, identifier) => { + if (typeof options === "string") { + identifier = options; + options = void 0; + } + try { + return new SemVer(version2, options).inc(release, identifier).version; + } catch (er) { + return null; + } + }; + module2.exports = inc; + } +}); + +// node_modules/semver/functions/compare.js +var require_compare = __commonJS({ + "node_modules/semver/functions/compare.js"(exports2, module2) { + var SemVer = require_semver(); + var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose)); + module2.exports = compare; + } +}); + +// node_modules/semver/functions/eq.js +var require_eq = __commonJS({ + "node_modules/semver/functions/eq.js"(exports2, module2) { + var compare = require_compare(); + var eq = (a, b, loose) => compare(a, b, loose) === 0; + module2.exports = eq; + } +}); + +// node_modules/semver/functions/diff.js +var require_diff2 = __commonJS({ + "node_modules/semver/functions/diff.js"(exports2, module2) { + var parse5 = require_parse(); + var eq = require_eq(); + var diff = (version1, version2) => { + if (eq(version1, version2)) { + return null; + } else { + const v12 = parse5(version1); + const v2 = parse5(version2); + const hasPre = v12.prerelease.length || v2.prerelease.length; + const prefix = hasPre ? "pre" : ""; + const defaultResult = hasPre ? "prerelease" : ""; + for (const key in v12) { + if (key === "major" || key === "minor" || key === "patch") { + if (v12[key] !== v2[key]) { + return prefix + key; + } + } + } + return defaultResult; + } + }; + module2.exports = diff; + } +}); + +// node_modules/semver/functions/major.js +var require_major = __commonJS({ + "node_modules/semver/functions/major.js"(exports2, module2) { + var SemVer = require_semver(); + var major = (a, loose) => new SemVer(a, loose).major; + module2.exports = major; + } +}); + +// node_modules/semver/functions/minor.js +var require_minor = __commonJS({ + "node_modules/semver/functions/minor.js"(exports2, module2) { + var SemVer = require_semver(); + var minor = (a, loose) => new SemVer(a, loose).minor; + module2.exports = minor; + } +}); + +// node_modules/semver/functions/patch.js +var require_patch = __commonJS({ + "node_modules/semver/functions/patch.js"(exports2, module2) { + var SemVer = require_semver(); + var patch = (a, loose) => new SemVer(a, loose).patch; + module2.exports = patch; + } +}); + +// node_modules/semver/functions/prerelease.js +var require_prerelease = __commonJS({ + "node_modules/semver/functions/prerelease.js"(exports2, module2) { + var parse5 = require_parse(); + var prerelease = (version2, options) => { + const parsed = parse5(version2, options); + return parsed && parsed.prerelease.length ? parsed.prerelease : null; + }; + module2.exports = prerelease; + } +}); + +// node_modules/semver/functions/rcompare.js +var require_rcompare = __commonJS({ + "node_modules/semver/functions/rcompare.js"(exports2, module2) { + var compare = require_compare(); + var rcompare = (a, b, loose) => compare(b, a, loose); + module2.exports = rcompare; + } +}); + +// node_modules/semver/functions/compare-loose.js +var require_compare_loose = __commonJS({ + "node_modules/semver/functions/compare-loose.js"(exports2, module2) { + var compare = require_compare(); + var compareLoose = (a, b) => compare(a, b, true); + module2.exports = compareLoose; + } +}); + +// node_modules/semver/functions/compare-build.js +var require_compare_build = __commonJS({ + "node_modules/semver/functions/compare-build.js"(exports2, module2) { + var SemVer = require_semver(); + var compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose); + const versionB = new SemVer(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB); + }; + module2.exports = compareBuild; + } +}); + +// node_modules/semver/functions/sort.js +var require_sort = __commonJS({ + "node_modules/semver/functions/sort.js"(exports2, module2) { + var compareBuild = require_compare_build(); + var sort = (list2, loose) => list2.sort((a, b) => compareBuild(a, b, loose)); + module2.exports = sort; + } +}); + +// node_modules/semver/functions/rsort.js +var require_rsort = __commonJS({ + "node_modules/semver/functions/rsort.js"(exports2, module2) { + var compareBuild = require_compare_build(); + var rsort = (list2, loose) => list2.sort((a, b) => compareBuild(b, a, loose)); + module2.exports = rsort; + } +}); + +// node_modules/semver/functions/gt.js +var require_gt = __commonJS({ + "node_modules/semver/functions/gt.js"(exports2, module2) { + var compare = require_compare(); + var gt = (a, b, loose) => compare(a, b, loose) > 0; + module2.exports = gt; + } +}); + +// node_modules/semver/functions/lt.js +var require_lt = __commonJS({ + "node_modules/semver/functions/lt.js"(exports2, module2) { + var compare = require_compare(); + var lt = (a, b, loose) => compare(a, b, loose) < 0; + module2.exports = lt; + } +}); + +// node_modules/semver/functions/neq.js +var require_neq = __commonJS({ + "node_modules/semver/functions/neq.js"(exports2, module2) { + var compare = require_compare(); + var neq = (a, b, loose) => compare(a, b, loose) !== 0; + module2.exports = neq; + } +}); + +// node_modules/semver/functions/gte.js +var require_gte = __commonJS({ + "node_modules/semver/functions/gte.js"(exports2, module2) { + var compare = require_compare(); + var gte = (a, b, loose) => compare(a, b, loose) >= 0; + module2.exports = gte; + } +}); + +// node_modules/semver/functions/lte.js +var require_lte = __commonJS({ + "node_modules/semver/functions/lte.js"(exports2, module2) { + var compare = require_compare(); + var lte = (a, b, loose) => compare(a, b, loose) <= 0; + module2.exports = lte; + } +}); + +// node_modules/semver/functions/cmp.js +var require_cmp = __commonJS({ + "node_modules/semver/functions/cmp.js"(exports2, module2) { + var eq = require_eq(); + var neq = require_neq(); + var gt = require_gt(); + var gte = require_gte(); + var lt = require_lt(); + var lte = require_lte(); + var 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}`); + } + }; + module2.exports = cmp; + } +}); + +// node_modules/semver/functions/coerce.js +var require_coerce = __commonJS({ + "node_modules/semver/functions/coerce.js"(exports2, module2) { + var SemVer = require_semver(); + var parse5 = require_parse(); + var { re, t } = require_re(); + var coerce = (version2, options) => { + if (version2 instanceof SemVer) { + return version2; + } + if (typeof version2 === "number") { + version2 = String(version2); + } + if (typeof version2 !== "string") { + return null; + } + options = options || {}; + let match = null; + if (!options.rtl) { + match = version2.match(re[t.COERCE]); + } else { + let next; + while ((next = re[t.COERCERTL].exec(version2)) && (!match || match.index + match[0].length !== version2.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; + } + re[t.COERCERTL].lastIndex = -1; + } + if (match === null) + return null; + return parse5(`${match[2]}.${match[3] || "0"}.${match[4] || "0"}`, options); + }; + module2.exports = coerce; + } +}); + +// node_modules/yallist/iterator.js +var require_iterator = __commonJS({ + "node_modules/yallist/iterator.js"(exports2, module2) { + "use strict"; + module2.exports = function(Yallist) { + Yallist.prototype[Symbol.iterator] = function* () { + for (let walker = this.head; walker; walker = walker.next) { + yield walker.value; + } + }; + }; + } +}); + +// node_modules/yallist/yallist.js +var require_yallist = __commonJS({ + "node_modules/yallist/yallist.js"(exports2, module2) { + "use strict"; + module2.exports = Yallist; + Yallist.Node = Node; + Yallist.create = Yallist; + function Yallist(list2) { + var self2 = this; + if (!(self2 instanceof Yallist)) { + self2 = new Yallist(); + } + self2.tail = null; + self2.head = null; + self2.length = 0; + if (list2 && typeof list2.forEach === "function") { + list2.forEach(function(item) { + self2.push(item); + }); + } else if (arguments.length > 0) { + for (var i = 0, l = arguments.length; i < l; i++) { + self2.push(arguments[i]); + } + } + return self2; + } + 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; + return next; + }; + 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 void 0; + } + 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 void 0; + } + 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++) { + 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++) { + 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.splice = function(start, deleteCount, ...nodes) { + if (start > this.length) { + start = this.length - 1; + } + if (start < 0) { + start = this.length + start; + } + for (var i = 0, walker = this.head; walker !== null && i < start; i++) { + walker = walker.next; + } + var ret = []; + for (var i = 0; walker && i < deleteCount; i++) { + ret.push(walker.value); + walker = this.removeNode(walker); + } + if (walker === null) { + walker = this.tail; + } + if (walker !== this.head && walker !== this.tail) { + walker = walker.prev; + } + for (var i = 0; i < nodes.length; i++) { + walker = insert(this, walker, nodes[i]); + } + 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 insert(self2, node, value) { + var inserted = node === self2.head ? new Node(value, null, node, self2) : new Node(value, node, node.next, self2); + if (inserted.next === null) { + self2.tail = inserted; + } + if (inserted.prev === null) { + self2.head = inserted; + } + self2.length++; + return inserted; + } + function push(self2, item) { + self2.tail = new Node(item, self2.tail, null, self2); + if (!self2.head) { + self2.head = self2.tail; + } + self2.length++; + } + function unshift(self2, item) { + self2.head = new Node(item, null, self2.head, self2); + if (!self2.tail) { + self2.tail = self2.head; + } + self2.length++; + } + function Node(value, prev, next, list2) { + if (!(this instanceof Node)) { + return new Node(value, prev, next, list2); + } + this.list = list2; + 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 { + require_iterator()(Yallist); + } catch (er) { + } + } +}); + +// node_modules/lru-cache/index.js +var require_lru_cache = __commonJS({ + "node_modules/lru-cache/index.js"(exports2, module2) { + "use strict"; + var Yallist = require_yallist(); + var MAX = Symbol("max"); + var LENGTH = Symbol("length"); + var LENGTH_CALCULATOR = Symbol("lengthCalculator"); + var ALLOW_STALE = Symbol("allowStale"); + var MAX_AGE = Symbol("maxAge"); + var DISPOSE = Symbol("dispose"); + var NO_DISPOSE_ON_SET = Symbol("noDisposeOnSet"); + var LRU_LIST = Symbol("lruList"); + var CACHE = Symbol("cache"); + var UPDATE_AGE_ON_GET = Symbol("updateAgeOnGet"); + var naiveLength = () => 1; + var LRUCache = class { + constructor(options) { + if (typeof options === "number") + options = { max: options }; + if (!options) + options = {}; + if (options.max && (typeof options.max !== "number" || options.max < 0)) + throw new TypeError("max must be a non-negative number"); + const max = this[MAX] = options.max || Infinity; + const lc = options.length || naiveLength; + this[LENGTH_CALCULATOR] = typeof lc !== "function" ? naiveLength : lc; + this[ALLOW_STALE] = options.stale || false; + if (options.maxAge && typeof options.maxAge !== "number") + throw new TypeError("maxAge must be a number"); + this[MAX_AGE] = options.maxAge || 0; + this[DISPOSE] = options.dispose; + this[NO_DISPOSE_ON_SET] = options.noDisposeOnSet || false; + this[UPDATE_AGE_ON_GET] = options.updateAgeOnGet || false; + this.reset(); + } + set max(mL) { + if (typeof mL !== "number" || mL < 0) + throw new TypeError("max must be a non-negative number"); + this[MAX] = mL || Infinity; + trim(this); + } + get max() { + return this[MAX]; + } + set allowStale(allowStale) { + this[ALLOW_STALE] = !!allowStale; + } + get allowStale() { + return this[ALLOW_STALE]; + } + set maxAge(mA) { + if (typeof mA !== "number") + throw new TypeError("maxAge must be a non-negative number"); + this[MAX_AGE] = mA; + trim(this); + } + get maxAge() { + return this[MAX_AGE]; + } + set lengthCalculator(lC) { + if (typeof lC !== "function") + lC = naiveLength; + if (lC !== this[LENGTH_CALCULATOR]) { + this[LENGTH_CALCULATOR] = lC; + this[LENGTH] = 0; + this[LRU_LIST].forEach((hit) => { + hit.length = this[LENGTH_CALCULATOR](hit.value, hit.key); + this[LENGTH] += hit.length; + }); + } + trim(this); + } + get lengthCalculator() { + return this[LENGTH_CALCULATOR]; + } + get length() { + return this[LENGTH]; + } + get itemCount() { + return this[LRU_LIST].length; + } + rforEach(fn, thisp) { + thisp = thisp || this; + for (let walker = this[LRU_LIST].tail; walker !== null; ) { + const prev = walker.prev; + forEachStep(this, fn, walker, thisp); + walker = prev; + } + } + forEach(fn, thisp) { + thisp = thisp || this; + for (let walker = this[LRU_LIST].head; walker !== null; ) { + const next = walker.next; + forEachStep(this, fn, walker, thisp); + walker = next; + } + } + keys() { + return this[LRU_LIST].toArray().map((k) => k.key); + } + values() { + return this[LRU_LIST].toArray().map((k) => k.value); + } + reset() { + if (this[DISPOSE] && this[LRU_LIST] && this[LRU_LIST].length) { + this[LRU_LIST].forEach((hit) => this[DISPOSE](hit.key, hit.value)); + } + this[CACHE] = new Map(); + this[LRU_LIST] = new Yallist(); + this[LENGTH] = 0; + } + dump() { + return this[LRU_LIST].map((hit) => isStale(this, hit) ? false : { + k: hit.key, + v: hit.value, + e: hit.now + (hit.maxAge || 0) + }).toArray().filter((h) => h); + } + dumpLru() { + return this[LRU_LIST]; + } + set(key, value, maxAge) { + maxAge = maxAge || this[MAX_AGE]; + if (maxAge && typeof maxAge !== "number") + throw new TypeError("maxAge must be a number"); + const now = maxAge ? Date.now() : 0; + const len = this[LENGTH_CALCULATOR](value, key); + if (this[CACHE].has(key)) { + if (len > this[MAX]) { + del(this, this[CACHE].get(key)); + return false; + } + const node = this[CACHE].get(key); + const item = node.value; + if (this[DISPOSE]) { + if (!this[NO_DISPOSE_ON_SET]) + this[DISPOSE](key, item.value); + } + item.now = now; + item.maxAge = maxAge; + item.value = value; + this[LENGTH] += len - item.length; + item.length = len; + this.get(key); + trim(this); + return true; + } + const hit = new Entry(key, value, len, now, maxAge); + if (hit.length > this[MAX]) { + if (this[DISPOSE]) + this[DISPOSE](key, value); + return false; + } + this[LENGTH] += hit.length; + this[LRU_LIST].unshift(hit); + this[CACHE].set(key, this[LRU_LIST].head); + trim(this); + return true; + } + has(key) { + if (!this[CACHE].has(key)) + return false; + const hit = this[CACHE].get(key).value; + return !isStale(this, hit); + } + get(key) { + return get(this, key, true); + } + peek(key) { + return get(this, key, false); + } + pop() { + const node = this[LRU_LIST].tail; + if (!node) + return null; + del(this, node); + return node.value; + } + del(key) { + del(this, this[CACHE].get(key)); + } + load(arr) { + this.reset(); + const now = Date.now(); + for (let l = arr.length - 1; l >= 0; l--) { + const hit = arr[l]; + const expiresAt = hit.e || 0; + if (expiresAt === 0) + this.set(hit.k, hit.v); + else { + const maxAge = expiresAt - now; + if (maxAge > 0) { + this.set(hit.k, hit.v, maxAge); + } + } + } + } + prune() { + this[CACHE].forEach((value, key) => get(this, key, false)); + } + }; + var get = (self2, key, doUse) => { + const node = self2[CACHE].get(key); + if (node) { + const hit = node.value; + if (isStale(self2, hit)) { + del(self2, node); + if (!self2[ALLOW_STALE]) + return void 0; + } else { + if (doUse) { + if (self2[UPDATE_AGE_ON_GET]) + node.value.now = Date.now(); + self2[LRU_LIST].unshiftNode(node); + } + } + return hit.value; + } + }; + var isStale = (self2, hit) => { + if (!hit || !hit.maxAge && !self2[MAX_AGE]) + return false; + const diff = Date.now() - hit.now; + return hit.maxAge ? diff > hit.maxAge : self2[MAX_AGE] && diff > self2[MAX_AGE]; + }; + var trim = (self2) => { + if (self2[LENGTH] > self2[MAX]) { + for (let walker = self2[LRU_LIST].tail; self2[LENGTH] > self2[MAX] && walker !== null; ) { + const prev = walker.prev; + del(self2, walker); + walker = prev; + } + } + }; + var del = (self2, node) => { + if (node) { + const hit = node.value; + if (self2[DISPOSE]) + self2[DISPOSE](hit.key, hit.value); + self2[LENGTH] -= hit.length; + self2[CACHE].delete(hit.key); + self2[LRU_LIST].removeNode(node); + } + }; + var Entry = class { + constructor(key, value, length, now, maxAge) { + this.key = key; + this.value = value; + this.length = length; + this.now = now; + this.maxAge = maxAge || 0; + } + }; + var forEachStep = (self2, fn, node, thisp) => { + let hit = node.value; + if (isStale(self2, hit)) { + del(self2, node); + if (!self2[ALLOW_STALE]) + hit = void 0; + } + if (hit) + fn.call(thisp, hit.value, hit.key, self2); + }; + module2.exports = LRUCache; + } +}); + +// node_modules/semver/classes/range.js +var require_range = __commonJS({ + "node_modules/semver/classes/range.js"(exports2, module2) { + var Range39 = class { + constructor(range, options) { + options = parseOptions(options); + if (range instanceof Range39) { + if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) { + return range; + } else { + return new Range39(range.raw, options); + } + } + if (range instanceof Comparator) { + this.raw = range.value; + this.set = [[range]]; + this.format(); + return this; + } + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + this.raw = range; + this.set = range.split(/\s*\|\|\s*/).map((range2) => this.parseRange(range2.trim())).filter((c) => c.length); + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${range}`); + } + if (this.set.length > 1) { + const first = this.set[0]; + this.set = this.set.filter((c) => !isNullSet(c[0])); + if (this.set.length === 0) + this.set = [first]; + else if (this.set.length > 1) { + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break; + } + } + } + } + this.format(); + } + format() { + this.range = this.set.map((comps) => { + return comps.join(" ").trim(); + }).join("||").trim(); + return this.range; + } + toString() { + return this.range; + } + parseRange(range) { + range = range.trim(); + const memoOpts = Object.keys(this.options).join(","); + const memoKey = `parseRange:${memoOpts}:${range}`; + const cached = cache.get(memoKey); + if (cached) + return cached; + const loose = this.options.loose; + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug("hyphen replace", range); + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); + debug("comparator trim", range, re[t.COMPARATORTRIM]); + range = range.replace(re[t.TILDETRIM], tildeTrimReplace); + range = range.replace(re[t.CARETTRIM], caretTrimReplace); + range = range.split(/\s+/).join(" "); + const compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options)).filter(this.options.loose ? (comp) => !!comp.match(compRe) : () => true).map((comp) => new Comparator(comp, this.options)); + const l = rangeList.length; + const rangeMap = new Map(); + for (const comp of rangeList) { + if (isNullSet(comp)) + return [comp]; + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has("")) + rangeMap.delete(""); + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result; + } + intersects(range, options) { + if (!(range instanceof Range39)) { + throw new TypeError("a Range is required"); + } + return this.set.some((thisComparators) => { + return isSatisfiable(thisComparators, options) && range.set.some((rangeComparators) => { + return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options); + }); + }); + }); + }); + } + test(version2) { + if (!version2) { + return false; + } + if (typeof version2 === "string") { + try { + version2 = new SemVer(version2, this.options); + } catch (er) { + return false; + } + } + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version2, this.options)) { + return true; + } + } + return false; + } + }; + module2.exports = Range39; + var LRU = require_lru_cache(); + var cache = new LRU({ max: 1e3 }); + var parseOptions = require_parse_options(); + var Comparator = require_comparator(); + var debug = require_debug(); + var SemVer = require_semver(); + var { + re, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace + } = require_re(); + var isNullSet = (c) => c.value === "<0.0.0-0"; + var isAny = (c) => c.value === ""; + var isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options); + }); + testComparator = remainingComparators.pop(); + } + return result; + }; + var 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; + }; + var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; + var replaceTildes = (comp, options) => comp.trim().split(/\s+/).map((comp2) => { + return replaceTilde(comp2, options); + }).join(" "); + var replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; + return comp.replace(r, (_, M, m, p, pr) => { + debug("tilde", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0 <${+M + 1}.0.0-0`; + } else if (isX(p)) { + ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug("replaceTilde pr", pr); + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + debug("tilde return", ret); + return ret; + }); + }; + var replaceCarets = (comp, options) => comp.trim().split(/\s+/).map((comp2) => { + return replaceCaret(comp2, options); + }).join(" "); + var replaceCaret = (comp, options) => { + debug("caret", comp, options); + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("caret", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === "0") { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug("replaceCaret pr", pr); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; + } + } else { + debug("no pr"); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}${z} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}${z} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; + } + } + debug("caret return", ret); + return ret; + }); + }; + var replaceXRanges = (comp, options) => { + debug("replaceXRanges", comp, options); + return comp.split(/\s+/).map((comp2) => { + return replaceXRange(comp2, options); + }).join(" "); + }; + var replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug("xRange", comp, ret, gtlt, M, m, p, pr); + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + if (gtlt === "=" && anyX) { + gtlt = ""; + } + pr = options.includePrerelease ? "-0" : ""; + if (xM) { + if (gtlt === ">" || gtlt === "<") { + ret = "<0.0.0-0"; + } else { + ret = "*"; + } + } else if (gtlt && anyX) { + if (xm) { + m = 0; + } + p = 0; + if (gtlt === ">") { + gtlt = ">="; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === "<=") { + gtlt = "<"; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + if (gtlt === "<") + pr = "-0"; + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; + } + debug("xRange return", ret); + return ret; + }); + }; + var replaceStars = (comp, options) => { + debug("replaceStars", comp, options); + return comp.trim().replace(re[t.STAR], ""); + }; + var replaceGTE0 = (comp, options) => { + debug("replaceGTE0", comp, options); + return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); + }; + var hyphenReplace = (incPr) => ($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${incPr ? "-0" : ""}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? "-0" : ""}`; + } + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + return `${from} ${to}`.trim(); + }; + var testSet = (set, version2, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version2)) { + return false; + } + } + if (version2.prerelease.length && !options.includePrerelease) { + for (let i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === Comparator.ANY) { + continue; + } + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver; + if (allowed.major === version2.major && allowed.minor === version2.minor && allowed.patch === version2.patch) { + return true; + } + } + } + return false; + } + return true; + }; + } +}); + +// node_modules/semver/classes/comparator.js +var require_comparator = __commonJS({ + "node_modules/semver/classes/comparator.js"(exports2, module2) { + var ANY = Symbol("SemVer ANY"); + var Comparator = class { + static get ANY() { + return ANY; + } + constructor(comp, options) { + options = parseOptions(options); + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp; + } else { + comp = comp.value; + } + } + 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); + } + parse(comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`); + } + this.operator = m[1] !== void 0 ? m[1] : ""; + if (this.operator === "=") { + this.operator = ""; + } + if (!m[2]) { + this.semver = ANY; + } else { + this.semver = new SemVer(m[2], this.options.loose); + } + } + toString() { + return this.value; + } + test(version2) { + debug("Comparator.test", version2, this.options.loose); + if (this.semver === ANY || version2 === ANY) { + return true; + } + if (typeof version2 === "string") { + try { + version2 = new SemVer(version2, this.options); + } catch (er) { + return false; + } + } + return cmp(version2, this.operator, this.semver, this.options); + } + intersects(comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError("a Comparator is required"); + } + if (!options || typeof options !== "object") { + options = { + loose: !!options, + includePrerelease: false + }; + } + if (this.operator === "") { + if (this.value === "") { + return true; + } + return new Range39(comp.value, options).test(this.value); + } else if (comp.operator === "") { + if (comp.value === "") { + return true; + } + return new Range39(this.value, options).test(comp.semver); + } + const sameDirectionIncreasing = (this.operator === ">=" || this.operator === ">") && (comp.operator === ">=" || comp.operator === ">"); + const sameDirectionDecreasing = (this.operator === "<=" || this.operator === "<") && (comp.operator === "<=" || comp.operator === "<"); + const sameSemVer = this.semver.version === comp.semver.version; + const differentDirectionsInclusive = (this.operator === ">=" || this.operator === "<=") && (comp.operator === ">=" || comp.operator === "<="); + const oppositeDirectionsLessThan = cmp(this.semver, "<", comp.semver, options) && (this.operator === ">=" || this.operator === ">") && (comp.operator === "<=" || comp.operator === "<"); + const oppositeDirectionsGreaterThan = cmp(this.semver, ">", comp.semver, options) && (this.operator === "<=" || this.operator === "<") && (comp.operator === ">=" || comp.operator === ">"); + return sameDirectionIncreasing || sameDirectionDecreasing || sameSemVer && differentDirectionsInclusive || oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; + } + }; + module2.exports = Comparator; + var parseOptions = require_parse_options(); + var { re, t } = require_re(); + var cmp = require_cmp(); + var debug = require_debug(); + var SemVer = require_semver(); + var Range39 = require_range(); + } +}); + +// node_modules/semver/functions/satisfies.js +var require_satisfies = __commonJS({ + "node_modules/semver/functions/satisfies.js"(exports2, module2) { + var Range39 = require_range(); + var satisfies = (version2, range, options) => { + try { + range = new Range39(range, options); + } catch (er) { + return false; + } + return range.test(version2); + }; + module2.exports = satisfies; + } +}); + +// node_modules/semver/ranges/to-comparators.js +var require_to_comparators = __commonJS({ + "node_modules/semver/ranges/to-comparators.js"(exports2, module2) { + var Range39 = require_range(); + var toComparators = (range, options) => new Range39(range, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + module2.exports = toComparators; + } +}); + +// node_modules/semver/ranges/max-satisfying.js +var require_max_satisfying = __commonJS({ + "node_modules/semver/ranges/max-satisfying.js"(exports2, module2) { + var SemVer = require_semver(); + var Range39 = require_range(); + var maxSatisfying = (versions, range, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range39(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!max || maxSV.compare(v) === -1) { + max = v; + maxSV = new SemVer(max, options); + } + } + }); + return max; + }; + module2.exports = maxSatisfying; + } +}); + +// node_modules/semver/ranges/min-satisfying.js +var require_min_satisfying = __commonJS({ + "node_modules/semver/ranges/min-satisfying.js"(exports2, module2) { + var SemVer = require_semver(); + var Range39 = require_range(); + var minSatisfying = (versions, range, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range39(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!min || minSV.compare(v) === 1) { + min = v; + minSV = new SemVer(min, options); + } + } + }); + return min; + }; + module2.exports = minSatisfying; + } +}); + +// node_modules/semver/ranges/min-version.js +var require_min_version = __commonJS({ + "node_modules/semver/ranges/min-version.js"(exports2, module2) { + var SemVer = require_semver(); + var Range39 = require_range(); + var gt = require_gt(); + var minVersion = (range, loose) => { + range = new Range39(range, loose); + let 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 (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let setMin = null; + comparators.forEach((comparator) => { + const 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(); + case "": + case ">=": + if (!setMin || gt(compver, setMin)) { + setMin = compver; + } + break; + case "<": + case "<=": + break; + default: + throw new Error(`Unexpected operation: ${comparator.operator}`); + } + }); + if (setMin && (!minver || gt(minver, setMin))) + minver = setMin; + } + if (minver && range.test(minver)) { + return minver; + } + return null; + }; + module2.exports = minVersion; + } +}); + +// node_modules/semver/ranges/valid.js +var require_valid2 = __commonJS({ + "node_modules/semver/ranges/valid.js"(exports2, module2) { + var Range39 = require_range(); + var validRange = (range, options) => { + try { + return new Range39(range, options).range || "*"; + } catch (er) { + return null; + } + }; + module2.exports = validRange; + } +}); + +// node_modules/semver/ranges/outside.js +var require_outside = __commonJS({ + "node_modules/semver/ranges/outside.js"(exports2, module2) { + var SemVer = require_semver(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var Range39 = require_range(); + var satisfies = require_satisfies(); + var gt = require_gt(); + var lt = require_lt(); + var lte = require_lte(); + var gte = require_gte(); + var outside = (version2, range, hilo, options) => { + version2 = new SemVer(version2, options); + range = new Range39(range, options); + let 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 (satisfies(version2, range, options)) { + return false; + } + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let high = null; + let low = null; + comparators.forEach((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 (high.operator === comp || high.operator === ecomp) { + return false; + } + if ((!low.operator || low.operator === comp) && ltefn(version2, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version2, low.semver)) { + return false; + } + } + return true; + }; + module2.exports = outside; + } +}); + +// node_modules/semver/ranges/gtr.js +var require_gtr = __commonJS({ + "node_modules/semver/ranges/gtr.js"(exports2, module2) { + var outside = require_outside(); + var gtr = (version2, range, options) => outside(version2, range, ">", options); + module2.exports = gtr; + } +}); + +// node_modules/semver/ranges/ltr.js +var require_ltr = __commonJS({ + "node_modules/semver/ranges/ltr.js"(exports2, module2) { + var outside = require_outside(); + var ltr = (version2, range, options) => outside(version2, range, "<", options); + module2.exports = ltr; + } +}); + +// node_modules/semver/ranges/intersects.js +var require_intersects = __commonJS({ + "node_modules/semver/ranges/intersects.js"(exports2, module2) { + var Range39 = require_range(); + var intersects = (r1, r2, options) => { + r1 = new Range39(r1, options); + r2 = new Range39(r2, options); + return r1.intersects(r2); + }; + module2.exports = intersects; + } +}); + +// node_modules/semver/ranges/simplify.js +var require_simplify = __commonJS({ + "node_modules/semver/ranges/simplify.js"(exports2, module2) { + var satisfies = require_satisfies(); + var compare = require_compare(); + module2.exports = (versions, range, options) => { + const set = []; + let min = null; + let prev = null; + const v = versions.sort((a, b) => compare(a, b, options)); + for (const version2 of v) { + const included = satisfies(version2, range, options); + if (included) { + prev = version2; + if (!min) + min = version2; + } else { + if (prev) { + set.push([min, prev]); + } + prev = null; + min = null; + } + } + if (min) + set.push([min, null]); + const ranges = []; + for (const [min2, max] of set) { + if (min2 === max) + ranges.push(min2); + else if (!max && min2 === v[0]) + ranges.push("*"); + else if (!max) + ranges.push(`>=${min2}`); + else if (min2 === v[0]) + ranges.push(`<=${max}`); + else + ranges.push(`${min2} - ${max}`); + } + const simplified = ranges.join(" || "); + const original = typeof range.raw === "string" ? range.raw : String(range); + return simplified.length < original.length ? simplified : range; + }; + } +}); + +// node_modules/semver/ranges/subset.js +var require_subset = __commonJS({ + "node_modules/semver/ranges/subset.js"(exports2, module2) { + var Range39 = require_range(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var satisfies = require_satisfies(); + var compare = require_compare(); + var subset = (sub, dom, options = {}) => { + if (sub === dom) + return true; + sub = new Range39(sub, options); + dom = new Range39(dom, options); + let sawNonNull = false; + OUTER: + for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) + continue OUTER; + } + if (sawNonNull) + return false; + } + return true; + }; + var simpleSubset = (sub, dom, options) => { + if (sub === dom) + return true; + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) + return true; + else if (options.includePrerelease) + sub = [new Comparator(">=0.0.0-0")]; + else + sub = [new Comparator(">=0.0.0")]; + } + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) + return true; + else + dom = [new Comparator(">=0.0.0")]; + } + const eqSet = new Set(); + let gt, lt; + for (const c of sub) { + if (c.operator === ">" || c.operator === ">=") + gt = higherGT(gt, c, options); + else if (c.operator === "<" || c.operator === "<=") + lt = lowerLT(lt, c, options); + else + eqSet.add(c.semver); + } + if (eqSet.size > 1) + return null; + let gtltComp; + if (gt && lt) { + gtltComp = compare(gt.semver, lt.semver, options); + if (gtltComp > 0) + return null; + else if (gtltComp === 0 && (gt.operator !== ">=" || lt.operator !== "<=")) + return null; + } + for (const eq of eqSet) { + if (gt && !satisfies(eq, String(gt), options)) + return null; + if (lt && !satisfies(eq, String(lt), options)) + return null; + for (const c of dom) { + if (!satisfies(eq, String(c), options)) + return false; + } + return true; + } + let higher, lower; + let hasDomLT, hasDomGT; + let needDomLTPre = lt && !options.includePrerelease && lt.semver.prerelease.length ? lt.semver : false; + let needDomGTPre = gt && !options.includePrerelease && gt.semver.prerelease.length ? gt.semver : false; + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt.operator === "<" && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">="; + hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<="; + if (gt) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === ">" || c.operator === ">=") { + higher = higherGT(gt, c, options); + if (higher === c && higher !== gt) + return false; + } else if (gt.operator === ">=" && !satisfies(gt.semver, String(c), options)) + return false; + } + if (lt) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomLTPre.major && c.semver.minor === needDomLTPre.minor && c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === "<" || c.operator === "<=") { + lower = lowerLT(lt, c, options); + if (lower === c && lower !== lt) + return false; + } else if (lt.operator === "<=" && !satisfies(lt.semver, String(c), options)) + return false; + } + if (!c.operator && (lt || gt) && gtltComp !== 0) + return false; + } + if (gt && hasDomLT && !lt && gtltComp !== 0) + return false; + if (lt && hasDomGT && !gt && gtltComp !== 0) + return false; + if (needDomGTPre || needDomLTPre) + return false; + return true; + }; + var higherGT = (a, b, options) => { + if (!a) + return b; + const comp = compare(a.semver, b.semver, options); + return comp > 0 ? a : comp < 0 ? b : b.operator === ">" && a.operator === ">=" ? b : a; + }; + var lowerLT = (a, b, options) => { + if (!a) + return b; + const comp = compare(a.semver, b.semver, options); + return comp < 0 ? a : comp > 0 ? b : b.operator === "<" && a.operator === "<=" ? b : a; + }; + module2.exports = subset; + } +}); + +// node_modules/semver/index.js +var require_semver2 = __commonJS({ + "node_modules/semver/index.js"(exports2, module2) { + var internalRe = require_re(); + module2.exports = { + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: require_constants().SEMVER_SPEC_VERSION, + SemVer: require_semver(), + compareIdentifiers: require_identifiers().compareIdentifiers, + rcompareIdentifiers: require_identifiers().rcompareIdentifiers, + parse: require_parse(), + valid: require_valid(), + clean: require_clean(), + inc: require_inc(), + diff: require_diff2(), + major: require_major(), + minor: require_minor(), + patch: require_patch(), + prerelease: require_prerelease(), + compare: require_compare(), + rcompare: require_rcompare(), + compareLoose: require_compare_loose(), + compareBuild: require_compare_build(), + sort: require_sort(), + rsort: require_rsort(), + gt: require_gt(), + lt: require_lt(), + eq: require_eq(), + neq: require_neq(), + gte: require_gte(), + lte: require_lte(), + cmp: require_cmp(), + coerce: require_coerce(), + Comparator: require_comparator(), + Range: require_range(), + satisfies: require_satisfies(), + toComparators: require_to_comparators(), + maxSatisfying: require_max_satisfying(), + minSatisfying: require_min_satisfying(), + minVersion: require_min_version(), + validRange: require_valid2(), + outside: require_outside(), + gtr: require_gtr(), + ltr: require_ltr(), + intersects: require_intersects(), + simplifyRange: require_simplify(), + subset: require_subset() + }; + } +}); + +// src/model/installBuffer.ts +var import_events16, logger32, State, InstallBuffer; +var init_installBuffer = __esm({ + "src/model/installBuffer.ts"() { + import_events16 = __toModule(require("events")); + init_status(); + logger32 = require_logger2()("model-installBuffer"); + (function(State3) { + State3[State3["Waiting"] = 0] = "Waiting"; + State3[State3["Faild"] = 1] = "Faild"; + State3[State3["Progressing"] = 2] = "Progressing"; + State3[State3["Success"] = 3] = "Success"; + })(State || (State = {})); + InstallBuffer = class extends import_events16.EventEmitter { + constructor(isUpdate = false, isSync = false, channel = void 0) { + super(); + this.isUpdate = isUpdate; + this.isSync = isSync; + this.channel = channel; + this.statMap = new Map(); + this.messagesMap = new Map(); + this.names = []; + } + setExtensions(names) { + this.statMap.clear(); + this.names = names; + for (let name2 of names) { + this.statMap.set(name2, 0); + } + } + addMessage(name2, msg, isProgress = false) { + if (isProgress && this.channel) + return; + let lines = this.messagesMap.get(name2) || []; + this.messagesMap.set(name2, lines.concat(msg.trim().split(/\r?\n/))); + if (this.channel) + this.channel.appendLine(`[${name2}] ${msg}`); + } + startProgress(names) { + for (let name2 of names) { + this.statMap.set(name2, 2); + } + } + finishProgress(name2, succeed = true) { + if (this.channel) { + if (succeed) { + this.channel.appendLine(`[${name2}] install succeed!`); + } else { + this.channel.appendLine(`[${name2}] install failed!`); + } + } + this.statMap.set(name2, succeed ? 3 : 1); + } + get remains() { + let count = 0; + for (let name2 of this.names) { + let stat = this.statMap.get(name2); + if (![3, 1].includes(stat)) { + count = count + 1; + } + } + return count; + } + getLines() { + let lines = []; + for (let name2 of this.names) { + let state = this.statMap.get(name2); + let processText = "*"; + switch (state) { + case 2: { + let d = new Date(); + let idx = Math.floor(d.getMilliseconds() / 100); + processText = frames[idx]; + break; + } + case 1: + processText = "\u2717"; + break; + case 3: + processText = "\u2713"; + break; + } + let msgs = this.messagesMap.get(name2) || []; + lines.push(`- ${processText} ${name2} ${msgs.length ? msgs[msgs.length - 1] : ""}`); + } + return lines; + } + getMessages(line) { + if (line <= 1) + return []; + let name2 = this.names[line - 2]; + if (!name2) + return []; + return this.messagesMap.get(name2); + } + draw(nvim, buffer) { + let { remains } = this; + let first = remains == 0 ? `${this.isUpdate ? "Update" : "Install"} finished` : `Installing, ${remains} remains...`; + let lines = [first, "", ...this.getLines()]; + buffer.setLines(lines, { start: 0, end: -1, strictIndexing: false }, true); + if (remains == 0 && this.interval) { + clearInterval(this.interval); + this.interval = null; + } + if (process.env.VIM_NODE_RPC) { + nvim.command("redraw", true); + } + } + highlight(nvim) { + nvim.call("matchadd", ["CocListFgCyan", "^\\-\\s\\zs\\*"], true); + nvim.call("matchadd", ["CocListFgGreen", "^\\-\\s\\zs\u2713"], true); + nvim.call("matchadd", ["CocListFgRed", "^\\-\\s\\zs\u2717"], true); + nvim.call("matchadd", ["CocListFgYellow", "^-.\\{3\\}\\zs\\S\\+"], true); + } + async show(nvim) { + let { isSync } = this; + if (this.channel) + return; + nvim.pauseNotification(); + nvim.command(isSync ? "enew" : "vs +enew", true); + nvim.call("bufnr", ["%"], true); + nvim.command("setl buftype=nofile bufhidden=wipe noswapfile nobuflisted wrap undolevels=-1", true); + if (!isSync) { + nvim.command("nnoremap q :q", true); + } + this.highlight(nvim); + let res = await nvim.resumeNotification(); + let bufnr = res && res[1] == null ? res[0][1] : null; + if (!bufnr) + return; + this.bufnr = bufnr; + let buffer = nvim.createBuffer(bufnr); + this.interval = setInterval(() => { + this.draw(nvim, buffer); + }, 100); + } + dispose() { + if (this.interval) { + clearInterval(this.interval); + } + } + }; + } +}); + +// node_modules/ini/ini.js +var require_ini = __commonJS({ + "node_modules/ini/ini.js"(exports2) { + exports2.parse = exports2.decode = decode; + exports2.stringify = exports2.encode = encode; + exports2.safe = safe; + exports2.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 section2 = (opt.section ? opt.section + "." : "") + nk; + var child = encode(obj[k], { + section: section2, + whitespace: opt.whitespace + }); + if (out.length && child.length) + out += eol; + out += child; + }); + return out; + } + function dotSplit(str) { + return str.replace(/\1/g, "LITERAL\\1LITERAL").replace(/\\\./g, "").split(/\./).map(function(part) { + return part.replace(/\1/g, "\\.").replace(/\2LITERAL\\1LITERAL\2/g, ""); + }); + } + function decode(str) { + var out = {}; + var p = out; + var section2 = null; + 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] !== void 0) { + section2 = unsafe(match[1]); + if (section2 === "__proto__") { + p = {}; + return; + } + p = out[section2] = out[section2] || {}; + return; + } + var key = unsafe(match[2]); + if (key === "__proto__") + return; + var value = match[3] ? unsafe(match[4]) : true; + switch (value) { + case "true": + case "false": + case "null": + value = JSON.parse(value); + } + if (key.length > 2 && key.slice(-2) === "[]") { + key = key.substring(0, key.length - 2); + if (key === "__proto__") + return; + if (!p[key]) + p[key] = []; + else if (!Array.isArray(p[key])) + p[key] = [p[key]]; + } + if (Array.isArray(p[key])) + p[key].push(value); + else + p[key] = value; + }); + Object.keys(out).filter(function(k, _, __) { + if (!out[k] || typeof out[k] !== "object" || Array.isArray(out[k])) + return false; + var parts = dotSplit(k); + var p2 = out; + var l = parts.pop(); + var nl = l.replace(/\\\./g, "."); + parts.forEach(function(part, _2, __2) { + if (part === "__proto__") + return; + if (!p2[part] || typeof p2[part] !== "object") + p2[part] = {}; + p2 = p2[part]; + }); + if (p2 === out && nl === l) + return false; + p2[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)) { + if (val.charAt(0) === "'") + val = val.substr(1, val.length - 2); + try { + val = JSON.parse(val); + } catch (_) { + } + } else { + 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; + } + } +}); + +// node_modules/rc/node_modules/strip-json-comments/index.js +var require_strip_json_comments = __commonJS({ + "node_modules/rc/node_modules/strip-json-comments/index.js"(exports2, module2) { + "use strict"; + var singleComment = 1; + var multiComment = 2; + function stripWithoutWhitespace() { + return ""; + } + function stripWithWhitespace(str, start, end) { + return str.slice(start, end).replace(/\S/g, " "); + } + module2.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)); + }; + } +}); + +// node_modules/rc/lib/utils.js +var require_utils3 = __commonJS({ + "node_modules/rc/lib/utils.js"(exports2) { + "use strict"; + var fs27 = require("fs"); + var ini = require_ini(); + var path36 = require("path"); + var stripJsonComments = require_strip_json_comments(); + var parse5 = exports2.parse = function(content) { + if (/^\s*{/.test(content)) + return JSON.parse(stripJsonComments(content)); + return ini.parse(content); + }; + var file = exports2.file = function() { + var args = [].slice.call(arguments).filter(function(arg) { + return arg != null; + }); + for (var i in args) + if (typeof args[i] !== "string") + return; + var file2 = path36.join.apply(null, args); + var content; + try { + return fs27.readFileSync(file2, "utf-8"); + } catch (err) { + return; + } + }; + var json = exports2.json = function() { + var content = file.apply(null, arguments); + return content ? parse5(content) : null; + }; + var env = exports2.env = function(prefix, env2) { + env2 = env2 || process.env; + var obj = {}; + var l = prefix.length; + for (var k in env2) { + if (k.toLowerCase().indexOf(prefix.toLowerCase()) === 0) { + var keypath = k.substring(l).split("__"); + var _emptyStringIndex; + while ((_emptyStringIndex = keypath.indexOf("")) > -1) { + keypath.splice(_emptyStringIndex, 1); + } + var cursor = obj; + keypath.forEach(function _buildSubObj(_subkey, i) { + if (!_subkey || typeof cursor !== "object") + return; + if (i === keypath.length - 1) + cursor[_subkey] = env2[k]; + if (cursor[_subkey] === void 0) + cursor[_subkey] = {}; + cursor = cursor[_subkey]; + }); + } + } + return obj; + }; + var find = exports2.find = function() { + var rel = path36.join.apply(null, [].slice.call(arguments)); + function find2(start, rel2) { + var file2 = path36.join(start, rel2); + try { + fs27.statSync(file2); + return file2; + } catch (err) { + if (path36.dirname(start) !== start) + return find2(path36.dirname(start), rel2); + } + } + return find2(process.cwd(), rel); + }; + } +}); + +// node_modules/deep-extend/lib/deep-extend.js +var require_deep_extend = __commonJS({ + "node_modules/deep-extend/lib/deep-extend.js"(exports2, module2) { + "use strict"; + 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"); + } + } + 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__" ? void 0 : object[property]; + } + var deepExtend = module2.exports = function() { + if (arguments.length < 1 || typeof arguments[0] !== "object") { + return false; + } + if (arguments.length < 2) { + return arguments[0]; + } + var target = arguments[0]; + var args = Array.prototype.slice.call(arguments, 1); + var val, src, clone; + args.forEach(function(obj) { + if (typeof obj !== "object" || obj === null || Array.isArray(obj)) { + return; + } + Object.keys(obj).forEach(function(key) { + src = safeGetProperty(target, key); + val = safeGetProperty(obj, key); + if (val === target) { + return; + } else if (typeof val !== "object" || val === null) { + target[key] = val; + return; + } else if (Array.isArray(val)) { + target[key] = deepCloneArray(val); + return; + } else if (isSpecificValue(val)) { + target[key] = cloneSpecificValue(val); + return; + } else if (typeof src !== "object" || src === null || Array.isArray(src)) { + target[key] = deepExtend({}, val); + return; + } else { + target[key] = deepExtend(src, val); + return; + } + }); + }); + return target; + }; + } +}); + +// node_modules/minimist/index.js +var require_minimist = __commonJS({ + "node_modules/minimist/index.js"(exports2, module2) { + module2.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(key2) { + flags.bools[key2] = true; + }); + } + var aliases = {}; + Object.keys(opts.alias || {}).forEach(function(key2) { + aliases[key2] = [].concat(opts.alias[key2]); + aliases[key2].forEach(function(x) { + aliases[x] = [key2].concat(aliases[key2].filter(function(y) { + return x !== y; + })); + }); + }); + [].concat(opts.string).filter(Boolean).forEach(function(key2) { + flags.strings[key2] = true; + if (aliases[key2]) { + flags.strings[aliases[key2]] = true; + } + }); + var defaults2 = opts["default"] || {}; + var argv = { _: [] }; + Object.keys(flags.bools).forEach(function(key2) { + setArg(key2, defaults2[key2] === void 0 ? false : defaults2[key2]); + }); + var notFlags = []; + if (args.indexOf("--") !== -1) { + notFlags = args.slice(args.indexOf("--") + 1); + args = args.slice(0, args.indexOf("--")); + } + function argDefined(key2, arg2) { + return flags.allBools && /^--[^=]+$/.test(arg2) || flags.strings[key2] || flags.bools[key2] || aliases[key2]; + } + function setArg(key2, val, arg2) { + if (arg2 && flags.unknownFn && !argDefined(key2, arg2)) { + if (flags.unknownFn(arg2) === false) + return; + } + var value2 = !flags.strings[key2] && isNumber(val) ? Number(val) : val; + setKey(argv, key2.split("."), value2); + (aliases[key2] || []).forEach(function(x) { + setKey(argv, x.split("."), value2); + }); + } + function setKey(obj, keys, value2) { + var o = obj; + for (var i2 = 0; i2 < keys.length - 1; i2++) { + var key2 = keys[i2]; + if (key2 === "__proto__") + return; + if (o[key2] === void 0) + o[key2] = {}; + if (o[key2] === Object.prototype || o[key2] === Number.prototype || o[key2] === String.prototype) + o[key2] = {}; + if (o[key2] === Array.prototype) + o[key2] = []; + o = o[key2]; + } + var key2 = keys[keys.length - 1]; + if (key2 === "__proto__") + return; + if (o === Object.prototype || o === Number.prototype || o === String.prototype) + o = {}; + if (o === Array.prototype) + o = []; + if (o[key2] === void 0 || flags.bools[key2] || typeof o[key2] === "boolean") { + o[key2] = value2; + } else if (Array.isArray(o[key2])) { + o[key2].push(value2); + } else { + o[key2] = [o[key2], value2]; + } + } + function aliasIsBoolean(key2) { + return aliases[key2].some(function(x) { + return flags.bools[x]; + }); + } + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + if (/^--.+=/.test(arg)) { + 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 !== void 0 && !/^-/.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(defaults2).forEach(function(key2) { + if (!hasKey(argv, key2.split("."))) { + setKey(argv, key2.split("."), defaults2[key2]); + (aliases[key2] || []).forEach(function(x) { + setKey(argv, x.split("."), defaults2[key2]); + }); + } + }); + if (opts["--"]) { + argv["--"] = new Array(); + notFlags.forEach(function(key2) { + argv["--"].push(key2); + }); + } else { + notFlags.forEach(function(key2) { + argv._.push(key2); + }); + } + return argv; + }; + function hasKey(obj, keys) { + var o = obj; + keys.slice(0, -1).forEach(function(key2) { + o = o[key2] || {}; + }); + 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); + } + } +}); + +// node_modules/rc/index.js +var require_rc = __commonJS({ + "node_modules/rc/index.js"(exports2, module2) { + var cc = require_utils3(); + var join2 = require("path").join; + var deepExtend = require_deep_extend(); + var etc = "/etc"; + var win = process.platform === "win32"; + var home = win ? process.env.USERPROFILE : process.env.HOME; + module2.exports = function(name2, defaults2, argv, parse5) { + if (typeof name2 !== "string") + throw new Error("rc(name): name *must* be string"); + if (!argv) + argv = require_minimist()(process.argv.slice(2)); + defaults2 = (typeof defaults2 === "string" ? cc.json(defaults2) : defaults2) || {}; + parse5 = parse5 || cc.parse; + var env = cc.env(name2 + "_"); + var configs = [defaults2]; + var configFiles = []; + function addConfigFile(file) { + if (configFiles.indexOf(file) >= 0) + return; + var fileConfig = cc.file(file); + if (fileConfig) { + configs.push(parse5(fileConfig)); + configFiles.push(file); + } + } + if (!win) + [ + join2(etc, name2, "config"), + join2(etc, name2 + "rc") + ].forEach(addConfigFile); + if (home) + [ + join2(home, ".config", name2, "config"), + join2(home, ".config", name2), + join2(home, "." + name2, "config"), + join2(home, "." + name2 + "rc") + ].forEach(addConfigFile); + addConfigFile(cc.find("." + name2 + "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] } : void 0 + ])); + }; + } +}); + +// node_modules/safe-buffer/index.js +var require_safe_buffer = __commonJS({ + "node_modules/safe-buffer/index.js"(exports2, module2) { + var buffer = require("buffer"); + var Buffer4 = buffer.Buffer; + function copyProps(src, dst) { + for (var key in src) { + dst[key] = src[key]; + } + } + if (Buffer4.from && Buffer4.alloc && Buffer4.allocUnsafe && Buffer4.allocUnsafeSlow) { + module2.exports = buffer; + } else { + copyProps(buffer, exports2); + exports2.Buffer = SafeBuffer; + } + function SafeBuffer(arg, encodingOrOffset, length) { + return Buffer4(arg, encodingOrOffset, length); + } + copyProps(Buffer4, SafeBuffer); + SafeBuffer.from = function(arg, encodingOrOffset, length) { + if (typeof arg === "number") { + throw new TypeError("Argument must not be a number"); + } + return Buffer4(arg, encodingOrOffset, length); + }; + SafeBuffer.alloc = function(size, fill, encoding) { + if (typeof size !== "number") { + throw new TypeError("Argument must be a number"); + } + var buf = Buffer4(size); + if (fill !== void 0) { + 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 Buffer4(size); + }; + SafeBuffer.allocUnsafeSlow = function(size) { + if (typeof size !== "number") { + throw new TypeError("Argument must be a number"); + } + return buffer.SlowBuffer(size); + }; + } +}); + +// node_modules/content-disposition/index.js +var require_content_disposition = __commonJS({ + "node_modules/content-disposition/index.js"(exports2, module2) { + "use strict"; + module2.exports = contentDisposition2; + module2.exports.parse = parse5; + var basename = require("path").basename; + var Buffer4 = require_safe_buffer().Buffer; + var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g; + var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/; + var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g; + var NON_LATIN1_REGEXP = /[^\x20-\x7e\xa0-\xff]/g; + var QESC_REGEXP = /\\([\u0000-\u007f])/g; + var QUOTE_REGEXP = /([\\"])/g; + var PARAM_REGEXP = /;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g; + var TEXT_REGEXP = /^[\x20-\x7e\x80-\xff]+$/; + var TOKEN_REGEXP = /^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/; + var EXT_VALUE_REGEXP = /^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/; + var DISPOSITION_TYPE_REGEXP = /^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/; + function contentDisposition2(filename, options) { + var opts = options || {}; + var type = opts.type || "attachment"; + var params = createparams(filename, opts.fallback); + return format2(new ContentDisposition(type, params)); + } + function createparams(filename, fallback) { + if (filename === void 0) { + return; + } + var params = {}; + if (typeof filename !== "string") { + throw new TypeError("filename must be a string"); + } + if (fallback === void 0) { + fallback = true; + } + if (typeof fallback !== "string" && typeof fallback !== "boolean") { + throw new TypeError("fallback must be a string or boolean"); + } + if (typeof fallback === "string" && NON_LATIN1_REGEXP.test(fallback)) { + throw new TypeError("fallback must be ISO-8859-1 string"); + } + var name2 = basename(filename); + var isQuotedString = TEXT_REGEXP.test(name2); + var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name2) : basename(fallback); + var hasFallback = typeof fallbackName === "string" && fallbackName !== name2; + if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name2)) { + params["filename*"] = name2; + } + if (isQuotedString || hasFallback) { + params.filename = hasFallback ? fallbackName : name2; + } + return params; + } + function format2(obj) { + var parameters = obj.parameters; + var type = obj.type; + if (!type || typeof type !== "string" || !TOKEN_REGEXP.test(type)) { + throw new TypeError("invalid type"); + } + var string2 = String(type).toLowerCase(); + if (parameters && typeof parameters === "object") { + var param; + var params = Object.keys(parameters).sort(); + for (var i = 0; i < params.length; i++) { + param = params[i]; + var val = param.substr(-1) === "*" ? ustring(parameters[param]) : qstring(parameters[param]); + string2 += "; " + param + "=" + val; + } + } + return string2; + } + function decodefield(str) { + var match = EXT_VALUE_REGEXP.exec(str); + if (!match) { + throw new TypeError("invalid extended field value"); + } + var charset = match[1].toLowerCase(); + var encoded = match[2]; + var value; + var binary = encoded.replace(HEX_ESCAPE_REPLACE_REGEXP, pdecode); + switch (charset) { + case "iso-8859-1": + value = getlatin1(binary); + break; + case "utf-8": + value = Buffer4.from(binary, "binary").toString("utf8"); + break; + default: + throw new TypeError("unsupported charset in extended field"); + } + return value; + } + function getlatin1(val) { + return String(val).replace(NON_LATIN1_REGEXP, "?"); + } + function parse5(string2) { + if (!string2 || typeof string2 !== "string") { + throw new TypeError("argument string is required"); + } + var match = DISPOSITION_TYPE_REGEXP.exec(string2); + if (!match) { + throw new TypeError("invalid type format"); + } + var index = match[0].length; + var type = match[1].toLowerCase(); + var key; + var names = []; + var params = {}; + var value; + index = PARAM_REGEXP.lastIndex = match[0].substr(-1) === ";" ? index - 1 : index; + while (match = PARAM_REGEXP.exec(string2)) { + if (match.index !== index) { + throw new TypeError("invalid parameter format"); + } + index += match[0].length; + key = match[1].toLowerCase(); + value = match[2]; + if (names.indexOf(key) !== -1) { + throw new TypeError("invalid duplicate parameter"); + } + names.push(key); + if (key.indexOf("*") + 1 === key.length) { + key = key.slice(0, -1); + value = decodefield(value); + params[key] = value; + continue; + } + if (typeof params[key] === "string") { + continue; + } + if (value[0] === '"') { + value = value.substr(1, value.length - 2).replace(QESC_REGEXP, "$1"); + } + params[key] = value; + } + if (index !== -1 && index !== string2.length) { + throw new TypeError("invalid parameter format"); + } + return new ContentDisposition(type, params); + } + function pdecode(str, hex) { + return String.fromCharCode(parseInt(hex, 16)); + } + function pencode(char) { + return "%" + String(char).charCodeAt(0).toString(16).toUpperCase(); + } + function qstring(val) { + var str = String(val); + return '"' + str.replace(QUOTE_REGEXP, "\\$1") + '"'; + } + function ustring(val) { + var str = String(val); + var encoded = encodeURIComponent(str).replace(ENCODE_URL_ATTR_CHAR_REGEXP, pencode); + return "UTF-8''" + encoded; + } + function ContentDisposition(type, parameters) { + this.type = type; + this.parameters = parameters; + } + } +}); + +// node_modules/follow-redirects/debug.js +var require_debug2 = __commonJS({ + "node_modules/follow-redirects/debug.js"(exports2, module2) { + var debug; + module2.exports = function() { + if (!debug) { + try { + debug = require_src()("follow-redirects"); + } catch (error) { + debug = function() { + }; + } + } + debug.apply(null, arguments); + }; + } +}); + +// node_modules/follow-redirects/index.js +var require_follow_redirects = __commonJS({ + "node_modules/follow-redirects/index.js"(exports2, module2) { + var url = require("url"); + var URL = url.URL; + var http3 = require("http"); + var https3 = require("https"); + var Writable = require("stream").Writable; + var assert = require("assert"); + var debug = require_debug2(); + var events = ["abort", "aborted", "connect", "error", "socket", "timeout"]; + var eventHandlers = Object.create(null); + events.forEach(function(event) { + eventHandlers[event] = function(arg1, arg2, arg3) { + this._redirectable.emit(event, arg1, arg2, arg3); + }; + }); + var RedirectionError = createErrorType("ERR_FR_REDIRECTION_FAILURE", ""); + var TooManyRedirectsError = createErrorType("ERR_FR_TOO_MANY_REDIRECTS", "Maximum number of redirects exceeded"); + var MaxBodyLengthExceededError = createErrorType("ERR_FR_MAX_BODY_LENGTH_EXCEEDED", "Request body larger than maxBodyLength limit"); + var WriteAfterEndError = createErrorType("ERR_STREAM_WRITE_AFTER_END", "write after end"); + function RedirectableRequest(options, responseCallback) { + 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 = []; + if (responseCallback) { + this.on("response", responseCallback); + } + var self2 = this; + this._onNativeResponse = function(response) { + self2._processResponse(response); + }; + this._performRequest(); + } + RedirectableRequest.prototype = Object.create(Writable.prototype); + RedirectableRequest.prototype.abort = function() { + abortRequest(this._currentRequest); + this.emit("abort"); + }; + RedirectableRequest.prototype.write = function(data, encoding, callback) { + if (this._ending) { + throw new WriteAfterEndError(); + } + if (!(typeof data === "string" || typeof data === "object" && "length" in data)) { + throw new TypeError("data should be a string, Buffer or Uint8Array"); + } + if (typeof encoding === "function") { + callback = encoding; + encoding = null; + } + if (data.length === 0) { + if (callback) { + callback(); + } + return; + } + if (this._requestBodyLength + data.length <= this._options.maxBodyLength) { + this._requestBodyLength += data.length; + this._requestBodyBuffers.push({ data, encoding }); + this._currentRequest.write(data, encoding, callback); + } else { + this.emit("error", new MaxBodyLengthExceededError()); + this.abort(); + } + }; + RedirectableRequest.prototype.end = function(data, encoding, callback) { + if (typeof data === "function") { + callback = data; + data = encoding = null; + } else if (typeof encoding === "function") { + callback = encoding; + encoding = null; + } + if (!data) { + this._ended = this._ending = true; + this._currentRequest.end(null, null, callback); + } else { + var self2 = this; + var currentRequest = this._currentRequest; + this.write(data, encoding, function() { + self2._ended = true; + currentRequest.end(null, null, callback); + }); + this._ending = true; + } + }; + RedirectableRequest.prototype.setHeader = function(name2, value) { + this._options.headers[name2] = value; + this._currentRequest.setHeader(name2, value); + }; + RedirectableRequest.prototype.removeHeader = function(name2) { + delete this._options.headers[name2]; + this._currentRequest.removeHeader(name2); + }; + RedirectableRequest.prototype.setTimeout = function(msecs, callback) { + var self2 = this; + if (callback) { + this.on("timeout", callback); + } + function destroyOnTimeout(socket) { + socket.setTimeout(msecs); + socket.removeListener("timeout", socket.destroy); + socket.addListener("timeout", socket.destroy); + } + function startTimer(socket) { + if (self2._timeout) { + clearTimeout(self2._timeout); + } + self2._timeout = setTimeout(function() { + self2.emit("timeout"); + clearTimer(); + }, msecs); + destroyOnTimeout(socket); + } + function clearTimer() { + clearTimeout(this._timeout); + if (callback) { + self2.removeListener("timeout", callback); + } + if (!this.socket) { + self2._currentRequest.removeListener("socket", startTimer); + } + } + if (this.socket) { + startTimer(this.socket); + } else { + this._currentRequest.once("socket", startTimer); + } + this.on("socket", destroyOnTimeout); + this.once("response", clearTimer); + this.once("error", clearTimer); + return this; + }; + [ + "flushHeaders", + "getHeader", + "setNoDelay", + "setSocketKeepAlive" + ].forEach(function(method) { + RedirectableRequest.prototype[method] = function(a, b) { + return this._currentRequest[method](a, b); + }; + }); + ["aborted", "connection", "socket"].forEach(function(property) { + Object.defineProperty(RedirectableRequest.prototype, property, { + get: function() { + return this._currentRequest[property]; + } + }); + }); + RedirectableRequest.prototype._sanitizeOptions = function(options) { + if (!options.headers) { + options.headers = {}; + } + if (options.host) { + if (!options.hostname) { + options.hostname = options.host; + } + delete options.host; + } + 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); + } + } + }; + RedirectableRequest.prototype._performRequest = function() { + var protocol = this._options.protocol; + var nativeProtocol = this._options.nativeProtocols[protocol]; + if (!nativeProtocol) { + this.emit("error", new TypeError("Unsupported protocol " + protocol)); + return; + } + if (this._options.agents) { + var scheme = protocol.substr(0, protocol.length - 1); + this._options.agent = this._options.agents[scheme]; + } + var request2 = this._currentRequest = nativeProtocol.request(this._options, this._onNativeResponse); + this._currentUrl = url.format(this._options); + request2._redirectable = this; + for (var e = 0; e < events.length; e++) { + request2.on(events[e], eventHandlers[events[e]]); + } + if (this._isRedirect) { + var i = 0; + var self2 = this; + var buffers = this._requestBodyBuffers; + (function writeNext(error) { + if (request2 === self2._currentRequest) { + if (error) { + self2.emit("error", error); + } else if (i < buffers.length) { + var buffer = buffers[i++]; + if (!request2.finished) { + request2.write(buffer.data, buffer.encoding, writeNext); + } + } else if (self2._ended) { + request2.end(); + } + } + })(); + } + }; + RedirectableRequest.prototype._processResponse = function(response) { + var statusCode = response.statusCode; + if (this._options.trackRedirects) { + this._redirects.push({ + url: this._currentUrl, + headers: response.headers, + statusCode + }); + } + var location = response.headers.location; + if (location && this._options.followRedirects !== false && statusCode >= 300 && statusCode < 400) { + abortRequest(this._currentRequest); + response.destroy(); + if (++this._redirectCount > this._options.maxRedirects) { + this.emit("error", new TooManyRedirectsError()); + return; + } + if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" || statusCode === 303 && !/^(?:GET|HEAD)$/.test(this._options.method)) { + this._options.method = "GET"; + this._requestBodyBuffers = []; + removeMatchingHeaders(/^content-/i, this._options.headers); + } + var previousHostName = removeMatchingHeaders(/^host$/i, this._options.headers) || url.parse(this._currentUrl).hostname; + var redirectUrl = url.resolve(this._currentUrl, location); + debug("redirecting to", redirectUrl); + this._isRedirect = true; + var redirectUrlParts = url.parse(redirectUrl); + Object.assign(this._options, redirectUrlParts); + if (redirectUrlParts.hostname !== previousHostName) { + removeMatchingHeaders(/^authorization$/i, this._options.headers); + } + if (typeof this._options.beforeRedirect === "function") { + var responseDetails = { headers: response.headers }; + try { + this._options.beforeRedirect.call(null, this._options, responseDetails); + } catch (err) { + this.emit("error", err); + return; + } + this._sanitizeOptions(this._options); + } + try { + this._performRequest(); + } catch (cause) { + var error = new RedirectionError("Redirected request failed: " + cause.message); + error.cause = cause; + this.emit("error", error); + } + } else { + response.responseUrl = this._currentUrl; + response.redirects = this._redirects; + this.emit("response", response); + this._requestBodyBuffers = []; + } + }; + function wrap(protocols) { + var exports3 = { + maxRedirects: 21, + maxBodyLength: 10 * 1024 * 1024 + }; + var nativeProtocols = {}; + Object.keys(protocols).forEach(function(scheme) { + var protocol = scheme + ":"; + var nativeProtocol = nativeProtocols[protocol] = protocols[scheme]; + var wrappedProtocol = exports3[scheme] = Object.create(nativeProtocol); + function request2(input, options, callback) { + if (typeof input === "string") { + var urlStr = input; + try { + input = urlToOptions(new URL(urlStr)); + } catch (err) { + input = url.parse(urlStr); + } + } else if (URL && input instanceof URL) { + input = urlToOptions(input); + } else { + callback = options; + options = input; + input = { protocol }; + } + if (typeof options === "function") { + callback = options; + options = null; + } + options = Object.assign({ + maxRedirects: exports3.maxRedirects, + maxBodyLength: exports3.maxBodyLength + }, input, options); + options.nativeProtocols = nativeProtocols; + assert.equal(options.protocol, protocol, "protocol mismatch"); + debug("options", options); + return new RedirectableRequest(options, callback); + } + function get(input, options, callback) { + var wrappedRequest = wrappedProtocol.request(input, options, callback); + wrappedRequest.end(); + return wrappedRequest; + } + Object.defineProperties(wrappedProtocol, { + request: { value: request2, configurable: true, enumerable: true, writable: true }, + get: { value: get, configurable: true, enumerable: true, writable: true } + }); + }); + return exports3; + } + function noop() { + } + function urlToOptions(urlObject) { + var options = { + protocol: urlObject.protocol, + hostname: urlObject.hostname.startsWith("[") ? 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; + } + function removeMatchingHeaders(regex, headers) { + var lastValue; + for (var header in headers) { + if (regex.test(header)) { + lastValue = headers[header]; + delete headers[header]; + } + } + return lastValue; + } + function createErrorType(code, defaultMessage) { + function CustomError(message) { + Error.captureStackTrace(this, this.constructor); + this.message = message || defaultMessage; + } + CustomError.prototype = new Error(); + CustomError.prototype.constructor = CustomError; + CustomError.prototype.name = "Error [" + code + "]"; + CustomError.prototype.code = code; + return CustomError; + } + function abortRequest(request2) { + for (var e = 0; e < events.length; e++) { + request2.removeListener(events[e], eventHandlers[events[e]]); + } + request2.on("error", noop); + request2.abort(); + } + module2.exports = wrap({ http: http3, https: https3 }); + module2.exports.wrap = wrap; + } +}); + +// node_modules/tar/lib/high-level-opt.js +var require_high_level_opt = __commonJS({ + "node_modules/tar/lib/high-level-opt.js"(exports2, module2) { + "use strict"; + var 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"] + ]); + module2.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)) : {}; + } +}); + +// node_modules/minipass/index.js +var require_minipass = __commonJS({ + "node_modules/minipass/index.js"(exports2, module2) { + "use strict"; + var EE = require("events"); + var Stream = require("stream"); + var Yallist = require_yallist(); + var SD = require("string_decoder").StringDecoder; + var EOF = Symbol("EOF"); + var MAYBE_EMIT_END = Symbol("maybeEmitEnd"); + var EMITTED_END = Symbol("emittedEnd"); + var EMITTING_END = Symbol("emittingEnd"); + var CLOSED = Symbol("closed"); + var READ = Symbol("read"); + var FLUSH = Symbol("flush"); + var FLUSHCHUNK = Symbol("flushChunk"); + var ENCODING = Symbol("encoding"); + var DECODER = Symbol("decoder"); + var FLOWING = Symbol("flowing"); + var PAUSED = Symbol("paused"); + var RESUME = Symbol("resume"); + var BUFFERLENGTH = Symbol("bufferLength"); + var BUFFERPUSH = Symbol("bufferPush"); + var BUFFERSHIFT = Symbol("bufferShift"); + var OBJECTMODE = Symbol("objectMode"); + var DESTROYED = Symbol("destroyed"); + var doIter = global._MP_NO_ITERATOR_SYMBOLS_ !== "1"; + var ASYNCITERATOR = doIter && Symbol.asyncIterator || Symbol("asyncIterator not implemented"); + var ITERATOR = doIter && Symbol.iterator || Symbol("iterator not implemented"); + var isEndish = (ev) => ev === "end" || ev === "finish" || ev === "prefinish"; + var isArrayBuffer = (b) => b instanceof ArrayBuffer || typeof b === "object" && b.constructor && b.constructor.name === "ArrayBuffer" && b.byteLength >= 0; + var isArrayBufferView = (b) => !Buffer.isBuffer(b) && ArrayBuffer.isView(b); + module2.exports = class Minipass extends Stream { + constructor(options) { + super(); + this[FLOWING] = false; + this[PAUSED] = 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[EMITTING_END] = false; + this[CLOSED] = false; + this.writable = true; + this.readable = true; + this[BUFFERLENGTH] = 0; + this[DESTROYED] = false; + } + 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; + } + get objectMode() { + return this[OBJECTMODE]; + } + set objectMode(om) { + this[OBJECTMODE] = this[OBJECTMODE] || !!om; + } + write(chunk, encoding, cb) { + if (this[EOF]) + throw new Error("write after end"); + if (this[DESTROYED]) { + this.emit("error", Object.assign(new Error("Cannot call write after a stream was destroyed"), { code: "ERR_STREAM_DESTROYED" })); + return true; + } + if (typeof encoding === "function") + cb = encoding, encoding = "utf8"; + if (!encoding) + encoding = "utf8"; + if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) { + if (isArrayBufferView(chunk)) + chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength); + else if (isArrayBuffer(chunk)) + chunk = Buffer.from(chunk); + else if (typeof chunk !== "string") + this.objectMode = true; + } + if (!this.objectMode && !chunk.length) { + if (this[BUFFERLENGTH] !== 0) + this.emit("readable"); + if (cb) + cb(); + return this.flowing; + } + if (typeof chunk === "string" && !this[OBJECTMODE] && !(encoding === this[ENCODING] && !this[DECODER].lastNeed)) { + chunk = Buffer.from(chunk, encoding); + } + if (Buffer.isBuffer(chunk) && this[ENCODING]) + chunk = this[DECODER].write(chunk); + if (this.flowing) { + if (this[BUFFERLENGTH] !== 0) + this[FLUSH](true); + this.emit("data", chunk); + } else + this[BUFFERPUSH](chunk); + if (this[BUFFERLENGTH] !== 0) + this.emit("readable"); + if (cb) + cb(); + return this.flowing; + } + read(n) { + if (this[DESTROYED]) + return null; + 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([ + Buffer.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[PAUSED]) + this[MAYBE_EMIT_END](); + return this; + } + [RESUME]() { + if (this[DESTROYED]) + return; + this[PAUSED] = false; + 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; + this[PAUSED] = true; + } + get destroyed() { + return this[DESTROYED]; + } + get flowing() { + return this[FLOWING]; + } + get paused() { + return this[PAUSED]; + } + [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](noDrain) { + do { + } while (this[FLUSHCHUNK](this[BUFFERSHIFT]())); + if (!noDrain && !this.buffer.length && !this[EOF]) + this.emit("drain"); + } + [FLUSHCHUNK](chunk) { + return chunk ? (this.emit("data", chunk), this.flowing) : false; + } + pipe(dest, opts) { + if (this[DESTROYED]) + return; + const ended = this[EMITTED_END]; + opts = opts || {}; + if (dest === process.stdout || dest === process.stderr) + opts.end = false; + else + opts.end = opts.end !== false; + const p = { dest, opts, ondrain: (_) => this[RESUME]() }; + this.pipes.push(p); + dest.on("drain", p.ondrain); + this[RESUME](); + if (ended && p.opts.end) + p.dest.end(); + 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 (isEndish(ev) && this[EMITTED_END]) { + super.emit(ev); + this.removeAllListeners(ev); + } + } + } + get emittedEnd() { + return this[EMITTED_END]; + } + [MAYBE_EMIT_END]() { + if (!this[EMITTING_END] && !this[EMITTED_END] && !this[DESTROYED] && this.buffer.length === 0 && this[EOF]) { + this[EMITTING_END] = true; + this.emit("end"); + this.emit("prefinish"); + this.emit("finish"); + if (this[CLOSED]) + this.emit("close"); + this[EMITTING_END] = false; + } + } + emit(ev, data) { + if (ev !== "error" && ev !== "close" && ev !== DESTROYED && this[DESTROYED]) + return; + else if (ev === "data") { + if (!data) + return; + if (this.pipes.length) + this.pipes.forEach((p) => p.dest.write(data) === false && 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.end) + p.dest.end(); + }); + } else if (ev === "close") { + this[CLOSED] = true; + if (!this[EMITTED_END] && !this[DESTROYED]) + 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 (!isEndish(ev)) + this[MAYBE_EMIT_END](); + else + this.removeAllListeners(ev); + } + } + collect() { + const buf = []; + if (!this[OBJECTMODE]) + buf.dataLength = 0; + const p = this.promise(); + this.on("data", (c) => { + buf.push(c); + if (!this[OBJECTMODE]) + buf.dataLength += c.length; + }); + return p.then(() => buf); + } + concat() { + return this[OBJECTMODE] ? Promise.reject(new Error("cannot concat in objectMode")) : this.collect().then((buf) => this[OBJECTMODE] ? Promise.reject(new Error("cannot concat in objectMode")) : this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength)); + } + promise() { + return new Promise((resolve3, reject) => { + this.on(DESTROYED, () => reject(new Error("stream destroyed"))); + this.on("end", () => resolve3()); + this.on("error", (er) => reject(er)); + }); + } + [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 resolve3 = 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(); + resolve3({ value, done: !!this[EOF] }); + }; + const onend = () => { + this.removeListener("error", onerr); + this.removeListener("data", ondata); + resolve3({ done: true }); + }; + const ondestroy = () => onerr(new Error("stream destroyed")); + return new Promise((res2, rej) => { + reject = rej; + resolve3 = res2; + this.once(DESTROYED, ondestroy); + this.once("error", onerr); + this.once("end", onend); + this.once("data", ondata); + }); + }; + return { next }; + } + [ITERATOR]() { + const next = () => { + const value = this.read(); + const done = value === null; + return { value, done }; + }; + return { next }; + } + destroy(er) { + if (this[DESTROYED]) { + if (er) + this.emit("error", er); + else + this.emit(DESTROYED); + return this; + } + this[DESTROYED] = true; + this.buffer = new Yallist(); + this[BUFFERLENGTH] = 0; + if (typeof this.close === "function" && !this[CLOSED]) + this.close(); + if (er) + this.emit("error", er); + else + this.emit(DESTROYED); + return this; + } + static isStream(s) { + return !!s && (s instanceof Minipass || s instanceof Stream || s instanceof EE && (typeof s.pipe === "function" || typeof s.write === "function" && typeof s.end === "function")); + } + }; + } +}); + +// node_modules/minizlib/constants.js +var require_constants2 = __commonJS({ + "node_modules/minizlib/constants.js"(exports2, module2) { + var realZlibConstants = require("zlib").constants || { ZLIB_VERNUM: 4736 }; + module2.exports = Object.freeze(Object.assign(Object.create(null), { + 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, + DEFLATE: 1, + INFLATE: 2, + GZIP: 3, + GUNZIP: 4, + DEFLATERAW: 5, + INFLATERAW: 6, + UNZIP: 7, + BROTLI_DECODE: 8, + BROTLI_ENCODE: 9, + 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, + BROTLI_OPERATION_PROCESS: 0, + BROTLI_OPERATION_FLUSH: 1, + BROTLI_OPERATION_FINISH: 2, + BROTLI_OPERATION_EMIT_METADATA: 3, + BROTLI_MODE_GENERIC: 0, + BROTLI_MODE_TEXT: 1, + BROTLI_MODE_FONT: 2, + BROTLI_DEFAULT_MODE: 0, + BROTLI_MIN_QUALITY: 0, + BROTLI_MAX_QUALITY: 11, + BROTLI_DEFAULT_QUALITY: 11, + BROTLI_MIN_WINDOW_BITS: 10, + BROTLI_MAX_WINDOW_BITS: 24, + BROTLI_LARGE_MAX_WINDOW_BITS: 30, + BROTLI_DEFAULT_WINDOW: 22, + BROTLI_MIN_INPUT_BLOCK_BITS: 16, + BROTLI_MAX_INPUT_BLOCK_BITS: 24, + BROTLI_PARAM_MODE: 0, + BROTLI_PARAM_QUALITY: 1, + BROTLI_PARAM_LGWIN: 2, + BROTLI_PARAM_LGBLOCK: 3, + BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: 4, + BROTLI_PARAM_SIZE_HINT: 5, + BROTLI_PARAM_LARGE_WINDOW: 6, + BROTLI_PARAM_NPOSTFIX: 7, + BROTLI_PARAM_NDIRECT: 8, + BROTLI_DECODER_RESULT_ERROR: 0, + BROTLI_DECODER_RESULT_SUCCESS: 1, + BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: 2, + BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: 3, + BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION: 0, + BROTLI_DECODER_PARAM_LARGE_WINDOW: 1, + BROTLI_DECODER_NO_ERROR: 0, + BROTLI_DECODER_SUCCESS: 1, + BROTLI_DECODER_NEEDS_MORE_INPUT: 2, + BROTLI_DECODER_NEEDS_MORE_OUTPUT: 3, + BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: -1, + BROTLI_DECODER_ERROR_FORMAT_RESERVED: -2, + BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: -3, + BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: -4, + BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: -5, + BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: -6, + BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: -7, + BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: -8, + BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: -9, + BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: -10, + BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: -11, + BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: -12, + BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: -13, + BROTLI_DECODER_ERROR_FORMAT_PADDING_1: -14, + BROTLI_DECODER_ERROR_FORMAT_PADDING_2: -15, + BROTLI_DECODER_ERROR_FORMAT_DISTANCE: -16, + BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: -19, + BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: -20, + BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: -21, + BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: -22, + BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: -25, + BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: -26, + BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: -27, + BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: -30, + BROTLI_DECODER_ERROR_UNREACHABLE: -31 + }, realZlibConstants)); + } +}); + +// node_modules/minizlib/index.js +var require_minizlib = __commonJS({ + "node_modules/minizlib/index.js"(exports2) { + "use strict"; + var assert = require("assert"); + var Buffer4 = require("buffer").Buffer; + var realZlib = require("zlib"); + var constants = exports2.constants = require_constants2(); + var Minipass = require_minipass(); + var OriginalBufferConcat = Buffer4.concat; + var _superWrite = Symbol("_superWrite"); + var ZlibError = class extends Error { + constructor(err) { + super("zlib: " + err.message); + this.code = err.code; + this.errno = err.errno; + if (!this.code) + this.code = "ZLIB_ERROR"; + this.message = "zlib: " + err.message; + Error.captureStackTrace(this, this.constructor); + } + get name() { + return "ZlibError"; + } + }; + var _opts = Symbol("opts"); + var _flushFlag = Symbol("flushFlag"); + var _finishFlushFlag = Symbol("finishFlushFlag"); + var _fullFlushFlag = Symbol("fullFlushFlag"); + var _handle = Symbol("handle"); + var _onError = Symbol("onError"); + var _sawError = Symbol("sawError"); + var _level = Symbol("level"); + var _strategy = Symbol("strategy"); + var _ended = Symbol("ended"); + var _defaultFullFlush = Symbol("_defaultFullFlush"); + var ZlibBase = class extends Minipass { + constructor(opts, mode) { + if (!opts || typeof opts !== "object") + throw new TypeError("invalid options for ZlibBase constructor"); + super(opts); + this[_sawError] = false; + this[_ended] = false; + this[_opts] = opts; + this[_flushFlag] = opts.flush; + this[_finishFlushFlag] = opts.finishFlush; + try { + this[_handle] = new realZlib[mode](opts); + } catch (er) { + throw new ZlibError(er); + } + this[_onError] = (err) => { + if (this[_sawError]) + return; + this[_sawError] = true; + this.close(); + this.emit("error", err); + }; + this[_handle].on("error", (er) => this[_onError](new ZlibError(er))); + this.once("end", () => this.close); + } + close() { + if (this[_handle]) { + this[_handle].close(); + this[_handle] = null; + this.emit("close"); + } + } + reset() { + if (!this[_sawError]) { + assert(this[_handle], "zlib binding closed"); + return this[_handle].reset(); + } + } + flush(flushFlag) { + if (this.ended) + return; + if (typeof flushFlag !== "number") + flushFlag = this[_fullFlushFlag]; + this.write(Object.assign(Buffer4.alloc(0), { [_flushFlag]: flushFlag })); + } + end(chunk, encoding, cb) { + if (chunk) + this.write(chunk, encoding); + this.flush(this[_finishFlushFlag]); + this[_ended] = true; + return super.end(null, null, cb); + } + get ended() { + return this[_ended]; + } + write(chunk, encoding, cb) { + if (typeof encoding === "function") + cb = encoding, encoding = "utf8"; + if (typeof chunk === "string") + chunk = Buffer4.from(chunk, encoding); + if (this[_sawError]) + return; + assert(this[_handle], "zlib binding closed"); + const nativeHandle = this[_handle]._handle; + const originalNativeClose = nativeHandle.close; + nativeHandle.close = () => { + }; + const originalClose = this[_handle].close; + this[_handle].close = () => { + }; + Buffer4.concat = (args) => args; + let result; + try { + const flushFlag = typeof chunk[_flushFlag] === "number" ? chunk[_flushFlag] : this[_flushFlag]; + result = this[_handle]._processChunk(chunk, flushFlag); + Buffer4.concat = OriginalBufferConcat; + } catch (err) { + Buffer4.concat = OriginalBufferConcat; + this[_onError](new ZlibError(err)); + } finally { + if (this[_handle]) { + this[_handle]._handle = nativeHandle; + nativeHandle.close = originalNativeClose; + this[_handle].close = originalClose; + this[_handle].removeAllListeners("error"); + } + } + if (this[_handle]) + this[_handle].on("error", (er) => this[_onError](new ZlibError(er))); + let writeReturn; + if (result) { + if (Array.isArray(result) && result.length > 0) { + writeReturn = this[_superWrite](Buffer4.from(result[0])); + for (let i = 1; i < result.length; i++) { + writeReturn = this[_superWrite](result[i]); + } + } else { + writeReturn = this[_superWrite](Buffer4.from(result)); + } + } + if (cb) + cb(); + return writeReturn; + } + [_superWrite](data) { + return super.write(data); + } + }; + var Zlib = class extends ZlibBase { + constructor(opts, mode) { + opts = opts || {}; + opts.flush = opts.flush || constants.Z_NO_FLUSH; + opts.finishFlush = opts.finishFlush || constants.Z_FINISH; + super(opts, mode); + this[_fullFlushFlag] = constants.Z_FULL_FLUSH; + this[_level] = opts.level; + this[_strategy] = opts.strategy; + } + params(level, strategy) { + if (this[_sawError]) + return; + if (!this[_handle]) + throw new Error("cannot switch params when binding is closed"); + if (!this[_handle].params) + throw new Error("not supported in this implementation"); + if (this[_level] !== level || this[_strategy] !== strategy) { + this.flush(constants.Z_SYNC_FLUSH); + assert(this[_handle], "zlib binding closed"); + const origFlush = this[_handle].flush; + this[_handle].flush = (flushFlag, cb) => { + this.flush(flushFlag); + cb(); + }; + try { + this[_handle].params(level, strategy); + } finally { + this[_handle].flush = origFlush; + } + if (this[_handle]) { + this[_level] = level; + this[_strategy] = strategy; + } + } + } + }; + var Deflate = class extends Zlib { + constructor(opts) { + super(opts, "Deflate"); + } + }; + var Inflate = class extends Zlib { + constructor(opts) { + super(opts, "Inflate"); + } + }; + var _portable = Symbol("_portable"); + var Gzip = class extends Zlib { + constructor(opts) { + super(opts, "Gzip"); + this[_portable] = opts && !!opts.portable; + } + [_superWrite](data) { + if (!this[_portable]) + return super[_superWrite](data); + this[_portable] = false; + data[9] = 255; + return super[_superWrite](data); + } + }; + var Gunzip = class extends Zlib { + constructor(opts) { + super(opts, "Gunzip"); + } + }; + var DeflateRaw = class extends Zlib { + constructor(opts) { + super(opts, "DeflateRaw"); + } + }; + var InflateRaw = class extends Zlib { + constructor(opts) { + super(opts, "InflateRaw"); + } + }; + var Unzip = class extends Zlib { + constructor(opts) { + super(opts, "Unzip"); + } + }; + var Brotli = class extends ZlibBase { + constructor(opts, mode) { + opts = opts || {}; + opts.flush = opts.flush || constants.BROTLI_OPERATION_PROCESS; + opts.finishFlush = opts.finishFlush || constants.BROTLI_OPERATION_FINISH; + super(opts, mode); + this[_fullFlushFlag] = constants.BROTLI_OPERATION_FLUSH; + } + }; + var BrotliCompress = class extends Brotli { + constructor(opts) { + super(opts, "BrotliCompress"); + } + }; + var BrotliDecompress = class extends Brotli { + constructor(opts) { + super(opts, "BrotliDecompress"); + } + }; + exports2.Deflate = Deflate; + exports2.Inflate = Inflate; + exports2.Gzip = Gzip; + exports2.Gunzip = Gunzip; + exports2.DeflateRaw = DeflateRaw; + exports2.InflateRaw = InflateRaw; + exports2.Unzip = Unzip; + if (typeof realZlib.BrotliCompress === "function") { + exports2.BrotliCompress = BrotliCompress; + exports2.BrotliDecompress = BrotliDecompress; + } else { + exports2.BrotliCompress = exports2.BrotliDecompress = class { + constructor() { + throw new Error("Brotli is not supported in this version of Node.js"); + } + }; + } + } +}); + +// node_modules/tar/lib/normalize-windows-path.js +var require_normalize_windows_path = __commonJS({ + "node_modules/tar/lib/normalize-windows-path.js"(exports2, module2) { + var platform3 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform; + module2.exports = platform3 !== "win32" ? (p) => p : (p) => p && p.replace(/\\/g, "/"); + } +}); + +// node_modules/tar/lib/read-entry.js +var require_read_entry = __commonJS({ + "node_modules/tar/lib/read-entry.js"(exports2, module2) { + "use strict"; + var MiniPass = require_minipass(); + var normPath = require_normalize_windows_path(); + var SLURP = Symbol("slurp"); + module2.exports = class ReadEntry extends MiniPass { + constructor(header, ex, gex) { + super(); + this.pause(); + 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; + default: + this.ignore = true; + } + this.path = normPath(header.path); + this.mode = header.mode; + if (this.mode) + this.mode = this.mode & 4095; + 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 = normPath(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); + return super.write(data.slice(0, r)); + } + [SLURP](ex, global2) { + for (const k in ex) { + if (ex[k] !== null && ex[k] !== void 0 && !(global2 && k === "path")) + this[k] = k === "path" || k === "linkpath" ? normPath(ex[k]) : ex[k]; + } + } + }; + } +}); + +// node_modules/tar/lib/types.js +var require_types2 = __commonJS({ + "node_modules/tar/lib/types.js"(exports2) { + "use strict"; + exports2.name = new Map([ + ["0", "File"], + ["", "OldFile"], + ["1", "Link"], + ["2", "SymbolicLink"], + ["3", "CharacterDevice"], + ["4", "BlockDevice"], + ["5", "Directory"], + ["6", "FIFO"], + ["7", "ContiguousFile"], + ["g", "GlobalExtendedHeader"], + ["x", "ExtendedHeader"], + ["A", "SolarisACL"], + ["D", "GNUDumpDir"], + ["I", "Inode"], + ["K", "NextFileHasLongLinkpath"], + ["L", "NextFileHasLongPath"], + ["M", "ContinuationFile"], + ["N", "OldGnuLongPath"], + ["S", "SparseFile"], + ["V", "TapeVolumeHeader"], + ["X", "OldExtendedHeader"] + ]); + exports2.code = new Map(Array.from(exports2.name).map((kv) => [kv[1], kv[0]])); + } +}); + +// node_modules/tar/lib/large-numbers.js +var require_large_numbers = __commonJS({ + "node_modules/tar/lib/large-numbers.js"(exports2, module2) { + "use strict"; + var encode = (num, buf) => { + if (!Number.isSafeInteger(num)) + throw Error("cannot encode number outside of javascript safe integer range"); + else if (num < 0) + encodeNegative(num, buf); + else + encodePositive(num, buf); + return buf; + }; + var encodePositive = (num, buf) => { + buf[0] = 128; + for (var i = buf.length; i > 1; i--) { + buf[i - 1] = num & 255; + num = Math.floor(num / 256); + } + }; + var encodeNegative = (num, buf) => { + buf[0] = 255; + var flipped = false; + num = num * -1; + for (var i = buf.length; i > 1; i--) { + var byte = num & 255; + num = Math.floor(num / 256); + if (flipped) + buf[i - 1] = onesComp(byte); + else if (byte === 0) + buf[i - 1] = 0; + else { + flipped = true; + buf[i - 1] = twosComp(byte); + } + } + }; + var parse5 = (buf) => { + const pre = buf[0]; + const value = pre === 128 ? pos(buf.slice(1, buf.length)) : pre === 255 ? twos(buf) : null; + if (value === null) + throw Error("invalid base256 encoding"); + if (!Number.isSafeInteger(value)) + throw Error("parsed number outside of javascript safe integer range"); + return value; + }; + var 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; + }; + var 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; + }; + var onesComp = (byte) => (255 ^ byte) & 255; + var twosComp = (byte) => (255 ^ byte) + 1 & 255; + module2.exports = { + encode, + parse: parse5 + }; + } +}); + +// node_modules/tar/lib/header.js +var require_header = __commonJS({ + "node_modules/tar/lib/header.js"(exports2, module2) { + "use strict"; + var types = require_types2(); + var pathModule = require("path").posix; + var large = require_large_numbers(); + var SLURP = Symbol("slurp"); + var TYPE = Symbol("type"); + var Header = class { + 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); + this[SLURP](ex); + this[SLURP](gex, true); + this[TYPE] = decString(buf, off + 156, 1); + if (this[TYPE] === "") + this[TYPE] = "0"; + if (this[TYPE] === "0" && this.path.substr(-1) === "/") + this[TYPE] = "5"; + if (this[TYPE] === "5") + this.size = 0; + this.linkpath = decString(buf, off + 157, 100); + if (buf.slice(off + 257, off + 265).toString() === "ustar\x0000") { + 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) { + 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 * 32; + 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 * 32) + this.nullBlock = true; + } + [SLURP](ex, global2) { + for (const k in ex) { + if (ex[k] !== null && ex[k] !== void 0 && !(global2 && 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 path36 = split[0]; + const prefix = split[1]; + this.needPax = split[2]; + this.needPax = encString(buf, off, 100, path36) || 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\x0000", 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 * 32; + 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 (const i in data) { + if (data[i] !== null && data[i] !== void 0) + 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; + } + }; + var 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 { + prefix = pathModule.dirname(pp); + pp = pathModule.basename(pp); + do { + if (Buffer.byteLength(pp) <= pathSize && Buffer.byteLength(prefix) <= prefixSize) + ret = [pp, prefix, false]; + else if (Buffer.byteLength(pp) > pathSize && Buffer.byteLength(prefix) <= prefixSize) + ret = [pp.substr(0, pathSize - 1), prefix, true]; + else { + pp = pathModule.join(pathModule.basename(prefix), pp); + prefix = pathModule.dirname(prefix); + } + } while (prefix !== root && !ret); + if (!ret) + ret = [p.substr(0, pathSize - 1), "", true]; + } + return ret; + }; + var decString = (buf, off, size) => buf.slice(off, off + size).toString("utf8").replace(/\0.*/, ""); + var decDate = (buf, off, size) => numToDate(decNumber(buf, off, size)); + var numToDate = (num) => num === null ? null : new Date(num * 1e3); + var decNumber = (buf, off, size) => buf[off] & 128 ? large.parse(buf.slice(off, off + size)) : decSmallNumber(buf, off, size); + var nanNull = (value) => isNaN(value) ? null : value; + var decSmallNumber = (buf, off, size) => nanNull(parseInt(buf.slice(off, off + size).toString("utf8").replace(/\0.*$/, "").trim(), 8)); + var MAXNUM = { + 12: 8589934591, + 8: 2097151 + }; + var encNumber = (buf, off, size, number2) => number2 === null ? false : number2 > MAXNUM[size] || number2 < 0 ? (large.encode(number2, buf.slice(off, off + size)), true) : (encSmallNumber(buf, off, size, number2), false); + var encSmallNumber = (buf, off, size, number2) => buf.write(octalString(number2, size), off, size, "ascii"); + var octalString = (number2, size) => padOctal(Math.floor(number2).toString(8), size); + var padOctal = (string2, size) => (string2.length === size - 1 ? string2 : new Array(size - string2.length - 1).join("0") + string2 + " ") + "\0"; + var encDate = (buf, off, size, date) => date === null ? false : encNumber(buf, off, size, date.getTime() / 1e3); + var NULLS = new Array(156).join("\0"); + var encString = (buf, off, size, string2) => string2 === null ? false : (buf.write(string2 + NULLS, off, size, "utf8"), string2.length !== Buffer.byteLength(string2) || string2.length > size); + module2.exports = Header; + } +}); + +// node_modules/tar/lib/pax.js +var require_pax = __commonJS({ + "node_modules/tar/lib/pax.js"(exports2, module2) { + "use strict"; + var Header = require_header(); + var path36 = require("path"); + var Pax = class { + constructor(obj, global2) { + 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 = global2 || false; + } + encode() { + const body = this.encodeBody(); + if (body === "") + return null; + const bodyLen = Buffer.byteLength(body); + const bufLen = 512 * Math.ceil(1 + bodyLen / 512); + const buf = Buffer.allocUnsafe(bufLen); + for (let i = 0; i < 512; i++) + buf[i] = 0; + new Header({ + path: ("PaxHeader/" + path36.basename(this.path)).slice(0, 99), + mode: this.mode || 420, + 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"); + 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] === void 0) + return ""; + const v = this[field] instanceof Date ? this[field].getTime() / 1e3 : this[field]; + const s = " " + (field === "dev" || field === "ino" || field === "nlink" ? "SCHILY." : "") + field + "=" + v + "\n"; + const byteLen = Buffer.byteLength(s); + 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 = (string2, ex, g) => new Pax(merge(parseKV(string2), ex), g); + var merge = (a, b) => b ? Object.keys(a).reduce((s, k) => (s[k] = a[k], s), b) : a; + var parseKV = (string2) => string2.replace(/\n$/, "").split("\n").reduce(parseKVLine, Object.create(null)); + var parseKVLine = (set, line) => { + const n = parseInt(line, 10); + 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 * 1e3) : /^[0-9]+$/.test(v) ? +v : v; + return set; + }; + module2.exports = Pax; + } +}); + +// node_modules/tar/lib/strip-trailing-slashes.js +var require_strip_trailing_slashes = __commonJS({ + "node_modules/tar/lib/strip-trailing-slashes.js"(exports2, module2) { + module2.exports = (str) => { + let i = str.length - 1; + let slashesStart = -1; + while (i > -1 && str.charAt(i) === "/") { + slashesStart = i; + i--; + } + return slashesStart === -1 ? str : str.slice(0, slashesStart); + }; + } +}); + +// node_modules/tar/lib/warn-mixin.js +var require_warn_mixin = __commonJS({ + "node_modules/tar/lib/warn-mixin.js"(exports2, module2) { + "use strict"; + module2.exports = (Base) => class extends Base { + warn(code, message, data = {}) { + if (this.file) + data.file = this.file; + if (this.cwd) + data.cwd = this.cwd; + data.code = message instanceof Error && message.code || code; + data.tarCode = code; + if (!this.strict && data.recoverable !== false) { + if (message instanceof Error) { + data = Object.assign(message, data); + message = message.message; + } + this.emit("warn", data.tarCode, message, data); + } else if (message instanceof Error) + this.emit("error", Object.assign(message, data)); + else + this.emit("error", Object.assign(new Error(`${code}: ${message}`), data)); + } + }; + } +}); + +// node_modules/tar/lib/winchars.js +var require_winchars = __commonJS({ + "node_modules/tar/lib/winchars.js"(exports2, module2) { + "use strict"; + var raw = [ + "|", + "<", + ">", + "?", + ":" + ]; + var win = raw.map((char) => String.fromCharCode(61440 + char.charCodeAt(0))); + var toWin = new Map(raw.map((char, i) => [char, win[i]])); + var toRaw = new Map(win.map((char, i) => [char, raw[i]])); + module2.exports = { + encode: (s) => raw.reduce((s2, c) => s2.split(c).join(toWin.get(c)), s), + decode: (s) => win.reduce((s2, c) => s2.split(c).join(toRaw.get(c)), s) + }; + } +}); + +// node_modules/tar/lib/strip-absolute-path.js +var require_strip_absolute_path = __commonJS({ + "node_modules/tar/lib/strip-absolute-path.js"(exports2, module2) { + var { isAbsolute, parse: parse5 } = require("path").win32; + module2.exports = (path36) => { + let r = ""; + let parsed = parse5(path36); + while (isAbsolute(path36) || parsed.root) { + const root = path36.charAt(0) === "/" && path36.slice(0, 4) !== "//?/" ? "/" : parsed.root; + path36 = path36.substr(root.length); + r += root; + parsed = parse5(path36); + } + return [r, path36]; + }; + } +}); + +// node_modules/tar/lib/mode-fix.js +var require_mode_fix = __commonJS({ + "node_modules/tar/lib/mode-fix.js"(exports2, module2) { + "use strict"; + module2.exports = (mode, isDir, portable) => { + mode &= 4095; + if (portable) + mode = (mode | 384) & ~18; + if (isDir) { + if (mode & 256) + mode |= 64; + if (mode & 32) + mode |= 8; + if (mode & 4) + mode |= 1; + } + return mode; + }; + } +}); + +// node_modules/tar/lib/write-entry.js +var require_write_entry = __commonJS({ + "node_modules/tar/lib/write-entry.js"(exports2, module2) { + "use strict"; + var MiniPass = require_minipass(); + var Pax = require_pax(); + var Header = require_header(); + var fs27 = require("fs"); + var path36 = require("path"); + var normPath = require_normalize_windows_path(); + var stripSlash = require_strip_trailing_slashes(); + var prefixPath = (path37, prefix) => { + if (!prefix) + return normPath(path37); + path37 = normPath(path37).replace(/^\.(\/|$)/, ""); + return stripSlash(prefix) + "/" + path37; + }; + var maxReadSize = 16 * 1024 * 1024; + var PROCESS = Symbol("process"); + var FILE = Symbol("file"); + var DIRECTORY = Symbol("directory"); + var SYMLINK = Symbol("symlink"); + var HARDLINK = Symbol("hardlink"); + var HEADER = Symbol("header"); + var READ = Symbol("read"); + var LSTAT = Symbol("lstat"); + var ONLSTAT = Symbol("onlstat"); + var ONREAD = Symbol("onread"); + var ONREADLINK = Symbol("onreadlink"); + var OPENFILE = Symbol("openfile"); + var ONOPENFILE = Symbol("onopenfile"); + var CLOSE = Symbol("close"); + var MODE = Symbol("mode"); + var AWAITDRAIN = Symbol("awaitDrain"); + var ONDRAIN = Symbol("ondrain"); + var PREFIX = Symbol("prefix"); + var HAD_ERROR = Symbol("hadError"); + var warner = require_warn_mixin(); + var winchars = require_winchars(); + var stripAbsolutePath = require_strip_absolute_path(); + var modeFix = require_mode_fix(); + var 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 = normPath(p); + this.portable = !!opt.portable; + this.myuid = process.getuid && process.getuid() || 0; + 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 = normPath(opt.cwd || process.cwd()); + this.strict = !!opt.strict; + this.noPax = !!opt.noPax; + this.noMtime = !!opt.noMtime; + this.mtime = opt.mtime || null; + this.prefix = opt.prefix ? normPath(opt.prefix) : null; + this.fd = null; + this.blockLen = null; + this.blockRemain = null; + this.buf = null; + this.offset = null; + this.length = null; + this.pos = null; + this.remain = null; + if (typeof opt.onwarn === "function") + this.on("warn", opt.onwarn); + let pathWarn = false; + if (!this.preservePaths) { + const [root, stripped] = stripAbsolutePath(this.path); + if (root) { + this.path = stripped; + pathWarn = root; + } + } + this.win32 = !!opt.win32 || process.platform === "win32"; + if (this.win32) { + this.path = winchars.decode(this.path.replace(/\\/g, "/")); + p = p.replace(/\\/g, "/"); + } + this.absolute = normPath(opt.absolute || path36.resolve(this.cwd, p)); + if (this.path === "") + this.path = "./"; + if (pathWarn) { + this.warn("TAR_ENTRY_INFO", `stripping ${pathWarn} from absolute path`, { + entry: this, + path: pathWarn + this.path + }); + } + if (this.statCache.has(this.absolute)) + this[ONLSTAT](this.statCache.get(this.absolute)); + else + this[LSTAT](); + } + emit(ev, ...data) { + if (ev === "error") + this[HAD_ERROR] = true; + return super.emit(ev, ...data); + } + [LSTAT]() { + fs27.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](); + default: + return this.end(); + } + } + [MODE](mode) { + return modeFix(mode, this.type === "Directory", this.portable); + } + [PREFIX](path37) { + return prefixPath(path37, this.prefix); + } + [HEADER]() { + if (this.type === "Directory" && this.portable) + this.noMtime = true; + this.header = new Header({ + path: this[PREFIX](this.path), + linkpath: this.type === "Link" ? this[PREFIX](this.linkpath) : this.linkpath, + 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) { + super.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[PREFIX](this.path), + linkpath: this.type === "Link" ? this[PREFIX](this.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()); + } + super.write(this.header.block); + } + [DIRECTORY]() { + if (this.path.substr(-1) !== "/") + this.path += "/"; + this.stat.size = 0; + this[HEADER](); + this.end(); + } + [SYMLINK]() { + fs27.readlink(this.absolute, (er, linkpath) => { + if (er) + return this.emit("error", er); + this[ONREADLINK](linkpath); + }); + } + [ONREADLINK](linkpath) { + this.linkpath = normPath(linkpath); + this[HEADER](); + this.end(); + } + [HARDLINK](linkpath) { + this.type = "Link"; + this.linkpath = normPath(path36.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]() { + fs27.open(this.absolute, "r", (er, fd) => { + if (er) + return this.emit("error", er); + this[ONOPENFILE](fd); + }); + } + [ONOPENFILE](fd) { + this.fd = fd; + if (this[HAD_ERROR]) + return this[CLOSE](); + this.blockLen = 512 * Math.ceil(this.stat.size / 512); + this.blockRemain = this.blockLen; + const bufLen = Math.min(this.blockLen, this.maxReadSize); + this.buf = Buffer.allocUnsafe(bufLen); + this.offset = 0; + this.pos = 0; + this.remain = this.stat.size; + this.length = this.buf.length; + this[READ](); + } + [READ]() { + const { fd, buf, offset, length, pos } = this; + fs27.read(fd, buf, offset, length, pos, (er, bytesRead) => { + if (er) { + return this[CLOSE](() => this.emit("error", er)); + } + this[ONREAD](bytesRead); + }); + } + [CLOSE](cb) { + fs27.close(this.fd, cb); + } + [ONREAD](bytesRead) { + if (bytesRead <= 0 && this.remain > 0) { + const er = new Error("encountered unexpected EOF"); + er.path = this.absolute; + er.syscall = "read"; + er.code = "EOF"; + return this[CLOSE](() => this.emit("error", er)); + } + if (bytesRead > this.remain) { + const er = new Error("did not encounter expected EOF"); + er.path = this.absolute; + er.syscall = "read"; + er.code = "EOF"; + return this[CLOSE](() => this.emit("error", er)); + } + if (bytesRead === this.remain) { + for (let i = bytesRead; i < this.length && bytesRead < this.blockRemain; i++) { + this.buf[i + this.offset] = 0; + bytesRead++; + this.remain++; + } + } + const writeBuf = this.offset === 0 && bytesRead === this.buf.length ? this.buf : this.buf.slice(this.offset, this.offset + bytesRead); + const flushed = this.write(writeBuf); + if (!flushed) + this[AWAITDRAIN](() => this[ONDRAIN]()); + else + this[ONDRAIN](); + } + [AWAITDRAIN](cb) { + this.once("drain", cb); + } + write(writeBuf) { + if (this.blockRemain < writeBuf.length) { + const er = new Error("writing more data than expected"); + er.path = this.absolute; + return this.emit("error", er); + } + this.remain -= writeBuf.length; + this.blockRemain -= writeBuf.length; + this.pos += writeBuf.length; + this.offset += writeBuf.length; + return super.write(writeBuf); + } + [ONDRAIN]() { + if (!this.remain) { + if (this.blockRemain) + super.write(Buffer.alloc(this.blockRemain)); + return this[CLOSE]((er) => er ? this.emit("error", er) : this.end()); + } + if (this.offset >= this.length) { + this.buf = Buffer.allocUnsafe(Math.min(this.blockRemain, this.buf.length)); + this.offset = 0; + } + this.length = this.buf.length - this.offset; + this[READ](); + } + }); + var WriteEntrySync = class extends WriteEntry { + [LSTAT]() { + this[ONLSTAT](fs27.lstatSync(this.absolute)); + } + [SYMLINK]() { + this[ONREADLINK](fs27.readlinkSync(this.absolute)); + } + [OPENFILE]() { + this[ONOPENFILE](fs27.openSync(this.absolute, "r")); + } + [READ]() { + let threw = true; + try { + const { fd, buf, offset, length, pos } = this; + const bytesRead = fs27.readSync(fd, buf, offset, length, pos); + this[ONREAD](bytesRead); + threw = false; + } finally { + if (threw) { + try { + this[CLOSE](() => { + }); + } catch (er) { + } + } + } + } + [AWAITDRAIN](cb) { + cb(); + } + [CLOSE](cb) { + fs27.closeSync(this.fd); + cb(); + } + }; + var 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.prefix = opt.prefix || null; + this.path = normPath(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 = normPath(readEntry.linkpath); + if (typeof opt.onwarn === "function") + this.on("warn", opt.onwarn); + let pathWarn = false; + if (!this.preservePaths) { + const [root, stripped] = stripAbsolutePath(this.path); + if (root) { + this.path = stripped; + pathWarn = root; + } + } + this.remain = readEntry.size; + this.blockRemain = readEntry.startBlockSize; + this.header = new Header({ + path: this[PREFIX](this.path), + linkpath: this.type === "Link" ? this[PREFIX](this.linkpath) : this.linkpath, + 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 (pathWarn) { + this.warn("TAR_ENTRY_INFO", `stripping ${pathWarn} from absolute path`, { + entry: this, + path: pathWarn + this.path + }); + } + 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[PREFIX](this.path), + linkpath: this.type === "Link" ? this[PREFIX](this.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); + } + [PREFIX](path37) { + return prefixPath(path37, this.prefix); + } + [MODE](mode) { + return modeFix(mode, this.type === "Directory", this.portable); + } + 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) + super.write(Buffer.alloc(this.blockRemain)); + return super.end(); + } + }); + WriteEntry.Sync = WriteEntrySync; + WriteEntry.Tar = WriteEntryTar; + var getType = (stat) => stat.isFile() ? "File" : stat.isDirectory() ? "Directory" : stat.isSymbolicLink() ? "SymbolicLink" : "Unsupported"; + module2.exports = WriteEntry; + } +}); + +// node_modules/tar/lib/pack.js +var require_pack = __commonJS({ + "node_modules/tar/lib/pack.js"(exports2, module2) { + "use strict"; + var PackJob = class { + constructor(path37, absolute) { + this.path = path37 || "./"; + this.absolute = absolute; + this.entry = null; + this.stat = null; + this.readdir = null; + this.pending = false; + this.ignore = false; + this.piped = false; + } + }; + var MiniPass = require_minipass(); + var zlib = require_minizlib(); + var ReadEntry = require_read_entry(); + var WriteEntry = require_write_entry(); + var WriteEntrySync = WriteEntry.Sync; + var WriteEntryTar = WriteEntry.Tar; + var Yallist = require_yallist(); + var EOF = Buffer.alloc(1024); + var ONSTAT = Symbol("onStat"); + var ENDED = Symbol("ended"); + var QUEUE = Symbol("queue"); + var CURRENT = Symbol("current"); + var PROCESS = Symbol("process"); + var PROCESSING = Symbol("processing"); + var PROCESSJOB = Symbol("processJob"); + var JOBS = Symbol("jobs"); + var JOBDONE = Symbol("jobDone"); + var ADDFSENTRY = Symbol("addFSEntry"); + var ADDTARENTRY = Symbol("addTarEntry"); + var STAT = Symbol("stat"); + var READDIR = Symbol("readdir"); + var ONREADDIR = Symbol("onreaddir"); + var PIPE = Symbol("pipe"); + var ENTRY = Symbol("entry"); + var ENTRYOPT = Symbol("entryOpt"); + var WRITEENTRYCLASS = Symbol("writeEntryClass"); + var WRITE = Symbol("write"); + var ONDRAIN = Symbol("ondrain"); + var fs27 = require("fs"); + var path36 = require("path"); + var warner = require_warn_mixin(); + var normPath = require_normalize_windows_path(); + var Pack = warner(class Pack extends MiniPass { + constructor(opt) { + super(opt); + opt = opt || Object.create(null); + this.opt = opt; + this.file = opt.file || ""; + this.cwd = opt.cwd || process.cwd(); + this.maxReadSize = opt.maxReadSize; + this.preservePaths = !!opt.preservePaths; + this.strict = !!opt.strict; + this.noPax = !!opt.noPax; + this.prefix = normPath(opt.prefix || ""); + 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.portable = !!opt.portable; + this.zip = null; + if (opt.gzip) { + if (typeof opt.gzip !== "object") + opt.gzip = {}; + if (this.portable) + opt.gzip.portable = true; + 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.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(path37) { + this.write(path37); + return this; + } + end(path37) { + if (path37) + this.write(path37); + this[ENDED] = true; + this[PROCESS](); + return this; + } + write(path37) { + if (this[ENDED]) + throw new Error("write after end"); + if (path37 instanceof ReadEntry) + this[ADDTARENTRY](path37); + else + this[ADDFSENTRY](path37); + return this.flowing; + } + [ADDTARENTRY](p) { + const absolute = normPath(path36.resolve(this.cwd, p.path)); + 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 = normPath(path36.resolve(this.cwd, p)); + this[QUEUE].push(new PackJob(p, absolute)); + this[PROCESS](); + } + [STAT](job) { + job.pending = true; + this[JOBS] += 1; + const stat = this.follow ? "stat" : "lstat"; + fs27[stat](job.absolute, (er, stat2) => { + job.pending = false; + this[JOBS] -= 1; + if (er) + this.emit("error", er); + else + this[ONSTAT](job, stat2); + }); + } + [ONSTAT](job, stat) { + this.statCache.set(job.absolute, stat); + job.stat = stat; + if (!this.filter(job.path, stat)) + job.ignore = true; + this[PROCESS](); + } + [READDIR](job) { + job.pending = true; + this[JOBS] += 1; + fs27.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; + 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; + } + 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: (code, msg, data) => this.warn(code, 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, + prefix: this.prefix + }; + } + [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(); + } + [PIPE](job) { + job.piped = true; + if (job.readdir) { + job.readdir.forEach((entry) => { + const p = 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(); + } + }); + var PackSync = class extends Pack { + constructor(opt) { + super(opt); + this[WRITEENTRYCLASS] = WriteEntrySync; + } + pause() { + } + resume() { + } + [STAT](job) { + const stat = this.follow ? "statSync" : "lstatSync"; + this[ONSTAT](job, fs27[stat](job.absolute)); + } + [READDIR](job, stat) { + this[ONREADDIR](job, fs27.readdirSync(job.absolute)); + } + [PIPE](job) { + const source = job.entry; + const zip = this.zip; + if (job.readdir) { + job.readdir.forEach((entry) => { + const p = 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; + module2.exports = Pack; + } +}); + +// node_modules/fs-minipass/index.js +var require_fs_minipass = __commonJS({ + "node_modules/fs-minipass/index.js"(exports2) { + "use strict"; + var MiniPass = require_minipass(); + var EE = require("events").EventEmitter; + var fs27 = require("fs"); + var writev = fs27.writev; + if (!writev) { + const binding = process.binding("fs"); + const FSReqWrap = binding.FSReqWrap || binding.FSReqCallback; + 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); + }; + } + var _autoClose = Symbol("_autoClose"); + var _close = Symbol("_close"); + var _ended = Symbol("_ended"); + var _fd = Symbol("_fd"); + var _finished = Symbol("_finished"); + var _flags = Symbol("_flags"); + var _flush = Symbol("_flush"); + var _handleChunk = Symbol("_handleChunk"); + var _makeBuf = Symbol("_makeBuf"); + var _mode = Symbol("_mode"); + var _needDrain = Symbol("_needDrain"); + var _onerror = Symbol("_onerror"); + var _onopen = Symbol("_onopen"); + var _onread = Symbol("_onread"); + var _onwrite = Symbol("_onwrite"); + var _open = Symbol("_open"); + var _path = Symbol("_path"); + var _pos = Symbol("_pos"); + var _queue = Symbol("_queue"); + var _read = Symbol("_read"); + var _readSize = Symbol("_readSize"); + var _reading = Symbol("_reading"); + var _remain = Symbol("_remain"); + var _size = Symbol("_size"); + var _write = Symbol("_write"); + var _writing = Symbol("_writing"); + var _defaultFlag = Symbol("_defaultFlag"); + var _errored = Symbol("_errored"); + var ReadStream = class extends MiniPass { + constructor(path36, opt) { + opt = opt || {}; + super(opt); + this.readable = true; + this.writable = false; + if (typeof path36 !== "string") + throw new TypeError("path must be a string"); + this[_errored] = false; + this[_fd] = typeof opt.fd === "number" ? opt.fd : null; + this[_path] = path36; + 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]() { + fs27.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](); + if (buf.length === 0) + return process.nextTick(() => this[_onread](null, 0, buf)); + fs27.read(this[_fd], buf, 0, buf.length, null, (er, br, buf2) => this[_onread](er, br, buf2)); + } + } + [_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") { + const fd = this[_fd]; + this[_fd] = null; + fs27.close(fd, (er) => er ? this.emit("error", er) : this.emit("close")); + } + } + [_onerror](er) { + this[_reading] = true; + this[_close](); + this.emit("error", er); + } + [_handleChunk](br, buf) { + let ret = false; + 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; + case "error": + if (this[_errored]) + return; + this[_errored] = true; + return super.emit(ev, data); + default: + return super.emit(ev, data); + } + } + }; + var ReadStreamSync = class extends ReadStream { + [_open]() { + let threw = true; + try { + this[_onopen](null, fs27.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](); + const br = buf.length === 0 ? 0 : fs27.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") { + const fd = this[_fd]; + this[_fd] = null; + fs27.closeSync(fd); + this.emit("close"); + } + } + }; + var WriteStream = class extends EE { + constructor(path36, opt) { + opt = opt || {}; + super(opt); + this.readable = false; + this.writable = true; + this[_errored] = false; + this[_writing] = false; + this[_ended] = false; + this[_needDrain] = false; + this[_queue] = []; + this[_path] = path36; + this[_fd] = typeof opt.fd === "number" ? opt.fd : null; + this[_mode] = opt.mode === void 0 ? 438 : opt.mode; + this[_pos] = typeof opt.start === "number" ? opt.start : null; + this[_autoClose] = typeof opt.autoClose === "boolean" ? opt.autoClose : true; + const defaultFlag = this[_pos] !== null ? "r+" : "w"; + this[_defaultFlag] = opt.flags === void 0; + this[_flags] = this[_defaultFlag] ? defaultFlag : opt.flags; + if (this[_fd] === null) + this[_open](); + } + emit(ev, data) { + if (ev === "error") { + if (this[_errored]) + return; + this[_errored] = true; + } + return super.emit(ev, data); + } + get fd() { + return this[_fd]; + } + get path() { + return this[_path]; + } + [_onerror](er) { + this[_close](); + this[_writing] = true; + this.emit("error", er); + } + [_open]() { + fs27.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; + if (!this[_writing] && !this[_queue].length && typeof this[_fd] === "number") + this[_onwrite](null, 0); + return this; + } + write(buf, enc) { + if (typeof buf === "string") + buf = Buffer.from(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) { + fs27.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") { + const fd = this[_fd]; + this[_fd] = null; + fs27.close(fd, (er) => er ? this.emit("error", er) : this.emit("close")); + } + } + }; + var WriteStreamSync = class extends WriteStream { + [_open]() { + let fd; + if (this[_defaultFlag] && this[_flags] === "r+") { + try { + fd = fs27.openSync(this[_path], this[_flags], this[_mode]); + } catch (er) { + if (er.code === "ENOENT") { + this[_flags] = "w"; + return this[_open](); + } else + throw er; + } + } else + fd = fs27.openSync(this[_path], this[_flags], this[_mode]); + this[_onopen](null, fd); + } + [_close]() { + if (this[_autoClose] && typeof this[_fd] === "number") { + const fd = this[_fd]; + this[_fd] = null; + fs27.closeSync(fd); + this.emit("close"); + } + } + [_write](buf) { + let threw = true; + try { + this[_onwrite](null, fs27.writeSync(this[_fd], buf, 0, buf.length, this[_pos])); + threw = false; + } finally { + if (threw) + try { + this[_close](); + } catch (_) { + } + } + } + }; + exports2.ReadStream = ReadStream; + exports2.ReadStreamSync = ReadStreamSync; + exports2.WriteStream = WriteStream; + exports2.WriteStreamSync = WriteStreamSync; + } +}); + +// node_modules/tar/lib/parse.js +var require_parse2 = __commonJS({ + "node_modules/tar/lib/parse.js"(exports2, module2) { + "use strict"; + var warner = require_warn_mixin(); + var Header = require_header(); + var EE = require("events"); + var Yallist = require_yallist(); + var maxMetaEntrySize = 1024 * 1024; + var Entry = require_read_entry(); + var Pax = require_pax(); + var zlib = require_minizlib(); + var gzipHeader = Buffer.from([31, 139]); + var STATE = Symbol("state"); + var WRITEENTRY = Symbol("writeEntry"); + var READENTRY = Symbol("readEntry"); + var NEXTENTRY = Symbol("nextEntry"); + var PROCESSENTRY = Symbol("processEntry"); + var EX = Symbol("extendedHeader"); + var GEX = Symbol("globalExtendedHeader"); + var META = Symbol("meta"); + var EMITMETA = Symbol("emitMeta"); + var BUFFER = Symbol("buffer"); + var QUEUE = Symbol("queue"); + var ENDED = Symbol("ended"); + var EMITTEDEND = Symbol("emittedEnd"); + var EMIT = Symbol("emit"); + var UNZIP = Symbol("unzip"); + var CONSUMECHUNK = Symbol("consumeChunk"); + var CONSUMECHUNKSUB = Symbol("consumeChunkSub"); + var CONSUMEBODY = Symbol("consumeBody"); + var CONSUMEMETA = Symbol("consumeMeta"); + var CONSUMEHEADER = Symbol("consumeHeader"); + var CONSUMING = Symbol("consuming"); + var BUFFERCONCAT = Symbol("bufferConcat"); + var MAYBEEND = Symbol("maybeEnd"); + var WRITING = Symbol("writing"); + var ABORTED = Symbol("aborted"); + var DONE = Symbol("onDone"); + var SAW_VALID_ENTRY = Symbol("sawValidEntry"); + var SAW_NULL_BLOCK = Symbol("sawNullBlock"); + var SAW_EOF = Symbol("sawEOF"); + var noop = (_) => true; + module2.exports = warner(class Parser extends EE { + constructor(opt) { + opt = opt || {}; + super(opt); + this.file = opt.file || ""; + this[SAW_VALID_ENTRY] = null; + this.on(DONE, (_) => { + if (this[STATE] === "begin" || this[SAW_VALID_ENTRY] === false) { + this.warn("TAR_BAD_ARCHIVE", "Unrecognized archive format"); + } + }); + 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; + 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; + this[SAW_NULL_BLOCK] = false; + this[SAW_EOF] = false; + if (typeof opt.onwarn === "function") + this.on("warn", opt.onwarn); + if (typeof opt.onentry === "function") + this.on("entry", opt.onentry); + } + [CONSUMEHEADER](chunk, position) { + if (this[SAW_VALID_ENTRY] === null) + this[SAW_VALID_ENTRY] = false; + let header; + try { + header = new Header(chunk, position, this[EX], this[GEX]); + } catch (er) { + return this.warn("TAR_ENTRY_INVALID", er); + } + if (header.nullBlock) { + if (this[SAW_NULL_BLOCK]) { + this[SAW_EOF] = true; + if (this[STATE] === "begin") + this[STATE] = "header"; + this[EMIT]("eof"); + } else { + this[SAW_NULL_BLOCK] = true; + this[EMIT]("nullBlock"); + } + } else { + this[SAW_NULL_BLOCK] = false; + if (!header.cksumValid) + this.warn("TAR_ENTRY_INVALID", "checksum failure", { header }); + else if (!header.path) + this.warn("TAR_ENTRY_INVALID", "path is required", { header }); + else { + const type = header.type; + if (/^(Symbolic)?Link$/.test(type) && !header.linkpath) + this.warn("TAR_ENTRY_INVALID", "linkpath required", { header }); + else if (!/^(Symbolic)?Link$/.test(type) && header.linkpath) + this.warn("TAR_ENTRY_INVALID", "linkpath forbidden", { header }); + else { + const entry = this[WRITEENTRY] = new Entry(header, this[EX], this[GEX]); + if (!this[SAW_VALID_ENTRY]) { + if (entry.remain) { + const onend = () => { + if (!entry.invalid) + this[SAW_VALID_ENTRY] = true; + }; + entry.on("end", onend); + } else + this[SAW_VALID_ENTRY] = true; + } + if (entry.meta) { + if (entry.size > this.maxMetaEntrySize) { + entry.ignore = true; + this[EMIT]("ignoredEntry", entry); + this[STATE] = "ignore"; + entry.resume(); + } 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" : "header"; + entry.resume(); + } else { + if (entry.remain) + this[STATE] = "body"; + else { + this[STATE] = "header"; + 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) { + 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) { + 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] = "header"; + this[WRITEENTRY] = null; + entry.end(); + } + return c.length; + } + [CONSUMEMETA](chunk, position) { + const entry = this[WRITEENTRY]; + const ret = this[CONSUMEBODY](chunk, position); + 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; + default: + throw new Error("unknown meta: " + entry.type); + } + } + abort(error) { + this[ABORTED] = true; + this.emit("abort", error); + this.warn("TAR_ABORT", error, { recoverable: false }); + } + write(chunk) { + if (this[ABORTED]) + return; + 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", (chunk2) => this[CONSUMECHUNK](chunk2)); + this[UNZIP].on("error", (er) => this.abort(er)); + this[UNZIP].on("end", (_) => { + this[ENDED] = true; + this[CONSUMECHUNK](); + }); + this[WRITING] = true; + const ret2 = this[UNZIP][ended ? "end" : "write"](chunk); + this[WRITING] = false; + return ret2; + } + } + this[WRITING] = true; + if (this[UNZIP]) + this[UNZIP].write(chunk); + else + this[CONSUMECHUNK](chunk); + this[WRITING] = false; + const ret = this[QUEUE].length ? false : this[READENTRY] ? this[READENTRY].flowing : true; + 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("TAR_BAD_ARCHIVE", `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] && !this[SAW_EOF]) { + const c = this[BUFFER]; + this[BUFFER] = null; + this[CONSUMECHUNKSUB](c); + } + this[CONSUMING] = false; + } + if (!this[BUFFER] || this[ENDED]) + this[MAYBEEND](); + } + [CONSUMECHUNKSUB](chunk) { + let position = 0; + const length = chunk.length; + while (position + 512 <= length && !this[ABORTED] && !this[SAW_EOF]) { + switch (this[STATE]) { + case "begin": + case "header": + 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; + 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); + } + } + } + }); + } +}); + +// node_modules/tar/lib/list.js +var require_list = __commonJS({ + "node_modules/tar/lib/list.js"(exports2, module2) { + "use strict"; + var hlo = require_high_level_opt(); + var Parser = require_parse2(); + var fs27 = require("fs"); + var fsm = require_fs_minipass(); + var path36 = require("path"); + var stripSlash = require_strip_trailing_slashes(); + module2.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) : list2(opt); + }; + var onentryFunction = (opt) => { + const onentry = opt.onentry; + opt.onentry = onentry ? (e) => { + onentry(e); + e.resume(); + } : (e) => e.resume(); + }; + var filesFilter = (opt, files) => { + const map = new Map(files.map((f) => [stripSlash(f), true])); + const filter = opt.filter; + const mapHas = (file, r) => { + const root = r || path36.parse(file).root || "."; + const ret = file === root ? false : map.has(file) ? map.get(file) : mapHas(path36.dirname(file), root); + map.set(file, ret); + return ret; + }; + opt.filter = filter ? (file, entry) => filter(file, entry) && mapHas(stripSlash(file)) : (file) => mapHas(stripSlash(file)); + }; + var listFileSync = (opt) => { + const p = list2(opt); + const file = opt.file; + let threw = true; + let fd; + try { + const stat = fs27.statSync(file); + const readSize = opt.maxReadSize || 16 * 1024 * 1024; + if (stat.size < readSize) + p.end(fs27.readFileSync(file)); + else { + let pos = 0; + const buf = Buffer.allocUnsafe(readSize); + fd = fs27.openSync(file, "r"); + while (pos < stat.size) { + const bytesRead = fs27.readSync(fd, buf, 0, readSize, pos); + pos += bytesRead; + p.write(buf.slice(0, bytesRead)); + } + p.end(); + } + threw = false; + } finally { + if (threw && fd) { + try { + fs27.closeSync(fd); + } catch (er) { + } + } + } + }; + var listFile = (opt, cb) => { + const parse5 = new Parser(opt); + const readSize = opt.maxReadSize || 16 * 1024 * 1024; + const file = opt.file; + const p = new Promise((resolve3, reject) => { + parse5.on("error", reject); + parse5.on("end", resolve3); + fs27.stat(file, (er, stat) => { + if (er) + reject(er); + else { + const stream = new fsm.ReadStream(file, { + readSize, + size: stat.size + }); + stream.on("error", reject); + stream.pipe(parse5); + } + }); + }); + return cb ? p.then(cb, cb) : p; + }; + var list2 = (opt) => new Parser(opt); + } +}); + +// node_modules/tar/lib/create.js +var require_create = __commonJS({ + "node_modules/tar/lib/create.js"(exports2, module2) { + "use strict"; + var hlo = require_high_level_opt(); + var Pack = require_pack(); + var fsm = require_fs_minipass(); + var t = require_list(); + var path36 = require("path"); + module2.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); + }; + var createFileSync = (opt, files) => { + const p = new Pack.Sync(opt); + const stream = new fsm.WriteStreamSync(opt.file, { + mode: opt.mode || 438 + }); + p.pipe(stream); + addFilesSync(p, files); + }; + var createFile = (opt, files, cb) => { + const p = new Pack(opt); + const stream = new fsm.WriteStream(opt.file, { + mode: opt.mode || 438 + }); + 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; + }; + var addFilesSync = (p, files) => { + files.forEach((file) => { + if (file.charAt(0) === "@") { + t({ + file: path36.resolve(p.cwd, file.substr(1)), + sync: true, + noResume: true, + onentry: (entry) => p.add(entry) + }); + } else + p.add(file); + }); + p.end(); + }; + var addFilesAsync = (p, files) => { + while (files.length) { + const file = files.shift(); + if (file.charAt(0) === "@") { + return t({ + file: path36.resolve(p.cwd, file.substr(1)), + noResume: true, + onentry: (entry) => p.add(entry) + }).then((_) => addFilesAsync(p, files)); + } else + p.add(file); + } + p.end(); + }; + var createSync = (opt, files) => { + const p = new Pack.Sync(opt); + addFilesSync(p, files); + return p; + }; + var create = (opt, files) => { + const p = new Pack(opt); + addFilesAsync(p, files); + return p; + }; + } +}); + +// node_modules/tar/lib/replace.js +var require_replace = __commonJS({ + "node_modules/tar/lib/replace.js"(exports2, module2) { + "use strict"; + var hlo = require_high_level_opt(); + var Pack = require_pack(); + var fs27 = require("fs"); + var fsm = require_fs_minipass(); + var t = require_list(); + var path36 = require("path"); + var Header = require_header(); + module2.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); + }; + var replaceSync = (opt, files) => { + const p = new Pack.Sync(opt); + let threw = true; + let fd; + let position; + try { + try { + fd = fs27.openSync(opt.file, "r+"); + } catch (er) { + if (er.code === "ENOENT") + fd = fs27.openSync(opt.file, "w+"); + else + throw er; + } + const st = fs27.fstatSync(fd); + const headBuf = Buffer.alloc(512); + POSITION: + for (position = 0; position < st.size; position += 512) { + for (let bufPos = 0, bytes2 = 0; bufPos < 512; bufPos += bytes2) { + bytes2 = fs27.readSync(fd, headBuf, bufPos, headBuf.length - bufPos, position + bufPos); + if (position === 0 && headBuf[0] === 31 && headBuf[1] === 139) + throw new Error("cannot append to compressed archives"); + if (!bytes2) + break POSITION; + } + const h = new Header(headBuf); + if (!h.cksumValid) + break; + const entryBlockSize = 512 * Math.ceil(h.size / 512); + if (position + entryBlockSize + 512 > st.size) + break; + position += entryBlockSize; + if (opt.mtimeCache) + opt.mtimeCache.set(h.path, h.mtime); + } + threw = false; + streamSync(opt, p, position, fd, files); + } finally { + if (threw) { + try { + fs27.closeSync(fd); + } catch (er) { + } + } + } + }; + var streamSync = (opt, p, position, fd, files) => { + const stream = new fsm.WriteStreamSync(opt.file, { + fd, + start: position + }); + p.pipe(stream); + addFilesSync(p, files); + }; + var replace = (opt, files, cb) => { + files = Array.from(files); + const p = new Pack(opt); + const getPos = (fd, size, cb_) => { + const cb2 = (er, pos) => { + if (er) + fs27.close(fd, (_) => cb_(er)); + else + cb_(null, pos); + }; + let position = 0; + if (size === 0) + return cb2(null, 0); + let bufPos = 0; + const headBuf = Buffer.alloc(512); + const onread = (er, bytes2) => { + if (er) + return cb2(er); + bufPos += bytes2; + if (bufPos < 512 && bytes2) { + return fs27.read(fd, headBuf, bufPos, headBuf.length - bufPos, position + bufPos, onread); + } + if (position === 0 && headBuf[0] === 31 && headBuf[1] === 139) + return cb2(new Error("cannot append to compressed archives")); + if (bufPos < 512) + return cb2(null, position); + const h = new Header(headBuf); + if (!h.cksumValid) + return cb2(null, position); + const entryBlockSize = 512 * Math.ceil(h.size / 512); + if (position + entryBlockSize + 512 > size) + return cb2(null, position); + position += entryBlockSize + 512; + if (position >= size) + return cb2(null, position); + if (opt.mtimeCache) + opt.mtimeCache.set(h.path, h.mtime); + bufPos = 0; + fs27.read(fd, headBuf, 0, 512, position, onread); + }; + fs27.read(fd, headBuf, 0, 512, position, onread); + }; + const promise = new Promise((resolve3, reject) => { + p.on("error", reject); + let flag = "r+"; + const onopen = (er, fd) => { + if (er && er.code === "ENOENT" && flag === "r+") { + flag = "w+"; + return fs27.open(opt.file, flag, onopen); + } + if (er) + return reject(er); + fs27.fstat(fd, (er2, st) => { + if (er2) + return fs27.close(fd, () => reject(er2)); + getPos(fd, st.size, (er3, position) => { + if (er3) + return reject(er3); + const stream = new fsm.WriteStream(opt.file, { + fd, + start: position + }); + p.pipe(stream); + stream.on("error", reject); + stream.on("close", resolve3); + addFilesAsync(p, files); + }); + }); + }; + fs27.open(opt.file, flag, onopen); + }); + return cb ? promise.then(cb, cb) : promise; + }; + var addFilesSync = (p, files) => { + files.forEach((file) => { + if (file.charAt(0) === "@") { + t({ + file: path36.resolve(p.cwd, file.substr(1)), + sync: true, + noResume: true, + onentry: (entry) => p.add(entry) + }); + } else + p.add(file); + }); + p.end(); + }; + var addFilesAsync = (p, files) => { + while (files.length) { + const file = files.shift(); + if (file.charAt(0) === "@") { + return t({ + file: path36.resolve(p.cwd, file.substr(1)), + noResume: true, + onentry: (entry) => p.add(entry) + }).then((_) => addFilesAsync(p, files)); + } else + p.add(file); + } + p.end(); + }; + } +}); + +// node_modules/tar/lib/update.js +var require_update = __commonJS({ + "node_modules/tar/lib/update.js"(exports2, module2) { + "use strict"; + var hlo = require_high_level_opt(); + var r = require_replace(); + module2.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); + }; + var mtimeFilter = (opt) => { + const filter = opt.filter; + if (!opt.mtimeCache) + opt.mtimeCache = new Map(); + opt.filter = filter ? (path36, stat) => filter(path36, stat) && !(opt.mtimeCache.get(path36) > stat.mtime) : (path36, stat) => !(opt.mtimeCache.get(path36) > stat.mtime); + }; + } +}); + +// node_modules/tar/node_modules/mkdirp/lib/opts-arg.js +var require_opts_arg = __commonJS({ + "node_modules/tar/node_modules/mkdirp/lib/opts-arg.js"(exports2, module2) { + var { promisify } = require("util"); + var fs27 = require("fs"); + var optsArg = (opts) => { + if (!opts) + opts = { mode: 511, fs: fs27 }; + else if (typeof opts === "object") + opts = __spreadValues({ mode: 511, fs: fs27 }, opts); + else if (typeof opts === "number") + opts = { mode: opts, fs: fs27 }; + else if (typeof opts === "string") + opts = { mode: parseInt(opts, 8), fs: fs27 }; + else + throw new TypeError("invalid options argument"); + opts.mkdir = opts.mkdir || opts.fs.mkdir || fs27.mkdir; + opts.mkdirAsync = promisify(opts.mkdir); + opts.stat = opts.stat || opts.fs.stat || fs27.stat; + opts.statAsync = promisify(opts.stat); + opts.statSync = opts.statSync || opts.fs.statSync || fs27.statSync; + opts.mkdirSync = opts.mkdirSync || opts.fs.mkdirSync || fs27.mkdirSync; + return opts; + }; + module2.exports = optsArg; + } +}); + +// node_modules/tar/node_modules/mkdirp/lib/path-arg.js +var require_path_arg = __commonJS({ + "node_modules/tar/node_modules/mkdirp/lib/path-arg.js"(exports2, module2) { + var platform3 = process.env.__TESTING_MKDIRP_PLATFORM__ || process.platform; + var { resolve: resolve3, parse: parse5 } = require("path"); + var pathArg = (path36) => { + if (/\0/.test(path36)) { + throw Object.assign(new TypeError("path must be a string without null bytes"), { + path: path36, + code: "ERR_INVALID_ARG_VALUE" + }); + } + path36 = resolve3(path36); + if (platform3 === "win32") { + const badWinChars = /[*|"<>?:]/; + const { root } = parse5(path36); + if (badWinChars.test(path36.substr(root.length))) { + throw Object.assign(new Error("Illegal characters in path."), { + path: path36, + code: "EINVAL" + }); + } + } + return path36; + }; + module2.exports = pathArg; + } +}); + +// node_modules/tar/node_modules/mkdirp/lib/find-made.js +var require_find_made = __commonJS({ + "node_modules/tar/node_modules/mkdirp/lib/find-made.js"(exports2, module2) { + var { dirname: dirname3 } = require("path"); + var findMade = (opts, parent, path36 = void 0) => { + if (path36 === parent) + return Promise.resolve(); + return opts.statAsync(parent).then((st) => st.isDirectory() ? path36 : void 0, (er) => er.code === "ENOENT" ? findMade(opts, dirname3(parent), parent) : void 0); + }; + var findMadeSync = (opts, parent, path36 = void 0) => { + if (path36 === parent) + return void 0; + try { + return opts.statSync(parent).isDirectory() ? path36 : void 0; + } catch (er) { + return er.code === "ENOENT" ? findMadeSync(opts, dirname3(parent), parent) : void 0; + } + }; + module2.exports = { findMade, findMadeSync }; + } +}); + +// node_modules/tar/node_modules/mkdirp/lib/mkdirp-manual.js +var require_mkdirp_manual = __commonJS({ + "node_modules/tar/node_modules/mkdirp/lib/mkdirp-manual.js"(exports2, module2) { + var { dirname: dirname3 } = require("path"); + var mkdirpManual = (path36, opts, made) => { + opts.recursive = false; + const parent = dirname3(path36); + if (parent === path36) { + return opts.mkdirAsync(path36, opts).catch((er) => { + if (er.code !== "EISDIR") + throw er; + }); + } + return opts.mkdirAsync(path36, opts).then(() => made || path36, (er) => { + if (er.code === "ENOENT") + return mkdirpManual(parent, opts).then((made2) => mkdirpManual(path36, opts, made2)); + if (er.code !== "EEXIST" && er.code !== "EROFS") + throw er; + return opts.statAsync(path36).then((st) => { + if (st.isDirectory()) + return made; + else + throw er; + }, () => { + throw er; + }); + }); + }; + var mkdirpManualSync = (path36, opts, made) => { + const parent = dirname3(path36); + opts.recursive = false; + if (parent === path36) { + try { + return opts.mkdirSync(path36, opts); + } catch (er) { + if (er.code !== "EISDIR") + throw er; + else + return; + } + } + try { + opts.mkdirSync(path36, opts); + return made || path36; + } catch (er) { + if (er.code === "ENOENT") + return mkdirpManualSync(path36, opts, mkdirpManualSync(parent, opts, made)); + if (er.code !== "EEXIST" && er.code !== "EROFS") + throw er; + try { + if (!opts.statSync(path36).isDirectory()) + throw er; + } catch (_) { + throw er; + } + } + }; + module2.exports = { mkdirpManual, mkdirpManualSync }; + } +}); + +// node_modules/tar/node_modules/mkdirp/lib/mkdirp-native.js +var require_mkdirp_native = __commonJS({ + "node_modules/tar/node_modules/mkdirp/lib/mkdirp-native.js"(exports2, module2) { + var { dirname: dirname3 } = require("path"); + var { findMade, findMadeSync } = require_find_made(); + var { mkdirpManual, mkdirpManualSync } = require_mkdirp_manual(); + var mkdirpNative = (path36, opts) => { + opts.recursive = true; + const parent = dirname3(path36); + if (parent === path36) + return opts.mkdirAsync(path36, opts); + return findMade(opts, path36).then((made) => opts.mkdirAsync(path36, opts).then(() => made).catch((er) => { + if (er.code === "ENOENT") + return mkdirpManual(path36, opts); + else + throw er; + })); + }; + var mkdirpNativeSync = (path36, opts) => { + opts.recursive = true; + const parent = dirname3(path36); + if (parent === path36) + return opts.mkdirSync(path36, opts); + const made = findMadeSync(opts, path36); + try { + opts.mkdirSync(path36, opts); + return made; + } catch (er) { + if (er.code === "ENOENT") + return mkdirpManualSync(path36, opts); + else + throw er; + } + }; + module2.exports = { mkdirpNative, mkdirpNativeSync }; + } +}); + +// node_modules/tar/node_modules/mkdirp/lib/use-native.js +var require_use_native = __commonJS({ + "node_modules/tar/node_modules/mkdirp/lib/use-native.js"(exports2, module2) { + var fs27 = require("fs"); + var version2 = process.env.__TESTING_MKDIRP_NODE_VERSION__ || process.version; + var versArr = version2.replace(/^v/, "").split("."); + var hasNative = +versArr[0] > 10 || +versArr[0] === 10 && +versArr[1] >= 12; + var useNative = !hasNative ? () => false : (opts) => opts.mkdir === fs27.mkdir; + var useNativeSync = !hasNative ? () => false : (opts) => opts.mkdirSync === fs27.mkdirSync; + module2.exports = { useNative, useNativeSync }; + } +}); + +// node_modules/tar/node_modules/mkdirp/index.js +var require_mkdirp = __commonJS({ + "node_modules/tar/node_modules/mkdirp/index.js"(exports2, module2) { + var optsArg = require_opts_arg(); + var pathArg = require_path_arg(); + var { mkdirpNative, mkdirpNativeSync } = require_mkdirp_native(); + var { mkdirpManual, mkdirpManualSync } = require_mkdirp_manual(); + var { useNative, useNativeSync } = require_use_native(); + var mkdirp = (path36, opts) => { + path36 = pathArg(path36); + opts = optsArg(opts); + return useNative(opts) ? mkdirpNative(path36, opts) : mkdirpManual(path36, opts); + }; + var mkdirpSync = (path36, opts) => { + path36 = pathArg(path36); + opts = optsArg(opts); + return useNativeSync(opts) ? mkdirpNativeSync(path36, opts) : mkdirpManualSync(path36, opts); + }; + mkdirp.sync = mkdirpSync; + mkdirp.native = (path36, opts) => mkdirpNative(pathArg(path36), optsArg(opts)); + mkdirp.manual = (path36, opts) => mkdirpManual(pathArg(path36), optsArg(opts)); + mkdirp.nativeSync = (path36, opts) => mkdirpNativeSync(pathArg(path36), optsArg(opts)); + mkdirp.manualSync = (path36, opts) => mkdirpManualSync(pathArg(path36), optsArg(opts)); + module2.exports = mkdirp; + } +}); + +// node_modules/chownr/chownr.js +var require_chownr = __commonJS({ + "node_modules/chownr/chownr.js"(exports2, module2) { + "use strict"; + var fs27 = require("fs"); + var path36 = require("path"); + var LCHOWN = fs27.lchown ? "lchown" : "chown"; + var LCHOWNSYNC = fs27.lchownSync ? "lchownSync" : "chownSync"; + var needEISDIRHandled = fs27.lchown && !process.version.match(/v1[1-9]+\./) && !process.version.match(/v10\.[6-9]/); + var lchownSync = (path37, uid, gid) => { + try { + return fs27[LCHOWNSYNC](path37, uid, gid); + } catch (er) { + if (er.code !== "ENOENT") + throw er; + } + }; + var chownSync = (path37, uid, gid) => { + try { + return fs27.chownSync(path37, uid, gid); + } catch (er) { + if (er.code !== "ENOENT") + throw er; + } + }; + var handleEISDIR = needEISDIRHandled ? (path37, uid, gid, cb) => (er) => { + if (!er || er.code !== "EISDIR") + cb(er); + else + fs27.chown(path37, uid, gid, cb); + } : (_, __, ___, cb) => cb; + var handleEISDirSync = needEISDIRHandled ? (path37, uid, gid) => { + try { + return lchownSync(path37, uid, gid); + } catch (er) { + if (er.code !== "EISDIR") + throw er; + chownSync(path37, uid, gid); + } + } : (path37, uid, gid) => lchownSync(path37, uid, gid); + var nodeVersion = process.version; + var readdir = (path37, options, cb) => fs27.readdir(path37, options, cb); + var readdirSync = (path37, options) => fs27.readdirSync(path37, options); + if (/^v4\./.test(nodeVersion)) + readdir = (path37, options, cb) => fs27.readdir(path37, cb); + var chown = (cpath, uid, gid, cb) => { + fs27[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, (er) => { + cb(er && er.code !== "ENOENT" ? er : null); + })); + }; + var chownrKid = (p, child, uid, gid, cb) => { + if (typeof child === "string") + return fs27.lstat(path36.resolve(p, child), (er, stats) => { + if (er) + return cb(er.code !== "ENOENT" ? er : null); + stats.name = child; + chownrKid(p, stats, uid, gid, cb); + }); + if (child.isDirectory()) { + chownr(path36.resolve(p, child.name), uid, gid, (er) => { + if (er) + return cb(er); + const cpath = path36.resolve(p, child.name); + chown(cpath, uid, gid, cb); + }); + } else { + const cpath = path36.resolve(p, child.name); + chown(cpath, uid, gid, cb); + } + }; + var chownr = (p, uid, gid, cb) => { + readdir(p, { withFileTypes: true }, (er, children) => { + if (er) { + if (er.code === "ENOENT") + return cb(); + else if (er.code !== "ENOTDIR" && er.code !== "ENOTSUP") + return cb(er); + } + if (er || !children.length) + return chown(p, uid, gid, cb); + let len = children.length; + let errState = null; + const then = (er2) => { + if (errState) + return; + if (er2) + return cb(errState = er2); + if (--len === 0) + return chown(p, uid, gid, cb); + }; + children.forEach((child) => chownrKid(p, child, uid, gid, then)); + }); + }; + var chownrKidSync = (p, child, uid, gid) => { + if (typeof child === "string") { + try { + const stats = fs27.lstatSync(path36.resolve(p, child)); + stats.name = child; + child = stats; + } catch (er) { + if (er.code === "ENOENT") + return; + else + throw er; + } + } + if (child.isDirectory()) + chownrSync(path36.resolve(p, child.name), uid, gid); + handleEISDirSync(path36.resolve(p, child.name), uid, gid); + }; + var chownrSync = (p, uid, gid) => { + let children; + try { + children = readdirSync(p, { withFileTypes: true }); + } catch (er) { + if (er.code === "ENOENT") + return; + else if (er.code === "ENOTDIR" || er.code === "ENOTSUP") + return handleEISDirSync(p, uid, gid); + else + throw er; + } + if (children && children.length) + children.forEach((child) => chownrKidSync(p, child, uid, gid)); + return handleEISDirSync(p, uid, gid); + }; + module2.exports = chownr; + chownr.sync = chownrSync; + } +}); + +// node_modules/tar/lib/mkdir.js +var require_mkdir = __commonJS({ + "node_modules/tar/lib/mkdir.js"(exports2, module2) { + "use strict"; + var mkdirp = require_mkdirp(); + var fs27 = require("fs"); + var path36 = require("path"); + var chownr = require_chownr(); + var normPath = require_normalize_windows_path(); + var SymlinkError = class extends Error { + constructor(symlink, path37) { + super("Cannot extract through symbolic link"); + this.path = path37; + this.symlink = symlink; + } + get name() { + return "SylinkError"; + } + }; + var CwdError = class extends Error { + constructor(path37, code) { + super(code + ": Cannot cd into '" + path37 + "'"); + this.path = path37; + this.code = code; + } + get name() { + return "CwdError"; + } + }; + var cGet = (cache, key) => cache.get(normPath(key)); + var cSet = (cache, key, val) => cache.set(normPath(key), val); + var checkCwd = (dir, cb) => { + fs27.stat(dir, (er, st) => { + if (er || !st.isDirectory()) + er = new CwdError(dir, er && er.code || "ENOTDIR"); + cb(er); + }); + }; + module2.exports = (dir, opt, cb) => { + dir = normPath(dir); + const umask = opt.umask; + const mode = opt.mode | 448; + 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 = normPath(opt.cwd); + const done = (er, created) => { + if (er) + cb(er); + else { + cSet(cache, dir, true); + if (created && doChown) + chownr(created, uid, gid, (er2) => done(er2)); + else if (needChmod) + fs27.chmod(dir, mode, cb); + else + cb(); + } + }; + if (cache && cGet(cache, dir) === true) + return done(); + if (dir === cwd) + return checkCwd(dir, done); + if (preserve) + return mkdirp(dir, { mode }).then((made) => done(null, made), done); + const sub = normPath(path36.relative(cwd, dir)); + const parts = sub.split("/"); + mkdir_(cwd, parts, mode, cache, unlink, cwd, null, done); + }; + var mkdir_ = (base, parts, mode, cache, unlink, cwd, created, cb) => { + if (!parts.length) + return cb(null, created); + const p = parts.shift(); + const part = normPath(path36.resolve(base + "/" + p)); + if (cGet(cache, part)) + return mkdir_(part, parts, mode, cache, unlink, cwd, created, cb); + fs27.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)); + }; + var onmkdir = (part, parts, mode, cache, unlink, cwd, created, cb) => (er) => { + if (er) { + fs27.lstat(part, (statEr, st) => { + if (statEr) { + statEr.path = statEr.path && normPath(statEr.path); + cb(statEr); + } else if (st.isDirectory()) + mkdir_(part, parts, mode, cache, unlink, cwd, created, cb); + else if (unlink) { + fs27.unlink(part, (er2) => { + if (er2) + return cb(er2); + fs27.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); + } + }; + var checkCwdSync = (dir) => { + let ok = false; + let code = "ENOTDIR"; + try { + ok = fs27.statSync(dir).isDirectory(); + } catch (er) { + code = er.code; + } finally { + if (!ok) + throw new CwdError(dir, code); + } + }; + module2.exports.sync = (dir, opt) => { + dir = normPath(dir); + const umask = opt.umask; + const mode = opt.mode | 448; + 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 = normPath(opt.cwd); + const done = (created2) => { + cSet(cache, dir, true); + if (created2 && doChown) + chownr.sync(created2, uid, gid); + if (needChmod) + fs27.chmodSync(dir, mode); + }; + if (cache && cGet(cache, dir) === true) + return done(); + if (dir === cwd) { + checkCwdSync(cwd); + return done(); + } + if (preserve) + return done(mkdirp.sync(dir, mode)); + const sub = normPath(path36.relative(cwd, dir)); + const parts = sub.split("/"); + let created = null; + for (let p = parts.shift(), part = cwd; p && (part += "/" + p); p = parts.shift()) { + part = normPath(path36.resolve(part)); + if (cGet(cache, part)) + continue; + try { + fs27.mkdirSync(part, mode); + created = created || part; + cSet(cache, part, true); + } catch (er) { + const st = fs27.lstatSync(part); + if (st.isDirectory()) { + cSet(cache, part, true); + continue; + } else if (unlink) { + fs27.unlinkSync(part); + fs27.mkdirSync(part, mode); + created = created || part; + cSet(cache, part, true); + continue; + } else if (st.isSymbolicLink()) + return new SymlinkError(part, part + "/" + parts.join("/")); + } + } + return done(created); + }; + } +}); + +// node_modules/tar/lib/normalize-unicode.js +var require_normalize_unicode = __commonJS({ + "node_modules/tar/lib/normalize-unicode.js"(exports2, module2) { + var normalizeCache = Object.create(null); + var { hasOwnProperty: hasOwnProperty3 } = Object.prototype; + module2.exports = (s) => { + if (!hasOwnProperty3.call(normalizeCache, s)) + normalizeCache[s] = s.normalize("NFKD"); + return normalizeCache[s]; + }; + } +}); + +// node_modules/tar/lib/path-reservations.js +var require_path_reservations = __commonJS({ + "node_modules/tar/lib/path-reservations.js"(exports2, module2) { + var assert = require("assert"); + var normalize = require_normalize_unicode(); + var stripSlashes = require_strip_trailing_slashes(); + var { join: join2 } = require("path"); + var platform3 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform; + var isWindows4 = platform3 === "win32"; + module2.exports = () => { + const queues = new Map(); + const reservations = new Map(); + const getDirs = (path36) => { + const dirs = path36.split("/").slice(0, -1).reduce((set, path37) => { + if (set.length) + path37 = join2(set[set.length - 1], path37); + set.push(path37 || "/"); + return set; + }, []); + return dirs; + }; + const running = new Set(); + const getQueues = (fn) => { + const res = reservations.get(fn); + if (!res) + throw new Error("function does not have any path reservations"); + return { + paths: res.paths.map((path36) => queues.get(path36)), + dirs: [...res.dirs].map((path36) => queues.get(path36)) + }; + }; + const check = (fn) => { + const { paths, dirs } = getQueues(fn); + return paths.every((q) => q[0] === fn) && dirs.every((q) => q[0] instanceof Set && q[0].has(fn)); + }; + const run = (fn) => { + if (running.has(fn) || !check(fn)) + return false; + running.add(fn); + fn(() => clear(fn)); + return true; + }; + const clear = (fn) => { + if (!running.has(fn)) + return false; + const { paths, dirs } = reservations.get(fn); + const next = new Set(); + paths.forEach((path36) => { + const q = queues.get(path36); + assert.equal(q[0], fn); + if (q.length === 1) + queues.delete(path36); + else { + q.shift(); + if (typeof q[0] === "function") + next.add(q[0]); + else + q[0].forEach((fn2) => next.add(fn2)); + } + }); + dirs.forEach((dir) => { + const q = queues.get(dir); + assert(q[0] instanceof Set); + if (q[0].size === 1 && q.length === 1) + queues.delete(dir); + else if (q[0].size === 1) { + q.shift(); + next.add(q[0]); + } else + q[0].delete(fn); + }); + running.delete(fn); + next.forEach((fn2) => run(fn2)); + return true; + }; + const reserve = (paths, fn) => { + paths = isWindows4 ? ["win32 parallelization disabled"] : paths.map((p) => { + return normalize(stripSlashes(join2(p))).toLowerCase(); + }); + const dirs = new Set(paths.map((path36) => getDirs(path36)).reduce((a, b) => a.concat(b))); + reservations.set(fn, { dirs, paths }); + paths.forEach((path36) => { + const q = queues.get(path36); + if (!q) + queues.set(path36, [fn]); + else + q.push(fn); + }); + dirs.forEach((dir) => { + const q = queues.get(dir); + if (!q) + queues.set(dir, [new Set([fn])]); + else if (q[q.length - 1] instanceof Set) + q[q.length - 1].add(fn); + else + q.push(new Set([fn])); + }); + return run(fn); + }; + return { check, reserve }; + }; + } +}); + +// node_modules/tar/lib/get-write-flag.js +var require_get_write_flag = __commonJS({ + "node_modules/tar/lib/get-write-flag.js"(exports2, module2) { + var platform3 = process.env.__FAKE_PLATFORM__ || process.platform; + var isWindows4 = platform3 === "win32"; + var fs27 = global.__FAKE_TESTING_FS__ || require("fs"); + var { O_CREAT, O_TRUNC, O_WRONLY, UV_FS_O_FILEMAP = 0 } = fs27.constants; + var fMapEnabled = isWindows4 && !!UV_FS_O_FILEMAP; + var fMapLimit = 512 * 1024; + var fMapFlag = UV_FS_O_FILEMAP | O_TRUNC | O_CREAT | O_WRONLY; + module2.exports = !fMapEnabled ? () => "w" : (size) => size < fMapLimit ? fMapFlag : "w"; + } +}); + +// node_modules/tar/lib/unpack.js +var require_unpack = __commonJS({ + "node_modules/tar/lib/unpack.js"(exports2, module2) { + "use strict"; + var assert = require("assert"); + var Parser = require_parse2(); + var fs27 = require("fs"); + var fsm = require_fs_minipass(); + var path36 = require("path"); + var mkdir = require_mkdir(); + var wc = require_winchars(); + var pathReservations = require_path_reservations(); + var stripAbsolutePath = require_strip_absolute_path(); + var normPath = require_normalize_windows_path(); + var stripSlash = require_strip_trailing_slashes(); + var normalize = require_normalize_unicode(); + var ONENTRY = Symbol("onEntry"); + var CHECKFS = Symbol("checkFs"); + var CHECKFS2 = Symbol("checkFs2"); + var PRUNECACHE = Symbol("pruneCache"); + var ISREUSABLE = Symbol("isReusable"); + var MAKEFS = Symbol("makeFs"); + var FILE = Symbol("file"); + var DIRECTORY = Symbol("directory"); + var LINK = Symbol("link"); + var SYMLINK = Symbol("symlink"); + var HARDLINK = Symbol("hardlink"); + var UNSUPPORTED = Symbol("unsupported"); + var CHECKPATH = Symbol("checkPath"); + var MKDIR = Symbol("mkdir"); + var ONERROR = Symbol("onError"); + var PENDING = Symbol("pending"); + var PEND = Symbol("pend"); + var UNPEND = Symbol("unpend"); + var ENDED = Symbol("ended"); + var MAYBECLOSE = Symbol("maybeClose"); + var SKIP = Symbol("skip"); + var DOCHOWN = Symbol("doChown"); + var UID = Symbol("uid"); + var GID = Symbol("gid"); + var CHECKED_CWD = Symbol("checkedCwd"); + var crypto2 = require("crypto"); + var getFlag = require_get_write_flag(); + var platform3 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform; + var isWindows4 = platform3 === "win32"; + var unlinkFile = (path37, cb) => { + if (!isWindows4) + return fs27.unlink(path37, cb); + const name2 = path37 + ".DELETE." + crypto2.randomBytes(16).toString("hex"); + fs27.rename(path37, name2, (er) => { + if (er) + return cb(er); + fs27.unlink(name2, cb); + }); + }; + var unlinkFileSync = (path37) => { + if (!isWindows4) + return fs27.unlinkSync(path37); + const name2 = path37 + ".DELETE." + crypto2.randomBytes(16).toString("hex"); + fs27.renameSync(path37, name2); + fs27.unlinkSync(name2); + }; + var uint32 = (a, b, c) => a === a >>> 0 ? a : b === b >>> 0 ? b : c; + var cacheKeyNormalize = (path37) => normalize(stripSlash(normPath(path37))).toLowerCase(); + var pruneCache = (cache, abs) => { + abs = cacheKeyNormalize(abs); + for (const path37 of cache.keys()) { + const pnorm = cacheKeyNormalize(path37); + if (pnorm === abs || pnorm.indexOf(abs + "/") === 0) + cache.delete(path37); + } + }; + var dropCache = (cache) => { + for (const key of cache.keys()) + cache.delete(key); + }; + var Unpack = class extends Parser { + constructor(opt) { + if (!opt) + opt = {}; + opt.ondone = (_) => { + this[ENDED] = true; + this[MAYBECLOSE](); + }; + super(opt); + this[CHECKED_CWD] = false; + this.reservations = pathReservations(); + 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") { + 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; + } + if (opt.preserveOwner === void 0 && 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; + this.forceChown = opt.forceChown === true; + this.win32 = !!opt.win32 || isWindows4; + this.newer = !!opt.newer; + this.keep = !!opt.keep; + this.noMtime = !!opt.noMtime; + this.preservePaths = !!opt.preservePaths; + this.unlink = !!opt.unlink; + this.cwd = normPath(path36.resolve(opt.cwd || process.cwd())); + this.strip = +opt.strip || 0; + this.processUmask = opt.noChmod ? 0 : process.umask(); + this.umask = typeof opt.umask === "number" ? opt.umask : this.processUmask; + this.dmode = opt.dmode || 511 & ~this.umask; + this.fmode = opt.fmode || 438 & ~this.umask; + this.on("entry", (entry) => this[ONENTRY](entry)); + } + warn(code, msg, data = {}) { + if (code === "TAR_BAD_ARCHIVE" || code === "TAR_ABORT") + data.recoverable = false; + return super.warn(code, msg, data); + } + [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 = normPath(entry.path).split("/"); + if (parts.length < this.strip) + return false; + entry.path = parts.slice(this.strip).join("/"); + if (entry.type === "Link") { + const linkparts = normPath(entry.linkpath).split("/"); + if (linkparts.length >= this.strip) + entry.linkpath = linkparts.slice(this.strip).join("/"); + else + return false; + } + } + if (!this.preservePaths) { + const p = normPath(entry.path); + const parts = p.split("/"); + if (parts.includes("..") || isWindows4 && /^[a-z]:\.\.$/i.test(parts[0])) { + this.warn("TAR_ENTRY_ERROR", `path contains '..'`, { + entry, + path: p + }); + return false; + } + const [root, stripped] = stripAbsolutePath(p); + if (root) { + entry.path = stripped; + this.warn("TAR_ENTRY_INFO", `stripping ${root} from absolute path`, { + entry, + path: p + }); + } + } + if (path36.isAbsolute(entry.path)) + entry.absolute = normPath(path36.resolve(entry.path)); + else + entry.absolute = normPath(path36.resolve(this.cwd, entry.path)); + if (!this.preservePaths && entry.absolute.indexOf(this.cwd + "/") !== 0 && entry.absolute !== this.cwd) { + this.warn("TAR_ENTRY_ERROR", "path escaped extraction target", { + entry, + path: normPath(entry.path), + resolvedPath: entry.absolute, + cwd: this.cwd + }); + return false; + } + if (entry.absolute === this.cwd && entry.type !== "Directory" && entry.type !== "GNUDumpDir") + return false; + if (this.win32) { + const { root: aRoot } = path36.win32.parse(entry.absolute); + entry.absolute = aRoot + wc.encode(entry.absolute.substr(aRoot.length)); + const { root: pRoot } = path36.win32.parse(entry.path); + entry.path = pRoot + wc.encode(entry.path.substr(pRoot.length)); + } + 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 | 448; + case "File": + case "OldFile": + case "ContiguousFile": + case "Link": + case "SymbolicLink": + return this[CHECKFS](entry); + case "CharacterDevice": + case "BlockDevice": + case "FIFO": + default: + return this[UNSUPPORTED](entry); + } + } + [ONERROR](er, entry) { + if (er.name === "CwdError") + this.emit("error", er); + else { + this.warn("TAR_ENTRY_ERROR", er, { entry }); + this[UNPEND](); + entry.resume(); + } + } + [MKDIR](dir, mode, cb) { + mkdir(normPath(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, + noChmod: this.noChmod + }, cb); + } + [DOCHOWN](entry) { + 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, fullyDone) { + const mode = entry.mode & 4095 || this.fmode; + const stream = new fsm.WriteStream(entry.absolute, { + flags: getFlag(entry.size), + mode, + autoClose: false + }); + stream.on("error", (er) => { + if (stream.fd) + fs27.close(stream.fd, () => { + }); + stream.write = () => true; + this[ONERROR](er, entry); + fullyDone(); + }); + let actions = 1; + const done = (er) => { + if (er) { + if (stream.fd) + fs27.close(stream.fd, () => { + }); + this[ONERROR](er, entry); + fullyDone(); + return; + } + if (--actions === 0) { + fs27.close(stream.fd, (er2) => { + if (er2) + this[ONERROR](er2, entry); + else + this[UNPEND](); + fullyDone(); + }); + } + }; + stream.on("finish", (_) => { + const abs = entry.absolute; + const fd = stream.fd; + if (entry.mtime && !this.noMtime) { + actions++; + const atime = entry.atime || new Date(); + const mtime = entry.mtime; + fs27.futimes(fd, atime, mtime, (er) => er ? fs27.utimes(abs, atime, mtime, (er2) => done(er2 && er)) : done()); + } + if (this[DOCHOWN](entry)) { + actions++; + const uid = this[UID](entry); + const gid = this[GID](entry); + fs27.fchown(fd, uid, gid, (er) => er ? fs27.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); + fullyDone(); + }); + entry.pipe(tx); + } + tx.pipe(stream); + } + [DIRECTORY](entry, fullyDone) { + const mode = entry.mode & 4095 || this.dmode; + this[MKDIR](entry.absolute, mode, (er) => { + if (er) { + this[ONERROR](er, entry); + fullyDone(); + return; + } + let actions = 1; + const done = (_) => { + if (--actions === 0) { + fullyDone(); + this[UNPEND](); + entry.resume(); + } + }; + if (entry.mtime && !this.noMtime) { + actions++; + fs27.utimes(entry.absolute, entry.atime || new Date(), entry.mtime, done); + } + if (this[DOCHOWN](entry)) { + actions++; + fs27.chown(entry.absolute, this[UID](entry), this[GID](entry), done); + } + done(); + }); + } + [UNSUPPORTED](entry) { + entry.unsupported = true; + this.warn("TAR_ENTRY_UNSUPPORTED", `unsupported entry type: ${entry.type}`, { entry }); + entry.resume(); + } + [SYMLINK](entry, done) { + this[LINK](entry, entry.linkpath, "symlink", done); + } + [HARDLINK](entry, done) { + const linkpath = normPath(path36.resolve(this.cwd, entry.linkpath)); + this[LINK](entry, linkpath, "link", done); + } + [PEND]() { + this[PENDING]++; + } + [UNPEND]() { + this[PENDING]--; + this[MAYBECLOSE](); + } + [SKIP](entry) { + this[UNPEND](); + entry.resume(); + } + [ISREUSABLE](entry, st) { + return entry.type === "File" && !this.unlink && st.isFile() && st.nlink <= 1 && !isWindows4; + } + [CHECKFS](entry) { + this[PEND](); + const paths = [entry.path]; + if (entry.linkpath) + paths.push(entry.linkpath); + this.reservations.reserve(paths, (done) => this[CHECKFS2](entry, done)); + } + [PRUNECACHE](entry) { + if (entry.type === "SymbolicLink") + dropCache(this.dirCache); + else if (entry.type !== "Directory") + pruneCache(this.dirCache, entry.absolute); + } + [CHECKFS2](entry, fullyDone) { + this[PRUNECACHE](entry); + const done = (er) => { + this[PRUNECACHE](entry); + fullyDone(er); + }; + const checkCwd = () => { + this[MKDIR](this.cwd, this.dmode, (er) => { + if (er) { + this[ONERROR](er, entry); + done(); + return; + } + this[CHECKED_CWD] = true; + start(); + }); + }; + const start = () => { + if (entry.absolute !== this.cwd) { + const parent = normPath(path36.dirname(entry.absolute)); + if (parent !== this.cwd) { + return this[MKDIR](parent, this.dmode, (er) => { + if (er) { + this[ONERROR](er, entry); + done(); + return; + } + afterMakeParent(); + }); + } + } + afterMakeParent(); + }; + const afterMakeParent = () => { + fs27.lstat(entry.absolute, (lstatEr, st) => { + if (st && (this.keep || this.newer && st.mtime > entry.mtime)) { + this[SKIP](entry); + done(); + return; + } + if (lstatEr || this[ISREUSABLE](entry, st)) + return this[MAKEFS](null, entry, done); + if (st.isDirectory()) { + if (entry.type === "Directory") { + const needChmod = !this.noChmod && entry.mode && (st.mode & 4095) !== entry.mode; + const afterChmod = (er) => this[MAKEFS](er, entry, done); + if (!needChmod) + return afterChmod(); + return fs27.chmod(entry.absolute, entry.mode, afterChmod); + } + if (entry.absolute !== this.cwd) { + return fs27.rmdir(entry.absolute, (er) => this[MAKEFS](er, entry, done)); + } + } + if (entry.absolute === this.cwd) + return this[MAKEFS](null, entry, done); + unlinkFile(entry.absolute, (er) => this[MAKEFS](er, entry, done)); + }); + }; + if (this[CHECKED_CWD]) + start(); + else + checkCwd(); + } + [MAKEFS](er, entry, done) { + if (er) { + this[ONERROR](er, entry); + done(); + return; + } + switch (entry.type) { + case "File": + case "OldFile": + case "ContiguousFile": + return this[FILE](entry, done); + case "Link": + return this[HARDLINK](entry, done); + case "SymbolicLink": + return this[SYMLINK](entry, done); + case "Directory": + case "GNUDumpDir": + return this[DIRECTORY](entry, done); + } + } + [LINK](entry, linkpath, link, done) { + fs27[link](linkpath, entry.absolute, (er) => { + if (er) + this[ONERROR](er, entry); + else { + this[UNPEND](); + entry.resume(); + } + done(); + }); + } + }; + var callSync = (fn) => { + try { + return [null, fn()]; + } catch (er) { + return [er, null]; + } + }; + var UnpackSync = class extends Unpack { + [MAKEFS](er, entry) { + return super[MAKEFS](er, entry, () => { + }); + } + [CHECKFS](entry) { + this[PRUNECACHE](entry); + if (!this[CHECKED_CWD]) { + const er2 = this[MKDIR](this.cwd, this.dmode); + if (er2) + return this[ONERROR](er2, entry); + this[CHECKED_CWD] = true; + } + if (entry.absolute !== this.cwd) { + const parent = normPath(path36.dirname(entry.absolute)); + if (parent !== this.cwd) { + const mkParent = this[MKDIR](parent, this.dmode); + if (mkParent) + return this[ONERROR](mkParent, entry); + } + } + const [lstatEr, st] = callSync(() => fs27.lstatSync(entry.absolute)); + if (st && (this.keep || this.newer && st.mtime > entry.mtime)) + return this[SKIP](entry); + if (lstatEr || this[ISREUSABLE](entry, st)) + return this[MAKEFS](null, entry); + if (st.isDirectory()) { + if (entry.type === "Directory") { + const needChmod = !this.noChmod && entry.mode && (st.mode & 4095) !== entry.mode; + const [er3] = needChmod ? callSync(() => { + fs27.chmodSync(entry.absolute, entry.mode); + }) : []; + return this[MAKEFS](er3, entry); + } + const [er2] = callSync(() => fs27.rmdirSync(entry.absolute)); + this[MAKEFS](er2, entry); + } + const [er] = entry.absolute === this.cwd ? [] : callSync(() => unlinkFileSync(entry.absolute)); + this[MAKEFS](er, entry); + } + [FILE](entry, done) { + const mode = entry.mode & 4095 || this.fmode; + const oner = (er) => { + let closeError; + try { + fs27.closeSync(fd); + } catch (e) { + closeError = e; + } + if (er || closeError) + this[ONERROR](er || closeError, entry); + done(); + }; + let fd; + try { + fd = fs27.openSync(entry.absolute, getFlag(entry.size), 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 { + fs27.writeSync(fd, chunk, 0, chunk.length); + } catch (er) { + oner(er); + } + }); + tx.on("end", (_) => { + let er = null; + if (entry.mtime && !this.noMtime) { + const atime = entry.atime || new Date(); + const mtime = entry.mtime; + try { + fs27.futimesSync(fd, atime, mtime); + } catch (futimeser) { + try { + fs27.utimesSync(entry.absolute, atime, mtime); + } catch (utimeser) { + er = futimeser; + } + } + } + if (this[DOCHOWN](entry)) { + const uid = this[UID](entry); + const gid = this[GID](entry); + try { + fs27.fchownSync(fd, uid, gid); + } catch (fchowner) { + try { + fs27.chownSync(entry.absolute, uid, gid); + } catch (chowner) { + er = er || fchowner; + } + } + } + oner(er); + }); + } + [DIRECTORY](entry, done) { + const mode = entry.mode & 4095 || this.dmode; + const er = this[MKDIR](entry.absolute, mode); + if (er) { + this[ONERROR](er, entry); + done(); + return; + } + if (entry.mtime && !this.noMtime) { + try { + fs27.utimesSync(entry.absolute, entry.atime || new Date(), entry.mtime); + } catch (er2) { + } + } + if (this[DOCHOWN](entry)) { + try { + fs27.chownSync(entry.absolute, this[UID](entry), this[GID](entry)); + } catch (er2) { + } + } + done(); + entry.resume(); + } + [MKDIR](dir, mode) { + try { + return mkdir.sync(normPath(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 + }); + } catch (er) { + return er; + } + } + [LINK](entry, linkpath, link, done) { + try { + fs27[link + "Sync"](linkpath, entry.absolute); + done(); + entry.resume(); + } catch (er) { + return this[ONERROR](er, entry); + } + } + }; + Unpack.Sync = UnpackSync; + module2.exports = Unpack; + } +}); + +// node_modules/tar/lib/extract.js +var require_extract = __commonJS({ + "node_modules/tar/lib/extract.js"(exports2, module2) { + "use strict"; + var hlo = require_high_level_opt(); + var Unpack = require_unpack(); + var fs27 = require("fs"); + var fsm = require_fs_minipass(); + var path36 = require("path"); + var stripSlash = require_strip_trailing_slashes(); + module2.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); + }; + var filesFilter = (opt, files) => { + const map = new Map(files.map((f) => [stripSlash(f), true])); + const filter = opt.filter; + const mapHas = (file, r) => { + const root = r || path36.parse(file).root || "."; + const ret = file === root ? false : map.has(file) ? map.get(file) : mapHas(path36.dirname(file), root); + map.set(file, ret); + return ret; + }; + opt.filter = filter ? (file, entry) => filter(file, entry) && mapHas(stripSlash(file)) : (file) => mapHas(stripSlash(file)); + }; + var extractFileSync = (opt) => { + const u = new Unpack.Sync(opt); + const file = opt.file; + const stat = fs27.statSync(file); + const readSize = opt.maxReadSize || 16 * 1024 * 1024; + const stream = new fsm.ReadStreamSync(file, { + readSize, + size: stat.size + }); + stream.pipe(u); + }; + var extractFile = (opt, cb) => { + const u = new Unpack(opt); + const readSize = opt.maxReadSize || 16 * 1024 * 1024; + const file = opt.file; + const p = new Promise((resolve3, reject) => { + u.on("error", reject); + u.on("close", resolve3); + fs27.stat(file, (er, stat) => { + if (er) + reject(er); + else { + const stream = new fsm.ReadStream(file, { + readSize, + size: stat.size + }); + stream.on("error", reject); + stream.pipe(u); + } + }); + }); + return cb ? p.then(cb, cb) : p; + }; + var extractSync = (opt) => new Unpack.Sync(opt); + var extract = (opt) => new Unpack(opt); + } +}); + +// node_modules/tar/index.js +var require_tar = __commonJS({ + "node_modules/tar/index.js"(exports2) { + "use strict"; + exports2.c = exports2.create = require_create(); + exports2.r = exports2.replace = require_replace(); + exports2.t = exports2.list = require_list(); + exports2.u = exports2.update = require_update(); + exports2.x = exports2.extract = require_extract(); + exports2.Pack = require_pack(); + exports2.Unpack = require_unpack(); + exports2.Parse = require_parse2(); + exports2.ReadEntry = require_read_entry(); + exports2.WriteEntry = require_write_entry(); + exports2.Header = require_header(); + exports2.Pax = require_pax(); + exports2.types = require_types2(); + } +}); + +// node_modules/traverse/index.js +var require_traverse = __commonJS({ + "node_modules/traverse/index.js"(exports2, module2) { + module2.exports = Traverse; + function Traverse(obj) { + if (!(this instanceof Traverse)) + return new Traverse(obj); + this.value = obj; + } + Traverse.prototype.get = function(ps) { + var node = this.value; + for (var i = 0; i < ps.length; i++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = void 0; + break; + } + node = node[key]; + } + return node; + }; + Traverse.prototype.set = function(ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) + node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; + }; + Traverse.prototype.map = function(cb) { + return walk2(this.value, cb, true); + }; + Traverse.prototype.forEach = function(cb) { + this.value = walk2(this.value, cb, false); + return this.value; + }; + Traverse.prototype.reduce = function(cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function(x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; + }; + Traverse.prototype.deepEqual = function(obj) { + if (arguments.length !== 1) { + throw new Error("deepEqual requires exactly one object to compare against"); + } + var equal = true; + var node = obj; + this.forEach(function(y) { + var notEqual = function() { + equal = false; + return void 0; + }.bind(this); + if (!this.isRoot) { + if (typeof node !== "object") + return notEqual(); + node = node[this.key]; + } + var x = node; + this.post(function() { + node = x; + }); + var toS = function(o) { + return Object.prototype.toString.call(o); + }; + if (this.circular) { + if (Traverse(obj).get(this.circular.path) !== x) + notEqual(); + } else if (typeof x !== typeof y) { + notEqual(); + } else if (x === null || y === null || x === void 0 || y === void 0) { + if (x !== y) + notEqual(); + } else if (x.__proto__ !== y.__proto__) { + notEqual(); + } else if (x === y) { + } else if (typeof x === "function") { + if (x instanceof RegExp) { + if (x.toString() != y.toString()) + notEqual(); + } else if (x !== y) + notEqual(); + } else if (typeof x === "object") { + if (toS(y) === "[object Arguments]" || toS(x) === "[object Arguments]") { + if (toS(x) !== toS(y)) { + notEqual(); + } + } else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) || x.getTime() !== y.getTime()) { + notEqual(); + } + } else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) + return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + return equal; + }; + Traverse.prototype.paths = function() { + var acc = []; + this.forEach(function(x) { + acc.push(this.path); + }); + return acc; + }; + Traverse.prototype.nodes = function() { + var acc = []; + this.forEach(function(x) { + acc.push(this.node); + }); + return acc; + }; + Traverse.prototype.clone = function() { + var parents = [], nodes = []; + return function clone(src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + if (typeof src === "object" && src !== null) { + var dst = copy(src); + parents.push(src); + nodes.push(dst); + Object.keys(src).forEach(function(key) { + dst[key] = clone(src[key]); + }); + parents.pop(); + nodes.pop(); + return dst; + } else { + return src; + } + }(this.value); + }; + function walk2(root, cb, immutable) { + var path36 = []; + var parents = []; + var alive = true; + return function walker(node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + var state = { + node, + node_, + path: [].concat(path36), + parent: parents.slice(-1)[0], + key: path36.slice(-1)[0], + isRoot: path36.length === 0, + level: path36.length, + circular: null, + update: function(x) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + }, + "delete": function() { + delete state.parent.node[state.key]; + }, + remove: function() { + if (Array.isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } else { + delete state.parent.node[state.key]; + } + }, + before: function(f) { + modifiers.before = f; + }, + after: function(f) { + modifiers.after = f; + }, + pre: function(f) { + modifiers.pre = f; + }, + post: function(f) { + modifiers.post = f; + }, + stop: function() { + alive = false; + } + }; + if (!alive) + return state; + if (typeof node === "object" && node !== null) { + state.isLeaf = Object.keys(node).length == 0; + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } else { + state.isLeaf = true; + } + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + var ret = cb.call(state, state.node); + if (ret !== void 0 && state.update) + state.update(ret); + if (modifiers.before) + modifiers.before.call(state, state.node); + if (typeof state.node == "object" && state.node !== null && !state.circular) { + parents.push(state); + var keys = Object.keys(state.node); + keys.forEach(function(key, i2) { + path36.push(key); + if (modifiers.pre) + modifiers.pre.call(state, state.node[key], key); + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + child.isLast = i2 == keys.length - 1; + child.isFirst = i2 == 0; + if (modifiers.post) + modifiers.post.call(state, child); + path36.pop(); + }); + parents.pop(); + } + if (modifiers.after) + modifiers.after.call(state, state.node); + return state; + }(root).node; + } + Object.keys(Traverse.prototype).forEach(function(key) { + Traverse[key] = function(obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; + }); + function copy(src) { + if (typeof src === "object" && src !== null) { + var dst; + if (Array.isArray(src)) { + dst = []; + } else if (src instanceof Date) { + dst = new Date(src); + } else if (src instanceof Boolean) { + dst = new Boolean(src); + } else if (src instanceof Number) { + dst = new Number(src); + } else if (src instanceof String) { + dst = new String(src); + } else { + dst = Object.create(Object.getPrototypeOf(src)); + } + Object.keys(src).forEach(function(key) { + dst[key] = src[key]; + }); + return dst; + } else + return src; + } + } +}); + +// node_modules/chainsaw/index.js +var require_chainsaw = __commonJS({ + "node_modules/chainsaw/index.js"(exports2, module2) { + var Traverse = require_traverse(); + var EventEmitter8 = require("events").EventEmitter; + module2.exports = Chainsaw; + function Chainsaw(builder) { + var saw = Chainsaw.saw(builder, {}); + var r = builder.call(saw.handlers, saw); + if (r !== void 0) + saw.handlers = r; + saw.record(); + return saw.chain(); + } + Chainsaw.light = function ChainsawLight(builder) { + var saw = Chainsaw.saw(builder, {}); + var r = builder.call(saw.handlers, saw); + if (r !== void 0) + saw.handlers = r; + return saw.chain(); + }; + Chainsaw.saw = function(builder, handlers) { + var saw = new EventEmitter8(); + saw.handlers = handlers; + saw.actions = []; + saw.chain = function() { + var ch = Traverse(saw.handlers).map(function(node) { + if (this.isRoot) + return node; + var ps = this.path; + if (typeof node === "function") { + this.update(function() { + saw.actions.push({ + path: ps, + args: [].slice.call(arguments) + }); + return ch; + }); + } + }); + process.nextTick(function() { + saw.emit("begin"); + saw.next(); + }); + return ch; + }; + saw.pop = function() { + return saw.actions.shift(); + }; + saw.next = function() { + var action = saw.pop(); + if (!action) { + saw.emit("end"); + } else if (!action.trap) { + var node = saw.handlers; + action.path.forEach(function(key) { + node = node[key]; + }); + node.apply(saw.handlers, action.args); + } + }; + saw.nest = function(cb) { + var args = [].slice.call(arguments, 1); + var autonext = true; + if (typeof cb === "boolean") { + var autonext = cb; + cb = args.shift(); + } + var s = Chainsaw.saw(builder, {}); + var r = builder.call(s.handlers, s); + if (r !== void 0) + s.handlers = r; + if (typeof saw.step !== "undefined") { + s.record(); + } + cb.apply(s.chain(), args); + if (autonext !== false) + s.on("end", saw.next); + }; + saw.record = function() { + upgradeChainsaw(saw); + }; + ["trap", "down", "jump"].forEach(function(method) { + saw[method] = function() { + throw new Error("To use the trap, down and jump features, please call record() first to start recording actions."); + }; + }); + return saw; + }; + function upgradeChainsaw(saw) { + saw.step = 0; + saw.pop = function() { + return saw.actions[saw.step++]; + }; + saw.trap = function(name2, cb) { + var ps = Array.isArray(name2) ? name2 : [name2]; + saw.actions.push({ + path: ps, + step: saw.step, + cb, + trap: true + }); + }; + saw.down = function(name2) { + var ps = (Array.isArray(name2) ? name2 : [name2]).join("/"); + var i = saw.actions.slice(saw.step).map(function(x) { + if (x.trap && x.step <= saw.step) + return false; + return x.path.join("/") == ps; + }).indexOf(true); + if (i >= 0) + saw.step += i; + else + saw.step = saw.actions.length; + var act = saw.actions[saw.step - 1]; + if (act && act.trap) { + saw.step = act.step; + act.cb(); + } else + saw.next(); + }; + saw.jump = function(step) { + saw.step = step; + saw.next(); + }; + } + } +}); + +// node_modules/buffers/index.js +var require_buffers = __commonJS({ + "node_modules/buffers/index.js"(exports2, module2) { + module2.exports = Buffers; + function Buffers(bufs) { + if (!(this instanceof Buffers)) + return new Buffers(bufs); + this.buffers = bufs || []; + this.length = this.buffers.reduce(function(size, buf) { + return size + buf.length; + }, 0); + } + Buffers.prototype.push = function() { + for (var i = 0; i < arguments.length; i++) { + if (!Buffer.isBuffer(arguments[i])) { + throw new TypeError("Tried to push a non-buffer"); + } + } + for (var i = 0; i < arguments.length; i++) { + var buf = arguments[i]; + this.buffers.push(buf); + this.length += buf.length; + } + return this.length; + }; + Buffers.prototype.unshift = function() { + for (var i = 0; i < arguments.length; i++) { + if (!Buffer.isBuffer(arguments[i])) { + throw new TypeError("Tried to unshift a non-buffer"); + } + } + for (var i = 0; i < arguments.length; i++) { + var buf = arguments[i]; + this.buffers.unshift(buf); + this.length += buf.length; + } + return this.length; + }; + Buffers.prototype.copy = function(dst, dStart, start, end) { + return this.slice(start, end).copy(dst, dStart, 0, end - start); + }; + Buffers.prototype.splice = function(i, howMany) { + var buffers = this.buffers; + var index = i >= 0 ? i : this.length - i; + var reps = [].slice.call(arguments, 2); + if (howMany === void 0) { + howMany = this.length - index; + } else if (howMany > this.length - index) { + howMany = this.length - index; + } + for (var i = 0; i < reps.length; i++) { + this.length += reps[i].length; + } + var removed = new Buffers(); + var bytes2 = 0; + var startBytes = 0; + for (var ii = 0; ii < buffers.length && startBytes + buffers[ii].length < index; ii++) { + startBytes += buffers[ii].length; + } + if (index - startBytes > 0) { + var start = index - startBytes; + if (start + howMany < buffers[ii].length) { + removed.push(buffers[ii].slice(start, start + howMany)); + var orig = buffers[ii]; + var buf0 = new Buffer(start); + for (var i = 0; i < start; i++) { + buf0[i] = orig[i]; + } + var buf1 = new Buffer(orig.length - start - howMany); + for (var i = start + howMany; i < orig.length; i++) { + buf1[i - howMany - start] = orig[i]; + } + if (reps.length > 0) { + var reps_ = reps.slice(); + reps_.unshift(buf0); + reps_.push(buf1); + buffers.splice.apply(buffers, [ii, 1].concat(reps_)); + ii += reps_.length; + reps = []; + } else { + buffers.splice(ii, 1, buf0, buf1); + ii += 2; + } + } else { + removed.push(buffers[ii].slice(start)); + buffers[ii] = buffers[ii].slice(0, start); + ii++; + } + } + if (reps.length > 0) { + buffers.splice.apply(buffers, [ii, 0].concat(reps)); + ii += reps.length; + } + while (removed.length < howMany) { + var buf = buffers[ii]; + var len = buf.length; + var take = Math.min(len, howMany - removed.length); + if (take === len) { + removed.push(buf); + buffers.splice(ii, 1); + } else { + removed.push(buf.slice(0, take)); + buffers[ii] = buffers[ii].slice(take); + } + } + this.length -= removed.length; + return removed; + }; + Buffers.prototype.slice = function(i, j) { + var buffers = this.buffers; + if (j === void 0) + j = this.length; + if (i === void 0) + i = 0; + if (j > this.length) + j = this.length; + var startBytes = 0; + for (var si = 0; si < buffers.length && startBytes + buffers[si].length <= i; si++) { + startBytes += buffers[si].length; + } + var target = new Buffer(j - i); + var ti = 0; + for (var ii = si; ti < j - i && ii < buffers.length; ii++) { + var len = buffers[ii].length; + var start = ti === 0 ? i - startBytes : 0; + var end = ti + len >= j - i ? Math.min(start + (j - i) - ti, len) : len; + buffers[ii].copy(target, ti, start, end); + ti += end - start; + } + return target; + }; + Buffers.prototype.pos = function(i) { + if (i < 0 || i >= this.length) + throw new Error("oob"); + var l = i, bi = 0, bu = null; + for (; ; ) { + bu = this.buffers[bi]; + if (l < bu.length) { + return { buf: bi, offset: l }; + } else { + l -= bu.length; + } + bi++; + } + }; + Buffers.prototype.get = function get(i) { + var pos = this.pos(i); + return this.buffers[pos.buf].get(pos.offset); + }; + Buffers.prototype.set = function set(i, b) { + var pos = this.pos(i); + return this.buffers[pos.buf].set(pos.offset, b); + }; + Buffers.prototype.indexOf = function(needle, offset) { + if (typeof needle === "string") { + needle = new Buffer(needle); + } else if (needle instanceof Buffer) { + } else { + throw new Error("Invalid type for a search string"); + } + if (!needle.length) { + return 0; + } + if (!this.length) { + return -1; + } + var i = 0, j = 0, match = 0, mstart, pos = 0; + if (offset) { + var p = this.pos(offset); + i = p.buf; + j = p.offset; + pos = offset; + } + for (; ; ) { + while (j >= this.buffers[i].length) { + j = 0; + i++; + if (i >= this.buffers.length) { + return -1; + } + } + var char = this.buffers[i][j]; + if (char == needle[match]) { + if (match == 0) { + mstart = { + i, + j, + pos + }; + } + match++; + if (match == needle.length) { + return mstart.pos; + } + } else if (match != 0) { + i = mstart.i; + j = mstart.j; + pos = mstart.pos; + match = 0; + } + j++; + pos++; + } + }; + Buffers.prototype.toBuffer = function() { + return this.slice(); + }; + Buffers.prototype.toString = function(encoding, start, end) { + return this.slice(start, end).toString(encoding); + }; + } +}); + +// node_modules/binary/lib/vars.js +var require_vars = __commonJS({ + "node_modules/binary/lib/vars.js"(exports2, module2) { + module2.exports = function(store) { + function getset(name2, value) { + var node = vars.store; + var keys = name2.split("."); + keys.slice(0, -1).forEach(function(k) { + if (node[k] === void 0) + node[k] = {}; + node = node[k]; + }); + var key = keys[keys.length - 1]; + if (arguments.length == 1) { + return node[key]; + } else { + return node[key] = value; + } + } + var vars = { + get: function(name2) { + return getset(name2); + }, + set: function(name2, value) { + return getset(name2, value); + }, + store: store || {} + }; + return vars; + }; + } +}); + +// node_modules/binary/index.js +var require_binary = __commonJS({ + "node_modules/binary/index.js"(exports2, module2) { + var Chainsaw = require_chainsaw(); + var EventEmitter8 = require("events").EventEmitter; + var Buffers = require_buffers(); + var Vars = require_vars(); + var Stream = require("stream").Stream; + exports2 = module2.exports = function(bufOrEm, eventName) { + if (Buffer.isBuffer(bufOrEm)) { + return exports2.parse(bufOrEm); + } + var s = exports2.stream(); + if (bufOrEm && bufOrEm.pipe) { + bufOrEm.pipe(s); + } else if (bufOrEm) { + bufOrEm.on(eventName || "data", function(buf) { + s.write(buf); + }); + bufOrEm.on("end", function() { + s.end(); + }); + } + return s; + }; + exports2.stream = function(input) { + if (input) + return exports2.apply(null, arguments); + var pending = null; + function getBytes(bytes2, cb, skip) { + pending = { + bytes: bytes2, + skip, + cb: function(buf) { + pending = null; + cb(buf); + } + }; + dispatch(); + } + var offset = null; + function dispatch() { + if (!pending) { + if (caughtEnd) + done = true; + return; + } + if (typeof pending === "function") { + pending(); + } else { + var bytes2 = offset + pending.bytes; + if (buffers.length >= bytes2) { + var buf; + if (offset == null) { + buf = buffers.splice(0, bytes2); + if (!pending.skip) { + buf = buf.slice(); + } + } else { + if (!pending.skip) { + buf = buffers.slice(offset, bytes2); + } + offset = bytes2; + } + if (pending.skip) { + pending.cb(); + } else { + pending.cb(buf); + } + } + } + } + function builder(saw) { + function next() { + if (!done) + saw.next(); + } + var self2 = words(function(bytes2, cb) { + return function(name2) { + getBytes(bytes2, function(buf) { + vars.set(name2, cb(buf)); + next(); + }); + }; + }); + self2.tap = function(cb) { + saw.nest(cb, vars.store); + }; + self2.into = function(key, cb) { + if (!vars.get(key)) + vars.set(key, {}); + var parent = vars; + vars = Vars(parent.get(key)); + saw.nest(function() { + cb.apply(this, arguments); + this.tap(function() { + vars = parent; + }); + }, vars.store); + }; + self2.flush = function() { + vars.store = {}; + next(); + }; + self2.loop = function(cb) { + var end = false; + saw.nest(false, function loop() { + this.vars = vars.store; + cb.call(this, function() { + end = true; + next(); + }, vars.store); + this.tap(function() { + if (end) + saw.next(); + else + loop.call(this); + }.bind(this)); + }, vars.store); + }; + self2.buffer = function(name2, bytes2) { + if (typeof bytes2 === "string") { + bytes2 = vars.get(bytes2); + } + getBytes(bytes2, function(buf) { + vars.set(name2, buf); + next(); + }); + }; + self2.skip = function(bytes2) { + if (typeof bytes2 === "string") { + bytes2 = vars.get(bytes2); + } + getBytes(bytes2, function() { + next(); + }); + }; + self2.scan = function find(name2, search) { + if (typeof search === "string") { + search = new Buffer(search); + } else if (!Buffer.isBuffer(search)) { + throw new Error("search must be a Buffer or a string"); + } + var taken = 0; + pending = function() { + var pos = buffers.indexOf(search, offset + taken); + var i = pos - offset - taken; + if (pos !== -1) { + pending = null; + if (offset != null) { + vars.set(name2, buffers.slice(offset, offset + taken + i)); + offset += taken + i + search.length; + } else { + vars.set(name2, buffers.slice(0, taken + i)); + buffers.splice(0, taken + i + search.length); + } + next(); + dispatch(); + } else { + i = Math.max(buffers.length - search.length - offset - taken, 0); + } + taken += i; + }; + dispatch(); + }; + self2.peek = function(cb) { + offset = 0; + saw.nest(function() { + cb.call(this, vars.store); + this.tap(function() { + offset = null; + }); + }); + }; + return self2; + } + ; + var stream = Chainsaw.light(builder); + stream.writable = true; + var buffers = Buffers(); + stream.write = function(buf) { + buffers.push(buf); + dispatch(); + }; + var vars = Vars(); + var done = false, caughtEnd = false; + stream.end = function() { + caughtEnd = true; + }; + stream.pipe = Stream.prototype.pipe; + Object.getOwnPropertyNames(EventEmitter8.prototype).forEach(function(name2) { + stream[name2] = EventEmitter8.prototype[name2]; + }); + return stream; + }; + exports2.parse = function parse5(buffer) { + var self2 = words(function(bytes2, cb) { + return function(name2) { + if (offset + bytes2 <= buffer.length) { + var buf = buffer.slice(offset, offset + bytes2); + offset += bytes2; + vars.set(name2, cb(buf)); + } else { + vars.set(name2, null); + } + return self2; + }; + }); + var offset = 0; + var vars = Vars(); + self2.vars = vars.store; + self2.tap = function(cb) { + cb.call(self2, vars.store); + return self2; + }; + self2.into = function(key, cb) { + if (!vars.get(key)) { + vars.set(key, {}); + } + var parent = vars; + vars = Vars(parent.get(key)); + cb.call(self2, vars.store); + vars = parent; + return self2; + }; + self2.loop = function(cb) { + var end = false; + var ender = function() { + end = true; + }; + while (end === false) { + cb.call(self2, ender, vars.store); + } + return self2; + }; + self2.buffer = function(name2, size) { + if (typeof size === "string") { + size = vars.get(size); + } + var buf = buffer.slice(offset, Math.min(buffer.length, offset + size)); + offset += size; + vars.set(name2, buf); + return self2; + }; + self2.skip = function(bytes2) { + if (typeof bytes2 === "string") { + bytes2 = vars.get(bytes2); + } + offset += bytes2; + return self2; + }; + self2.scan = function(name2, search) { + if (typeof search === "string") { + search = new Buffer(search); + } else if (!Buffer.isBuffer(search)) { + throw new Error("search must be a Buffer or a string"); + } + vars.set(name2, null); + for (var i = 0; i + offset <= buffer.length - search.length + 1; i++) { + for (var j = 0; j < search.length && buffer[offset + i + j] === search[j]; j++) + ; + if (j === search.length) + break; + } + vars.set(name2, buffer.slice(offset, offset + i)); + offset += i + search.length; + return self2; + }; + self2.peek = function(cb) { + var was = offset; + cb.call(self2, vars.store); + offset = was; + return self2; + }; + self2.flush = function() { + vars.store = {}; + return self2; + }; + self2.eof = function() { + return offset >= buffer.length; + }; + return self2; + }; + function decodeLEu(bytes2) { + var acc = 0; + for (var i = 0; i < bytes2.length; i++) { + acc += Math.pow(256, i) * bytes2[i]; + } + return acc; + } + function decodeBEu(bytes2) { + var acc = 0; + for (var i = 0; i < bytes2.length; i++) { + acc += Math.pow(256, bytes2.length - i - 1) * bytes2[i]; + } + return acc; + } + function decodeBEs(bytes2) { + var val = decodeBEu(bytes2); + if ((bytes2[0] & 128) == 128) { + val -= Math.pow(256, bytes2.length); + } + return val; + } + function decodeLEs(bytes2) { + var val = decodeLEu(bytes2); + if ((bytes2[bytes2.length - 1] & 128) == 128) { + val -= Math.pow(256, bytes2.length); + } + return val; + } + function words(decode) { + var self2 = {}; + [1, 2, 4, 8].forEach(function(bytes2) { + var bits = bytes2 * 8; + self2["word" + bits + "le"] = self2["word" + bits + "lu"] = decode(bytes2, decodeLEu); + self2["word" + bits + "ls"] = decode(bytes2, decodeLEs); + self2["word" + bits + "be"] = self2["word" + bits + "bu"] = decode(bytes2, decodeBEu); + self2["word" + bits + "bs"] = decode(bytes2, decodeBEs); + }); + self2.word8 = self2.word8u = self2.word8be; + self2.word8s = self2.word8bs; + return self2; + } + } +}); + +// node_modules/unzip-stream/lib/matcher-stream.js +var require_matcher_stream = __commonJS({ + "node_modules/unzip-stream/lib/matcher-stream.js"(exports2, module2) { + var Transform2 = require("stream").Transform; + var util4 = require("util"); + function MatcherStream(patternDesc, matchFn) { + if (!(this instanceof MatcherStream)) { + return new MatcherStream(); + } + Transform2.call(this); + var p = typeof patternDesc === "object" ? patternDesc.pattern : patternDesc; + this.pattern = Buffer.isBuffer(p) ? p : Buffer.from(p); + this.requiredLength = this.pattern.length; + if (patternDesc.requiredExtraSize) + this.requiredLength += patternDesc.requiredExtraSize; + this.data = new Buffer(""); + this.bytesSoFar = 0; + this.matchFn = matchFn; + } + util4.inherits(MatcherStream, Transform2); + MatcherStream.prototype.checkDataChunk = function(ignoreMatchZero) { + var enoughData = this.data.length >= this.requiredLength; + if (!enoughData) { + return; + } + var matchIndex = this.data.indexOf(this.pattern, ignoreMatchZero ? 1 : 0); + if (matchIndex >= 0 && matchIndex + this.requiredLength > this.data.length) { + if (matchIndex > 0) { + var packet = this.data.slice(0, matchIndex); + this.push(packet); + this.bytesSoFar += matchIndex; + this.data = this.data.slice(matchIndex); + } + return; + } + if (matchIndex === -1) { + var packetLen = this.data.length - this.requiredLength + 1; + var packet = this.data.slice(0, packetLen); + this.push(packet); + this.bytesSoFar += packetLen; + this.data = this.data.slice(packetLen); + return; + } + if (matchIndex > 0) { + var packet = this.data.slice(0, matchIndex); + this.data = this.data.slice(matchIndex); + this.push(packet); + this.bytesSoFar += matchIndex; + } + var finished = this.matchFn ? this.matchFn(this.data, this.bytesSoFar) : true; + if (finished) { + this.data = new Buffer(""); + return; + } + return true; + }; + MatcherStream.prototype._transform = function(chunk, encoding, cb) { + this.data = Buffer.concat([this.data, chunk]); + var firstIteration = true; + while (this.checkDataChunk(!firstIteration)) { + firstIteration = false; + } + cb(); + }; + MatcherStream.prototype._flush = function(cb) { + if (this.data.length > 0) { + var firstIteration = true; + while (this.checkDataChunk(!firstIteration)) { + firstIteration = false; + } + } + if (this.data.length > 0) { + this.push(this.data); + this.data = null; + } + cb(); + }; + module2.exports = MatcherStream; + } +}); + +// node_modules/unzip-stream/lib/entry.js +var require_entry = __commonJS({ + "node_modules/unzip-stream/lib/entry.js"(exports2, module2) { + "use strict"; + var stream = require("stream"); + var inherits = require("util").inherits; + function Entry() { + if (!(this instanceof Entry)) { + return new Entry(); + } + stream.PassThrough.call(this); + this.path = null; + this.type = null; + this.isDirectory = false; + } + inherits(Entry, stream.PassThrough); + Entry.prototype.autodrain = function() { + return this.pipe(new stream.Transform({ transform: function(d, e, cb) { + cb(); + } })); + }; + module2.exports = Entry; + } +}); + +// node_modules/unzip-stream/lib/unzip-stream.js +var require_unzip_stream = __commonJS({ + "node_modules/unzip-stream/lib/unzip-stream.js"(exports2, module2) { + "use strict"; + var binary = require_binary(); + var stream = require("stream"); + var util4 = require("util"); + var zlib = require("zlib"); + var MatcherStream = require_matcher_stream(); + var Entry = require_entry(); + var states = { + STREAM_START: 0, + START: 1, + LOCAL_FILE_HEADER: 2, + LOCAL_FILE_HEADER_SUFFIX: 3, + FILE_DATA: 4, + FILE_DATA_END: 5, + DATA_DESCRIPTOR: 6, + CENTRAL_DIRECTORY_FILE_HEADER: 7, + CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX: 8, + CDIR64_END: 9, + CDIR64_END_DATA_SECTOR: 10, + CDIR64_LOCATOR: 11, + CENTRAL_DIRECTORY_END: 12, + CENTRAL_DIRECTORY_END_COMMENT: 13, + TRAILING_JUNK: 14, + ERROR: 99 + }; + var FOUR_GIGS = 4294967296; + var SIG_LOCAL_FILE_HEADER = 67324752; + var SIG_DATA_DESCRIPTOR = 134695760; + var SIG_CDIR_RECORD = 33639248; + var SIG_CDIR64_RECORD_END = 101075792; + var SIG_CDIR64_LOCATOR_END = 117853008; + var SIG_CDIR_RECORD_END = 101010256; + function UnzipStream(options) { + if (!(this instanceof UnzipStream)) { + return new UnzipStream(options); + } + stream.Transform.call(this); + this.options = options || {}; + this.data = new Buffer(""); + this.state = states.STREAM_START; + this.skippedBytes = 0; + this.parsedEntity = null; + this.outStreamInfo = {}; + } + util4.inherits(UnzipStream, stream.Transform); + UnzipStream.prototype.processDataChunk = function(chunk) { + var requiredLength; + switch (this.state) { + case states.STREAM_START: + case states.START: + requiredLength = 4; + break; + case states.LOCAL_FILE_HEADER: + requiredLength = 26; + break; + case states.LOCAL_FILE_HEADER_SUFFIX: + requiredLength = this.parsedEntity.fileNameLength + this.parsedEntity.extraFieldLength; + break; + case states.DATA_DESCRIPTOR: + requiredLength = 12; + break; + case states.CENTRAL_DIRECTORY_FILE_HEADER: + requiredLength = 42; + break; + case states.CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX: + requiredLength = this.parsedEntity.fileNameLength + this.parsedEntity.extraFieldLength + this.parsedEntity.fileCommentLength; + break; + case states.CDIR64_END: + requiredLength = 52; + break; + case states.CDIR64_END_DATA_SECTOR: + requiredLength = this.parsedEntity.centralDirectoryRecordSize - 44; + break; + case states.CDIR64_LOCATOR: + requiredLength = 16; + break; + case states.CENTRAL_DIRECTORY_END: + requiredLength = 18; + break; + case states.CENTRAL_DIRECTORY_END_COMMENT: + requiredLength = this.parsedEntity.commentLength; + break; + case states.FILE_DATA: + return 0; + case states.FILE_DATA_END: + return 0; + case states.TRAILING_JUNK: + if (this.options.debug) + console.log("found", chunk.length, "bytes of TRAILING_JUNK"); + return chunk.length; + default: + return chunk.length; + } + var chunkLength = chunk.length; + if (chunkLength < requiredLength) { + return 0; + } + switch (this.state) { + case states.STREAM_START: + case states.START: + var signature = chunk.readUInt32LE(0); + switch (signature) { + case SIG_LOCAL_FILE_HEADER: + this.state = states.LOCAL_FILE_HEADER; + break; + case SIG_CDIR_RECORD: + this.state = states.CENTRAL_DIRECTORY_FILE_HEADER; + break; + case SIG_CDIR64_RECORD_END: + this.state = states.CDIR64_END; + break; + case SIG_CDIR64_LOCATOR_END: + this.state = states.CDIR64_LOCATOR; + break; + case SIG_CDIR_RECORD_END: + this.state = states.CENTRAL_DIRECTORY_END; + break; + default: + var isStreamStart = this.state === states.STREAM_START; + if (!isStreamStart && (signature & 65535) !== 19280 && this.skippedBytes < 26) { + var remaining = signature; + var toSkip = 4; + for (var i = 1; i < 4 && remaining !== 0; i++) { + remaining = remaining >>> 8; + if ((remaining & 255) === 80) { + toSkip = i; + break; + } + } + this.skippedBytes += toSkip; + if (this.options.debug) + console.log("Skipped", this.skippedBytes, "bytes"); + return toSkip; + } + this.state = states.ERROR; + var errMsg = isStreamStart ? "Not a valid zip file" : "Invalid signature in zip file"; + if (this.options.debug) { + var sig = chunk.readUInt32LE(0); + var asString; + try { + asString = chunk.slice(0, 4).toString(); + } catch (e) { + } + console.log("Unexpected signature in zip file: 0x" + sig.toString(16), '"' + asString + '", skipped', this.skippedBytes, "bytes"); + } + this.emit("error", new Error(errMsg)); + return chunk.length; + } + this.skippedBytes = 0; + return requiredLength; + case states.LOCAL_FILE_HEADER: + this.parsedEntity = this._readFile(chunk); + this.state = states.LOCAL_FILE_HEADER_SUFFIX; + return requiredLength; + case states.LOCAL_FILE_HEADER_SUFFIX: + var entry = new Entry(); + var isUtf8 = (this.parsedEntity.flags & 2048) !== 0; + entry.path = this._decodeString(chunk.slice(0, this.parsedEntity.fileNameLength), isUtf8); + var extraDataBuffer = chunk.slice(this.parsedEntity.fileNameLength, this.parsedEntity.fileNameLength + this.parsedEntity.extraFieldLength); + var extra = this._readExtraFields(extraDataBuffer); + if (extra && extra.parsed) { + if (extra.parsed.path && !isUtf8) { + entry.path = extra.parsed.path; + } + if (Number.isFinite(extra.parsed.uncompressedSize) && this.parsedEntity.uncompressedSize === FOUR_GIGS - 1) { + this.parsedEntity.uncompressedSize = extra.parsed.uncompressedSize; + } + if (Number.isFinite(extra.parsed.compressedSize) && this.parsedEntity.compressedSize === FOUR_GIGS - 1) { + this.parsedEntity.compressedSize = extra.parsed.compressedSize; + } + } + this.parsedEntity.extra = extra.parsed || {}; + if (this.options.debug) { + const debugObj = Object.assign({}, this.parsedEntity, { + path: entry.path, + flags: "0x" + this.parsedEntity.flags.toString(16), + extraFields: extra && extra.debug + }); + console.log("decoded LOCAL_FILE_HEADER:", JSON.stringify(debugObj, null, 2)); + } + this._prepareOutStream(this.parsedEntity, entry); + this.emit("entry", entry); + this.state = states.FILE_DATA; + return requiredLength; + case states.CENTRAL_DIRECTORY_FILE_HEADER: + this.parsedEntity = this._readCentralDirectoryEntry(chunk); + this.state = states.CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX; + return requiredLength; + case states.CENTRAL_DIRECTORY_FILE_HEADER_SUFFIX: + var isUtf8 = (this.parsedEntity.flags & 2048) !== 0; + var path36 = this._decodeString(chunk.slice(0, this.parsedEntity.fileNameLength), isUtf8); + var extraDataBuffer = chunk.slice(this.parsedEntity.fileNameLength, this.parsedEntity.fileNameLength + this.parsedEntity.extraFieldLength); + var extra = this._readExtraFields(extraDataBuffer); + if (extra && extra.parsed && extra.parsed.path && !isUtf8) { + path36 = extra.parsed.path; + } + this.parsedEntity.extra = extra.parsed; + var isUnix = (this.parsedEntity.versionMadeBy & 65280) >> 8 === 3; + var unixAttrs, isSymlink; + if (isUnix) { + unixAttrs = this.parsedEntity.externalFileAttributes >>> 16; + var fileType = unixAttrs >>> 12; + isSymlink = (fileType & 10) === 10; + } + if (this.options.debug) { + const debugObj = Object.assign({}, this.parsedEntity, { + path: path36, + flags: "0x" + this.parsedEntity.flags.toString(16), + unixAttrs: unixAttrs && "0" + unixAttrs.toString(8), + isSymlink, + extraFields: extra.debug + }); + console.log("decoded CENTRAL_DIRECTORY_FILE_HEADER:", JSON.stringify(debugObj, null, 2)); + } + this.state = states.START; + return requiredLength; + case states.CDIR64_END: + this.parsedEntity = this._readEndOfCentralDirectory64(chunk); + if (this.options.debug) { + console.log("decoded CDIR64_END_RECORD:", this.parsedEntity); + } + this.state = states.CDIR64_END_DATA_SECTOR; + return requiredLength; + case states.CDIR64_END_DATA_SECTOR: + this.state = states.START; + return requiredLength; + case states.CDIR64_LOCATOR: + this.state = states.START; + return requiredLength; + case states.CENTRAL_DIRECTORY_END: + this.parsedEntity = this._readEndOfCentralDirectory(chunk); + if (this.options.debug) { + console.log("decoded CENTRAL_DIRECTORY_END:", this.parsedEntity); + } + this.state = states.CENTRAL_DIRECTORY_END_COMMENT; + return requiredLength; + case states.CENTRAL_DIRECTORY_END_COMMENT: + if (this.options.debug) { + console.log("decoded CENTRAL_DIRECTORY_END_COMMENT:", chunk.slice(0, requiredLength).toString()); + } + this.state = states.TRAILING_JUNK; + return requiredLength; + case states.ERROR: + return chunk.length; + default: + console.log("didn't handle state #", this.state, "discarding"); + return chunk.length; + } + }; + UnzipStream.prototype._prepareOutStream = function(vars, entry) { + var self2 = this; + var isDirectory = vars.uncompressedSize === 0 && /[\/\\]$/.test(entry.path); + entry.path = entry.path.replace(/^([/\\]*[.]+[/\\]+)*[/\\]*/, ""); + entry.type = isDirectory ? "Directory" : "File"; + entry.isDirectory = isDirectory; + var fileSizeKnown = !(vars.flags & 8); + if (fileSizeKnown) { + entry.size = vars.uncompressedSize; + } + var isVersionSupported = vars.versionsNeededToExtract <= 45; + this.outStreamInfo = { + stream: null, + limit: fileSizeKnown ? vars.compressedSize : -1, + written: 0 + }; + if (!fileSizeKnown) { + var pattern = new Buffer(4); + pattern.writeUInt32LE(SIG_DATA_DESCRIPTOR, 0); + var zip64Mode = vars.extra.zip64Mode; + var extraSize = zip64Mode ? 20 : 12; + var searchPattern = { + pattern, + requiredExtraSize: extraSize + }; + var matcherStream = new MatcherStream(searchPattern, function(matchedChunk, sizeSoFar) { + var vars2 = self2._readDataDescriptor(matchedChunk, zip64Mode); + var compressedSizeMatches = vars2.compressedSize === sizeSoFar; + if (!zip64Mode && !compressedSizeMatches && sizeSoFar >= FOUR_GIGS) { + var overflown = sizeSoFar - FOUR_GIGS; + while (overflown >= 0) { + compressedSizeMatches = vars2.compressedSize === overflown; + if (compressedSizeMatches) + break; + overflown -= FOUR_GIGS; + } + } + if (!compressedSizeMatches) { + return; + } + self2.state = states.FILE_DATA_END; + var sliceOffset = zip64Mode ? 24 : 16; + if (self2.data.length > 0) { + self2.data = Buffer.concat([matchedChunk.slice(sliceOffset), self2.data]); + } else { + self2.data = matchedChunk.slice(sliceOffset); + } + return true; + }); + this.outStreamInfo.stream = matcherStream; + } else { + this.outStreamInfo.stream = new stream.PassThrough(); + } + var isEncrypted = vars.flags & 1 || vars.flags & 64; + if (isEncrypted || !isVersionSupported) { + var message = isEncrypted ? "Encrypted files are not supported!" : "Zip version " + Math.floor(vars.versionsNeededToExtract / 10) + "." + vars.versionsNeededToExtract % 10 + " is not supported"; + entry.skip = true; + setImmediate(() => { + entry.emit("error", new Error(message)); + }); + this.outStreamInfo.stream.pipe(new Entry().autodrain()); + return; + } + var isCompressed = vars.compressionMethod > 0; + if (isCompressed) { + var inflater = zlib.createInflateRaw(); + inflater.on("error", function(err) { + self2.state = states.ERROR; + self2.emit("error", err); + }); + this.outStreamInfo.stream.pipe(inflater).pipe(entry); + } else { + this.outStreamInfo.stream.pipe(entry); + } + if (this._drainAllEntries) { + entry.autodrain(); + } + }; + UnzipStream.prototype._readFile = function(data) { + var vars = binary.parse(data).word16lu("versionsNeededToExtract").word16lu("flags").word16lu("compressionMethod").word16lu("lastModifiedTime").word16lu("lastModifiedDate").word32lu("crc32").word32lu("compressedSize").word32lu("uncompressedSize").word16lu("fileNameLength").word16lu("extraFieldLength").vars; + return vars; + }; + UnzipStream.prototype._readExtraFields = function(data) { + var extra = {}; + var result = { parsed: extra }; + if (this.options.debug) { + result.debug = []; + } + var index = 0; + while (index < data.length) { + var vars = binary.parse(data).skip(index).word16lu("extraId").word16lu("extraSize").vars; + index += 4; + var fieldType = void 0; + switch (vars.extraId) { + case 1: + fieldType = "Zip64 extended information extra field"; + var z64vars = binary.parse(data.slice(index, index + vars.extraSize)).word64lu("uncompressedSize").word64lu("compressedSize").word64lu("offsetToLocalHeader").word32lu("diskStartNumber").vars; + if (z64vars.uncompressedSize !== null) { + extra.uncompressedSize = z64vars.uncompressedSize; + } + if (z64vars.compressedSize !== null) { + extra.compressedSize = z64vars.compressedSize; + } + extra.zip64Mode = true; + break; + case 10: + fieldType = "NTFS extra field"; + break; + case 21589: + fieldType = "extended timestamp"; + var timestampFields = data.readUInt8(index); + var offset = 1; + if (vars.extraSize >= offset + 4 && timestampFields & 1) { + extra.mtime = new Date(data.readUInt32LE(index + offset) * 1e3); + offset += 4; + } + if (vars.extraSize >= offset + 4 && timestampFields & 2) { + extra.atime = new Date(data.readUInt32LE(index + offset) * 1e3); + offset += 4; + } + if (vars.extraSize >= offset + 4 && timestampFields & 4) { + extra.ctime = new Date(data.readUInt32LE(index + offset) * 1e3); + } + break; + case 28789: + fieldType = "Info-ZIP Unicode Path Extra Field"; + var fieldVer = data.readUInt8(index); + if (fieldVer === 1) { + var offset = 1; + var nameCrc32 = data.readUInt32LE(index + offset); + offset += 4; + var pathBuffer = data.slice(index + offset); + extra.path = pathBuffer.toString(); + } + break; + case 13: + case 22613: + fieldType = vars.extraId === 13 ? "PKWARE Unix" : "Info-ZIP UNIX (type 1)"; + var offset = 0; + if (vars.extraSize >= 8) { + var atime = new Date(data.readUInt32LE(index + offset) * 1e3); + offset += 4; + var mtime = new Date(data.readUInt32LE(index + offset) * 1e3); + offset += 4; + extra.atime = atime; + extra.mtime = mtime; + if (vars.extraSize >= 12) { + var uid = data.readUInt16LE(index + offset); + offset += 2; + var gid = data.readUInt16LE(index + offset); + offset += 2; + extra.uid = uid; + extra.gid = gid; + } + } + break; + case 30805: + fieldType = "Info-ZIP UNIX (type 2)"; + var offset = 0; + if (vars.extraSize >= 4) { + var uid = data.readUInt16LE(index + offset); + offset += 2; + var gid = data.readUInt16LE(index + offset); + offset += 2; + extra.uid = uid; + extra.gid = gid; + } + break; + case 30837: + fieldType = "Info-ZIP New Unix"; + var offset = 0; + var extraVer = data.readUInt8(index); + offset += 1; + if (extraVer === 1) { + var uidSize = data.readUInt8(index + offset); + offset += 1; + if (uidSize <= 6) { + extra.uid = data.readUIntLE(index + offset, uidSize); + } + offset += uidSize; + var gidSize = data.readUInt8(index + offset); + offset += 1; + if (gidSize <= 6) { + extra.gid = data.readUIntLE(index + offset, gidSize); + } + } + break; + case 30062: + fieldType = "ASi Unix"; + var offset = 0; + if (vars.extraSize >= 14) { + var crc = data.readUInt32LE(index + offset); + offset += 4; + var mode = data.readUInt16LE(index + offset); + offset += 2; + var sizdev = data.readUInt32LE(index + offset); + offset += 4; + var uid = data.readUInt16LE(index + offset); + offset += 2; + var gid = data.readUInt16LE(index + offset); + offset += 2; + extra.mode = mode; + extra.uid = uid; + extra.gid = gid; + if (vars.extraSize > 14) { + var start = index + offset; + var end = index + vars.extraSize - 14; + var symlinkName = this._decodeString(data.slice(start, end)); + extra.symlink = symlinkName; + } + } + break; + } + if (this.options.debug) { + result.debug.push({ + extraId: "0x" + vars.extraId.toString(16), + description: fieldType, + data: data.slice(index, index + vars.extraSize).inspect() + }); + } + index += vars.extraSize; + } + return result; + }; + UnzipStream.prototype._readDataDescriptor = function(data, zip64Mode) { + if (zip64Mode) { + var vars = binary.parse(data).word32lu("dataDescriptorSignature").word32lu("crc32").word64lu("compressedSize").word64lu("uncompressedSize").vars; + return vars; + } + var vars = binary.parse(data).word32lu("dataDescriptorSignature").word32lu("crc32").word32lu("compressedSize").word32lu("uncompressedSize").vars; + return vars; + }; + UnzipStream.prototype._readCentralDirectoryEntry = function(data) { + var vars = binary.parse(data).word16lu("versionMadeBy").word16lu("versionsNeededToExtract").word16lu("flags").word16lu("compressionMethod").word16lu("lastModifiedTime").word16lu("lastModifiedDate").word32lu("crc32").word32lu("compressedSize").word32lu("uncompressedSize").word16lu("fileNameLength").word16lu("extraFieldLength").word16lu("fileCommentLength").word16lu("diskNumber").word16lu("internalFileAttributes").word32lu("externalFileAttributes").word32lu("offsetToLocalFileHeader").vars; + return vars; + }; + UnzipStream.prototype._readEndOfCentralDirectory64 = function(data) { + var vars = binary.parse(data).word64lu("centralDirectoryRecordSize").word16lu("versionMadeBy").word16lu("versionsNeededToExtract").word32lu("diskNumber").word32lu("diskNumberWithCentralDirectoryStart").word64lu("centralDirectoryEntries").word64lu("totalCentralDirectoryEntries").word64lu("sizeOfCentralDirectory").word64lu("offsetToStartOfCentralDirectory").vars; + return vars; + }; + UnzipStream.prototype._readEndOfCentralDirectory = function(data) { + var vars = binary.parse(data).word16lu("diskNumber").word16lu("diskStart").word16lu("centralDirectoryEntries").word16lu("totalCentralDirectoryEntries").word32lu("sizeOfCentralDirectory").word32lu("offsetToStartOfCentralDirectory").word16lu("commentLength").vars; + return vars; + }; + var cp437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\xB6\xA7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0 "; + UnzipStream.prototype._decodeString = function(buffer, isUtf8) { + if (isUtf8) { + return buffer.toString("utf8"); + } + if (this.options.decodeString) { + return this.options.decodeString(buffer); + } + let result = ""; + for (var i = 0; i < buffer.length; i++) { + result += cp437[buffer[i]]; + } + return result; + }; + UnzipStream.prototype._parseOrOutput = function(encoding, cb) { + var consume; + while ((consume = this.processDataChunk(this.data)) > 0) { + this.data = this.data.slice(consume); + if (this.data.length === 0) + break; + } + if (this.state === states.FILE_DATA) { + if (this.outStreamInfo.limit >= 0) { + var remaining = this.outStreamInfo.limit - this.outStreamInfo.written; + var packet; + if (remaining < this.data.length) { + packet = this.data.slice(0, remaining); + this.data = this.data.slice(remaining); + } else { + packet = this.data; + this.data = new Buffer(""); + } + this.outStreamInfo.written += packet.length; + if (this.outStreamInfo.limit === this.outStreamInfo.written) { + this.state = states.START; + this.outStreamInfo.stream.end(packet, encoding, cb); + } else { + this.outStreamInfo.stream.write(packet, encoding, cb); + } + } else { + var packet = this.data; + this.data = new Buffer(""); + this.outStreamInfo.written += packet.length; + var outputStream = this.outStreamInfo.stream; + outputStream.write(packet, encoding, () => { + if (this.state === states.FILE_DATA_END) { + this.state = states.START; + return outputStream.end(cb); + } + cb(); + }); + } + return; + } + cb(); + }; + UnzipStream.prototype.drainAll = function() { + this._drainAllEntries = true; + }; + UnzipStream.prototype._transform = function(chunk, encoding, cb) { + var self2 = this; + if (self2.data.length > 0) { + self2.data = Buffer.concat([self2.data, chunk]); + } else { + self2.data = chunk; + } + var startDataLength = self2.data.length; + var done = function() { + if (self2.data.length > 0 && self2.data.length < startDataLength) { + startDataLength = self2.data.length; + self2._parseOrOutput(encoding, done); + return; + } + cb(); + }; + self2._parseOrOutput(encoding, done); + }; + UnzipStream.prototype._flush = function(cb) { + var self2 = this; + if (self2.data.length > 0) { + self2._parseOrOutput("buffer", function() { + if (self2.data.length > 0) + return setImmediate(function() { + self2._flush(cb); + }); + cb(); + }); + return; + } + if (self2.state === states.FILE_DATA) { + return cb(new Error("Stream finished in an invalid state, uncompression failed")); + } + setImmediate(cb); + }; + module2.exports = UnzipStream; + } +}); + +// node_modules/unzip-stream/lib/parser-stream.js +var require_parser_stream = __commonJS({ + "node_modules/unzip-stream/lib/parser-stream.js"(exports2, module2) { + var Transform2 = require("stream").Transform; + var util4 = require("util"); + var UnzipStream = require_unzip_stream(); + function ParserStream(opts) { + if (!(this instanceof ParserStream)) { + return new ParserStream(opts); + } + var transformOpts = opts || {}; + Transform2.call(this, { readableObjectMode: true }); + this.opts = opts || {}; + this.unzipStream = new UnzipStream(this.opts); + var self2 = this; + this.unzipStream.on("entry", function(entry) { + self2.push(entry); + }); + this.unzipStream.on("error", function(error) { + self2.emit("error", error); + }); + } + util4.inherits(ParserStream, Transform2); + ParserStream.prototype._transform = function(chunk, encoding, cb) { + this.unzipStream.write(chunk, encoding, cb); + }; + ParserStream.prototype._flush = function(cb) { + var self2 = this; + this.unzipStream.end(function() { + process.nextTick(function() { + self2.emit("close"); + }); + cb(); + }); + }; + ParserStream.prototype.on = function(eventName, fn) { + if (eventName === "entry") { + return Transform2.prototype.on.call(this, "data", fn); + } + return Transform2.prototype.on.call(this, eventName, fn); + }; + ParserStream.prototype.drainAll = function() { + this.unzipStream.drainAll(); + return this.pipe(new Transform2({ objectMode: true, transform: function(d, e, cb) { + cb(); + } })); + }; + module2.exports = ParserStream; + } +}); + +// node_modules/mkdirp/index.js +var require_mkdirp2 = __commonJS({ + "node_modules/mkdirp/index.js"(exports2, module2) { + var path36 = require("path"); + var fs27 = require("fs"); + var _0777 = parseInt("0777", 8); + module2.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 || fs27; + if (mode === void 0) { + mode = _0777; + } + if (!made) + made = null; + var cb = f || function() { + }; + p = path36.resolve(p); + xfs.mkdir(p, mode, function(er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case "ENOENT": + if (path36.dirname(p) === p) + return cb(er); + mkdirP(path36.dirname(p), opts, function(er2, made2) { + if (er2) + cb(er2, made2); + else + mkdirP(p, opts, cb, made2); + }); + break; + default: + xfs.stat(p, function(er2, stat) { + 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 || fs27; + if (mode === void 0) { + mode = _0777; + } + if (!made) + made = null; + p = path36.resolve(p); + try { + xfs.mkdirSync(p, mode); + made = made || p; + } catch (err0) { + switch (err0.code) { + case "ENOENT": + made = sync(path36.dirname(p), opts, made); + sync(p, opts, made); + break; + default: + var stat; + try { + stat = xfs.statSync(p); + } catch (err1) { + throw err0; + } + if (!stat.isDirectory()) + throw err0; + break; + } + } + return made; + }; + } +}); + +// node_modules/unzip-stream/lib/extract.js +var require_extract2 = __commonJS({ + "node_modules/unzip-stream/lib/extract.js"(exports2, module2) { + var fs27 = require("fs"); + var path36 = require("path"); + var util4 = require("util"); + var mkdirp = require_mkdirp2(); + var Transform2 = require("stream").Transform; + var UnzipStream = require_unzip_stream(); + function Extract(opts) { + if (!(this instanceof Extract)) + return new Extract(opts); + Transform2.call(this); + this.opts = opts || {}; + this.unzipStream = new UnzipStream(this.opts); + this.unfinishedEntries = 0; + this.afterFlushWait = false; + this.createdDirectories = {}; + var self2 = this; + this.unzipStream.on("entry", this._processEntry.bind(this)); + this.unzipStream.on("error", function(error) { + self2.emit("error", error); + }); + } + util4.inherits(Extract, Transform2); + Extract.prototype._transform = function(chunk, encoding, cb) { + this.unzipStream.write(chunk, encoding, cb); + }; + Extract.prototype._flush = function(cb) { + var self2 = this; + var allDone = function() { + process.nextTick(function() { + self2.emit("close"); + }); + cb(); + }; + this.unzipStream.end(function() { + if (self2.unfinishedEntries > 0) { + self2.afterFlushWait = true; + return self2.on("await-finished", allDone); + } + allDone(); + }); + }; + Extract.prototype._processEntry = function(entry) { + var self2 = this; + var destPath = path36.join(this.opts.path, entry.path); + var directory = entry.isDirectory ? destPath : path36.dirname(destPath); + this.unfinishedEntries++; + var writeFileFn = function() { + var pipedStream = fs27.createWriteStream(destPath); + pipedStream.on("close", function() { + self2.unfinishedEntries--; + self2._notifyAwaiter(); + }); + pipedStream.on("error", function(error) { + self2.emit("error", error); + }); + entry.pipe(pipedStream); + }; + if (this.createdDirectories[directory] || directory === ".") { + return writeFileFn(); + } + mkdirp(directory, function(err) { + if (err) + return self2.emit("error", err); + self2.createdDirectories[directory] = true; + if (entry.isDirectory) { + self2.unfinishedEntries--; + self2._notifyAwaiter(); + return; + } + writeFileFn(); + }); + }; + Extract.prototype._notifyAwaiter = function() { + if (this.afterFlushWait && this.unfinishedEntries === 0) { + this.emit("await-finished"); + this.afterFlushWait = false; + } + }; + module2.exports = Extract; + } +}); + +// node_modules/unzip-stream/unzip.js +var require_unzip = __commonJS({ + "node_modules/unzip-stream/unzip.js"(exports2) { + "use strict"; + exports2.Parse = require_parser_stream(); + exports2.Extract = require_extract2(); + } +}); + +// node_modules/@tootallnate/once/dist/index.js +var require_dist = __commonJS({ + "node_modules/@tootallnate/once/dist/index.js"(exports2, module2) { + "use strict"; + function noop() { + } + function once(emitter, name2) { + const o = once.spread(emitter, name2); + const r = o.then((args) => args[0]); + r.cancel = o.cancel; + return r; + } + (function(once2) { + function spread(emitter, name2) { + let c = null; + const p = new Promise((resolve3, reject) => { + function cancel() { + emitter.removeListener(name2, onEvent); + emitter.removeListener("error", onError); + p.cancel = noop; + } + function onEvent(...args) { + cancel(); + resolve3(args); + } + function onError(err) { + cancel(); + reject(err); + } + c = cancel; + emitter.on(name2, onEvent); + emitter.on("error", onError); + }); + if (!c) { + throw new TypeError("Could not get `cancel()` function"); + } + p.cancel = c; + return p; + } + once2.spread = spread; + })(once || (once = {})); + module2.exports = once; + } +}); + +// node_modules/agent-base/dist/src/promisify.js +var require_promisify = __commonJS({ + "node_modules/agent-base/dist/src/promisify.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + function promisify(fn) { + return function(req, opts) { + return new Promise((resolve3, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } else { + resolve3(rtn); + } + }); + }); + }; + } + exports2.default = promisify; + } +}); + +// node_modules/agent-base/dist/src/index.js +var require_src2 = __commonJS({ + "node_modules/agent-base/dist/src/index.js"(exports2, module2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + var events_1 = require("events"); + var debug_1 = __importDefault(require_src()); + var promisify_1 = __importDefault(require_promisify()); + var debug = debug_1.default("agent-base"); + function isAgent(v) { + return Boolean(v) && typeof v.addRequest === "function"; + } + function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== "string") + return false; + return stack.split("\n").some((l) => l.indexOf("(https.js:") !== -1 || l.indexOf("node:https:") !== -1); + } + function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); + } + (function(createAgent2) { + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === "function") { + this.callback = callback; + } else if (callback) { + opts = callback; + } + this.timeout = null; + if (opts && typeof opts.timeout === "number") { + this.timeout = opts.timeout; + } + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === "number") { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === "string") { + return this.explicitProtocol; + } + return isSecureEndpoint() ? "https:" : "http:"; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== "boolean") { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = "localhost"; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? "https:" : "http:"; + } + if (opts.host && opts.path) { + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit("error", err); + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = "ETIMEOUT"; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + debug("Callback returned another Agent instance %o", socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once("free", () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== "function") { + onerror(new Error("`callback` is not defined")); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug("Converting legacy callback function to promise"); + this.promisifiedCallback = promisify_1.default(this.callback); + } else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === "number" && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ("port" in opts && typeof opts.port !== "number") { + opts.port = Number(opts.port); + } + try { + debug("Resolving socket for %o request: %o", opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug("Freeing socket %o %o", socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug("Destroying agent %o", this.constructor.name); + } + } + createAgent2.Agent = Agent; + createAgent2.prototype = createAgent2.Agent.prototype; + })(createAgent || (createAgent = {})); + module2.exports = createAgent; + } +}); + +// node_modules/http-proxy-agent/dist/agent.js +var require_agent = __commonJS({ + "node_modules/http-proxy-agent/dist/agent.js"(exports2) { + "use strict"; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve3) { + resolve3(value); + }); + } + return new (P || (P = Promise))(function(resolve3, 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 ? resolve3(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var net_1 = __importDefault(require("net")); + var tls_1 = __importDefault(require("tls")); + var url_1 = __importDefault(require("url")); + var debug_1 = __importDefault(require_src()); + var once_1 = __importDefault(require_dist()); + var agent_base_1 = require_src2(); + var debug = debug_1.default("http-proxy-agent"); + function isHTTPS(protocol) { + return typeof protocol === "string" ? /^https:?$/i.test(protocol) : false; + } + var HttpProxyAgent2 = class extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === "string") { + opts = url_1.default.parse(_opts); + } else { + opts = _opts; + } + if (!opts) { + throw new Error("an HTTP(S) proxy server `host` and `port` must be specified!"); + } + debug("Creating new HttpProxyAgent instance: %o", opts); + super(opts); + const proxy = Object.assign({}, opts); + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === "string") { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + if (proxy.host && proxy.path) { + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + const parsed = url_1.default.parse(req.path); + if (!parsed.protocol) { + parsed.protocol = "http:"; + } + if (!parsed.hostname) { + parsed.hostname = opts.hostname || opts.host || null; + } + if (parsed.port == null && typeof opts.port) { + parsed.port = String(opts.port); + } + if (parsed.port === "80") { + delete parsed.port; + } + req.path = url_1.default.format(parsed); + if (proxy.auth) { + req.setHeader("Proxy-Authorization", `Basic ${Buffer.from(proxy.auth).toString("base64")}`); + } + let socket; + if (secureProxy) { + debug("Creating `tls.Socket`: %o", proxy); + socket = tls_1.default.connect(proxy); + } else { + debug("Creating `net.Socket`: %o", proxy); + socket = net_1.default.connect(proxy); + } + if (req._header) { + let first; + let endOfHeaders; + debug("Regenerating stored HTTP header string for request"); + req._header = null; + req._implicitHeader(); + if (req.output && req.output.length > 0) { + debug("Patching connection write() output buffer with updated header"); + first = req.output[0]; + endOfHeaders = first.indexOf("\r\n\r\n") + 4; + req.output[0] = req._header + first.substring(endOfHeaders); + debug("Output buffer: %o", req.output); + } else if (req.outputData && req.outputData.length > 0) { + debug("Patching connection write() output buffer with updated header"); + first = req.outputData[0].data; + endOfHeaders = first.indexOf("\r\n\r\n") + 4; + req.outputData[0].data = req._header + first.substring(endOfHeaders); + debug("Output buffer: %o", req.outputData[0].data); + } + } + yield once_1.default(socket, "connect"); + return socket; + }); + } + }; + exports2.default = HttpProxyAgent2; + } +}); + +// node_modules/http-proxy-agent/dist/index.js +var require_dist2 = __commonJS({ + "node_modules/http-proxy-agent/dist/index.js"(exports2, module2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + var agent_1 = __importDefault(require_agent()); + function createHttpProxyAgent2(opts) { + return new agent_1.default(opts); + } + (function(createHttpProxyAgent3) { + createHttpProxyAgent3.HttpProxyAgent = agent_1.default; + createHttpProxyAgent3.prototype = agent_1.default.prototype; + })(createHttpProxyAgent2 || (createHttpProxyAgent2 = {})); + module2.exports = createHttpProxyAgent2; + } +}); + +// node_modules/https-proxy-agent/dist/parse-proxy-response.js +var require_parse_proxy_response = __commonJS({ + "node_modules/https-proxy-agent/dist/parse-proxy-response.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var debug_1 = __importDefault(require_src()); + var debug = debug_1.default("https-proxy-agent:parse-proxy-response"); + function parseProxyResponse(socket) { + return new Promise((resolve3, reject) => { + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once("readable", read); + } + function cleanup() { + socket.removeListener("end", onend); + socket.removeListener("error", onerror); + socket.removeListener("close", onclose); + socket.removeListener("readable", read); + } + function onclose(err) { + debug("onclose had error %o", err); + } + function onend() { + debug("onend"); + } + function onerror(err) { + cleanup(); + debug("onerror %o", err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf("\r\n\r\n"); + if (endOfHeaders === -1) { + debug("have not received end of HTTP headers yet..."); + read(); + return; + } + const firstLine = buffered.toString("ascii", 0, buffered.indexOf("\r\n")); + const statusCode = +firstLine.split(" ")[1]; + debug("got proxy server response: %o", firstLine); + resolve3({ + statusCode, + buffered + }); + } + socket.on("error", onerror); + socket.on("close", onclose); + socket.on("end", onend); + read(); + }); + } + exports2.default = parseProxyResponse; + } +}); + +// node_modules/https-proxy-agent/dist/agent.js +var require_agent2 = __commonJS({ + "node_modules/https-proxy-agent/dist/agent.js"(exports2) { + "use strict"; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve3) { + resolve3(value); + }); + } + return new (P || (P = Promise))(function(resolve3, 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 ? resolve3(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var net_1 = __importDefault(require("net")); + var tls_1 = __importDefault(require("tls")); + var url_1 = __importDefault(require("url")); + var assert_1 = __importDefault(require("assert")); + var debug_1 = __importDefault(require_src()); + var agent_base_1 = require_src2(); + var parse_proxy_response_1 = __importDefault(require_parse_proxy_response()); + var debug = debug_1.default("https-proxy-agent:agent"); + var HttpsProxyAgent2 = class extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === "string") { + opts = url_1.default.parse(_opts); + } else { + opts = _opts; + } + if (!opts) { + throw new Error("an HTTP(S) proxy server `host` and `port` must be specified!"); + } + debug("creating new HttpsProxyAgent instance: %o", opts); + super(opts); + const proxy = Object.assign({}, opts); + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === "string") { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + if (this.secureProxy && !("ALPNProtocols" in proxy)) { + proxy.ALPNProtocols = ["http 1.1"]; + } + if (proxy.host && proxy.path) { + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + let socket; + if (secureProxy) { + debug("Creating `tls.Socket`: %o", proxy); + socket = tls_1.default.connect(proxy); + } else { + debug("Creating `net.Socket`: %o", proxy); + socket = net_1.default.connect(proxy); + } + const headers = Object.assign({}, proxy.headers); + const hostname = `${opts.host}:${opts.port}`; + let payload = `CONNECT ${hostname} HTTP/1.1\r +`; + if (proxy.auth) { + headers["Proxy-Authorization"] = `Basic ${Buffer.from(proxy.auth).toString("base64")}`; + } + let { host, port, secureEndpoint } = opts; + if (!isDefaultPort(port, secureEndpoint)) { + host += `:${port}`; + } + headers.Host = host; + headers.Connection = "close"; + for (const name2 of Object.keys(headers)) { + payload += `${name2}: ${headers[name2]}\r +`; + } + const proxyResponsePromise = parse_proxy_response_1.default(socket); + socket.write(`${payload}\r +`); + const { statusCode, buffered } = yield proxyResponsePromise; + if (statusCode === 200) { + req.once("socket", resume); + if (opts.secureEndpoint) { + const servername = opts.servername || opts.host; + if (!servername) { + throw new Error('Could not determine "servername"'); + } + debug("Upgrading socket connection to TLS"); + return tls_1.default.connect(Object.assign(Object.assign({}, omit2(opts, "host", "hostname", "path", "port")), { + socket, + servername + })); + } + return socket; + } + socket.destroy(); + const fakeSocket = new net_1.default.Socket(); + fakeSocket.readable = true; + req.once("socket", (s) => { + debug("replaying proxy buffer for failed request"); + assert_1.default(s.listenerCount("data") > 0); + s.push(buffered); + s.push(null); + }); + return fakeSocket; + }); + } + }; + exports2.default = HttpsProxyAgent2; + function resume(socket) { + socket.resume(); + } + function isDefaultPort(port, secure) { + return Boolean(!secure && port === 80 || secure && port === 443); + } + function isHTTPS(protocol) { + return typeof protocol === "string" ? /^https:?$/i.test(protocol) : false; + } + function omit2(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; + } + } +}); + +// node_modules/https-proxy-agent/dist/index.js +var require_dist3 = __commonJS({ + "node_modules/https-proxy-agent/dist/index.js"(exports2, module2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + var agent_1 = __importDefault(require_agent2()); + function createHttpsProxyAgent2(opts) { + return new agent_1.default(opts); + } + (function(createHttpsProxyAgent3) { + createHttpsProxyAgent3.HttpsProxyAgent = agent_1.default; + createHttpsProxyAgent3.prototype = agent_1.default.prototype; + })(createHttpsProxyAgent2 || (createHttpsProxyAgent2 = {})); + module2.exports = createHttpsProxyAgent2; + } +}); + +// node_modules/mimic-response/index.js +var require_mimic_response = __commonJS({ + "node_modules/mimic-response/index.js"(exports2, module2) { + "use strict"; + var knownProperties = [ + "aborted", + "complete", + "headers", + "httpVersion", + "httpVersionMinor", + "httpVersionMajor", + "method", + "rawHeaders", + "rawTrailers", + "setTimeout", + "socket", + "statusCode", + "statusMessage", + "trailers", + "url" + ]; + module2.exports = (fromStream, toStream) => { + if (toStream._readableState.autoDestroy) { + throw new Error("The second stream must have the `autoDestroy` option set to `false`"); + } + const fromProperties = new Set(Object.keys(fromStream).concat(knownProperties)); + const properties = {}; + for (const property of fromProperties) { + if (property in toStream) { + continue; + } + properties[property] = { + get() { + const value = fromStream[property]; + const isFunction = typeof value === "function"; + return isFunction ? value.bind(fromStream) : value; + }, + set(value) { + fromStream[property] = value; + }, + enumerable: true, + configurable: false + }; + } + Object.defineProperties(toStream, properties); + fromStream.once("aborted", () => { + toStream.destroy(); + toStream.emit("aborted"); + }); + fromStream.once("close", () => { + if (fromStream.complete) { + if (toStream.readable) { + toStream.once("end", () => { + toStream.emit("close"); + }); + } else { + toStream.emit("close"); + } + } else { + toStream.emit("close"); + } + }); + return toStream; + }; + } +}); + +// node_modules/decompress-response/index.js +var require_decompress_response = __commonJS({ + "node_modules/decompress-response/index.js"(exports2, module2) { + "use strict"; + var { Transform: Transform2, PassThrough } = require("stream"); + var zlib = require("zlib"); + var mimicResponse = require_mimic_response(); + module2.exports = (response) => { + const contentEncoding = (response.headers["content-encoding"] || "").toLowerCase(); + if (!["gzip", "deflate", "br"].includes(contentEncoding)) { + return response; + } + const isBrotli = contentEncoding === "br"; + if (isBrotli && typeof zlib.createBrotliDecompress !== "function") { + response.destroy(new Error("Brotli is not supported on Node.js < 12")); + return response; + } + let isEmpty2 = true; + const checker = new Transform2({ + transform(data, _encoding, callback) { + isEmpty2 = false; + callback(null, data); + }, + flush(callback) { + callback(); + } + }); + const finalStream = new PassThrough({ + autoDestroy: false, + destroy(error, callback) { + response.destroy(); + callback(error); + } + }); + const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip(); + decompressStream.once("error", (error) => { + if (isEmpty2 && !response.readable) { + finalStream.end(); + return; + } + finalStream.destroy(error); + }); + mimicResponse(response, finalStream); + response.pipe(checker).pipe(decompressStream).pipe(finalStream); + return finalStream; + }; + } +}); + +// src/model/fetch.ts +function getSystemProxyURI(endpoint) { + let env; + if (endpoint.protocol === "http:") { + env = process.env.HTTP_PROXY || process.env.http_proxy || null; + } else if (endpoint.protocol === "https:") { + env = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || null; + } + let noProxy = process.env.NO_PROXY || process.env.no_proxy; + if (noProxy === "*") { + env = null; + } else if (noProxy) { + 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(); + if (noProxyItem.includes(":")) { + let noProxyItemParts = noProxyItem.split(":", 2); + let noProxyHost = noProxyItemParts[0].replace(/^\.*/, "."); + let noProxyPort = noProxyItemParts[1]; + if (port === noProxyPort && hostname.endsWith(noProxyHost)) { + env = null; + break; + } + } else { + noProxyItem = noProxyItem.replace(/^\.*/, "."); + if (hostname.endsWith(noProxyItem)) { + env = null; + break; + } + } + } + } + return env; +} +function getAgent(endpoint, options) { + let proxy = options.proxyUrl || getSystemProxyURI(endpoint); + if (proxy) { + const proxyEndpoint = (0, import_url.parse)(proxy); + if (!/^https?:$/.test(proxyEndpoint.protocol)) { + return null; + } + let opts = { + host: proxyEndpoint.hostname, + port: proxyEndpoint.port ? Number(proxyEndpoint.port) : proxyEndpoint.protocol === "https" ? "443" : "80", + auth: proxyEndpoint.auth, + rejectUnauthorized: typeof options.strictSSL === "boolean" ? options.strictSSL : true + }; + logger33.info(`Using proxy ${proxy} from ${options.proxyUrl ? "configuration" : "system environment"} for ${endpoint.hostname}:`); + return endpoint.protocol === "http:" ? (0, import_http_proxy_agent.default)(opts) : (0, import_https_proxy_agent.default)(opts); + } + return null; +} +function resolveRequestOptions(url, options = {}) { + let config = workspace_default.getConfiguration("http"); + let { data } = options; + let dataType = getDataType(data); + let proxyOptions = { + proxyUrl: config.get("proxy", ""), + strictSSL: config.get("proxyStrictSSL", true), + proxyAuthorization: config.get("proxyAuthorization", null), + proxyCA: config.get("proxyCA", null) + }; + if (options.query && !url.includes("?")) { + url = `${url}?${(0, import_querystring.stringify)(options.query)}`; + } + let headers = Object.assign(options.headers || {}, { "Proxy-Authorization": proxyOptions.proxyAuthorization }); + let endpoint = (0, import_url.parse)(url); + let agent = getAgent(endpoint, proxyOptions); + let opts = { + method: options.method || "GET", + hostname: endpoint.hostname, + port: endpoint.port ? parseInt(endpoint.port, 10) : endpoint.protocol === "https:" ? 443 : 80, + path: endpoint.path, + agent, + rejectUnauthorized: proxyOptions.strictSSL, + maxRedirects: 3, + headers: Object.assign({ + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64)", + "Accept-Encoding": "gzip, deflate" + }, headers) + }; + if (proxyOptions.proxyCA) { + opts.ca = import_fs11.default.readFileSync(proxyOptions.proxyCA); + } + if (dataType == "object") { + opts.headers["Content-Type"] = "application/json"; + } else if (dataType == "string") { + opts.headers["Content-Type"] = "text/plain"; + } + if (options.user && options.password) { + opts.auth = options.user + ":" + options.password; + } + if (options.timeout) { + opts.timeout = options.timeout; + } + if (options.buffer) + opts.buffer = true; + return opts; +} +function request(url, data, opts, token) { + let mod = url.startsWith("https:") ? import_follow_redirects.https : import_follow_redirects.http; + return new Promise((resolve3, reject) => { + if (token) { + let disposable = token.onCancellationRequested(() => { + disposable.dispose(); + req.destroy(new Error("request aborted")); + }); + } + const req = mod.request(opts, (res) => { + let readable = res; + if (res.statusCode >= 200 && res.statusCode < 300 || res.statusCode === 1223) { + let headers = res.headers || {}; + let chunks = []; + let contentType = headers["content-type"] || ""; + readable = (0, import_decompress_response.default)(res); + readable.on("data", (chunk) => { + chunks.push(chunk); + }); + readable.on("end", () => { + let buf = Buffer.concat(chunks); + if (!opts.buffer && (contentType.startsWith("application/json") || contentType.startsWith("text/"))) { + let ms = contentType.match(/charset=(\S+)/); + let encoding = ms ? ms[1] : "utf8"; + let rawData = buf.toString(encoding); + if (!contentType.includes("application/json")) { + resolve3(rawData); + } else { + try { + const parsedData = JSON.parse(rawData); + resolve3(parsedData); + } catch (e) { + reject(new Error(`Parse response error: ${e}`)); + } + } + } else { + resolve3(buf); + } + }); + readable.on("error", (err) => { + reject(new Error(`Unable to connect ${url}: ${err.message}`)); + }); + } else { + reject(new Error(`Bad response from ${url}: ${res.statusCode}`)); + } + }); + req.on("error", reject); + req.on("timeout", () => { + req.destroy(new Error(`Request timeout after ${opts.timeout}ms`)); + }); + if (data) { + if (typeof data === "string" || Buffer.isBuffer(data)) { + req.write(data); + } else { + req.write(JSON.stringify(data)); + } + } + if (opts.timeout) { + req.setTimeout(opts.timeout); + } + req.end(); + }); +} +function getDataType(data) { + if (data === null) + return "null"; + if (data === void 0) + return "undefined"; + if (typeof data == "string") + return "string"; + if (Buffer.isBuffer(data)) + return "buffer"; + if (Array.isArray(data) || objectLiteral(data)) + return "object"; + return "unknown"; +} +function fetch(url, options = {}, token) { + let opts = resolveRequestOptions(url, options); + return request(url, options.data, opts, token).catch((err) => { + logger33.error(`Fetch error for ${url}:`, opts, err); + if (opts.agent && opts.agent.proxy) { + let { proxy } = opts.agent; + throw new Error(`Request failed using proxy ${proxy.host}: ${err.message}`); + } else { + throw err; + } + }); +} +var import_follow_redirects, import_url, import_fs11, import_querystring, import_http_proxy_agent, import_https_proxy_agent, import_decompress_response, logger33; +var init_fetch = __esm({ + "src/model/fetch.ts"() { + import_follow_redirects = __toModule(require_follow_redirects()); + import_url = __toModule(require("url")); + import_fs11 = __toModule(require("fs")); + init_is(); + init_workspace(); + import_querystring = __toModule(require("querystring")); + import_http_proxy_agent = __toModule(require_dist2()); + import_https_proxy_agent = __toModule(require_dist3()); + import_decompress_response = __toModule(require_decompress_response()); + logger33 = require_logger2()("model-fetch"); + } +}); + +// src/model/download.ts +function download(url, options, token) { + let { dest, onProgress, extract } = options; + if (!dest || !import_path14.default.isAbsolute(dest)) { + throw new Error(`Expect absolute file path for dest option.`); + } + let stat; + try { + stat = import_fs_extra5.default.statSync(dest); + } catch (_e) { + import_fs_extra5.default.mkdirpSync(dest); + } + if (stat && !stat.isDirectory()) { + throw new Error(`${dest} exists, but not directory!`); + } + let mod = url.startsWith("https") ? import_follow_redirects2.https : import_follow_redirects2.http; + let opts = resolveRequestOptions(url, options); + let extname = import_path14.default.extname(url); + return new Promise((resolve3, reject) => { + if (token) { + let disposable = token.onCancellationRequested(() => { + disposable.dispose(); + req.destroy(new Error("request aborted")); + }); + } + const req = mod.request(opts, (res) => { + var _a2, _b; + if (res.statusCode >= 200 && res.statusCode < 300 || res.statusCode === 1223) { + let headers = res.headers || {}; + let dispositionHeader = headers["content-disposition"]; + if (!extname && dispositionHeader) { + let disposition = import_content_disposition.default.parse(dispositionHeader); + if ((_a2 = disposition.parameters) == null ? void 0 : _a2.filename) { + extname = import_path14.default.extname(disposition.parameters.filename); + } + } + if (extract === true) { + if (extname === ".zip" || headers["content-type"] == "application/zip") { + extract = "unzip"; + } else if (extname == ".tgz") { + extract = "untar"; + } else { + reject(new Error(`Unable to extract for ${url}`)); + return; + } + } + let total = Number(headers["content-length"]); + let cur = 0; + if (!isNaN(total)) { + res.on("data", (chunk) => { + cur += chunk.length; + let percent = (cur / total * 100).toFixed(1); + if (onProgress) { + onProgress(percent); + } else { + logger34.info(`Download ${url} progress ${percent}%`); + } + }); + } + res.on("error", (err) => { + reject(new Error(`Unable to connect ${url}: ${err.message}`)); + }); + res.on("end", () => { + logger34.info("Download completed:", url); + }); + let stream; + if (extract === "untar") { + stream = res.pipe(import_tar.default.x({ strip: (_b = options.strip) != null ? _b : 1, C: dest })); + } else if (extract === "unzip") { + stream = res.pipe(import_unzip_stream.default.Extract({ path: dest })); + } else { + dest = import_path14.default.join(dest, `${v1_default()}${extname}`); + stream = res.pipe(import_fs_extra5.default.createWriteStream(dest)); + } + stream.on("finish", () => { + logger34.info(`Downloaded ${url} => ${dest}`); + setTimeout(() => { + resolve3(dest); + }, 100); + }); + stream.on("error", reject); + } else { + reject(new Error(`Invalid response from ${url}: ${res.statusCode}`)); + } + }); + req.on("error", reject); + req.on("timeout", () => { + req.destroy(new Error(`request timeout after ${options.timeout}ms`)); + }); + if (options.timeout) { + req.setTimeout(options.timeout); + } + req.end(); + }); +} +var import_content_disposition, import_follow_redirects2, import_fs_extra5, import_path14, import_tar, import_unzip_stream, logger34; +var init_download = __esm({ + "src/model/download.ts"() { + import_content_disposition = __toModule(require_content_disposition()); + import_follow_redirects2 = __toModule(require_follow_redirects()); + import_fs_extra5 = __toModule(require_lib5()); + import_path14 = __toModule(require("path")); + import_tar = __toModule(require_tar()); + import_unzip_stream = __toModule(require_unzip()); + init_esm_node(); + init_fetch(); + logger34 = require_logger2()("model-download"); + } +}); + +// src/model/installer.ts +function registryUrl(scope = "coc.nvim") { + const result = (0, import_rc.default)("npm", { registry: "https://registry.npmjs.org/" }); + const registry = result[`${scope}:registry`] || result.config_registry || result.registry; + return registry.endsWith("/") ? registry : registry + "/"; +} +function createInstallerFactory(npm, root) { + return (def) => new Installer(root, npm, def); +} +var import_events17, import_child_process3, import_readline2, import_fs_extra6, import_os6, import_path15, import_rc, import_semver, logger35, Installer; +var init_installer = __esm({ + "src/model/installer.ts"() { + import_events17 = __toModule(require("events")); + import_child_process3 = __toModule(require("child_process")); + init_main3(); + import_readline2 = __toModule(require("readline")); + import_fs_extra6 = __toModule(require_lib5()); + import_os6 = __toModule(require("os")); + import_path15 = __toModule(require("path")); + import_rc = __toModule(require_rc()); + import_semver = __toModule(require_semver2()); + init_workspace(); + init_download(); + init_fetch(); + init_fs(); + logger35 = require_logger2()("model-installer"); + Installer = class extends import_events17.EventEmitter { + constructor(root, npm, def) { + super(); + this.root = root; + this.npm = npm; + this.def = def; + if (!import_fs_extra6.default.existsSync(root)) + import_fs_extra6.default.mkdirpSync(root); + if (/^https?:/.test(def)) { + this.url = def; + } else { + if (def.startsWith("@")) { + const idx = def.indexOf("@", 1); + if (idx > 1) { + this.name = def.substring(0, idx); + this.version = def.substring(idx + 1); + } else { + this.name = def; + } + } else { + if (def.includes("@")) { + let [name2, version2] = def.split("@", 2); + this.name = name2; + this.version = version2; + } else { + this.name = def; + } + } + } + } + get info() { + return { name: this.name, version: this.version }; + } + async install() { + this.log(`Using npm from: ${this.npm}`); + let info = await this.getInfo(); + logger35.info(`Fetched info of ${this.def}`, info); + let { name: name2 } = info; + let required = info["engines.coc"] ? info["engines.coc"].replace(/^\^/, ">=") : ""; + if (required && !import_semver.default.satisfies(workspace_default.version, required)) { + throw new Error(`${name2} ${info.version} requires coc.nvim >= ${required}, please update coc.nvim.`); + } + await this.doInstall(info); + return name2; + } + async update(url) { + this.url = url; + let folder = import_path15.default.join(this.root, this.name); + let stat = await import_fs_extra6.default.lstat(folder); + if (stat.isSymbolicLink()) { + this.log(`Skipped update for symbol link`); + return; + } + let version2; + if (import_fs_extra6.default.existsSync(import_path15.default.join(folder, "package.json"))) { + let content = await import_fs_extra6.default.readFile(import_path15.default.join(folder, "package.json"), "utf8"); + version2 = JSON.parse(content).version; + } + this.log(`Using npm from: ${this.npm}`); + let info = await this.getInfo(); + if (version2 && info.version && import_semver.default.gte(version2, info.version)) { + this.log(`Current version ${version2} is up to date.`); + return; + } + let required = info["engines.coc"] ? info["engines.coc"].replace(/^\^/, ">=") : ""; + if (required && !import_semver.default.satisfies(workspace_default.version, required)) { + throw new Error(`${info.version} requires coc.nvim ${required}, please update coc.nvim.`); + } + await this.doInstall(info); + let jsonFile = import_path15.default.join(this.root, info.name, "package.json"); + if (import_fs_extra6.default.existsSync(jsonFile)) { + this.log(`Updated to v${info.version}`); + return import_path15.default.dirname(jsonFile); + } else { + throw new Error(`Package.json not found: ${jsonFile}`); + } + } + async doInstall(info) { + let folder = import_path15.default.join(this.root, info.name); + if (import_fs_extra6.default.existsSync(folder)) { + let stat2 = import_fs_extra6.default.statSync(folder); + if (!stat2.isDirectory()) { + this.log(`${folder} is not directory skipped install`); + return; + } + } + let tmpFolder = await import_fs_extra6.default.mkdtemp(import_path15.default.join(import_os6.default.tmpdir(), `${info.name.replace("/", "-")}-`)); + let url = info["dist.tarball"]; + this.log(`Downloading from ${url}`); + await download(url, { dest: tmpFolder, onProgress: (p) => this.log(`Download progress ${p}%`, true), extract: "untar" }); + this.log(`Extension download at ${tmpFolder}`); + let content = await import_fs_extra6.default.readFile(import_path15.default.join(tmpFolder, "package.json"), "utf8"); + let { dependencies } = JSON.parse(content); + if (dependencies && Object.keys(dependencies).length) { + let p = new Promise((resolve3, reject) => { + let args = ["install", "--ignore-scripts", "--no-lockfile", "--production", "--no-global"]; + if (url.startsWith("https://github.com")) { + args = ["install"]; + } + if ((this.npm.endsWith("npm") || this.npm.endsWith("npm.CMD")) && !this.npm.endsWith("pnpm")) { + args.push("--legacy-peer-deps"); + } + if (this.npm.endsWith("yarn")) { + args.push("--ignore-engines"); + } + this.log(`Installing dependencies by: ${this.npm} ${args.join(" ")}.`); + const child = (0, import_child_process3.spawn)(this.npm, args, { + cwd: tmpFolder + }); + const rl = import_readline2.default.createInterface({ + input: child.stdout + }); + rl.on("line", (line) => { + this.log(`[npm] ${line}`, true); + }); + child.stderr.setEncoding("utf8"); + child.stdout.setEncoding("utf8"); + child.on("error", reject); + let err = ""; + child.stderr.on("data", (data) => { + err += data; + }); + child.on("exit", (code) => { + if (code) { + if (err) + this.log(err); + reject(new Error(`${this.npm} install exited with ${code}`)); + return; + } + resolve3(); + }); + }); + await p; + } + let jsonFile = import_path15.default.resolve(this.root, global.hasOwnProperty("__TEST__") ? "" : "..", "package.json"); + let errors = []; + let obj = parse3(import_fs_extra6.default.readFileSync(jsonFile, "utf8"), errors, { allowTrailingComma: true }); + if (errors && errors.length > 0) { + throw new Error(`Error on load ${jsonFile}`); + } + obj.dependencies = obj.dependencies || {}; + if (this.url) { + obj.dependencies[info.name] = this.url; + } else { + obj.dependencies[info.name] = ">=" + info.version; + } + const sortedObj = { dependencies: {} }; + Object.keys(obj.dependencies).sort().forEach((k) => { + sortedObj.dependencies[k] = obj.dependencies[k]; + }); + let stat = await statAsync(folder); + if (stat) { + if (stat.isDirectory()) { + import_fs_extra6.default.removeSync(folder); + } else { + import_fs_extra6.default.unlinkSync(folder); + } + } + await import_fs_extra6.default.move(tmpFolder, folder, { overwrite: true }); + await import_fs_extra6.default.writeFile(jsonFile, JSON.stringify(sortedObj, null, 2), { encoding: "utf8" }); + this.log(`Update package.json at ${jsonFile}`); + this.log(`Installed extension ${this.name}@${info.version} at ${folder}`); + } + async getInfo() { + if (this.url) + return await this.getInfoFromUri(); + let registry = registryUrl(); + this.log(`Get info from ${registry}`); + let buffer = await fetch(registry + this.name, { timeout: 1e4, buffer: true }); + let res = JSON.parse(buffer.toString()); + if (!this.version) + this.version = res["dist-tags"]["latest"]; + let obj = res["versions"][this.version]; + if (!obj) + throw new Error(`${this.def} doesn't exists in ${registry}.`); + let requiredVersion = obj["engines"] && obj["engines"]["coc"]; + if (!requiredVersion) { + throw new Error(`${this.def} 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 getInfoFromUri() { + let { url } = this; + if (!url.includes("github.com")) { + throw new Error(`"${url}" is not supported, coc.nvim support github.com only`); + } + url = url.replace(/\/$/, ""); + let branch = "master"; + if (url.includes("@")) { + let idx = url.indexOf("@"); + branch = url.substr(idx + 1); + url = url.substring(0, idx); + } + let fileUrl = url.replace("github.com", "raw.githubusercontent.com") + `/${branch}/package.json`; + this.log(`Get info from ${fileUrl}`); + let content = await fetch(fileUrl, { timeout: 1e4 }); + let obj = typeof content == "string" ? JSON.parse(content) : content; + this.name = obj.name; + return { + "dist.tarball": `${url}/archive/${branch}.tar.gz`, + "engines.coc": obj["engines"] ? obj["engines"]["coc"] : null, + name: obj.name, + version: obj.version + }; + } + log(msg, isProgress = false) { + logger35.info(msg); + this.emit("message", msg, isProgress); + } + }; + } +}); + +// src/model/memos.ts +var import_fs13, logger36, Memos; +var init_memos = __esm({ + "src/model/memos.ts"() { + import_fs13 = __toModule(require("fs")); + init_object(); + logger36 = require_logger2()("model-memos"); + Memos = class { + constructor(filepath) { + this.filepath = filepath; + if (!import_fs13.default.existsSync(filepath)) { + import_fs13.default.writeFileSync(filepath, "{}", "utf8"); + } + } + fetchContent(id, key) { + try { + let content = import_fs13.default.readFileSync(this.filepath, "utf8"); + let res = JSON.parse(content); + let obj = res[id]; + if (!obj) + return void 0; + return obj[key]; + } catch (e) { + return void 0; + } + } + async update(id, key, value) { + let { filepath } = this; + try { + let content = import_fs13.default.readFileSync(filepath, "utf8"); + let current = content ? JSON.parse(content) : {}; + current[id] = current[id] || {}; + if (value !== void 0) { + current[id][key] = deepClone(value); + } else { + delete current[id][key]; + } + content = JSON.stringify(current, null, 2); + import_fs13.default.writeFileSync(filepath, content, "utf8"); + } catch (e) { + logger36.error(`Error on update memos:`, e); + } + } + createMemento(id) { + return { + get: (key, defaultValue) => { + let res = this.fetchContent(id, key); + return res === void 0 ? defaultValue : res; + }, + update: async (key, value) => { + await this.update(id, key, value); + } + }; + } + }; + } +}); + +// src/util/lodash.ts +function defaults(obj, ...sources) { + obj = Object(obj); + sources.forEach((source) => { + if (source != null) { + source = Object(source); + for (const key in source) { + const value = obj[key]; + if (value === void 0 || value === objectProto[key] && !hasOwnProperty2.call(obj, key)) { + obj[key] = source[key]; + } + } + } + }); + return obj; +} +function omit(obj, properties) { + let o = {}; + for (let key of Object.keys(obj)) { + if (!properties.includes(key)) { + o[key] = obj[key]; + } + } + return o; +} +var objectProto, hasOwnProperty2; +var init_lodash = __esm({ + "src/util/lodash.ts"() { + objectProto = Object.prototype; + hasOwnProperty2 = objectProto.hasOwnProperty; + } +}); + +// src/provider/manager.ts +function addLocation(arr, location) { + let { range, uri } = location; + if (arr.find((o) => o.uri == uri && equals(o.range, range)) != null) + return; + arr.push(location); +} +var import_vscode_languageserver_protocol21, logger37, Manager; +var init_manager2 = __esm({ + "src/provider/manager.ts"() { + import_vscode_languageserver_protocol21 = __toModule(require_main2()); + init_workspace(); + init_object(); + logger37 = require_logger2()("provider-manager"); + Manager = class { + constructor() { + this.providers = new Set(); + } + hasProvider(document2) { + return this.getProvider(document2) != null; + } + getProvider(document2) { + let currScore = 0; + let providerItem; + for (let item of this.providers) { + let { selector, priority } = item; + let score5 = workspace_default.match(selector, document2); + if (score5 == 0) + continue; + if (typeof priority == "number") { + score5 = priority; + } + if (score5 < currScore) + continue; + currScore = score5; + providerItem = item; + } + return providerItem; + } + getProviderById(id) { + let item = Array.from(this.providers).find((o) => o.id == id); + return item ? item.provider : null; + } + getProviders(document2) { + let items = Array.from(this.providers); + items = items.filter((item) => workspace_default.match(item.selector, document2) > 0); + return items.sort((a, b) => workspace_default.match(b.selector, document2) - workspace_default.match(a.selector, document2)); + } + toLocations(arr) { + let res = []; + for (let def of arr) { + if (!def) + continue; + if (import_vscode_languageserver_protocol21.Location.is(def)) { + addLocation(res, def); + } else if (Array.isArray(def)) { + for (let d of def) { + if (import_vscode_languageserver_protocol21.Location.is(d)) { + addLocation(res, d); + } else if (import_vscode_languageserver_protocol21.LocationLink.is(d)) { + let { targetUri, targetSelectionRange, targetRange } = d; + addLocation(res, import_vscode_languageserver_protocol21.Location.create(targetUri, targetSelectionRange || targetRange)); + } + } + } else { + logger37.error(`Bad definition`, def); + } + } + return res; + } + }; + } +}); + +// src/provider/callHierarchyManager.ts +var import_vscode_languageserver_protocol22, CallHierarchyManager; +var init_callHierarchyManager = __esm({ + "src/provider/callHierarchyManager.ts"() { + import_vscode_languageserver_protocol22 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + CallHierarchyManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol22.Disposable.create(() => { + this.providers.delete(item); + }); + } + async prepareCallHierarchy(document2, position, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + if (provider.prepareCallHierarchy === null) + return null; + return await Promise.resolve(provider.prepareCallHierarchy(document2, position, token)); + } + async provideCallHierarchyOutgoingCalls(document2, item, token) { + let providerItem = this.getProvider(document2); + if (!providerItem) + return null; + let { provider } = providerItem; + if (provider.provideCallHierarchyOutgoingCalls === null) + return null; + return await Promise.resolve(provider.provideCallHierarchyOutgoingCalls(item, token)); + } + async provideCallHierarchyIncomingCalls(document2, item, token) { + let providerItem = this.getProvider(document2); + if (!providerItem) + return null; + let { provider } = providerItem; + if (provider.provideCallHierarchyIncomingCalls(item, token) === null) + return null; + return await Promise.resolve(provider.provideCallHierarchyIncomingCalls(item, token)); + } + }; + } +}); + +// src/provider/codeActionManager.ts +var import_vscode_languageserver_protocol23, logger38, CodeActionManager; +var init_codeActionManager = __esm({ + "src/provider/codeActionManager.ts"() { + import_vscode_languageserver_protocol23 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + logger38 = require_logger2()("codeActionManager"); + CodeActionManager = class extends Manager { + constructor() { + super(...arguments); + this.providerMap = new WeakMap(); + } + register(selector, provider, clientId, codeActionKinds) { + let item = { + id: v4_default(), + selector, + provider, + kinds: codeActionKinds, + clientId + }; + this.providers.add(item); + return import_vscode_languageserver_protocol23.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideCodeActions(document2, range, context, token) { + let providers = this.getProviders(document2); + if (!providers.length) + return null; + if (context.only) { + let { only } = context; + providers = providers.filter((p) => { + if (p.kinds && !p.kinds.some((kind) => only.includes(kind))) { + return false; + } + return true; + }); + } + let res = []; + await Promise.all(providers.map((item) => { + let { provider, id } = item; + return Promise.resolve(provider.provideCodeActions(document2, range, context, token)).then((actions) => { + if (!actions || actions.length == 0) + return; + for (let action of actions) { + if (import_vscode_languageserver_protocol23.Command.is(action)) { + let codeAction = { + title: action.title, + command: action + }; + res.push(codeAction); + this.providerMap.set(codeAction, id); + } else { + if (context.only) { + if (!action.kind) + continue; + let found = false; + for (let only of context.only) { + if (action.kind.startsWith(only)) { + found = true; + break; + } + } + if (!found) + continue; + } + let idx = res.findIndex((o) => o.title == action.title); + if (idx == -1) { + this.providerMap.set(action, id); + res.push(action); + } + } + } + }); + })); + return res; + } + async resolveCodeAction(codeAction, token) { + if (codeAction.edit != null) + return codeAction; + let id = this.providerMap.get(codeAction); + if (!id) + throw new Error(`provider id not found from codeAction`); + let provider = this.getProviderById(id); + if (!provider || typeof provider.resolveCodeAction !== "function") { + return codeAction; + } + let resolved = await Promise.resolve(provider.resolveCodeAction(codeAction, token)); + if (resolved) + this.providerMap.set(resolved, id); + return resolved || codeAction; + } + }; + } +}); + +// src/provider/codeLensManager.ts +var import_vscode_languageserver_protocol24, CodeLensManager; +var init_codeLensManager = __esm({ + "src/provider/codeLensManager.ts"() { + import_vscode_languageserver_protocol24 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + init_lodash(); + CodeLensManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol24.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideCodeLenses(document2, token) { + let providers = this.getProviders(document2); + if (!providers.length) + return null; + let arr = await Promise.all(providers.map((item) => { + let { provider, id } = item; + return Promise.resolve(provider.provideCodeLenses(document2, token)).then((res) => { + if (Array.isArray(res)) { + for (let item2 of res) { + item2.source = id; + } + } + return res; + }); + })); + return [].concat(...arr); + } + async resolveCodeLens(codeLens, token) { + if (codeLens.command) + return codeLens; + let { source } = codeLens; + let provider = this.getProviderById(source); + if (!provider || typeof provider.resolveCodeLens != "function") { + return codeLens; + } + let res = await Promise.resolve(provider.resolveCodeLens(omit(codeLens, ["source"]), token)); + Object.assign(codeLens, res); + return codeLens; + } + }; + } +}); + +// src/provider/declarationManager.ts +var import_vscode_languageserver_protocol25, logger39, DeclarationManager; +var init_declarationManager = __esm({ + "src/provider/declarationManager.ts"() { + import_vscode_languageserver_protocol25 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + logger39 = require_logger2()("definitionManager"); + DeclarationManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol25.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideDeclaration(document2, position, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + return await Promise.resolve(provider.provideDeclaration(document2, position, token)); + } + }; + } +}); + +// src/provider/definitionManager.ts +var import_vscode_languageserver_protocol26, logger40, DefinitionManager; +var init_definitionManager = __esm({ + "src/provider/definitionManager.ts"() { + import_vscode_languageserver_protocol26 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + init_object(); + logger40 = require_logger2()("definitionManager"); + DefinitionManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol26.Disposable.create(() => { + this.providers.delete(item); + }); + } + async getDefinitions(document2, position, token) { + const providers = this.getProviders(document2); + if (!providers.length) + return []; + const arr = await Promise.all(providers.map((item) => { + const { provider } = item; + return Promise.resolve(provider.provideDefinition(document2, position, token)); + })); + return arr; + } + async provideDefinition(document2, position, token) { + const arr = await this.getDefinitions(document2, position, token); + return this.toLocations(arr); + } + async provideDefinitionLinks(document2, position, token) { + const arr = await this.getDefinitions(document2, position, token); + const defs = []; + for (const def of arr) { + if (!Array.isArray(def)) + continue; + for (const val of def) { + if (import_vscode_languageserver_protocol26.LocationLink.is(val)) { + let idx = defs.findIndex((o) => o.targetUri == val.targetUri && equals(o.targetRange, val.targetRange)); + if (idx == -1) + defs.push(val); + } + } + } + return defs; + } + }; + } +}); + +// src/provider/documentColorManager.ts +var import_vscode_languageserver_protocol27, DocumentColorManager; +var init_documentColorManager = __esm({ + "src/provider/documentColorManager.ts"() { + import_vscode_languageserver_protocol27 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + DocumentColorManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol27.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideDocumentColors(document2, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + let res = await Promise.resolve(provider.provideDocumentColors(document2, token)); + return res; + } + async provideColorPresentations(colorInformation, document2, token) { + let { range, color } = colorInformation; + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + let res = await Promise.resolve(provider.provideColorPresentations(color, { document: document2, range }, token)); + return res; + } + }; + } +}); + +// src/provider/documentHighlightManager.ts +var import_vscode_languageserver_protocol28, DocumentHighlightManager; +var init_documentHighlightManager = __esm({ + "src/provider/documentHighlightManager.ts"() { + import_vscode_languageserver_protocol28 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + DocumentHighlightManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol28.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideDocumentHighlights(document2, position, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + return await Promise.resolve(provider.provideDocumentHighlights(document2, position, token)); + } + }; + } +}); + +// src/provider/documentLinkManager.ts +var import_vscode_languageserver_protocol29, DocumentLinkManager; +var init_documentLinkManager = __esm({ + "src/provider/documentLinkManager.ts"() { + import_vscode_languageserver_protocol29 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + DocumentLinkManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol29.Disposable.create(() => { + this.providers.delete(item); + }); + } + async _provideDocumentLinks(item, document2, token) { + let { provider, id } = item; + let items = await Promise.resolve(provider.provideDocumentLinks(document2, token)); + if (!items || !items.length) + return []; + items.forEach((item2) => { + item2.data = item2.data || {}; + item2.data.source = id; + }); + return items; + } + async provideDocumentLinks(document2, token) { + let items = this.getProviders(document2); + if (items.length == 0) + return []; + const arr = await Promise.all(items.map((item) => this._provideDocumentLinks(item, document2, 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; + } + }; + } +}); + +// src/provider/documentSymbolManager.ts +var import_vscode_languageserver_protocol30, DocumentSymbolManager; +var init_documentSymbolManager = __esm({ + "src/provider/documentSymbolManager.ts"() { + import_vscode_languageserver_protocol30 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + DocumentSymbolManager = class extends Manager { + register(selector, provider, displayName) { + let item = { + id: v4_default(), + displayName, + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol30.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideDocumentSymbols(document2, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + return await Promise.resolve(provider.provideDocumentSymbols(document2, token)) || []; + } + }; + } +}); + +// src/provider/foldingRangeManager.ts +var import_vscode_languageserver_protocol31, FoldingRangeManager; +var init_foldingRangeManager = __esm({ + "src/provider/foldingRangeManager.ts"() { + import_vscode_languageserver_protocol31 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + FoldingRangeManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol31.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideFoldingRanges(document2, context, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + return await Promise.resolve(provider.provideFoldingRanges(document2, context, token)) || []; + } + }; + } +}); + +// src/provider/formatManager.ts +var import_vscode_languageserver_protocol32, FormatManager; +var init_formatManager = __esm({ + "src/provider/formatManager.ts"() { + import_vscode_languageserver_protocol32 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + FormatManager = class extends Manager { + register(selector, provider, priority = 0) { + let item = { + id: v4_default(), + selector, + priority, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol32.Disposable.create(() => { + this.providers.delete(item); + }); + } + handles(doc) { + return this.getProvider(doc) != null; + } + async provideDocumentFormattingEdits(document2, options, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + return await Promise.resolve(provider.provideDocumentFormattingEdits(document2, options, token)); + } + }; + } +}); + +// src/provider/formatRangeManager.ts +var import_vscode_languageserver_protocol33, FormatRangeManager; +var init_formatRangeManager = __esm({ + "src/provider/formatRangeManager.ts"() { + import_vscode_languageserver_protocol33 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + FormatRangeManager = class extends Manager { + register(selector, provider, priority = 0) { + let item = { + id: v4_default(), + selector, + provider, + priority + }; + this.providers.add(item); + return import_vscode_languageserver_protocol33.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideDocumentRangeFormattingEdits(document2, range, options, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + return await Promise.resolve(provider.provideDocumentRangeFormattingEdits(document2, range, options, token)); + } + }; + } +}); + +// src/provider/hoverManager.ts +var import_vscode_languageserver_protocol34, HoverManager; +var init_hoverManager = __esm({ + "src/provider/hoverManager.ts"() { + import_vscode_languageserver_protocol34 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + HoverManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol34.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideHover(document2, position, token) { + let items = this.getProviders(document2); + 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(document2, position, token)); + if (hover && hover.contents != "") + res.push(hover); + } + return res; + } + }; + } +}); + +// src/provider/implementationManager.ts +var import_vscode_languageserver_protocol35, ImplementationManager; +var init_implementationManager = __esm({ + "src/provider/implementationManager.ts"() { + import_vscode_languageserver_protocol35 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + ImplementationManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol35.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideReferences(document2, position, token) { + let providers = this.getProviders(document2); + if (!providers.length) + return null; + let arr = await Promise.all(providers.map((item) => { + let { provider } = item; + return Promise.resolve(provider.provideImplementation(document2, position, token)); + })); + return this.toLocations(arr); + } + }; + } +}); + +// src/provider/linkedEditingRangeManager.ts +var import_vscode_languageserver_protocol36, logger41, LinkedEditingRangeManager; +var init_linkedEditingRangeManager = __esm({ + "src/provider/linkedEditingRangeManager.ts"() { + init_esm_node(); + import_vscode_languageserver_protocol36 = __toModule(require_main2()); + init_manager2(); + logger41 = require_logger2()("linkedEditingManager"); + LinkedEditingRangeManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol36.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideLinkedEditingRanges(document2, position, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + if (!provider.provideLinkedEditingRanges) + return null; + return await Promise.resolve(provider.provideLinkedEditingRanges(document2, position, token)); + } + }; + } +}); + +// src/provider/onTypeFormatManager.ts +var import_vscode_languageserver_protocol37, logger42, OnTypeFormatManager; +var init_onTypeFormatManager = __esm({ + "src/provider/onTypeFormatManager.ts"() { + import_vscode_languageserver_protocol37 = __toModule(require_main2()); + init_workspace(); + logger42 = require_logger2()("onTypeFormatManager"); + OnTypeFormatManager = class { + constructor() { + this.providers = new Set(); + } + register(selector, provider, triggerCharacters) { + let item = { + triggerCharacters, + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol37.Disposable.create(() => { + this.providers.delete(item); + }); + } + hasProvider(document2) { + for (let o of this.providers) { + let { selector } = o; + if (workspace_default.match(selector, document2) > 0) { + return true; + } + } + return false; + } + getProvider(document2, triggerCharacter) { + for (let o of this.providers) { + let { triggerCharacters, selector } = o; + if (workspace_default.match(selector, document2) > 0 && triggerCharacters.includes(triggerCharacter)) { + return o.provider; + } + } + return null; + } + async onCharacterType(character, document2, position, token) { + let provider = this.getProvider(document2, character); + if (!provider) + return; + let formatOpts = await workspace_default.getFormatOptions(document2.uri); + return await Promise.resolve(provider.provideOnTypeFormattingEdits(document2, position, character, formatOpts, token)); + } + }; + } +}); + +// src/provider/referenceManager.ts +var import_vscode_languageserver_protocol38, ReferenceManager; +var init_referenceManager = __esm({ + "src/provider/referenceManager.ts"() { + import_vscode_languageserver_protocol38 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + ReferenceManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol38.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideReferences(document2, position, context, token) { + let providers = this.getProviders(document2); + if (!providers.length) + return null; + let arr = await Promise.all(providers.map((item) => { + let { provider } = item; + return Promise.resolve(provider.provideReferences(document2, position, context, token)); + })); + return this.toLocations(arr); + } + }; + } +}); + +// src/provider/renameManager.ts +var import_vscode_languageserver_protocol39, RenameManager; +var init_renameManager = __esm({ + "src/provider/renameManager.ts"() { + import_vscode_languageserver_protocol39 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + RenameManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol39.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideRenameEdits(document2, position, newName, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + return await Promise.resolve(provider.provideRenameEdits(document2, position, newName, token)); + } + async prepareRename(document2, position, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + if (provider.prepareRename == null) + return null; + let res = await Promise.resolve(provider.prepareRename(document2, position, token)); + if (res == null) + return false; + return res; + } + }; + } +}); + +// src/provider/selectionRangeManager.ts +var import_vscode_languageserver_protocol40, SelectionRangeManager; +var init_selectionRangeManager = __esm({ + "src/provider/selectionRangeManager.ts"() { + import_vscode_languageserver_protocol40 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + SelectionRangeManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol40.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideSelectionRanges(document2, positions2, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + let ranges = await Promise.resolve(provider.provideSelectionRanges(document2, positions2, token)); + if (!ranges || ranges.length == 0) + return []; + for (let i = 0; i < ranges.length - 1; i++) { + let r = ranges[i]; + if (!r.parent) + r.parent = ranges[i + 1]; + } + return ranges; + } + }; + } +}); + +// src/provider/semanticTokensManager.ts +var import_vscode_languageserver_protocol41, logger43, SemanticTokensManager; +var init_semanticTokensManager = __esm({ + "src/provider/semanticTokensManager.ts"() { + init_esm_node(); + import_vscode_languageserver_protocol41 = __toModule(require_main2()); + init_manager2(); + logger43 = require_logger2()("semanticTokensManager"); + SemanticTokensManager = class extends Manager { + constructor() { + super(...arguments); + this.resolvedProvider = new Map(); + } + register(selector, provider, legend, onChange) { + let id = v4_default(); + let item = { + id, + selector, + legend, + provider + }; + this.providers.add(item); + let disposable; + if (typeof provider.onDidChangeSemanticTokens === "function") { + disposable = provider.onDidChangeSemanticTokens(() => { + onChange(); + }); + } + return import_vscode_languageserver_protocol41.Disposable.create(() => { + disposable == null ? void 0 : disposable.dispose(); + for (let [uri, providerId] of this.resolvedProvider.entries()) { + if (providerId == id) { + this.resolvedProvider.delete(uri); + } + } + this.providers.delete(item); + }); + } + getLegend(document2) { + const item = this.getProvider(document2); + if (!item) + return; + this.resolvedProvider.set(document2.uri, item.id); + return item.legend; + } + resolveProvider(document2) { + var _a2; + let id = this.resolvedProvider.get(document2.uri); + if (id) + return this.getProviderById(id); + return (_a2 = this.getProvider(document2)) == null ? void 0 : _a2.provider; + } + hasSemanticTokensEdits(document2) { + let provider = this.resolveProvider(document2); + if (!provider) + return false; + return typeof provider.provideDocumentSemanticTokensEdits === "function"; + } + async provideDocumentSemanticTokens(document2, token) { + let provider = this.resolveProvider(document2); + if (!provider || typeof provider.provideDocumentSemanticTokens !== "function") + return null; + return await Promise.resolve(provider.provideDocumentSemanticTokens(document2, token)); + } + async provideDocumentSemanticTokensEdits(document2, previousResultId, token) { + let provider = this.resolveProvider(document2); + if (!provider || typeof provider.provideDocumentSemanticTokensEdits !== "function") + return null; + return await Promise.resolve(provider.provideDocumentSemanticTokensEdits(document2, previousResultId, token)); + } + }; + } +}); + +// src/provider/semanticTokensRangeManager.ts +var import_vscode_languageserver_protocol42, logger44, SemanticTokensRangeManager; +var init_semanticTokensRangeManager = __esm({ + "src/provider/semanticTokensRangeManager.ts"() { + init_esm_node(); + import_vscode_languageserver_protocol42 = __toModule(require_main2()); + init_manager2(); + logger44 = require_logger2()("semanticTokensRangeManager"); + SemanticTokensRangeManager = class extends Manager { + register(selector, provider, legend) { + let item = { + id: v4_default(), + selector, + legend, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol42.Disposable.create(() => { + this.providers.delete(item); + }); + } + getLegend(document2) { + const item = this.getProvider(document2); + if (!item) + return; + return item.legend; + } + async provideDocumentRangeSemanticTokens(document2, range, token) { + let item = this.getProvider(document2); + if (!item) + return null; + let { provider } = item; + if (provider.provideDocumentRangeSemanticTokens === null) + return null; + return await Promise.resolve(provider.provideDocumentRangeSemanticTokens(document2, range, token)); + } + }; + } +}); + +// src/provider/signatureManager.ts +var import_vscode_languageserver_protocol43, SignatureManager; +var init_signatureManager = __esm({ + "src/provider/signatureManager.ts"() { + import_vscode_languageserver_protocol43 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + SignatureManager = class extends Manager { + register(selector, provider, triggerCharacters) { + let characters = triggerCharacters.reduce((p, c) => p.concat(c.length == 1 ? [c] : c.split(/\s*/g)), []); + let item = { + id: v4_default(), + selector, + provider, + triggerCharacters: characters + }; + this.providers.add(item); + return import_vscode_languageserver_protocol43.Disposable.create(() => { + this.providers.delete(item); + }); + } + shouldTrigger(document2, triggerCharacter) { + let item = this.getProvider(document2); + if (!item) + return false; + let { triggerCharacters } = item; + return triggerCharacters && triggerCharacters.indexOf(triggerCharacter) != -1; + } + async provideSignatureHelp(document2, position, token, context) { + let item = this.getProvider(document2); + if (!item) + return null; + let res = await Promise.resolve(item.provider.provideSignatureHelp(document2, position, token, context)); + if (res && res.signatures && res.signatures.length) + return res; + return null; + } + }; + } +}); + +// src/provider/typeDefinitionManager.ts +var import_vscode_languageserver_protocol44, TypeDefinitionManager; +var init_typeDefinitionManager = __esm({ + "src/provider/typeDefinitionManager.ts"() { + import_vscode_languageserver_protocol44 = __toModule(require_main2()); + init_manager2(); + init_esm_node(); + TypeDefinitionManager = class extends Manager { + register(selector, provider) { + let item = { + id: v4_default(), + selector, + provider + }; + this.providers.add(item); + return import_vscode_languageserver_protocol44.Disposable.create(() => { + this.providers.delete(item); + }); + } + async provideTypeDefinition(document2, position, token) { + let providers = this.getProviders(document2); + if (!providers.length) + return null; + let arr = await Promise.all(providers.map((item) => { + let { provider } = item; + return Promise.resolve(provider.provideTypeDefinition(document2, position, token)); + })); + return this.toLocations(arr); + } + }; + } +}); + +// src/provider/workspaceSymbolsManager.ts +var import_vscode_languageserver_protocol45, WorkspaceSymbolManager; +var init_workspaceSymbolsManager = __esm({ + "src/provider/workspaceSymbolsManager.ts"() { + init_esm_node(); + import_vscode_languageserver_protocol45 = __toModule(require_main2()); + WorkspaceSymbolManager = class { + constructor() { + this.providers = new Map(); + } + register(provider) { + let id = v4_default(); + this.providers.set(id, provider); + return import_vscode_languageserver_protocol45.Disposable.create(() => { + this.providers.delete(id); + }); + } + async provideWorkspaceSymbols(query, token) { + let entries = Array.from(this.providers.entries()); + if (!entries.length) + return []; + let res = []; + await Promise.all(entries.map((o) => { + let [id, p] = o; + return Promise.resolve(p.provideWorkspaceSymbols(query, token)).then((list2) => { + if (list2) + res.push(...list2.map((item) => Object.assign({ source: id }, item))); + }); + })); + return res; + } + async resolveWorkspaceSymbol(symbolInfo, token) { + let provider = this.providers.get(symbolInfo.source); + if (!provider) + return; + if (typeof provider.resolveWorkspaceSymbol != "function") { + return Promise.resolve(symbolInfo); + } + return await Promise.resolve(provider.resolveWorkspaceSymbol(symbolInfo, token)); + } + hasProvider() { + return this.providers.size > 0; + } + }; + } +}); + +// src/languages.ts +var import_vscode_languageserver_protocol46, logger45, Languages, languages_default; +var init_languages = __esm({ + "src/languages.ts"() { + import_vscode_languageserver_protocol46 = __toModule(require_main2()); + init_manager(); + init_callHierarchyManager(); + init_codeActionManager(); + init_codeLensManager(); + init_declarationManager(); + init_definitionManager(); + init_documentColorManager(); + init_documentHighlightManager(); + init_documentLinkManager(); + init_documentSymbolManager(); + init_foldingRangeManager(); + init_formatManager(); + init_formatRangeManager(); + init_hoverManager(); + init_implementationManager(); + init_linkedEditingRangeManager(); + init_onTypeFormatManager(); + init_referenceManager(); + init_renameManager(); + init_selectionRangeManager(); + init_semanticTokensManager(); + init_semanticTokensRangeManager(); + init_signatureManager(); + init_typeDefinitionManager(); + init_workspaceSymbolsManager(); + logger45 = require_logger2()("languages"); + Languages = class { + constructor() { + this._onDidSemanticTokensRefresh = new import_vscode_languageserver_protocol46.Emitter(); + this.onDidSemanticTokensRefresh = this._onDidSemanticTokensRefresh.event; + this.onTypeFormatManager = new OnTypeFormatManager(); + this.documentLinkManager = new DocumentLinkManager(); + this.documentColorManager = new DocumentColorManager(); + this.foldingRangeManager = new FoldingRangeManager(); + this.renameManager = new RenameManager(); + this.formatManager = new FormatManager(); + this.codeActionManager = new CodeActionManager(); + this.workspaceSymbolsManager = new WorkspaceSymbolManager(); + this.formatRangeManager = new FormatRangeManager(); + this.hoverManager = new HoverManager(); + this.signatureManager = new SignatureManager(); + this.documentSymbolManager = new DocumentSymbolManager(); + this.documentHighlightManager = new DocumentHighlightManager(); + this.definitionManager = new DefinitionManager(); + this.declarationManager = new DeclarationManager(); + this.typeDefinitionManager = new TypeDefinitionManager(); + this.referenceManager = new ReferenceManager(); + this.implementationManager = new ImplementationManager(); + this.codeLensManager = new CodeLensManager(); + this.selectionRangeManager = new SelectionRangeManager(); + this.callHierarchyManager = new CallHierarchyManager(); + this.semanticTokensManager = new SemanticTokensManager(); + this.semanticTokensRangeManager = new SemanticTokensRangeManager(); + this.linkedEditingManager = new LinkedEditingRangeManager(); + this.cancelTokenSource = new import_vscode_languageserver_protocol46.CancellationTokenSource(); + } + hasFormatProvider(doc) { + if (this.formatManager.hasProvider(doc)) { + return true; + } + if (this.formatRangeManager.hasProvider(doc)) { + return true; + } + return false; + } + registerOnTypeFormattingEditProvider(selector, provider, triggerCharacters) { + return this.onTypeFormatManager.register(selector, provider, triggerCharacters); + } + registerCompletionItemProvider(name2, shortcut, selector, provider, triggerCharacters = [], priority, allCommitCharacters) { + selector = typeof selector == "string" ? [{ language: selector }] : selector; + let sources = (init_sources2(), sources_exports).default; + return sources.createLanguageSource(name2, shortcut, selector, provider, triggerCharacters, priority, allCommitCharacters); + } + 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, metadata) { + return this.documentSymbolManager.register(selector, provider, metadata == null ? void 0 : metadata.label); + } + 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(provider) { + if (arguments.length > 1 && typeof arguments[1].provideWorkspaceSymbols === "function") { + provider = arguments[1]; + } + return this.workspaceSymbolsManager.register(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); + } + registerCallHierarchyProvider(selector, provider) { + return this.callHierarchyManager.register(selector, provider); + } + registerDocumentSemanticTokensProvider(selector, provider, legend) { + this._onDidSemanticTokensRefresh.fire(selector); + return this.semanticTokensManager.register(selector, provider, legend, () => { + this._onDidSemanticTokensRefresh.fire(selector); + }); + } + registerDocumentRangeSemanticTokensProvider(selector, provider, legend) { + this._onDidSemanticTokensRefresh.fire(selector); + return this.semanticTokensRangeManager.register(selector, provider, legend); + } + registerLinkedEditingRangeProvider(selector, provider) { + return this.linkedEditingManager.register(selector, provider); + } + shouldTriggerSignatureHelp(document2, triggerCharacter) { + return this.signatureManager.shouldTrigger(document2, triggerCharacter); + } + async getHover(document2, position, token) { + return await this.hoverManager.provideHover(document2, position, token); + } + async getSignatureHelp(document2, position, token, context) { + return await this.signatureManager.provideSignatureHelp(document2, position, token, context); + } + async getDefinition(document2, position, token) { + if (!this.definitionManager.hasProvider(document2)) + return null; + return await this.definitionManager.provideDefinition(document2, position, token); + } + async getDefinitionLinks(document2, position, token) { + if (!this.definitionManager.hasProvider(document2)) + return null; + return await this.definitionManager.provideDefinitionLinks(document2, position, token); + } + async getDeclaration(document2, position, token) { + if (!this.declarationManager.hasProvider(document2)) + return null; + return await this.declarationManager.provideDeclaration(document2, position, token); + } + async getTypeDefinition(document2, position, token) { + if (!this.typeDefinitionManager.hasProvider(document2)) + return null; + return await this.typeDefinitionManager.provideTypeDefinition(document2, position, token); + } + async getImplementation(document2, position, token) { + if (!this.implementationManager.hasProvider(document2)) + return null; + return await this.implementationManager.provideReferences(document2, position, token); + } + async getReferences(document2, context, position, token) { + if (!this.referenceManager.hasProvider(document2)) + return null; + return await this.referenceManager.provideReferences(document2, position, context, token); + } + async getDocumentSymbol(document2, token) { + return await this.documentSymbolManager.provideDocumentSymbols(document2, token); + } + async getSelectionRanges(document2, positions2, token) { + return await this.selectionRangeManager.provideSelectionRanges(document2, positions2, token); + } + async getWorkspaceSymbols(query, token) { + query = query || ""; + return await this.workspaceSymbolsManager.provideWorkspaceSymbols(query, token); + } + async resolveWorkspaceSymbol(symbol, token) { + return await this.workspaceSymbolsManager.resolveWorkspaceSymbol(symbol, token); + } + async prepareRename(document2, position, token) { + return await this.renameManager.prepareRename(document2, position, token); + } + async provideRenameEdits(document2, position, newName, token) { + return await this.renameManager.provideRenameEdits(document2, position, newName, token); + } + async provideDocumentFormattingEdits(document2, options, token) { + if (!this.formatManager.hasProvider(document2)) { + let hasRangeFormater = this.formatRangeManager.hasProvider(document2); + if (!hasRangeFormater) + return null; + let end = document2.positionAt(document2.getText().length); + let range = import_vscode_languageserver_protocol46.Range.create(import_vscode_languageserver_protocol46.Position.create(0, 0), end); + return await this.provideDocumentRangeFormattingEdits(document2, range, options, token); + } + return await this.formatManager.provideDocumentFormattingEdits(document2, options, token); + } + async provideDocumentRangeFormattingEdits(document2, range, options, token) { + if (!this.formatRangeManager.hasProvider(document2)) + return null; + return await this.formatRangeManager.provideDocumentRangeFormattingEdits(document2, range, options, token); + } + async getCodeActions(document2, range, context, token) { + return await this.codeActionManager.provideCodeActions(document2, range, context, token); + } + async getDocumentHighLight(document2, position, token) { + return await this.documentHighlightManager.provideDocumentHighlights(document2, position, token); + } + async getDocumentLinks(document2, token) { + if (!this.documentLinkManager.hasProvider(document2)) { + return null; + } + return await this.documentLinkManager.provideDocumentLinks(document2, token) || []; + } + async resolveDocumentLink(link) { + return await this.documentLinkManager.resolveDocumentLink(link, this.token); + } + async provideDocumentColors(document2, token) { + return await this.documentColorManager.provideDocumentColors(document2, token); + } + async provideFoldingRanges(document2, context, token) { + if (!this.foldingRangeManager.hasProvider(document2)) { + return null; + } + return await this.foldingRangeManager.provideFoldingRanges(document2, context, token); + } + async provideColorPresentations(color, document2, token) { + return await this.documentColorManager.provideColorPresentations(color, document2, token); + } + async getCodeLens(document2, token) { + return await this.codeLensManager.provideCodeLenses(document2, token); + } + async resolveCodeLens(codeLens, token) { + if (codeLens.command != null) + return codeLens; + return await this.codeLensManager.resolveCodeLens(codeLens, token); + } + async resolveCodeAction(codeAction, token) { + return await this.codeActionManager.resolveCodeAction(codeAction, token); + } + async provideDocumentOnTypeEdits(character, document2, position, token) { + return this.onTypeFormatManager.onCharacterType(character, document2, position, token); + } + canFormatOnType(character, document2) { + return this.onTypeFormatManager.getProvider(document2, character) != null; + } + async prepareCallHierarchy(document2, position, token) { + return this.callHierarchyManager.prepareCallHierarchy(document2, position, token); + } + async provideIncomingCalls(document2, item, token) { + return this.callHierarchyManager.provideCallHierarchyIncomingCalls(document2, item, token); + } + async provideOutgoingCalls(document2, item, token) { + return this.callHierarchyManager.provideCallHierarchyOutgoingCalls(document2, item, token); + } + getLegend(document2, range) { + if (range) + return this.semanticTokensRangeManager.getLegend(document2); + return this.semanticTokensManager.getLegend(document2); + } + hasSemanticTokensEdits(document2) { + return this.semanticTokensManager.hasSemanticTokensEdits(document2); + } + async provideDocumentSemanticTokens(document2, token) { + return this.semanticTokensManager.provideDocumentSemanticTokens(document2, token); + } + async provideDocumentSemanticTokensEdits(document2, previousResultId, token) { + return this.semanticTokensManager.provideDocumentSemanticTokensEdits(document2, previousResultId, token); + } + async provideDocumentRangeSemanticTokens(document2, range, token) { + return this.semanticTokensRangeManager.provideDocumentRangeSemanticTokens(document2, range, token); + } + hasLinkedEditing(document2) { + return this.linkedEditingManager.hasProvider(document2); + } + async provideLinkedEdits(document2, position, token) { + return this.linkedEditingManager.provideLinkedEditingRanges(document2, position, token); + } + hasProvider(id, document2) { + switch (id) { + case "formatOnType": + return this.onTypeFormatManager.hasProvider(document2); + case "rename": + return this.renameManager.hasProvider(document2); + case "onTypeEdit": + return this.onTypeFormatManager.hasProvider(document2); + case "documentLink": + return this.documentLinkManager.hasProvider(document2); + case "documentColor": + return this.documentColorManager.hasProvider(document2); + case "foldingRange": + return this.foldingRangeManager.hasProvider(document2); + case "format": + return this.formatManager.hasProvider(document2) || this.formatRangeManager.hasProvider(document2); + case "codeAction": + return this.codeActionManager.hasProvider(document2); + case "workspaceSymbols": + return this.workspaceSymbolsManager.hasProvider(); + case "formatRange": + return this.formatRangeManager.hasProvider(document2); + case "hover": + return this.hoverManager.hasProvider(document2); + case "signature": + return this.signatureManager.hasProvider(document2); + case "documentSymbol": + return this.documentSymbolManager.hasProvider(document2); + case "documentHighlight": + return this.documentHighlightManager.hasProvider(document2); + case "definition": + return this.definitionManager.hasProvider(document2); + case "declaration": + return this.declarationManager.hasProvider(document2); + case "typeDefinition": + return this.typeDefinitionManager.hasProvider(document2); + case "reference": + return this.referenceManager.hasProvider(document2); + case "implementation": + return this.implementationManager.hasProvider(document2); + case "codeLens": + return this.codeLensManager.hasProvider(document2); + case "selectionRange": + return this.selectionRangeManager.hasProvider(document2); + case "callHierarchy": + return this.callHierarchyManager.hasProvider(document2); + case "semanticTokens": + return this.semanticTokensManager.hasProvider(document2); + case "linkedEditing": + return this.linkedEditingManager.hasProvider(document2); + default: + throw new Error(`Invalid provider name: ${id}`); + } + } + createDiagnosticCollection(owner) { + return manager_default.create(owner); + } + get token() { + this.cancelTokenSource = new import_vscode_languageserver_protocol46.CancellationTokenSource(); + return this.cancelTokenSource.token; + } + }; + languages_default = new Languages(); + } +}); + +// src/model/highligher.ts +var Highlighter; +var init_highligher = __esm({ + "src/model/highligher.ts"() { + init_ansiparse(); + init_string(); + Highlighter = class { + constructor() { + this.lines = []; + this.highlights = []; + } + addLine(line, hlGroup) { + if (line.includes("\n")) { + for (let content of line.split(/\r?\n/)) { + this.addLine(content, hlGroup); + } + return; + } + if (hlGroup) { + this.highlights.push({ + lnum: this.lines.length, + colStart: line.match(/^\s*/)[0].length, + colEnd: byteLength(line), + hlGroup + }); + } + if (line.includes("")) { + let res = parseAnsiHighlights(line); + for (let hl of res.highlights) { + let { span, hlGroup: hlGroup2 } = hl; + if (span[0] != span[1]) { + this.highlights.push({ + lnum: this.lines.length, + colStart: span[0], + colEnd: span[1], + hlGroup: hlGroup2 + }); + } + } + this.lines.push(res.line); + } else { + this.lines.push(line); + } + } + addLines(lines) { + this.lines.push(...lines); + } + addTexts(items) { + this.addLines(""); + for (let item of items) { + this.addText(item.text, item.hlGroup); + } + } + addText(text, hlGroup) { + let { lines } = this; + let pre = lines[lines.length - 1] || ""; + if (hlGroup) { + let colStart = byteLength(pre); + this.highlights.push({ + lnum: lines.length ? lines.length - 1 : 0, + colStart, + colEnd: colStart + 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] || ""; + } + 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.lnum, + srcId: -1 + }); + } + } + }; + } +}); + +// node_modules/vscode-languageserver-protocol/node.js +var require_node3 = __commonJS({ + "node_modules/vscode-languageserver-protocol/node.js"(exports2, module2) { + "use strict"; + module2.exports = require_main2(); + } +}); + +// src/util/processes.ts +function terminate(process2, cwd) { + if (process2.killed) + return; + if (isWindows3) { + try { + let options = { + stdio: ["pipe", "pipe", "ignore"] + }; + if (cwd) { + options.cwd = cwd; + } + cp.execFileSync("taskkill", ["/T", "/F", "/PID", process2.pid.toString()], options); + return true; + } catch (err) { + return false; + } + } else if (isLinux2 || isMacintosh2) { + try { + let filepath = (0, import_path16.join)(pluginRoot2, "bin/terminateProcess.sh"); + if (!import_fs14.default.existsSync(filepath)) { + console.error(`"${filepath}" not found`); + return false; + } + let result = cp.spawnSync(filepath, [process2.pid.toString()]); + return result.error ? false : true; + } catch (err) { + return false; + } + } else { + process2.kill("SIGKILL"); + return true; + } +} +var cp, import_path16, import_fs14, isWindows3, isMacintosh2, isLinux2, pluginRoot2; +var init_processes = __esm({ + "src/util/processes.ts"() { + cp = __toModule(require("child_process")); + import_path16 = __toModule(require("path")); + import_fs14 = __toModule(require("fs")); + isWindows3 = process.platform === "win32"; + isMacintosh2 = process.platform === "darwin"; + isLinux2 = process.platform === "linux"; + pluginRoot2 = false ? resolve2(__dirname, "../..") : (0, import_path16.dirname)(__dirname); + } +}); + +// src/language-client/progressPart.ts +var import_vscode_languageserver_protocol47, logger46, ProgressPart; +var init_progressPart = __esm({ + "src/language-client/progressPart.ts"() { + import_vscode_languageserver_protocol47 = __toModule(require_main2()); + init_util(); + init_window(); + "use strict"; + logger46 = require_logger2()("language-client-progressPart"); + ProgressPart = class { + constructor(client, token, done) { + this.client = client; + this.token = token; + this.disposables = []; + this._cancelled = false; + this.statusBarItem = window_default.createStatusBarItem(99, { progress: true }); + this.disposables.push(client.onProgress(import_vscode_languageserver_protocol47.WorkDoneProgress.type, this.token, (value) => { + switch (value.kind) { + case "begin": + this.begin(value); + break; + case "report": + this.report(value); + break; + case "end": + this.done(value.message); + done && done(this); + break; + } + })); + } + begin(params) { + if (typeof this.title === "string") + return; + this.title = params.title; + this.report(params); + } + report(params) { + let statusBarItem = this.statusBarItem; + let parts = []; + if (this.title) + parts.push(this.title); + if (typeof params.percentage == "number") + parts.push(params.percentage.toFixed(0) + "%"); + if (params.message) + parts.push(params.message); + statusBarItem.text = parts.join(" "); + statusBarItem.show(); + } + cancel() { + if (this._cancelled) + return; + this._cancelled = true; + disposeAll(this.disposables); + } + done(message) { + if (this._cancelled) + return; + const statusBarItem = this.statusBarItem; + statusBarItem.text = `${this.title} ${message || "finished"}`; + setTimeout(() => { + statusBarItem.dispose(); + }, 300); + this.cancel(); + } + }; + } +}); + +// src/language-client/utils/async.ts +var import_vscode_languageserver_protocol48, Delayer; +var init_async = __esm({ + "src/language-client/utils/async.ts"() { + import_vscode_languageserver_protocol48 = __toModule(require_main2()); + Delayer = class { + constructor(defaultDelay) { + this.defaultDelay = defaultDelay; + this.timeout = void 0; + this.completionPromise = void 0; + this.onSuccess = void 0; + this.task = void 0; + } + trigger(task, delay = this.defaultDelay) { + this.task = task; + if (delay >= 0) { + this.cancelTimeout(); + } + if (!this.completionPromise) { + this.completionPromise = new Promise((resolve3) => { + this.onSuccess = resolve3; + }).then(() => { + this.completionPromise = void 0; + this.onSuccess = void 0; + let result = this.task(); + this.task = void 0; + return result; + }); + } + if (delay >= 0 || this.timeout === void 0) { + this.timeout = (0, import_vscode_languageserver_protocol48.RAL)().timer.setTimeout(() => { + this.timeout = void 0; + this.onSuccess(void 0); + }, delay >= 0 ? delay : this.defaultDelay); + } + return this.completionPromise; + } + forceDelivery() { + if (!this.completionPromise) { + return void 0; + } + this.cancelTimeout(); + let result = this.task(); + this.completionPromise = void 0; + this.onSuccess = void 0; + this.task = void 0; + return result; + } + isTriggered() { + return this.timeout !== void 0; + } + cancel() { + this.cancelTimeout(); + this.completionPromise = void 0; + } + dispose() { + this.cancelTimeout(); + } + cancelTimeout() { + if (this.timeout !== void 0) { + (0, import_vscode_languageserver_protocol48.RAL)().timer.clearTimeout(this.timeout); + this.timeout = void 0; + } + } + }; + } +}); + +// src/language-client/utils/converter.ts +function convertToTextDocumentItem(document2) { + return { + uri: document2.uri, + languageId: document2.languageId, + version: document2.version, + text: document2.getText() + }; +} +function asCloseTextDocumentParams(document2) { + return { + textDocument: { + uri: document2.uri + } + }; +} +function asChangeTextDocumentParams(document2) { + let result = { + textDocument: { + uri: document2.uri, + version: document2.version + }, + contentChanges: [{ text: document2.getText() }] + }; + return result; +} +function asWillSaveTextDocumentParams(event) { + return { + textDocument: asVersionedTextDocumentIdentifier(event.document), + reason: event.reason + }; +} +function asVersionedTextDocumentIdentifier(textDocument) { + return { + uri: textDocument.uri, + version: textDocument.version + }; +} +function asSaveTextDocumentParams(document2, includeText) { + let result = { + textDocument: asVersionedTextDocumentIdentifier(document2) + }; + if (includeText) { + result.text = document2.getText(); + } + return result; +} +function asUri(resource) { + return resource.toString(); +} +function asCompletionParams(textDocument, position, context) { + return { + textDocument: { + uri: textDocument.uri + }, + position, + context: omit(context, ["option"]) + }; +} +function asTextDocumentPositionParams(textDocument, position) { + return { + textDocument: { + uri: textDocument.uri + }, + position + }; +} +function asSignatureHelpParams(textDocument, position, context) { + return { + textDocument: asTextDocumentIdentifier(textDocument), + position, + context + }; +} +function asTextDocumentIdentifier(textDocument) { + return { + uri: textDocument.uri + }; +} +function asReferenceParams(textDocument, position, options) { + return { + textDocument: { + uri: textDocument.uri + }, + position, + context: { includeDeclaration: options.includeDeclaration } + }; +} +function asDocumentSymbolParams(textDocument) { + return { + textDocument: { + uri: textDocument.uri + } + }; +} +function asCodeLensParams(textDocument) { + return { + textDocument: { + uri: textDocument.uri + } + }; +} +var init_converter = __esm({ + "src/language-client/utils/converter.ts"() { + init_lodash(); + } +}); + +// src/language-client/utils/uuid.ts +function generateUuid() { + return v4_default(); +} +var init_uuid = __esm({ + "src/language-client/utils/uuid.ts"() { + init_esm_node(); + } +}); + +// src/language-client/client.ts +function createConnection(input, output, errorHandler, closeHandler, options) { + let logger113 = new ConsoleLogger(); + let connection = (0, import_vscode_languageserver_protocol49.createProtocolConnection)(input, output, logger113, options); + connection.onError((data) => { + errorHandler(data[0], data[1], data[2]); + }); + connection.onClose(closeHandler); + let result = { + listen: () => connection.listen(), + sendRequest: (type, ...params) => connection.sendRequest(string(type) ? type : type.method, ...params), + onRequest: (type, handler) => connection.onRequest(string(type) ? type : type.method, handler), + sendNotification: (type, params) => connection.sendNotification(string(type) ? type : type.method, params), + onNotification: (type, handler) => connection.onNotification(string(type) ? type : type.method, handler), + onProgress: connection.onProgress, + sendProgress: connection.sendProgress, + trace: (value, tracer, sendNotificationOrTraceOptions) => { + const defaultTraceOptions = { + sendNotification: false, + traceFormat: import_vscode_languageserver_protocol49.TraceFormat.Text + }; + if (sendNotificationOrTraceOptions === void 0) { + connection.trace(value, tracer, defaultTraceOptions); + } else if (boolean(sendNotificationOrTraceOptions)) { + connection.trace(value, tracer, sendNotificationOrTraceOptions); + } else { + connection.trace(value, tracer, sendNotificationOrTraceOptions); + } + }, + initialize: (params) => connection.sendRequest(import_vscode_languageserver_protocol49.InitializeRequest.type, params), + shutdown: () => connection.sendRequest(import_vscode_languageserver_protocol49.ShutdownRequest.type, void 0), + exit: () => connection.sendNotification(import_vscode_languageserver_protocol49.ExitNotification.type), + onLogMessage: (handler) => connection.onNotification(import_vscode_languageserver_protocol49.LogMessageNotification.type, handler), + onShowMessage: (handler) => connection.onNotification(import_vscode_languageserver_protocol49.ShowMessageNotification.type, handler), + onTelemetry: (handler) => connection.onNotification(import_vscode_languageserver_protocol49.TelemetryEventNotification.type, handler), + didChangeConfiguration: (params) => connection.sendNotification(import_vscode_languageserver_protocol49.DidChangeConfigurationNotification.type, params), + didChangeWatchedFiles: (params) => connection.sendNotification(import_vscode_languageserver_protocol49.DidChangeWatchedFilesNotification.type, params), + didOpenTextDocument: (params) => connection.sendNotification(import_vscode_languageserver_protocol49.DidOpenTextDocumentNotification.type, params), + didChangeTextDocument: (params) => connection.sendNotification(import_vscode_languageserver_protocol49.DidChangeTextDocumentNotification.type, params), + didCloseTextDocument: (params) => connection.sendNotification(import_vscode_languageserver_protocol49.DidCloseTextDocumentNotification.type, params), + didSaveTextDocument: (params) => connection.sendNotification(import_vscode_languageserver_protocol49.DidSaveTextDocumentNotification.type, params), + onDiagnostics: (handler) => connection.onNotification(import_vscode_languageserver_protocol49.PublishDiagnosticsNotification.type, handler), + dispose: () => connection.dispose() + }; + return result; +} +function ensure(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_path17, import_vscode_languageserver_protocol49, import_os7, logger47, ConsoleLogger, NullLogger, ErrorAction, CloseAction, DefaultErrorHandler, RevealOutputChannelOn, State2, ClientState, SupportedSymbolKinds, SupportedCompletionItemKinds, SupportedSymbolTags, DynamicFeature, DocumentNotifications, DidOpenTextDocumentFeature, DidCloseTextDocumentFeature, DidChangeTextDocumentFeature, WillSaveFeature, WillSaveWaitUntilFeature, DidSaveTextDocumentFeature, FileSystemWatcherFeature, TextDocumentFeature, WorkspaceFeature, CompletionItemFeature, HoverFeature, SignatureHelpFeature, DefinitionFeature, ReferencesFeature, DocumentHighlightFeature, DocumentSymbolFeature, WorkspaceSymbolFeature, CodeActionFeature, CodeLensFeature, DocumentFormattingFeature, DocumentRangeFormattingFeature, DocumentOnTypeFormattingFeature, RenameFeature, DocumentLinkFeature, ConfigurationFeature, ExecuteCommandFeature, MessageTransports, OnReady, BaseLanguageClient; +var init_client = __esm({ + "src/language-client/client.ts"() { + import_path17 = __toModule(require("path")); + import_vscode_languageserver_protocol49 = __toModule(require_main2()); + init_esm2(); + init_commands2(); + init_languages(); + init_fs(); + init_is(); + init_lodash(); + init_window(); + init_workspace(); + init_sources2(); + init_progressPart(); + init_async(); + import_os7 = __toModule(require("os")); + init_converter(); + init_uuid(); + logger47 = require_logger2()("language-client-client"); + ConsoleLogger = class { + error(message) { + logger47.error(message); + } + warn(message) { + logger47.warn(message); + } + info(message) { + logger47.info(message); + } + log(message) { + logger47.log(message); + } + }; + NullLogger = class { + error(_message) { + } + warn(_message) { + } + info(_message) { + } + log(_message) { + } + }; + (function(ErrorAction2) { + ErrorAction2[ErrorAction2["Continue"] = 1] = "Continue"; + ErrorAction2[ErrorAction2["Shutdown"] = 2] = "Shutdown"; + })(ErrorAction || (ErrorAction = {})); + (function(CloseAction2) { + CloseAction2[CloseAction2["DoNotRestart"] = 1] = "DoNotRestart"; + CloseAction2[CloseAction2["Restart"] = 2] = "Restart"; + })(CloseAction || (CloseAction = {})); + DefaultErrorHandler = class { + constructor(name2, maxRestartCount) { + this.name = name2; + this.maxRestartCount = maxRestartCount; + this.restarts = []; + } + error(_error, _message, count) { + if (count && count <= 3) { + return 1; + } + return 2; + } + closed() { + this.restarts.push(Date.now()); + if (this.restarts.length < this.maxRestartCount) { + return 2; + } else { + let diff = this.restarts[this.restarts.length - 1] - this.restarts[0]; + if (diff <= 3 * 60 * 1e3) { + window_default.showMessage(`The "${this.name}" server crashed ${this.maxRestartCount} times in the last 3 minutes. The server will not be restarted.`, "error"); + return 1; + } else { + this.restarts.shift(); + return 2; + } + } + } + }; + (function(RevealOutputChannelOn2) { + RevealOutputChannelOn2[RevealOutputChannelOn2["Info"] = 1] = "Info"; + RevealOutputChannelOn2[RevealOutputChannelOn2["Warn"] = 2] = "Warn"; + RevealOutputChannelOn2[RevealOutputChannelOn2["Error"] = 3] = "Error"; + RevealOutputChannelOn2[RevealOutputChannelOn2["Never"] = 4] = "Never"; + })(RevealOutputChannelOn || (RevealOutputChannelOn = {})); + (function(State3) { + State3[State3["Stopped"] = 1] = "Stopped"; + State3[State3["Running"] = 2] = "Running"; + State3[State3["Starting"] = 3] = "Starting"; + })(State2 || (State2 = {})); + (function(ClientState2) { + ClientState2[ClientState2["Initial"] = 0] = "Initial"; + ClientState2[ClientState2["Starting"] = 1] = "Starting"; + ClientState2[ClientState2["StartFailed"] = 2] = "StartFailed"; + ClientState2[ClientState2["Running"] = 3] = "Running"; + ClientState2[ClientState2["Stopping"] = 4] = "Stopping"; + ClientState2[ClientState2["Stopped"] = 5] = "Stopped"; + })(ClientState || (ClientState = {})); + SupportedSymbolKinds = [ + import_vscode_languageserver_protocol49.SymbolKind.File, + import_vscode_languageserver_protocol49.SymbolKind.Module, + import_vscode_languageserver_protocol49.SymbolKind.Namespace, + import_vscode_languageserver_protocol49.SymbolKind.Package, + import_vscode_languageserver_protocol49.SymbolKind.Class, + import_vscode_languageserver_protocol49.SymbolKind.Method, + import_vscode_languageserver_protocol49.SymbolKind.Property, + import_vscode_languageserver_protocol49.SymbolKind.Field, + import_vscode_languageserver_protocol49.SymbolKind.Constructor, + import_vscode_languageserver_protocol49.SymbolKind.Enum, + import_vscode_languageserver_protocol49.SymbolKind.Interface, + import_vscode_languageserver_protocol49.SymbolKind.Function, + import_vscode_languageserver_protocol49.SymbolKind.Variable, + import_vscode_languageserver_protocol49.SymbolKind.Constant, + import_vscode_languageserver_protocol49.SymbolKind.String, + import_vscode_languageserver_protocol49.SymbolKind.Number, + import_vscode_languageserver_protocol49.SymbolKind.Boolean, + import_vscode_languageserver_protocol49.SymbolKind.Array, + import_vscode_languageserver_protocol49.SymbolKind.Object, + import_vscode_languageserver_protocol49.SymbolKind.Key, + import_vscode_languageserver_protocol49.SymbolKind.Null, + import_vscode_languageserver_protocol49.SymbolKind.EnumMember, + import_vscode_languageserver_protocol49.SymbolKind.Struct, + import_vscode_languageserver_protocol49.SymbolKind.Event, + import_vscode_languageserver_protocol49.SymbolKind.Operator, + import_vscode_languageserver_protocol49.SymbolKind.TypeParameter + ]; + SupportedCompletionItemKinds = [ + import_vscode_languageserver_protocol49.CompletionItemKind.Text, + import_vscode_languageserver_protocol49.CompletionItemKind.Method, + import_vscode_languageserver_protocol49.CompletionItemKind.Function, + import_vscode_languageserver_protocol49.CompletionItemKind.Constructor, + import_vscode_languageserver_protocol49.CompletionItemKind.Field, + import_vscode_languageserver_protocol49.CompletionItemKind.Variable, + import_vscode_languageserver_protocol49.CompletionItemKind.Class, + import_vscode_languageserver_protocol49.CompletionItemKind.Interface, + import_vscode_languageserver_protocol49.CompletionItemKind.Module, + import_vscode_languageserver_protocol49.CompletionItemKind.Property, + import_vscode_languageserver_protocol49.CompletionItemKind.Unit, + import_vscode_languageserver_protocol49.CompletionItemKind.Value, + import_vscode_languageserver_protocol49.CompletionItemKind.Enum, + import_vscode_languageserver_protocol49.CompletionItemKind.Keyword, + import_vscode_languageserver_protocol49.CompletionItemKind.Snippet, + import_vscode_languageserver_protocol49.CompletionItemKind.Color, + import_vscode_languageserver_protocol49.CompletionItemKind.File, + import_vscode_languageserver_protocol49.CompletionItemKind.Reference, + import_vscode_languageserver_protocol49.CompletionItemKind.Folder, + import_vscode_languageserver_protocol49.CompletionItemKind.EnumMember, + import_vscode_languageserver_protocol49.CompletionItemKind.Constant, + import_vscode_languageserver_protocol49.CompletionItemKind.Struct, + import_vscode_languageserver_protocol49.CompletionItemKind.Event, + import_vscode_languageserver_protocol49.CompletionItemKind.Operator, + import_vscode_languageserver_protocol49.CompletionItemKind.TypeParameter + ]; + SupportedSymbolTags = [ + import_vscode_languageserver_protocol49.SymbolTag.Deprecated + ]; + (function(DynamicFeature3) { + function is(value) { + let candidate = value; + return candidate && func(candidate.register) && func(candidate.unregister) && func(candidate.dispose) && candidate.registrationType !== void 0; + } + DynamicFeature3.is = is; + })(DynamicFeature || (DynamicFeature = {})); + DocumentNotifications = class { + 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_default.match(selector, textDocument) > 0) { + return true; + } + } + return false; + } + register(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, (data2) => this._client.sendNotification(this._type, this._createParams(data2))); + } 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 = void 0; + } + } + dispose() { + this._selectors.clear(); + if (this._listener) { + this._listener.dispose(); + this._listener = void 0; + } + } + getProvider(document2) { + for (const selector of this._selectors.values()) { + if (workspace_default.match(selector, document2)) { + return { + send: (data) => { + this.callback(data); + } + }; + } + } + return void 0; + } + }; + DidOpenTextDocumentFeature = class extends DocumentNotifications { + constructor(client, _syncedDocuments) { + super(client, workspace_default.onDidOpenTextDocument, import_vscode_languageserver_protocol49.DidOpenTextDocumentNotification.type, client.clientOptions.middleware.didOpen, (textDocument) => { + return { textDocument: convertToTextDocumentItem(textDocument) }; + }, DocumentNotifications.textDocumentFilter); + this._syncedDocuments = _syncedDocuments; + } + get registrationType() { + return import_vscode_languageserver_protocol49.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({ + id: generateUuid(), + registerOptions: { documentSelector } + }); + } + } + register(data) { + super.register(data); + if (!data.registerOptions.documentSelector) { + return; + } + let documentSelector = data.registerOptions.documentSelector; + workspace_default.textDocuments.forEach((textDocument) => { + let uri = textDocument.uri.toString(); + if (this._syncedDocuments.has(uri)) { + return; + } + if (workspace_default.match(documentSelector, textDocument) > 0) { + let middleware = this._client.clientOptions.middleware; + let didOpen = (textDocument2) => { + this._client.sendNotification(this._type, this._createParams(textDocument2)); + }; + 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); + } + }; + DidCloseTextDocumentFeature = class extends DocumentNotifications { + constructor(client, _syncedDocuments) { + super(client, workspace_default.onDidCloseTextDocument, import_vscode_languageserver_protocol49.DidCloseTextDocumentNotification.type, client.clientOptions.middleware.didClose, (textDocument) => asCloseTextDocumentParams(textDocument), DocumentNotifications.textDocumentFilter); + this._syncedDocuments = _syncedDocuments; + } + get registrationType() { + return import_vscode_languageserver_protocol49.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({ + id: generateUuid(), + registerOptions: { documentSelector } + }); + } + } + notificationSent(textDocument) { + super.notificationSent(textDocument); + this._syncedDocuments.delete(textDocument.uri.toString()); + } + unregister(id) { + let selector = this._selectors.get(id); + super.unregister(id); + let selectors = this._selectors.values(); + this._syncedDocuments.forEach((textDocument) => { + if (workspace_default.match(selector, textDocument) > 0 && !this._selectorFilter(selectors, textDocument)) { + let middleware = this._client.clientOptions.middleware; + let didClose = (textDocument2) => { + this._client.sendNotification(this._type, this._createParams(textDocument2)); + }; + this._syncedDocuments.delete(textDocument.uri.toString()); + if (middleware.didClose) { + middleware.didClose(textDocument, didClose); + } else { + didClose(textDocument); + } + } + }); + } + }; + DidChangeTextDocumentFeature = class { + constructor(_client) { + this._client = _client; + this._changeData = new Map(); + } + get registrationType() { + return import_vscode_languageserver_protocol49.DidChangeTextDocumentNotification.type; + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "textDocument"), "synchronization").dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; + if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.change !== void 0 && textDocumentSyncOptions.change !== import_vscode_languageserver_protocol49.TextDocumentSyncKind.None) { + this.register({ + id: generateUuid(), + registerOptions: Object.assign({}, { documentSelector }, { syncKind: textDocumentSyncOptions.change }) + }); + } + } + register(data) { + if (!data.registerOptions.documentSelector) { + return; + } + if (!this._listener) { + this._listener = workspace_default.onDidChangeTextDocument(this.callback, this); + } + this._changeData.set(data.id, { + documentSelector: data.registerOptions.documentSelector, + syncKind: data.registerOptions.syncKind + }); + } + callback(event) { + if (event.contentChanges.length === 0) { + return; + } + let doc = workspace_default.getDocument(event.textDocument.uri); + if (!doc) + return; + let { textDocument } = doc; + for (const changeData of this._changeData.values()) { + if (workspace_default.match(changeData.documentSelector, textDocument) > 0) { + let middleware = this._client.clientOptions.middleware; + if (changeData.syncKind === import_vscode_languageserver_protocol49.TextDocumentSyncKind.Incremental) { + if (middleware.didChange) { + middleware.didChange(event, () => this._client.sendNotification(import_vscode_languageserver_protocol49.DidChangeTextDocumentNotification.type, omit(event, ["bufnr", "original"]))); + } else { + this._client.sendNotification(import_vscode_languageserver_protocol49.DidChangeTextDocumentNotification.type, omit(event, ["bufnr", "original"])); + } + } else if (changeData.syncKind === import_vscode_languageserver_protocol49.TextDocumentSyncKind.Full) { + let didChange = (event2) => { + let { textDocument: textDocument2 } = workspace_default.getDocument(event2.textDocument.uri); + this._client.sendNotification(import_vscode_languageserver_protocol49.DidChangeTextDocumentNotification.type, asChangeTextDocumentParams(textDocument2)); + }; + 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 = void 0; + } + } + dispose() { + this._changeData.clear(); + if (this._listener) { + this._listener.dispose(); + this._listener = void 0; + } + } + getProvider(document2) { + for (const changeData of this._changeData.values()) { + if (workspace_default.match(changeData.documentSelector, document2)) { + return { + send: (event) => { + this.callback(event); + } + }; + } + } + return void 0; + } + }; + WillSaveFeature = class extends DocumentNotifications { + constructor(client) { + super(client, workspace_default.onWillSaveTextDocument, import_vscode_languageserver_protocol49.WillSaveTextDocumentNotification.type, client.clientOptions.middleware.willSave, (willSaveEvent) => asWillSaveTextDocumentParams(willSaveEvent), (selectors, willSaveEvent) => DocumentNotifications.textDocumentFilter(selectors, willSaveEvent.document)); + } + get registrationType() { + return import_vscode_languageserver_protocol49.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({ + id: generateUuid(), + registerOptions: { documentSelector } + }); + } + } + }; + WillSaveWaitUntilFeature = class { + constructor(_client) { + this._client = _client; + this._selectors = new Map(); + } + get registrationType() { + return import_vscode_languageserver_protocol49.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({ + id: generateUuid(), + registerOptions: { documentSelector } + }); + } + } + register(data) { + if (!data.registerOptions.documentSelector) { + return; + } + if (!this._listener) { + this._listener = workspace_default.onWillSaveTextDocument(this.callback, this); + } + this._selectors.set(data.id, data.registerOptions.documentSelector); + } + callback(event) { + if (DocumentNotifications.textDocumentFilter(this._selectors.values(), event.document)) { + let middleware = this._client.clientOptions.middleware; + let willSaveWaitUntil = (event2) => { + return this._client.sendRequest(import_vscode_languageserver_protocol49.WillSaveTextDocumentWaitUntilRequest.type, asWillSaveTextDocumentParams(event2)).then((edits) => { + return edits ? edits : []; + }, (e) => { + window_default.showMessage(`Error on willSaveWaitUntil: ${e}`, "error"); + logger47.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 = void 0; + } + } + dispose() { + this._selectors.clear(); + if (this._listener) { + this._listener.dispose(); + this._listener = void 0; + } + } + }; + DidSaveTextDocumentFeature = class extends DocumentNotifications { + constructor(client) { + super(client, workspace_default.onDidSaveTextDocument, import_vscode_languageserver_protocol49.DidSaveTextDocumentNotification.type, client.clientOptions.middleware.didSave, (textDocument) => asSaveTextDocumentParams(textDocument, this._includeText), DocumentNotifications.textDocumentFilter); + this._includeText = false; + } + get registrationType() { + return import_vscode_languageserver_protocol49.DidSaveTextDocumentNotification.type; + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "textDocument"), "synchronization").didSave = true; + } + initialize(capabilities, documentSelector) { + const textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; + if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.save) { + const saveOptions = typeof textDocumentSyncOptions.save === "boolean" ? { includeText: false } : { includeText: !!textDocumentSyncOptions.save.includeText }; + this.register({ + id: generateUuid(), + registerOptions: Object.assign({}, { documentSelector }, saveOptions) + }); + } + } + register(data) { + this._includeText = !!data.registerOptions.includeText; + super.register(data); + } + }; + FileSystemWatcherFeature = class { + constructor(_client, _notifyFileEvent) { + this._notifyFileEvent = _notifyFileEvent; + this._watchers = new Map(); + } + get registrationType() { + return import_vscode_languageserver_protocol49.DidChangeWatchedFilesNotification.type; + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "workspace"), "didChangeWatchedFiles").dynamicRegistration = true; + } + initialize(_capabilities, _documentSelector) { + } + register(data) { + if (!Array.isArray(data.registerOptions.watchers)) { + return; + } + let disposables = []; + for (let watcher of data.registerOptions.watchers) { + if (!string(watcher.globPattern)) { + continue; + } + let watchCreate = true, watchChange = true, watchDelete = true; + if (watcher.kind != null) { + watchCreate = (watcher.kind & import_vscode_languageserver_protocol49.WatchKind.Create) !== 0; + watchChange = (watcher.kind & import_vscode_languageserver_protocol49.WatchKind.Change) != 0; + watchDelete = (watcher.kind & import_vscode_languageserver_protocol49.WatchKind.Delete) != 0; + } + let fileSystemWatcher = workspace_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: asUri(resource), + type: import_vscode_languageserver_protocol49.FileChangeType.Created + }), null, listeners); + } + if (watchChange) { + fileSystemWatcher.onDidChange((resource) => this._notifyFileEvent({ + uri: asUri(resource), + type: import_vscode_languageserver_protocol49.FileChangeType.Changed + }), null, listeners); + } + if (watchDelete) { + fileSystemWatcher.onDidDelete((resource) => this._notifyFileEvent({ + uri: asUri(resource), + type: import_vscode_languageserver_protocol49.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(); + } + }; + TextDocumentFeature = class { + constructor(_client, _registrationType) { + this._client = _client; + this._registrationType = _registrationType; + this._registrations = new Map(); + } + get registrationType() { + return this._registrationType; + } + register(data) { + if (!data.registerOptions.documentSelector) { + return; + } + let registration = this.registerLanguageProvider(data.registerOptions); + this._registrations.set(data.id, { disposable: registration[0], data, provider: registration[1] }); + } + unregister(id) { + let registration = this._registrations.get(id); + if (registration) { + registration.disposable.dispose(); + } + } + dispose() { + this._registrations.forEach((value) => { + value.disposable.dispose(); + }); + this._registrations.clear(); + } + getRegistration(documentSelector, capability) { + if (!capability) { + return [void 0, void 0]; + } else if (import_vscode_languageserver_protocol49.TextDocumentRegistrationOptions.is(capability)) { + const id = import_vscode_languageserver_protocol49.StaticRegistrationOptions.hasId(capability) ? capability.id : generateUuid(); + const selector = capability.documentSelector || documentSelector; + if (selector) { + return [id, Object.assign({}, capability, { documentSelector: selector })]; + } + } else if (boolean(capability) && capability === true || import_vscode_languageserver_protocol49.WorkDoneProgressOptions.is(capability)) { + if (!documentSelector) { + return [void 0, void 0]; + } + let options = boolean(capability) && capability === true ? { documentSelector } : Object.assign({}, capability, { documentSelector }); + return [generateUuid(), options]; + } + return [void 0, void 0]; + } + getRegistrationOptions(documentSelector, capability) { + if (!documentSelector || !capability) { + return void 0; + } + return boolean(capability) && capability === true ? { documentSelector } : Object.assign({}, capability, { documentSelector }); + } + getProvider(textDocument) { + for (const registration of this._registrations.values()) { + let selector = registration.data.registerOptions.documentSelector; + if (selector !== null && workspace_default.match(selector, textDocument) > 0) { + return registration.provider; + } + } + return void 0; + } + getAllProviders() { + const result = []; + for (const item of this._registrations.values()) { + result.push(item.provider); + } + return result; + } + }; + WorkspaceFeature = class { + constructor(_client, _registrationType) { + this._client = _client; + this._registrationType = _registrationType; + this._registrations = new Map(); + } + get registrationType() { + return this._registrationType; + } + register(data) { + const registration = this.registerLanguageProvider(data.registerOptions); + this._registrations.set(data.id, { disposable: registration[0], provider: registration[1] }); + } + unregister(id) { + const registration = this._registrations.get(id); + if (registration) + registration.disposable.dispose(); + } + dispose() { + this._registrations.forEach((value) => { + value.disposable.dispose(); + }); + this._registrations.clear(); + } + getProviders() { + const result = []; + for (const registration of this._registrations.values()) { + result.push(registration.provider); + } + return result; + } + }; + CompletionItemFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.CompletionRequest.type); + } + fillClientCapabilities(capabilities) { + let snippetSupport = this._client.clientOptions.disableSnippetCompletion !== true; + let completion = ensure(ensure(capabilities, "textDocument"), "completion"); + completion.dynamicRegistration = true; + completion.contextSupport = true; + completion.completionItem = { + snippetSupport, + commitCharactersSupport: true, + documentationFormat: this._client.supporedMarkupKind, + deprecatedSupport: true, + preselectSupport: true, + insertReplaceSupport: true, + tagSupport: { valueSet: [import_vscode_languageserver_protocol49.CompletionItemTag.Deprecated] }, + resolveSupport: { properties: ["documentation", "detail", "additionalTextEdits"] }, + insertTextModeSupport: { valueSet: [import_vscode_languageserver_protocol49.InsertTextMode.asIs, import_vscode_languageserver_protocol49.InsertTextMode.adjustIndentation] } + }; + completion.completionItemKind = { valueSet: SupportedCompletionItemKinds }; + } + initialize(capabilities, documentSelector) { + this.index = 0; + const options = this.getRegistrationOptions(documentSelector, capabilities.completionProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + let triggerCharacters = options.triggerCharacters || []; + let allCommitCharacters = options.allCommitCharacters || []; + let priority = options.priority; + const provider = { + provideCompletionItems: (document2, position, token, context) => { + const client = this._client; + const middleware = this._client.clientOptions.middleware; + const provideCompletionItems = (document3, position2, context2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.CompletionRequest.type, asCompletionParams(document3, position2, context2), token2).then((result) => result, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.CompletionRequest.type, token2, error, null); + }); + }; + return middleware.provideCompletionItem ? middleware.provideCompletionItem(document2, position, context, token, provideCompletionItems) : provideCompletionItems(document2, position, context, token); + }, + resolveCompletionItem: options.resolveProvider ? (item, token) => { + const client = this._client; + const middleware = this._client.clientOptions.middleware; + const resolveCompletionItem = (item2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.CompletionResolveRequest.type, item2, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.CompletionResolveRequest.type, token2, error, item2); + }); + }; + return middleware.resolveCompletionItem ? middleware.resolveCompletionItem(item, token, resolveCompletionItem) : resolveCompletionItem(item, token); + } : void 0 + }; + let name2 = this._client.id + (this.index ? "-" + this.index : ""); + sources_default.removeSource(name2); + const disposable = languages_default.registerCompletionItemProvider(name2, "LS", options.documentSelector || this._client.clientOptions.documentSelector, provider, triggerCharacters, priority, allCommitCharacters); + this.index = this.index + 1; + return [disposable, provider]; + } + }; + HoverFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.HoverRequest.type); + } + fillClientCapabilities(capabilities) { + const hoverCapability = ensure(ensure(capabilities, "textDocument"), "hover"); + hoverCapability.dynamicRegistration = true; + hoverCapability.contentFormat = this._client.supporedMarkupKind; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.hoverProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideHover: (document2, position, token) => { + const client = this._client; + const provideHover = (document3, position2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.HoverRequest.type, asTextDocumentPositionParams(document3, position2), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.HoverRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideHover ? middleware.provideHover(document2, position, token, provideHover) : provideHover(document2, position, token); + } + }; + return [languages_default.registerHoverProvider(options.documentSelector, provider), provider]; + } + }; + SignatureHelpFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.SignatureHelpRequest.type); + } + fillClientCapabilities(capabilities) { + let config = ensure(ensure(capabilities, "textDocument"), "signatureHelp"); + config.dynamicRegistration = true; + config.contextSupport = true; + config.signatureInformation = { + documentationFormat: this._client.supporedMarkupKind, + activeParameterSupport: true, + parameterInformation: { + labelOffsetSupport: true + } + }; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.signatureHelpProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideSignatureHelp: (document2, position, token, context) => { + const client = this._client; + const providerSignatureHelp = (document3, position2, context2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.SignatureHelpRequest.type, asSignatureHelpParams(document3, position2, context2), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.SignatureHelpRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideSignatureHelp ? middleware.provideSignatureHelp(document2, position, context, token, providerSignatureHelp) : providerSignatureHelp(document2, position, context, token); + } + }; + const triggerCharacters = options.triggerCharacters || []; + const disposable = languages_default.registerSignatureHelpProvider(options.documentSelector, provider, triggerCharacters); + return [disposable, provider]; + } + }; + DefinitionFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.DefinitionRequest.type); + } + fillClientCapabilities(capabilities) { + let definitionSupport = ensure(ensure(capabilities, "textDocument"), "definition"); + definitionSupport.dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.definitionProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideDefinition: (document2, position, token) => { + const client = this._client; + const provideDefinition = (document3, position2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.DefinitionRequest.type, asTextDocumentPositionParams(document3, position2), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.DefinitionRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideDefinition ? middleware.provideDefinition(document2, position, token, provideDefinition) : provideDefinition(document2, position, token); + } + }; + return [languages_default.registerDefinitionProvider(options.documentSelector, provider), provider]; + } + }; + ReferencesFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.ReferencesRequest.type); + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "textDocument"), "references").dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.referencesProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideReferences: (document2, position, options2, token) => { + const client = this._client; + const _providerReferences = (document3, position2, options3, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.ReferencesRequest.type, asReferenceParams(document3, position2, options3), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.ReferencesRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideReferences ? middleware.provideReferences(document2, position, options2, token, _providerReferences) : _providerReferences(document2, position, options2, token); + } + }; + return [languages_default.registerReferencesProvider(options.documentSelector, provider), provider]; + } + }; + DocumentHighlightFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.DocumentHighlightRequest.type); + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "textDocument"), "documentHighlight").dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentHighlightProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideDocumentHighlights: (document2, position, token) => { + const client = this._client; + const _provideDocumentHighlights = (document3, position2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.DocumentHighlightRequest.type, asTextDocumentPositionParams(document3, position2), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.DocumentHighlightRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideDocumentHighlights ? middleware.provideDocumentHighlights(document2, position, token, _provideDocumentHighlights) : _provideDocumentHighlights(document2, position, token); + } + }; + return [languages_default.registerDocumentHighlightProvider(options.documentSelector, provider), provider]; + } + }; + DocumentSymbolFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.DocumentSymbolRequest.type); + } + fillClientCapabilities(capabilities) { + let symbolCapabilities = ensure(ensure(capabilities, "textDocument"), "documentSymbol"); + symbolCapabilities.dynamicRegistration = true; + symbolCapabilities.symbolKind = { + valueSet: SupportedSymbolKinds + }; + symbolCapabilities.hierarchicalDocumentSymbolSupport = true; + symbolCapabilities.tagSupport = { + valueSet: SupportedSymbolTags + }; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentSymbolProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideDocumentSymbols: (document2, token) => { + const client = this._client; + const _provideDocumentSymbols = (document3, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.DocumentSymbolRequest.type, asDocumentSymbolParams(document3), token2).then((data) => { + if (data === null) { + return void 0; + } + if (data.length === 0) { + return []; + } else { + let element = data[0]; + if (import_vscode_languageserver_protocol49.DocumentSymbol.is(element)) { + return data; + } else { + return data; + } + } + }, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.DocumentSymbolRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideDocumentSymbols ? middleware.provideDocumentSymbols(document2, token, _provideDocumentSymbols) : _provideDocumentSymbols(document2, token); + } + }; + const metadata = options.label ? { label: options.label } : void 0; + return [languages_default.registerDocumentSymbolProvider(options.documentSelector, provider, metadata), provider]; + } + }; + WorkspaceSymbolFeature = class extends WorkspaceFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.WorkspaceSymbolRequest.type); + } + fillClientCapabilities(capabilities) { + let symbolCapabilities = ensure(ensure(capabilities, "workspace"), "symbol"); + symbolCapabilities.dynamicRegistration = true; + symbolCapabilities.symbolKind = { + valueSet: SupportedSymbolKinds + }; + symbolCapabilities.tagSupport = { + valueSet: SupportedSymbolTags + }; + } + initialize(capabilities) { + if (!capabilities.workspaceSymbolProvider) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: capabilities.workspaceSymbolProvider === true ? { workDoneProgress: false } : capabilities.workspaceSymbolProvider + }); + } + registerLanguageProvider(_options) { + const provider = { + provideWorkspaceSymbols: (query, token) => { + const client = this._client; + const provideWorkspaceSymbols = (query2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.WorkspaceSymbolRequest.type, { query: query2 }, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.WorkspaceSymbolRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideWorkspaceSymbols ? middleware.provideWorkspaceSymbols(query, token, provideWorkspaceSymbols) : provideWorkspaceSymbols(query, token); + } + }; + return [languages_default.registerWorkspaceSymbolProvider(provider), provider]; + } + }; + CodeActionFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.CodeActionRequest.type); + this.disposables = []; + } + fillClientCapabilities(capabilities) { + const cap = ensure(ensure(capabilities, "textDocument"), "codeAction"); + cap.dynamicRegistration = true; + cap.isPreferredSupport = true; + cap.disabledSupport = true; + cap.dataSupport = true; + cap.honorsChangeAnnotations = false; + cap.resolveSupport = { + properties: ["edit"] + }; + cap.codeActionLiteralSupport = { + codeActionKind: { + valueSet: [ + import_vscode_languageserver_protocol49.CodeActionKind.Empty, + import_vscode_languageserver_protocol49.CodeActionKind.QuickFix, + import_vscode_languageserver_protocol49.CodeActionKind.Refactor, + import_vscode_languageserver_protocol49.CodeActionKind.RefactorExtract, + import_vscode_languageserver_protocol49.CodeActionKind.RefactorInline, + import_vscode_languageserver_protocol49.CodeActionKind.RefactorRewrite, + import_vscode_languageserver_protocol49.CodeActionKind.Source, + import_vscode_languageserver_protocol49.CodeActionKind.SourceOrganizeImports + ] + } + }; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.codeActionProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const registCommand = (id) => { + if (commands_default.has(id)) + return; + const client = this._client; + const executeCommand = (command, args) => { + const params = { + command, + arguments: args + }; + return client.sendRequest(import_vscode_languageserver_protocol49.ExecuteCommandRequest.type, params).then(void 0, (error) => { + client.handleFailedRequest(import_vscode_languageserver_protocol49.ExecuteCommandRequest.type, void 0, error, void 0); + throw error; + }); + }; + const middleware = client.clientOptions.middleware; + this.disposables.push(commands_default.registerCommand(id, (...args) => { + return middleware.executeCommand ? middleware.executeCommand(id, args, executeCommand) : executeCommand(id, args); + }, null, true)); + }; + const provider = { + provideCodeActions: (document2, range, context, token) => { + const client = this._client; + const _provideCodeActions = (document3, range2, context2, token2) => { + const params = { + textDocument: { + uri: document3.uri + }, + range: range2, + context: context2 + }; + return client.sendRequest(import_vscode_languageserver_protocol49.CodeActionRequest.type, params, token2).then((values) => { + if (values === null) { + return void 0; + } + values.forEach((val) => { + var _a2; + let cmd = import_vscode_languageserver_protocol49.Command.is(val) ? val.command : (_a2 = val.command) == null ? void 0 : _a2.command; + if (cmd && !commands_default.has(cmd)) + registCommand(cmd); + }); + return values; + }, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.CodeActionRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideCodeActions ? middleware.provideCodeActions(document2, range, context, token, _provideCodeActions) : _provideCodeActions(document2, range, context, token); + }, + resolveCodeAction: options.resolveProvider ? (item, token) => { + const client = this._client; + const middleware = this._client.clientOptions.middleware; + const resolveCodeAction = (item2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.CodeActionResolveRequest.type, item2, token2).then((values) => values, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.CodeActionResolveRequest.type, token2, error, item2); + }); + }; + return middleware.resolveCodeAction ? middleware.resolveCodeAction(item, token, resolveCodeAction) : resolveCodeAction(item, token); + } : void 0 + }; + return [languages_default.registerCodeActionProvider(options.documentSelector, provider, this._client.id, options.codeActionKinds), provider]; + } + dispose() { + this.disposables.forEach((o) => { + o.dispose(); + }); + this.disposables = []; + super.dispose(); + } + }; + CodeLensFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.CodeLensRequest.type); + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "textDocument"), "codeLens").dynamicRegistration = true; + ensure(ensure(capabilities, "workspace"), "codeLens").refreshSupport = true; + } + initialize(capabilities, documentSelector) { + const client = this._client; + client.onRequest(import_vscode_languageserver_protocol49.CodeLensRefreshRequest.type, async () => { + for (const provider of this.getAllProviders()) { + provider.onDidChangeCodeLensEmitter.fire(); + } + }); + const options = this.getRegistrationOptions(documentSelector, capabilities.codeLensProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const emitter = new import_vscode_languageserver_protocol49.Emitter(); + const provider = { + onDidChangeCodeLenses: emitter.event, + provideCodeLenses: (document2, token) => { + const client = this._client; + const provideCodeLenses = (document3, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.CodeLensRequest.type, asCodeLensParams(document3), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.CodeLensRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideCodeLenses ? middleware.provideCodeLenses(document2, token, provideCodeLenses) : provideCodeLenses(document2, token); + }, + resolveCodeLens: options.resolveProvider ? (codeLens, token) => { + const client = this._client; + const resolveCodeLens = (codeLens2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.CodeLensResolveRequest.type, codeLens2, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.CodeLensResolveRequest.type, token2, error, codeLens2); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.resolveCodeLens ? middleware.resolveCodeLens(codeLens, token, resolveCodeLens) : resolveCodeLens(codeLens, token); + } : void 0 + }; + return [languages_default.registerCodeLensProvider(options.documentSelector, provider), { provider, onDidChangeCodeLensEmitter: emitter }]; + } + }; + DocumentFormattingFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.DocumentFormattingRequest.type); + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "textDocument"), "formatting").dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentFormattingProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideDocumentFormattingEdits: (document2, options2, token) => { + const client = this._client; + const provideDocumentFormattingEdits = (document3, options3, token2) => { + const params = { + textDocument: { uri: document3.uri }, + options: options3 + }; + return client.sendRequest(import_vscode_languageserver_protocol49.DocumentFormattingRequest.type, params, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.DocumentFormattingRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideDocumentFormattingEdits ? middleware.provideDocumentFormattingEdits(document2, options2, token, provideDocumentFormattingEdits) : provideDocumentFormattingEdits(document2, options2, token); + } + }; + return [ + languages_default.registerDocumentFormatProvider(options.documentSelector, provider, this._client.clientOptions.formatterPriority), + provider + ]; + } + }; + DocumentRangeFormattingFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.DocumentRangeFormattingRequest.type); + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "textDocument"), "rangeFormatting").dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentRangeFormattingProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideDocumentRangeFormattingEdits: (document2, range, options2, token) => { + const client = this._client; + const provideDocumentRangeFormattingEdits = (document3, range2, options3, token2) => { + const params = { + textDocument: { uri: document3.uri }, + range: range2, + options: options3 + }; + return client.sendRequest(import_vscode_languageserver_protocol49.DocumentRangeFormattingRequest.type, params, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.DocumentRangeFormattingRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideDocumentRangeFormattingEdits ? middleware.provideDocumentRangeFormattingEdits(document2, range, options2, token, provideDocumentRangeFormattingEdits) : provideDocumentRangeFormattingEdits(document2, range, options2, token); + } + }; + return [languages_default.registerDocumentRangeFormatProvider(options.documentSelector, provider), provider]; + } + }; + DocumentOnTypeFormattingFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.DocumentOnTypeFormattingRequest.type); + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "textDocument"), "onTypeFormatting").dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentOnTypeFormattingProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideOnTypeFormattingEdits: (document2, position, ch, options2, token) => { + const client = this._client; + const provideOnTypeFormattingEdits = (document3, position2, ch2, options3, token2) => { + const params = { + textDocument: asVersionedTextDocumentIdentifier(document3), + position: position2, + ch: ch2, + options: options3 + }; + return client.sendRequest(import_vscode_languageserver_protocol49.DocumentOnTypeFormattingRequest.type, params, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.DocumentOnTypeFormattingRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideOnTypeFormattingEdits ? middleware.provideOnTypeFormattingEdits(document2, position, ch, options2, token, provideOnTypeFormattingEdits) : provideOnTypeFormattingEdits(document2, position, ch, options2, token); + } + }; + const moreTriggerCharacter = options.moreTriggerCharacter || []; + const characters = [options.firstTriggerCharacter, ...moreTriggerCharacter]; + return [languages_default.registerOnTypeFormattingEditProvider(options.documentSelector, provider, characters), provider]; + } + }; + RenameFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.RenameRequest.type); + } + fillClientCapabilities(capabilities) { + let rename = ensure(ensure(capabilities, "textDocument"), "rename"); + rename.dynamicRegistration = true; + rename.prepareSupport = true; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.renameProvider); + if (!options) { + return; + } + if (boolean(capabilities.renameProvider)) { + options.prepareProvider = false; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideRenameEdits: (document2, position, newName, token) => { + const client = this._client; + const provideRenameEdits = (document3, position2, newName2, token2) => { + const params = { + textDocument: { uri: document3.uri }, + position: position2, + newName: newName2 + }; + return client.sendRequest(import_vscode_languageserver_protocol49.RenameRequest.type, params, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.RenameRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideRenameEdits ? middleware.provideRenameEdits(document2, position, newName, token, provideRenameEdits) : provideRenameEdits(document2, position, newName, token); + }, + prepareRename: options.prepareProvider ? (document2, position, token) => { + const client = this._client; + const prepareRename = (document3, position2, token2) => { + const params = { + textDocument: asTextDocumentIdentifier(document3), + position: position2 + }; + return client.sendRequest(import_vscode_languageserver_protocol49.PrepareRenameRequest.type, params, token2).then((result) => { + if (import_vscode_languageserver_protocol49.Range.is(result)) { + return result; + } else if (this.isDefaultBehavior(result)) { + return result.defaultBehavior === true ? null : Promise.reject(new Error(`The element can't be renamed.`)); + } else if (result && import_vscode_languageserver_protocol49.Range.is(result.range)) { + return { + range: result.range, + placeholder: result.placeholder + }; + } + return Promise.reject(new Error(`The element can't be renamed.`)); + }, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.PrepareRenameRequest.type, token2, error, void 0); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.prepareRename ? middleware.prepareRename(document2, position, token, prepareRename) : prepareRename(document2, position, token); + } : void 0 + }; + return [languages_default.registerRenameProvider(options.documentSelector, provider), provider]; + } + isDefaultBehavior(value) { + const candidate = value; + return candidate && boolean(candidate.defaultBehavior); + } + }; + DocumentLinkFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol49.DocumentLinkRequest.type); + } + fillClientCapabilities(capabilities) { + const documentLinkCapabilities = ensure(ensure(capabilities, "textDocument"), "documentLink"); + documentLinkCapabilities.dynamicRegistration = true; + documentLinkCapabilities.tooltipSupport = true; + } + initialize(capabilities, documentSelector) { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentLinkProvider); + if (!options) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: options + }); + } + registerLanguageProvider(options) { + const provider = { + provideDocumentLinks: (document2, token) => { + const client = this._client; + const provideDocumentLinks = (document3, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.DocumentLinkRequest.type, { + textDocument: { uri: document3.uri } + }, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.DocumentLinkRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideDocumentLinks ? middleware.provideDocumentLinks(document2, token, provideDocumentLinks) : provideDocumentLinks(document2, token); + }, + resolveDocumentLink: options.resolveProvider ? (link, token) => { + const client = this._client; + let resolveDocumentLink = (link2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol49.DocumentLinkResolveRequest.type, link2, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol49.DocumentLinkResolveRequest.type, token2, error, link2); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.resolveDocumentLink ? middleware.resolveDocumentLink(link, token, resolveDocumentLink) : resolveDocumentLink(link, token); + } : void 0 + }; + return [languages_default.registerDocumentLinkProvider(options.documentSelector, provider), provider]; + } + }; + ConfigurationFeature = class { + constructor(_client) { + this._client = _client; + this._listeners = new Map(); + } + get registrationType() { + return import_vscode_languageserver_protocol49.DidChangeConfigurationNotification.type; + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "workspace"), "didChangeConfiguration").dynamicRegistration = true; + } + initialize() { + var _a2; + let section2 = (_a2 = this._client.clientOptions.synchronize) == null ? void 0 : _a2.configurationSection; + if (section2 !== void 0) { + this.register({ + id: generateUuid(), + registerOptions: { + section: section2 + } + }); + } + } + register(data) { + let { section: section2 } = data.registerOptions; + let disposable = workspace_default.onDidChangeConfiguration((event) => { + if (typeof section2 == "string" && !event.affectsConfiguration(section2)) { + return; + } + if (Array.isArray(section2) && !section2.some((v) => event.affectsConfiguration(v))) { + return; + } + if (section2 != void 0) { + this.onDidChangeConfiguration(data.registerOptions.section); + } + }); + this._listeners.set(data.id, disposable); + if (string(section2) && section2.endsWith(".settings")) { + let settings = this.getConfiguredSettings(section2); + if (!settings || emptyObject(settings)) + return; + } + if (section2 != void 0) { + 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 isConfigured = typeof configurationSection === "string" && configurationSection.startsWith("languageserver."); + let sections; + if (string(configurationSection)) { + sections = [configurationSection]; + } else { + sections = configurationSection; + } + let didChangeConfiguration = (sections2) => { + if (sections2 === void 0) { + this._client.sendNotification(import_vscode_languageserver_protocol49.DidChangeConfigurationNotification.type, { settings: null }); + return; + } + this._client.sendNotification(import_vscode_languageserver_protocol49.DidChangeConfigurationNotification.type, { + settings: isConfigured ? this.getConfiguredSettings(sections2[0]) : this.extractSettingsInformation(sections2) + }); + }; + let middleware = this.getMiddleware(); + middleware ? middleware(sections, didChangeConfiguration) : didChangeConfiguration(sections); + } + getConfiguredSettings(key) { + let len = ".settings".length; + let config = workspace_default.getConfiguration(key.slice(0, -len)); + return config.get("settings", {}); + } + extractSettingsInformation(keys) { + function ensurePath(config, path36) { + let current = config; + for (let i = 0; i < path36.length - 1; i++) { + let obj = current[path36[i]]; + if (!obj) { + obj = Object.create(null); + current[path36[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_default.getConfiguration(key.substr(0, index)).get(key.substr(index + 1)); + } else { + config = workspace_default.getConfiguration(key); + } + if (config) { + let path36 = keys[i].split("."); + ensurePath(result, path36)[path36[path36.length - 1]] = config; + } + } + return result; + } + getMiddleware() { + let middleware = this._client.clientOptions.middleware; + if (middleware.workspace && middleware.workspace.didChangeConfiguration) { + return middleware.workspace.didChangeConfiguration; + } else { + return void 0; + } + } + }; + ExecuteCommandFeature = class { + constructor(_client) { + this._client = _client; + this._commands = new Map(); + } + get registrationType() { + return import_vscode_languageserver_protocol49.ExecuteCommandRequest.type; + } + fillClientCapabilities(capabilities) { + ensure(ensure(capabilities, "workspace"), "executeCommand").dynamicRegistration = true; + } + initialize(capabilities) { + if (!capabilities.executeCommandProvider) { + return; + } + this.register({ + id: generateUuid(), + registerOptions: Object.assign({}, capabilities.executeCommandProvider) + }); + } + register(data) { + const client = this._client; + const middleware = client.clientOptions.middleware; + const executeCommand = (command, args) => { + const params = { + command, + arguments: args + }; + return client.sendRequest(import_vscode_languageserver_protocol49.ExecuteCommandRequest.type, params).then(void 0, (error) => { + client.handleFailedRequest(import_vscode_languageserver_protocol49.ExecuteCommandRequest.type, void 0, error, void 0); + throw error; + }); + }; + if (data.registerOptions.commands) { + let disposables = []; + for (const command of data.registerOptions.commands) { + disposables.push(commands_default.registerCommand(command, (...args) => { + return middleware.executeCommand ? middleware.executeCommand(command, args, executeCommand) : executeCommand(command, args); + }, 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(); + } + }; + (function(MessageTransports2) { + function is(value) { + let candidate = value; + return candidate && import_vscode_languageserver_protocol49.MessageReader.is(value.reader) && import_vscode_languageserver_protocol49.MessageWriter.is(value.writer); + } + MessageTransports2.is = is; + })(MessageTransports || (MessageTransports = {})); + OnReady = class { + 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); + } + }; + BaseLanguageClient = class { + constructor(id, name2, clientOptions) { + this._features = []; + this._dynamicFeatures = new Map(); + var _a2; + this._id = id; + this._name = name2; + if (clientOptions.outputChannel) { + this._outputChannel = clientOptions.outputChannel; + } else { + this._outputChannel = void 0; + } + let disableSnippetCompletion = false; + let suggest = workspace_default.getConfiguration("suggest"); + if (suggest.get("snippetsSupport", true) === false || clientOptions.disableSnippetCompletion) { + disableSnippetCompletion = true; + } + const markdown = { isTrusted: false }; + if (clientOptions.markdown !== void 0 && clientOptions.markdown.isTrusted === true) { + markdown.isTrusted = true; + } + this._clientOptions = { + disableWorkspaceFolders: clientOptions.disableWorkspaceFolders, + disableSnippetCompletion, + disableDynamicRegister: clientOptions.disableDynamicRegister, + disableDiagnostics: clientOptions.disableDiagnostics, + disableCompletion: clientOptions.disableCompletion, + formatterPriority: clientOptions.formatterPriority, + ignoredRootPaths: clientOptions.ignoredRootPaths, + documentSelector: clientOptions.documentSelector || [], + synchronize: clientOptions.synchronize || {}, + diagnosticCollectionName: clientOptions.diagnosticCollectionName, + outputChannelName: clientOptions.outputChannelName || this._id, + revealOutputChannelOn: clientOptions.revealOutputChannelOn || 4, + stdioEncoding: clientOptions.stdioEncoding || "utf8", + initializationOptions: clientOptions.initializationOptions, + initializationFailedHandler: clientOptions.initializationFailedHandler, + progressOnInitialization: !!clientOptions.progressOnInitialization, + errorHandler: clientOptions.errorHandler || this.createDefaultErrorHandler((_a2 = clientOptions.connectionOptions) == null ? void 0 : _a2.maxRestartCount), + middleware: clientOptions.middleware || {}, + workspaceFolder: clientOptions.workspaceFolder, + connectionOptions: clientOptions.connectionOptions, + markdown + }; + this.state = 0; + this._connectionPromise = void 0; + this._resolvedConnection = void 0; + this._initializeResult = void 0; + this._listeners = void 0; + this._providers = void 0; + this._diagnostics = void 0; + this._fileEvents = []; + this._fileEventDelayer = new Delayer(250); + this._onReady = new Promise((resolve3, reject) => { + this._onReadyCallbacks = new OnReady(resolve3, reject); + }); + this._onStop = void 0; + this._stateChangeEmitter = new import_vscode_languageserver_protocol49.Emitter(); + this._trace = import_vscode_languageserver_protocol49.Trace.Off; + this._tracer = { + log: (messageOrDataObject, data) => { + if (string(messageOrDataObject)) { + this.logTrace(messageOrDataObject, data); + } else { + this.logObjectTrace(messageOrDataObject); + } + } + }; + this._syncedDocuments = new Map(); + let preferences = workspace_default.getConfiguration("coc.preferences"); + this._markdownSupport = preferences.get("enableMarkdown", true); + this.registerBuiltinFeatures(); + } + get supporedMarkupKind() { + if (this._markdownSupport) + return [import_vscode_languageserver_protocol49.MarkupKind.Markdown, import_vscode_languageserver_protocol49.MarkupKind.PlainText]; + return [import_vscode_languageserver_protocol49.MarkupKind.PlainText]; + } + 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 === 3) { + return 2; + } else if (this.state === 1) { + return 3; + } else { + return 1; + } + } + get initializeResult() { + return this._initializeResult; + } + sendRequest(type, ...params) { + if (!this.isConnectionActive()) { + throw new Error("Language client is not ready yet"); + } + try { + return this._resolvedConnection.sendRequest(type, ...params); + } catch (error) { + this.error(`Sending request ${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 { + return this._resolvedConnection.onRequest(type, handler); + } catch (error) { + this.error(`Registering request handler ${string(type) ? type : type.method} failed.`, error); + throw error; + } + } + sendNotification(type, params) { + if (!this.isConnectionActive()) { + throw new Error("Language client is not ready yet"); + } + try { + this._resolvedConnection.sendNotification(type, params); + } catch (error) { + this.error(`Sending notification ${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 { + return this._resolvedConnection.onNotification(type, handler); + } catch (error) { + this.error(`Registering notification handler ${string(type) ? type : type.method} failed.`, error); + throw error; + } + } + onProgress(type, token, handler) { + if (!this.isConnectionActive()) { + throw new Error("Language client is not ready yet"); + } + try { + if (type == import_vscode_languageserver_protocol49.WorkDoneProgress.type) { + const handleWorkDoneProgress = this._clientOptions.middleware.handleWorkDoneProgress; + if (handleWorkDoneProgress !== void 0) { + return this._resolvedConnection.onProgress(type, token, (params) => { + handleWorkDoneProgress(token, params, () => handler(params)); + }); + } + } + return this._resolvedConnection.onProgress(type, token, handler); + } catch (error) { + this.error(`Registering progress handler for token ${token} failed.`, error); + throw error; + } + } + sendProgress(type, token, value) { + if (!this.isConnectionActive()) { + throw new Error("Language client is not ready yet"); + } + try { + this._resolvedConnection.sendProgress(type, token, value); + } catch (error) { + this.error(`Sending progress for token ${token} 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 = window_default.createOutputChannel(outputChannelName ? outputChannelName : this._name); + } + return this._outputChannel; + } + get diagnostics() { + return this._diagnostics; + } + createDefaultErrorHandler(maxRestartCount) { + return new DefaultErrorHandler(this._id, maxRestartCount != null ? maxRestartCount : 4); + } + 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 import_vscode_languageserver_protocol49.ResponseError) { + const responseError = data; + return ` Message: ${responseError.message} + Code: ${responseError.code} ${responseError.data ? "\n" + responseError.data.toString() : ""}`; + } + if (data instanceof Error) { + if (string(data.stack)) { + return data.stack; + } + return data.message; + } + if (string(data)) { + return data; + } + return data.toString(); + } + _appendOutput(type, message, data) { + let level = 3; + switch (type) { + case "Info": + level = 1; + break; + case "Warn": + level = 2; + 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 === 0 || this.state === 4 || this.state === 5; + } + needsStop() { + return this.state === 1 || this.state === 3; + } + onReady() { + return this._onReady; + } + get started() { + return this.state != 0; + } + isConnectionActive() { + return this.state === 3 && !!this._resolvedConnection; + } + start() { + if (this._onReadyCallbacks.isUsed) { + this._onReady = new Promise((resolve3, reject) => { + this._onReadyCallbacks = new OnReady(resolve3, reject); + }); + } + this._listeners = []; + this._providers = []; + if (!this._diagnostics) { + let opts = this._clientOptions; + let name2 = opts.diagnosticCollectionName ? opts.diagnosticCollectionName : this._id; + this._diagnostics = languages_default.createDiagnosticCollection(name2); + } + this.state = 1; + this.resolveConnection().then((connection) => { + connection.onLogMessage((message) => { + let kind; + switch (message.type) { + case import_vscode_languageserver_protocol49.MessageType.Error: + kind = "error"; + this.error(message.message); + break; + case import_vscode_languageserver_protocol49.MessageType.Warning: + kind = "warning"; + this.warn(message.message); + break; + case import_vscode_languageserver_protocol49.MessageType.Info: + kind = "info"; + this.info(message.message); + break; + default: + kind = "log"; + this.outputChannel.appendLine(message.message); + } + if (global.hasOwnProperty("__TEST__")) { + console.log(`[${kind}] ${message.message}`); + return; + } + }); + connection.onShowMessage((message) => { + switch (message.type) { + case import_vscode_languageserver_protocol49.MessageType.Error: + window_default.showErrorMessage(message.message); + break; + case import_vscode_languageserver_protocol49.MessageType.Warning: + window_default.showWarningMessage(message.message); + break; + case import_vscode_languageserver_protocol49.MessageType.Info: + window_default.showInformationMessage(message.message); + break; + default: + window_default.showInformationMessage(message.message); + } + }); + connection.onRequest(import_vscode_languageserver_protocol49.ShowMessageRequest.type, (params) => { + let messageFunc; + switch (params.type) { + case import_vscode_languageserver_protocol49.MessageType.Error: + messageFunc = window_default.showErrorMessage.bind(window_default); + break; + case import_vscode_languageserver_protocol49.MessageType.Warning: + messageFunc = window_default.showWarningMessage.bind(window_default); + break; + case import_vscode_languageserver_protocol49.MessageType.Info: + messageFunc = window_default.showInformationMessage.bind(window_default); + break; + default: + messageFunc = window_default.showInformationMessage.bind(window_default); + } + let actions = params.actions || []; + return messageFunc(params.message, ...actions); + }); + connection.onRequest(import_vscode_languageserver_protocol49.ShowDocumentRequest.type, async (params) => { + var _a2; + const showDocument = async (params2) => { + var _a3; + try { + if (params2.external === true) { + await workspace_default.openResource(params2.uri); + return { success: true }; + } else { + if (params2.selection) { + params2.selection.start; + } + await workspace_default.jumpTo(params2.uri, (_a3 = params2.selection) == null ? void 0 : _a3.start); + return { success: true }; + } + } catch (error) { + return { success: true }; + } + }; + const middleware = (_a2 = this._clientOptions.middleware.window) == null ? void 0 : _a2.showDocument; + if (middleware !== void 0) { + return middleware(params, showDocument); + } else { + return showDocument(params); + } + }); + connection.onTelemetry((_data) => { + }); + connection.listen(); + return this.initialize(connection); + }).then(void 0, (error) => { + this.state = 2; + this._onReadyCallbacks.reject(error); + this.error("Starting client failed ", error); + }); + return import_vscode_languageserver_protocol49.Disposable.create(() => { + if (this.needsStop()) { + this.stop(); + } + }); + } + resolveConnection() { + if (!this._connectionPromise) { + this._connectionPromise = this.createConnection(); + } + return this._connectionPromise; + } + resolveRootPath() { + if (this._clientOptions.workspaceFolder) { + return URI.parse(this._clientOptions.workspaceFolder.uri).fsPath; + } + let { ignoredRootPaths } = this._clientOptions; + let config = workspace_default.getConfiguration(this.id); + let rootPatterns = config.get("rootPatterns", []); + let required = config.get("requireRootPattern", false); + let resolved; + if (rootPatterns && rootPatterns.length) { + let doc = workspace_default.getDocument(workspace_default.bufnr); + if (doc && doc.schema == "file") { + let dir = import_path17.default.dirname(URI.parse(doc.uri).fsPath); + resolved = resolveRoot(dir, rootPatterns, workspace_default.cwd); + } + } + if (required && !resolved) + return false; + let rootPath = resolved || workspace_default.rootPath || workspace_default.cwd; + if (rootPath === import_os7.default.homedir() || ignoredRootPaths && ignoredRootPaths.includes(rootPath)) { + this.warn(`Ignored rootPath ${rootPath} of client "${this._id}"`); + return null; + } + return rootPath; + } + initialize(connection) { + this.refreshTrace(connection, false); + let { initializationOptions, progressOnInitialization } = this._clientOptions; + let rootPath = this.resolveRootPath(); + if (rootPath === false) { + console.warn(`required root pattern not found, server not started.`); + return; + } + let initParams = { + processId: process.pid, + rootPath: rootPath ? rootPath : null, + rootUri: rootPath ? asUri(URI.file(rootPath)) : null, + capabilities: this.computeClientCapabilities(), + initializationOptions: func(initializationOptions) ? initializationOptions() : initializationOptions, + trace: import_vscode_languageserver_protocol49.Trace.toString(this._trace), + workspaceFolders: null, + locale: this.getLocale(), + clientInfo: { + name: "coc.nvim", + version: workspace_default.version + } + }; + this.fillInitializeParams(initParams); + if (progressOnInitialization) { + const token = generateUuid(); + initParams.workDoneToken = token; + const part = new ProgressPart(connection, token); + part.begin({ title: `initializing ${this.id}`, kind: "begin" }); + return this.doInitialize(connection, initParams).then((result) => { + part.done(); + return result; + }, (error) => { + part.cancel(); + throw error; + }); + } else { + return this.doInitialize(connection, initParams); + } + } + doInitialize(connection, initParams) { + return connection.initialize(initParams).then((result) => { + this._resolvedConnection = connection; + this._initializeResult = result; + this.state = 3; + let textDocumentSyncOptions = void 0; + if (number(result.capabilities.textDocumentSync)) { + if (result.capabilities.textDocumentSync === import_vscode_languageserver_protocol49.TextDocumentSyncKind.None) { + textDocumentSyncOptions = { + openClose: false, + change: import_vscode_languageserver_protocol49.TextDocumentSyncKind.None, + save: void 0 + }; + } else { + textDocumentSyncOptions = { + openClose: true, + change: result.capabilities.textDocumentSync, + save: { + includeText: false + } + }; + } + } else if (result.capabilities.textDocumentSync != null && result.capabilities.textDocumentSync !== void 0) { + textDocumentSyncOptions = result.capabilities.textDocumentSync; + } + this._capabilities = Object.assign({}, result.capabilities, { + resolvedTextDocumentSync: textDocumentSyncOptions + }); + if (!this._clientOptions.disableDiagnostics) { + connection.onDiagnostics((params) => this.handleDiagnostics(params)); + } + connection.onRequest(import_vscode_languageserver_protocol49.RegistrationRequest.type, (params) => this.handleRegistrationRequest(params)); + connection.onRequest("client/registerFeature", (params) => this.handleRegistrationRequest(params)); + connection.onRequest(import_vscode_languageserver_protocol49.UnregistrationRequest.type, (params) => this.handleUnregistrationRequest(params)); + connection.onRequest("client/unregisterFeature", (params) => this.handleUnregistrationRequest(params)); + connection.onRequest(import_vscode_languageserver_protocol49.ApplyWorkspaceEditRequest.type, (params) => this.handleApplyWorkspaceEdit(params)); + connection.sendNotification(import_vscode_languageserver_protocol49.InitializedNotification.type, {}); + this.hookFileEvents(connection); + this.hookConfigurationChanged(connection); + this.initializeFeatures(connection); + this._onReadyCallbacks.resolve(); + return result; + }).then(void 0, (error) => { + if (this._clientOptions.initializationFailedHandler) { + if (this._clientOptions.initializationFailedHandler(error)) { + this.initialize(connection); + } else { + this.stop(); + this._onReadyCallbacks.reject(error); + } + } else if (error instanceof import_vscode_languageserver_protocol49.ResponseError && error.data && error.data.retry) { + window_default.showPrompt(error.message + " Retry?").then((confirmed) => { + if (confirmed) { + this.initialize(connection); + } else { + this.stop(); + this._onReadyCallbacks.reject(error); + } + }); + } else { + if (error && error.message) { + window_default.showMessage(error.message, "error"); + } + this.error("Server initialization failed.", error); + this.stop(); + this._onReadyCallbacks.reject(error); + } + throw error; + }); + } + stop() { + this._initializeResult = void 0; + if (!this._connectionPromise) { + this.state = 5; + return Promise.resolve(); + } + if (this.state === 4 && this._onStop) { + return this._onStop; + } + this.state = 4; + this.cleanUp(); + return this._onStop = this.resolveConnection().then((connection) => { + return connection.shutdown().then(() => { + connection.exit(); + connection.dispose(); + this.state = 5; + this.cleanUpChannel(); + this._onStop = void 0; + this._connectionPromise = void 0; + this._resolvedConnection = void 0; + }); + }).catch((e) => { + logger47.error("Error on stop languageserver:", e); + this.state = 5; + this.cleanUpChannel(); + this._onStop = void 0; + this._connectionPromise = void 0; + this._resolvedConnection = void 0; + }); + } + cleanUp(channel = true, diagnostics = true) { + if (this._listeners) { + this._listeners.forEach((listener) => listener.dispose()); + this._listeners = void 0; + } + if (this._providers) { + this._providers.forEach((provider) => provider.dispose()); + this._providers = void 0; + } + for (let feature of this._features.values()) { + if (typeof feature.dispose === "function") { + feature.dispose(); + } else { + logger47.error(`Feature can't be disposed`, feature); + } + } + if (this._syncedDocuments) { + this._syncedDocuments.clear(); + } + if (channel) { + this.cleanUpChannel(); + } + if (this._diagnostics) { + if (diagnostics) { + this._diagnostics.dispose(); + this._diagnostics = void 0; + } else { + this._diagnostics.clear(); + } + } + } + cleanUpChannel() { + if (this._outputChannel) { + this._outputChannel.dispose(); + this._outputChannel = void 0; + } + } + notifyFileEvent(event) { + var _a2; + const client = this; + function didChangeWatchedFile(event2) { + client._fileEvents.push(event2); + client._fileEventDelayer.trigger(() => { + client.onReady().then(() => { + client.resolveConnection().then((connection) => { + if (client.isConnectionActive()) { + connection.didChangeWatchedFiles({ changes: client._fileEvents }); + } + client._fileEvents = []; + }); + }, (error) => { + client.error(`Notify file events failed.`, error); + }); + }); + } + const workSpaceMiddleware = (_a2 = this.clientOptions.middleware) == null ? void 0 : _a2.workspace; + (workSpaceMiddleware == null ? void 0 : workSpaceMiddleware.didChangeWatchedFile) ? workSpaceMiddleware.didChangeWatchedFile(event, didChangeWatchedFile) : didChangeWatchedFile(event); + } + handleDiagnostics(params) { + if (!this._diagnostics) { + return; + } + let { uri, diagnostics } = params; + let middleware = this.clientOptions.middleware.handleDiagnostics; + if (middleware) { + middleware(uri, diagnostics, (uri2, diagnostics2) => this.setDiagnostics(uri2, diagnostics2)); + } else { + this.setDiagnostics(uri, diagnostics); + } + } + setDiagnostics(uri, diagnostics) { + var _a2; + if (!this._diagnostics) { + return; + } + const separate = workspace_default.getConfiguration("diagnostic").get("separateRelatedInformationAsDiagnostics"); + if (separate && diagnostics.length > 0) { + const entries = new Map(); + entries.set(uri, diagnostics); + for (const diagnostic of diagnostics) { + if ((_a2 = diagnostic.relatedInformation) == null ? void 0 : _a2.length) { + let message = `${diagnostic.message} Related diagnostics: -`;for(let l of s.relatedInformation){let u=VE.default.basename($.parse(l.location.uri).fsPath),c=l.location.range.start.line;a=`${a} -${u}(line ${c+1}): ${l.message}`;let f=o.get(l.location.uri)||[];f.push(D.Diagnostic.create(l.location.range,l.message,D.DiagnosticSeverity.Hint,s.code,s.source)),o.set(l.location.uri,f)}s.message=a}this._diagnostics.set(Array.from(o))}}else this._diagnostics.set(e,t)}createConnection(){let e=(i,n,o)=>{us.error("connection error:",i,n),this.handleConnectionError(i,n,o)},t=()=>{this.handleConnectionClosed()};return this.createMessageTransports(this._clientOptions.stdioEncoding||"utf8").then(i=>hye(i.reader,i.writer,e,t))}handleConnectionClosed(){if(this.state===4||this.state===5)return;try{this._resolvedConnection&&this._resolvedConnection.dispose()}catch(t){}let e=1;try{e=this._clientOptions.errorHandler.closed()}catch(t){}this._connectionPromise=void 0,this._resolvedConnection=void 0,e===1?(this.error("Connection to server got closed. Server will not be restarted."),this.state=5,this.cleanUp(!1,!0)):e===2&&(this.info("Connection to server got closed. Server will restart."),this.cleanUp(!1,!0),this.state=0,this.start())}restart(){this.cleanUp(!0,!1),this.start()}handleConnectionError(e,t,i){this._clientOptions.errorHandler.error(e,t,i)===2&&(this.error("Connection to server is erroring. Shutting down server."),this.stop())}hookConfigurationChanged(e){b.onDidChangeConfiguration(()=>{this.refreshTrace(e,!0)})}refreshTrace(e,t=!1){let i=b.getConfiguration(this._id),n=D.Trace.Off,o=D.TraceFormat.Text;if(i){let s=i.get("trace.server","off");typeof s=="string"?n=D.Trace.fromString(s):(n=D.Trace.fromString(i.get("trace.server.verbosity","off")),o=D.TraceFormat.fromString(i.get("trace.server.format","text")))}this._trace=n,this._traceFormat=o,e.trace(this._trace,this._tracer,{sendNotification:t,traceFormat:this._traceFormat})}hookFileEvents(e){let t=this._clientOptions.synchronize.fileEvents;if(!t)return;let i;Array.isArray(t)?i=t:i=[t],!!i&&this._dynamicFeatures.get(D.DidChangeWatchedFilesNotification.type.method).registerRaw(Be(),i)}registerFeatures(e){for(let t of e)this.registerFeature(t)}registerFeature(e){if(this._features.push(e),JE.is(e)){let t=e.messages;if(Array.isArray(t))for(let i of t)this._method2Message.set(i.method,i),this._dynamicFeatures.set(i.method,e);else this._method2Message.set(t.method,t),this._dynamicFeatures.set(t.method,e)}}getFeature(e){return this._dynamicFeatures.get(e)}registerBuiltinFeatures(){this.registerFeature(new RH(this)),this.registerFeature(new sH(this,this._syncedDocuments)),this.registerFeature(new lH(this)),this.registerFeature(new uH(this)),this.registerFeature(new cH(this)),this.registerFeature(new fH(this)),this.registerFeature(new aH(this,this._syncedDocuments)),this.registerFeature(new pH(this,e=>this.notifyFileEvent(e))),this._clientOptions.disableCompletion||this.registerFeature(new hH(this)),this.registerFeature(new mH(this)),this.registerFeature(new gH(this)),this.registerFeature(new vH(this)),this.registerFeature(new yH(this)),this.registerFeature(new bH(this)),this.registerFeature(new wH(this)),this.registerFeature(new xH(this)),this.registerFeature(new DH(this)),this.registerFeature(new SH(this)),this.registerFeature(new EH(this)),this.registerFeature(new CH(this)),this.registerFeature(new _H(this)),this.registerFeature(new PH(this)),this.registerFeature(new TH(this)),this.registerFeature(new kH(this))}fillInitializeParams(e){for(let t of this._features)No(t.fillInitializeParams)&&t.fillInitializeParams(e)}computeClientCapabilities(){let e={};re(e,"workspace").applyEdit=!0;let t=re(re(e,"workspace"),"workspaceEdit");t.documentChanges=!0,t.resourceOperations=[D.ResourceOperationKind.Create,D.ResourceOperationKind.Rename,D.ResourceOperationKind.Delete],t.failureHandling=D.FailureHandlingKind.TextOnlyTransactional;let i=re(re(e,"textDocument"),"publishDiagnostics");i.relatedInformation=!0,i.versionSupport=!1,i.tagSupport={valueSet:[D.DiagnosticTag.Unnecessary,D.DiagnosticTag.Deprecated]};for(let n of this._features)n.fillClientCapabilities(e);return e}initializeFeatures(e){let t=this._clientOptions.documentSelector;for(let i of this._features)i.initialize(this._capabilities,t)}handleRegistrationRequest(e){return this.clientOptions.disableDynamicRegister?Promise.resolve():new Promise((t,i)=>{for(let n of e.registrations){let o=this._dynamicFeatures.get(n.method);if(!o){i(new Error(`No feature implementation for ${n.method} found. Registration failed.`));return}let s=n.registerOptions||{};s.documentSelector=s.documentSelector||this._clientOptions.documentSelector;let a={id:n.id,registerOptions:s};o.register(this._method2Message.get(n.method),a)}t()})}handleUnregistrationRequest(e){return new Promise((t,i)=>{for(let n of e.unregisterations){let o=this._dynamicFeatures.get(n.method);if(!o){i(new Error(`No feature implementation for ${n.method} found. Unregistration failed.`));return}o.unregister(n.id)}t()})}handleApplyWorkspaceEdit(e){let t=e.edit,i=new Map;b.textDocuments.forEach(o=>i.set(o.uri.toString(),o));let n=!1;if(t.documentChanges){for(let o of t.documentChanges)if(D.TextDocumentEdit.is(o)&&o.textDocument.version&&o.textDocument.version>=0){let s=i.get(o.textDocument.uri);if(s&&s.version!==o.textDocument.version){n=!0;break}}}return n?Promise.resolve({applied:!1}):b.applyEdit(e.edit).then(o=>({applied:o}))}logFailedRequest(e,t){t instanceof D.ResponseError&&t.code===D.ErrorCodes.RequestCancelled||this.error(`Request ${e.method} failed.`,t)}};var Ea=S(W());"use strict";function IH(r,e){return r[e]===void 0&&(r[e]={}),r[e]}var XE=class extends Ve{constructor(e){super(e,Ea.DocumentColorRequest.type)}fillClientCapabilities(e){IH(IH(e,"textDocument"),"colorProvider").dynamicRegistration=!0}initialize(e,t){let[i,n]=this.getRegistration(t,e.colorProvider);!i||!n||this.register(this.messages,{id:i,registerOptions:n})}registerLanguageProvider(e){let t={provideColorPresentations:(i,n,o)=>{let s=this._client,a=(u,c,f)=>{let p={color:u,textDocument:{uri:c.document.uri},range:c.range};return s.sendRequest(Ea.ColorPresentationRequest.type,p,f).then(d=>d,d=>(s.logFailedRequest(Ea.ColorPresentationRequest.type,d),Promise.resolve(null)))},l=s.clientOptions.middleware;return l.provideColorPresentations?l.provideColorPresentations(i,n,o,a):a(i,n,o)},provideDocumentColors:(i,n)=>{let o=this._client,s=(l,u)=>{let c={textDocument:{uri:l.uri}};return o.sendRequest(Ea.DocumentColorRequest.type,c,u).then(f=>f,f=>(o.logFailedRequest(Ea.ColorPresentationRequest.type,f),Promise.resolve(null)))},a=o.clientOptions.middleware;return a.provideDocumentColors?a.provideDocumentColors(i,n,s):s(i,n)}};return[B.registerDocumentColorProvider(e.documentSelector,t),t]}};var FH=S(W());var lje=U()("languageclient-configuration"),ZE=class{constructor(e){this._client=e;var i;let t=(i=this._client.clientOptions.synchronize)==null?void 0:i.configurationSection;typeof t=="string"&&t.startsWith("languageserver.")&&(this.languageserverSection=t)}fillClientCapabilities(e){e.workspace=e.workspace||{},e.workspace.configuration=!0}initialize(){let e=this._client;e.onRequest(FH.ConfigurationRequest.type,(t,i)=>{let n=s=>{let a=[];for(let l of s.items)a.push(this.getConfiguration(l.scopeUri,l.section));return a},o=e.clientOptions.middleware.workspace;return o&&o.configuration?o.configuration(t,i,n):n(t,i)})}getConfiguration(e,t){let i=null;if(t){this.languageserverSection&&(t=`${this.languageserverSection}.${t}`);let n=t.lastIndexOf(".");if(n===-1)i=b.getConfiguration(void 0,e).get(t,{});else{let o=b.getConfiguration(t.substr(0,n),e);o&&(i=o.get(t.substr(n+1)))}}else{let n=b.getConfiguration(this.languageserverSection,e);i={};for(let o of Object.keys(n))n.has(o)&&(i[o]=QE(n.get(o)))}return i}dispose(){}};function QE(r){if(r){if(Array.isArray(r))return r.map(QE);if(typeof r=="object"){let e=Object.create(null);for(let t in r)Object.prototype.hasOwnProperty.call(r,t)&&(e[t]=QE(r[t]));return e}}return r}var Dv=S(W());"use strict";function AH(r,e){return r[e]===void 0&&(r[e]={}),r[e]}var eC=class extends Ve{constructor(e){super(e,Dv.DeclarationRequest.type)}fillClientCapabilities(e){let t=AH(AH(e,"textDocument"),"declaration");t.dynamicRegistration=!0}initialize(e,t){let[i,n]=this.getRegistration(t,e.declarationProvider);!i||!n||this.register(this.messages,{id:i,registerOptions:n})}registerLanguageProvider(e){let t={provideDeclaration:(i,n,o)=>{let s=this._client,a=(u,c,f)=>s.sendRequest(Dv.DeclarationRequest.type,En(u,c),f).then(p=>p,p=>(s.logFailedRequest(Dv.DeclarationRequest.type,p),Promise.resolve(null))),l=s.clientOptions.middleware;return l.provideDeclaration?l.provideDeclaration(i,n,o,a):a(i,n,o)}};return[B.registerDeclarationProvider(e.documentSelector,t),t]}};var Sv=S(W());"use strict";function OH(r,e){return r[e]===void 0&&(r[e]={}),r[e]}var tC=class extends Ve{constructor(e){super(e,Sv.FoldingRangeRequest.type)}fillClientCapabilities(e){let t=OH(OH(e,"textDocument"),"foldingRange");t.dynamicRegistration=!0,t.rangeLimit=5e3,t.lineFoldingOnly=!0}initialize(e,t){let[i,n]=this.getRegistration(t,e.foldingRangeProvider);!i||!n||this.register(this.messages,{id:i,registerOptions:n})}registerLanguageProvider(e){let t={provideFoldingRanges:(i,n,o)=>{let s=this._client,a=(u,c,f)=>{let p={textDocument:{uri:u.uri}};return s.sendRequest(Sv.FoldingRangeRequest.type,p,f).then(d=>d,d=>(s.logFailedRequest(Sv.FoldingRangeRequest.type,d),Promise.resolve(null)))},l=s.clientOptions.middleware;return l.provideFoldingRanges?l.provideFoldingRanges(i,n,o,a):a(i,n,o)}};return[B.registerFoldingRangeProvider(e.documentSelector,t),t]}};var Ev=S(W());function LH(r,e){return r[e]===void 0&&(r[e]={}),r[e]}var rC=class extends Ve{constructor(e){super(e,Ev.ImplementationRequest.type)}fillClientCapabilities(e){let t=LH(LH(e,"textDocument"),"implementation");t.dynamicRegistration=!0}initialize(e,t){let[i,n]=this.getRegistration(t,e.implementationProvider);!i||!n||this.register(this.messages,{id:i,registerOptions:n})}registerLanguageProvider(e){let t={provideImplementation:(i,n,o)=>{let s=this._client,a=(u,c,f)=>s.sendRequest(Ev.ImplementationRequest.type,En(u,c),f).then(p=>p,p=>(s.logFailedRequest(Ev.ImplementationRequest.type,p),Promise.resolve(null))),l=s.clientOptions.middleware;return l.provideImplementation?l.provideImplementation(i,n,o,a):a(i,n,o)}};return[B.registerImplementationProvider(e.documentSelector,t),t]}};var MH=S(W());"use strict";function gye(r,e){return r[e]===void 0&&(r[e]=Object.create(null)),r[e]}var iC=class{constructor(e){this._client=e;this.activeParts=new Set}fillClientCapabilities(e){gye(e,"window").workDoneProgress=!0}initialize(){let e=this._client,t=n=>{this.activeParts.delete(n)},i=n=>{this.activeParts.add(new zp(this._client,n.token,t))};e.onRequest(MH.WorkDoneProgressCreateRequest.type,i)}dispose(){for(let e of this.activeParts)e.done();this.activeParts.clear()}};var Cv=S(W());function NH(r,e){return r[e]===void 0&&(r[e]={}),r[e]}var nC=class extends Ve{constructor(e){super(e,Cv.TypeDefinitionRequest.type)}fillClientCapabilities(e){let t=NH(NH(e,"textDocument"),"typeDefinition");t.dynamicRegistration=!0}initialize(e,t){let[i,n]=this.getRegistration(t,e.typeDefinitionProvider);!i||!n||this.register(this.messages,{id:i,registerOptions:n})}registerLanguageProvider(e){let t={provideTypeDefinition:(i,n,o)=>{let s=this._client,a=(u,c,f)=>s.sendRequest(Cv.TypeDefinitionRequest.type,En(u,c),f).then(p=>p,p=>(s.logFailedRequest(Cv.TypeDefinitionRequest.type,p),Promise.resolve(null))),l=s.clientOptions.middleware;return l.provideTypeDefinition?l.provideTypeDefinition(i,n,o,a):a(i,n,o)}};return[B.registerTypeDefinitionProvider(e.documentSelector,t),t]}};var Kp=S(W());"use strict";var RUe=U()("language-client-workspaceFolder");function oC(r,e){if(r!==void 0)return r[e]}function qH(r,e){return r.filter(t=>!e.includes(t))}var sC=class{constructor(e){this._client=e;this._listeners=new Map}get messages(){return Kp.DidChangeWorkspaceFoldersNotification.type}asProtocol(e){return e===void 0?null:{uri:e.uri,name:e.name}}fillInitializeParams(e){let t=b.workspaceFolders;this._initialFolders=t,t===void 0?e.workspaceFolders=null:e.workspaceFolders=t.map(i=>this.asProtocol(i)),e.workspaceFolders=b.workspaceFolders}fillClientCapabilities(e){e.workspace=e.workspace||{},e.workspace.workspaceFolders=!0}initialize(e){let t=this._client;t.onRequest(Kp.WorkspaceFoldersRequest.type,o=>{let s=()=>{let l=b.workspaceFolders;return l===void 0?null:l.map(c=>this.asProtocol(c))},a=t.clientOptions.middleware.workspace;return a&&a.workspaceFolders?a.workspaceFolders(o,s):s(o)});let i=oC(oC(oC(e,"workspace"),"workspaceFolders"),"changeNotifications"),n;typeof i=="string"?n=i:i===!0&&(n=Be()),n&&this.register(this.messages,{id:n,registerOptions:void 0})}doSendEvent(e,t){let i={event:{added:e.map(n=>this.asProtocol(n)),removed:t.map(n=>this.asProtocol(n))}};this._client.sendNotification(Kp.DidChangeWorkspaceFoldersNotification.type,i)}sendInitialEvent(e){if(this._initialFolders&&e){let t=qH(this._initialFolders,e),i=qH(e,this._initialFolders);(i.length>0||t.length>0)&&this.doSendEvent(i,t)}else this._initialFolders?this.doSendEvent([],this._initialFolders):e&&this.doSendEvent(e,[])}register(e,t){let i=t.id,n=this._client,o=b.onDidChangeWorkspaceFolders(s=>{let a=u=>{this.doSendEvent(u.added,u.removed)},l=n.clientOptions.middleware.workspace;l&&l.didChangeWorkspaceFolders?l.didChangeWorkspaceFolders(s,a):a(s)});this._listeners.set(i,o),this.sendInitialEvent(b.workspaceFolders)}unregister(e){let t=this._listeners.get(e);t!==void 0&&(this._listeners.delete(e),t.dispose())}dispose(){for(let e of this._listeners.values())e.dispose();this._listeners.clear()}};var _v=S(W());"use strict";function $H(r,e){return r[e]===void 0&&(r[e]={}),r[e]}var aC=class extends Ve{constructor(e){super(e,_v.SelectionRangeRequest.type)}fillClientCapabilities(e){let t=$H($H(e,"textDocument"),"selectionRange");t.dynamicRegistration=!0}initialize(e,t){let[i,n]=this.getRegistration(t,e.selectionRangeProvider);!i||!n||this.register(this.messages,{id:i,registerOptions:n})}registerLanguageProvider(e){let t={provideSelectionRanges:(i,n,o)=>{let s=this._client,a=(u,c,f)=>{let p={textDocument:{uri:u.uri},positions:c};return s.sendRequest(_v.SelectionRangeRequest.type,p,f).then(d=>d,d=>(s.logFailedRequest(_v.SelectionRangeRequest.type,d),Promise.resolve(null)))},l=s.clientOptions.middleware;return l.provideSelectionRanges?l.provideSelectionRanges(i,n,o,a):a(i,n,o)}};return[B.registerSelectionRangeProvider(e.documentSelector,t),t]}};var d6e=Ca.default.ChildProcess,oo=U()("language-client-index"),uC;(function(e){function r(t){return wt(t.command)}e.is=r})(uC||(uC={}));var Gt;(function(r){r[r.stdio=0]="stdio",r[r.ipc=1]="ipc",r[r.pipe=2]="pipe",r[r.socket=3]="socket"})(Gt||(Gt={}));var Pv;(function(e){function r(t){let i=t;return i&&i.kind===3&&hm(i.port)}e.isSocket=r})(Pv||(Pv={}));var cC;(function(e){function r(t){return wt(t.module)}e.is=r})(cC||(cC={}));var fC;(function(e){function r(t){let i=t;return i&&i.writer!==void 0&&i.reader!==void 0}e.is=r})(fC||(fC={}));var pC;(function(e){function r(t){let i=t;return i&&i.process!==void 0&&typeof i.detached=="boolean"}e.is=r})(pC||(pC={}));var Tv=class extends xv{constructor(e,t,i,n,o){let s,a,l,u,c;wt(t)?(s=e,a=t,l=i,u=n,c=!!o):(s=e.toLowerCase(),a=e,l=t,u=i,c=n),c===void 0&&(c=!1),super(s,a,u),this._serverOptions=l,this._forceDebug=c,this.registerProposedFeatures()}stop(){return super.stop().then(()=>{if(this._serverProcess){let e=this._serverProcess;this._serverProcess=void 0,(this._isDetached===void 0||!this._isDetached)&&this.checkProcessDied(e),this._isDetached=void 0}})}get serviceState(){let e=this._state;switch(e){case be.Initial:return ye.Initial;case be.Running:return ye.Running;case be.StartFailed:return ye.StartFailed;case be.Starting:return ye.Starting;case be.Stopped:return ye.Stopped;case be.Stopping:return ye.Stopping;default:return oo.error(`Unknown state: ${e}`),ye.Stopped}}static stateName(e){switch(e){case be.Initial:return"Initial";case be.Running:return"Running";case be.StartFailed:return"StartFailed";case be.Starting:return"Starting";case be.Stopped:return"Stopped";case be.Stopping:return"Stopping";default:return"Unknonw"}}checkProcessDied(e){if(!(!e||global.hasOwnProperty("__TEST__"))){if(global.hasOwnProperty("__TEST__")){process.kill(e.pid,0);return}setTimeout(()=>{try{process.kill(e.pid,0),z4(e)}catch(t){}},2e3)}}handleConnectionClosed(){this._serverProcess=void 0,super.handleConnectionClosed()}createMessageTransports(e){function t(a){return a?Object.assign({},process.env,a):process.env}function i(){let a=process.execArgv;return a?a.some(l=>/^--debug=?/.test(l)||/^--debug-brk=?/.test(l)||/^--inspect=?/.test(l)||/^--inspect-brk=?/.test(l)):!1}let n=this._serverOptions;if(No(n))return n().then(a=>{if(Vp.is(a))return this._isDetached=!!a.detached,a;if(fC.is(a))return this._isDetached=!!a.detached,{reader:new Et.StreamMessageReader(a.reader),writer:new Et.StreamMessageWriter(a.writer)};{let l;return pC.is(a)?(l=a.process,this._isDetached=a.detached):(l=a,this._isDetached=!1),l.stderr.on("data",u=>this.appendOutput(u,e)),{reader:new Et.StreamMessageReader(l.stdout),writer:new Et.StreamMessageWriter(l.stdin)}}});let o=n,s=n;return s.run||s.debug?typeof v8debug=="object"||this._forceDebug||i()?o=s.debug:o=s.run:o=n,this._getServerWorkingDir(o.options).then(a=>{if(cC.is(o)&&o.module){let l=o,u=l.transport||0,c=[],f=l.options||Object.create(null),p=l.runtime||process.execPath;f.execArgv&&f.execArgv.forEach(m=>c.push(m)),u!=1&&c.push(l.module),l.args&&l.args.forEach(m=>c.push(m));let d=Object.create(null);d.cwd=a,d.env=t(f.env);let h;if(u===1?(d.stdio=[null,null,null],c.push("--node-ipc")):u===0?c.push("--stdio"):u===2?(h=Et.generateRandomPipeName(),c.push(`--pipe=${h}`)):Pv.isSocket(u)&&c.push(`--socket=${u.port}`),c.push(`--clientProcessId=${process.pid.toString()}`),u===1){let m={cwd:a,env:t(f.env),stdio:[null,null,null,"ipc"],execPath:p,execArgv:f.execArgv||[]},y=Ca.default.fork(l.module,c,m);return!y||!y.pid?Promise.reject(`Launching server module "${l.module}" failed.`):(y.on("error",g=>{oo.error(g)}),oo.info(`${this.id} started with ${y.pid}`),this._serverProcess=y,y.stdout.on("data",g=>this.appendOutput(g,e)),y.stderr.on("data",g=>this.appendOutput(g,e)),{reader:new Et.IPCMessageReader(y),writer:new Et.IPCMessageWriter(y)})}else if(u===0){let m=Ca.default.spawn(p,c,d);return!m||!m.pid?Promise.reject(`Launching server module "${l.module}" failed.`):(oo.info(`${this.id} started with ${m.pid}`),m.on("error",y=>{oo.error(`Process ${p} error: `,y)}),this._serverProcess=m,m.stderr.on("data",y=>this.appendOutput(y,e)),{reader:new Et.StreamMessageReader(m.stdout),writer:new Et.StreamMessageWriter(m.stdin)})}else{if(u==2)return Promise.resolve(Et.createClientPipeTransport(h)).then(m=>{let y=Ca.default.spawn(p,c,d);return!y||!y.pid?Promise.reject(`Launching server module "${l.module}" failed.`):(oo.info(`Language server ${this.id} started with ${y.pid}`),this._serverProcess=y,y.stderr.on("data",g=>this.appendOutput(g,e)),y.stdout.on("data",g=>this.appendOutput(g,e)),Promise.resolve(m.onConnected()).then(g=>({reader:g[0],writer:g[1]})))});if(Pv.isSocket(l.transport))return Promise.resolve(Et.createClientSocketTransport(l.transport.port)).then(m=>{let y=Ca.default.spawn(p,c,d);return!y||!y.pid?Promise.reject(`Launching server ${l.module} failed.`):(y.on("exit",g=>{g!=0&&this.error(`command "${p} ${c.join(" ")}" exited with code: ${g}`)}),oo.info(`Language server ${this.id} started with ${y.pid}`),this._serverProcess=y,y.stderr.on("data",g=>this.appendOutput(g,e)),y.stdout.on("data",g=>this.appendOutput(g,e)),Promise.resolve(m.onConnected()).then(g=>({reader:g[0],writer:g[1]})))})}}else if(uC.is(o)&&o.command){let l=o,u=l.args||[],c=Object.assign({},l.options);c.env=c.env?Object.assign({},process.env,c.env):process.env,c.cwd=a;let f=b.expand(o.command),p=Ca.default.spawn(f,u,c);return p.on("error",d=>{this.error(d.message),oo.error(d)}),!p||!p.pid?Promise.reject(`Launching server "${this.id}" using command ${l.command} failed.`):(oo.info(`Language server "${this.id}" started with ${p.pid}`),p.on("exit",d=>{d!=0&&this.error(`${l.command} exited with code: ${d}`)}),p.stderr.on("data",d=>this.appendOutput(d,e)),this._serverProcess=p,this._isDetached=!!c.detached,{reader:new Et.StreamMessageReader(p.stdout),writer:new Et.StreamMessageWriter(p.stdin)})}return Promise.reject(`Unsupported server configuration ${JSON.stringify(n,null,2)}`)})}registerProposedFeatures(){this.registerFeatures(Rv.createAll(this))}registerBuiltinFeatures(){super.registerBuiltinFeatures(),this.registerFeature(new ZE(this)),this.registerFeature(new nC(this)),this.registerFeature(new rC(this)),this.registerFeature(new eC(this)),this.registerFeature(new XE(this)),this.registerFeature(new tC(this)),this.registerFeature(new aC(this)),this.registerFeature(new iC(this)),this.clientOptions.disableWorkspaceFolders||this.registerFeature(new sC(this))}_getServerWorkingDir(e){let t=e&&e.cwd;return t&&!lC.default.isAbsolute(t)&&(t=lC.default.join(b.cwd,t)),t||(t=b.cwd),t?new Promise(i=>{BH.default.lstat(t,(n,o)=>{i(!n&&o.isDirectory()?t:void 0)})}):Promise.resolve(void 0)}appendOutput(e,t){let i=wt(e)?e:e.toString(t);this.outputChannel.append(i.endsWith(` -`)?i:i+` -`)}},jH=class{constructor(e,t){this._client=e;this._setting=t;this._listeners=[]}start(){return b.onDidChangeConfiguration(e=>{e.affectsConfiguration(this._setting)&&this.onDidChangeConfiguration()},null,this._listeners),this.onDidChangeConfiguration(),{dispose:()=>{z(this._listeners),this._client.needsStop()&&this._client.stop()}}}onDidChangeConfiguration(){let e=this._setting.indexOf("."),t=e>=0?this._setting.substr(0,e):this._setting,i=e>=0?this._setting.substr(e+1):void 0,n=i?b.getConfiguration(t).get(i,!0):b.getConfiguration(t);n&&this._client.needsStart()?this._client.start():!n&&this._client.needsStop()&&this._client.stop()}},Rv;(function(e){function r(t){return[]}e.createAll=r})(Rv||(Rv={}));var _a=U()("services");function vye(r){switch(r){case ye.Initial:return"init";case ye.Running:return"running";case ye.Starting:return"starting";case ye.StartFailed:return"startFailed";case ye.Stopping:return"stopping";case ye.Stopped:return"stopped";default:return"unknown"}}var zH=class extends UH.EventEmitter{constructor(){super(...arguments);this.registered=new Map;this.disposables=[]}init(){b.onDidOpenTextDocument(e=>{this.start(e)},null,this.disposables),b.onDidChangeConfiguration(e=>{e.affectsConfiguration("languageserver")&&this.createCustomServices()},null,this.disposables),this.createCustomServices()}dispose(){this.removeAllListeners(),z(this.disposables);for(let e of this.registered.values())e.dispose()}regist(e){let{id:t}=e;if(t||_a.error("invalid service configuration. ",e.name),!this.registered.get(t))return this.registered.set(t,e),_a.info(`registered service "${t}"`),this.shouldStart(e)&&e.start(),e.state==ye.Running&&this.emit("ready",t),e.onServiceReady(()=>{_a.info(`service ${t} started`),this.emit("ready",t)},null,this.disposables),Au.Disposable.create(()=>{e.stop(),e.dispose(),this.registered.delete(t)})}getService(e){let t=this.registered.get(e);return t||(t=this.registered.get(`languageserver.${e}`)),t}shouldStart(e){if(e.state!=ye.Initial)return!1;let t=e.selector;for(let i of b.documents)if(b.match(t,i.textDocument))return!0;return!1}start(e){let t=this.getServices(e);for(let i of t)i.state==ye.Initial&&i.start()}getServices(e){let t=[];for(let i of this.registered.values())b.match(i.selector,e)>0&&t.push(i);return t}stop(e){let t=this.registered.get(e);if(!t){C.showMessage(`Service ${e} not found`,"error");return}return Promise.resolve(t.stop())}stopAll(){for(let e of this.registered.values())e.stop()}async toggle(e){let t=this.registered.get(e);if(!t){C.showMessage(`Service ${e} not found`,"error");return}let{state:i}=t;try{i==ye.Running?await Promise.resolve(t.stop()):i==ye.Initial?await t.start():i==ye.Stopped&&await t.restart()}catch(n){C.showMessage(`Service error: ${n.message}`,"error")}}getServiceStats(){let e=[];for(let[t,i]of this.registered)e.push({id:t,languageIds:yye(i.selector),state:vye(i.state)});return e}createCustomServices(){let e=b.getConfiguration().get("languageserver",{});for(let t of Object.keys(e)){let i=e[t];this.registLanguageClient(t,i)}}waitClient(e){let t=this.getService(e);return t&&t.state==ye.Running?Promise.resolve():t?new Promise(i=>{t.onServiceReady(()=>{i()})}):new Promise(i=>{let n=o=>{(o==e||o==`languageserver.${e}`)&&(this.off("ready",n),i())};this.on("ready",n)})}async registNotification(e,t){await this.waitClient(e);let i=this.getService(e);if(!i.client){C.showMessage(`Not a language client: ${e}`,"error");return}i.client.onNotification(t,async o=>{await b.nvim.call("coc#do_notify",[e,t,o])})}async sendNotification(e,t,i){if(!t)throw new Error("method required for ontification");let n=this.getService(e);if(!n||!n.client)throw new Error(`Language server ${e} not found`);if(n.state==ye.Starting&&await n.client.onReady(),n.state!=ye.Running)throw new Error(`Language server ${e} not running`);await Promise.resolve(n.client.sendNotification(t,i))}async sendRequest(e,t,i,n){if(!t)throw new Error("method required for sendRequest");let o=this.getService(e);if(o||await He(100),o=this.getService(e),!o||!o.client)throw new Error(`Language server ${e} not found`);if(o.state==ye.Starting&&await o.client.onReady(),o.state!=ye.Running)throw new Error(`Language server ${e} not running`);return n||(n=new Au.CancellationTokenSource().token),await Promise.resolve(o.client.sendRequest(t,i,n))}registLanguageClient(e,t){let i=typeof e=="string"?`languageserver.${e}`:e.id,n=[],o=new Au.Emitter,s=typeof e=="string"?null:e;if(this.registered.has(i))return;let a=!1,l={id:i,client:s,name:typeof e=="string"?e:e.name,selector:typeof e=="string"?GH(t.filetypes,t.additionalSchemes):e.clientOptions.documentSelector,state:ye.Initial,onServiceReady:o.event,start:()=>{if(l.state==ye.Starting||l.state==ye.Running||s&&!s.needsStart())return;if(a&&s)return s.restart(),Promise.resolve();if(!a){if(typeof e=="string"&&!s){let c=b.getConfiguration().get("languageserver",{})[e];if(!c||c.enable===!1)return;let f=bye(i,e,c);if(!f)return;s=new Tv(i,e,f[1],f[0]),l.selector=f[0].documentSelector,l.client=s}s.onDidChangeState(c=>{let{oldState:f,newState:p}=c;p==ni.Starting?l.state=ye.Starting:p==ni.Running?l.state=ye.Running:p==ni.Stopped&&(l.state=ye.Stopped);let d=VH(f),h=VH(p);_a.info(`${s.name} state change: ${d} => ${h}`)},null,n),a=!0}l.state=ye.Starting,_a.debug(`starting service: ${i}`);let u=s.start();return n.push(u),new Promise(c=>{s.onReady().then(()=>{o.fire(void 0),c()},f=>{C.showMessage(`Server ${i} failed to start: ${f}`,"error"),_a.error(`Server ${i} failed to start:`,f),l.state=ye.StartFailed,c()})})},dispose:async()=>{o.dispose(),z(n)},stop:async()=>{!s||!s.needsStop()||await Promise.resolve(s.stop())},restart:async()=>{s?(l.state=ye.Starting,s.restart()):await l.start()}};return this.regist(l)}};function yye(r){let e=r.map(t=>typeof t=="string"?t:t.language);return e=e.filter(t=>typeof t=="string"),Array.from(new Set(e))}function bye(r,e,t){let{command:i,module:n,port:o,args:s,filetypes:a}=t;if(s=s||[],!a)return C.showMessage(`Wrong configuration of LS "${e}", filetypes not found`,"error"),null;if(!i&&!n&&!o)return C.showMessage(`Wrong configuration of LS "${e}", no command or module specified.`,"error"),null;let l;if(n){if(n=b.expand(n),!WH.default.existsSync(n))return C.showMessage(`Module file "${n}" not found for LS "${e}"`,"error"),null;l={module:n,runtime:t.runtime||process.execPath,args:s,transport:xye(t),options:Dye(t)}}else i?l={command:i,args:s,options:Sye(t)}:o&&(l=()=>new Promise((d,h)=>{let m=new HH.default.Socket,y=t.host||"127.0.0.1";_a.info(`languageserver "${r}" connecting to ${y}:${o}`),m.connect(o,y,()=>{d({reader:m,writer:m})}),m.on("error",g=>{h(new Error(`Connection error for ${r}: ${g.message}`))})}));let u=!!t.disableWorkspaceFolders,c=!!t.disableSnippetCompletion;return[{ignoredRootPaths:(t.ignoredRootPaths||[]).map(d=>b.expand(d)),disableWorkspaceFolders:u,disableSnippetCompletion:c,disableDynamicRegister:!!t.disableDynamicRegister,disableCompletion:!!t.disableCompletion,disableDiagnostics:!!t.disableDiagnostics,formatterPriority:t.formatterPriority||0,documentSelector:GH(t.filetypes,t.additionalSchemes),revealOutputChannelOn:wye(t.revealOutputChannelOn),synchronize:{configurationSection:`${r}.settings`},diagnosticCollectionName:e,outputChannelName:r,stdioEncoding:t.stdioEncoding||"utf8",progressOnInitialization:t.progressOnInitialization!==!1,initializationOptions:t.initializationOptions||{}},l]}function wye(r){switch(r){case"info":return ii.Info;case"warn":return ii.Warn;case"error":return ii.Error;case"never":return ii.Never;default:return ii.Never}}function GH(r,e){let t=[],i=["file","untitled"].concat(e||[]);return r?(r.forEach(n=>{t.push(...i.map(o=>({language:n,scheme:o})))}),t):i.map(n=>({scheme:n}))}function xye(r){let{transport:e,transportPort:t}=r;return!e||e=="ipc"?Gt.ipc:e=="stdio"?Gt.stdio:e=="pipe"?Gt.pipe:{kind:Gt.socket,port:t}}function Dye(r){return{cwd:r.cwd,execArgv:r.execArgv||[],env:r.env||void 0}}function Sye(r){return{cwd:r.cwd,detached:!!r.detached,shell:!!r.shell,env:r.env||void 0}}function VH(r){switch(r){case ni.Running:return"running";case ni.Starting:return"starting";case ni.Stopped:return"stopped";default:return"unknown"}}var Vt=new zH;var $z=S(Vr()),ed=S(W());var KH=S(require("events")),Pa=["","","","","","","","","","","","","","","","","","","<2-LeftMouse>","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],dC=class extends KH.EventEmitter{constructor(){super();this.configuration=b.getConfiguration("list"),this.disposable=b.onDidChangeConfiguration(e=>{e.affectsConfiguration("list")&&(this.configuration=b.getConfiguration("list"),this.emit("change"))})}get(e,t){return this.configuration.get(e,t)}get previousKey(){return this.fixKey(this.configuration.get("previousKeymap",""))}get nextKey(){return this.fixKey(this.configuration.get("nextKeymap",""))}dispose(){this.disposable.dispose(),this.removeAllListeners()}fixKey(e){if(Pa.includes(e))return e;let t=Pa.find(i=>i.toLowerCase()==e.toLowerCase());return t||(C.showMessage(`Configured key "${e}" not supported.`,"error"),null)}},kv=dC;var A6e=S(bh());var N6e=U()("list-mappings"),hC=class{constructor(e,t,i){this.manager=e;this.nvim=t;this.config=i;this.insertMappings=new Map;this.normalMappings=new Map;this.userInsertMappings=new Map;this.userNormalMappings=new Map;let{prompt:n}=e;this.add("insert","",()=>{n.removeTail()}),this.add("insert","",()=>{var o;(o=e.session)==null||o.history.next()}),this.add("insert","",()=>{var o;(o=e.session)==null||o.history.previous()}),this.add("insert","",async()=>{await n.paste()}),this.add("insert","",()=>e.switchMatcher()),this.add("insert",["",""],async()=>{await e.doAction()}),this.add("insert",["",""," "],()=>e.chooseAction()),this.add("insert","",()=>{e.toggleMode()}),this.add("insert","",()=>{e.stop()}),this.add("insert","",()=>e.cancel()),this.add("insert","",async()=>{var o;await((o=e.session)==null?void 0:o.reloadItems())}),this.add("insert","",()=>{n.moveLeft()}),this.add("insert","",()=>{n.moveRight()}),this.add("insert",["",""],()=>{n.moveToEnd()}),this.add("insert",["",""],()=>{n.moveToStart()}),this.add("insert",["","",""],()=>{n.onBackspace()}),this.add("insert","",()=>{n.removeWord()}),this.add("insert","",()=>{n.removeAhead()}),this.add("insert","",()=>n.insertRegister()),this.add("insert","",()=>e.feedkeys("",!1)),this.add("insert","",()=>e.feedkeys("",!1)),this.add("insert","",()=>e.feedkeys("",!1)),this.add("insert","",()=>e.normal("j")),this.add("insert","",()=>e.normal("k")),this.add("insert",[""],this.doScroll.bind(this,"")),this.add("insert",[""],this.doScroll.bind(this,"")),this.add("insert",[""],this.doScroll.bind(this,"")),this.add("insert",[""],this.doScroll.bind(this,"")),this.add("normal","",()=>{}),this.add("normal","t",()=>e.doAction("tabe")),this.add("normal","s",()=>e.doAction("split")),this.add("normal","d",()=>e.doAction("drop")),this.add("normal",["","","\r"],()=>e.doAction()),this.add("normal","",()=>{var o;return(o=e.session)==null?void 0:o.ui.selectAll()}),this.add("normal"," ",()=>{var o;return(o=e.session)==null?void 0:o.ui.toggleSelection()}),this.add("normal","p",()=>e.togglePreview()),this.add("normal",[""," ",""],()=>e.chooseAction()),this.add("normal","",()=>{e.stop()}),this.add("normal","",()=>e.cancel()),this.add("normal","",()=>{var o;return(o=e.session)==null?void 0:o.reloadItems()}),this.add("normal","",()=>{var o;return(o=e.session)==null?void 0:o.jumpBack()}),this.add("normal","",()=>this.scrollPreview("down")),this.add("normal","",()=>this.scrollPreview("up")),this.add("normal",["i","I","o","O","a","A"],()=>e.toggleMode()),this.add("normal","?",()=>{var o;return(o=e.session)==null?void 0:o.showHelp()}),this.add("normal",":",async()=>{await e.cancel(!1),await t.eval('feedkeys(":")')}),this.add("normal",[""],this.doScroll.bind(this,"")),this.add("normal",[""],this.doScroll.bind(this,"")),this.createMappings(),i.on("change",()=>{this.createMappings()})}createMappings(){let e=this.config.get("insertMappings",{});this.userInsertMappings=this.fixUserMappings(e);let t=this.config.get("normalMappings",{});this.userNormalMappings=this.fixUserMappings(t)}fixUserMappings(e){let t=new Map;for(let[i,n]of Object.entries(e))if(i.length==1)t.set(i,n);else if(i.startsWith("<")&&i.endsWith(">"))if(i.toLowerCase()=="")t.set(" ",n);else if(i.toLowerCase()=="")t.set("",n);else if(Pa.includes(i))t.set(i,n);else{let o=!1;for(let s=0;s"),{cusorIndex:t,interactive:i,input:n,_matcher:o}=this,s=['echo ""'];if(this.mode=="insert")if(i?s.push("echohl MoreMsg | echon 'INTERACTIVE ' | echohl None"):o&&s.push(`echohl MoreMsg | echon '${o.toUpperCase()} ' | echohl None`),s.push(`echohl Special | echon '${e} ' | echohl None`),t==n.length)s.push(`echon '${n.replace(/'/g,"''")}'`),s.push("echohl Cursor | echon ' ' | echohl None");else{let l=n.slice(0,t);l&&s.push(`echon '${l.replace(/'/g,"''")}'`),s.push(`echohl Cursor | echon '${n[t].replace(/'/,"''")}' | echohl None`);let u=n.slice(t+1);s.push(`echon '${u.replace(/'/g,"''")}'`)}else s.push('echohl MoreMsg | echo "" | echohl None');s.push("redraw");let a=s.join("|");this.nvim.command(a,!0)}moveLeft(){this.cusorIndex!=0&&(this.cusorIndex=this.cusorIndex-1,this.drawPrompt())}moveRight(){this.cusorIndex!=this._input.length&&(this.cusorIndex=this.cusorIndex+1,this.drawPrompt())}moveToEnd(){this.cusorIndex!=this._input.length&&(this.cusorIndex=this._input.length,this.drawPrompt())}moveToStart(){this.cusorIndex!=0&&(this.cusorIndex=0,this.drawPrompt())}onBackspace(){let{cusorIndex:e,input:t}=this;if(e==0)return;let i=t.slice(0,e),n=t.slice(e);this.cusorIndex=e-1,this._input=`${i.slice(0,i.length-1)}${n}`,this.drawPrompt(),this._onDidChangeInput.fire(this._input)}removeNext(){let{cusorIndex:e,input:t}=this;if(e==t.length-1)return;let i=t.slice(0,e),n=t.slice(e+1);this._input=`${i}${n}`,this.drawPrompt(),this._onDidChangeInput.fire(this._input)}removeWord(){let{cusorIndex:e,input:t}=this;if(e==0)return;let i=t.slice(0,e),n=t.slice(e),o=i.replace(/[\w$]+([^\w$]+)?$/,"");this.cusorIndex=e-(i.length-o.length),this._input=`${o}${n}`,this.drawPrompt(),this._onDidChangeInput.fire(this._input)}removeTail(){let{cusorIndex:e,input:t}=this;if(e==t.length)return;let i=t.slice(0,e);this._input=i,this.drawPrompt(),this._onDidChangeInput.fire(this._input)}removeAhead(){let{cusorIndex:e,input:t}=this;if(e==0)return;let i=t.slice(e);this.cusorIndex=0,this._input=i,this.drawPrompt(),this._onDidChangeInput.fire(this._input)}async acceptCharacter(e){if(this.requestInput){if(this.requestInput=!1,/^[0-9a-z"%#*+/:\-.]$/.test(e)){let t=await this.nvim.call("getreg",e);t=t.replace(/\n/g," "),this.addText(t)}}else this.addText(e)}insertRegister(){this.requestInput=!0}async paste(){let e=await this.nvim.eval("@*");e=e.replace(/\n/g,""),!!e&&this.addText(e)}async eval(e){let t=await this.nvim.call("eval",[e]);t=t.replace(/\n/g,""),this.addText(t)}addText(e){let{cusorIndex:t,input:i}=this;this.cusorIndex=t+e.length;let n=i.slice(0,t),o=i.slice(t);this._input=`${n}${e}${o}`,this.drawPrompt(),this._onDidChangeInput.fire(this._input)}},XH=mC;var wC=S(Vr()),lz=S(W());function so(r){let e=[];for(let t=0,i=r.length;t=97&&r<=122||r>=65&&r<=90}function nn(r,e){return r==e||r>=97&&r<=122&&e+32===r}function Yp(r,e){let t=r.charCodeAt(0),i=e.charCodeAt(0);return t===i||t>=97&&t<=122&&i+32===t}function Ou(r,e){let t=r.length;if(r.length>e.length)return!1;let i=0;for(let n=0;n=97&&s<=122&&o+32===s){i=i+1;continue}}return i===t}var z6e=U()("list-history"),gC=class{constructor(e,t){this.prompt=e;this.name=t;this.index=-1;this.loaded=[];this.current=[];this.db=b.createDatabase(`list-${t}-history`),this.key=Buffer.from(b.cwd).toString("base64")}filter(){let{input:e}=this.prompt;if(e==this.curr)return;this.historyInput="";let t=so(e);this.current=this.loaded.filter(i=>Ou(t,i)),this.index=-1}get curr(){return this.index==-1?null:this.current[this.index]}load(e){let{db:t}=this;e=e||"";let i=t.fetch(this.key);!i||!Array.isArray(i)?this.loaded=[]:this.loaded=i,this.index=-1,this.current=this.loaded.filter(n=>n.startsWith(e))}add(){let{loaded:e,db:t,prompt:i}=this,{input:n}=i;if(!n||n.length<2||n==this.historyInput)return;let o=e.indexOf(n);o!=-1&&e.splice(o,1),e.push(n),e.length>200&&(e=e.slice(-200)),t.push(this.key,e)}previous(){let{current:e,index:t}=this;!e||!e.length||(t<=0?this.index=e.length-1:this.index=t-1,this.historyInput=this.prompt.input=e[this.index]||"")}next(){let{current:e,index:t}=this;!e||!e.length||(t==e.length-1?this.index=0:this.index=t+1,this.historyInput=this.prompt.input=e[this.index]||"")}},ZH=gC;var QH=S(Vr()),Lu=S(W());var t8e=U()("list-ui"),vC=class{constructor(e,t,i,n){this.nvim=e;this.name=t;this.listOptions=i;this.config=n;this.newTab=!1;this.currIndex=0;this.drawCount=0;this.items=[];this.disposables=[];this.selected=new Set;this.mutex=new ar;this._onDidChangeLine=new Lu.Emitter;this._onDidOpen=new Lu.Emitter;this._onDidClose=new Lu.Emitter;this._onDidLineChange=new Lu.Emitter;this._onDoubleClick=new Lu.Emitter;this.onDidChangeLine=this._onDidChangeLine.event;this.onDidLineChange=this._onDidLineChange.event;this.onDidOpen=this._onDidOpen.event;this.onDidClose=this._onDidClose.event;this.onDidDoubleClick=this._onDoubleClick.event;this.signOffset=n.get("signOffset"),this.matchHighlightGroup=n.get("matchHighlightGroup","Search"),this.newTab=i.position=="tab",A.on("BufWinLeave",async s=>{s!=this.bufnr||this.window==null||(this.window=null,this._onDidClose.fire(s))},null,this.disposables),A.on("CursorMoved",async(s,a)=>{s==this.bufnr&&this.onLineChange(a[0]-1)},null,this.disposables);let o=QH.default(async s=>{if(s!=this.bufnr)return;let[a,l,u]=await e.eval('[win_getid(),line("w0"),line("w$")]');u<300||!this.window||a!=this.window.id||(e.pauseNotification(),this.doHighlight(l-1,u),e.command("redraw",!0),e.resumeNotification(!1,!0))},100);this.disposables.push({dispose:()=>{o.clear()}}),A.on("CursorMoved",o,null,this.disposables)}get limitLines(){return this.config.get("limitLines",3e4)}onLineChange(e){this.currIndex!=e&&(this.currIndex=e,this._onDidChangeLine.fire(e))}set index(e){if(e<0||e>=this.items.length)return;let{nvim:t}=this;t.pauseNotification(),this.setCursor(e+1,0),t.command("redraw",!0),t.resumeNotification(!1,!0).logError()}get index(){return this.currIndex}get firstItem(){return this.items[0]}get lastItem(){return this.items[this.items.length-1]}getItem(e){return this.items[e]}get item(){let{window:e}=this;return e?e.cursor.then(t=>(this.currIndex=t[0]-1,this.items[this.currIndex]),t=>null):Promise.resolve(null)}async echoMessage(e){if(this.bufnr)return;let{items:t}=this,n=`[${t.indexOf(e)+1}/${t.length}] ${e.label||""}`;this.nvim.callTimer("coc#util#echo_lines",[[n]],!0)}async updateItem(e,t){if(!this.bufnr||b.bufnr!=this.bufnr)return;let i=Object.assign({resolved:!0},e);if(t0&&this.bufnr){i.pauseNotification();for(let o of t)i.command(`sign place ${n+o} line=${o} name=CocSelected buffer=${this.bufnr}`,!0);await i.resumeNotification()}}async toggleSelection(){let{nvim:e,selected:t,signOffset:i,bufnr:n}=this;if(b.bufnr!=n)return;let o=await e.call("line","."),s=await e.call("mode");if(s=="v"||s=="V"){let[l,u]=await this.getSelectedRange(),c=t.has(l);l>u&&([l,u]=[u,l]);for(let p=l;p<=u;p++)c?(t.delete(p),e.command(`sign unplace ${i+p} buffer=${n}`,!0)):(t.add(p),e.command(`sign place ${i+p} line=${p} name=CocSelected buffer=${n}`,!0));this.setCursor(u,0),e.command("redraw",!0),await e.resumeNotification();return}let a=t.has(o);e.pauseNotification(),a?(t.delete(o),e.command(`sign unplace ${i+o} buffer=${n}`,!0)):(t.add(o),e.command(`sign place ${i+o} line=${o} name=CocSelected buffer=${n}`,!0)),this.setCursor(o+1,0),e.command("redraw",!0),await e.resumeNotification()}async selectLines(e,t){let{nvim:i,signOffset:n,bufnr:o,length:s}=this;this.clearSelection();let{selected:a}=this;i.pauseNotification(),e>t&&([e,t]=[t,e]);for(let u=e;u<=t&&!(u>s);u++)a.add(u),i.command(`sign place ${n+u} line=${u} name=CocSelected buffer=${o}`,!0);this.setCursor(t,0),i.command("redraw",!0),await i.resumeNotification()}async selectAll(){let{length:e}=this;e!=0&&await this.selectLines(1,e)}clearSelection(){let{selected:e,nvim:t,signOffset:i,bufnr:n}=this;if(!!n&&e.size>0){let o=[];for(let s of e)o.push(i+s);t.call("coc#util#unplace_signs",[n,o],!0),this.selected=new Set}}get shown(){return this.window!=null}get bufnr(){var e;return(e=this.buffer)==null?void 0:e.id}get winid(){var e;return(e=this.window)==null?void 0:e.id}get ready(){return this.window?Promise.resolve():new Promise((e,t)=>{let i=setTimeout(()=>{t(new Error("window create timeout"))},3e3),n=this.onDidLineChange(()=>{n.dispose(),clearTimeout(i),e()})})}async drawItems(e,t,i=!1,n){let o=this.drawCount=this.drawCount+1,{nvim:s,name:a,listOptions:l}=this,u=await this.mutex.acquire();if(this.items=e.length>this.limitLines?e.slice(0,this.limitLines):e,this.window==null&&!(n&&n.isCancellationRequested))try{let{position:d,numberSelect:h}=l,[m,y]=await s.call("coc#list#create",[d,t,a,h]);n&&n.isCancellationRequested?s.call("coc#list#clean_up",[],!0):(this.height=t,this.buffer=s.createBuffer(m),this.window=s.createWindow(y),this._onDidOpen.fire(this.bufnr))}catch(d){s.call("coc#prompt#stop_prompt",["list"],!0),s.call("coc#list#clean_up",[],!0),u(),C.showMessage(`Error on list create: ${d.message}`,"error");return}if(u(),n&&n.isCancellationRequested||o!==this.drawCount)return;let f=this.items.map(d=>d.label);this.clearSelection();let p=i?this.currIndex:0;await this.setLines(f,!1,p),this._onDidLineChange.fire(this.currIndex+1)}async appendItems(e){if(!this.window)return;let t=this.items.length;if(t>=this.limitLines)return;let i=this.limitLines-t,n=e.slice(0,i);this.items=this.items.concat(n),await this.setLines(n.map(o=>o.label),t>0,this.currIndex)}async setLines(e,t=!1,i){let{nvim:n,buffer:o,window:s}=this;if(!o||!s)return;if(n.pauseNotification(),!t){let l=this.config.get("statusLineSegments");l&&s.notify("nvim_win_set_option",["statusline",l.join(" ")]),n.call("coc#compat#clear_matches",[s.id],!0),e.length||(e=["No results, press ? on normal mode to get help."],n.call("coc#compat#matchaddpos",["Comment",[[1]],99,this.window.id],!0))}if(o.setOption("modifiable",!0,!0),b.isVim?n.call("coc#list#setlines",[o.id,e,t],!0):o.setLines(e,{start:t?-1:0,end:-1,strictIndexing:!1},!0),o.setOption("modifiable",!1,!0),!t&&i==0)this.doHighlight(0,300);else{let l=this.newTab?b.env.lines:this.height;this.doHighlight(Math.max(0,i-l),Math.min(i+l+1,this.length-1))}t||(this.currIndex=i,s.notify("nvim_win_set_cursor",[[i+1,0]])),n.command("redraws",!0);let a=await n.resumeNotification();Array.isArray(a[1])&&a[1][0]==0&&(this.window=null)}restoreWindow(){if(this.newTab)return;let{winid:e,height:t}=this;e&&t&&this.nvim.call("coc#list#restore",[e,t],!0)}reset(){this.window&&(this.window=null,this.buffer=null)}dispose(){z(this.disposables),this.window=null,this._onDidChangeLine.dispose(),this._onDidOpen.dispose(),this._onDidClose.dispose(),this._onDidLineChange.dispose(),this._onDoubleClick.dispose()}get length(){return this.items.length}get selectedItems(){let{selected:e,items:t}=this,i=[];for(let n of e)t[n-1]&&i.push(t[n-1]);return i}doHighlight(e,t){let{nvim:i}=b,{items:n}=this,o=[];for(let s=e;s<=Math.min(t,n.length-1);s++){let{ansiHighlights:a,highlights:l}=n[s];if(a)for(let u of a){let{span:c,hlGroup:f}=u;o.push({hlGroup:f,priority:9,pos:[s+1,c[0]+1,c[1]-c[0]]})}if(l&&Array.isArray(l.spans)){let{spans:u,hlGroup:c}=l;for(let f of u)o.push({hlGroup:c||this.matchHighlightGroup,priority:11,pos:[s+1,f[0]+1,f[1]-f[0]]})}}i.call("coc#compat#matchaddgroups",[this.window.id,o],!0)}setCursor(e,t){let{window:i,items:n}=this,o=n.length==0?1:n.length;e>o||(this.onLineChange(e-1),i&&i.notify("nvim_win_set_cursor",[[e,t]]))}async getSelectedRange(){let{nvim:e}=this;await e.call("coc#prompt#stop_prompt",["list"]),await e.eval('feedkeys("\\", "in")');let[,t]=await e.call("getpos","'<"),[,i]=await e.call("getpos","'>");return t>i&&([t,i]=[i,t]),this.nvim.call("coc#prompt#start_prompt",["list"],!0),[t,i]}},ez=vC;var Xp=S(W());var Mu=-Infinity,Eye=Infinity,Cye=-.005,_ye=-.005,Pye=-.01,tz=1,Tye=.9,Rye=.8,kye=.7,Iye=.6;function Fye(r){return r.toLowerCase()===r}function Aye(r){return r.toUpperCase()===r}function Oye(r){let e=r.length,t=new Array(e),i="/";for(let n=0;n1024)return Mu;let n=new Array(t),o=new Array(t);return rz(r,e,n,o),o[t-1][i-1]}function iz(r,e){let t=r.length,i=e.length,n=new Array(t);if(!t||!i)return n;if(t===i){for(let l=0;l1024)return n;let o=new Array(t),s=new Array(t);rz(r,e,o,s);let a=!1;for(let l=t-1,u=i-1;l>=0;l--)for(;u>=0;u--)if(o[l][u]!==Mu&&(a||o[l][u]===s[l][u])){a=l&&u&&s[l][u]===o[l-1][u-1]+tz,n[l]=u--;break}return n}function nz(r,e){r=r.toLowerCase(),e=e.toLowerCase();let t=r.length;for(let i=0,n=0;ie.score&&(e=r[t]);return e}var Mye=U()("list-worker"),Nye="",bC=class{constructor(e,t,i,n,o){this.nvim=e;this.list=t;this.prompt=i;this.listOptions=n;this.config=o;this._loading=!1;this.totalItems=[];this._onDidChangeItems=new Xp.Emitter;this._onDidChangeLoading=new Xp.Emitter;this.onDidChangeItems=this._onDidChangeItems.event;this.onDidChangeLoading=this._onDidChangeLoading.event}set loading(e){this._loading!=e&&(this._loading=e,this._onDidChangeLoading.fire(e))}get isLoading(){return this._loading}async loadItems(e,t=!1){let{list:i,listOptions:n}=this;this.loading=!0;let{interactive:o}=n;this.tokenSource=new Xp.CancellationTokenSource;let s=this.tokenSource.token,a=await i.loadItems(e,s);if(!s.isCancellationRequested)if(!a||Array.isArray(a)){this.tokenSource=null,a=a||[],this.totalItems=a.map(u=>(u.label=this.fixLabel(u.label),this.parseListItemAnsi(u),u)),this.loading=!1;let l;o?l=this.convertToHighlightItems(a):l=this.filterItems(a),this._onDidChangeItems.fire({items:l,reload:t,finished:!0})}else{let l=a,u=this.totalItems=[],c=0,f=e.input,p,d,h=g=>{if(d=Date.now(),c>=u.length)return;let w=this.input!=f;if(!(o&&w))if(c==0||w){f=this.input,c=u.length;let x;o?x=this.convertToHighlightItems(u):x=this.filterItems(u),this._onDidChangeItems.fire({items:x,reload:t,append:!1,finished:g})}else{let x=u.slice(c);c=u.length;let E;o?E=this.convertToHighlightItems(x):E=this.filterItems(x),this._onDidChangeItems.fire({items:E,append:!0,finished:g})}};l.on("data",g=>{p&&clearTimeout(p),!s.isCancellationRequested&&(o&&this.input!=f||(g.label=this.fixLabel(g.label),this.parseListItemAnsi(g),u.push(g),!d&&u.length==500||Date.now()-d>200?h():p=setTimeout(()=>h(),50)))});let m=()=>{l!=null&&(this.tokenSource=null,l=null,this.loading=!1,y.dispose(),p&&clearTimeout(p),u.length==0?this._onDidChangeItems.fire({items:[],finished:!0}):h(!0))},y=s.onCancellationRequested(()=>{l&&(l.dispose(),m())});l.on("error",async g=>{l!=null&&(l=null,this.tokenSource=null,this.loading=!1,y.dispose(),p&&clearTimeout(p),this.nvim.call("coc#prompt#stop_prompt",["list"],!0),C.showMessage(`Task error: ${g.toString()}`,"error"),Mye.error(g))}),l.on("end",m)}}drawItems(){let{totalItems:e,listOptions:t}=this,i;t.interactive?i=this.convertToHighlightItems(e):i=this.filterItems(e),this._onDidChangeItems.fire({items:i,finished:!0})}stop(){this.tokenSource&&(this.tokenSource.cancel(),this.tokenSource=null),this.loading=!1}get length(){return this.totalItems.length}get input(){return this.prompt.input}convertToHighlightItems(e){let{input:t}=this;return t?e.map(i=>{let n=Fv(i);if(n=="")return i;let o=sz(n,t);if(!o||!o.score)return i;let s=this.getHighlights(n,o.matches);return Object.assign({},i,{highlights:s})}):[]}filterItems(e){let{input:t}=this,{sort:i,matcher:n,ignorecase:o}=this.listOptions,s=this.config.extendedSearchMode?qye(t):[t];if(t.length==0||s.length==0)return e;if(n=="strict"){let u=[];for(let c of e){let f=[],p=Fv(c),d=!0;for(let h of s){let m=o?p.toLowerCase().indexOf(h.toLowerCase()):p.indexOf(h);if(m==-1){d=!1;break}f.push([Kr(p,m),Kr(p,m+ue(h))])}d&&u.push(Object.assign({},c,{highlights:{spans:f}}))}return u}if(n=="regex"){let u=[],c=o?"iu":"u",f=s.reduce((p,d)=>{try{let h=new RegExp(d,c);p.push(h)}catch(h){}return p},[]);for(let p of e){let d=[],h=Fv(p),m=!0;for(let y of f){let g=h.match(y);if(g==null){m=!1;break}d.push([Kr(h,g.index),Kr(h,g.index+ue(g[0]))])}m&&u.push(Object.assign({},p,{highlights:{spans:d}}))}return u}let a=[],l=0;for(let u of e){let c=u.filterText||u.label,f=0,p=[],d=Fv(u),h=!0;for(let y of s){if(!nz(y,c)){h=!1;break}p.push(...iz(y,d)),i&&(f+=Iv(y,c))}if(!h)continue;let m=Object.assign({},u,{sortText:typeof u.sortText=="string"?u.sortText:String.fromCharCode(l),score:f,highlights:this.getHighlights(d,p)});a.push(m),l=l+1}return i&&a.length&&a.sort((u,c)=>u.score!=c.score?c.score-u.score:u.sortText>c.sortText?1:-1),a}getHighlights(e,t){let i=[];if(t&&t.length){let n=t.shift(),o=t.shift(),s=n;for(;o;){if(o==s+1){s=o,o=t.shift();continue}i.push([Kr(e,n),Kr(e,s)+1]),n=o,s=n,o=t.shift()}i.push([Kr(e,n),Kr(e,s)+1])}return{spans:i}}parseListItemAnsi(e){let{label:t}=e;if(e.ansiHighlights||!t.includes(Nye))return;let{line:i,highlights:n}=$l(t);e.label=i,e.ansiHighlights=n}fixLabel(e){let{columns:t}=b.env;return e=e.split(` -`).join(" "),e.slice(0,t*2)}dispose(){this.stop()}},az=bC;function Fv(r){return r.filterText!=null?sj(r.filterText,r.label):r.label}function qye(r){let e=[],t=0,i=0,n="";for(;io.replace(/\\\s/g," ").trim()).filter(o=>o.length>0)}var $ye=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],uz=U()("list-session"),xC=class{constructor(e,t,i,n,o=[],s){this.nvim=e;this.prompt=t;this.list=i;this.listOptions=n;this.listArgs=o;this.config=s;this.loadingFrame="";this.hidden=!1;this.disposables=[];this.args=[];this.ui=new ez(e,i.name,n,s),this.history=new ZH(t,i.name),this.worker=new az(e,i,t,n,{interactiveDebounceTime:s.get("interactiveDebounceTime",100),extendedSearchMode:s.get("extendedSearchMode",!0)}),this.interactiveDebounceTime=s.get("interactiveDebounceTime",100);let a=wC.default(async()=>{let[u,c,f]=await e.eval('[coc#list#has_preview(),win_getid(),line(".")]');u&&c==this.winid&&await this.doPreview(f-1)},50);this.disposables.push({dispose:()=>{a.clear()}}),this.ui.onDidChangeLine(a,null,this.disposables),this.ui.onDidChangeLine(this.resolveItem,this,this.disposables),this.ui.onDidLineChange(this.resolveItem,this,this.disposables);let l=wC.default(async()=>{let{autoPreview:u}=this.listOptions;if(!u){let[c,f]=await e.eval("[coc#list#has_preview(),mode()]");if(!c||f!="n")return}await this.doAction("preview")},50);this.disposables.push({dispose:()=>{l.clear()}}),this.ui.onDidLineChange(l,null,this.disposables),this.ui.onDidLineChange(()=>{this.updateStatus()},null,this.disposables),this.ui.onDidOpen(async()=>{typeof this.list.doHighlight=="function"&&this.list.doHighlight(),this.listOptions.first&&await this.doAction()},null,this.disposables),this.ui.onDidClose(async()=>{await this.hide()},null,this.disposables),this.ui.onDidDoubleClick(async()=>{await this.doAction()},null,this.disposables),this.worker.onDidChangeItems(async({items:u,reload:c,append:f,finished:p})=>{if(!this.hidden)if(f)await this.ui.appendItems(u);else{let d=this.config.get("height",10);p&&!n.interactive&&n.input.length==0&&(d=Math.min(u.length,d));let h=this.uiTokenSource=new lz.CancellationTokenSource;await this.ui.drawItems(u,Math.max(1,d),c,h.token)}},null,this.disposables),this.worker.onDidChangeLoading(u=>{this.hidden||(u?this.interval=setInterval(()=>{let c=Math.floor(new Date().getMilliseconds()/100);this.loadingFrame=$ye[c],this.updateStatus()},100):(this.interval&&(this.loadingFrame="",clearInterval(this.interval),this.interval=null),this.updateStatus()))},null,this.disposables)}async start(e){this.args=e,this.cwd=b.cwd,this.hidden=!1;let{listOptions:t,listArgs:i}=this,n=await this.nvim.eval('[win_getid(),bufnr("%"),winheight("%")]');this.listArgs=i,this.history.load(t.input||""),this.window=this.nvim.createWindow(n[0]),this.buffer=this.nvim.createBuffer(n[1]),this.savedHeight=n[2],await this.worker.loadItems(this.context)}async reloadItems(){if(!this.window)return;let e=await this.nvim.call("winbufnr",[this.window.id]);e!=-1&&(this.buffer=this.nvim.createBuffer(e),await this.worker.loadItems(this.context,!0))}async call(e){var o,s;await this.nvim.call("coc#prompt#stop_prompt",["list"]);let t=await this.ui.getItems(),i={name:this.name,args:this.listArgs,input:this.prompt.input,winid:(o=this.window)==null?void 0:o.id,bufnr:(s=this.buffer)==null?void 0:s.id,targets:t},n=await this.nvim.call(e,[i]);return this.prompt.start(),n}async chooseAction(){let{nvim:e}=this,{actions:t,defaultAction:i}=this.list,n=t.map(c=>c.name),o=n.indexOf(i);o!=-1&&(n.splice(o,1),n.unshift(i));let s=new Set,a=[],l=[];for(let c of n){let f=0;for(let p of c){if(!s.has(p)){s.add(p),a.push(`${c.slice(0,f)}&${c.slice(f)}`);break}f++}f==c.length&&l.push(c)}l.length&&(uz.error(`Can't create shortcut for actions: ${l.join(",")} of "${this.name}" list`),n=n.filter(c=>!l.includes(c))),await e.call("coc#prompt#stop_prompt",["list"]);let u=await e.call("confirm",["Choose action:",a.join(` -`)]);await He(10),this.prompt.start(),u&&await this.doAction(n[u-1])}async doAction(e){let{list:t}=this;e=e||t.defaultAction;let i=t.actions.find(o=>o.name==e);if(!i){C.showMessage(`Action ${e} not found`,"error");return}let n;if(e=="preview"){let o=await this.ui.item;n=o?[o]:[]}else n=await this.ui.getItems();n.length&&await this.doItemAction(n,i)}async doPreview(e){let t=this.ui.getItem(e),i=this.list.actions.find(n=>n.name=="preview");!t||!i||await this.doItemAction([t],i)}async first(){await this.doDefaultAction(0)}async last(){await this.doDefaultAction(this.ui.length-1)}async previous(){await this.doDefaultAction(this.ui.index-1)}async next(){await this.doDefaultAction(this.ui.index+1)}async doDefaultAction(e){let{ui:t}=this,i=t.getItem(e);!i||(t.index=e,await this.doItemAction([i],this.defaultAction),await t.echoMessage(i))}get name(){return this.list.name}get winid(){return this.ui.winid}get length(){return this.ui.length}get defaultAction(){let{defaultAction:e,actions:t}=this.list,i=t.find(n=>n.name==e);if(!i)throw new Error(`default action "${e}" not found`);return i}async hide(){if(this.hidden)return;this.uiTokenSource&&(this.uiTokenSource.cancel(),this.uiTokenSource.dispose(),this.uiTokenSource=null);let{nvim:e,interval:t}=this;t&&clearInterval(t),this.hidden=!0,this.worker.stop(),this.history.add();let{winid:i}=this.ui;this.ui.reset(),this.window&&i&&(await e.call("coc#list#hide",[this.window.id,this.savedHeight,i]),b.isVim&&(e.command("redraw",!0),await He(10))),e.call("coc#prompt#stop_prompt",["list"],!0)}toggleMode(){let e=this.prompt.mode=="normal"?"insert":"normal";this.prompt.mode=e,this.listOptions.mode=e,this.updateStatus()}stop(){this.worker.stop()}async resolveItem(){let e=this.ui.index,t=this.ui.getItem(e);if(!t||t.resolved)return;let{list:i}=this;if(typeof i.resolveItem=="function"){let n=await Promise.resolve(i.resolveItem(t));n&&e==this.ui.index&&await this.ui.updateItem(n,e)}}async showHelp(){await this.hide();let{list:e,nvim:t}=this;if(!e)return;t.pauseNotification(),t.command("tabe +setl\\ previewwindow [LIST HELP]",!0),t.command("setl nobuflisted noswapfile buftype=nofile bufhidden=wipe",!0),await t.resumeNotification();let i=e.options&&e.options.length,n=await t.buffer,o=new ls;if(o.addLine("NAME","Label"),o.addLine(` ${e.name} - ${e.description||""} -`),o.addLine("SYNOPSIS","Label"),o.addLine(` :CocList [LIST OPTIONS] ${e.name}${i?" [ARGUMENTS]":""} -`),e.detail){o.addLine("DESCRIPTION","Label");let a=e.detail.split(` -`).map(l=>" "+l);o.addLine(a.join(` -`)+` -`)}if(i){o.addLine("ARGUMENTS","Label"),o.addLine("");for(let a of e.options)o.addLine(a.name,"Special"),o.addLine(` ${a.description}`),o.addLine("");o.addLine("")}let s=b.getConfiguration(`list.source.${e.name}`);if(Object.keys(s).length){o.addLine("CONFIGURATIONS","Label"),o.addLine("");let a={};ge.all.forEach(l=>{let{packageJSON:u}=l,{contributes:c}=u;if(!c)return;let{configuration:f}=c;if(f){let{properties:p}=f;if(p)for(let d of Object.keys(p))a[d]=p[d]}});for(let l of Object.keys(s)){let u=s[l],c=`list.source.${e.name}.${l}`,f=a[c]&&a[c].description?a[c].description:l;o.addLine(` "${c}"`,"MoreMsg"),o.addText(` - ${f}, current value: `),o.addText(JSON.stringify(u),"Special")}o.addLine("")}o.addLine("ACTIONS","Label"),o.addLine(` ${e.actions.map(a=>a.name).join(", ")}`),o.addLine(""),o.addLine("see ':h coc-list-options' for available list options.","Comment"),t.pauseNotification(),o.render(n,0,-1),t.command("setl nomod",!0),t.command("setl nomodifiable",!0),t.command("normal! gg",!0),t.command("nnoremap q :bd!",!0),await t.resumeNotification()}switchMatcher(){let{matcher:e,interactive:t}=this.listOptions;if(t)return;let i=["fuzzy","strict","regex"],n=i.indexOf(e)+1;n>=i.length&&(n=0),this.listOptions.matcher=i[n],this.prompt.matcher=i[n],this.worker.drawItems()}updateStatus(){let{ui:e,list:t,nvim:i}=this;if(!e.winid)return;let n=i.createBuffer(e.bufnr),o={mode:this.prompt.mode.toUpperCase(),args:this.args.join(" "),name:t.name,cwd:this.cwd,loading:this.loadingFrame,total:this.worker.length};i.pauseNotification(),n.setVar("list_status",o,!0),i.command("redraws",!0),i.resumeNotification(!1,!0).logError()}get context(){let{winid:e}=this.ui;return{options:this.listOptions,args:this.listArgs,input:this.prompt.input,cwd:b.cwd,window:this.window,buffer:this.buffer,listWindow:e?this.nvim.createWindow(e):void 0}}redrawItems(){this.worker.drawItems()}onMouseEvent(e){switch(e){case"":return this.ui.onMouse("mouseDown");case"":return this.ui.onMouse("mouseDrag");case"":return this.ui.onMouse("mouseUp");case"<2-LeftMouse>":return this.ui.onMouse("doubleClick")}}async doNumberSelect(e){if(!this.listOptions.numberSelect)return!1;let t=e.charCodeAt(0);if(t>=48&&t<=57){let i=Number(e);return i==0&&(i=10),this.ui.length>=i&&(this.nvim.pauseNotification(),this.ui.setCursor(Number(e),0),await this.nvim.resumeNotification(),await this.doAction()),!0}return!1}jumpBack(){let{window:e,nvim:t}=this;e&&(t.pauseNotification(),t.call("coc#prompt#stop_prompt",["list"],!0),this.nvim.call("win_gotoid",[e.id],!0),t.resumeNotification(!1,!0).logError())}async resume(){this.winid&&await this.hide();let e=await this.nvim.eval('[win_getid(),bufnr("%"),winheight("%")]');this.hidden=!1,this.window=this.nvim.createWindow(e[0]),this.buffer=this.nvim.createBuffer(e[1]),this.savedHeight=e[2],this.prompt.start(),await this.ui.resume(),this.listOptions.autoPreview&&await this.doAction("preview")}async doItemAction(e,t){let{noQuit:i}=this.listOptions,{nvim:n}=this,o=t.persist===!0||t.name=="preview",s=this.winid&&(o||i);try{if(s?o||(n.pauseNotification(),n.call("coc#prompt#stop_prompt",["list"],!0),n.call("win_gotoid",[this.context.window.id],!0),await n.resumeNotification()):await this.hide(),t.multiple)await Promise.resolve(t.execute(e,this.context));else if(t.parallel)await Promise.all(e.map(a=>Promise.resolve(t.execute(a,this.context))));else for(let a of e)await Promise.resolve(t.execute(a,this.context));s&&this.ui.restoreWindow(),t.reload&&s&&await this.worker.loadItems(this.context,!0)}catch(a){C.showMessage(a.message,"error"),uz.error(`Error on action "${t.name}"`,a)}}onInputChange(){this.timer&&clearTimeout(this.timer);let e=this.worker.length;if(this.listOptions.input=this.prompt.input,this.listOptions.interactive)this.worker.stop(),this.timer=setTimeout(async()=>{await this.worker.loadItems(this.context)},this.interactiveDebounceTime);else if(e){let t=Math.max(Math.min(Math.floor(e/200),300),50);this.timer=setTimeout(()=>{this.worker.drawItems()},t)}}dispose(){if(!this.hidden){this.hidden=!0,this.uiTokenSource&&(this.uiTokenSource.cancel(),this.uiTokenSource.dispose(),this.uiTokenSource=null);let{winid:e}=this.ui;this.ui.reset(),this.window&&e&&this.nvim.call("coc#list#hide",[this.window.id,this.savedHeight,e],!0)}this.interval&&clearInterval(this.interval),this.timer&&clearTimeout(this.timer),z(this.disposables),this.worker.dispose(),this.ui.dispose()}},cz=xC;var mz=S(require("fs")),SC=S(require("path")),gz=S(require("readline")),$r=S(W());var fz=S(require("child_process")),pz=S(require("events")),dz=S(require("readline"));var Bye=U()("list-commandTask"),DC=class extends pz.EventEmitter{constructor(e){super();this.opt=e;this.disposables=[];this.start()}start(){let{cmd:e,args:t,cwd:i,onLine:n}=this.opt,o=fz.spawn(e,t,{cwd:i,windowsHide:!0});this.disposables.push({dispose:()=>{o.kill()}}),o.on("error",a=>{this.emit("error",a.message)}),o.stderr.on("data",a=>{Bye.error(`[${e} Error]`,a.toString("utf8"))});let s=dz.default.createInterface(o.stdout);s.on("line",a=>{let l=n(a);l&&this.emit("data",l)}),s.on("close",()=>{this.emit("end")})}dispose(){z(this.disposables)}},hz=DC;var jye=U()("list-basic"),EC=class{constructor(e){this.nvim=e;this.defaultAction="open";this.actions=[];this.options=[];this.disposables=[];this.config=new kv}get alignColumns(){return this.config.get("alignColumns",!1)}get hlGroup(){return this.config.get("previewHighlightGroup","Search")}get previewHeight(){return this.config.get("maxPreviewHeight",12)}get splitRight(){return this.config.get("previewSplitRight",!1)}parseArguments(e){if(!this.optionMap){this.optionMap=new Map;for(let i of this.options){let n=i.name.split(/,\s*/g).map(s=>s.replace(/\s+.*/g,"")),o=i.key?i.key:n[n.length-1].replace(/^-/,"");for(let s of n)this.optionMap.set(s,{name:o,hasValue:i.hasValue})}}let t={};for(let i=0;i{let n=await this.convertLocation(t.location);await this.previewLocation(n,i)}});let{nvim:e}=this;this.createAction({name:"quickfix",multiple:!0,execute:async t=>{let i=await Promise.all(t.map(o=>this.convertLocation(o.location).then(s=>b.getQuickfixItem(s))));await e.call("setqflist",[i]);let n=await e.getVar("coc_quickfix_open_command");e.command(typeof n=="string"?n:"copen",!0)}});for(let t of["open","tabe","drop","vsplit","split"])this.createAction({name:t,execute:async i=>{await this.jumpTo(i.location,t=="open"?null:t)}})}async convertLocation(e){if(typeof e=="string")return $r.Location.create(e,$r.Range.create(0,0,0,0));if($r.Location.is(e))return e;let t=$.parse(e.uri);if(t.scheme!="file")return $r.Location.create(e.uri,$r.Range.create(0,0,0,0));let i=gz.default.createInterface({input:mz.default.createReadStream(t.fsPath,{encoding:"utf8"})}),n=e.line,o=0,s=!1,a=await new Promise(l=>{i.on("line",u=>{if(!s){if(u.includes(n)){i.removeAllListeners(),i.close(),s=!0,l(u);return}o=o+1}}),i.on("error",u=>{this.nvim.errWriteLine(`Read ${t.fsPath} error: ${u.message}`),l(null)})});if(a!=null){let l=e.text?a.indexOf(e.text):0;l==0&&(l=a.match(/^\s*/)[0].length);let u=$r.Position.create(o,l+(e.text?e.text.length:0));return $r.Location.create(e.uri,$r.Range.create($r.Position.create(o,l),u))}return $r.Location.create(e.uri,$r.Range.create(0,0,0,0))}async jumpTo(e,t){if(typeof e=="string"){await b.jumpTo(e,null,t);return}let{range:i,uri:n}=await this.convertLocation(e),o=i.start;o.line==0&&o.character==0&&Ne(o,i.end)==0&&(o=null),await b.jumpTo(n,o,t)}createAction(e){let{name:t}=e,i=this.actions.findIndex(n=>n.name==t);i!==-1&&this.actions.splice(i,1),this.actions.push(e)}async previewLocation(e,t){if(!t.listWindow)return;let{nvim:i}=this,{uri:n,range:o}=e,s=b.getDocument(e.uri),a=$.parse(n),l=[];if(s)l=s.getLines();else if(a.scheme=="file")try{l=(await Vl(a.fsPath,"utf8")).split(/\r?\n/)}catch(c){""+a.fsPath,c.message}let u={winid:t.window.id,range:Gn(o)?null:o,lnum:o.start.line+1,name:a.scheme=="file"?a.fsPath:n,filetype:s?s.filetype:this.getFiletype(a.fsPath),position:t.options.position,maxHeight:this.previewHeight,splitRight:this.splitRight,hlGroup:this.hlGroup,scheme:a.scheme};await i.call("coc#list#preview",[l,u]),b.isVim&&i.command("redraw",!0)}async preview(e,t){let{nvim:i}=this,{bufname:n,filetype:o,range:s,lines:a,lnum:l}=e,u={winid:t.window.id,lnum:s?s.start.line+1:l||1,filetype:o||"txt",position:t.options.position,maxHeight:this.previewHeight,splitRight:this.splitRight,hlGroup:this.hlGroup};n&&(u.name=n),s&&(u.range=s),await i.call("coc#list#preview",[a,u]),b.isVim&&i.command("redraw",!0)}doHighlight(){}dispose(){z(this.disposables)}getFiletype(e){let t=SC.default.extname(e);if(!t)return"";for(let i of b.documents){let n=$.parse(i.uri).fsPath;if(SC.default.extname(n)==t){let{filetype:o}=i;return o=="javascriptreact"?"javascript":o=="typescriptreact"?"typescript":o.indexOf(".")!==-1?o.split(".")[0]:o}}return""}},Nt=EC;var Av=S(require("path"));function Br(r,e){if(e.length===0)return[];let t=[];if(r){let i=Array(Math.min(...e.map(n=>n.label.length))).fill(0);for(let n of e)for(let o=0;o({...n,label:n.label.map((o,s)=>o.padEnd(i[s])).join(" ")}))}else t=e.map(i=>({...i,label:i.label.join(" ")}));return t}function vz(r,e){var t;if(r==="hidden")return"";if(r==="full")return e;if(r==="short"){let i=e.split(Av.default.sep);return i.length<2?e:[...i.slice(0,i.length-2).filter(o=>o.length>0).map(o=>o[0]),i[i.length-1]].join(Av.default.sep)}else{let i=e.split(Av.default.sep);return(t=i[i.length-1])!=null?t:""}}var CC=class extends Nt{constructor(e){super(e);this.defaultAction="run";this.description="registered commands of coc.nvim";this.name="commands";this.mru=b.createMru("commands"),this.addAction("run",async t=>{let{cmd:i}=t.data;await A.fire("Command",[i]),me.executeCommand(i).logError(),await me.addRecent(i)}),this.addAction("append",async t=>{let{cmd:i}=t.data;await e.feedKeys(`:CocCommand ${i} `,"n",!1)})}async loadItems(e){let t=[],i=await this.mru.load(),{commandList:n,onCommandList:o,titles:s}=me,a=n.map(l=>l.id).concat(o);for(let l of[...new Set(a)])t.push({label:[l,...s.get(l)?[s.get(l)]:[]],filterText:l,data:{cmd:l,score:Uye(i,l)}});return t.sort((l,u)=>u.data.score-l.data.score),Br(this.alignColumns,t)}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocCommandsTitle /\\t.*$/ contained containedin=CocCommandsLine",!0),e.command("highlight default link CocCommandsTitle Comment",!0),e.resumeNotification().catch(t=>{})}},yz=CC;function Uye(r,e){let t=r.indexOf(e);return t==-1?-1:r.length-t}var bz=S(require("path"));var Ov=S(jn()),Zp=S(require("path"));var X8e=U()("list-location"),_C=class extends Nt{constructor(e){super(e);this.defaultAction="open";this.description="show locations saved by g:coc_jump_locations variable";this.name="location";this.addLocationActions()}async loadItems(e,t){let i=await this.nvim.getVar("coc_jump_locations");if(t.isCancellationRequested)return[];i=i||[],i.forEach(a=>{if(!a.uri){let l=Zp.default.isAbsolute(a.filename)?a.filename:Zp.default.join(e.cwd,a.filename);a.uri=$.file(l).toString()}if(!a.bufnr&&b.getDocument(a.uri)!=null&&(a.bufnr=b.getDocument(a.uri).bufnr),a.range)a.lnum=a.lnum||a.range.start.line+1,a.col=a.col||a.range.start.character+1;else{let{lnum:l,col:u}=a;a.range=Ov.Range.create(l-1,u-1,l-1,u-1)}});let n=await this.nvim.call("bufnr","%"),o=i.every(a=>a.bufnr&&n&&a.bufnr==n);return i.map(a=>{let l=o?"":a.filename,u=`${l}${a.text.trim()}`;Zp.default.isAbsolute(l)&&(l=Xe(e.cwd,l)?Zp.default.relative(e.cwd,l):l);let c=`${l} |${a.type?a.type+" ":""}${a.lnum} col ${a.col}| `,f;if(a.range&&a.range.start.line==a.range.end.line){let d=ue(c)+ue(a.text.slice(0,a.range.start.character)),h=ue(c)+ue(a.text.slice(0,a.range.end.character));f={hlGroup:"Search",span:[d,h]}}return{label:c+a.text,location:Ov.Location.create(a.uri,a.range),filterText:u,ansiHighlights:f?[f]:void 0}})}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocLocationName /\\v^[^|]+/ contained containedin=CocLocationLine",!0),e.command("syntax match CocLocationPosition /\\v\\|\\w*\\s?\\d+\\scol\\s\\d+\\|/ contained containedin=CocLocationLine",!0),e.command("syntax match CocLocationError /Error/ contained containedin=CocLocationPosition",!0),e.command("syntax match CocLocationWarning /Warning/ contained containedin=CocLocationPosition",!0),e.command("highlight default link CocLocationName Directory",!0),e.command("highlight default link CocLocationPosition LineNr",!0),e.command("highlight default link CocLocationError Error",!0),e.command("highlight default link CocLocationWarning WarningMsg",!0),e.resumeNotification().catch(t=>{})}},cs=_C;var oWe=U()("list-symbols"),PC=class extends cs{constructor(){super(...arguments);this.defaultAction="open";this.description="diagnostics of current workspace";this.name="diagnostics"}async loadItems(e){let t=mt.getDiagnosticList(),{cwd:i}=e,n=this.getConfig().get("includeCode",!0),o=this.getConfig().get("pathFormat","full"),s=t.map(a=>{let l=Xe(i,a.file)?bz.default.relative(i,a.file):a.file,u=vz(o,l),c=o!=="hidden"?[`${u}:${a.lnum}`]:[],f=n?[`[${a.source}${a.code?"":"]"}`,a.code?`${a.code}]`:""]:[];return{label:[...c,...f,a.severity,a.message],location:a.location}});return Br(this.alignColumns,s)}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocDiagnosticsFile /\\v^\\s*\\S+/ contained containedin=CocDiagnosticsLine",!0),e.command("syntax match CocDiagnosticsError /\\tError\\s*\\t/ contained containedin=CocDiagnosticsLine",!0),e.command("syntax match CocDiagnosticsWarning /\\tWarning\\s*\\t/ contained containedin=CocDiagnosticsLine",!0),e.command("syntax match CocDiagnosticsInfo /\\tInformation\\s*\\t/ contained containedin=CocDiagnosticsLine",!0),e.command("syntax match CocDiagnosticsHint /\\tHint\\s*\\t/ contained containedin=CocDiagnosticsLine",!0),e.command("highlight default link CocDiagnosticsFile Comment",!0),e.command("highlight default link CocDiagnosticsError CocErrorSign",!0),e.command("highlight default link CocDiagnosticsWarning CocWarningSign",!0),e.command("highlight default link CocDiagnosticsInfo CocInfoSign",!0),e.command("highlight default link CocDiagnosticsHint CocHintSign",!0),e.resumeNotification().catch(t=>{})}},wz=PC;var Nu=S($i()),xz=S(require("os")),Lv=S(require("path"));var Wye=U()("list-extensions"),TC=class extends Nt{constructor(e){super(e);this.defaultAction="toggle";this.description="manage coc extensions";this.name="extensions";this.addAction("toggle",async t=>{let{id:i,state:n}=t.data;n!="disabled"&&(n=="activated"?await ge.deactivate(i):await ge.activate(i),await He(100))},{persist:!0,reload:!0,parallel:!0}),this.addAction("configuration",async t=>{let{root:i}=t.data,n=Lv.default.join(i,"package.json");if(Nu.default.existsSync(n)){let s=Nu.default.readFileSync(n,"utf8").split(/\r?\n/).findIndex(a=>a.includes('"contributes"'));await b.jumpTo($.file(n).toString(),{line:s==-1?0:s,character:0})}}),this.addAction("open",async t=>{let{root:i}=t.data;b.env.isiTerm?e.call("coc#util#iterm_open",[i],!0):e.call("coc#util#open_url",[i],!0)}),this.addAction("disable",async t=>{let{id:i,state:n}=t.data;n!=="disabled"&&await ge.toggleExtension(i)},{persist:!0,reload:!0,parallel:!0}),this.addAction("enable",async t=>{let{id:i,state:n}=t.data;n=="disabled"&&await ge.toggleExtension(i)},{persist:!0,reload:!0,parallel:!0}),this.addAction("lock",async t=>{let{id:i}=t.data;await ge.toggleLock(i)},{persist:!0,reload:!0}),this.addAction("help",async t=>{let{root:i}=t.data,o=(await Nu.default.readdir(i)).find(s=>/^readme/i.test(s));if(o){let s=await e.call("fnameescape",[Lv.default.join(i,o)]);await b.callAsync("coc#util#execute",[`edit ${s}`])}}),this.addAction("reload",async t=>{let{id:i}=t.data;await ge.reloadExtension(i)},{persist:!0,reload:!0}),this.addAction("fix",async t=>{let{root:i,isLocal:n}=t.data,{npm:o}=ge;if(n){C.showMessage("Can't fix for local extension.","warning");return}if(!o)return;let s=Lv.default.join(i,"node_modules");Nu.default.existsSync(s)&&Nu.default.removeSync(s);let a=await b.createTerminal({cwd:i});!await a.show(!1)||(b.nvim.command("startinsert",!0),a.sendText(`${o} install --production --ignore-scripts --no-lockfile`,!0))}),this.addMultipleAction("uninstall",async t=>{let i=[];for(let n of t)n.data.isLocal||i.push(n.data.id);ge.uninstallExtension(i).catch(n=>{Wye.error(n)})})}async loadItems(e){let t=[],i=await ge.getExtensionStates(),n=await ge.getLockedList();for(let o of i){let s="+";o.state=="disabled"?s="-":o.state=="activated"?s="*":o.state=="unknown"&&(s="?");let a=await this.nvim.call("resolve",o.root),l=n.includes(o.id);t.push({label:[`${s} ${o.id}${l?" \uE0A2":""}`,...o.isLocal?["[RTP]"]:[],o.version,a.replace(xz.default.homedir(),"~")],filterText:o.id,data:{id:o.id,root:a,state:o.state,isLocal:o.isLocal,priority:Hye(o.state)}})}return t.sort((o,s)=>o.data.priority!=s.data.priority?s.data.priority-o.data.priority:s.data.id-o.data.id?1:-1),Br(this.alignColumns,t)}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocExtensionsActivited /\\v^\\*/ contained containedin=CocExtensionsLine",!0),e.command("syntax match CocExtensionsLoaded /\\v^\\+/ contained containedin=CocExtensionsLine",!0),e.command("syntax match CocExtensionsDisabled /\\v^-/ contained containedin=CocExtensionsLine",!0),e.command("syntax match CocExtensionsName /\\v%3c\\S+/ contained containedin=CocExtensionsLine",!0),e.command("syntax match CocExtensionsRoot /\\v\\t[^\\t]*$/ contained containedin=CocExtensionsLine",!0),e.command("syntax match CocExtensionsLocal /\\v\\[RTP\\]/ contained containedin=CocExtensionsLine",!0),e.command("highlight default link CocExtensionsActivited Special",!0),e.command("highlight default link CocExtensionsLoaded Normal",!0),e.command("highlight default link CocExtensionsDisabled Comment",!0),e.command("highlight default link CocExtensionsName String",!0),e.command("highlight default link CocExtensionsLocal MoreMsg",!0),e.command("highlight default link CocExtensionsRoot Comment",!0),e.resumeNotification().catch(t=>{})}},Dz=TC;function Hye(r){switch(r){case"unknown":return 2;case"activated":return 1;case"disabled":return-1;default:return 0}}var Sz=S(require("path"));var Ez=S($i());var RC=class extends Nt{constructor(e){super(e);this.defaultAction="edit";this.description="list of current workspace folders";this.name="folders";this.addAction("edit",async t=>{let i=await e.call("input",["Folder: ",t.label,"dir"]),n=await It(i);if(!n||!n.isDirectory()){C.showMessage(`invalid path: ${i}`,"error");return}b.renameWorkspaceFolder(t.label,i)}),this.addAction("delete",async t=>{b.removeWorkspaceFolder(t.label)},{reload:!0,persist:!0}),this.addAction("newfile",async t=>{let i=await C.requestInput("File name",t.label+"/"),n=Sz.default.dirname(i),o=await It(n);(!o||!o.isDirectory())&&Ez.default.mkdirpSync(n),await b.createFile(i,{overwrite:!1,ignoreIfExists:!0}),await this.jumpTo($.file(i).toString())})}async loadItems(e){return b.folderPaths.map(t=>({label:t}))}},Cz=RC;var _z=S(require("path"));var kC=S(jn());var IC=class extends Nt{constructor(e){super(e);this.defaultAction="open";this.description="links of current buffer";this.name="links";this.addAction("open",async t=>{let{target:i}=t.data;$.parse(i).scheme.startsWith("http")?await e.call("coc#util#open_url",i):await b.jumpTo(i)}),this.addAction("jump",async t=>{let{location:i}=t.data;await b.jumpTo(i.uri,i.range.start)})}async loadItems(e,t){let i=await e.window.buffer,n=b.getDocument(i.id);if(!n)return null;let o=[],s=await B.getDocumentLinks(n.textDocument,t);if(s==null)throw new Error("Links provider not found.");let a=[];for(let l of s)l.target?o.push({label:Pz(l.target),data:{target:l.target,location:kC.Location.create(n.uri,l.range)}}):(l=await B.resolveDocumentLink(l),l.target&&o.push({label:Pz(l.target),data:{target:l.target,location:kC.Location.create(n.uri,l.range)}}),a.push(l));return o}},Tz=IC;function Pz(r){if(!r.startsWith("file:"))return r;let e=$.parse(r).fsPath;return Xe(b.cwd,e)?_z.default.relative(b.cwd,e):e}var FC=class extends Nt{constructor(e,t){super(e);this.listMap=t;this.name="lists";this.defaultAction="open";this.description="registered lists of coc.nvim";this.mru=new Jl("lists");this.addAction("open",async i=>{let{name:n}=i.data;await this.mru.add(n),await e.command(`CocList ${n}`)})}async loadItems(e){let t=[],i=await this.mru.load();for(let n of this.listMap.values())n.name!="lists"&&t.push({label:[n.name,...n.description?[n.description]:[]],data:{name:n.name,interactive:n.interactive,score:zye(i,n.name)}});return t.sort((n,o)=>o.data.score-n.data.score),Br(this.alignColumns,t)}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocListsDesc /\\t.*$/ contained containedin=CocListsLine",!0),e.command("highlight default link CocListsDesc Comment",!0),e.resumeNotification().catch(t=>{})}},Rz=FC;function zye(r,e){let t=r.indexOf(e);return t==-1?-1:r.length-t}var kz=S(require("path")),Qp=S(jn());var Iz=S(_l());var Ye=S(W());function _n(r){switch(r){case Ye.SymbolKind.File:return"File";case Ye.SymbolKind.Module:return"Module";case Ye.SymbolKind.Namespace:return"Namespace";case Ye.SymbolKind.Package:return"Package";case Ye.SymbolKind.Class:return"Class";case Ye.SymbolKind.Method:return"Method";case Ye.SymbolKind.Property:return"Property";case Ye.SymbolKind.Field:return"Field";case Ye.SymbolKind.Constructor:return"Constructor";case Ye.SymbolKind.Enum:return"Enum";case Ye.SymbolKind.Interface:return"Interface";case Ye.SymbolKind.Function:return"Function";case Ye.SymbolKind.Variable:return"Variable";case Ye.SymbolKind.Constant:return"Constant";case Ye.SymbolKind.String:return"String";case Ye.SymbolKind.Number:return"Number";case Ye.SymbolKind.Boolean:return"Boolean";case Ye.SymbolKind.Array:return"Array";case Ye.SymbolKind.Object:return"Object";case Ye.SymbolKind.Key:return"Key";case Ye.SymbolKind.Null:return"Null";case Ye.SymbolKind.EnumMember:return"EnumMember";case Ye.SymbolKind.Struct:return"Struct";case Ye.SymbolKind.Event:return"Event";case Ye.SymbolKind.Operator:return"Operator";case Ye.SymbolKind.TypeParameter:return"TypeParameter";default:return"Unknown"}}var GWe=U()("list-symbols");function Fz(r,e){return`${r.name}${e?` ${e}`:""}`}var AC=class extends cs{constructor(){super(...arguments);this.description="symbols of current document";this.name="outline";this.options=[{name:"-k, -kind KIND",hasValue:!0,description:"filters also by kind"}]}async loadItems(e,t){let i=await e.window.buffer,n=b.getDocument(i.id);if(!n)return null;let s=this.getConfig().get("ctagsFilestypes",[]),a,l=this.parseArguments(e.args);if(s.includes(n.filetype)||(a=await B.getDocumentSymbol(n.textDocument,t)),t.isCancellationRequested)return[];if(!a)return await this.loadCtagsSymbols(n);if(a.length==0)return[];let u=l.kind?l.kind.toLowerCase():null,c=[];if(!a[0].hasOwnProperty("location")){function p(d,h=0){d.sort(Gye);for(let m of d){let y=_n(m.kind),g=Qp.Location.create(n.uri,m.selectionRange);c.push({label:[`${"| ".repeat(h)}${m.name}`,`[${y}]`,`${m.range.start.line+1}`],filterText:Fz(m,l.kind==""?y:null),location:g,data:{kind:y}}),m.children&&m.children.length&&p(m.children,h+1)}}p(a),u&&(c=c.filter(d=>d.data.kind.toLowerCase().indexOf(u)==0))}else{a.sort((d,h)=>{let m=d.location.range.start,y=h.location.range.start,g=m.line-y.line;return g==0?m.character-y.character:g});for(let d of a){let h=_n(d.kind);d.name.endsWith(") callback")||u&&!h.toLowerCase().startsWith(u)||(d.location.uri===void 0&&(d.location.uri=n.uri),c.push({label:[d.name,`[${h}]`,`${d.location.range.start.line+1}`],filterText:Fz(d,l.kind==""?h:null),location:d.location}))}}return Br(this.alignColumns,c)}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocOutlineName /\\v\\s?[^\\t]+\\s/ contained containedin=CocOutlineLine",!0),e.command("syntax match CocOutlineIndentLine /\\v\\|/ contained containedin=CocOutlineLine,CocOutlineName",!0),e.command("syntax match CocOutlineKind /\\[\\w\\+\\]/ contained containedin=CocOutlineLine",!0),e.command("syntax match CocOutlineLine /\\d\\+$/ contained containedin=CocOutlineLine",!0),e.command("highlight default link CocOutlineName Normal",!0),e.command("highlight default link CocOutlineIndentLine Comment",!0),e.command("highlight default link CocOutlineKind Typedef",!0),e.command("highlight default link CocOutlineLine Comment",!0),e.resumeNotification(!1,!0).logError()}async loadCtagsSymbols(e){if(!Iz.default.sync("ctags",{nothrow:!0}))return[];let t=$.parse(e.uri),i=kz.default.extname(t.fsPath),n="",s=`${await this.nvim.call("tempname")}.${i}`,a=await this.nvim.call("fnameescape",s);await tj(a,e.getDocumentContent());try{n=await hn(`ctags -f - --excmd=number --language-force=${e.filetype} ${a}`)}catch(c){}if(n.trim().length||(n=await hn(`ctags -f - --excmd=number ${a}`)),n=n.trim(),!n)return[];let l=n.split(/\r?\n/),u=[];for(let c of l){let f=c.split(" ");if(f.length<4)continue;let p=Number(f[2].replace(/;"$/,"")),d=e.getline(p-1);if(!d)continue;let h=d.indexOf(f[0]),m=h==-1?0:h,y=Qp.Range.create(p-1,m,p-1,m+f[0].length);u.push({label:`${f[0]} [${f[3]}] ${p}`,filterText:f[0],location:Qp.Location.create(e.uri,y),data:{line:p}})}return u.sort((c,f)=>c.data.line-f.data.line),u}},Az=AC;function Gye(r,e){let t=r.selectionRange,i=e.selectionRange;return t.start.line!=i.start.line?t.start.line-i.start.line:t.start.character-i.start.character}var OC=class extends Nt{constructor(e){super(e);this.defaultAction="toggle";this.description="registered services of coc.nvim";this.name="services";this.addAction("toggle",async t=>{let{id:i}=t.data;await Vt.toggle(i),await He(100)},{persist:!0,reload:!0})}async loadItems(e){let t=Vt.getServiceStats();return t.sort((i,n)=>i.id>n.id?-1:1),Br(this.alignColumns,t.map(i=>({label:[i.state=="running"?"*":" ",i.id,`[${i.state}]`,i.languageIds.join(", ")],data:{id:i.id}})))}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocServicesPrefix /\\v^./ contained containedin=CocServicesLine",!0),e.command("syntax match CocServicesName /\\v%3c\\S+/ contained containedin=CocServicesLine",!0),e.command("syntax match CocServicesStat /\\v\\t\\[\\w+\\]/ contained containedin=CocServicesLine",!0),e.command("syntax match CocServicesLanguages /\\v(\\])@<=.*$/ contained containedin=CocServicesLine",!0),e.command("highlight default link CocServicesPrefix Special",!0),e.command("highlight default link CocServicesName Type",!0),e.command("highlight default link CocServicesStat Statement",!0),e.command("highlight default link CocServicesLanguages Comment",!0),e.resumeNotification().catch(t=>{})}},Oz=OC;var Mv=S(jn());var i5e=U()("list-sources"),LC=class extends Nt{constructor(e){super(e);this.defaultAction="toggle";this.description="registered completion sources";this.name="sources";this.addAction("toggle",async t=>{let{name:i}=t.data;Ge.toggleSource(i)},{persist:!0,reload:!0}),this.addAction("refresh",async t=>{let{name:i}=t.data;await Ge.refresh(i)},{persist:!0,reload:!0}),this.addAction("open",async t=>{let{location:i}=t;i&&await this.jumpTo(i)})}async loadItems(e){let t=Ge.sourceStats(),i=await e.buffer.getOption("filetype"),n=b.env.disabledSources,o=n?n[i]||[]:[];return t.sort((s,a)=>s.type!=a.type?s.typea.name?-1:1),t.map(s=>{let a=s.disabled?" ":"*";o&&o.includes(s.name)&&(a="-");let l;return s.filepath&&(l=Mv.Location.create($.file(s.filepath).toString(),Mv.Range.create(0,0,0,0))),{label:`${a} ${Nv(s.name,22)} ${Nv("["+s.shortcut+"]",10)} ${Nv(s.triggerCharacters.join(""),10)} ${Nv(s.priority.toString(),3)} ${s.filetypes.join(",")}`,location:l,data:{name:s.name}}})}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocSourcesPrefix /\\v^./ contained containedin=CocSourcesLine",!0),e.command("syntax match CocSourcesName /\\v%3c\\S+/ contained containedin=CocSourcesLine",!0),e.command("syntax match CocSourcesType /\\v%25v.*%36v/ contained containedin=CocSourcesLine",!0),e.command("syntax match CocSourcesPriority /\\v%46v.*%50v/ contained containedin=CocSourcesLine",!0),e.command("syntax match CocSourcesFileTypes /\\v\\S+$/ contained containedin=CocSourcesLine",!0),e.command("highlight default link CocSourcesPrefix Special",!0),e.command("highlight default link CocSourcesName Type",!0),e.command("highlight default link CocSourcesPriority Number",!0),e.command("highlight default link CocSourcesFileTypes Comment",!0),e.command("highlight default link CocSourcesType Statement",!0),e.resumeNotification(!1,!0)}},Lz=LC;function Nv(r,e){return r.length>e?r.slice(0,e-1)+".":r+" ".repeat(e-r.length)}var MC=S(require("path")),Mz=S(ta());var Nz=S(W());var g5e=U()("list-symbols"),NC=class extends cs{constructor(){super(...arguments);this.interactive=!0;this.description="search workspace symbols";this.detail="Symbols list is provided by server, it works on interactive mode only.";this.name="symbols";this.options=[{name:"-k, -kind KIND",description:"Filter symbols by kind.",hasValue:!0}]}async loadItems(e,t){let{input:i}=e,n=this.parseArguments(e.args),o=n.kind?n.kind.toLowerCase():"";if(!e.options.interactive)throw new Error("Symbols only works on interactive mode");let s=await B.getWorkspaceSymbols(i,t);if(!s)throw new Error("No workspace symbols provider registed");let l=this.getConfig().get("excludes",[]),u=[];for(let c of s){let f=_n(c.kind);if(o&&f.toLowerCase()!=o)continue;let p=$.parse(c.location.uri).fsPath;Xe(b.cwd,p)&&(p=MC.default.relative(b.cwd,p)),!l.some(d=>Mz.default(p,d))&&u.push({label:[c.name,`[${f}]`,p],filterText:`${c.name}`,location:c.location,data:{original:c,kind:c.kind,file:p,score:Iv(i,c.name)}})}return u.sort((c,f)=>c.data.score!=f.data.score?f.data.score-c.data.score:c.data.kind!=f.data.kind?c.data.kind-f.data.kind:c.data.file.length-f.data.file.length),Br(this.alignColumns,u)}async resolveItem(e){let t=e.data.original;if(!t)return null;let i=new Nz.CancellationTokenSource,n=await B.resolveWorkspaceSymbol(t,i.token);if(!n)return null;let o=_n(n.kind),s=$.parse(n.location.uri).fsPath;return Xe(b.cwd,s)&&(s=MC.default.relative(b.cwd,s)),{label:`${t.name} [${o}] ${s}`,filterText:`${t.name}`,location:t.location}}doHighlight(){let{nvim:e}=this;e.pauseNotification(),e.command("syntax match CocSymbolsName /\\v^\\s*\\S+/ contained containedin=CocSymbolsLine",!0),e.command("syntax match CocSymbolsKind /\\[\\w\\+\\]\\s*\\t/ contained containedin=CocSymbolsLine",!0),e.command("syntax match CocSymbolsFile /\\S\\+$/ contained containedin=CocSymbolsLine",!0),e.command("highlight default link CocSymbolsName Normal",!0),e.command("highlight default link CocSymbolsKind Typedef",!0),e.command("highlight default link CocSymbolsFile Comment",!0),e.resumeNotification().catch(t=>{})}},qz=NC;var Bz=U()("list-manager"),jz=["","","","<2-LeftMouse>"],Uz=class{constructor(){this.plugTs=0;this.sessionsMap=new Map;this.disposables=[];this.listMap=new Map}init(e){this.nvim=e,this.config=new kv,this.prompt=new XH(e,this.config),this.mappings=new JH(this,e,this.config);let t=this.config.get("selectedSignText","*");e.command(`sign define CocSelected text=${t} texthl=CocSelectedText linehl=CocSelectedLine`,!0),A.on("InputChar",this.onInputChar,this,this.disposables),A.on("FocusGained",$z.default(async()=>{await this.getCurrentSession()&&this.prompt.drawPrompt()},100),null,this.disposables);let i;A.on("WinEnter",n=>{let o=this.getSessionByWinid(n);o&&this.prompt.start(o.listOptions)},null,this.disposables),A.on("WinLeave",n=>{this.getSessionByWinid(n)&&this.prompt.cancel()}),this.disposables.push(ed.Disposable.create(()=>{i&&clearTimeout(i)})),this.prompt.onDidChangeInput(()=>{let{session:n}=this;!n||(n.onInputChange(),n.history.filter())}),this.registerList(new Tz(e)),this.registerList(new cs(e)),this.registerList(new qz(e)),this.registerList(new Az(e)),this.registerList(new yz(e)),this.registerList(new Dz(e)),this.registerList(new wz(e)),this.registerList(new Lz(e)),this.registerList(new Oz(e)),this.registerList(new Rz(e,this.listMap)),this.registerList(new Cz(e))}async start(e){let t=this.parseArgs(e);if(!t)return;let{name:i}=t.list,n=this.sessionsMap.get(i);n&&n.dispose(),this.prompt.start(t.options);let o=new cz(this.nvim,this.prompt,t.list,t.options,t.listArgs,this.config);this.sessionsMap.set(i,o),this.lastSession=o;try{await o.start(e)}catch(s){this.nvim.call("coc#prompt#stop_prompt",["list"],!0);let a=s instanceof Error?s.message:s.toString();C.showMessage(`Error on "CocList ${i}": ${a}`,"error"),Bz.error(s)}}getSessionByWinid(e){for(let t of this.sessionsMap.values())if(t&&t.winid==e)return this.lastSession=t,t;return null}async getCurrentSession(){let{id:e}=await this.nvim.window;for(let t of this.sessionsMap.values())if(t&&t.winid==e)return this.lastSession=t,t;return null}async resume(e){var t;if(!e)await((t=this.session)==null?void 0:t.resume());else{let i=this.sessionsMap.get(e);if(!i){C.showMessage(`Can't find exists ${e} list`);return}await i.resume()}}async doAction(e){let t=this.lastSession;!t||await t.doAction(e)}async first(e){let t=this.getSession(e);t&&await t.first()}async last(e){let t=this.getSession(e);t&&await t.last()}async previous(e){let t=this.getSession(e);t&&await t.previous()}async next(e){let t=this.getSession(e);t&&await t.next()}getSession(e){return e?this.sessionsMap.get(e):this.session}async cancel(e=!0){this.prompt.cancel(),!!e&&this.session&&await this.session.hide()}reset(){this.prompt.cancel(),this.lastSession=void 0;for(let e of this.sessionsMap.values())e.dispose();this.sessionsMap.clear(),this.nvim.call("coc#prompt#stop_prompt",["list"],!0)}switchMatcher(){var e;(e=this.session)==null||e.switchMatcher()}async togglePreview(){let{nvim:e}=this,t=await e.call("coc#list#get_preview",[0]);t!=-1?(await e.createWindow(t).close(!0),await e.command("redraw")):await this.doAction("preview")}async chooseAction(){let{lastSession:e}=this;e&&await e.chooseAction()}parseArgs(e){let t=[],i=!1,n=!1,o=!1,s=!1,a=!1,l,u="",c="fuzzy",f="bottom",p=[],d=[];for(let y of e)if(!l&&y.startsWith("-"))d.push(y);else if(l)p.push(y);else{if(!/^\w+$/.test(y))return C.showMessage(`Invalid list option: "${y}"`,"error"),null;l=y}l=l||"lists";let h=b.getConfiguration(`list.source.${l}`);!d.length&&!p.length&&(d=h.get("defaultOptions",[])),p.length||(p=h.get("defaultArgs",[]));for(let y of d)if(y.startsWith("--input"))u=y.slice(8);else if(y=="--number-select"||y=="-N")o=!0;else if(y=="--auto-preview"||y=="-A")n=!0;else if(y=="--regex"||y=="-R")c="regex";else if(y=="--strict"||y=="-S")c="strict";else if(y=="--interactive"||y=="-I")i=!0;else if(y=="--top")f="top";else if(y=="--tab")f="tab";else if(y=="--ignore-case"||y=="--normal"||y=="--no-sort")t.push(y.slice(2));else if(y=="--first")a=!0;else if(y=="--no-quit")s=!0;else return C.showMessage(`Invalid option "${y}" of list`,"error"),null;let m=this.listMap.get(l);return m?i&&!m.interactive?(C.showMessage(`Interactive mode of "${l}" list not supported`,"error"),null):{list:m,listArgs:p,options:{numberSelect:o,autoPreview:n,noQuit:s,first:a,input:u,interactive:i,matcher:c,position:f,ignorecase:!!t.includes("ignore-case"),mode:t.includes("normal")?"normal":"insert",sort:!t.includes("no-sort")}}:(C.showMessage(`List ${l} not found`,"error"),null)}async onInputChar(e,t,i){if(e!="list")return;let{mode:n}=this.prompt,o=Date.now();if(t==""||this.plugTs&&o-this.plugTs<20){this.plugTs=o;return}if(!!t){if(t==""){await this.cancel();return}try{n=="insert"?await this.onInsertInput(t,i):await this.onNormalInput(t,i)}catch(s){C.showMessage(`Error on input ${t}: ${s}`),Bz.error(s)}}}async onInsertInput(e,t){let{session:i}=this;if(!i)return;if(jz.includes(e)){await this.onMouseEvent(e);return}if(!(await i.doNumberSelect(e)||await this.mappings.doInsertKeymap(e)||t)&&!(e.startsWith("<")&&e.endsWith(">")))for(let s of e){let a=s.codePointAt(0);if(a==65533||a<32||a>=127&&a<=159)return;await this.prompt.acceptCharacter(s)}}async onNormalInput(e,t){if(jz.includes(e)){await this.onMouseEvent(e);return}await this.mappings.doNormalKeymap(e)||await this.feedkeys(e)}onMouseEvent(e){if(this.session)return this.session.onMouseEvent(e)}async feedkeys(e,t=!0){let{nvim:i}=this;e=e.startsWith("<")&&e.endsWith(">")?`\\${e}`:e,await i.call("coc#prompt#stop_prompt",["list"]),await i.call("eval",[`feedkeys("${e}", "${t?"i":"in"}")`]),this.prompt.start()}async command(e){let{nvim:t}=this;await t.call("coc#prompt#stop_prompt",["list"]),await t.command(e),this.prompt.start()}async normal(e,t=!0){let{nvim:i}=this;await i.call("coc#prompt#stop_prompt",["list"]),await i.command(`normal${t?"!":""} ${e}`),this.prompt.start()}async call(e){if(this.session)return await this.session.call(e)}get session(){return this.lastSession}registerList(e){let{name:t}=e,i=this.listMap.get(t);return this.listMap.has(t)&&(i&&(typeof i.dispose=="function"&&i.dispose(),this.listMap.delete(t)),C.showMessage(`list "${t}" recreated.`)),this.listMap.set(t,e),ge.addSchemeProperty(`list.source.${t}.defaultOptions`,{type:"array",default:e.interactive?["--interactive"]:[],description:`Default list options of "${t}" list, only used when both list option and argument are empty.`,uniqueItems:!0,items:{type:"string",enum:["--top","--normal","--no-sort","--input","--tab","--strict","--regex","--ignore-case","--number-select","--interactive","--auto-preview","--first","--no-quit"]}}),ge.addSchemeProperty(`list.source.${t}.defaultArgs`,{type:"array",default:[],description:`Default argument list of "${t}" list, only used when list argument is empty.`,uniqueItems:!0,items:{type:"string"}}),ed.Disposable.create(()=>{typeof e.dispose=="function"&&e.dispose(),this.listMap.delete(t)})}get names(){return Array.from(this.listMap.keys())}get descriptions(){let e={};for(let t of this.listMap.keys()){let i=this.listMap.get(t);e[t]=i.description}return e}async loadItems(e){let t=[e],i=this.parseArgs(t);if(!i)return;let{list:n,options:o,listArgs:s}=i,l=new ed.CancellationTokenSource().token,u=await this.nvim.eval('[win_getid(),bufnr("%")]');return await n.loadItems({options:o,args:s,input:"",cwd:b.cwd,window:this.nvim.createWindow(u[0]),buffer:this.nvim.createBuffer(u[1]),listWindow:null},l)}toggleMode(){let e=this.lastSession;e&&e.toggleMode()}get isActivated(){var e;return((e=this.session)==null?void 0:e.winid)!=null}stop(){let e=this.lastSession;e&&e.stop()}dispose(){for(let e of this.sessionsMap.values())e.dispose();this.sessionsMap.clear(),this.config&&this.config.dispose(),this.lastSession=void 0,z(this.disposables)}},Kt=new Uz;function Yye(){let r=e=>e==="coc.nvim"?Hz():this.require(e);return r.resolve=e=>Pn._resolveFilename(e,this),r.main=process.mainModule,r.extensions=Pn._extensions,r.cache=Pn._cache,r}function Xye(r){return function(e,t){let i=Yye.call(this),n=Gz.dirname(t),o=e.replace(/^\#\!.*/,""),s=Pn.wrap(o),a=qv.runInContext(s,r,{filename:t}),l=[this.exports,i,this,t,n];return a.apply(this.exports,l)}}function Zye(r,e){let t=new Pn(r);t.paths=Pn._nodeModulePaths(r);let i=qv.createContext({module:t,Buffer,console:{debug:(...n)=>{e.debug.apply(e,n)},log:(...n)=>{e.debug.apply(e,n)},error:(...n)=>{e.error.apply(e,n)},info:(...n)=>{e.info.apply(e,n)},warn:(...n)=>{e.warn.apply(e,n)}}});Z5(i,global),i.Reflect=Reflect,i.require=function(o){let s=Pn.prototype._compile;Pn.prototype._compile=Xye(i);let a=i.module.require(o);return Pn.prototype._compile=s,a},i.process=new process.constructor;for(let n of Object.keys(process))i.process[n]=process[n];return Kye.forEach(n=>{i.process[n]=Jye(n)}),i.process.chdir=()=>{},i.process.umask=n=>{if(typeof n!="undefined")throw new Error("Cannot use process.umask() to change mask (read-only)");return process.umask()},i}function Kz(r,e,t=!1){if(t||!zz.default.existsSync(e))return{activate:()=>{},deactivate:null};let i=Zye(e,Vz(`extension:${r}`));delete Pn._cache[require.resolve(e)];let n=i.require(e),o=n&&n.activate||n;return typeof o!="function"?{activate:()=>{},deactivate:null}:{activate:o,deactivate:typeof n.deactivate=="function"?n.deactivate:null}}var Qz=U(),Er=Qz("extensions"),e9=class{constructor(){this.extensions=new Map;this.disabled=new Set;this._onDidLoadExtension=new $v.Emitter;this._onDidActiveExtension=new $v.Emitter;this._onDidUnloadExtension=new $v.Emitter;this._additionalSchemes={};this.activated=!1;this.disposables=[];this.ready=!0;this.onDidLoadExtension=this._onDidLoadExtension.event;this.onDidActiveExtension=this._onDidActiveExtension.event;this.onDidUnloadExtension=this._onDidUnloadExtension.event;let e=global.hasOwnProperty("__TEST__")?Ie.default.join(__dirname,"__tests__"):process.env.COC_DATA_HOME,t=this.root=Ie.default.join(e,"extensions");at.default.existsSync(t)||at.default.mkdirpSync(t);let i=Ie.default.join(t,"package.json");at.default.existsSync(i)||at.default.writeFileSync(i,'{"dependencies":{}}',"utf8");let n=Ie.default.join(t,"db.json");this.db=new eg(n)}get outputChannel(){return this._outputChannel?this._outputChannel:(this._outputChannel=C.createOutputChannel("extensions"),this._outputChannel)}async init(){let e=this.db.fetch("extension")||{},t=Object.keys(e);for(let o of t)e[o].disabled==!0&&this.disabled.add(o);if(process.env.COC_NO_PLUGINS)return;let i=await this.globalExtensionStats(),n=await this.localExtensionStats(i.map(o=>o.id));i=i.concat(n),this.memos=new Y5(Ie.default.resolve(this.root,"../memos.json")),i.map(o=>{let s=o.isLocal?Yr.Local:Yr.Global;try{this.createExtension(o.root,o.packageJSON,s)}catch(a){Er.error(`Error on create ${o.root}:`,a)}}),await this.loadFileExtensions(),me.register({id:"extensions.forceUpdateAll",execute:async()=>{let o=await this.cleanExtensions();Er.info(`Force update extensions: ${o}`),await this.installExtensions(o)}},!1,"remove all global extensions and install them"),b.onDidRuntimePathChange(async o=>{for(let s of o)s&&this.checkDirectory(s)===!0&&await this.loadExtension(s)},null,this.disposables)}async activateExtensions(){this.activated=!0;for(let o of this.extensions.values()){let{id:s,packageJSON:a}=o.extension;await this.setupActiveEvents(s,a)}let e=new mn(b.nvim);if(A.on("CursorMoved",Jz.debounce(async o=>{if(this.installBuffer&&o==this.installBuffer.bufnr){let s=await b.nvim.call("line",["."]),a=this.installBuffer.getMessages(s-1),l=a&&a.length?[{content:a.join(` -`),filetype:"txt"}]:[];await e.show(l,{modes:["n"]})}},500)),global.hasOwnProperty("__TEST__"))return;this.checkExtensions().logError();let t=b.getConfiguration("coc.preferences"),i=t.get("extensionUpdateCheck","never"),n=t.get("silentAutoupdate",!0);if(i!="never"){let o=new Date,s=new Date(o.getFullYear(),o.getMonth(),o.getDate()-(i=="daily"?0:7)),a=this.db.fetch("lastUpdate");if(a&&Number(a)>s.getTime())return;this.outputChannel.appendLine("Start auto update..."),this.updateExtensions(!1,n).logError()}}async updateExtensions(e,t=!1){if(!this.npm)return;let i=await this.getLockedList(),n=await this.globalExtensionStats();n=n.filter(l=>![...i,...this.disabled].includes(l.id)),this.db.push("lastUpdate",Date.now()),t&&C.showMessage("Updating extensions, checkout output:///extensions for details.","more");let o=this.installBuffer=new F0(!0,e,t?this.outputChannel:void 0);o.setExtensions(n.map(l=>l.id)),await o.show(b.nvim);let s=gv(this.npm,this.modulesFolder);await xf(n,l=>{let{id:u}=l;o.startProgress([u]);let c=l.exotic?l.uri:null,f=s(u);return f.on("message",(p,d)=>{o.addMessage(u,p,d)}),f.update(c).then(p=>{o.finishProgress(u,!0),p&&this.loadExtension(p).logError()},p=>{o.addMessage(u,p.message),o.finishProgress(u,!1)})},t?1:3)}async checkExtensions(){let{globalExtensions:e}=b.env;if(e&&e.length){let t=this.filterGlobalExtensions(e);this.installExtensions(t).logError()}}get installer(){return gv(this.npm,this.modulesFolder)}async installExtensions(e=[]){let{npm:t}=this;if(!t||!e.length)return;e=ng(e);let i=this.installBuffer=new F0;i.setExtensions(e),await i.show(b.nvim);let n=gv(this.npm,this.modulesFolder);await xf(e,s=>{i.startProgress([s]);let a=n(s);return a.on("message",(l,u)=>{i.addMessage(s,l,u)}),a.install().then(l=>{i.finishProgress(s,!0);let u=Ie.default.join(this.modulesFolder,l);this.loadExtension(u).logError()},l=>{i.addMessage(s,l.message),i.finishProgress(s,!1),Er.error(`Error on install ${s}`,l)})})}getMissingExtensions(){let e=this.loadJson()||{dependencies:{}},t=[];for(let i of Object.keys(e.dependencies)){let n=Ie.default.join(this.modulesFolder,i);if(!at.default.existsSync(n)){let o=e.dependencies[i];o.startsWith("http")?t.push(o):t.push(i)}}return t}get npm(){let e=b.getConfiguration("npm").get("binPath","npm");e=b.expand(e);for(let t of[e,"yarnpkg","yarn","npm"])try{return Zz.default.sync(t)}catch(i){continue}return C.showMessage("Can't find npm or yarn in your $PATH","error"),null}get all(){return Array.from(this.extensions.values()).map(e=>e.extension).filter(e=>!this.isDisabled(e.id))}getExtension(e){return this.extensions.get(e)}getExtensionState(e){if(this.isDisabled(e))return"disabled";let i=this.extensions.get(e);if(!i)return"unknown";let{extension:n}=i;return n.isActive?"activated":"loaded"}async getExtensionStates(){let e=await this.localExtensionStats([]),t=await this.globalExtensionStats();return e.concat(t.filter(i=>e.find(n=>n.id==i.id)==null))}async getLockedList(){let e=await this.db.fetch("extension");return e=e||{},Object.keys(e).filter(t=>e[t].locked===!0)}async toggleLock(e){let t=`extension.${e}.locked`;await this.db.fetch(t)?this.db.delete(t):this.db.push(t,!0)}async toggleExtension(e){let t=this.getExtensionState(e);if(t==null)return;t=="activated"&&await this.deactivate(e);let i=`extension.${e}.disabled`;if(this.db.push(i,t!="disabled"),t!="disabled")this.disabled.add(e),await this.unloadExtension(e);else{this.disabled.delete(e);let n=Ie.default.join(this.modulesFolder,e);at.default.existsSync(n)&&await this.loadExtension(n)}await He(200)}async reloadExtension(e){let t=this.extensions.get(e);if(!t){C.showMessage(`Extension ${e} not registered`,"error");return}if(t.type==Yr.Internal){C.showMessage(`Can't reload internal extension "${t.id}"`,"warning");return}t.type==Yr.SingleFile?await this.loadExtensionFile(t.filepath):t.directory?await this.loadExtension(t.directory):C.showMessage(`Can't reload extension ${t.id}`,"warning")}async cleanExtensions(){let e=this.modulesFolder;if(!at.default.existsSync(e))return[];let t=this.globalExtensions,i=[];for(let n of t){let o=Ie.default.join(e,n),s=await at.default.lstat(o);!s||s&&s.isSymbolicLink()||(await this.unloadExtension(n),await at.default.remove(o),i.push(n))}return i}async uninstallExtension(e){try{if(!e.length)return;let[t,i]=ig(e,a=>this.globalExtensions.includes(a));i.length&&C.showMessage(`Extensions ${i} not global extensions, can't uninstall!`,"warning");let n=this.loadJson()||{dependencies:{}};for(let a of t){await this.unloadExtension(a),delete n.dependencies[a];let l=Ie.default.join(this.modulesFolder,a);at.default.existsSync(l)&&await at.default.remove(l)}let o={dependencies:{}};Object.keys(n.dependencies).sort().forEach(a=>{o.dependencies[a]=n.dependencies[a]});let s=Ie.default.join(this.root,"package.json");at.default.writeFileSync(s,JSON.stringify(o,null,2),{encoding:"utf8"}),C.showMessage(`Removed: ${t.join(" ")}`)}catch(t){C.showMessage(`Uninstall failed: ${t.message}`,"error")}}isDisabled(e){return this.disabled.has(e)}has(e){return this.extensions.has(e)}isActivated(e){let t=this.extensions.get(e);return!!(t&&t.extension.isActive)}async loadExtension(e){try{let t=Ie.default.dirname(e),i=Ie.default.normalize(t)!=Ie.default.normalize(this.modulesFolder),n=Ie.default.join(e,"package.json"),o=JSON.parse(at.default.readFileSync(n,"utf8")),{name:s}=o;return this.isDisabled(s)?!1:(await this.unloadExtension(s),this.createExtension(e,Object.freeze(o),i?Yr.Local:Yr.Global),!0)}catch(t){return C.showMessage(`Error on load extension from "${e}": ${t.message}`,"error"),Er.error(`Error on load extension from ${e}`,t),!1}}async loadFileExtensions(){if(!process.env.COC_VIMCONFIG)return;let e=Ie.default.join(process.env.COC_VIMCONFIG,"coc-extensions");if(!at.default.existsSync(e))return;let t=await at.default.readdir(e);t=t.filter(i=>i.endsWith(".js"));for(let i of t)await this.loadExtensionFile(Ie.default.join(e,i))}loadedExtensions(){return Array.from(this.extensions.keys())}async watchExtension(e){let t=this.extensions.get(e);if(!t){C.showMessage(`extension ${e} not found`,"error");return}if(e.startsWith("single-"))C.showMessage(`watching ${t.filepath}`),this.disposables.push(Rl(t.filepath,async()=>{await this.loadExtensionFile(t.filepath),C.showMessage(`reloaded ${e}`)}));else{let i=b.getWatchmanPath();if(!i){C.showMessage("watchman not found","error");return}let n=await ia.createClient(i,t.directory);if(!n){C.showMessage("Can't create watchman client, check output:///watchman");return}C.showMessage(`watching ${t.directory}`),this.disposables.push(n),n.subscribe("**/*.js",async()=>{await this.reloadExtension(e),C.showMessage(`reloaded ${e}`)}).then(o=>{this.disposables.push(o)},o=>{Er.error(o)})}}async loadExtensionFile(e){let t=Ie.default.basename(e),i=Ie.default.basename(e,".js"),n="single-"+i;if(this.isDisabled(n))return;let o=Ie.default.dirname(e),s={name:n,main:t,engines:{coc:"^0.0.79"}},a=Ie.default.join(o,i+".json"),l=await It(a);if(l&&l.isFile()){let u=await Vl(a,"utf8"),c=JSON.parse(u);if(c){let f=["activationEvents","contributes"];for(let p of f)c[p]&&(s[p]=c[p])}}await this.unloadExtension(n),this.createExtension(o,s,Yr.SingleFile)}async activate(e){if(this.isDisabled(e))throw new Error(`Extension ${e} is disabled!`);let t=this.extensions.get(e);if(!t)throw new Error(`Extension ${e} not registered!`);let{extension:i}=t;return i.isActive?!0:(await Promise.resolve(i.activate()),i.isActive?(this._onDidActiveExtension.fire(i),!0):!1)}async deactivate(e){let t=this.extensions.get(e);return t?(await Promise.resolve(t.deactivate()),!0):!1}async call(e,t,i){let n=this.extensions.get(e);if(!n)throw new Error(`extension ${e} not registered`);let{extension:o}=n;o.isActive||await this.activate(e);let{exports:s}=o;if(!s||!s.hasOwnProperty(t))throw new Error(`method ${t} not found on extension ${e}`);return await Promise.resolve(s[t].apply(null,i))}getExtensionApi(e){let t=this.extensions.get(e);if(!t)return null;let{extension:i}=t;return i.isActive?i.exports:null}registerExtension(e,t){let{id:i,packageJSON:n}=e;this.extensions.set(i,{id:i,type:Yr.Internal,extension:e,deactivate:t,isLocal:!0});let{contributes:o}=n;if(o){let{configuration:s}=o;if(s&&s.properties){let{properties:a}=s,l={};for(let u of Object.keys(a)){let c=a[u].default;c!=null&&(l[u]=c)}b.configurations.extendsDefaults(l)}}this._onDidLoadExtension.fire(e),this.setupActiveEvents(i,n).logError()}get globalExtensions(){let e=this.loadJson();return!e||!e.dependencies?[]:Object.keys(e.dependencies)}async globalExtensionStats(){let e=this.loadJson();if(!e||!e.dependencies)return[];let{modulesFolder:t}=this;return(await Promise.all(Object.keys(e.dependencies).map(n=>new Promise(async o=>{try{let s=e.dependencies[n],a=Ie.default.join(t,n),l=this.checkDirectory(a);if(l instanceof Error)return C.showMessage(`Unable to load global extension at ${a}: ${l.message}`,"error"),Er.error(`Error on load ${a}`,l),o(null);let u=await Vl(Ie.default.join(a,"package.json"),"utf8");a=await at.default.realpath(a);let c=JSON.parse(u),f=c&&c.version||"",p=c&&c.description||"",d=Yz.default.isValid(s)?s:"";o({id:n,isLocal:!1,version:f,description:p,exotic:/^https?:/.test(s),uri:d.replace(/\.git(#master)?$/,""),root:a,state:this.getExtensionState(n),packageJSON:Object.freeze(c)})}catch(s){Er.error(s),o(null)}})))).filter(n=>n!=null)}async localExtensionStats(e){let i=(await b.nvim.eval("&runtimepath")).split(",");return(await Promise.all(i.map(o=>new Promise(async s=>{try{if(this.checkDirectory(o)!==!0)return s(null);let l=Ie.default.join(o,"package.json"),u=await Vl(l,"utf8"),c=JSON.parse(u),f=this.extensions.get(c.name);if(f&&!f.isLocal)return Er.info(`Extension "${c.name}" in runtimepath already loaded.`),s(null);if(e.includes(c.name))return Er.info(`Skipped load vim plugin from "${o}", "${c.name}" already global extension.`),s(null);let p=c&&c.version||"",d=c&&c.description||"";s({id:c.name,isLocal:!0,version:p,description:d,exotic:!1,root:o,state:this.getExtensionState(c.name),packageJSON:Object.freeze(c)})}catch(a){Er.error(a),s(null)}})))).filter(o=>o!=null)}loadJson(){let{root:e}=this,t=Ie.default.join(e,"package.json");if(!at.default.existsSync(t))return null;let i=[],n=at.default.readFileSync(t,"utf8"),o=Hl(n,i,{allowTrailingComma:!0});return i&&i.length>0&&(C.showMessage(`Error on parse ${t}`,"error"),b.nvim.call("coc#util#open_file",["edit",t],!0)),o}get schemes(){return this._additionalSchemes}addSchemeProperty(e,t){this._additionalSchemes[e]=t,b.configurations.extendsDefaults({[e]:t.default})}async setupActiveEvents(e,t){let{activationEvents:i}=t;if(!this.canActivate(e))return;if(!i||Array.isArray(i)&&i.includes("*")){await this.activate(e).catch(s=>{C.showMessage(`Error on activate extension ${e}: ${s.message}`),this.outputChannel.appendLine(`Error on activate extension ${e}. -${s.message} - ${s.stack}`)});return}let n=[],o=()=>(z(n),new Promise(s=>{if(!this.canActivate(e))return this.outputChannel.appendLine(`Extension ${e} is disabled or not loaded.`),s();let a=setTimeout(()=>{this.outputChannel.appendLine(`Extension ${e} activate cost more than 1s`),s()},1e3);this.activate(e).then(()=>{clearTimeout(a),s()},l=>{clearTimeout(a),C.showMessage(`Error on activate extension ${e}: ${l.message}`),this.outputChannel.appendLine(`Error on activate extension ${e}:${l.message} - ${l.stack}`),s()})}));for(let s of i){let a=s.split(":"),l=a[0];if(l=="onLanguage"){if(b.filetypes.has(a[1])){await o();return}b.onDidOpenTextDocument(u=>{u.languageId==a[1]&&o()},null,n)}else if(l=="onCommand")me.onCommandList.push(a[1]),A.on("Command",async u=>{u==a[1]&&(await o(),await He(500))},null,n);else if(l=="workspaceContains"){let u=async()=>{let f=b.workspaceFolders.map(p=>$.parse(p.uri).fsPath);for(let p of f)if(jo(p,a[1].split(/\s+/)))return await o(),!0};if(await u())return;b.onDidChangeWorkspaceFolders(u,null,n)}else if(l=="onFileSystem"){for(let u of b.documents)if($.parse(u.uri).scheme==a[1]){await o();return}b.onDidOpenTextDocument(u=>{$.parse(u.uri).scheme==a[1]&&o()},null,n)}else C.showMessage(`Unsupported event ${s} of ${e}`,"error")}}createExtension(e,t,i){let n=t.name,o=!1,s=null,a=Ie.default.join(e,t.main||"index.js"),l,u=[],c={activate:async()=>{if(o)return s;let p={subscriptions:u,extensionPath:e,globalState:this.memos.createMemento(`${n}|global`),workspaceState:this.memos.createMemento(`${n}|${b.rootPath}`),asAbsolutePath:d=>Ie.default.join(e,d),storagePath:Ie.default.join(this.root,`${n}-data`),logger:Qz(n)};if(o=!0,!l)try{let d=!(t.engines||{}).hasOwnProperty("coc");l=Kz(n,a,d)}catch(d){Er.error(`Error on createExtension ${n} from ${a}`,d);return}try{s=await Promise.resolve(l.activate(p)),Er.debug("activate:",n)}catch(d){o=!1,Er.error(`Error on active extension ${n}: ${d.stack}`,d)}return s}};Object.defineProperties(c,{id:{get:()=>n,enumerable:!0},packageJSON:{get:()=>t,enumerable:!0},extensionPath:{get:()=>e,enumerable:!0},isActive:{get:()=>o,enumerable:!0},exports:{get:()=>s,enumerable:!0}}),this.extensions.set(n,{id:n,type:i,isLocal:i==Yr.Local,extension:c,directory:e,filepath:a,deactivate:()=>{if(!!o&&(o=!1,z(u),u.splice(0,u.length),u=[],l&&l.deactivate))try{return Promise.resolve(l.deactivate()).catch(p=>{Er.error(`Error on ${n} deactivate: `,p)})}catch(p){Er.error(`Error on ${n} deactivate: `,p)}}});let{contributes:f}=t;if(f){let{configuration:p,rootPatterns:d,commands:h}=f;if(p&&p.properties){let{properties:m}=p,y={};for(let g of Object.keys(m)){let w=m[g].default;w!=null&&(y[g]=w)}b.configurations.extendsDefaults(y)}if(d&&d.length)for(let m of d)b.addRootPattern(m.filetype,m.patterns);if(h&&h.length)for(let m of h)me.titles.set(m.command,m.title)}this._onDidLoadExtension.fire(c),this.activated&&this.setupActiveEvents(n,t).logError()}filterGlobalExtensions(e){let t=new Map;e.forEach(s=>{let a=this.getExtensionName(s);a&&t.set(a,s)});let i=this.loadJson(),n=[],o=[];if(i&&i.dependencies)for(let s of Object.keys(i.dependencies)){let a=i.dependencies[s];typeof a=="string"&&at.default.existsSync(Ie.default.join(this.modulesFolder,s,"package.json"))&&(o.push(s),/^https?:/.test(a)&&n.push(a))}for(let s of t.keys()){if(this.disabled.has(s)||this.extensions.has(s)){t.delete(s);continue}(/^https?:/.test(s)&&n.some(a=>a.startsWith(s))||o.includes(s))&&t.delete(s)}return Array.from(t.values())}getExtensionName(e){return/^https?:/.test(e)||!e.includes("@")?e:e.replace(/@[\d.]+$/,"")}get modulesFolder(){return Ie.default.join(this.root,global.hasOwnProperty("__TEST__")?"":"node_modules")}canActivate(e){return!this.disabled.has(e)&&this.extensions.has(e)}async unloadExtension(e){this.extensions.get(e)&&(await this.deactivate(e),this.extensions.delete(e),this._onDidUnloadExtension.fire(e))}checkDirectory(e){try{let t=Ie.default.join(e,"package.json");if(!at.default.existsSync(t))throw new Error("package.json not found");let i=JSON.parse(at.default.readFileSync(t,"utf8")),{name:n,engines:o,main:s}=i;if(!n||!o)throw new Error("can't find name & engines in package.json");if(!o||!xt(o))throw new Error(`invalid engines in ${t}`);if(s&&!at.default.existsSync(Ie.default.join(e,s)))throw new Error(`main file ${s} not found, you may need to build the project.`);let a=Object.keys(o);if(!a.includes("coc")&&!a.includes("vscode"))throw new Error("Engines in package.json doesn't have coc or vscode");if(a.includes("coc")){let l=o.coc.replace(/^\^/,">=");if(!Xz.default.satisfies(b.version,l))throw new Error(`Please update coc.nvim, ${i.name} requires coc.nvim ${o.coc}`)}return!0}catch(t){return t}}dispose(){z(this.disposables)}},ge=new e9;var Q4e=U()("model-source"),qC=class{constructor(e){this._disabled=!1;this.nvim=b.nvim,this.name=e.name,this.filepath=e.filepath||"",this.sourceType=e.sourceType||Xr.Native,this.isSnippet=!!e.isSnippet,this.defaults=e}get priority(){return this.getConfig("priority",1)}get triggerOnly(){let e=this.defaults.triggerOnly;return typeof e=="boolean"?e:!this.triggerCharacters&&!this.triggerPatterns?!1:Array.isArray(this.triggerPatterns)&&this.triggerPatterns.length!=0}get triggerCharacters(){return this.getConfig("triggerCharacters",null)}get optionalFns(){return this.defaults.optionalFns||[]}get triggerPatterns(){let e=this.getConfig("triggerPatterns",null);return!e||e.length==0?null:e.map(t=>typeof t=="string"?new RegExp(t+"$"):t)}get shortcut(){let e=this.getConfig("shortcut","");return e||this.name.slice(0,3)}get enable(){return this._disabled?!1:this.getConfig("enable",!0)}get filetypes(){return this.getConfig("filetypes",null)}get disableSyntaxes(){return this.getConfig("disableSyntaxes",[])}getConfig(e,t){let i=b.getConfiguration(`coc.source.${this.name}`);return t=this.defaults.hasOwnProperty(e)?this.defaults[e]:t,i.get(e,t)}toggle(){this._disabled=!this._disabled}get firstMatch(){return this.getConfig("firstMatch",!0)}get menu(){let{shortcut:e}=this;return e?`[${e}]`:""}filterWords(e,t){let{firstMatch:i}=this,n=[],{input:o}=t,s=t.word;if(!o.length)return[];let a=o[0];for(let l of e)!l||l.length<3||i&&a!=l[0]||!i&&a.toLowerCase()!=l[0].toLowerCase()||l==s||l==o||n.push(l);return n}fixStartcol(e,t){let{col:i,input:n,line:o,bufnr:s}=e,a=Rt(o,0,i),l=b.getDocument(s);if(!l)return i;let{chars:u}=l;for(let c=a.length-1;c>=0;c--){let f=a[c];if(!u.isKeywordChar(f)&&!t.includes(f))break;n=`${f}${n}`,i=i-1}return e.col=i,e.input=n,i}async shouldComplete(e){let{disableSyntaxes:t}=this;if(e.synname&&t&&t.length){let n=(e.synname||"").toLowerCase();if(t.findIndex(o=>n.includes(o.toLowerCase()))!==-1)return!1}let i=this.defaults.shouldComplete;return i?await Promise.resolve(i.call(this,e)):!0}async refresh(){let e=this.defaults.refresh;e&&await Promise.resolve(e.call(this))}async onCompleteDone(e,t){let i=this.defaults.onCompleteDone;i&&await Promise.resolve(i.call(this,e,t))}async doComplete(e,t){let i=this.defaults.doComplete;return i?await Promise.resolve(i.call(this,e,t)):null}},Tn=qC;var sHe=U()("model-source-vim"),$C=class extends Tn{async callOptinalFunc(e,t){if(!this.optionalFns.includes(e))return null;let n=`coc#source#${this.name}#${e}`,o;try{o=await this.nvim.call(n,t)}catch(s){return C.showMessage(`Vim error from source ${this.name}: ${s.message}`,"error"),null}return o}async shouldComplete(e){return await super.shouldComplete(e)?this.optionalFns.includes("should_complete")?!!await this.callOptinalFunc("should_complete",[e]):!0:!1}async refresh(){await this.callOptinalFunc("refresh",[])}async onCompleteDone(e,t){await super.onCompleteDone(e,t),!!this.optionalFns.includes("on_complete")&&await this.callOptinalFunc("on_complete",[e])}onEnter(e){if(!this.optionalFns.includes("on_enter"))return;let t=b.getDocument(e);if(!t)return;let{filetypes:i}=this;i&&!i.includes(t.filetype)||this.callOptinalFunc("on_enter",[{bufnr:e,uri:t.uri,languageId:t.filetype}]).logError()}async doComplete(e,t){let{col:i,input:n,line:o,colnr:s}=e,a=await this.callOptinalFunc("get_startcol",[e]);if(t.isCancellationRequested)return;if(a){if(a<0)return null;a=Number(a),(isNaN(a)||a<0)&&(a=i),a!==i&&(n=Rt(o,a,s-1),e=Object.assign({},e,{col:a,changed:i-a,input:n}))}let l=await this.nvim.callAsync("coc#util#do_complete",[this.name,e]);if(!l||l.length==0||t.isCancellationRequested)return null;if(this.firstMatch&&n.length){let c=n[0];l=l.filter(f=>{let p=f.filterText?f.filterText[0]:f.word[0];return Yp(c,p)})}l=l.map(c=>{if(typeof c=="string")return{word:c,menu:this.menu,isSnippet:this.isSnippet};let f=c.menu?c.menu+" ":"";return c.menu=`${f}${this.menu}`,c.isSnippet=this.isSnippet,delete c.user_data,c});let u={items:l};return a&&(u.startcol=a),u}},t9=$C;var h9=U()("sources"),m9=class{constructor(){this.sourceMap=new Map;this.disposables=[];this.remoteSourcePaths=[]}get nvim(){return b.nvim}createNativeSources(){try{this.disposables.push(i9().regist(this.sourceMap)),this.disposables.push(o9().regist(this.sourceMap)),this.disposables.push(u9().regist(this.sourceMap))}catch(e){console.error("Create source error:"+e.message)}}async createVimSourceExtension(e,t){let i=Hv.default.basename(t,".vim");try{await e.command(`source ${t}`);let n=await e.call("coc#util#remote_fns",i);for(let c of["init","complete"])if(!n.includes(c))return C.showMessage(`${c} not found for source ${i}`,"error"),null;let o=await e.call(`coc#source#${i}#init`,[]),s={name:`coc-source-${i}`,engines:{coc:">= 0.0.1"},activationEvents:o.filetypes?o.filetypes.map(c=>`onLanguage:${c}`):["*"],contributes:{configuration:{properties:{[`coc.source.${i}.enable`]:{type:"boolean",default:!0},[`coc.source.${i}.firstMatch`]:{type:"boolean",default:!!o.firstMatch},[`coc.source.${i}.triggerCharacters`]:{type:"number",default:o.triggerCharacters||[]},[`coc.source.${i}.priority`]:{type:"number",default:o.priority||9},[`coc.source.${i}.shortcut`]:{type:"string",default:o.shortcut||i.slice(0,3).toUpperCase(),description:"Shortcut text shown in complete menu."},[`coc.source.${i}.disableSyntaxes`]:{type:"array",default:[],items:{type:"string"}},[`coc.source.${i}.filetypes`]:{type:"array",default:o.filetypes||null,description:"Enabled filetypes.",items:{type:"string"}}}}}},a=new t9({name:i,filepath:t,sourceType:Xr.Remote,optionalFns:n.filter(c=>!["init","complete"].includes(c))}),l=!1,u={id:s.name,packageJSON:s,exports:void 0,extensionPath:t,activate:()=>(l=!0,this.addSource(a),Promise.resolve())};Object.defineProperty(u,"isActive",{get:()=>l}),ge.registerExtension(u,()=>{l=!1,this.removeSource(a)})}catch(n){C.showMessage(`Error on create vim source ${i}: ${n.message}`,"error")}}createRemoteSources(){let{runtimepath:e}=b.env,t=e.split(",");for(let i of t)this.createVimSources(i).logError()}async createVimSources(e){if(this.remoteSourcePaths.includes(e))return;this.remoteSourcePaths.push(e);let t=Hv.default.join(e,"autoload/coc/source"),i=await It(t);if(i&&i.isDirectory()){let n=await p9.default.promisify(f9.default.readdir)(t);n=n.filter(s=>s.endsWith(".vim"));let o=n.map(s=>Hv.default.join(t,s));if(o.length==0)return;await Promise.all(o.map(s=>this.createVimSourceExtension(this.nvim,s)))}}init(){this.createNativeSources(),this.createRemoteSources(),A.on("BufEnter",this.onDocumentEnter,this,this.disposables),b.watchOption("runtimepath",async(e,t)=>{let i=c9.default(e,t);for(let[n,o]of i)if(n==1){let s=o.replace(/,$/,"").split(",");for(let a of s)a&&await this.createVimSources(a)}},this.disposables)}get names(){return Array.from(this.sourceMap.keys())}get sources(){return Array.from(this.sourceMap.values())}has(e){return this.names.findIndex(t=>t==e)!=-1}getSource(e){return e&&this.sourceMap.get(e)||null}async doCompleteResolve(e,t){let i=this.getSource(e.source);if(i&&typeof i.onCompleteResolve=="function")try{await Promise.resolve(i.onCompleteResolve(e,t))}catch(n){h9.error("Error on complete resolve:",n.stack)}}async doCompleteDone(e,t){let i=JSON.parse(e.user_data),n=this.getSource(i.source);n&&typeof n.onCompleteDone=="function"&&await Promise.resolve(n.onCompleteDone(e,t))}shouldCommit(e,t){if(!e||!e.source)return!1;let i=this.getSource(e.source);return i&&i.sourceType==Xr.Service&&typeof i.shouldCommit=="function"?i.shouldCommit(e,t):!1}getCompleteSources(e){let{filetype:t}=e,i=Rt(e.line,0,e.colnr-1),n=e.input==""&&!!e.triggerCharacter,o=dm(e.filepath,e.bufnr,"",b.env.isCygwin);return n?this.getTriggerSources(i,t,o):this.getNormalSources(e.filetype,o)}getNormalSources(e,t){return this.sources.filter(i=>{let{filetypes:n,triggerOnly:o,documentSelector:s,enable:a}=i;return!(!a||o||n&&!n.includes(e)||s&&Xl(s,t,e)==0||this.disabledByLanguageId(i,e))})}checkTrigger(e,t,i){let{triggerCharacters:n,triggerPatterns:o}=e;return!n&&!o?!1:!!(i&&n&&n.includes(i)||o&&o.findIndex(s=>s.test(t))!==-1)}shouldTrigger(e,t,i){return this.getTriggerSources(e,t,i).length>0}getTriggerSources(e,t,i){let n=e.length?e[e.length-1]:"";return n?this.sources.filter(o=>{let{filetypes:s,enable:a,documentSelector:l}=o;return!a||s&&!s.includes(t)||l&&Xl(l,i,t)==0||this.disabledByLanguageId(o,t)?!1:this.checkTrigger(o,e,n)}):[]}addSource(e){let{name:t}=e;return this.names.includes(t)&&h9.warn(`Recreate source ${t}`),this.sourceMap.set(t,e),d9.Disposable.create(()=>{this.sourceMap.delete(t)})}removeSource(e){let t=typeof e=="string"?e:e.name;this.sourceMap.delete(t)}async refresh(e){for(let t of this.sources)(!e||t.name==e)&&typeof t.refresh=="function"&&await Promise.resolve(t.refresh())}toggleSource(e){if(!e)return;let t=this.getSource(e);!t||typeof t.toggle=="function"&&t.toggle()}sourceStats(){let e=[],t=this.sources;for(let i of t)e.push({name:i.name,priority:i.priority,triggerCharacters:i.triggerCharacters||[],shortcut:i.shortcut||"",filetypes:i.filetypes||[],filepath:i.filepath||"",type:i.sourceType==Xr.Native?"native":i.sourceType==Xr.Remote?"remote":"service",disabled:!i.enable});return e}onDocumentEnter(e){let{sources:t}=this;for(let i of t)!i.enable||typeof i.onEnter=="function"&&i.onEnter(e)}createSource(e){if(!e.name||!e.doComplete){console.error("name and doComplete required for createSource");return}let t=new Tn(Object.assign({sourceType:Xr.Service},e));return this.addSource(t)}disabledByLanguageId(e,t){let i=b.env.disabledSources,n=i?i[t]:[];return Array.isArray(n)&&n.includes(e.name)}dispose(){z(this.disposables)}},Ge=new m9;var Ta=S(W());function v9(r=0,e){for(let t=r;t=65&&r<=90}function g9(r,e){if(r==0)return!0;let t=e[r];if(!Jp(t))return!1;let i=e[r-1];return!!(!Jp(i)||y9(t)&&!y9(i))}function b9(r,e){if(e.length==0||r.length=r.length)return 0;let n=[],o=t[0],s=r.length,a=t.length==1;if(!Jp(o)){for(let c=e;ci||{}})}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(e=>e.isIncomplete)!==-1}async completeSource(e){let{col:t}=this.option,i=Object.assign({},this.option),n=this.config.timeout;n=Math.max(Math.min(n,15e3),500);try{if(typeof e.shouldComplete=="function"&&!await Promise.resolve(e.shouldComplete(i)))return null;let o=Date.now(),s=this.tokenSources.get(e.name);s&&s.cancel();let a=new Ta.CancellationTokenSource;this.tokenSources.set(e.name,a),await new Promise((l,u)=>{let{name:c}=e,f=setTimeout(()=>{this.nvim.command(`echohl WarningMsg| echom 'source ${e.name} timeout after ${n}ms'|echohl None`,!0),a.cancel()},n),p=!1,d=!1,h=!1,m=setTimeout(()=>{d||(h=!0,l(void 0))},cbe),y=()=>{d||(d=!0,g.dispose(),clearTimeout(m),clearTimeout(f),this.tokenSources.delete(c))},g=a.token.onCancellationRequested(()=>{g.dispose(),this.completing.delete(c),p=!0,y(),zv.debug(`Source "${c}" cancelled`),l(void 0)});this.completing.add(c),Promise.resolve(e.doComplete(i,a.token)).then(w=>{if(this.completing.delete(c),p)return;y();let x=Date.now()-o;if(zv.debug(`Source "${c}" takes ${x}ms`),w&&w.items&&w.items.length){if(w.priority=e.priority,w.source=c,h&&w.startcol&&w.startcol!=t)this.results=[w];else{let{results:E}=this,P=E.findIndex(k=>k.source==c);P!=-1?E.splice(P,1,w):E.push(w)}h&&this._onDidComplete.fire(),l(void 0)}else l(void 0)},w=>{this.completing.delete(c),y(),u(w)})})}catch(o){this.nvim.command(`echoerr 'Complete ${e.name} error: ${o.message.replace(/'/g,"''")}'`,!0),zv.error("Complete error:",e.name,o)}}async completeInComplete(e){let{results:t,document:i}=this;t.filter(f=>!f.isIncomplete).forEach(f=>{f.items.forEach(p=>delete p.user_data)});let s=t.filter(f=>f.isIncomplete).map(f=>f.source),{input:a,colnr:l,linenr:u}=this.option;Object.assign(this.option,{input:e,line:i.getline(u-1),colnr:l+(e.length-a.length),triggerCharacter:null,triggerForInComplete:!0});let c=this.sources.filter(f=>s.includes(f.name));return await Promise.all(c.map(f=>this.completeSource(f))),this.filterResults(e,Math.floor(Date.now()/1e3))}filterResults(e,t=0){let{results:i}=this;i.sort((h,m)=>h.source=="tabnine"?1:m.source=="tabnine"?-1:m.priority-h.priority);let n=Date.now(),{bufnr:o}=this.option,{snippetIndicator:s,removeDuplicateItems:a,fixInsertedWord:l,asciiCharactersOnly:u}=this.config,c=!l||t==0?"":this.getFollowPart();if(i.length==0)return[];let f=[],p=so(e),d=new Set;for(let h=0,m=i.length;h{let y=h.sortText,g=m.sortText,w=h.filterText,x=m.filterText;if(h.score!=m.score)return m.score-h.score;if(h.priority!=m.priority)return m.priority-h.priority;if(y&&g&&y!=g)return y{let{priority:s,source:a}=o,l=s<90,u=n.get(a)||0;return i&&l&&u==i||t&&!l&&u==t?!1:(n.set(a,u+1),!0)})}hasMatch(e){let{results:t}=this;if(!t)return!1;let i=so(e);for(let n=0,o=t.length;nOu(i,l.filterText||l.word))!==-1)return!0;return!1}async doComplete(){let e=this.option,{line:t,colnr:i,linenr:n,col:o}=this.option;if(this.config.localityBonus){let l=n-1;this.localBonus=this.document.getLocalifyBonus(Ta.Position.create(l,e.col-1),Ta.Position.create(l,i))}else this.localBonus=new Map;await Promise.all(this.sources.map(l=>this.completeSource(l)));let{results:s}=this;if(s.length==0)return[];let a=s.find(l=>l.startcol!=null&&l.startcol!=o);if(a){let{startcol:l}=a;e.col=l,e.input=Rt(t,l,i-1),this.results=[a]}return zv.info(`Results from: ${this.results.map(l=>l.source).join(",")}`),this.filterResults(e.input,Math.floor(Date.now()/1e3))}resolveCompletionItem(e){let{results:t}=this;if(!t)return null;try{if(e.user_data){let{source:i}=JSON.parse(e.user_data);return t.find(o=>o.source==i).items.find(o=>o.user_data==e.user_data)}for(let i of t){let n=i.items.find(o=>o.abbr==e.abbr&&o.info==e.info);if(n)return n}return null}catch(i){return null}}getFollowPart(){let{colnr:e,line:t}=this.option,i=Bf(t,e-1);return i==t.length?"":t.slice(i-t.length).match(/^\S?[\w-]*/)[0]}dispose(){if(!this._canceled){this._onDidComplete.dispose(),this._canceled=!0;for(let e of this.tokenSources.values())e.cancel();this.tokenSources.clear(),this.sources=[],this.results=[]}}},w9=BC;var VHe=U()("floating"),jC=class{constructor(e,t){this.nvim=e;this.isVim=t;this.winid=0;this.bufnr=0}async show(e,t,i,n){let{nvim:o}=this;e=e.filter(c=>c.content.trim().length>0);let{lines:s,codes:a,highlights:l}=qm(e);if(s.length==0){this.close();return}let u=await o.call("coc#float#create_pum_float",[this.winid,this.bufnr,s,{codes:a,highlights:l,maxWidth:i.maxPreviewWidth,pumbounding:t}]);if(this.isVim&&o.command("redraw",!0),!(!u||u.length==0)&&(this.winid=u[0],this.bufnr=u[1],n.isCancellationRequested)){this.close();return}}close(){let{winid:e,nvim:t}=this;this.winid=0,!!e&&(t.call("coc#float#close",[e],!0),this.isVim&&t.command("redraw",!0))}},x9=jC;function UC(r,e){let t,i,n,o=0;function s(){t=arguments;let l=Date.now()-o;return n||(o!=0&&l>=e?a():n=setTimeout(a,e-l)),i}function a(){n=0,o=Date.now(),i=r.apply(null,t),t=null}return s.clear=()=>{n&&clearTimeout(n)},s}var fs=U()("completion"),fbe=["abbr","menu","info","kind","icase","dup","empty","user_data"],D9=class{constructor(){this.activated=!1;this.disposables=[];this.complete=null;this.recentScores={};this.changedTick=0;this.insertCharTs=0;this.insertLeaveTs=0}init(){this.config=this.getCompleteConfig(),this.floating=new x9(b.nvim,b.env.isVim),A.on(["InsertCharPre","MenuPopupChanged","TextChangedI","CursorMovedI","InsertLeave"],()=>{this.triggerTimer&&(clearTimeout(this.triggerTimer),this.triggerTimer=null)},this,this.disposables),A.on("InsertCharPre",this.onInsertCharPre,this,this.disposables),A.on("InsertLeave",this.onInsertLeave,this,this.disposables),A.on("InsertEnter",this.onInsertEnter,this,this.disposables),A.on("TextChangedP",this.onTextChangedP,this,this.disposables),A.on("TextChangedI",this.onTextChangedI,this,this.disposables);let e=UC(this.onPumChange.bind(this),b.isVim?200:100);A.on("CompleteDone",async t=>{this.currItem=null,this.cancelResolve(),this.floating.close(),await this.onCompleteDone(t)},this,this.disposables),A.on("MenuPopupChanged",t=>{if(!this.activated||this.isCommandLine)return;let{completed_item:i}=t,n=i.hasOwnProperty("word")?i:null;qe(n,this.currItem)||(this.cancelResolve(),this.currItem=n,e(t))},this,this.disposables),b.onDidChangeConfiguration(t=>{t.affectsConfiguration("suggest")&&(this.config=this.getCompleteConfig())},null,this.disposables)}get nvim(){return b.nvim}get option(){return this.complete?this.complete.option:null}get isCommandLine(){var e;return(e=this.document)==null?void 0:e.uri.endsWith("%5BCommand%20Line%5D")}addRecent(e,t){!e||(this.recentScores[`${t}|${e}`]=Date.now())}get isActivated(){return this.activated}get document(){return this.option?b.getDocument(this.option.bufnr):null}getCompleteConfig(){let e=b.getConfiguration("suggest");function t(a,l){return e.get(a,l)}let i=t("keepCompleteopt",!1),n=t("autoTrigger","always");if(i&&n!="none"){let{completeOpt:a}=b;!a.includes("noinsert")&&!a.includes("noselect")&&(n="none")}let o=b.floatSupported&&t("floatEnable",!0),s=b.env.pumevent&&t("acceptSuggestionOnCommitCharacter",!1);return{autoTrigger:n,floatEnable:o,keepCompleteopt:i,defaultSortMethod:t("defaultSortMethod","length"),removeDuplicateItems:t("removeDuplicateItems",!1),disableMenuShortcut:t("disableMenuShortcut",!1),acceptSuggestionOnCommitCharacter:s,disableKind:t("disableKind",!1),disableMenu:t("disableMenu",!1),previewIsKeyword:t("previewIsKeyword","@,48-57,_192-255"),enablePreview:t("enablePreview",!1),enablePreselect:t("enablePreselect",!1),maxPreviewWidth:t("maxPreviewWidth",80),triggerCompletionWait:t("triggerCompletionWait",100),labelMaxLength:t("labelMaxLength",200),triggerAfterInsertEnter:t("triggerAfterInsertEnter",!1),noselect:t("noselect",!0),numberSelect:t("numberSelect",!1),maxItemCount:t("maxCompleteItemCount",50),timeout:t("timeout",500),minTriggerInputLength:t("minTriggerInputLength",1),snippetIndicator:t("snippetIndicator","~"),fixInsertedWord:t("fixInsertedWord",!0),localityBonus:t("localityBonus",!0),highPrioritySourceLimit:t("highPrioritySourceLimit",null),lowPrioritySourceLimit:t("lowPrioritySourceLimit",null),asciiCharactersOnly:t("asciiCharactersOnly",!1)}}async startCompletion(e){this.pretext=Rt(e.line,0,e.colnr-1);try{await this._doComplete(e)}catch(t){this.stop(!1),fs.error("Complete error:",t.stack)}}async resumeCompletion(e=!1){let{document:t,complete:i}=this;if(!t||i.isCanceled||!i.results||i.results.length==0)return;let n=this.getResumeInput();if(n==this.input&&!e)return;if(!n||n.endsWith(" ")||!n.startsWith(i.input)){this.stop();return}this.input=n;let o=[];if(i.isIncomplete){await t.patchChange();let{changedtick:s}=t;if(o=await i.completeInComplete(n),i.isCanceled||t.changedtick!=s)return}else o=i.filterResults(n);if(!i.isCompleting&&o.length===0){this.stop();return}await this.showCompletion(i.option.col,o)}hasSelected(){return b.env.pumevent?this.currItem!=null:!this.config.noselect}async showCompletion(e,t){let{nvim:i,document:n,option:o}=this,{numberSelect:s,disableKind:a,labelMaxLength:l,disableMenuShortcut:u,disableMenu:c}=this.config,f=this.config.enablePreselect?t.findIndex(h=>h.preselect):-1;s&&o.input.length&&!/^\d/.test(o.input)&&(t=t.map((h,m)=>{let y=m+1;return m<9?Object.assign({},h,{abbr:h.abbr?`${y} ${h.abbr}`:`${y} ${h.word}`}):h}),i.call("coc#_map",[],!0)),this.changedTick=n.changedtick;let p=fbe.slice();a&&(p=p.filter(h=>h!="kind")),c&&(p=p.filter(h=>h!="menu"));let d=t.map(h=>{let m={word:h.word,equal:1};for(let y of p)h.hasOwnProperty(y)&&(u&&y=="menu"?m[y]=h[y].replace(/\[.+\]$/,""):y=="abbr"&&h[y].length>l?m[y]=h[y].slice(0,l):m[y]=h[y]);return m});i.call("coc#_do_complete",[e,d,f],!0)}async _doComplete(e){let{source:t}=e,{nvim:i,config:n}=this,o=b.getDocument(e.bufnr);if(!o||!o.attached)return;e.filetype=o.filetype,this.input=e.input;let s=[];if(t==null)s=Ge.getCompleteSources(e);else{let u=Ge.getSource(t);u&&s.push(u)}if(!s.length||(await o.patchChange(),o.changedtick!=e.changedtick))return;let a=new w9(e,o,this.recentScores,n,s,i);this.start(a);let l=await this.complete.doComplete();if(!a.isCanceled){if(l.length==0&&!a.isCompleting){this.stop();return}a.onDidComplete(async()=>{if(this.currItem!=null)return;let u=this.getResumeInput();if(a.isCanceled||u==null)return;let{input:c}=this.option;if(u==c){let f=a.filterResults(u,Math.floor(Date.now()/1e3));await this.showCompletion(e.col,f)}else await this.resumeCompletion()}),l.length&&(this.getResumeInput()==e.input?await this.showCompletion(e.col,l):await this.resumeCompletion(!0))}}async onTextChangedP(e,t){let{option:i,document:n}=this,o=this.pretext=t.pre;if(!i||i.bufnr!=e||t.changedtick==this.changedTick)return;let s=this.latestInsert!=null;if(this.lastInsert=null,t.pre.match(/^\s*/)[0]!==i.line.match(/^\s*/)[0]){fs.warn("Complete stopped by indent change."),this.stop();return}!s||!o||(Ge.shouldTrigger(o,n.filetype,n.uri)?await this.triggerCompletion(n,o):await this.resumeCompletion())}async onTextChangedI(e,t){let{nvim:i,latestInsertChar:n,option:o}=this,s=this.pretext==t.pre,a=this.pretext=t.pre;this.lastInsert=null;let l=b.getDocument(e);if(!!l){if(!this.activated){if(!n)return;if(Ge.getTriggerSources(a,l.filetype,l.uri).length){await this.triggerCompletion(l,this.pretext);return}this.triggerTimer=setTimeout(async()=>{await this.triggerCompletion(l,a)},this.config.triggerCompletionWait);return}if(!(!o||e!=o.bufnr)){if(o.linenr!=t.lnum||o.col>=t.col-1){this.stop();return}if(s&&!n){this.stop(!1);return}if(a&&this.currItem&&this.config.acceptSuggestionOnCommitCharacter&&n){let u=this.getCompleteItem(this.currItem),c=a[a.length-1];if(Ge.shouldCommit(u,c)){let{linenr:f,col:p,line:d,colnr:h}=this.option;this.stop();let{word:m}=u,y=`${d.slice(0,p)}${m}${n}${d.slice(h-1)}`;await i.call("coc#util#setline",[f,y]);let g=p+m.length+2;await i.call("cursor",[f,g]),await l.patchChange();return}}Ge.shouldTrigger(a,l.filetype,l.uri)?await this.triggerCompletion(l,a):await this.resumeCompletion()}}}async triggerCompletion(e,t){if(!e||!e.attached){fs.warn("Document not attached, suggest disabled.");return}if(!this.shouldTrigger(e,t))return;if(e.getVar("suggest_disable")){fs.warn("Suggest disabled by b:coc_suggest_disable");return}await e.patchChange();let[n,o]=await this.nvim.eval('[get(b:,"coc_suggest_disable",0),coc#util#get_complete_option()]');if(n==1){fs.warn("Suggest disabled by b:coc_suggest_disable");return}if(o.blacklist&&o.blacklist.includes(o.input)){fs.warn("Suggest disabled by b:coc_suggest_blacklist",o.blacklist);return}t.length&&(o.triggerCharacter=t.slice(-1)),fs.debug("trigger completion with",o),await this.startCompletion(o)}async onCompleteDone(e){let{document:t,isActivated:i}=this;if(!i||!t||!e.hasOwnProperty("word"))return;let n=Object.assign({},this.option),o=this.getCompleteItem(e);if(this.stop(!1),!o)return;let s=this.insertCharTs,a=this.insertLeaveTs;try{if(await Ge.doCompleteResolve(o,new WC.CancellationTokenSource().token),this.addRecent(o.word,t.bufnr),await He(50),this.insertCharTs!=s||this.insertLeaveTs!=a)return;let[l,u,c]=await this.nvim.eval("[pumvisible(),line('.'),strpart(getline('.'), 0, col('.') - 1)]");if(l||u!=n.linenr||this.activated||!c.endsWith(o.word))return;await t.patchChange(),await Ge.doCompleteDone(o,n)}catch(l){fs.error("error on complete done",l.stack)}}async onInsertLeave(){this.insertLeaveTs=Date.now(),this.stop(!1)}async onInsertEnter(e){if(!this.config.triggerAfterInsertEnter||this.config.autoTrigger!=="always")return;let t=b.getDocument(e);if(!t)return;let i=await this.nvim.eval("strpart(getline('.'), 0, col('.') - 1)");!i||await this.triggerCompletion(t,i)}async onInsertCharPre(e){this.lastInsert={character:e,timestamp:Date.now()},this.insertCharTs=this.lastInsert.timestamp}get latestInsert(){let{lastInsert:e}=this;return!e||Date.now()-e.timestamp>500?null:e}get latestInsertChar(){let{latestInsert:e}=this;return e?e.character:""}shouldTrigger(e,t){let i=this.config.autoTrigger;if(i=="none")return!1;if(Ge.shouldTrigger(t,e.filetype,e.uri))return!0;if(i!=="always"||this.isActivated)return!1;let n=t.slice(-1);if(n&&(e.isWord(t.slice(-1))||n.codePointAt(0)>255)){let o=this.config.minTriggerInputLength;return o==1?!0:this.getInput(e,t).length>=o}return!1}async onPumChange(e){if(!this.activated)return;let{completed_item:t,col:i,row:n,height:o,width:s,scrollbar:a}=e,l={col:i,row:n,height:o,width:s,scrollbar:a},u=this.getCompleteItem(t);if(!u){this.floating.close();return}let c=this.resolveTokenSource=new WC.CancellationTokenSource,{token:f}=c;if(await Ge.doCompleteResolve(u,f),this.resolveTokenSource=null,f.isCancellationRequested)return;let p=u.documentation;if(!p&&u.info){let{info:d}=u;p=[{filetype:/^[\w-\s.,\t]+$/.test(d)?"txt":this.document.filetype,content:d}]}!this.isActivated||(!p||p.length==0?this.floating.close():(this.config.floatEnable&&await this.floating.show(p,l,{maxPreviewWidth:this.config.maxPreviewWidth},f),this.isActivated||this.floating.close()))}start(e){let{activated:t}=this;this.activated=!0,t&&this.complete.dispose(),this.complete=e,this.config.keepCompleteopt||this.nvim.command(`noa set completeopt=${this.completeOpt}`,!0)}cancelResolve(){this.resolveTokenSource&&(this.resolveTokenSource.cancel(),this.resolveTokenSource=null)}stop(e=!0){let{nvim:t}=this;!this.activated||(this.cancelResolve(),this.currItem=null,this.activated=!1,this.complete&&(this.complete.dispose(),this.complete=null),t.pauseNotification(),e&&t.call("coc#_hide",[],!0),this.floating.close(),this.config.numberSelect&&t.call("coc#_unmap",[],!0),this.config.keepCompleteopt||this.nvim.command(`noa set completeopt=${b.completeOpt}`,!0),t.command("let g:coc#_context['candidates'] = []",!0),t.call("coc#_cancel",[],!0),t.resumeNotification(!1,!0))}getInput(e,t){let i="";for(let n=t.length-1;n>=0;n--){let o=n==0?null:t[n-1];if(!o||!e.isWord(o)){i=t.slice(n,t.length);break}}return i}getResumeInput(){let{option:e,pretext:t}=this;if(!e)return null;let i=Buffer.from(t,"utf8");if(i.lengthNe(s.range.start,t.start)==0)!==-1)return!1;let n=bD(this.range.start,e);return n.line==0&&n.character==0||this.adjustPosition(n.character,n.line),!0}get isPlainText(){return this._placeholders.length>1?!1:this._placeholders.every(e=>e.value=="")}get finalCount(){return this._placeholders.filter(e=>e.isFinalTabstop).length}toString(){return this.tmSnippet.toString()}get range(){let{position:e}=this,t=this.tmSnippet.toString(),n=kt.create("untitled:/1","snippet",0,t).positionAt(t.length),o=n.line==0?e.character+n.character:n.character;return ao.Range.create(e,ao.Position.create(e.line+n.line,o))}get firstPlaceholder(){let e=0;for(let t of this._placeholders)t.index!=0&&(e==0||t.indexe)&&(e=t.index);return this.getPlaceholder(e)}getPlaceholderById(e){return this._placeholders.find(t=>t.id==e)}getPlaceholder(e){let t=this._placeholders.filter(n=>n.index==e),i=t.filter(n=>!n.transform);return i.length?i[0]:t[0]}getPrevPlaceholder(e){if(e==0)return this.lastPlaceholder;let t=this.getPlaceholder(e-1);return t||this.getPrevPlaceholder(e-1)}getNextPlaceholder(e){let t=this._placeholders.map(o=>o.index),i=Math.max.apply(null,t);if(e>=i)return this.finalPlaceholder;let n=this.getPlaceholder(e+1);return n||this.getNextPlaceholder(e+1)}get finalPlaceholder(){return this._placeholders.find(e=>e.isFinalTabstop)}getPlaceholderByRange(e){return this._placeholders.find(t=>Ji(e,t.range))}insertSnippet(e,t,i){let{start:n}=e.range,o=ao.Position.create(i.start.line-n.line,i.start.line==n.line?i.start.character-n.character:i.start.character),s=ao.Position.create(i.end.line-n.line,i.end.line==n.line?i.end.character-n.character:i.end.character),a=ao.Range.create(o,s),l=this.tmSnippet.insertSnippet(t,e.id,a);return this.update(),l}updatePlaceholder(e,t){let{start:i,end:n}=t.range,{range:o}=this,{value:s,id:a,index:l}=e,u=HB(e.range,s,t),c=0;if(!u.includes(` -`)){for(let d of this._placeholders)if(d.index==l&&d.id{let p=e.offset(c),d=n.positionAt(p),h={line:t+d.line,character:d.line==0?i+d.character:d.character},m;if(c instanceof yn){let x=c.name;l.has(x)?m=l.get(x):(l.set(x,u),m=u,u=u+1)}else m=c.index;let y=c.toString(),g=y.split(/\r?\n/),w={range:ao.Range.create(h,{line:h.line+g.length-1,character:g.length==1?h.character+y.length:g[g.length-1].length}),transform:c.transform!=null,line:h.line,id:f,index:m,value:y,isVariable:c instanceof yn,isFinalTabstop:c.index===0};if(Object.defineProperty(w,"snippet",{enumerable:!1}),c instanceof ei&&c.choice){let{options:x}=c.choice;x&&x.length&&(w.choice=x.map(E=>E.value))}return w})}};var rd=S(require("path"));var mze=U()("snippets-variable"),id=class{constructor(){this._variableToValue={};let e=new Date;Object.assign(this._variableToValue,{CURRENT_YEAR:e.getFullYear().toString(),CURRENT_YEAR_SHORT:e.getFullYear().toString().slice(-2),CURRENT_MONTH:(e.getMonth()+1).toString(),CURRENT_DATE:e.getDate().toString(),CURRENT_HOUR:e.getHours().toString(),CURRENT_MINUTE:e.getMinutes().toString(),CURRENT_SECOND:e.getSeconds().toString(),CURRENT_DAY_NAME:e.toLocaleString("en-US",{weekday:"long"}),CURRENT_DAY_NAME_SHORT:e.toLocaleString("en-US",{weekday:"short"}),CURRENT_MONTH_NAME:e.toLocaleString("en-US",{month:"long"}),CURRENT_MONTH_NAME_SHORT:e.toLocaleString("en-US",{month:"short"}),TM_FILENAME:null,TM_FILENAME_BASE:null,TM_DIRECTORY:null,TM_FILEPATH:null,YANK:null,TM_LINE_INDEX:null,TM_LINE_NUMBER:null,TM_CURRENT_LINE:null,TM_CURRENT_WORD:null,TM_SELECTED_TEXT:null,CLIPBOARD:null})}async resovleValue(e){let{nvim:t}=C;if(["TM_FILENAME","TM_FILENAME_BASE","TM_DIRECTORY","TM_FILEPATH"].includes(e)){let i=await t.eval('expand("%:p")');if(e=="TM_FILENAME")return rd.default.basename(i);if(e=="TM_FILENAME_BASE")return rd.default.basename(i,rd.default.extname(i));if(e=="TM_DIRECTORY")return rd.default.dirname(i);if(e=="TM_FILEPATH")return i}if(e=="YANK")return await t.call("getreg",['""']);if(e=="TM_LINE_INDEX")return(await t.call("line",["."])-1).toString();if(e=="TM_LINE_NUMBER")return(await t.call("line",["."])).toString();if(e=="TM_CURRENT_LINE")return await t.call("getline",["."]);if(e=="TM_CURRENT_WORD")return await t.eval("expand('')");if(e=="TM_SELECTED_TEXT")return await t.eval("get(g:,'coc_selected_text', '')");if(e=="CLIPBOARD")return await t.eval("@*")}async resolve(e){let t=e.name,i=this._variableToValue[t];if(i!=null)return i.toString();let n=await this.resovleValue(t);return n||(e.children&&e.children.length?e.toString():this._variableToValue.hasOwnProperty(t)?"":t)}};var Bu=U()("snippets-session"),zC=class{constructor(e,t){this.nvim=e;this.bufnr=t;this._isActive=!1;this._currId=0;this.applying=!1;this.preferComplete=!1;this._snippet=null;this._onCancelEvent=new $u.Emitter;this.onCancel=this._onCancelEvent.event;let i=b.getConfiguration("coc.preferences"),n=b.getConfiguration("suggest");this.preferComplete=i.get("preferCompleteThanJumpPlaceholder",n.get("preferCompleteThanJumpPlaceholder",!1))}async start(e,t=!0,i){let{document:n}=this;if(!n||!n.attached)return!1;if(A.fire("InsertSnippet",[]).logError(),!i){let d=await C.getCursorPosition();i=$u.Range.create(d,d)}let o=i.start,s=await b.getFormatOptions(this.document.uri);await n.patchChange(!0);let a=n.getline(o.line),l=a.match(/^\s*/)[0],u=pbe(e,l,s),c=new id,f=new HC(u,o,c);await f.init();let p=$u.TextEdit.replace(i,f.toString());if(e.endsWith(` -`)&&a.slice(o.character).length&&(p.newText=p.newText+l,u=u+l),this.applying=!0,await n.applyEdits([p]),this.applying=!1,this._isActive){let d=this.findPlaceholder(i);if(d&&!d.isFinalTabstop){let h=this.snippet.insertSnippet(d,u,i),m=this.snippet.getPlaceholder(h);return this._currId=m.id,t&&await this.selectPlaceholder(m),!0}}if(f.isPlainText){this.deactivate();let d=f.finalPlaceholder;return await C.moveTo(d.range.start),!1}return this._snippet=f,this._currId=f.firstPlaceholder.id,t&&await this.selectPlaceholder(f.firstPlaceholder),this.activate(),!0}activate(){this._isActive||(this._isActive=!0,this.nvim.call("coc#snippet#enable",[],!0))}deactivate(){this._isActive&&(this._isActive=!1,this._snippet=null,this.nvim.call("coc#snippet#disable",[],!0),Bu.debug("[SnippetManager::cancel]")),this._onCancelEvent.fire(void 0),this._onCancelEvent.dispose()}get isActive(){return this._isActive}async nextPlaceholder(){if(!this.isActive)return;await this.document.patchChange();let e=this.placeholder,t=this.snippet.getNextPlaceholder(e.index);await this.selectPlaceholder(t)}async previousPlaceholder(){if(!this.isActive)return;await this.document.patchChange();let e=this.placeholder,t=this.snippet.getPrevPlaceholder(e.index);await this.selectPlaceholder(t)}async synchronizeUpdatedPlaceholders(e){if(!this.isActive||!this.document||this.applying)return;let t={range:e.range,newText:e.text},{snippet:i}=this;if(i.adjustTextEdit(t))return;if(Ne(t.range.start,i.range.end)>0){if(!t.newText)return;Bu.info("Content change after snippet, cancelling snippet session"),this.deactivate();return}let o=this.findPlaceholder(t.range);if(!o){Bu.info("Change outside placeholder, cancelling snippet session"),this.deactivate();return}if(o.isFinalTabstop&&i.finalCount<=1){Bu.info("Change final placeholder, cancelling snippet session"),this.deactivate();return}this._currId=o.id;let{edits:s,delta:a}=i.updatePlaceholder(o,t);!s.length||(this.applying=!0,await this.document.applyEdits(s),this.applying=!1,a&&await this.nvim.call("coc#util#move_cursor",a))}async selectCurrentPlaceholder(e=!0){let t=this.snippet.getPlaceholderById(this._currId);t&&await this.selectPlaceholder(t,e)}async selectPlaceholder(e,t=!0){let{nvim:i,document:n}=this;if(!n||!e)return;let{start:o,end:s}=e.range,a=s.character-o.character,l=ue(n.getline(o.line).slice(0,o.character))+1;this._currId=e.id,e.choice?(await i.call("coc#snippet#show_choices",[o.line+1,l,a,e.choice]),t&&i.call("coc#util#do_autocmd",["CocJumpPlaceholder"],!0)):await this.select(e,t)}async select(e,t=!0){let{range:i,value:n,isFinalTabstop:o}=e,{document:s,nvim:a}=this,{start:l,end:u}=i,{textDocument:c}=s,f=c.offsetAt(u)-c.offsetAt(l),p=s.getline(l.line),d=p?ue(p.slice(0,l.character)):0,h=s.getline(u.line),m=h?ue(h.slice(0,u.character)):0;a.setVar("coc_last_placeholder",{current_text:n,start:{line:l.line,col:d},end:{line:u.line,col:m}},!0);let[y,g,w,x]=await a.eval("[&virtualedit, &selection, pumvisible(), mode()]"),E="";if(w&&this.preferComplete){let P=ps.hasSelected()?"":"\\";await a.eval(`feedkeys("${P}\\", 'in')`);return}x!="n"&&(E+="\\"),f==0?d==0||!x.startsWith("i")&&d`),x=="i"&&E=="\\a"&&(E=""),a.pauseNotification(),a.setOption("virtualedit","onemore",!0),a.call("cursor",[l.line+1,d+(E=="a"?0:1)],!0),E&&a.call("eval",[`feedkeys("${E}", 'in')`],!0),x=="i"&&a.call("coc#_cancel",[],!0),a.setOption("virtualedit",y,!0),o&&(this.snippet.finalCount==1?(Bu.info("Jump to final placeholder, cancelling snippet session"),this.deactivate()):a.call("coc#snippet#disable",[],!0)),b.env.isVim&&a.command("redraw",!0),await a.resumeNotification(),t&&a.call("coc#util#do_autocmd",["CocJumpPlaceholder"],!0)}async getVirtualCol(e,t){let{nvim:i}=this;return await i.eval(`virtcol([${e}, ${t}])`)}async checkPosition(){if(!this.isActive)return;let e=await C.getCursorPosition();this.snippet&&Ht(e,this.snippet.range)!=0&&(Bu.info("Cursor insert out of range, cancelling snippet session"),this.deactivate())}findPlaceholder(e){if(!this.snippet)return null;let{placeholder:t}=this;return t&&Ji(e,t.range)?t:this.snippet.getPlaceholderByRange(e)||null}get placeholder(){return this.snippet?this.snippet.getPlaceholderById(this._currId):null}get snippet(){return this._snippet}get document(){return b.getDocument(this.bufnr)}};function pbe(r,e,t){let i=r.split(/\r?\n/),n=t.insertSpaces?" ".repeat(t.tabSize):" ",o=t.tabSize||2;return i=i.map((s,a)=>{let l=s.match(/^\s*/)[0],u=l,c=l.startsWith(" ");return c&&t.insertSpaces?u=n.repeat(l.length):!c&&!t.insertSpaces&&(u=n.repeat(l.length/o)),(a==0||s.length==0?"":e)+u+s.slice(l.length)}),i.join(` -`)}var Lze=U()("snippets-manager"),S9=class{constructor(){this.sessionMap=new Map;this.disposables=[];b.onDidChangeTextDocument(async e=>{let t=this.getSession(e.bufnr);t&&await t.synchronizeUpdatedPlaceholders(e.contentChanges[0])},null,this.disposables),b.onDidCloseTextDocument(e=>{let t=b.getDocument(e.uri);if(!t)return;let i=this.getSession(t.bufnr);i&&i.deactivate()},null,this.disposables),A.on("BufEnter",async e=>{let t=this.getSession(e);!this.statusItem||(t&&t.isActive?this.statusItem.show():this.statusItem.hide())},null,this.disposables),A.on("InsertEnter",async()=>{let{session:e}=this;!e||await e.checkPosition()},null,this.disposables)}init(){let e=b.getConfiguration("coc.preferences");this.statusItem=C.createStatusBarItem(0),this.statusItem.text=e.get("snippetStatusText","SNIP")}async insertSnippet(e,t=!0,i){let{bufnr:n}=b,o=this.getSession(n);o||(o=new zC(b.nvim,n),this.sessionMap.set(n,o),o.onCancel(()=>{this.sessionMap.delete(n),b.bufnr==n&&this.statusItem.hide()}));let s=await o.start(e,t,i);return s&&this.statusItem.show(),s}async selectCurrentPlaceholder(e=!0){let{session:t}=this;if(t)return await t.selectCurrentPlaceholder(e)}async nextPlaceholder(){let{session:e}=this;if(e)return await e.nextPlaceholder();b.nvim.call("coc#snippet#disable",[],!0),this.statusItem.hide()}async previousPlaceholder(){let{session:e}=this;if(e)return await e.previousPlaceholder();b.nvim.call("coc#snippet#disable",[],!0),this.statusItem.hide()}cancel(){let e=this.getSession(b.bufnr);if(e)return e.deactivate();b.nvim.call("coc#snippet#disable",[],!0),this.statusItem&&this.statusItem.hide()}get session(){let e=this.getSession(b.bufnr);return e&&e.isActive?e:null}isActived(e){let t=this.getSession(e);return t&&t.isActive}jumpable(){let{session:e}=this;if(!e)return!1;let t=e.placeholder;return!!(t&&!t.isFinalTabstop)}getSession(e){return this.sessionMap.get(e)}async resolveSnippet(e){let i=new Go().parse(e,!0),n=new id;return await i.resolveVariables(n),i}dispose(){this.cancel();for(let e of this.disposables)e.dispose()}},At=new S9;var Jze=U()("commands"),E9=class{constructor(e,t,i,n=!1){this.id=e;this.impl=t;this.thisArg=i;this.internal=n}execute(...e){let{impl:t,thisArg:i}=this;return t.apply(i,e||[])}dispose(){this.thisArg=null,this.impl=null}},C9=class{constructor(){this.commands=new Map;this.titles=new Map;this.onCommandList=[]}init(e,t){this.mru=b.createMru("commands"),this.register({id:"vscode.open",execute:async i=>{e.call("coc#util#open_url",i.toString(),!0)}},!0),this.register({id:"workbench.action.reloadWindow",execute:async()=>{await e.command("edit")}},!0),this.register({id:"editor.action.insertSnippet",execute:async i=>(e.call("coc#_cancel",[],!0),await At.insertSnippet(i.newText,!0,i.range))},!0),this.register({id:"editor.action.doCodeAction",execute:async i=>{await t.cocAction("doCodeAction",i)}},!0),this.register({id:"editor.action.triggerSuggest",execute:async()=>{await He(60),e.call("coc#start",[],!0)}},!0),this.register({id:"editor.action.triggerParameterHints",execute:async()=>{await He(60),await t.cocAction("showSignatureHelp")}},!0),this.register({id:"editor.action.addRanges",execute:async i=>{await t.cocAction("addRanges",i)}},!0),this.register({id:"editor.action.restart",execute:async()=>{await He(30),e.command("CocRestart",!0)}},!0),this.register({id:"editor.action.showReferences",execute:async(i,n,o)=>{await b.showLocations(o)}},!0),this.register({id:"editor.action.rename",execute:async(i,n)=>{await b.jumpTo(i,n),await t.cocAction("rename")}},!0),this.register({id:"editor.action.format",execute:async()=>{await t.cocAction("format")}},!0),this.register({id:"workspace.diffDocument",execute:async()=>{let i=await b.document;!i||await e.call("coc#util#diff_content",[i.getLines()])}}),this.register({id:"workspace.clearWatchman",execute:async()=>{(await C.runTerminalCommand("watchman watch-del-all")).success&&C.showMessage("Cleared watchman watching directories.")}},!1,"run watch-del-all for watchman to free up memory."),this.register({id:"workspace.workspaceFolders",execute:async()=>{let n=b.workspaceFolders.map(o=>$.parse(o.uri).fsPath);await C.echoLines(n)}},!1,"show opened workspaceFolders."),this.register({id:"workspace.renameCurrentFile",execute:async()=>{await b.renameCurrent()}},!1,"change current filename to a new name and reload it."),this.register({id:"extensions.toggleAutoUpdate",execute:async()=>{let i=b.getConfiguration("coc.preferences");i.get("extensionUpdateCheck","daily")=="never"?(i.update("extensionUpdateCheck","daily",!0),C.showMessage("Extension auto update enabled.","more")):(i.update("extensionUpdateCheck","never",!0),C.showMessage("Extension auto update disabled.","more"))}},!1,"toggle auto update of extensions."),this.register({id:"workspace.diagnosticRelated",execute:()=>mt.jumpRelated()},!1,"jump to related locations of current diagnostic."),this.register({id:"workspace.showOutput",execute:async i=>{if(i)C.showOutputChannel(i);else{let n=b.channelNames;if(n.length==0)return;if(n.length==1)C.showOutputChannel(n[0]);else{let o=await C.showQuickpick(n);if(o==-1)return;let s=n[o];C.showOutputChannel(s)}}}},!1,"open output buffer to show output from languageservers or extensions."),this.register({id:"document.echoFiletype",execute:async()=>{let i=await e.call("bufnr","%"),n=b.getDocument(i);!n||await C.echoLines([n.filetype])}},!1,"echo the mapped filetype of the current buffer"),this.register({id:"document.renameCurrentWord",execute:async()=>{let i=await e.call("bufnr","%"),n=b.getDocument(i);if(!n)return;let o=await t.cocAction("getWordEdit");if(!o){C.showMessage("Invalid position","warning");return}let s=[],{changes:a,documentChanges:l}=o;if(a){let u=a[n.uri];u&&(s=u.map(c=>c.range))}else if(l)for(let u of l)Gv.TextDocumentEdit.is(u)&&u.textDocument.uri==n.uri&&(s=u.edits.map(c=>c.range));s.length&&await t.cocAction("addRanges",s)}},!1,"rename word under cursor in current buffer by use multiple cursors."),this.register({id:"document.jumpToNextSymbol",execute:async()=>{let i=await b.document;if(!i)return;let n=await t.cocAction("symbolRanges");if(!n)return;let{textDocument:o}=i,s=await C.getOffset();n.sort((a,l)=>a.start.line!=l.start.line?a.start.line-l.start.line:a.start.character-l.start.character);for(let a=0;a<=n.length-1;a++)if(o.offsetAt(n[a].start)>s){await C.moveTo(n[a].start);return}await C.moveTo(n[0].start)}},!1,"Jump to next symbol highlight position."),this.register({id:"document.jumpToPrevSymbol",execute:async()=>{let i=await b.document;if(!i)return;let n=await t.cocAction("symbolRanges");if(!n)return;let{textDocument:o}=i,s=await C.getOffset();n.sort((a,l)=>a.start.line!=l.start.line?a.start.line-l.start.line:a.start.character-l.start.character);for(let a=n.length-1;a>=0;a--)if(o.offsetAt(n[a].end){this.commands.delete(e)})}executeCommand(e,...t){let i=this.commands.get(e);if(!i)throw new Error(`Command: ${e} not found`);return Promise.resolve(i.execute.apply(i,t))}async addRecent(e){await this.mru.add(e),await b.nvim.command('silent! call repeat#set("\\(coc-command-repeat)", -1)')}async repeatCommand(){let t=(await this.mru.load())[0];t&&(await this.executeCommand(t),await b.nvim.command('silent! call repeat#set("\\(coc-command-repeat)", -1)'))}},me=new C9;var Wu=S(jn());var ju=S(Ul()),Uu=S(W());var nd=S(jn());var Qze=U()("cursors-range"),GC=class{constructor(e,t,i,n,o){this.line=e;this.start=t;this.end=i;this.text=n;this.preCount=o;this.currStart=t,this.currEnd=i}add(e,t){let{text:i,preCount:n}=this,o=e==0?"":i.slice(0,e),s=i.slice(e);this.text=`${o}${t}${s}`,this.currStart=this.currStart+n*t.length,this.currEnd=this.currEnd+(n+1)*t.length}replace(e,t,i=""){let{text:n,preCount:o}=this,s=e==0?"":n.slice(0,e),a=n.slice(t);this.text=s+i+a;let l=t-e-i.length;this.currStart=this.currStart-o*l,this.currEnd=this.currEnd-(o+1)*l}get range(){return nd.Range.create(this.line,this.start,this.line,this.end)}get currRange(){return nd.Range.create(this.line,this.currStart,this.line,this.currEnd)}applyEdit(e){let{range:t,newText:i}=e,n=t.start.character,o=t.end.character;n==o?this.add(n-this.currStart,i):this.replace(n-this.currStart,o-this.currStart,i)}adjustFromEdit(e){let{range:t,newText:i}=e;if(Ne(t.start,nd.Position.create(this.line,this.currEnd))>0)return;let n=i.split(` -`),o=n.length-(t.end.line-t.start.line+1);if(this.line=this.line+o,t.end.line==this.line){let s=t.start.line==t.end.line?t.end.character-t.start.character:t.end.character;n.length>1&&t.start.line==t.end.line&&(s=s+t.start.character);let a=0;n.length>1?a=n[n.length-1].length:t.start.line==t.end.line?a=i.length:a=t.start.character+i.length;let l=a-s;for(let u of["start","end","currStart","currEnd"])this[u]+=l}}sync(){this.start=this.currStart,this.end=this.currEnd}get textEdit(){return{range:this.range,newText:this.text}}},VC=GC;var od=S(W());function KC(r,e){let t=[];for(let i=e.start.line;i<=e.end.line;i++){let n=r.getline(i)||"",o=i==e.start.line?e.start.character:0,s=i==e.end.line?e.end.character:n.length;o!=s&&t.push(od.Range.create(i,o,i,s))}return t}function _9(r,e){let{start:t,end:i}=e;t.line>i.line&&([t,i]=[i,t]);let n=t.character{this.cancel()},!0)),this.disposables.push(b.registerLocalKeymap("n",o,async()=>{if(!this.activated)return;let a=this.ranges.map(u=>u.currRange),l=await C.getCursorPosition();for(let u of a)if(Ne(u.start,l)>0){await C.moveTo(u.start);return}a.length&&await C.moveTo(a[0].start)},!0)),this.disposables.push(b.registerLocalKeymap("n",s,async()=>{if(!this.activated)return;let a=this.ranges.map(u=>u.currRange);a.reverse();let l=await C.getCursorPosition();for(let u of a)if(Ne(u.end,l)<0){await C.moveTo(u.start);return}a.length&&await C.moveTo(a[a.length-1].start)},!0)),this.doc.onDocumentChange(this.onChange,this,this.disposables)}async onChange(e){if(!this.activated||this.ranges.length==0||this.changing)return;let t=e.contentChanges[0],{text:i,range:n}=t,o=this.ranges.some(l=>Bl(n,l.currRange)),s=this.ranges[0].currRange.start;if(i.endsWith(` -`)&&Ne(s,n.end)==0&&(o=!1),!o){this.ranges.forEach(l=>{l.adjustFromEdit({range:n,newText:i})}),this.doHighlights(),this.textDocument=this.doc.textDocument;return}this.changed=!0;let a=this.getTextRange(n,i);a?await this.applySingleEdit(a,{range:n,newText:i}):(this.applyComposedEdit(e.original,{range:n,newText:i}),this.activated&&(this.ranges.forEach(l=>{l.sync()}),this.textDocument=this.doc.textDocument))}doHighlights(){let{nvim:e,buffer:t,ranges:i}=this;t.clearNamespace("cursors");let n=i.map(o=>o.currRange);t.highlightRanges("cursors","CocCursorRange",n),e.command("redraw",!0)}addRanges(e){let{nvim:t,doc:i}=this;if(this.changed)return C.showMessage("Can't add ranges after range change."),!1;this.ranges=this.ranges.filter(a=>{let{currRange:l}=a;return!e.some(u=>Bm(u,l))});let{textDocument:n}=i;for(let a of e){let{line:l}=a.start,u=new VC(l,a.start.character,a.end.character,n.getText(a),0);this.ranges.push(u)}this.ranges.sort((a,l)=>Ne(a.range.start,l.range.start));let o=0,s=-1;for(let a of this.ranges){let{line:l}=a;l!=s&&(o=0),a.preCount=o,o=o+1,s=l}return t.pauseNotification(),this.doHighlights(),t.resumeNotification(!1,!0),!0}cancel(){if(!this.activated)return;let{nvim:e}=this;this.activated=!1;let{cancelKey:t,nextKey:i,previousKey:n}=this.config;e.pauseNotification(),this.buffer.clearNamespace("cursors"),this.buffer.setVar("coc_cursors_activated",0,!0),e.command("redraw",!0),e.resumeNotification(!1,!0),this._onDidCancel.fire()}dispose(){if(!!this.doc){this._onDidCancel.dispose();for(let e of this.disposables)e.dispose();this.ranges=[],this.doc=null,this.textDocument=null}}get buffer(){return this.nvim.createBuffer(this.doc.bufnr)}getTextRange(e,t){let{ranges:i}=this;if(t.indexOf(` -`)!==-1||e.start.line!=e.end.line)return null;i.sort((n,o)=>n.line!=o.line?n.line-o.line:n.currRange.start.character-o.currRange.start.character);for(let n=0;n{s.add(s.text.length,i)});else{let s=t.start.character-e.currRange.start.character;n.forEach(a=>{a.add(Math.min(a.text.length,s),i)})}else{let o=t.end.character-t.start.character;if(e.currRange.end.character==t.end.character)if(e.currRange.start.character==t.start.character)if(i.includes(e.text)){let a=i.indexOf(e.text),l=a==0?"":i.slice(0,a),u=i.slice(a+e.text.length);l&&n.forEach(c=>c.add(0,l)),u&&n.forEach(c=>c.add(c.text.length,u))}else if(e.text.includes(i)){let a=e.text.indexOf(i),l=e.text.length-(a+i.length);a!=0&&n.forEach(u=>u.replace(0,a)),l>0&&n.forEach(u=>u.replace(u.text.length-l,u.text.length))}else this.cancel();else n.forEach(a=>{let l=a.text.length;a.replace(Math.max(0,l-o),l,i)});else{let a=t.start.character-e.currRange.start.character;n.forEach(l=>{let u=l.text.length;l.replace(a,Math.min(a+o,u),i)})}}}addRange(e,t){if(this.changed){C.showMessage("Can't add range after range change.");return}let{ranges:i}=this,n=i.findIndex(o=>Bl(o.range,e));if(n!==-1){i.splice(n,1);for(let o of i)o.line==e.start.line&&o.start>e.start.character&&(o.preCount=o.preCount-1)}else{let o=0,s=0,{line:a}=e.start;for(let u of i){if(u.line>a||u.line==a&&u.start>e.end.character)break;u.line==a&&o++,s++}let l=new VC(a,e.start.character,e.end.character,t,o);i.splice(s,0,l);for(let u of i)u.line==e.start.line&&u.start>e.start.character&&(u.preCount=u.preCount+1)}this.ranges.length==0?this.cancel():this.doHighlights()}async applySingleEdit(e,t){let{range:i,newText:n}=t,{doc:o}=this;if(this.adjustRanges(e,i,n),this.ranges.length==1){this.doHighlights();return}let s=this.ranges.map(d=>d.textEdit),l=kt.applyEdits(this.textDocument,s).split(` -`),u=new Set,c=[];for(let d of this.ranges)u.has(d.line)||(u.add(d.line),c.push([d.line,l[d.line]]));let{nvim:f}=this;this.changing=!0,await o.changeLines(c),this.changing=!1,this.activated&&(this.ranges.forEach(d=>{d.sync()}),this.textDocument=this.doc.textDocument),f.pauseNotification();let{cursor:p}=A;if(e.preCount>0&&p.bufnr==o.bufnr&&e.line+1==p.lnum){let d=e.preCount*(n.length-(i.end.character-i.start.character));f.call("cursor",[p.lnum,p.col+d],!0)}this.doHighlights(),f.resumeNotification(!1,!0)}applyComposedEdit(e,t){let{range:i,newText:n}=t,{ranges:o}=this,s=kt.create("file:///1","",0,e),a=[],l=ju.default(e,n),u=0;for(let c=0;cc.newText.includes(` -`)||c.range.start.line!=c.range.end.line)){this.cancel();return}if(a.length==o.length){let c;for(let f=0;f{t.affectsConfiguration("cursors")&&this.loadConfig()},null,this.disposables),A.on("BufUnload",t=>{let i=this.getSession(t);!i||(i.dispose(),this.sessionsMap.delete(t))},null,this.disposables)}loadConfig(){let e=b.getConfiguration("cursors");this.config={nextKey:e.get("nextKey",""),previousKey:e.get("previousKey",""),cancelKey:e.get("cancelKey","")}}getSession(e){return this.sessionsMap.get(e)}async isActivated(){let e=await this.nvim.call("bufnr",["%"]);return this.sessionsMap.get(e)!=null}async select(e,t,i){let n=b.getDocument(e);if(!n||!n.attached){C.showMessage(`buffer ${e} not attached.`);return}let{nvim:o}=this,s=this.createSession(n),a=await C.getCursorPosition(),l;if(t=="operator"){await o.command(`normal! ${i=="line"?"'[":"`["}`);let u=await C.getCursorPosition();await o.command(`normal! ${i=="line"?"']":"`]"}`);let c=await C.getCursorPosition();await C.moveTo(a);let f=Ne(u,c);if(f==0)return;f>=0&&([u,c]=[c,u]);let p=n.getline(c.line);c.character=u.length?l=Wu.Range.create(a.line,u.length-1,a.line,u.length):l=Wu.Range.create(a.line,a.character,a.line,a.character+1),s.addRange(l,u.slice(l.start.character,l.end.character))}else if(t=="range"){await o.call("eval",'feedkeys("\\", "in")');let u=await b.getSelectedRange(i,n);if(!u||Ne(u.start,u.end)==0)return;let c=i==""?_9(n,u):KC(n,u);for(let f of c){let p=n.textDocument.getText(f);s.addRange(f,p)}}else{C.showMessage(`${t} not supported`,"error");return}(t=="word"||t=="position")&&await o.command(`silent! call repeat#set("\\(coc-cursors-${t})", -1)`)}createSession(e){let t=this.getSession(e.bufnr);return t||(t=new T9(this.nvim,e,this.config),this.sessionsMap.set(e.bufnr,t),t.onDidCancel(()=>{t.dispose(),this.sessionsMap.delete(e.bufnr)}),t)}async addRanges(e){let{nvim:t}=this,i=await t.call("bufnr",["%"]),n=b.getDocument(i);return!n||!n.attached?(C.showMessage("Document not attached","error"),!1):this.createSession(n).addRanges(e)}reset(){for(let e of this.sessionsMap.values())e.cancel();this.sessionsMap.clear()}dispose(){for(let e of this.sessionsMap.values())e.dispose();this.sessionsMap.clear();for(let e of this.disposables)e.dispose()}},R9=XC;var ke=S(W());var ZC=S(Vr()),QC=S(W());var dbe=U()("codelens-buffer"),e_=class{constructor(e,t,i){this.nvim=e;this.bufnr=t;this.config=i;this._disposed=!1;this.fetchCodelenses=ZC.default(()=>{this._fetchCodeLenses().logError()},global.hasOwnProperty("__TEST__")?10:100),this.resolveCodeLens=ZC.default(()=>{this._resolveCodeLenses().logError()},global.hasOwnProperty("__TEST__")?10:100),this.forceFetch().logError()}async forceFetch(){this.fetchCodelenses.clear(),await this._fetchCodeLenses()}get textDocument(){var e;return(e=b.getDocument(this.bufnr))==null?void 0:e.textDocument}get hasProvider(){let{textDocument:e}=this;return e?B.hasProvider("codeLens",e):!1}async _fetchCodeLenses(){if(!this.config.enabled||!this.hasProvider)return;let{textDocument:e}=this,t=e.version;if(this.codeLenses&&this.codeLenses.codeLenses.length>0&&t==this.codeLenses.version){await this._resolveCodeLenses(!0)||this.clear();return}this.cancel();let n=(this.tokenSource=new QC.CancellationTokenSource).token,o=await B.getCodeLens(e,n);this.tokenSource=void 0,!n.isCancellationRequested&&(this.resolveCodeLens.clear(),Array.isArray(o)&&(this.codeLenses={version:t,codeLenses:o},await this._resolveCodeLenses(!0)||this.clear()))}async _resolveCodeLenses(e=!1){if(!this.config.enabled||!this.codeLenses||this._disposed)return!1;let{codeLenses:t,version:i}=this.codeLenses,[n,o,s]=await this.nvim.eval("[bufnr('%'),line('w0'),line('w$')]");if(!this.textDocument||this.textDocument.version!=i||n!=this.bufnr||(t=t.filter(f=>{let p=f.range.start.line+1;return p>=o&&p<=s}),e||(t=t.filter(f=>f.command==null)),!t.length))return!1;let a=new QC.CancellationTokenSource,l=a.token,u=setTimeout(()=>{a.cancel()},1e3);if(await Promise.all(t.map(f=>B.resolveCodeLens(f,l))),clearTimeout(u),this.tokenSource=void 0,l.isCancellationRequested||this._disposed)return!1;this.srcId=await this.nvim.createNamespace("coc-codelens"),this.nvim.pauseNotification(),e&&this.clear(),this.setVirtualText(t);let c=await this.nvim.resumeNotification();return Array.isArray(c)&&c[1]!=null?(dbe.error("Error on resolve codeLens",c[1][2]),!1):!0}setVirtualText(e){if(e.length==0)return;let t=new Map;for(let i of e){let{range:n,command:o}=i;if(!o)continue;let{line:s}=n.start;t.has(s)?t.get(s).push(i):t.set(s,[i])}for(let i of t.keys()){let o=t.get(i).map(l=>l.command);o=o.filter(l=>l&&l.title);let s=[],a=o.length;for(let l=0;l=0;a--)if(i.has(a)){n=i.get(a);break}if(!n){C.showMessage("No codeLenses available","warning");return}let o=n.map(a=>a.command);if(o=o.filter(a=>a.command!=null&&a.command!=""),o.length==0)C.showMessage("CodeLenses command not found","warning");else if(o.length==1)me.execute(o[0]);else{let a=await C.showMenuPicker(o.map(l=>l.title));if(a==-1)return;me.execute(o[a])}}cancel(){this.tokenSource&&(this.tokenSource.cancel(),this.tokenSource.dispose(),this.tokenSource=null)}onChange(){!this.config.enabled||(this.cancel(),this.resolveCodeLens.clear())}dispose(){this._disposed=!0,this.codeLenses=void 0,this.cancel(),this.fetchCodelenses.clear(),this.resolveCodeLens.clear()}},k9=e_;var O9e=U()("codelens"),t_=class{constructor(e){this.nvim=e;this.disposables=[];this.setConfiguration(),b.onDidChangeConfiguration(i=>{this.setConfiguration(i)},null,this.disposables),this.buffers=b.registerBufferSync(i=>{if(i.buftype=="")return new k9(e,i.bufnr,this.config)}),A.on("ready",()=>{this.checkProvider()},null,this.disposables),A.on("CursorMoved",i=>{let n=this.buffers.getItem(i);n&&n.resolveCodeLens()},null,this.disposables);let t=async i=>{let n=this.buffers.getItem(i);n&&await n.forceFetch()};A.on("CursorHold",t,this,this.disposables)}checkProvider(){for(let e of this.buffers.items)e.hasProvider&&e.fetchCodelenses()}setConfiguration(e){if(e&&!e.affectsConfiguration("codeLens"))return;let t=b.getConfiguration("codeLens"),i=this.nvim.hasFunction("nvim_buf_set_virtual_text")&&t.get("enable",!1);if(e&&i!=this.config.enabled)for(let n of this.buffers.items)i?n.forceFetch().logError():n.clear();this.config=Object.assign(this.config||{},{enabled:i,separator:t.get("separator","\u2023"),subseparator:t.get("subseparator"," ")})}async doAction(){let{nvim:e}=this,t=await e.call("bufnr","%"),i=await e.call("line",".")-1,n=this.buffers.getItem(t);await(n==null?void 0:n.doAction(i))}dispose(){this.buffers.dispose(),z(this.disposables)}},I9=t_;var ZK=S(W());var _y=S(W());var WK=S(UK());WK.default.shim();function HK(r,e){if(!e.length)return null;let t=e.length-1,i=e[t];if(i.text==r)return i;for(;t>=0;){let n=e[t];if(n.text==r)return n;t--}return null}function DP(r,e){let t=r.selectionRange,i=e.selectionRange;return t.start.linei.start.line?1:t.start.character-i.start.character}function SP(r,e,t){let{name:i,selectionRange:n,kind:o,children:s,range:a}=e,{start:l}=n;if(r.push({col:l.character+1,lnum:l.line+1,text:i,level:t,kind:_n(o),range:a,selectionRange:n}),s&&s.length){s.sort(DP);for(let u of s)SP(r,u,t+1)}}function zK(r,e){let t=r.location.range.start,i=e.location.range.start,n=t.line-i.line;return n==0?t.character-i.character:n}function Z0e(r){return r&&!r.hasOwnProperty("location")}function EP(r){return Z0e(r[0])}function GK(r){return!!(_y.MarkupContent.is(r)&&r.kind==_y.MarkupKind.Markdown)}function Xu(r,e,t,i=!1){let n=e.trim();!n.length||(i&&t!=="markdown"&&(n="``` "+t+` -`+n+"\n```"),r.push({content:n,filetype:t}))}async function Qe(r){let{changedtick:e}=r;await r.patchChange(),e!=r.changedtick&&await He(50)}function xd(r){let e=wd(r);return`${CP(e.red.toString(16))}${CP(e.green.toString(16))}${CP(e.blue.toString(16))}`}function CP(r){return r.length==1?`0${r}`:r}function wd(r){let{red:e,green:t,blue:i}=r;return{red:Math.round(e*255),green:Math.round(t*255),blue:Math.round(i*255)}}function VK(r){let e=[r.red,r.green,r.blue],t=[];for(let n=0;n{this.doHighlight().catch(o=>{YK.error("Error on color highlight:",o.stack)})},global.hasOwnProperty("__TEST__")?10:500)}onChange(){this.cancel(),this.highlight()}get buffer(){return this.nvim.createBuffer(this.bufnr)}get colors(){return this._colors}hasColor(){return this._colors.length>0}setState(e){this.enabled=e,e?this.highlight():this.clearHighlight()}async doHighlight(){let e=b.getDocument(this.bufnr);if(!(!e||!this.enabled))try{this.tokenSource=new JK.CancellationTokenSource;let{token:t}=this.tokenSource;if(this.version&&e.version==this.version)return;let{version:i}=e,n;if(n=await B.provideDocumentColors(e.textDocument,t),n=n||[],t.isCancellationRequested)return;this.version=i,await this.addHighlight(n,t)}catch(t){YK.error("Error on highlight:",t)}}async addHighlight(e,t){if(e=e||[],qe(this._colors,e))return;let{nvim:i}=this;this._colors=e;let n=lj(e,100);i.pauseNotification(),this.buffer.clearNamespace("color"),this.defineColors(e),i.resumeNotification(!1,!0);for(let o of n){if(t.isCancellationRequested){this._colors=[];return}i.pauseNotification();let s=this.getColorRanges(o);for(let a of s)this.highlightColor(a.ranges,a.color);i.resumeNotification(!1,!0)}b.isVim&&this.nvim.command("redraw",!0)}highlightColor(e,t){let{red:i,green:n,blue:o}=wd(t),s=`BG${xd(t)}`;this.buffer.highlightRanges("color",s,e)}defineColors(e){for(let t of e){let i=xd(t.color);this.usedColors.has(i)||(this.nvim.command(`hi BG${i} guibg=#${i} guifg=#${VK(t.color)?"ffffff":"000000"}`,!0),this.usedColors.add(i))}}getColorRanges(e){let t=[];for(let i of e){let{color:n,range:o}=i,s=t.findIndex(a=>qe(wd(a.color),wd(n)));s==-1?t.push({color:n,ranges:[o]}):t[s].ranges.push(o)}return t}clearHighlight(){this.highlight.clear(),this._colors=[],this.version=null,this.buffer.clearNamespace("color")}hasColorAtPostion(e){let{colors:t}=this;return t.some(i=>Ht(e,i.range)==0)}cancel(){this.tokenSource&&(this.tokenSource.cancel(),this.tokenSource=null)}dispose(){this.highlight.clear(),this.cancel()}},XK=_P;var $Ge=U()("colors"),PP=class{constructor(e){this.nvim=e;this._enabled=!0;this.disposables=[];let t=b.getConfiguration("coc.preferences");this._enabled=t.get("colorSupport",!0),b.isVim&&!b.env.textprop&&(this._enabled=!1);let i=new Set;this.highlighters=b.registerBufferSync(n=>{let o=new XK(this.nvim,n.bufnr,this._enabled,i);return o.highlight(),o}),ge.onDidActiveExtension(()=>{this.highlightAll()},null,this.disposables),b.onDidChangeConfiguration(async n=>{if(!(b.isVim&&!b.env.textprop)&&n.affectsConfiguration("coc.preferences.colorSupport")){let s=b.getConfiguration("coc.preferences").get("colorSupport",!0);if(s!=this._enabled){this._enabled=s;for(let a of this.highlighters.items)a.setState(s)}}},null,this.disposables)}async pickPresentation(){let e=await this.currentColorInfomation();if(!e)return C.showMessage("Color not found at current position","warning");let t=await b.document,i=new ZK.CancellationTokenSource,n=await B.provideColorPresentations(e,t.textDocument,i.token);if(!n||n.length==0)return;let o=await C.showMenuPicker(n.map(c=>c.label),"choose color:");if(o==-1)return;let s=n[o],{textEdit:a,additionalTextEdits:l,label:u}=s;a||(a={range:e.range,newText:u}),await t.applyEdits([a]),l&&await t.applyEdits(l)}async pickColor(){let e=await this.currentColorInfomation();if(!e)return C.showMessage("Color not found at current position","warning");let{color:t}=e,i=[(t.red*255).toFixed(0),(t.green*255).toFixed(0),(t.blue*255).toFixed(0)],n=await this.nvim.call("coc#util#pick_color",[i]);if(n===!1)return;if(!n||n.length!=3){C.showMessage("Failed to get color","warning");return}let o=xd({red:n[0]/65535,green:n[1]/65535,blue:n[2]/65535,alpha:1});await(await b.document).applyEdits([{range:e.range,newText:`#${o}`}])}get enabled(){return this._enabled}clearHighlight(e){let t=this.highlighters.getItem(e);!t||t.clearHighlight()}hasColor(e){let t=this.highlighters.getItem(e);return t?t.hasColor():!1}hasColorAtPostion(e,t){let i=this.highlighters.getItem(e);return i?i.hasColorAtPostion(t):!1}highlightAll(){for(let e of this.highlighters.items)e.highlight()}async doHighlight(e){let t=this.highlighters.getItem(e);!t||await t.doHighlight()}async currentColorInfomation(){let e=await this.nvim.call("bufnr","%"),t=this.highlighters.getItem(e);if(!t)return null;let i=await C.getCursorPosition();for(let n of t.colors){let{range:o}=n,{start:s,end:a}=o;if(i.line==s.line&&i.character>=s.character&&i.character<=a.character)return n}return null}dispose(){this.highlighters.dispose(),z(this.disposables)}},QK=PP;var sn=S(W());var TP=U()("handler-format"),eJ=new Map([["<",">"],[">","<"],["{","}"],["[","]"],["(",")"]]),RP=class{constructor(e){this.nvim=e;this.disposables=[];this.requestStatusItem=C.createStatusBarItem(0,{progress:!0}),this.loadPreferences(),b.onDidChangeConfiguration(this.loadPreferences,this,this.disposables),b.onWillSaveTextDocument(s=>{let{languageId:a}=s.document,l=this.preferences.formatOnSaveFiletypes;if(l.includes(a)||l.some(u=>u==="*")){let u=async()=>{if(!B.hasFormatProvider(s.document)){TP.warn(`Format provider not found for ${s.document.uri}`);return}let c=await b.getFormatOptions(s.document.uri),f=new sn.CancellationTokenSource,p=setTimeout(()=>{f.cancel()},1e3),d=await B.provideDocumentFormattingEdits(s.document,c,f.token);return clearTimeout(p),d};s.waitUntil(u())}},null,this.disposables),A.on(["CursorMoved","CursorMovedI","InsertEnter","TextChangedI","TextChangedP","TextChanged"],()=>{this.requestTokenSource&&(this.requestTokenSource.cancel(),this.requestTokenSource=null)},null,this.disposables),A.on("Enter",async s=>{let{bracketEnterImprove:a}=this.preferences;if(await this.tryFormatOnType(` -`,s),a){let l=await e.call("line",".")-1,u=b.getDocument(s);if(!u)return;await u.patchChange();let c=u.getline(l-1),f=u.getline(l),p=c[c.length-1];if(p&&eJ.has(p)){let d=f.trim()[0];if(d&&eJ.get(p)==d){let h=[],m=await b.getFormatOptions(u.uri),y=m.insertSpaces?" ".repeat(m.tabSize):" ",g=f.match(/^\s*/)[0],w=sn.Position.create(l-1,c.length);if(u.filetype=="vim"){let x=` -`+g+y;h.push({range:sn.Range.create(l,g.length,l,g.length),newText:" \\ "}),x=x+"\\ ",h.push({range:sn.Range.create(w,w),newText:x}),await u.applyEdits(h),await C.moveTo(sn.Position.create(l,x.length-1))}else await e.eval(`feedkeys("\\O", 'in')`)}}}},null,this.disposables);let t,i;A.on("InsertCharPre",async()=>{i=Date.now()},null,this.disposables),A.on("TextChangedI",async(s,a)=>{if(t=Date.now(),!i||t-i>300)return;i=null;let l=b.getDocument(s);if(!l)return;let u=a.pre[a.pre.length-1];!u||!B.hasProvider("onTypeEdit",l.textDocument)||await this.tryFormatOnType(u,s)},null,this.disposables);let n,o;A.on("InsertEnter",s=>{n=s,o=Date.now()}),A.on("TextChangedI",async(s,a)=>{!this.preferences.formatOnType&&!/^\s*$/.test(a.pre)||n!=s||!o||Date.now()-o>30||await this.tryFormatOnType(` -`,s,!0)})}loadPreferences(e){if(!e||e.affectsConfiguration("coc.preferences")){let t=b.getConfiguration("coc.preferences");this.preferences={formatOnType:t.get("formatOnType",!1),formatOnSaveFiletypes:t.get("formatOnSaveFiletypes",[]),formatOnTypeFiletypes:t.get("formatOnTypeFiletypes",[]),bracketEnterImprove:t.get("bracketEnterImprove",!0)}}}async withRequestToken(e,t){this.requestTokenSource&&(this.requestTokenSource.cancel(),this.requestTokenSource.dispose());let i=this.requestStatusItem;this.requestTokenSource=new sn.CancellationTokenSource;let{token:n}=this.requestTokenSource;n.onCancellationRequested(()=>{i.text=`${e} request canceled`,i.isProgress=!1,i.hide()}),i.isProgress=!0,i.text=`requesting ${e}`,i.show();let o;try{o=await Promise.resolve(t(n))}catch(s){C.showMessage(s.message,"error"),TP.error(`Error on ${e}`,s)}return this.requestTokenSource&&(this.requestTokenSource.dispose(),this.requestTokenSource=void 0),n.isCancellationRequested?null:(i.hide(),o==null&&TP.warn(`${e} provider not found!`),o)}async tryFormatOnType(e,t,i=!1){if(!e||OB(e)||!this.preferences.formatOnType||At.getSession(t)!=null)return;let n=b.getDocument(t);if(!n||!n.attached||n.isCommandLine)return;let o=this.preferences.formatOnTypeFiletypes;if(o.length&&!o.includes(n.filetype)||!B.hasOnTypeProvider(e,n.textDocument))return;let s,a=await this.withRequestToken("onTypeFormat ",async c=>{s=await C.getCursorPosition();let f=n.getline(s.line-1);if(i&&/^\s*$/.test(f))return;let p=i?{line:s.line-1,character:f.length}:s;return await Qe(n),await B.provideDocumentOnTypeEdits(e,n.textDocument,p,c)});if(!a||!a.length)return;let l=jl(s,a);await n.applyEdits(a);let u=l?sn.Position.create(s.line+l.line,s.character+l.character):null;u&&!i&&await C.moveTo(u)}async documentFormat(e){await Qe(e);let t=await b.getFormatOptions(e.uri),i=await this.withRequestToken("format",n=>B.provideDocumentFormattingEdits(e.textDocument,t,n));return i&&i.length>0?(await e.applyEdits(i),!0):!1}async documentRangeFormat(e,t){await Qe(e);let i;if(t){if(i=await b.getSelectedRange(t,e),!i)return-1}else{let[s,a,l]=await this.nvim.eval("[v:lnum,v:count,mode()]");if(a==0||l=="i"||l=="R")return-1;i=sn.Range.create(s-1,0,s-1+a,0)}let n=await b.getFormatOptions(e.uri),o=await this.withRequestToken("format",s=>B.provideDocumentRangeFormattingEdits(e.textDocument,i,n,s));return o&&o.length>0?(await e.applyEdits(o),0):-1}dispose(){z(this.disposables)}},tJ=RP;var Dd=S(W());var Q0e=U()("documentHighlight"),kP=class{constructor(e){this.nvim=e;this.disposables=[];this.highlights=new Map;A.on(["TextChanged","TextChangedI","CursorMoved","CursorMovedI"],()=>{this.cancel(),this.clearHighlights()},null,this.disposables)}clearHighlights(){if(this.highlights.size==0)return;let{nvim:e}=b;for(let t of this.highlights.keys())e.createWindow(t).clearMatchGroup("^CocHighlight");this.highlights.clear()}async highlight(){let{nvim:e}=this;this.cancel();let[t,i,n]=await e.eval("[bufnr('%'),win_getid(),get(b:,'coc_cursors_activated',0)]"),o=b.getDocument(t);if(!o||!o.attached||!B.hasProvider("documentHighlight",o.textDocument)||n)return;let s=await C.getCursorPosition(),a=await this.getHighlights(o,s);if(!a)return;let l={};for(let f of a){if(!f.range)continue;let p=f.kind==Dd.DocumentHighlightKind.Text?"CocHighlightText":f.kind==Dd.DocumentHighlightKind.Read?"CocHighlightRead":"CocHighlightWrite";l[p]=l[p]||[],l[p].push(f.range)}let u=e.createWindow(i);e.pauseNotification(),u.clearMatchGroup("^CocHighlight");for(let f of Object.keys(l))u.highlightRanges(f,l[f],-1,!0);b.isVim&&e.command("redraw",!0);let c=this.nvim.resumeNotification();Array.isArray(c)&&c[1]!=null?Q0e.error("Error on highlight",c[1][2]):this.highlights.set(i,a)}hasHighlights(e){return this.highlights.get(e)!=null}async getHighlights(e,t){if(!e||!e.attached||e.isCommandLine)return null;let n=e.getline(t.line)[t.character];if(!n||!e.isWord(n))return null;try{this.tokenSource=new Dd.CancellationTokenSource,e.forceSync();let{token:o}=this.tokenSource,s=await B.getDocumentHighLight(e.textDocument,t,o);return this.tokenSource=null,o.isCancellationRequested?null:s}catch(o){return null}}cancel(){this.tokenSource&&(this.tokenSource.cancel(),this.tokenSource.dispose(),this.tokenSource=null)}dispose(){this.highlights.clear(),this.cancel(),z(this.disposables)}},rJ=kP;var ec=S(W());var iJ=S(require("child_process")),nJ=S(require("events")),oJ=S(require("path")),sJ=S(require("readline")),aJ=S(jn()),lJ=S(_l());var eSe=U()("handler-search"),tSe=["--color","ansi","--colors","path:fg:black","--colors","line:fg:green","--colors","match:fg:red","--no-messages","--heading","-n"],rSe="",uJ=class extends nJ.EventEmitter{start(e,t,i){this.process=iJ.spawn(e,t,{cwd:i}),this.process.on("error",c=>{this.emit("error",c.message)});let n=sJ.default.createInterface(this.process.stdout),o,s,a=[],l=[],u=!0;n.on("line",c=>{if(c.includes(rSe)){let f=jf(c);if(f[0].foreground=="black"){s={filepath:oJ.default.join(i,f[0].text),ranges:[]};return}if(f[0].foreground=="green"){let d=parseInt(f[0].text,10)-1,h=f[0].text.length+1;u&&(o=d,u=!1);let m="";for(let g of f){if(g.foreground=="red"){let w=d-o,x=m.length-h;l.push(aJ.Range.create(w,x,w,x+g.text.length))}m+=g.text}let y=m.slice(h);a.push(y)}}else{let f=c.trim().length==0;if(s&&(f||c.trim()=="--")){let p={lines:a,highlights:l,start:o,end:o+a.length};s.ranges.push(p)}f&&(this.emit("item",s),s=null),a=[],l=[],u=!0}}),n.on("close",()=>{if(s){if(a.length){let c={lines:a,highlights:l,start:o,end:o+a.length};s.ranges.push(c)}this.emit("item",s)}a=l=s=null,this.emit("end")})}dispose(){this.process&&this.process.kill()}},IP=class{constructor(e,t="rg"){this.nvim=e;this.cmd=t}run(e,t,i){let{nvim:n,cmd:o}=this,{afterContext:s,beforeContext:a}=i.config,l=["-A",s.toString(),"-B",a.toString()].concat(tSe,e);l.push("--","./");try{o=lJ.default.sync(o)}catch(m){return C.showMessage(`Please install ripgrep and make sure ${this.cmd} is in your $PATH`,"error"),Promise.reject(m)}this.task=new uJ,this.task.start(o,l,t);let u=new ar,c=0,f=0,p=Date.now(),d=[],h=async()=>{if(d.length==0)return;let m=d.slice();d=[];let y=await u.acquire();try{await i.addFileItems(m)}catch(g){eSe.error(g)}y()};return new Promise((m,y)=>{let g=setInterval(h,300);this.task.on("item",async w=>{c++,f=f+w.ranges.reduce((x,E)=>x+E.highlights.length,0),d.push(w)}),this.task.on("error",w=>{clearInterval(g),C.showMessage(`Error on command "${o}": ${w}`,"error"),this.task=null,y(new Error(w))}),this.task.on("end",async()=>{clearInterval(g);try{await h(),(await u.acquire())(),this.task.removeAllListeners(),this.task=null;let x=i.buffer;if(x){if(n.pauseNotification(),c==0)x.setLines(["No match found"],{start:1,end:2,strictIndexing:!1},!0),x.addHighlight({line:1,srcId:-1,colEnd:-1,colStart:0,hlGroup:"Error"}).logError(),x.setOption("modified",!1,!0);else{let E=new ls;E.addText("Files","MoreMsg"),E.addText(": "),E.addText(`${c} `,"Number"),E.addText("Matches","MoreMsg"),E.addText(": "),E.addText(`${f} `,"Number"),E.addText("Duration","MoreMsg"),E.addText(": "),E.addText(`${Date.now()-p}ms`,"Number"),E.render(x,1,2)}x.setOption("modified",!1,!0),await n.resumeNotification(!1,!0)}}catch(w){y(w);return}m()})})}},cJ=IP;var Zu=S(Ul()),Sd=S(require("path")),Py=S(W());var fJ=U()("handler-refactorBuffer"),Qu="\u3000",FP=class{constructor(e,t,i,n,o){this.bufnr=e;this.srcId=t;this.nvim=i;this.config=n;this.opts=o;this.mutex=new ar;this._disposed=!1;this.disposables=[];this._fileItems=[];this.matchIds=new Set;this.changing=!1;this.disposables.push(b.registerLocalKeymap("n","",this.splitOpen.bind(this),!0)),b.onDidChangeTextDocument(this.onDocumentChange,this,this.disposables)}get fileItems(){return this._fileItems}onChange(e){if(this.changing)return;let t=this.document,{nvim:i,_fileItems:n}=this;if(!n.length)return;let o=e.contentChanges[0];if(!("range"in o))return;let{original:s}=e;if(o.range.end.line<2)return;t.buffer.setOption("modified",!0,!0);let{range:a,text:l}=o,c=l.split(` -`).length-(a.end.line-a.start.line)-1;if(c==0)return;let f=[];if(l.includes("\u3000")){let d=a.start.line,h=Zu.default(s,l),m=0,y=kt.create("file:///1","",0,s);for(let g=0;gy.lnumg+w.delta,0);h.lnum=h.lnum+y,p=!0}}!p||(i.pauseNotification(),this.highlightLineNr(),i.resumeNotification().then(d=>{Array.isArray(d)&&d[1]!=null&&fJ.error("Error on highlightLineNr:",d[1])}).logError())}async onDocumentChange(e){if(e.bufnr==this.bufnr||this.changing)return;let{uri:t}=e.textDocument,{range:i,text:n}=e.contentChanges[0],o=$.parse(t).fsPath,s=this._fileItems.find(u=>u.filepath==o);if(!s)return;let a=n.split(` -`).length-(i.end.line-i.start.line)-1,l=[];for(let u=0;u=c.end))if(i.end.lineu.ranges&&u.ranges.length>0),l.length&&(this.changing=!0,await this.document.applyEdits(l),this.changing=!1),this.nvim.pauseNotification(),this.highlightLineNr(),this.buffer.setOption("modified",!1,!0),await this.nvim.resumeNotification()}async getFileChanges(){if(this._disposed)return[];let e=[],t=await this.buffer.lines;t.push(Qu);let i=[],n,o;for(let s=0;s1){let l=a.match(/^\u3000(.*)/);l&&(n=this.getAbsolutePath(l[1].replace(/\s+$/,"")),o=s+1,i=[])}}else i.push(a)}return e}async splitOpen(){let{nvim:e}=this,i=await e.createWindow(this.opts.fromWinid).valid,n=await e.eval('getline(1,line("."))'),o=n.length;for(let s=0;sd.filepath==f.filepath);p?p.ranges.push(...f.ranges):this._fileItems.push(f)}let o=i.lineCount,s=new ls,a=[];for(let f of e)for(let p of f.ranges){s.addLine(Qu),s.addLine(Qu),p.lnum=o+s.length,s.addText(`${Xe(t,f.filepath)?Sd.default.relative(t,f.filepath):f.filepath}`);let d=String(p.start+1).length+String(p.end).length+4;this.srcId||s.addText(" ".repeat(d));let h=0-s.length-o;p.highlights&&a.push(...p.highlights.map(y=>iSe(y,h)));let{lines:m}=p;m||(m=await this.getLines(f.filepath,p.start,p.end),p.lines=m),s.addLines(m)}let{nvim:l,buffer:u}=this;if(this.changing=!0,l.pauseNotification(),s.render(u,o),this.highlightLineNr(),u.setOption("modified",!1,!0),u.setOption("undolevels",1e3,!0),o==2&&a.length){let f=a[0].start;l.call("coc#util#jumpTo",[f.line,f.character],!0)}b.isVim&&l.command("redraw",!0);let[,c]=await l.resumeNotification();if(c)throw new Error(c[2]);await i.patchChange(),this.changing=!1,await me.executeCommand("editor.action.addRanges",a)}catch(o){this.changing=!1,fJ.error("Error on add file item:",o)}n()}async save(){let{nvim:e}=this,t=this.document,{buffer:i}=t;await t.patchChange();let n=await this.getFileChanges();if(!n)return;n.sort((l,u)=>l.lnum-u.lnum);let o=[],s=new Map;for(let l=0;lm.filepath==c),h=d?d.ranges.find(m=>m.lnum==f):null;if(!h||qe(h.lines,u.lines)){o.push(l),p&&h&&(h.start=h.start+p,h.end=h.end+p);continue}if(u.start=h.start,u.end=h.end,p!=0&&(h.start=h.start+p),u.lines.length!=h.lines.length){let y=u.lines.length-h.lines.length+p;s.set(c,y),h.end=h.end+y}else h.end=h.end+p;h.lines=u.lines}if(o.length&&(n=n.filter((l,u)=>!o.includes(u))),n.length==0)return C.showMessage("No change.","more"),await i.setOption("modified",!1),!1;let a={};for(let l of n){let u=$.file(l.filepath).toString(),c=a[u]||[];c.push({range:Py.Range.create(l.start,0,l.end,0),newText:l.lines.join(` -`)+` -`}),a[u]=c}return this.changing=!0,await b.applyEdit({changes:a}),this.changing=!1,e.pauseNotification(),i.setOption("modified",!1,!0),this.config.saveToFile&&e.command("silent noa wa",!0),this.highlightLineNr(),await e.resumeNotification(),!0}getFileRange(e){for(let t of this._fileItems)for(let i of t.ranges)if(i.lnum==e)return i;return null}getLinesRange(e){for(let t of this._fileItems)for(let i of t.ranges)if(i.lnum==e)return[i.start,i.end];return null}async getLines(e,t,i){let n=$.file(e).toString(),o=b.getDocument(n);return o?o.getLines(t,i):await Q3(e,t,i-1)}getAbsolutePath(e){return Sd.default.isAbsolute(e)?e:Sd.default.join(this.opts.cwd,e)}getFileRangeRange(e,t=!0){let{document:i}=this;if(!i)return null;let{lnum:n}=e;if(!i.getline(n-1).startsWith("\u3000"))return null;let s=t?n:n-1,a=i.lineCount;for(let l=n;l{let t=this.buffers.get(e.bufnr);t&&(t.dispose(),this.buffers.delete(e.bufnr))},null,this.disposables),b.onDidChangeTextDocument(e=>{let t=this.buffers.get(e.bufnr);t&&t.onChange(e)},null,this.disposables)}setConfiguration(e){if(e&&!e.affectsConfiguration("refactor"))return;let t=b.getConfiguration("refactor");this.config=Object.assign(this.config||{},{afterContext:t.get("afterContext",3),beforeContext:t.get("beforeContext",3),openCommand:t.get("openCommand","edit"),saveToFile:t.get("saveToFile",!0)})}getBuffer(e){return this.buffers.get(e)}async search(e){let t=await this.createRefactorBuffer();if(!t)return;let i=await this.nvim.call("getcwd",[]);await new cJ(this.nvim).run(e,i,t)}async createRefactorBuffer(e){let{nvim:t}=this,[i,n]=await t.eval("[win_getid(),getcwd()]"),{openCommand:o}=this.config;t.pauseNotification(),t.command(`${o} ${oSe}${sSe++}`,!0),t.command("setl buftype=acwrite nobuflisted bufhidden=wipe nofen wrap conceallevel=2 concealcursor=n",!0),t.command("setl undolevels=-1 nolist nospell noswapfile foldmethod=expr foldexpr=coc#util#refactor_foldlevel(v:lnum)",!0),t.command("setl foldtext=coc#util#refactor_fold_text(v:foldstart)",!0),t.call("setline",[1,["Save current buffer to make changes",Qu]],!0),t.call("matchadd",["Comment","\\%1l"],!0),t.call("matchadd",["Conceal","^\\%u3000"],!0),t.call("matchadd",["Label","^\\%u3000\\zs\\S\\+"],!0),t.command("setl nomod",!0),e&&t.command(`runtime! syntax/${e}.vim`,!0),t.call("coc#util#do_autocmd",["CocRefactorOpen"],!0);let[,s]=await t.resumeNotification();if(s){nSe.error(s),C.showMessage(`Error on open refactor window: ${s}`,"error");return}let[a,l]=await t.eval('[bufnr("%"),win_getid()]'),u={fromWinid:i,winid:l,cwd:n};await b.document;let c=new pJ(a,this.srcId,this.nvim,this.config,u);return this.buffers.set(a,c),c}async fromLines(e){let t=await this.createRefactorBuffer();return t&&await t.buffer.setLines(e,{start:0,end:-1,strictIndexing:!1}),t}async fromLocations(e,t){if(!e||e.length==0)return null;let i={},n={changes:i};for(let o of e){let s=i[o.uri]||[];s.push({range:o.range,newText:""}),i[o.uri]=s}return await this.fromWorkspaceEdit(n,t)}async fromWorkspaceEdit(e,t){if(!e||aSe(e))return;let i=[],{beforeContext:n,afterContext:o}=this.config,{changes:s,documentChanges:a}=e;if(!s){s={};for(let u of a||[])if(ec.TextDocumentEdit.is(u)){let{textDocument:c,edits:f}=u;c.uri.startsWith("file:")&&(s[c.uri]=f)}}for(let u of Object.keys(s)){let c=await this.getLineCount(u),f=s[u],p=[],d=null,h=null,m=[];f.sort((y,g)=>y.range.start.line-g.range.start.line);for(let y of f){let{line:g}=y.range.start,w=Math.max(0,g-n);d!=null&&w{if(!this.signaturePosition)return;let o=b.getDocument(i);if(!o)return;let{line:s,character:a}=this.signaturePosition;if(n[0]-1==s){let l=o.getline(n[0]-1),u=ue(l.slice(0,a))+1;if(n[1]>=u)return}this.signatureFactory.close()},null,this.disposables),A.on(["InsertLeave","BufEnter"],()=>{var i;(i=this.tokenSource)==null||i.cancel(),this.signatureFactory.close()},null,this.disposables),A.on(["TextChangedI","TextChangedP"],async()=>{this.config.hideOnChange&&this.signatureFactory.close()},null,this.disposables);let t;A.on("InsertCharPre",async()=>{t=Date.now()},null,this.disposables),A.on("TextChangedI",async(i,n)=>{if(!this.config.trigger||!t||Date.now()-t>300)return;t=null;let o=b.getDocument(i);if(!o||o.isCommandLine||!o.attached)return;let s=n.pre[n.pre.length-1];!s||B.shouldTriggerSignatureHelp(o.textDocument,s)&&await this.triggerSignatureHelp(o,{line:n.lnum-1,character:n.pre.length},!1)},null,this.disposables)}loadConfiguration(e){if(!e||e.affectsConfiguration("signature")){let t=b.getConfiguration("signature"),i=t.get("target","float");i=="float"&&!b.floatSupported&&(i="echo"),this.config={target:i,trigger:t.get("enable",!0),wait:Math.max(t.get("triggerSignatureWait",500),200),maxWindowHeight:t.get("maxWindowHeight",80),maxWindowWidth:t.get("maxWindowWidth",80),preferAbove:t.get("preferShownAbove",!0),hideOnChange:t.get("hideOnTextChange",!1)}}}async triggerSignatureHelp(e,t,i=!0){var p;(p=this.tokenSource)==null||p.cancel();let n=this.tokenSource=new an.CancellationTokenSource,o=n.token;o.onCancellationRequested(()=>{n.dispose(),this.tokenSource=void 0});let{target:s}=this.config,a=this.timer=setTimeout(()=>{n.cancel()},this.config.wait),{changedtick:l}=e;if(await e.patchChange(),l!=e.changedtick&&await He(30),o.isCancellationRequested)return!1;let u=await B.getSignatureHelp(e.textDocument,t,o,{isRetrigger:!1,triggerKind:i?an.SignatureHelpTriggerKind.Invoked:an.SignatureHelpTriggerKind.TriggerCharacter});if(clearTimeout(a),o.isCancellationRequested)return!1;if(!u||u.signatures.length==0)return this.signatureFactory.close(),!1;let{activeSignature:c,signatures:f}=u;if(c){let[d]=f.splice(c,1);d&&f.unshift(d)}s=="echo"?this.echoSignature(u):await this.showSignatureHelp(e,t,u)}async showSignatureHelp(e,t,i){let{signatures:n,activeParameter:o}=i,s=0,a=null,l=n.reduce((d,h,m)=>{var w;let y=null,g=h.label.indexOf("(");if(m==0&&o!=null){let x=(w=h.parameters)==null?void 0:w[o];if(x){let E=h.label.slice(g==-1?0:g);if(a=x.documentation,typeof x.label=="string"){let P=E.slice(0),k=P.match(new RegExp("\\b"+x.label.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"\\b")),_=k?k.index:P.indexOf(x.label);_!=-1&&(y=[_+g,_+x.label.length+g])}else y=x.label}}if(y==null&&(y=[g+1,g+1]),s==0&&(s=y[0]+1),d.push({content:h.label,filetype:e.filetype,active:y}),a){let x=typeof a=="string"?a:a.value;x.trim().length&&d.push({content:x,filetype:mJ(h.documentation)?"markdown":"txt"})}if(m==0&&h.documentation){let{documentation:x}=h,E=typeof x=="string"?x:x.value;E.trim().length&&d.push({content:E,filetype:mJ(h.documentation)?"markdown":"txt"})}return d},[]),u=At.getSession(e.bufnr);if(u&&u.isActive){let{value:d}=u.placeholder;d.includes(` -`)||(s+=d.length),this.signaturePosition=an.Position.create(t.line,t.character-d.length)}else this.signaturePosition=t;let{preferAbove:c,maxWindowHeight:f,maxWindowWidth:p}=this.config;await this.signatureFactory.show(l,{maxWidth:p,maxHeight:f,preferTop:c,autoHide:!1,offsetX:s,modes:["i","ic","s"]})}echoSignature(e){var s;let{signatures:t,activeParameter:i}=e,n=b.env.columns;t=t.slice(0,b.env.cmdheight);let o=[];for(let a of t){let l=[],{label:u}=a;u=u.replace(/\n/g," "),u.length>=n-16&&(u=u.slice(0,n-16)+"...");let c=u.indexOf("(");if(c==-1)l=[{text:u,type:"Normal"}];else{l.push({text:u.slice(0,c),type:"Label"});let f=u.slice(c);if(o.length==0&&i!=null){let p=(s=a.parameters)==null?void 0:s[i];if(p){let d,h;if(typeof p.label=="string"){let m=f.slice(0),y=m.match(new RegExp("\\b"+p.label.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"\\b")),g=y?y.index:m.indexOf(p.label);g==-1?l.push({text:f,type:"Normal"}):(d=g,h=g+p.label.length)}else[d,h]=p.label,d=d-c,h=h-c;d!=null&&h!=null&&(l.push({text:f.slice(0,d),type:"Normal"}),l.push({text:f.slice(d,h),type:"MoreMsg"}),l.push({text:f.slice(h),type:"Normal"}))}}else l.push({text:f,type:"Normal"})}o.push(l)}this.nvim.callTimer("coc#util#echo_signatures",[o],!0)}dispose(){z(this.disposables),this.timer&&clearTimeout(this.timer),this.tokenSource&&(this.tokenSource.cancel(),this.tokenSource.dispose())}},gJ=OP;function mJ(r){return!!(an.MarkupContent.is(r)&&r.kind==an.MarkupKind.Markdown)}var vJ=S(Vr()),fo=S(W());var LP=class{constructor(e){this.nvim=e;this.disposables=[];this.buffers=b.registerBufferSync(t=>{if(t.buftype!="")return;let i=new yJ(t.bufnr);return i.onDidUpdate(async n=>{await A.fire("SymbolsUpdate",[i.bufnr,n])}),i}),A.on("CursorHold",async t=>{!this.functionUpdate||this.buffers.getItem(t)==null||await this.getCurrentFunctionSymbol(t)},null,this.disposables)}get functionUpdate(){return b.getConfiguration("coc.preferences").get("currentFunctionSymbolAutoUpdate",!1)}get labels(){return b.getConfiguration("suggest").get("completionItemKindLabels",{})}async getDocumentSymbols(e){let t=this.buffers.getItem(e);return t==null?void 0:t.getSymbols()}async getCurrentFunctionSymbol(e){e||(e=await this.nvim.call("bufnr",["%"]));let t=await C.getCursorPosition(),i=await this.getDocumentSymbols(e),n=this.nvim.createBuffer(e);if(!i||i.length===0)return n.setVar("coc_current_function","",!0),this.nvim.call("coc#util#do_autocmd",["CocStatusChange"],!0),"";i=i.filter(s=>["Class","Method","Function","Struct"].includes(s.kind));let o="";for(let s of i.reverse())if(s.range&&Ht(t,s.range)==0&&!s.text.endsWith(") callback")){o=s.text;let a=this.labels[s.kind.toLowerCase()];a&&(o=`${a} ${o}`);break}return this.functionUpdate&&(n.setVar("coc_current_function",o,!0),this.nvim.call("coc#util#do_autocmd",["CocStatusChange"],!0)),o}async selectSymbolRange(e,t,i){let n=await this.nvim.call("bufnr",["%"]),o=b.getDocument(n);if(!o||!o.attached)return;let s;if(t)s=await b.getSelectedRange(t,o);else{let c=await C.getCursorPosition();s=fo.Range.create(c,c)}let a=await this.getDocumentSymbols(n);if(!a||a.length===0){C.showMessage("No symbols found","warning");return}let l=a.filter(c=>c.kind=="Property");a=a.filter(c=>i.includes(c.kind));let u;for(let c of a.reverse())if(c.range&&!qe(c.range,s)&&Ji(s,c.range)){u=c.range;break}if(!u){for(let c of l)if(c.range&&!qe(c.range,s)&&Ji(s,c.range)){u=c.range;break}}if(e&&u){let{start:c,end:f}=u,p=o.getline(c.line+1),d=o.getline(f.line-1);u=fo.Range.create(c.line+1,p.match(/^\s*/)[0].length,f.line-1,d.length)}u&&await b.selectRange(u)}dispose(){this.buffers.dispose(),z(this.disposables)}},bJ=LP,yJ=class{constructor(e){this.bufnr=e;this.disposables=[];this.autoUpdate=!1;this.symbols=[];this._onDidUpdate=new fo.Emitter;this.onDidUpdate=this._onDidUpdate.event;this.fetchSymbols=vJ.default(()=>{this._fetchSymbols().logError()},global.hasOwnProperty("__TEST__")?10:500)}async getSymbols(){let e=b.getDocument(this.bufnr);return e?(e.forceSync(),this.autoUpdate=!0,e.version==this.version?this.symbols:(this.cancel(),await this._fetchSymbols(),this.symbols)):[]}onChange(){this.cancel()}get textDocument(){var e;return(e=b.getDocument(this.bufnr))==null?void 0:e.textDocument}async _fetchSymbols(){let{textDocument:e}=this;if(!e||e.version==this.version)return;let{version:t}=e,i=this.tokenSource=new fo.CancellationTokenSource,{token:n}=i,o=await B.getDocumentSymbol(e,n);if(this.tokenSource=void 0,o==null||n.isCancellationRequested)return;let s=0,a=[],l=null;if(EP(o))o.sort(DP),o.forEach(u=>SP(a,u,s));else{o.sort(zK);for(let u of o){let{name:c,kind:f,location:p,containerName:d}=u;if(!d||!l)s=0;else if(l.containerName==d)s=l.level||0;else{let y=HK(d,a);s=y?y.level+1:0}let{start:h}=p.range,m={col:h.character+1,lnum:h.line+1,text:c,level:s,kind:_n(f),range:p.range,containerName:d};a.push(m),l=m}}this.version=t,this.symbols=a,EP(o)?this._onDidUpdate.fire(o):this._onDidUpdate.fire(o.map(u=>fo.DocumentSymbol.create(u.name,"",u.kind,u.location.range,u.location.range)))}cancel(){this.fetchSymbols.clear(),this.tokenSource&&(this.tokenSource.cancel(),this.tokenSource=null)}dispose(){this.cancel(),this.symbols=void 0,this._onDidUpdate.dispose(),z(this.disposables)}};var wJ=U()("Handler"),MP=class{constructor(e){this.nvim=e;this.documentLines=[];this.selectionRange=null;this.disposables=[];this.getPreferences(),this.requestStatusItem=C.createStatusBarItem(0,{progress:!0}),b.onDidChangeConfiguration(()=>{this.getPreferences()}),this.refactor=new hJ,this.hoverFactory=new mn(e),this.signature=new gJ(e),this.format=new tJ(e),this.symbols=new bJ(e),this.codeLens=new I9(e),this.colors=new QK(e),this.documentHighlighter=new rJ(e),A.on(["CursorMoved","CursorMovedI","InsertEnter","InsertSnippet","InsertLeave"],()=>{this.requestTokenSource&&this.requestTokenSource.cancel()},null,this.disposables);let t={onDidChange:null,provideTextDocumentContent:async()=>(e.pauseNotification(),e.command("setlocal conceallevel=2 nospell nofoldenable wrap",!0),e.command("setlocal bufhidden=wipe nobuflisted",!0),e.command("setfiletype markdown",!0),e.command(`if winnr('j') != winnr('k') | exe "normal! z${Math.min(this.documentLines.length,this.preferences.previewMaxHeight)}\\ | endif"`,!0),await e.resumeNotification(),this.documentLines.join(` -`))};this.disposables.push(b.registerTextDocumentContentProvider("coc",t)),this.disposables.push(me.registerCommand("editor.action.pickColor",()=>this.pickColor())),me.titles.set("editor.action.pickColor","pick color from system color picker when possible."),this.disposables.push(me.registerCommand("editor.action.colorPresentation",()=>this.pickPresentation())),me.titles.set("editor.action.colorPresentation","change color presentation."),this.disposables.push(me.registerCommand("editor.action.organizeImport",async i=>{await this.organizeImport(i)})),me.titles.set("editor.action.organizeImport","run organize import code action.")}async organizeImport(e){e||(e=await this.nvim.call("bufnr",["%"]));let t=b.getDocument(e);if(!t||!t.attached)throw new Error(`buffer ${e} not attached`);await Qe(t);let i=await this.getCodeActions(t,void 0,[ke.CodeActionKind.SourceOrganizeImports]);if(i&&i.length){await this.applyCodeAction(i[0]);return}throw new Error("Organize import action not found.")}checkProvier(e,t){if(!B.hasProvider(e,t))throw new Error(`${e} provider not found for current buffer, your language server doesn't support it.`)}async withRequestToken(e,t,i){this.requestTokenSource&&(this.requestTokenSource.cancel(),this.requestTokenSource.dispose()),this.requestTimer&&clearTimeout(this.requestTimer);let n=this.requestStatusItem;this.requestTokenSource=new ke.CancellationTokenSource;let{token:o}=this.requestTokenSource;o.onCancellationRequested(()=>{n.text=`${e} request canceled`,n.isProgress=!1,this.requestTimer=setTimeout(()=>{n.hide()},500)}),n.isProgress=!0,n.text=`requesting ${e}`,n.show();let s;try{s=await Promise.resolve(t(o))}catch(a){C.showMessage(a.message,"error"),wJ.error(`Error on ${e}`,a)}return this.requestTokenSource&&(this.requestTokenSource.dispose(),this.requestTokenSource=void 0),o.isCancellationRequested?null:(n.hide(),i&&(!s||Array.isArray(s)&&s.length==0)?(C.showMessage(`${e} not found`,"warning"),null):s)}async getCurrentFunctionSymbol(){let{doc:e}=await this.getCurrentState();return this.checkProvier("documentSymbol",e.textDocument),await this.symbols.getCurrentFunctionSymbol()}async selectSymbolRange(e,t,i){let{doc:n}=await this.getCurrentState();return this.checkProvier("documentSymbol",n.textDocument),await this.symbols.selectSymbolRange(e,t,i)}async getDocumentSymbols(e){let t=b.getDocument(e);if(!t||!t.attached)throw new Error(`buffer ${e} not attached`);return this.checkProvier("documentSymbol",t.textDocument),await this.symbols.getDocumentSymbols(e)}async hasProvider(e){let t=await this.nvim.call("bufnr","%"),i=b.getDocument(t);return i?B.hasProvider(e,i.textDocument):!1}async onHover(e){let{doc:t,position:i,winid:n}=await this.getCurrentState();this.checkProvier("hover",t.textDocument),this.hoverFactory.close(),await Qe(t);let o=await this.withRequestToken("hover",a=>B.getHover(t.textDocument,i,a),!0);if(o==null)return!1;let s=o.find(a=>ke.Range.is(a.range));if(s==null?void 0:s.range){let a=this.nvim.createWindow(n),l=await a.highlightRanges("CocHoverRange",[s.range],99);setTimeout(()=>{l.length&&a.clearMatches(l),b.isVim&&this.nvim.command("redraw",!0)},500)}return await this.previewHover(o,e),!0}async getHover(){let e=[],{doc:t,position:i}=await this.getCurrentState();this.checkProvier("hover",t.textDocument),await Qe(t);let n=new ke.CancellationTokenSource,o=await B.getHover(t.textDocument,i,n.token);if(Array.isArray(o))for(let s of o){let{contents:a}=s;Array.isArray(a)?a.forEach(l=>{e.push(typeof l=="string"?l:l.value)}):ke.MarkupContent.is(a)?e.push(a.value):e.push(typeof a=="string"?a:a.value)}return e=e.filter(s=>s!=null&&s.length>0),e}async gotoDefinition(e){let{doc:t,position:i}=await this.getCurrentState();this.checkProvier("definition",t.textDocument),await Qe(t);let n=await this.withRequestToken("definition",o=>B.getDefinition(t.textDocument,i,o),!0);return n==null?!1:(await this.handleLocations(n,e),!0)}async definitions(){let{doc:e,position:t}=await this.getCurrentState();if(!B.hasProvider("reference",e.textDocument))return[];await Qe(e);let i=new ke.CancellationTokenSource;return B.getDefinition(e.textDocument,t,i.token)}async gotoDeclaration(e){let{doc:t,position:i}=await this.getCurrentState();this.checkProvier("declaration",t.textDocument),await Qe(t);let n=await this.withRequestToken("declaration",o=>B.getDeclaration(t.textDocument,i,o),!0);return n==null?!1:(await this.handleLocations(n,e),!0)}async declarations(){let{doc:e,position:t}=await this.getCurrentState();if(!B.hasProvider("declaration",e.textDocument))return[];await Qe(e);let i=new ke.CancellationTokenSource;return B.getDeclaration(e.textDocument,t,i.token)}async gotoTypeDefinition(e){let{doc:t,position:i}=await this.getCurrentState();this.checkProvier("typeDefinition",t.textDocument),await Qe(t);let n=await this.withRequestToken("type definition",o=>B.getTypeDefinition(t.textDocument,i,o),!0);return n==null?!1:(await this.handleLocations(n,e),!0)}async typeDefinitions(){let{doc:e,position:t}=await this.getCurrentState();if(!B.hasProvider("typeDefinition",e.textDocument))return[];await Qe(e);let i=new ke.CancellationTokenSource;return B.getTypeDefinition(e.textDocument,t,i.token)}async gotoImplementation(e){let{doc:t,position:i}=await this.getCurrentState();this.checkProvier("implementation",t.textDocument),await Qe(t);let n=await this.withRequestToken("implementation",o=>B.getImplementation(t.textDocument,i,o),!0);return n==null?!1:(await this.handleLocations(n,e),!0)}async implementations(){let{doc:e,position:t}=await this.getCurrentState();if(!B.hasProvider("implementation",e.textDocument))return[];await Qe(e);let i=new ke.CancellationTokenSource;return B.getImplementation(e.textDocument,t,i.token)}async gotoReferences(e,t=!0){let{doc:i,position:n}=await this.getCurrentState();this.checkProvier("reference",i.textDocument),await Qe(i);let o=await this.withRequestToken("references",s=>B.getReferences(i.textDocument,{includeDeclaration:t},n,s),!0);return o==null?!1:(await this.handleLocations(o,e),!0)}async references(){let{doc:e,position:t}=await this.getCurrentState();if(!B.hasProvider("reference",e.textDocument))return[];await Qe(e);let i=new ke.CancellationTokenSource;return B.getReferences(e.textDocument,{includeDeclaration:!0},t,i.token)}async getWordEdit(){let{doc:e,position:t}=await this.getCurrentState(),i=e.getWordRangeAtPosition(t);if(!i||Gn(i))return null;let n=e.textDocument.getText(i);if(B.hasProvider("rename",e.textDocument)){await Qe(e);let s=new ke.CancellationTokenSource;if(await B.prepareRename(e.textDocument,t,s.token)===!1)return null;let l=await B.provideRenameEdits(e.textDocument,t,n,s.token);if(l)return l}C.showMessage("Rename provider not found, extract word ranges from current buffer","more");let o=e.getSymbolRanges(n);return{changes:{[e.uri]:o.map(s=>({range:s,newText:n}))}}}async rename(e){let{doc:t,position:i}=await this.getCurrentState();this.checkProvier("rename",t.textDocument),await Qe(t);let n=this.requestStatusItem;try{let o=new ke.CancellationTokenSource().token,s=await B.prepareRename(t.textDocument,i,o);if(s===!1)return n.hide(),C.showMessage("Invalid position for rename","warning"),!1;if(o.isCancellationRequested)return!1;let a;if(e||(ke.Range.is(s)?(a=t.textDocument.getText(s),await C.moveTo(s.start)):s&&typeof s.placeholder=="string"?a=s.placeholder:a=await this.nvim.eval('expand("")'),e=await C.requestInput("New name",a)),!e)return n.hide(),!1;let l=await B.provideRenameEdits(t.textDocument,i,e,o);return o.isCancellationRequested?!1:(n.hide(),l?(await b.applyEdit(l),b.isVim&&this.nvim.command("redraw",!0),!0):(C.showMessage("Invalid position for rename","warning"),!1))}catch(o){return n.hide(),C.showMessage(`Error on rename: ${o.message}`,"error"),wJ.error(o),!1}}async documentFormatting(){let{doc:e}=await this.getCurrentState();return this.checkProvier("format",e.textDocument),await this.format.documentFormat(e)}async documentRangeFormatting(e){let{doc:t}=await this.getCurrentState();return this.checkProvier("formatRange",t.textDocument),await this.format.documentRangeFormat(t,e)}async getTagList(){let{doc:e,position:t}=await this.getCurrentState(),i=await this.nvim.call("expand","");if(!i||!B.hasProvider("definition",e.textDocument))return null;let n=new ke.CancellationTokenSource,o=await B.getDefinition(e.textDocument,t,n.token);return!o||!o.length?null:o.map(s=>{let a=$.parse(s.uri),l=a.scheme=="file"?a.fsPath:a.toString();return{name:i,cmd:`keepjumps ${s.range.start.line+1} | normal ${s.range.start.character+1}|`,filename:l}})}async runCommand(e,...t){if(e){await A.fire("Command",[e]);let i=await me.executeCommand(e,...t);return t.length==0&&await me.addRecent(e),i}else await Kt.start(["commands"])}async getCodeActions(e,t,i){t=t||ke.Range.create(0,0,e.lineCount,0);let o={diagnostics:mt.getDiagnosticsInRange(e.textDocument,t)};i&&Array.isArray(i)&&(o.only=i);let s=await this.withRequestToken("code action",a=>B.getCodeActions(e.textDocument,t,o,a));return!s||s.length==0?[]:(s.sort((a,l)=>a.isPreferred&&!l.isPreferred?-1:l.isPreferred&&!a.isPreferred?1:0),s)}async doCodeAction(e,t){let{doc:i}=await this.getCurrentState(),n;e&&(n=await b.getSelectedRange(e,i)),await Qe(i);let o=await this.getCodeActions(i,n,Array.isArray(t)?t:null);if(t&&typeof t=="string"&&(o=o.filter(l=>l.title==t||l.command&&l.command.title==t),o.length==1)){await this.applyCodeAction(o[0]);return}if(!o||o.length==0){C.showMessage(`No${t?" "+t:""} code action available`,"warning");return}let s=this.preferences.floatActions?await C.showMenuPicker(o.map(l=>l.title),"Choose action"):await C.showQuickpick(o.map(l=>l.title)),a=o[s];a&&await this.applyCodeAction(a)}async getCurrentCodeActions(e,t){let{doc:i}=await this.getCurrentState(),n;return e&&(n=await b.getSelectedRange(e,i)),await this.getCodeActions(i,n,t)}async doQuickfix(){let e=await this.getCurrentCodeActions("line",[ke.CodeActionKind.QuickFix]);return!e||e.length==0?(C.showMessage("No quickfix action available","warning"),!1):(await this.applyCodeAction(e[0]),await this.nvim.command('silent! call repeat#set("\\(coc-fix-current)", -1)'),!0)}async applyCodeAction(e){let{command:t,edit:i}=e;if(i&&await b.applyEdit(i),t)if(me.has(t.command))me.execute(t);else{let n=e.clientId,o=Vt.getService(n),s={command:t.command,arguments:t.arguments};if(o.client){let{client:a}=o;a.sendRequest(ke.ExecuteCommandRequest.type,s).then(void 0,l=>{C.showMessage(`Execute '${t.command} error: ${l}'`,"error")})}}}async doCodeLensAction(){await this.codeLens.doAction()}async fold(e){let{doc:t,winid:i}=await this.getCurrentState();this.checkProvier("foldingRange",t.textDocument),await Qe(t);let n=this.nvim.createWindow(i),[o,s]=await this.nvim.eval("[&foldmethod,&foldlevel]");if(o!="manual")return C.showMessage("foldmethod option should be manual!","warning"),!1;let a=await this.withRequestToken("folding range",l=>B.provideFoldingRanges(t.textDocument,{},l),!0);if(!a)return!1;if(e&&(a=a.filter(l=>l.kind==e)),a.length){a.sort((l,u)=>u.startLine-l.startLine),this.nvim.pauseNotification(),this.nvim.command("normal! zE",!0);for(let l of a){let{startLine:u,endLine:c}=l,f=`${u+1}, ${c+1}fold`;this.nvim.command(f,!0)}return n.setOption("foldenable",!0,!0),n.setOption("foldlevel",s,!0),b.isVim&&this.nvim.command("redraw",!0),await this.nvim.resumeNotification(),!0}return!1}async pickColor(){let{doc:e}=await this.getCurrentState();this.checkProvier("documentColor",e.textDocument),await this.colors.pickColor()}async pickPresentation(){let{doc:e}=await this.getCurrentState();this.checkProvier("documentColor",e.textDocument),await this.colors.pickPresentation()}async highlight(){await this.documentHighlighter.highlight()}async getSymbolsRanges(){let{doc:e,position:t}=await this.getCurrentState();this.checkProvier("documentHighlight",e.textDocument);let i=await this.documentHighlighter.getHighlights(e,t);return i?i.map(n=>n.range):null}async links(){let{doc:e}=await this.getCurrentState();this.checkProvier("documentLink",e.textDocument);let t=await this.withRequestToken("links",n=>B.getDocumentLinks(e.textDocument,n));t=t||[];let i=[];for(let n of t)n.target||(n=await B.resolveDocumentLink(n)),i.push(n);return t}async openLink(){let{doc:e,position:t}=await this.getCurrentState();this.checkProvier("documentLink",e.textDocument);let i=await this.withRequestToken("links",n=>B.getDocumentLinks(e.textDocument,n));if(!i||i.length==0)return!1;for(let n of i)if(Ht(t,n.range)==0){let{target:o}=n;return o||(n=await B.resolveDocumentLink(n),o=n.target),o?(await b.openResource(o),!0):!1}return!1}async getCommands(){let e=me.commandList,t=[],{titles:i}=me;for(let n of e)t.push({id:n.id,title:i.get(n.id)||""});return t}async showSignatureHelp(){let{doc:e,position:t}=await this.getCurrentState();return B.hasProvider("signature",e.textDocument)?await this.signature.triggerSignatureHelp(e,t):!1}async findLocations(e,t,i,n){let{doc:o,position:s}=await this.getCurrentState();i=i||{},Object.assign(i,{textDocument:{uri:o.uri},position:s});let a=await Vt.sendRequest(e,t,i);a=a||[];let l=[];if(Array.isArray(a))l=a;else if(a.hasOwnProperty("location")&&a.hasOwnProperty("children")){let u=c=>{if(l.push(c.location),c.children&&c.children.length)for(let f of c.children)u(f)};u(a)}await this.handleLocations(l,n)}async handleLocations(e,t){if(!e)return;let n=(Array.isArray(e)?e:[e]).length;if(n!=0)if(n==1&&t!==!1){let o=e[0];if(ke.LocationLink.is(e[0])){let l=e[0];o=ke.Location.create(l.targetUri,l.targetRange)}let{uri:s,range:a}=o;await b.jumpTo(s,a.start,t)}else await b.showLocations(e)}async getSelectionRanges(){let{doc:e,position:t}=await this.getCurrentState();this.checkProvier("selectionRange",e.textDocument),await Qe(e);let i=await this.withRequestToken("selection ranges",n=>B.getSelectionRanges(e.textDocument,[t],n));return i&&i.length?i:null}async selectRange(e,t){let{nvim:i}=this,{doc:n}=await this.getCurrentState();this.checkProvier("selectionRange",n.textDocument);let o=[];if(!t&&(!this.selectionRange||!e))return;if(e){let u=await b.getSelectedRange(e,n);o.push(u.start,u.end)}else{let u=await C.getCursorPosition();o.push(u)}if(!t){let u=ke.Range.create(o[0],o[1]),{selectionRange:c}=this;for(;c&&c.parent&&!qe(c.parent.range,u);)c=c.parent;c&&c.parent&&await b.selectRange(c.range);return}await Qe(n);let s=await this.withRequestToken("selection ranges",u=>B.getSelectionRanges(n.textDocument,o,u));if(!s||s.length==0)return;await i.eval("mode()")!="n"&&await i.eval(`feedkeys("\\", 'in')`);let l;if(s.length==1)l=s[0];else if(o.length>1){let u=ke.Range.create(o[0],o[1]);for(l=s[0];l;){if(qe(u,l.range)){l=l.parent;continue}if(Ht(o[1],l.range)==0)break;l=l.parent}}!l||(this.selectionRange=s[0],await b.selectRange(l.range))}async codeActionRange(e,t,i){let{doc:n}=await this.getCurrentState();await Qe(n);let o=n.getline(t-1),s=ke.Range.create(e-1,0,t-1,o.length),a=await this.getCodeActions(n,s,i?[i]:null);if(!a||a.length==0){C.showMessage(`No${i?" "+i:""} code action available`,"warning");return}let l=await C.showMenuPicker(a.map(c=>c.title),"Choose action"),u=a[l];u&&await this.applyCodeAction(u)}async doRefactor(){let{doc:e,position:t}=await this.getCurrentState();await Qe(e);let i=await this.withRequestToken("refactor",async n=>{let o=await B.prepareRename(e.textDocument,t,n);if(n.isCancellationRequested)return null;if(o===!1)return C.showMessage("Invalid position","warning"),null;let s=await B.provideRenameEdits(e.textDocument,t,"NewName",n);return n.isCancellationRequested?null:s||(C.showMessage("Empty workspaceEdit from language server","warning"),null)});i&&await this.refactor.fromWorkspaceEdit(i,e.filetype)}async saveRefactor(e){await this.refactor.save(e)}async search(e){await this.refactor.search(e)}async previewHover(e,t){let i=[],n=b.getConfiguration("hover");t||(t=this.preferences.hoverTarget||n.get("target","float"),t=="float"&&!b.floatSupported&&(t="preview"));let o=t==="preview";for(let a of e){let{contents:l}=a;if(Array.isArray(l))for(let u of l)typeof u=="string"?Xu(i,u,"markdown",o):Xu(i,u.value,u.language,o);else ke.MarkedString.is(l)?typeof l=="string"?Xu(i,l,"markdown",o):Xu(i,l.value,l.language,o):ke.MarkupContent.is(l)&&Xu(i,l.value,GK(l)?"markdown":"txt",o)}if(t=="float"){let a={modes:["n"]};a.maxWidth=n.get("floatMaxWidth",80),a.maxHeight=n.get("floatMaxHeight",void 0),a.autoHide=n.get("autoHide",!0),await this.hoverFactory.show(i,a);return}let s=i.reduce((a,l)=>{let u=l.content.split(/\r?\n/);return a.length>0&&a.push(""),a.push(...u),a},[]);if(t=="echo"){let a=s.join(` -`).trim();a.length&&await this.nvim.call("coc#util#echo_hover",a)}else this.documentLines=s,await this.nvim.command("noswapfile pedit coc://document")}getPreferences(){let e=b.getConfiguration("coc.preferences"),t=e.get("hoverTarget",void 0);this.preferences={hoverTarget:t,previewMaxHeight:e.get("previewMaxHeight",12),previewAutoClose:e.get("previewAutoClose",!1),floatActions:e.get("floatActions",!0)}}async getCurrentState(){let{nvim:e}=this,[t,[i,n],o]=await e.eval("[bufnr('%'),coc#util#cursor(),win_getid()]"),s=b.getDocument(t);if(!s||!s.attached)throw new Error(`current buffer ${t} not attached`);return{doc:s,position:ke.Position.create(i,n),winid:o}}dispose(){this.requestTimer&&(clearTimeout(this.requestTimer),this.requestTimer=void 0),this.refactor.dispose(),this.signature.dispose(),this.symbols.dispose(),this.hoverFactory.dispose(),this.colors.dispose(),this.format.dispose(),this.documentHighlighter.dispose(),z(this.disposables)}},xJ=MP;var tc=U()("plugin"),qP=class extends DJ.EventEmitter{constructor(e){super();this.nvim=e;this._ready=!1;this.actions=new Map;Object.defineProperty(b,"nvim",{get:()=>this.nvim}),this.cursors=new R9(e),this.addAction("hasProvider",t=>this.handler.hasProvider(t)),this.addAction("getTagList",async()=>await this.handler.getTagList()),this.addAction("hasSelected",()=>ps.hasSelected()),this.addAction("listNames",()=>Kt.names),this.addAction("listDescriptions",()=>Kt.descriptions),this.addAction("listLoadItems",async t=>await Kt.loadItems(t)),this.addAction("search",(...t)=>this.handler.search(t)),this.addAction("cursorsSelect",(t,i,n)=>this.cursors.select(t,i,n)),this.addAction("fillDiagnostics",t=>mt.setLocationlist(t)),this.addAction("getConfig",async t=>{let i=await b.document;return b.getConfiguration(t,i?i.uri:void 0)}),this.addAction("rootPatterns",t=>{let i=b.getDocument(t);return i?{buffer:b.getRootPatterns(i,Jr.Buffer),server:b.getRootPatterns(i,Jr.LanguageServer),global:b.getRootPatterns(i,Jr.Global)}:null}),this.addAction("installExtensions",async(...t)=>{await ge.installExtensions(t)}),this.addAction("saveRefactor",async t=>{await this.handler.saveRefactor(t)}),this.addAction("updateExtensions",async t=>{await ge.updateExtensions(t)}),this.addAction("commandList",()=>me.commandList.map(t=>t.id)),this.addAction("openList",async(...t)=>{await this.ready,await Kt.start(t)}),this.addAction("selectSymbolRange",(t,i,n)=>this.handler.selectSymbolRange(t,i,n)),this.addAction("listResume",t=>Kt.resume(t)),this.addAction("listCancel",()=>Kt.cancel(!0)),this.addAction("listPrev",t=>Kt.previous(t)),this.addAction("listNext",t=>Kt.next(t)),this.addAction("listFirst",t=>Kt.first(t)),this.addAction("listLast",t=>Kt.last(t)),this.addAction("sendRequest",(t,i,n)=>Vt.sendRequest(t,i,n)),this.addAction("sendNotification",(t,i,n)=>Vt.sendNotification(t,i,n)),this.addAction("registNotification",(t,i)=>Vt.registNotification(t,i)),this.addAction("doAutocmd",async(t,...i)=>{let n=b.autocmds.get(t);if(n)try{await Promise.resolve(n.callback.apply(n.thisArg,i))}catch(o){tc.error(`Error on autocmd ${n.event}`,o),C.showMessage(`Error on autocmd ${n.event}: ${o.message}`)}}),this.addAction("updateConfig",(t,i)=>{b.configurations.updateUserConfig({[t]:i})}),this.addAction("snippetNext",async()=>(await At.nextPlaceholder(),"")),this.addAction("snippetPrev",async()=>(await At.previousPlaceholder(),"")),this.addAction("snippetCancel",()=>{At.cancel()}),this.addAction("openLocalConfig",async()=>{await C.openLocalConfig()}),this.addAction("openLog",async()=>{let t=tc.getLogFile();await b.jumpTo($.file(t).toString())}),this.addAction("attach",()=>b.attach()),this.addAction("detach",()=>b.detach()),this.addAction("doKeymap",async(t,i="",n)=>{let o=b.keymaps.get(t);if(!o)return tc.error(`keymap for ${t} not found`),this.nvim.command(`silent! unmap ${n.startsWith("{")&&n.endsWith("}")?`<${n.slice(1,-1)}>`:n}`,!0),i;let[s,a]=o,l=await Promise.resolve(s());return a&&await e.command(`silent! call repeat#set("\\(coc-${t})", -1)`),l!=null?l:i}),this.addAction("registExtensions",async(...t)=>{for(let i of t)await ge.loadExtension(i)}),this.addAction("snippetCheck",async(t,i)=>{if(t&&!ge.has("coc-snippets"))return console.error("coc-snippets required for check expand status!"),!1;if(i&&At.jumpable())return!0;if(t){let n=ge.getExtensionApi("coc-snippets");if(n&&n.hasOwnProperty("expandable")&&await Promise.resolve(n.expandable()))return!0}return!1}),this.addAction("showInfo",async()=>{this.infoChannel?this.infoChannel.clear():this.infoChannel=C.createOutputChannel("info");let t=this.infoChannel;t.appendLine("## versions"),t.appendLine("");let n=(await this.nvim.call("execute",["version"])).trim().split(/\r?\n/,2)[0].replace(/\(.*\)/,"").trim();t.appendLine("vim version: "+n+`${b.isVim?" "+b.env.version:""}`),t.appendLine("node version: "+process.version),t.appendLine("coc.nvim version: "+this.version),t.appendLine("coc.nvim directory: "+SJ.default.dirname(__dirname)),t.appendLine("term: "+(process.env.TERM_PROGRAM||process.env.TERM)),t.appendLine("platform: "+process.platform),t.appendLine(""),t.appendLine("## Log of coc.nvim"),t.appendLine("");let o=tc.getLogFile();if(NP.default.existsSync(o)){let s=NP.default.readFileSync(o,{encoding:"utf8"});t.appendLine(s)}t.show()}),this.addAction("findLocations",(t,i,n,o)=>this.handler.findLocations(t,i,n,o)),this.addAction("links",()=>this.handler.links()),this.addAction("openLink",()=>this.handler.openLink()),this.addAction("pickColor",()=>this.handler.pickColor()),this.addAction("colorPresentation",()=>this.handler.pickPresentation()),this.addAction("highlight",async()=>{await this.handler.highlight()}),this.addAction("fold",t=>this.handler.fold(t)),this.addAction("startCompletion",async t=>{await ps.startCompletion(t)}),this.addAction("stopCompletion",()=>{ps.stop(!1)}),this.addAction("sourceStat",()=>Ge.sourceStats()),this.addAction("refreshSource",async t=>{await Ge.refresh(t)}),this.addAction("toggleSource",t=>{Ge.toggleSource(t)}),this.addAction("diagnosticInfo",async()=>{await mt.echoMessage()}),this.addAction("diagnosticToggle",()=>{mt.toggleDiagnostic()}),this.addAction("diagnosticToggleBuffer",async t=>{t||(t=await e.call("bufnr",["%"])),mt.toggleDiagnosticBuffer(t)}),this.addAction("diagnosticNext",async t=>{await mt.jumpNext(t)}),this.addAction("diagnosticPrevious",async t=>{await mt.jumpPrevious(t)}),this.addAction("diagnosticPreview",async()=>{await mt.preview()}),this.addAction("diagnosticList",()=>mt.getDiagnosticList()),this.addAction("jumpDefinition",t=>this.handler.gotoDefinition(t)),this.addAction("definitions",()=>this.handler.definitions()),this.addAction("jumpDeclaration",t=>this.handler.gotoDeclaration(t)),this.addAction("declarations",()=>this.handler.declarations()),this.addAction("jumpImplementation",t=>this.handler.gotoImplementation(t)),this.addAction("implementations",()=>this.handler.implementations()),this.addAction("jumpTypeDefinition",t=>this.handler.gotoTypeDefinition(t)),this.addAction("typeDefinitions",()=>this.handler.typeDefinitions()),this.addAction("jumpReferences",t=>this.handler.gotoReferences(t)),this.addAction("references",()=>this.handler.references()),this.addAction("jumpUsed",t=>this.handler.gotoReferences(t,!1)),this.addAction("doHover",t=>this.handler.onHover(t)),this.addAction("getHover",()=>this.handler.getHover()),this.addAction("showSignatureHelp",()=>this.handler.showSignatureHelp()),this.addAction("documentSymbols",async t=>(t||(t=await e.call("bufnr",["%"])),await this.handler.getDocumentSymbols(t))),this.addAction("ensureDocument",async()=>{let t=await b.document;return t&&t.attached}),this.addAction("symbolRanges",()=>this.handler.getSymbolsRanges()),this.addAction("selectionRanges",()=>this.handler.getSelectionRanges()),this.addAction("rangeSelect",(t,i)=>this.handler.selectRange(t,i)),this.addAction("rename",t=>this.handler.rename(t)),this.addAction("getWorkspaceSymbols",async t=>{let i=new Ed.CancellationTokenSource;return await B.getWorkspaceSymbols(t,i.token)}),this.addAction("formatSelected",t=>this.handler.documentRangeFormatting(t)),this.addAction("format",()=>this.handler.documentFormatting()),this.addAction("commands",()=>this.handler.getCommands()),this.addAction("services",()=>Vt.getServiceStats()),this.addAction("toggleService",t=>Vt.toggle(t)),this.addAction("codeAction",(t,i)=>this.handler.doCodeAction(t,i)),this.addAction("organizeImport",()=>this.handler.organizeImport()),this.addAction("fixAll",()=>this.handler.doCodeAction(null,[Ed.CodeActionKind.SourceFixAll])),this.addAction("doCodeAction",t=>this.handler.applyCodeAction(t)),this.addAction("codeActions",(t,i)=>this.handler.getCurrentCodeActions(t,i)),this.addAction("quickfixes",t=>this.handler.getCurrentCodeActions(t,[Ed.CodeActionKind.QuickFix])),this.addAction("codeLensAction",()=>this.handler.doCodeLensAction()),this.addAction("runCommand",(...t)=>this.handler.runCommand(...t)),this.addAction("doQuickfix",()=>this.handler.doQuickfix()),this.addAction("refactor",()=>this.handler.doRefactor()),this.addAction("repeatCommand",()=>me.repeatCommand()),this.addAction("extensionStats",()=>ge.getExtensionStates()),this.addAction("loadedExtensions",()=>ge.loadedExtensions()),this.addAction("watchExtension",t=>ge.watchExtension(t)),this.addAction("activeExtension",t=>ge.activate(t)),this.addAction("deactivateExtension",t=>ge.deactivate(t)),this.addAction("reloadExtension",t=>ge.reloadExtension(t)),this.addAction("toggleExtension",t=>ge.toggleExtension(t)),this.addAction("uninstallExtension",(...t)=>ge.uninstallExtension(t)),this.addAction("getCurrentFunctionSymbol",()=>this.handler.getCurrentFunctionSymbol()),this.addAction("getWordEdit",()=>this.handler.getWordEdit()),this.addAction("addRanges",async t=>{await this.cursors.addRanges(t)}),this.addAction("currentWorkspacePath",()=>b.rootPath),this.addAction("addCommand",t=>{this.addCommand(t)}),this.addAction("selectCurrentPlaceholder",t=>At.selectCurrentPlaceholder(!!t)),this.addAction("codeActionRange",(t,i,n)=>this.handler.codeActionRange(t,i,n)),b.onDidChangeWorkspaceFolders(()=>{e.setVar("WorkspaceFolders",b.folderPaths,!0)}),me.init(e,this)}addAction(e,t){if(this.actions.has(e))throw new Error(`Action ${e} already exists`);this.actions.set(e,t)}addCommand(e){let t=`vim.${e.id}`;me.registerCommand(t,async()=>{await this.nvim.command(e.cmd)}),e.title&&me.titles.set(t,e.title)}async init(){let{nvim:e}=this,t=Date.now();try{await ge.init(),await b.init(),B.init();for(let i of b.env.vimCommands)this.addCommand(i);At.init(),ps.init(),mt.init(),Kt.init(e),e.setVar("coc_workspace_initialized",1,!0),e.setVar("WorkspaceFolders",b.folderPaths,!0),Ge.init(),this.handler=new xJ(e),Vt.init(),await ge.activateExtensions(),b.setupDynamicAutocmd(!0),e.setVar("coc_service_initialized",1,!0),e.call("coc#util#do_autocmd",["CocNvimInit"],!0),this._ready=!0,await A.fire("ready",[]),tc.info(`coc.nvim ${this.version} initialized with node: ${process.version} after ${Date.now()-t}ms`),this.emit("ready")}catch(i){console.error(`Error on initialize: ${i.stack}`),tc.error(i.stack)}b.onDidOpenTextDocument(async i=>{!i.uri.endsWith(Gi)||ge.has("coc-json")||C.showMessage("Run :CocInstall coc-json for json intellisense","more")})}get isReady(){return this._ready}get ready(){return this._ready?Promise.resolve():new Promise(e=>{this.once("ready",()=>{e()})})}get version(){return b.version+"-4cd2b40390"}hasAction(e){return this.actions.has(e)}async cocAction(e,...t){let i=this.actions.get(e);if(!i)throw new Error(`Action "${e}" not exists`);return await Promise.resolve(i.apply(null,t))}getHandler(){return this.handler}dispose(){this.removeAllListeners(),ge.dispose(),Kt.dispose(),b.dispose(),C.dispose(),Ge.dispose(),Vt.stopAll(),Vt.dispose(),this.handler&&this.handler.dispose(),At.dispose(),me.dispose(),ps.dispose(),mt.dispose()}},EJ=qP;var pSe=TJ().default;pSe({reader:process.stdin,writer:process.stdout});process.on("uncaughtException",function(r){let e="Uncaught exception: "+r.message;console.error(e),$P.error("uncaughtException",r.stack)});process.on("unhandledRejection",function(r,e){r instanceof Error?console.error("UnhandledRejection: "+r.message+` -`+r.stack):console.error("UnhandledRejection: "+r),$P.error("unhandledRejection ",e,r)}); +`; + for (const info of diagnostic.relatedInformation) { + const basename = import_path17.default.basename(URI.parse(info.location.uri).fsPath); + const ln = info.location.range.start.line; + message = `${message} +${basename}(line ${ln + 1}): ${info.message}`; + const diags = entries.get(info.location.uri) || []; + diags.push(import_vscode_languageserver_protocol49.Diagnostic.create(info.location.range, info.message, import_vscode_languageserver_protocol49.DiagnosticSeverity.Hint, diagnostic.code, diagnostic.source)); + entries.set(info.location.uri, diags); + } + diagnostic.message = message; + } + this._diagnostics.set(Array.from(entries)); + } + } else { + this._diagnostics.set(uri, diagnostics); + } + } + createConnection() { + let errorHandler = (error, message, count) => { + logger47.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, this._clientOptions.connectionOptions); + }); + } + handleConnectionClosed() { + if (this.state === 5) { + return; + } + try { + if (this._resolvedConnection) { + this._resolvedConnection.dispose(); + } + } catch (error) { + } + let action = 1; + if (this.state !== 4) { + try { + action = this._clientOptions.errorHandler.closed(); + } catch (error) { + } + } + this._connectionPromise = void 0; + this._resolvedConnection = void 0; + if (action === 1) { + this.error("Connection to server got closed. Server will not be restarted."); + if (this.state === 1) { + this._onReadyCallbacks.reject(new Error(`Connection to server got closed. Server will not be restarted.`)); + this.state = 2; + } else { + this.state = 5; + } + this.cleanUp(false, true); + } else if (action === 2) { + this.info("Connection to server got closed. Server will restart."); + this.cleanUp(false, true); + this.state = 0; + this.start(); + } + } + restart() { + this.cleanUp(true, false); + this.start(); + } + handleConnectionError(error, message, count) { + let action = this._clientOptions.errorHandler.error(error, message, count); + if (action === 2) { + this.error("Connection to server is erroring. Shutting down server."); + this.stop(); + } + } + hookConfigurationChanged(connection) { + workspace_default.onDidChangeConfiguration(() => { + this.refreshTrace(connection, true); + }); + } + refreshTrace(connection, sendNotification = false) { + let config = workspace_default.getConfiguration(this._id); + let trace = import_vscode_languageserver_protocol49.Trace.Off; + let traceFormat = import_vscode_languageserver_protocol49.TraceFormat.Text; + if (config) { + const traceConfig = config.get("trace.server", "off"); + if (typeof traceConfig === "string") { + trace = import_vscode_languageserver_protocol49.Trace.fromString(traceConfig); + } else { + trace = import_vscode_languageserver_protocol49.Trace.fromString(config.get("trace.server.verbosity", "off")); + traceFormat = import_vscode_languageserver_protocol49.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(import_vscode_languageserver_protocol49.DidChangeWatchedFilesNotification.type.method).registerRaw(generateUuid(), watchers); + } + registerFeatures(features) { + for (let feature of features) { + this.registerFeature(feature); + } + } + registerFeature(feature) { + this._features.push(feature); + if (DynamicFeature.is(feature)) { + const registrationType = feature.registrationType; + this._dynamicFeatures.set(registrationType.method, feature); + } + } + getFeature(request2) { + return this._dynamicFeatures.get(request2); + } + 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 (func(feature.fillInitializeParams)) { + feature.fillInitializeParams(params); + } + } + } + computeClientCapabilities() { + const result = {}; + ensure(result, "workspace").applyEdit = true; + const workspaceEdit = ensure(ensure(result, "workspace"), "workspaceEdit"); + workspaceEdit.documentChanges = true; + workspaceEdit.resourceOperations = [import_vscode_languageserver_protocol49.ResourceOperationKind.Create, import_vscode_languageserver_protocol49.ResourceOperationKind.Rename, import_vscode_languageserver_protocol49.ResourceOperationKind.Delete]; + workspaceEdit.failureHandling = import_vscode_languageserver_protocol49.FailureHandlingKind.TextOnlyTransactional; + const diagnostics = ensure(ensure(result, "textDocument"), "publishDiagnostics"); + diagnostics.relatedInformation = true; + diagnostics.versionSupport = false; + diagnostics.tagSupport = { valueSet: [import_vscode_languageserver_protocol49.DiagnosticTag.Unnecessary, import_vscode_languageserver_protocol49.DiagnosticTag.Deprecated] }; + const windowCapabilities = ensure(result, "window"); + const showMessage = ensure(windowCapabilities, "showMessage"); + showMessage.messageActionItem = { additionalPropertiesSupport: false }; + const showDocument = ensure(windowCapabilities, "showDocument"); + showDocument.support = false; + const generalCapabilities = ensure(result, "general"); + generalCapabilities.regularExpressions = { engine: "ECMAScript", version: "ES2020" }; + generalCapabilities.markdown = { parser: "marked", version: "1.1.0" }; + 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((resolve3, reject) => { + for (const 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 + }; + try { + feature.register(data); + } catch (err) { + reject(err); + return; + } + } + resolve3(); + }); + } + handleUnregistrationRequest(params) { + return new Promise((resolve3, 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); + } + resolve3(); + }); + } + handleApplyWorkspaceEdit(params) { + let workspaceEdit = params.edit; + let openTextDocuments = new Map(); + workspace_default.textDocuments.forEach((document2) => openTextDocuments.set(document2.uri.toString(), document2)); + let versionMismatch = false; + if (workspaceEdit.documentChanges) { + for (const change of workspaceEdit.documentChanges) { + if (import_vscode_languageserver_protocol49.TextDocumentEdit.is(change) && change.textDocument.version && change.textDocument.version >= 0) { + let textDocument = openTextDocuments.get(change.textDocument.uri); + if (textDocument && textDocument.version !== change.textDocument.version) { + versionMismatch = true; + break; + } + } + } + } + if (versionMismatch) { + return Promise.resolve({ applied: false }); + } + return workspace_default.applyEdit(params.edit).then((value) => { + return { applied: value }; + }); + } + getLocale() { + const lang = process.env.LANG; + if (!lang) + return "en"; + return lang.split(".")[0]; + } + handleFailedRequest(type, token, error, defaultValue) { + if (error instanceof import_vscode_languageserver_protocol49.ResponseError) { + if (error.code === import_vscode_languageserver_protocol49.LSPErrorCodes.RequestCancelled) { + if (token !== void 0 && token.isCancellationRequested) { + return defaultValue; + } + } else if (error.code === import_vscode_languageserver_protocol49.LSPErrorCodes.ContentModified) { + return defaultValue; + } + } + this.error(`Request ${type.method} failed.`, error); + } + logFailedRequest(type, error) { + if (error instanceof import_vscode_languageserver_protocol49.ResponseError && error.code === import_vscode_languageserver_protocol49.LSPErrorCodes.RequestCancelled) { + return; + } + this.error(`Request ${type.method} failed.`, error); + } + }; + } +}); + +// src/language-client/colorProvider.ts +function ensure2(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol50, ColorProviderFeature; +var init_colorProvider = __esm({ + "src/language-client/colorProvider.ts"() { + import_vscode_languageserver_protocol50 = __toModule(require_main2()); + init_languages(); + init_client(); + "use strict"; + ColorProviderFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol50.DocumentColorRequest.type); + } + fillClientCapabilities(capabilities) { + ensure2(ensure2(capabilities, "textDocument"), "colorProvider").dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + let [id, options] = this.getRegistration(documentSelector, capabilities.colorProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const provider = { + provideColorPresentations: (color, context, token) => { + const client = this._client; + const provideColorPresentations = (color2, context2, token2) => { + const requestParams = { + color: color2, + textDocument: { uri: context2.document.uri }, + range: context2.range + }; + return client.sendRequest(import_vscode_languageserver_protocol50.ColorPresentationRequest.type, requestParams, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol50.ColorPresentationRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideColorPresentations ? middleware.provideColorPresentations(color, context, token, provideColorPresentations) : provideColorPresentations(color, context, token); + }, + provideDocumentColors: (document2, token) => { + const client = this._client; + const provideDocumentColors = (document3, token2) => { + const requestParams = { + textDocument: { uri: document3.uri } + }; + return client.sendRequest(import_vscode_languageserver_protocol50.DocumentColorRequest.type, requestParams, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol50.ColorPresentationRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideDocumentColors ? middleware.provideDocumentColors(document2, token, provideDocumentColors) : provideDocumentColors(document2, token); + } + }; + return [languages_default.registerDocumentColorProvider(options.documentSelector, provider), provider]; + } + }; + } +}); + +// src/language-client/configuration.ts +function toJSONObject(obj) { + if (obj) { + if (Array.isArray(obj)) { + return obj.map(toJSONObject); + } else if (typeof obj === "object") { + const res = Object.create(null); + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + res[key] = toJSONObject(obj[key]); + } + } + return res; + } + } + return obj; +} +var import_vscode_languageserver_protocol51, logger48, ConfigurationFeature2; +var init_configuration3 = __esm({ + "src/language-client/configuration.ts"() { + import_vscode_languageserver_protocol51 = __toModule(require_main2()); + init_workspace(); + logger48 = require_logger2()("languageclient-configuration"); + ConfigurationFeature2 = class { + constructor(_client) { + this._client = _client; + var _a2; + let section2 = (_a2 = this._client.clientOptions.synchronize) == null ? void 0 : _a2.configurationSection; + if (typeof section2 === "string" && section2.startsWith("languageserver.")) { + this.languageserverSection = section2; + } + } + fillClientCapabilities(capabilities) { + capabilities.workspace = capabilities.workspace || {}; + capabilities.workspace.configuration = true; + } + initialize() { + let client = this._client; + client.onRequest(import_vscode_languageserver_protocol51.ConfigurationRequest.type, (params, token) => { + let configuration = (params2) => { + let result = []; + for (let item of params2.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, section2) { + let result = null; + if (section2) { + if (this.languageserverSection) { + section2 = `${this.languageserverSection}.${section2}`; + } + let index = section2.lastIndexOf("."); + if (index === -1) { + result = toJSONObject(workspace_default.getConfiguration(void 0, resource).get(section2)); + } else { + let config = workspace_default.getConfiguration(section2.substr(0, index), resource); + if (config) { + result = toJSONObject(config.get(section2.substr(index + 1))); + } + } + } else { + let config = workspace_default.getConfiguration(this.languageserverSection, resource); + result = {}; + for (let key of Object.keys(config)) { + if (config.has(key)) { + result[key] = toJSONObject(config.get(key)); + } + } + } + return result; + } + dispose() { + } + }; + } +}); + +// src/language-client/declaration.ts +function ensure3(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol52, DeclarationFeature; +var init_declaration = __esm({ + "src/language-client/declaration.ts"() { + import_vscode_languageserver_protocol52 = __toModule(require_main2()); + init_languages(); + init_client(); + init_converter(); + "use strict"; + DeclarationFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol52.DeclarationRequest.type); + } + fillClientCapabilities(capabilities) { + let declarationSupport = ensure3(ensure3(capabilities, "textDocument"), "declaration"); + declarationSupport.dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const [id, options] = this.getRegistration(documentSelector, capabilities.declarationProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const provider = { + provideDeclaration: (document2, position, token) => { + const client = this._client; + const provideDeclaration = (document3, position2, token2) => client.sendRequest(import_vscode_languageserver_protocol52.DeclarationRequest.type, asTextDocumentPositionParams(document3, position2), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol52.DeclarationRequest.type, token2, error, null); + }); + const middleware = client.clientOptions.middleware; + return middleware.provideDeclaration ? middleware.provideDeclaration(document2, position, token, provideDeclaration) : provideDeclaration(document2, position, token); + } + }; + return [languages_default.registerDeclarationProvider(options.documentSelector, provider), provider]; + } + }; + } +}); + +// src/language-client/foldingRange.ts +function ensure4(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol53, FoldingRangeFeature; +var init_foldingRange = __esm({ + "src/language-client/foldingRange.ts"() { + import_vscode_languageserver_protocol53 = __toModule(require_main2()); + init_languages(); + init_client(); + "use strict"; + FoldingRangeFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol53.FoldingRangeRequest.type); + } + fillClientCapabilities(capabilities) { + let capability = ensure4(ensure4(capabilities, "textDocument"), "foldingRange"); + capability.dynamicRegistration = true; + capability.rangeLimit = 5e3; + capability.lineFoldingOnly = true; + } + initialize(capabilities, documentSelector) { + const [id, options] = this.getRegistration(documentSelector, capabilities.foldingRangeProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const provider = { + provideFoldingRanges: (document2, context, token) => { + const client = this._client; + const provideFoldingRanges = (document3, _, token2) => { + const requestParams = { + textDocument: { uri: document3.uri } + }; + return client.sendRequest(import_vscode_languageserver_protocol53.FoldingRangeRequest.type, requestParams, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol53.FoldingRangeRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideFoldingRanges ? middleware.provideFoldingRanges(document2, context, token, provideFoldingRanges) : provideFoldingRanges(document2, context, token); + } + }; + return [languages_default.registerFoldingRangeProvider(options.documentSelector, provider), provider]; + } + }; + } +}); + +// src/language-client/implementation.ts +function ensure5(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol54, ImplementationFeature; +var init_implementation = __esm({ + "src/language-client/implementation.ts"() { + import_vscode_languageserver_protocol54 = __toModule(require_main2()); + init_languages(); + init_client(); + init_converter(); + ImplementationFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol54.ImplementationRequest.type); + } + fillClientCapabilities(capabilities) { + const implementationSupport = ensure5(ensure5(capabilities, "textDocument"), "implementation"); + implementationSupport.dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const [id, options] = this.getRegistration(documentSelector, capabilities.implementationProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const provider = { + provideImplementation: (document2, position, token) => { + const client = this._client; + const provideImplementation = (document3, position2, token2) => client.sendRequest(import_vscode_languageserver_protocol54.ImplementationRequest.type, asTextDocumentPositionParams(document3, position2), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol54.ImplementationRequest.type, token2, error, null); + }); + const middleware = client.clientOptions.middleware; + return middleware.provideImplementation ? middleware.provideImplementation(document2, position, token, provideImplementation) : provideImplementation(document2, position, token); + } + }; + return [languages_default.registerImplementationProvider(options.documentSelector, provider), provider]; + } + }; + } +}); + +// src/language-client/progress.ts +function ensure6(target, key) { + if (target[key] === void 0) { + target[key] = Object.create(null); + } + return target[key]; +} +var import_vscode_languageserver_protocol55, ProgressFeature; +var init_progress2 = __esm({ + "src/language-client/progress.ts"() { + import_vscode_languageserver_protocol55 = __toModule(require_main2()); + init_progressPart(); + "use strict"; + ProgressFeature = class { + constructor(_client) { + this._client = _client; + this.activeParts = new Set(); + } + fillClientCapabilities(capabilities) { + ensure6(capabilities, "window").workDoneProgress = true; + } + initialize() { + let client = this._client; + const deleteHandler = (part) => { + this.activeParts.delete(part); + }; + const createHandler = (params) => { + this.activeParts.add(new ProgressPart(this._client, params.token, deleteHandler)); + }; + client.onRequest(import_vscode_languageserver_protocol55.WorkDoneProgressCreateRequest.type, createHandler); + } + dispose() { + for (const part of this.activeParts) { + part.done(); + } + this.activeParts.clear(); + } + }; + } +}); + +// src/language-client/typeDefinition.ts +function ensure7(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol56, TypeDefinitionFeature; +var init_typeDefinition = __esm({ + "src/language-client/typeDefinition.ts"() { + import_vscode_languageserver_protocol56 = __toModule(require_main2()); + init_languages(); + init_client(); + init_converter(); + TypeDefinitionFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol56.TypeDefinitionRequest.type); + } + fillClientCapabilities(capabilities) { + const typeDefinitionSupport = ensure7(ensure7(capabilities, "textDocument"), "typeDefinition"); + typeDefinitionSupport.dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const [id, options] = this.getRegistration(documentSelector, capabilities.typeDefinitionProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const provider = { + provideTypeDefinition: (document2, position, token) => { + const client = this._client; + const provideTypeDefinition = (document3, position2, token2) => client.sendRequest(import_vscode_languageserver_protocol56.TypeDefinitionRequest.type, asTextDocumentPositionParams(document3, position2), token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol56.TypeDefinitionRequest.type, token2, error, null); + }); + const middleware = client.clientOptions.middleware; + return middleware.provideTypeDefinition ? middleware.provideTypeDefinition(document2, position, token, provideTypeDefinition) : provideTypeDefinition(document2, position, token); + } + }; + return [languages_default.registerTypeDefinitionProvider(options.documentSelector, provider), provider]; + } + }; + } +}); + +// src/language-client/workspaceFolders.ts +function access(target, key) { + if (target === void 0) { + return void 0; + } + return target[key]; +} +function arrayDiff(left, right) { + return left.filter((element) => !right.includes(element)); +} +var import_vscode_languageserver_protocol57, import_os8, logger49, WorkspaceFoldersFeature; +var init_workspaceFolders = __esm({ + "src/language-client/workspaceFolders.ts"() { + import_vscode_languageserver_protocol57 = __toModule(require_main2()); + init_workspace(); + import_os8 = __toModule(require("os")); + init_uuid(); + init_esm2(); + "use strict"; + logger49 = require_logger2()("language-client-workspaceFolder"); + WorkspaceFoldersFeature = class { + constructor(_client) { + this._client = _client; + this._listeners = new Map(); + } + get registrationType() { + return import_vscode_languageserver_protocol57.DidChangeWorkspaceFoldersNotification.type; + } + getValidWorkspaceFolders() { + let { workspaceFolders } = workspace_default; + if (!workspaceFolders || workspaceFolders.length == 0) + return void 0; + let home = import_os8.default.homedir(); + let { ignoredRootPaths } = this._client.clientOptions; + if (!Array.isArray(ignoredRootPaths)) { + ignoredRootPaths = []; + } + let arr = workspaceFolders.filter((o) => { + let fsPath = URI.parse(o.uri).fsPath; + return fsPath != home && !ignoredRootPaths.includes(fsPath); + }); + return arr.length ? arr : void 0; + } + asProtocol(workspaceFolder) { + if (workspaceFolder === void 0) { + return null; + } + return { uri: workspaceFolder.uri, name: workspaceFolder.name }; + } + fillInitializeParams(params) { + const folders = this.getValidWorkspaceFolders(); + this._initialFolders = folders; + if (folders == null) { + params.workspaceFolders = null; + } else { + params.workspaceFolders = folders.map((folder) => this.asProtocol(folder)); + } + } + fillClientCapabilities(capabilities) { + capabilities.workspace = capabilities.workspace || {}; + capabilities.workspace.workspaceFolders = true; + } + initialize(capabilities) { + let client = this._client; + client.onRequest(import_vscode_languageserver_protocol57.WorkspaceFoldersRequest.type, (token) => { + let workspaceFolders = () => { + let folders = this.getValidWorkspaceFolders(); + if (folders === void 0) { + return null; + } + let result = folders.map((folder) => this.asProtocol(folder)); + return result; + }; + const middleware = client.clientOptions.middleware.workspace; + return middleware && middleware.workspaceFolders ? middleware.workspaceFolders(token, workspaceFolders) : workspaceFolders(token); + }); + const value = access(access(access(capabilities, "workspace"), "workspaceFolders"), "changeNotifications"); + let id; + if (typeof value === "string") { + id = value; + } else if (value === true) { + id = generateUuid(); + } + if (id) { + this.register({ + id, + registerOptions: void 0 + }); + } + } + doSendEvent(addedFolders, removedFolders) { + let params = { + event: { + added: addedFolders.map((folder) => this.asProtocol(folder)), + removed: removedFolders.map((folder) => this.asProtocol(folder)) + } + }; + this._client.sendNotification(import_vscode_languageserver_protocol57.DidChangeWorkspaceFoldersNotification.type, params); + } + sendInitialEvent(currentWorkspaceFolders) { + if (this._initialFolders && currentWorkspaceFolders) { + const removed = arrayDiff(this._initialFolders, currentWorkspaceFolders); + const added = arrayDiff(currentWorkspaceFolders, this._initialFolders); + if (added.length > 0 || removed.length > 0) { + this.doSendEvent(added, removed); + } + } else if (this._initialFolders) { + this.doSendEvent([], this._initialFolders); + } else if (currentWorkspaceFolders) { + this.doSendEvent(currentWorkspaceFolders, []); + } + } + register(data) { + let id = data.id; + let client = this._client; + let disposable = workspace_default.onDidChangeWorkspaceFolders((event) => { + let didChangeWorkspaceFolders = (event2) => { + this.doSendEvent(event2.added, event2.removed); + }; + let middleware = client.clientOptions.middleware.workspace; + middleware && middleware.didChangeWorkspaceFolders ? middleware.didChangeWorkspaceFolders(event, didChangeWorkspaceFolders) : didChangeWorkspaceFolders(event); + }); + this._listeners.set(id, disposable); + let workspaceFolders = this.getValidWorkspaceFolders(); + this.sendInitialEvent(workspaceFolders); + } + 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(); + } + }; + } +}); + +// src/language-client/selectionRange.ts +function ensure8(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol58, SelectionRangeFeature; +var init_selectionRange = __esm({ + "src/language-client/selectionRange.ts"() { + import_vscode_languageserver_protocol58 = __toModule(require_main2()); + init_languages(); + init_client(); + "use strict"; + SelectionRangeFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol58.SelectionRangeRequest.type); + } + fillClientCapabilities(capabilities) { + let capability = ensure8(ensure8(capabilities, "textDocument"), "selectionRange"); + capability.dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + let [id, options] = this.getRegistration(documentSelector, capabilities.selectionRangeProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const provider = { + provideSelectionRanges: (document2, positions2, token) => { + const client = this._client; + const provideSelectionRanges = (document3, positions3, token2) => { + const requestParams = { + textDocument: { uri: document3.uri }, + positions: positions3 + }; + return client.sendRequest(import_vscode_languageserver_protocol58.SelectionRangeRequest.type, requestParams, token2).then((ranges) => ranges, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol58.SelectionRangeRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideSelectionRanges ? middleware.provideSelectionRanges(document2, positions2, token, provideSelectionRanges) : provideSelectionRanges(document2, positions2, token); + } + }; + return [languages_default.registerSelectionRangeProvider(options.documentSelector, provider), provider]; + } + }; + } +}); + +// src/language-client/callHierarchy.ts +function ensure9(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol59, CallHierarchyFeature; +var init_callHierarchy = __esm({ + "src/language-client/callHierarchy.ts"() { + import_vscode_languageserver_protocol59 = __toModule(require_main2()); + init_languages(); + init_client(); + init_converter(); + "use strict"; + CallHierarchyFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol59.CallHierarchyPrepareRequest.type); + } + fillClientCapabilities(cap) { + const capabilities = cap; + const capability = ensure9(ensure9(capabilities, "textDocument"), "callHierarchy"); + capability.dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + const [id, options] = this.getRegistration(documentSelector, capabilities.callHierarchyProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const provider = { + prepareCallHierarchy: (document2, position, token) => { + const client = this._client; + const prepareCallHierarchy = (document3, position2, token2) => { + const params = asTextDocumentPositionParams(document3, position2); + return client.sendRequest(import_vscode_languageserver_protocol59.CallHierarchyPrepareRequest.type, params, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol59.CallHierarchyPrepareRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.prepareCallHierarchy ? middleware.prepareCallHierarchy(document2, position, token, prepareCallHierarchy) : prepareCallHierarchy(document2, position, token); + }, + provideCallHierarchyIncomingCalls: (item, token) => { + const client = this._client; + const provideCallHierarchyIncomingCalls = (item2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol59.CallHierarchyIncomingCallsRequest.type, { item: item2 }, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol59.CallHierarchyIncomingCallsRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideCallHierarchyIncomingCalls ? middleware.provideCallHierarchyIncomingCalls(item, token, provideCallHierarchyIncomingCalls) : provideCallHierarchyIncomingCalls(item, token); + }, + provideCallHierarchyOutgoingCalls: (item, token) => { + const client = this._client; + const provideCallHierarchyOutgoingCalls = (item2, token2) => { + return client.sendRequest(import_vscode_languageserver_protocol59.CallHierarchyOutgoingCallsRequest.type, { item: item2 }, token2).then((res) => res, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol59.CallHierarchyOutgoingCallsRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideCallHierarchyOutgoingCalls ? middleware.provideCallHierarchyOutgoingCalls(item, token, provideCallHierarchyOutgoingCalls) : provideCallHierarchyOutgoingCalls(item, token); + } + }; + return [languages_default.registerCallHierarchyProvider(options.documentSelector, provider), provider]; + } + }; + } +}); + +// src/language-client/semanticTokens.ts +function ensure10(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol60, logger50, SemanticTokensFeature; +var init_semanticTokens = __esm({ + "src/language-client/semanticTokens.ts"() { + import_vscode_languageserver_protocol60 = __toModule(require_main2()); + init_languages(); + init_converter(); + init_is(); + init_client(); + "use strict"; + logger50 = require_logger2()("languageclient-semanticTokens"); + SemanticTokensFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol60.SemanticTokensRegistrationType.type); + } + fillClientCapabilities(capabilities) { + const capability = ensure10(ensure10(capabilities, "textDocument"), "semanticTokens"); + capability.dynamicRegistration = true; + capability.tokenTypes = [ + import_vscode_languageserver_protocol60.SemanticTokenTypes.namespace, + import_vscode_languageserver_protocol60.SemanticTokenTypes.type, + import_vscode_languageserver_protocol60.SemanticTokenTypes.class, + import_vscode_languageserver_protocol60.SemanticTokenTypes.enum, + import_vscode_languageserver_protocol60.SemanticTokenTypes.interface, + import_vscode_languageserver_protocol60.SemanticTokenTypes.struct, + import_vscode_languageserver_protocol60.SemanticTokenTypes.typeParameter, + import_vscode_languageserver_protocol60.SemanticTokenTypes.parameter, + import_vscode_languageserver_protocol60.SemanticTokenTypes.variable, + import_vscode_languageserver_protocol60.SemanticTokenTypes.property, + import_vscode_languageserver_protocol60.SemanticTokenTypes.enumMember, + import_vscode_languageserver_protocol60.SemanticTokenTypes.event, + import_vscode_languageserver_protocol60.SemanticTokenTypes.function, + import_vscode_languageserver_protocol60.SemanticTokenTypes.method, + import_vscode_languageserver_protocol60.SemanticTokenTypes.macro, + import_vscode_languageserver_protocol60.SemanticTokenTypes.keyword, + import_vscode_languageserver_protocol60.SemanticTokenTypes.modifier, + import_vscode_languageserver_protocol60.SemanticTokenTypes.comment, + import_vscode_languageserver_protocol60.SemanticTokenTypes.string, + import_vscode_languageserver_protocol60.SemanticTokenTypes.number, + import_vscode_languageserver_protocol60.SemanticTokenTypes.regexp, + import_vscode_languageserver_protocol60.SemanticTokenTypes.operator + ]; + capability.tokenModifiers = [ + import_vscode_languageserver_protocol60.SemanticTokenModifiers.declaration, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.definition, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.readonly, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.static, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.deprecated, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.abstract, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.async, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.modification, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.documentation, + import_vscode_languageserver_protocol60.SemanticTokenModifiers.defaultLibrary + ]; + capability.formats = [import_vscode_languageserver_protocol60.TokenFormat.Relative]; + capability.requests = { + range: true, + full: { + delta: true + } + }; + capability.multilineTokenSupport = false; + capability.overlappingTokenSupport = false; + ensure10(ensure10(capabilities, "workspace"), "semanticTokens").refreshSupport = true; + } + initialize(capabilities, documentSelector) { + const client = this._client; + client.onRequest(import_vscode_languageserver_protocol60.SemanticTokensRefreshRequest.type, async () => { + for (const provider of this.getAllProviders()) { + provider.onDidChangeSemanticTokensEmitter.fire(); + } + }); + const [id, options] = this.getRegistration(documentSelector, capabilities.semanticTokensProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const fullProvider = boolean(options.full) ? options.full : options.full !== void 0; + const hasEditProvider = options.full !== void 0 && typeof options.full !== "boolean" && options.full.delta === true; + const eventEmitter = new import_vscode_languageserver_protocol60.Emitter(); + const documentProvider = fullProvider ? { + onDidChangeSemanticTokens: eventEmitter.event, + provideDocumentSemanticTokens: (document2, token) => { + const client = this._client; + const middleware = client.clientOptions.middleware; + const provideDocumentSemanticTokens = (document3, token2) => { + const params = { + textDocument: asTextDocumentIdentifier(document3) + }; + return client.sendRequest(import_vscode_languageserver_protocol60.SemanticTokensRequest.type, params, token2).then((result) => result, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol60.SemanticTokensRequest.type, token2, error, null); + }); + }; + return middleware.provideDocumentSemanticTokens ? middleware.provideDocumentSemanticTokens(document2, token, provideDocumentSemanticTokens) : provideDocumentSemanticTokens(document2, token); + }, + provideDocumentSemanticTokensEdits: hasEditProvider ? (document2, previousResultId, token) => { + const client = this._client; + const middleware = client.clientOptions.middleware; + const provideDocumentSemanticTokensEdits = (document3, previousResultId2, token2) => { + const params = { + textDocument: asTextDocumentIdentifier(document3), + previousResultId: previousResultId2 + }; + return client.sendRequest(import_vscode_languageserver_protocol60.SemanticTokensDeltaRequest.type, params, token2).then((result) => result, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol60.SemanticTokensDeltaRequest.type, token2, error, null); + }); + }; + return middleware.provideDocumentSemanticTokensEdits ? middleware.provideDocumentSemanticTokensEdits(document2, previousResultId, token, provideDocumentSemanticTokensEdits) : provideDocumentSemanticTokensEdits(document2, previousResultId, token); + } : void 0 + } : void 0; + const hasRangeProvider = options.range === true; + const rangeProvider = hasRangeProvider ? { + provideDocumentRangeSemanticTokens: (document2, range, token) => { + const client = this._client; + const middleware = client.clientOptions.middleware; + const provideDocumentRangeSemanticTokens = (document3, range2, token2) => { + const params = { + textDocument: asTextDocumentIdentifier(document3), + range: range2 + }; + return client.sendRequest(import_vscode_languageserver_protocol60.SemanticTokensRangeRequest.type, params, token2).then((result) => result, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol60.SemanticTokensRangeRequest.type, token2, error, null); + }); + }; + return middleware.provideDocumentRangeSemanticTokens ? middleware.provideDocumentRangeSemanticTokens(document2, range, token, provideDocumentRangeSemanticTokens) : provideDocumentRangeSemanticTokens(document2, range, token); + } + } : void 0; + const disposables = []; + if (documentProvider !== void 0) { + disposables.push(languages_default.registerDocumentSemanticTokensProvider(options.documentSelector, documentProvider, options.legend)); + } + if (rangeProvider !== void 0) { + disposables.push(languages_default.registerDocumentRangeSemanticTokensProvider(options.documentSelector, rangeProvider, options.legend)); + } + return [import_vscode_languageserver_protocol60.Disposable.create(() => disposables.forEach((item) => item.dispose())), { range: rangeProvider, full: documentProvider, onDidChangeSemanticTokensEmitter: eventEmitter }]; + } + }; + } +}); + +// src/language-client/linkedEditingRange.ts +function ensure11(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +var import_vscode_languageserver_protocol61, logger51, LinkedEditingFeature; +var init_linkedEditingRange = __esm({ + "src/language-client/linkedEditingRange.ts"() { + import_vscode_languageserver_protocol61 = __toModule(require_main2()); + init_languages(); + init_client(); + init_converter(); + logger51 = require_logger2()("languageclient-linkedEditingRange"); + LinkedEditingFeature = class extends TextDocumentFeature { + constructor(client) { + super(client, import_vscode_languageserver_protocol61.LinkedEditingRangeRequest.type); + } + fillClientCapabilities(capabilities) { + const linkedEditingSupport = ensure11(ensure11(capabilities, "textDocument"), "linkedEditingRange"); + linkedEditingSupport.dynamicRegistration = true; + } + initialize(capabilities, documentSelector) { + let [id, options] = this.getRegistration(documentSelector, capabilities.linkedEditingRangeProvider); + if (!id || !options) { + return; + } + this.register({ id, registerOptions: options }); + } + registerLanguageProvider(options) { + const provider = { + provideLinkedEditingRanges: (document2, position, token) => { + const client = this._client; + const provideLinkedEditing = (document3, position2, token2) => { + const params = asTextDocumentPositionParams(document3, position2); + return client.sendRequest(import_vscode_languageserver_protocol61.LinkedEditingRangeRequest.type, params, token2).then((result) => result, (error) => { + return client.handleFailedRequest(import_vscode_languageserver_protocol61.LinkedEditingRangeRequest.type, token2, error, null); + }); + }; + const middleware = client.clientOptions.middleware; + return middleware.provideLinkedEditingRange ? middleware.provideLinkedEditingRange(document2, position, token, provideLinkedEditing) : provideLinkedEditing(document2, position, token); + } + }; + return [languages_default.registerLinkedEditingRangeProvider(options.documentSelector, provider), provider]; + } + }; + } +}); + +// src/language-client/fileOperations.ts +function ensure12(target, key) { + if (target[key] === void 0) { + target[key] = {}; + } + return target[key]; +} +function access2(target, key) { + return target[key]; +} +function assign(target, key, value) { + target[key] = value; +} +function asCreateDeleteFilesParams(e) { + return { + files: e.files.map((f) => ({ uri: f.toString() })) + }; +} +function asRenameFilesParams(e) { + return { + files: e.files.map((f) => ({ oldUri: f.oldUri.toString(), newUri: f.newUri.toString() })) + }; +} +var minimatch5, import_vscode_languageserver_protocol62, logger52, FileOperationFeature, NotificationFileOperationFeature, DidCreateFilesFeature, DidRenameFilesFeature, DidDeleteFilesFeature, RequestFileOperationFeature, WillCreateFilesFeature, WillRenameFilesFeature, WillDeleteFilesFeature; +var init_fileOperations = __esm({ + "src/language-client/fileOperations.ts"() { + minimatch5 = __toModule(require_minimatch()); + import_vscode_languageserver_protocol62 = __toModule(require_main2()); + init_types(); + init_fs(); + init_workspace(); + init_uuid(); + logger52 = require_logger2()("language-client-fileOperations"); + FileOperationFeature = class { + constructor(client, event, registrationType, clientCapability, serverCapability) { + this._filters = new Map(); + this._client = client; + this._event = event; + this._registrationType = registrationType; + this._clientCapability = clientCapability; + this._serverCapability = serverCapability; + } + get registrationType() { + return this._registrationType; + } + fillClientCapabilities(capabilities) { + const value = ensure12(ensure12(capabilities, "workspace"), "fileOperations"); + assign(value, "dynamicRegistration", true); + assign(value, this._clientCapability, true); + } + initialize(capabilities) { + var _a2; + const options = (_a2 = capabilities.workspace) == null ? void 0 : _a2.fileOperations; + const capability = options !== void 0 ? access2(options, this._serverCapability) : void 0; + if ((capability == null ? void 0 : capability.filters) !== void 0) { + try { + this.register({ + id: generateUuid(), + registerOptions: { filters: capability.filters } + }); + } catch (e) { + this._client.warn(`Ignoring invalid glob pattern for ${this._serverCapability} registration: ${e}`); + } + } + } + register(data) { + if (!this._listener) { + this._listener = this._event(this.send, this); + } + const minimatchFilter = data.registerOptions.filters.map((filter) => { + const matcher = new minimatch5.Minimatch(filter.pattern.glob, FileOperationFeature.asMinimatchOptions(filter.pattern.options)); + if (!matcher.makeRe()) { + throw new Error(`Invalid pattern ${filter.pattern.glob}!`); + } + return { scheme: filter.scheme, matcher, kind: filter.pattern.matches }; + }); + this._filters.set(data.id, minimatchFilter); + } + unregister(id) { + this._filters.delete(id); + if (this._filters.size === 0 && this._listener) { + this._listener.dispose(); + this._listener = void 0; + } + } + dispose() { + this._filters.clear(); + if (this._listener) { + this._listener.dispose(); + this._listener = void 0; + } + } + async filter(event, prop) { + const fileMatches = await Promise.all(event.files.map(async (item) => { + const uri = prop(item); + const path36 = uri.fsPath.replace(/\\/g, "/"); + for (const filters of this._filters.values()) { + for (const filter of filters) { + if (filter.scheme !== void 0 && filter.scheme !== uri.scheme) { + continue; + } + if (filter.matcher.match(path36)) { + if (filter.kind === void 0) { + return true; + } + const fileType = await FileOperationFeature.getFileType(uri); + if (fileType === void 0) { + this._client.error(`Failed to determine file type for ${uri.toString()}.`); + return true; + } + if (fileType === FileType.File && filter.kind === import_vscode_languageserver_protocol62.FileOperationPatternKind.file || fileType === FileType.Directory && filter.kind === import_vscode_languageserver_protocol62.FileOperationPatternKind.folder) { + return true; + } + } else if (filter.kind === import_vscode_languageserver_protocol62.FileOperationPatternKind.folder) { + const fileType = await FileOperationFeature.getFileType(uri); + if (fileType === FileType.Directory && filter.matcher.match(`${path36}/`)) { + return true; + } + } + } + } + return false; + })); + const files = event.files.filter((_, index) => fileMatches[index]); + return __spreadProps(__spreadValues({}, event), { files }); + } + static async getFileType(uri) { + try { + const stat = await statAsync(uri.fsPath); + if (stat.isFile()) { + return FileType.File; + } + if (stat.isDirectory()) { + return FileType.Directory; + } + if (stat.isSymbolicLink()) { + return FileType.SymbolicLink; + } + return FileType.Unknown; + } catch (e) { + return void 0; + } + } + static asMinimatchOptions(options) { + if (options === void 0) { + return void 0; + } + if (options.ignoreCase === true) { + return { nocase: true }; + } + return void 0; + } + }; + NotificationFileOperationFeature = class extends FileOperationFeature { + constructor(client, event, notificationType, clientCapability, serverCapability, accessUri, createParams) { + super(client, event, notificationType, clientCapability, serverCapability); + this._notificationType = notificationType; + this._accessUri = accessUri; + this._createParams = createParams; + } + async send(originalEvent) { + const filteredEvent = await this.filter(originalEvent, this._accessUri); + if (filteredEvent.files.length) { + const next = async (event) => { + this._client.sendNotification(this._notificationType, this._createParams(event)); + }; + this.doSend(filteredEvent, next); + } + } + }; + DidCreateFilesFeature = class extends NotificationFileOperationFeature { + constructor(client) { + super(client, workspace_default.onDidCreateFiles, import_vscode_languageserver_protocol62.DidCreateFilesNotification.type, "didCreate", "didCreate", (i) => i, (e) => asCreateDeleteFilesParams(e)); + } + doSend(event, next) { + var _a2; + const middleware = (_a2 = this._client.clientOptions.middleware) == null ? void 0 : _a2.workspace; + return (middleware == null ? void 0 : middleware.didCreateFiles) ? middleware.didCreateFiles(event, next) : next(event); + } + }; + DidRenameFilesFeature = class extends NotificationFileOperationFeature { + constructor(client) { + super(client, workspace_default.onDidRenameFiles, import_vscode_languageserver_protocol62.DidRenameFilesNotification.type, "didRename", "didRename", (i) => i.oldUri, (e) => asRenameFilesParams(e)); + } + doSend(event, next) { + var _a2; + const middleware = (_a2 = this._client.clientOptions.middleware) == null ? void 0 : _a2.workspace; + return (middleware == null ? void 0 : middleware.didRenameFiles) ? middleware.didRenameFiles(event, next) : next(event); + } + }; + DidDeleteFilesFeature = class extends NotificationFileOperationFeature { + constructor(client) { + super(client, workspace_default.onDidDeleteFiles, import_vscode_languageserver_protocol62.DidDeleteFilesNotification.type, "didDelete", "didDelete", (i) => i, (e) => asCreateDeleteFilesParams(e)); + } + doSend(event, next) { + var _a2; + const middleware = (_a2 = this._client.clientOptions.middleware) == null ? void 0 : _a2.workspace; + return (middleware == null ? void 0 : middleware.didDeleteFiles) ? middleware.didDeleteFiles(event, next) : next(event); + } + }; + RequestFileOperationFeature = class extends FileOperationFeature { + constructor(client, event, requestType, clientCapability, serverCapability, accessUri, createParams) { + super(client, event, requestType, clientCapability, serverCapability); + this._requestType = requestType; + this._accessUri = accessUri; + this._createParams = createParams; + } + async send(originalEvent) { + const waitUntil = this.waitUntil(originalEvent); + originalEvent.waitUntil(waitUntil); + } + async waitUntil(originalEvent) { + const filteredEvent = await this.filter(originalEvent, this._accessUri); + if (filteredEvent.files.length) { + const next = (event) => { + return this._client.sendRequest(this._requestType, this._createParams(event)); + }; + return this.doSend(filteredEvent, next); + } else { + return void 0; + } + } + }; + WillCreateFilesFeature = class extends RequestFileOperationFeature { + constructor(client) { + super(client, workspace_default.onWillCreateFiles, import_vscode_languageserver_protocol62.WillCreateFilesRequest.type, "willCreate", "willCreate", (i) => i, (e) => asCreateDeleteFilesParams(e)); + } + doSend(event, next) { + var _a2; + const middleware = (_a2 = this._client.clientOptions.middleware) == null ? void 0 : _a2.workspace; + return (middleware == null ? void 0 : middleware.willCreateFiles) ? middleware.willCreateFiles(event, next) : next(event); + } + }; + WillRenameFilesFeature = class extends RequestFileOperationFeature { + constructor(client) { + super(client, workspace_default.onWillRenameFiles, import_vscode_languageserver_protocol62.WillRenameFilesRequest.type, "willRename", "willRename", (i) => i.oldUri, (e) => asRenameFilesParams(e)); + } + doSend(event, next) { + var _a2; + const middleware = (_a2 = this._client.clientOptions.middleware) == null ? void 0 : _a2.workspace; + return (middleware == null ? void 0 : middleware.willRenameFiles) ? middleware.willRenameFiles(event, next) : next(event); + } + }; + WillDeleteFilesFeature = class extends RequestFileOperationFeature { + constructor(client) { + super(client, workspace_default.onWillDeleteFiles, import_vscode_languageserver_protocol62.WillDeleteFilesRequest.type, "willDelete", "willDelete", (i) => i, (e) => asCreateDeleteFilesParams(e)); + } + doSend(event, next) { + var _a2; + const middleware = (_a2 = this._client.clientOptions.middleware) == null ? void 0 : _a2.workspace; + return (middleware == null ? void 0 : middleware.willDeleteFiles) ? middleware.willDeleteFiles(event, next) : next(event); + } + }; + } +}); + +// src/language-client/index.ts +var import_child_process4, import_fs17, import_path18, import_node, ChildProcess2, logger53, Executable, TransportKind, Transport, NodeModule, StreamInfo, ChildProcessInfo, LanguageClient, SettingMonitor, ProposedFeatures; +var init_language_client = __esm({ + "src/language-client/index.ts"() { + import_child_process4 = __toModule(require("child_process")); + import_fs17 = __toModule(require("fs")); + import_path18 = __toModule(require("path")); + import_node = __toModule(require_node3()); + init_types(); + init_util(); + init_is(); + init_processes(); + init_workspace(); + init_client(); + init_colorProvider(); + init_configuration3(); + init_declaration(); + init_foldingRange(); + init_implementation(); + init_progress2(); + init_typeDefinition(); + init_workspaceFolders(); + init_selectionRange(); + init_callHierarchy(); + init_semanticTokens(); + init_linkedEditingRange(); + init_fileOperations(); + init_client(); + ChildProcess2 = import_child_process4.default.ChildProcess; + logger53 = require_logger2()("language-client-index"); + (function(Executable3) { + function is(value) { + return string(value.command); + } + Executable3.is = is; + })(Executable || (Executable = {})); + (function(TransportKind2) { + TransportKind2[TransportKind2["stdio"] = 0] = "stdio"; + TransportKind2[TransportKind2["ipc"] = 1] = "ipc"; + TransportKind2[TransportKind2["pipe"] = 2] = "pipe"; + TransportKind2[TransportKind2["socket"] = 3] = "socket"; + })(TransportKind || (TransportKind = {})); + (function(Transport3) { + function isSocket(value) { + let candidate = value; + return candidate && candidate.kind === 3 && number(candidate.port); + } + Transport3.isSocket = isSocket; + })(Transport || (Transport = {})); + (function(NodeModule2) { + function is(value) { + return string(value.module); + } + NodeModule2.is = is; + })(NodeModule || (NodeModule = {})); + (function(StreamInfo2) { + function is(value) { + let candidate = value; + return candidate && candidate.writer !== void 0 && candidate.reader !== void 0; + } + StreamInfo2.is = is; + })(StreamInfo || (StreamInfo = {})); + (function(ChildProcessInfo2) { + function is(value) { + let candidate = value; + return candidate && candidate.process !== void 0 && typeof candidate.detached === "boolean"; + } + ChildProcessInfo2.is = is; + })(ChildProcessInfo || (ChildProcessInfo = {})); + LanguageClient = class extends BaseLanguageClient { + constructor(arg1, arg2, arg3, arg4, arg5) { + let id; + let name2; + let serverOptions; + let clientOptions; + let forceDebug; + if (string(arg2)) { + id = arg1; + name2 = arg2; + serverOptions = arg3; + clientOptions = arg4; + forceDebug = !!arg5; + } else { + id = arg1.toLowerCase(); + name2 = arg1; + serverOptions = arg2; + clientOptions = arg3; + forceDebug = arg4; + } + if (forceDebug === void 0) { + forceDebug = false; + } + super(id, name2, clientOptions); + this._serverOptions = serverOptions; + this._forceDebug = forceDebug; + this.registerProposedFeatures(); + } + stop() { + return super.stop().then(() => { + if (this._serverProcess) { + let toCheck = this._serverProcess; + this._serverProcess = void 0; + if (this._isDetached === void 0 || !this._isDetached) { + this.checkProcessDied(toCheck); + } + this._isDetached = void 0; + } + }); + } + get serviceState() { + let state = this._state; + switch (state) { + case ClientState.Initial: + return ServiceStat.Initial; + case ClientState.Running: + return ServiceStat.Running; + case ClientState.StartFailed: + return ServiceStat.StartFailed; + case ClientState.Starting: + return ServiceStat.Starting; + case ClientState.Stopped: + return ServiceStat.Stopped; + case ClientState.Stopping: + return ServiceStat.Stopping; + default: + logger53.error(`Unknown state: ${state}`); + return ServiceStat.Stopped; + } + } + static stateName(state) { + switch (state) { + case ClientState.Initial: + return "Initial"; + case ClientState.Running: + return "Running"; + case ClientState.StartFailed: + return "StartFailed"; + case ClientState.Starting: + return "Starting"; + case ClientState.Stopped: + return "Stopped"; + case ClientState.Stopping: + return "Stopping"; + default: + return "Unknonw"; + } + } + checkProcessDied(childProcess) { + if (!childProcess || global.hasOwnProperty("__TEST__")) + return; + if (global.hasOwnProperty("__TEST__")) { + process.kill(childProcess.pid, 0); + return; + } + setTimeout(() => { + try { + process.kill(childProcess.pid, 0); + terminate(childProcess); + } catch (error) { + } + }, 2e3); + } + handleConnectionClosed() { + this._serverProcess = void 0; + super.handleConnectionClosed(); + } + createMessageTransports(encoding) { + function getEnvironment(env, fork) { + if (!env && !fork) { + return void 0; + } + let result = Object.create(null); + Object.keys(process.env).forEach((key) => result[key] = process.env[key]); + if (env) { + Object.keys(env).forEach((key) => result[key] = env[key]); + } + return result; + } + const debugStartWith = ["--debug=", "--debug-brk=", "--inspect=", "--inspect-brk="]; + const debugEquals = ["--debug", "--debug-brk", "--inspect", "--inspect-brk"]; + function startedInDebugMode() { + let args = process.execArgv; + if (args) { + return args.some((arg) => { + return debugStartWith.some((value) => arg.startsWith(value)) || debugEquals.some((value) => arg === value); + }); + } + return false; + } + function assertStdio(process2) { + if (process2.stdin === null || process2.stdout === null || process2.stderr === null) { + throw new Error("Process created without stdio streams"); + } + } + let server = this._serverOptions; + if (func(server)) { + return server().then((result) => { + if (MessageTransports.is(result)) { + this._isDetached = !!result.detached; + return result; + } else if (StreamInfo.is(result)) { + this._isDetached = !!result.detached; + return { + reader: new import_node.StreamMessageReader(result.reader), + writer: new import_node.StreamMessageWriter(result.writer) + }; + } else { + let cp3; + if (ChildProcessInfo.is(result)) { + cp3 = result.process; + this._isDetached = result.detached; + } else { + cp3 = result; + this._isDetached = false; + } + cp3.stderr.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + return { + reader: new import_node.StreamMessageReader(cp3.stdout), + writer: new import_node.StreamMessageWriter(cp3.stdin) + }; + } + }); + } + let json; + let runDebug = server; + if (runDebug.run || runDebug.debug) { + if (typeof v8debug === "object" || this._forceDebug || startedInDebugMode()) { + json = runDebug.debug; + } else { + json = runDebug.run; + } + } else { + json = server; + } + return this._getServerWorkingDir(json.options).then((serverWorkingDir) => { + if (NodeModule.is(json) && json.module) { + let node = json; + let transport = node.transport || 0; + if (node.runtime) { + let args = []; + let options = node.options || Object.create(null); + if (options.execArgv) { + options.execArgv.forEach((element) => args.push(element)); + } + args.push(node.module); + if (node.args) { + node.args.forEach((element) => args.push(element)); + } + const execOptions = Object.create(null); + execOptions.cwd = serverWorkingDir; + execOptions.env = getEnvironment(options.env, false); + const runtime = this._getRuntimePath(node.runtime, serverWorkingDir); + let pipeName; + if (transport === 1) { + execOptions.stdio = [null, null, null, "ipc"]; + args.push("--node-ipc"); + } else if (transport === 0) { + args.push("--stdio"); + } else if (transport === 2) { + pipeName = (0, import_node.generateRandomPipeName)(); + args.push(`--pipe=${pipeName}`); + } else if (Transport.isSocket(transport)) { + args.push(`--socket=${transport.port}`); + } + args.push(`--clientProcessId=${process.pid.toString()}`); + if (transport === 1 || transport === 0) { + let serverProcess = import_child_process4.default.spawn(runtime, args, execOptions); + if (!serverProcess || !serverProcess.pid) { + return Promise.reject(`Launching server using runtime ${runtime} failed.`); + } + this._serverProcess = serverProcess; + serverProcess.stderr.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + if (transport === 1) { + serverProcess.stdout.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + return Promise.resolve({ reader: new import_node.IPCMessageReader(serverProcess), writer: new import_node.IPCMessageWriter(serverProcess) }); + } else { + return Promise.resolve({ reader: new import_node.StreamMessageReader(serverProcess.stdout), writer: new import_node.StreamMessageWriter(serverProcess.stdin) }); + } + } else if (transport === 2) { + return (0, import_node.createClientPipeTransport)(pipeName).then((transport2) => { + let process2 = import_child_process4.default.spawn(runtime, args, execOptions); + if (!process2 || !process2.pid) { + return Promise.reject(`Launching server using runtime ${runtime} failed.`); + } + this._serverProcess = process2; + process2.stderr.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + process2.stdout.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + return transport2.onConnected().then((protocol) => { + return { reader: protocol[0], writer: protocol[1] }; + }); + }); + } else if (Transport.isSocket(transport)) { + return (0, import_node.createClientSocketTransport)(transport.port).then((transport2) => { + let process2 = import_child_process4.default.spawn(runtime, args, execOptions); + if (!process2 || !process2.pid) { + return Promise.reject(`Launching server using runtime ${runtime} failed.`); + } + this._serverProcess = process2; + process2.stderr.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + process2.stdout.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + return transport2.onConnected().then((protocol) => { + return { reader: protocol[0], writer: protocol[1] }; + }); + }); + } + } else { + let pipeName; + return new Promise((resolve3, _reject) => { + let args = node.args && node.args.slice() || []; + if (transport === 1) { + args.push("--node-ipc"); + } else if (transport === 0) { + args.push("--stdio"); + } else if (transport === 2) { + pipeName = (0, import_node.generateRandomPipeName)(); + args.push(`--pipe=${pipeName}`); + } else if (Transport.isSocket(transport)) { + args.push(`--socket=${transport.port}`); + } + args.push(`--clientProcessId=${process.pid.toString()}`); + let options = node.options || Object.create(null); + options.env = getEnvironment(options.env, true); + options.execArgv = options.execArgv || []; + options.cwd = serverWorkingDir; + options.silent = true; + if (transport === 1 || transport === 0) { + let sp = import_child_process4.default.fork(node.module, args || [], options); + assertStdio(sp); + this._serverProcess = sp; + sp.stderr.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + if (transport === 1) { + sp.stdout.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + resolve3({ reader: new import_node.IPCMessageReader(this._serverProcess), writer: new import_node.IPCMessageWriter(this._serverProcess) }); + } else { + resolve3({ reader: new import_node.StreamMessageReader(sp.stdout), writer: new import_node.StreamMessageWriter(sp.stdin) }); + } + } else if (transport === 2) { + void (0, import_node.createClientPipeTransport)(pipeName).then((transport2) => { + let sp = import_child_process4.default.fork(node.module, args || [], options); + assertStdio(sp); + this._serverProcess = sp; + sp.stderr.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + sp.stdout.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + void transport2.onConnected().then((protocol) => { + resolve3({ reader: protocol[0], writer: protocol[1] }); + }); + }); + } else if (Transport.isSocket(transport)) { + void (0, import_node.createClientSocketTransport)(transport.port).then((transport2) => { + let sp = import_child_process4.default.fork(node.module, args || [], options); + assertStdio(sp); + this._serverProcess = sp; + sp.stderr.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + sp.stdout.on("data", (data) => this.outputChannel.append(string(data) ? data : data.toString(encoding))); + void transport2.onConnected().then((protocol) => { + resolve3({ 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({}, process.env, options.env) : process.env; + options.cwd = options.cwd || serverWorkingDir; + let cmd = workspace_default.expand(json.command); + let serverProcess = import_child_process4.default.spawn(cmd, args, options); + serverProcess.on("error", (e) => { + this.error(e.message); + logger53.error(e); + }); + if (!serverProcess || !serverProcess.pid) { + return Promise.reject(`Launching server "${this.id}" using command ${command.command} failed.`); + } + logger53.info(`Language server "${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.outputChannel.append(string(data) ? data : data.toString(encoding))); + this._serverProcess = serverProcess; + this._isDetached = !!options.detached; + return Promise.resolve({ reader: new import_node.StreamMessageReader(serverProcess.stdout), writer: new import_node.StreamMessageWriter(serverProcess.stdin) }); + } + return Promise.reject(`Unsupported server configuration ${JSON.stringify(server, null, 2)}`); + }); + } + _getRuntimePath(runtime, serverWorkingDirectory) { + if (import_path18.default.isAbsolute(runtime)) { + return runtime; + } + const mainRootPath = this._mainGetRootPath(); + if (mainRootPath !== void 0) { + const result = import_path18.default.join(mainRootPath, runtime); + if (import_fs17.default.existsSync(result)) { + return result; + } + } + if (serverWorkingDirectory !== void 0) { + const result = import_path18.default.join(serverWorkingDirectory, runtime); + if (import_fs17.default.existsSync(result)) { + return result; + } + } + return runtime; + } + _mainGetRootPath() { + let folders = workspace_default.workspaceFolders; + if (!folders || folders.length === 0) { + return void 0; + } + let folder = folders[0]; + return folder.uri; + } + registerProposedFeatures() { + this.registerFeatures(ProposedFeatures.createAll(this)); + } + registerBuiltinFeatures() { + super.registerBuiltinFeatures(); + this.registerFeature(new ConfigurationFeature2(this)); + this.registerFeature(new TypeDefinitionFeature(this)); + this.registerFeature(new ImplementationFeature(this)); + this.registerFeature(new DeclarationFeature(this)); + this.registerFeature(new ColorProviderFeature(this)); + this.registerFeature(new FoldingRangeFeature(this)); + this.registerFeature(new SelectionRangeFeature(this)); + this.registerFeature(new ProgressFeature(this)); + this.registerFeature(new CallHierarchyFeature(this)); + if (workspace_default.isNvim || workspace_default.isVim && workspace_default.env.textprop) { + const config = workspace_default.getConfiguration("coc.preferences"); + const enabled = config.get("semanticTokensHighlights", true); + if (enabled) + this.registerFeature(new SemanticTokensFeature(this)); + } + this.registerFeature(new LinkedEditingFeature(this)); + this.registerFeature(new DidCreateFilesFeature(this)); + this.registerFeature(new DidRenameFilesFeature(this)); + this.registerFeature(new DidDeleteFilesFeature(this)); + this.registerFeature(new WillCreateFilesFeature(this)); + this.registerFeature(new WillRenameFilesFeature(this)); + this.registerFeature(new WillDeleteFilesFeature(this)); + if (!this.clientOptions.disableWorkspaceFolders) { + this.registerFeature(new WorkspaceFoldersFeature(this)); + } + } + _getServerWorkingDir(options) { + let cwd = options && options.cwd; + if (cwd && !import_path18.default.isAbsolute(cwd)) + cwd = import_path18.default.join(workspace_default.cwd, cwd); + if (!cwd) + cwd = workspace_default.cwd; + if (cwd) { + return new Promise((s) => { + import_fs17.default.lstat(cwd, (err, stats) => { + s(!err && stats.isDirectory() ? cwd : void 0); + }); + }); + } + return Promise.resolve(void 0); + } + appendOutput(data, encoding) { + let msg = string(data) ? data : data.toString(encoding); + this.outputChannel.append(msg.endsWith("\n") ? msg : msg + "\n"); + } + }; + SettingMonitor = class { + constructor(_client, _setting) { + this._client = _client; + this._setting = _setting; + this._listeners = []; + } + start() { + workspace_default.onDidChangeConfiguration((e) => { + if (e.affectsConfiguration(this._setting)) { + this.onDidChangeConfiguration(); + } + }, null, this._listeners); + this.onDidChangeConfiguration(); + return { + dispose: () => { + 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) : void 0; + let enabled = rest ? workspace_default.getConfiguration(primary).get(rest, true) : workspace_default.getConfiguration(primary); + if (enabled && this._client.needsStart()) { + this._client.start(); + } else if (!enabled && this._client.needsStop()) { + this._client.stop(); + } + } + }; + (function(ProposedFeatures2) { + function createAll(_client) { + let result = []; + return result; + } + ProposedFeatures2.createAll = createAll; + })(ProposedFeatures || (ProposedFeatures = {})); + } +}); + +// src/services.ts +function getStateName(state) { + switch (state) { + case ServiceStat.Initial: + return "init"; + case ServiceStat.Running: + return "running"; + case ServiceStat.Starting: + return "starting"; + case ServiceStat.StartFailed: + return "startFailed"; + case ServiceStat.Stopping: + return "stopping"; + case ServiceStat.Stopped: + return "stopped"; + default: + return "unknown"; + } +} +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 Array.from(new Set(res)); +} +function getLanguageServerOptions(id, name2, config) { + let { command, module: module2, port, args, filetypes } = config; + args = args || []; + if (!filetypes) { + window_default.showMessage(`Wrong configuration of LS "${name2}", filetypes not found`, "error"); + return null; + } + if (!command && !module2 && !port) { + window_default.showMessage(`Wrong configuration of LS "${name2}", no command or module specified.`, "error"); + return null; + } + let serverOptions; + if (module2) { + module2 = workspace_default.expand(module2); + if (!import_fs18.default.existsSync(module2)) { + window_default.showMessage(`Module file "${module2}" not found for LS "${name2}"`, "error"); + return null; + } + serverOptions = { + module: module2, + 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 = () => new Promise((resolve3, reject) => { + let client = new import_net2.default.Socket(); + let host = config.host || "127.0.0.1"; + logger54.info(`languageserver "${id}" connecting to ${host}:${port}`); + client.connect(port, host, () => { + resolve3({ + reader: client, + writer: client + }); + }); + client.on("error", (e) => { + reject(new Error(`Connection error for ${id}: ${e.message}`)); + }); + }); + } + let disableWorkspaceFolders = !!config.disableWorkspaceFolders; + let disableSnippetCompletion = !!config.disableSnippetCompletion; + let ignoredRootPaths = config.ignoredRootPaths || []; + let clientOptions = { + ignoredRootPaths: ignoredRootPaths.map((s) => workspace_default.expand(s)), + disableWorkspaceFolders, + disableSnippetCompletion, + disableDynamicRegister: !!config.disableDynamicRegister, + disableCompletion: !!config.disableCompletion, + disableDiagnostics: !!config.disableDiagnostics, + formatterPriority: config.formatterPriority || 0, + documentSelector: getDocumentSelector(config.filetypes, config.additionalSchemes), + revealOutputChannelOn: getRevealOutputChannelOn(config.revealOutputChannelOn), + synchronize: { + configurationSection: `${id}.settings` + }, + diagnosticCollectionName: name2, + outputChannelName: id, + stdioEncoding: config.stdioEncoding || "utf8", + progressOnInitialization: config.progressOnInitialization !== false, + initializationOptions: config.initializationOptions || {} + }; + return [clientOptions, serverOptions]; +} +function getRevealOutputChannelOn(revealOn) { + switch (revealOn) { + case "info": + return RevealOutputChannelOn.Info; + case "warn": + return RevealOutputChannelOn.Warn; + case "error": + return RevealOutputChannelOn.Error; + case "never": + return RevealOutputChannelOn.Never; + default: + return RevealOutputChannelOn.Never; + } +} +function getDocumentSelector(filetypes, additionalSchemes) { + let documentSelector = []; + let schemes = ["file", "untitled"].concat(additionalSchemes || []); + if (!filetypes) + return schemes.map((s) => ({ scheme: s })); + filetypes.forEach((filetype) => { + documentSelector.push(...schemes.map((scheme) => ({ language: filetype, scheme }))); + }); + return documentSelector; +} +function getTransportKind(config) { + let { transport, transportPort } = config; + if (!transport || transport == "ipc") + return TransportKind.ipc; + if (transport == "stdio") + return TransportKind.stdio; + if (transport == "pipe") + return TransportKind.pipe; + return { kind: TransportKind.socket, port: transportPort }; +} +function getForkOptions(config) { + return { + cwd: config.cwd, + execArgv: config.execArgv || [], + env: config.env || void 0 + }; +} +function getSpawnOptions(config) { + return { + cwd: config.cwd, + detached: !!config.detached, + shell: !!config.shell, + env: config.env || void 0 + }; +} +function stateString(state) { + switch (state) { + case State2.Running: + return "running"; + case State2.Starting: + return "starting"; + case State2.Stopped: + return "stopped"; + default: + return "unknown"; + } +} +var import_events18, import_fs18, import_net2, import_vscode_languageserver_protocol63, logger54, ServiceManager, services_default; +var init_services = __esm({ + "src/services.ts"() { + import_events18 = __toModule(require("events")); + import_fs18 = __toModule(require("fs")); + import_net2 = __toModule(require("net")); + import_vscode_languageserver_protocol63 = __toModule(require_main2()); + init_language_client(); + init_types(); + init_util(); + init_workspace(); + init_window(); + logger54 = require_logger2()("services"); + ServiceManager = class extends import_events18.EventEmitter { + constructor() { + super(...arguments); + this.registered = new Map(); + this.disposables = []; + } + init() { + workspace_default.onDidOpenTextDocument((document2) => { + this.start(document2); + }, null, this.disposables); + workspace_default.onDidChangeConfiguration((e) => { + if (e.affectsConfiguration("languageserver")) { + this.createCustomServices(); + } + }, null, this.disposables); + this.createCustomServices(); + } + dispose() { + this.removeAllListeners(); + disposeAll(this.disposables); + for (let service of this.registered.values()) { + service.dispose(); + } + } + regist(service) { + let { id } = service; + if (!id) + logger54.error("invalid service configuration. ", service.name); + if (this.registered.get(id)) + return; + this.registered.set(id, service); + logger54.info(`registered service "${id}"`); + if (this.shouldStart(service)) { + service.start(); + } + if (service.state == ServiceStat.Running) { + this.emit("ready", id); + } + service.onServiceReady(() => { + logger54.info(`service ${id} started`); + this.emit("ready", id); + }, null, this.disposables); + return import_vscode_languageserver_protocol63.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; + } + shouldStart(service) { + if (service.state != ServiceStat.Initial) { + return false; + } + let selector = service.selector; + for (let doc of workspace_default.documents) { + if (workspace_default.match(selector, doc.textDocument)) { + return true; + } + } + return false; + } + start(document2) { + let services = this.getServices(document2); + for (let service of services) { + if (service.state == ServiceStat.Initial) { + service.start(); + } + } + } + getServices(document2) { + let res = []; + for (let service of this.registered.values()) { + if (workspace_default.match(service.selector, document2) > 0) { + res.push(service); + } + } + return res; + } + stop(id) { + let service = this.registered.get(id); + if (!service) { + window_default.showMessage(`Service ${id} not found`, "error"); + return; + } + return Promise.resolve(service.stop()); + } + stopAll() { + for (let service of this.registered.values()) { + service.stop(); + } + } + async toggle(id) { + let service = this.registered.get(id); + if (!service) { + window_default.showMessage(`Service ${id} not found`, "error"); + return; + } + let { state } = service; + try { + if (state == ServiceStat.Running) { + await Promise.resolve(service.stop()); + } else if (state == ServiceStat.Initial) { + await service.start(); + } else if (state == ServiceStat.Stopped) { + await service.restart(); + } + } catch (e) { + window_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 lspConfig = workspace_default.getConfiguration().get("languageserver", {}); + for (let key of Object.keys(lspConfig)) { + let config = lspConfig[key]; + if (!this.validServerConfig(key, config)) { + continue; + } + this.registLanguageClient(key, config); + } + } + validServerConfig(key, config) { + let errors = []; + if (config.module != null && typeof config.module !== "string") { + errors.push(`"module" field of languageserver ${key} should be string`); + } + if (config.command != null && typeof config.command !== "string") { + errors.push(`"command" field of languageserver ${key} should be string`); + } + if (config.transport != null && typeof config.transport !== "string") { + errors.push(`"transport" field of languageserver ${key} should be string`); + } + if (config.transportPort != null && typeof config.transportPort !== "number") { + errors.push(`"transportPort" field of languageserver ${key} should be string`); + } + if (!Array.isArray(config.filetypes) || !config.filetypes.every((s) => typeof s === "string")) { + errors.push(`"filetypes" field of languageserver ${key} should be array of string`); + } + if (config.additionalSchemes && (!Array.isArray(config.additionalSchemes) || config.additionalSchemes.some((s) => typeof s !== "string"))) { + errors.push(`"additionalSchemes" field of languageserver ${key} should be array of string`); + } + if (errors.length) { + window_default.showMessage(errors.join("\n"), "error"); + return false; + } + return true; + } + waitClient(id) { + let service = this.getService(id); + if (service && service.state == ServiceStat.Running) + return Promise.resolve(); + if (service) + return new Promise((resolve3) => { + service.onServiceReady(() => { + resolve3(); + }); + }); + return new Promise((resolve3) => { + let listener = (clientId) => { + if (clientId == id || clientId == `languageserver.${id}`) { + this.off("ready", listener); + resolve3(); + } + }; + this.on("ready", listener); + }); + } + async registNotification(id, method) { + await this.waitClient(id); + let service = this.getService(id); + if (!service.client) { + window_default.showMessage(`Not a language client: ${id}`, "error"); + return; + } + let client = service.client; + client.onNotification(method, async (result) => { + await workspace_default.nvim.call("coc#do_notify", [id, method, result]); + }); + } + async sendNotification(id, method, params) { + if (!method) + throw new Error(`method required for ontification`); + let service = this.getService(id); + if (!service || !service.client) + throw new Error(`Language server ${id} not found`); + if (service.state == ServiceStat.Starting) { + await service.client.onReady(); + } + if (service.state != ServiceStat.Running) { + throw new Error(`Language server ${id} not running`); + } + await Promise.resolve(service.client.sendNotification(method, params)); + } + async sendRequest(id, method, params, token) { + if (!method) + throw new Error(`method required for sendRequest`); + let service = this.getService(id); + if (!service) + await wait(100); + service = this.getService(id); + if (!service || !service.client) { + throw new Error(`Language server ${id} not found`); + } + if (service.state == ServiceStat.Starting) { + await service.client.onReady(); + } + if (service.state != ServiceStat.Running) { + throw new Error(`Language server ${id} not running`); + } + if (!token) { + let tokenSource = new import_vscode_languageserver_protocol63.CancellationTokenSource(); + token = tokenSource.token; + } + return await Promise.resolve(service.client.sendRequest(method, params, token)); + } + registLanguageClient(name2, config) { + let id = typeof name2 === "string" ? `languageserver.${name2}` : name2.id; + let disposables = []; + let onDidServiceReady = new import_vscode_languageserver_protocol63.Emitter(); + let client = typeof name2 === "string" ? null : name2; + if (this.registered.has(id)) + return; + let created = false; + let service = { + id, + client, + name: typeof name2 === "string" ? name2 : name2.name, + selector: typeof name2 === "string" ? getDocumentSelector(config.filetypes, config.additionalSchemes) : name2.clientOptions.documentSelector, + state: ServiceStat.Initial, + onServiceReady: onDidServiceReady.event, + start: () => { + if (service.state == ServiceStat.Starting || service.state == ServiceStat.Running) { + return; + } + if (client && !client.needsStart()) { + return; + } + if (created && client) { + client.restart(); + return Promise.resolve(); + } + if (!created) { + if (typeof name2 == "string" && !client) { + let config2 = workspace_default.getConfiguration().get("languageserver", {})[name2]; + if (!config2 || config2.enable === false) + return; + let opts = getLanguageServerOptions(id, name2, config2); + if (!opts) + return; + client = new LanguageClient(id, name2, opts[1], opts[0]); + service.selector = opts[0].documentSelector; + service.client = client; + } + client.onDidChangeState((changeEvent) => { + let { oldState, newState } = changeEvent; + if (newState == State2.Starting) { + service.state = ServiceStat.Starting; + } else if (newState == State2.Running) { + service.state = ServiceStat.Running; + } else if (newState == State2.Stopped) { + service.state = ServiceStat.Stopped; + } + let oldStr = stateString(oldState); + let newStr = stateString(newState); + logger54.info(`${client.name} state change: ${oldStr} => ${newStr}`); + }, null, disposables); + created = true; + } + service.state = ServiceStat.Starting; + logger54.debug(`starting service: ${id}`); + let disposable = client.start(); + disposables.push(disposable); + return new Promise((resolve3) => { + client.onReady().then(() => { + onDidServiceReady.fire(void 0); + resolve3(); + }, (e) => { + window_default.showMessage(`Server ${id} failed to start: ${e}`, "error"); + logger54.error(`Server ${id} failed to start:`, e); + service.state = ServiceStat.StartFailed; + resolve3(); + }); + }); + }, + dispose: async () => { + onDidServiceReady.dispose(); + disposeAll(disposables); + }, + stop: async () => { + if (!client || !client.needsStop()) + return; + await Promise.resolve(client.stop()); + }, + restart: async () => { + if (client) { + service.state = ServiceStat.Starting; + client.restart(); + } else { + await service.start(); + } + } + }; + return this.regist(service); + } + }; + services_default = new ServiceManager(); + } +}); + +// src/list/configuration.ts +var import_events19, validKeys, ListConfiguration; +var init_configuration4 = __esm({ + "src/list/configuration.ts"() { + init_workspace(); + init_window(); + import_events19 = __toModule(require("events")); + validKeys = [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "<2-LeftMouse>", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ]; + ListConfiguration = class extends import_events19.EventEmitter { + constructor() { + super(); + this.configuration = workspace_default.getConfiguration("list"); + this.disposable = workspace_default.onDidChangeConfiguration((e) => { + if (e.affectsConfiguration("list")) { + this.configuration = workspace_default.getConfiguration("list"); + this.emit("change"); + } + }); + } + get(key, defaultValue) { + return this.configuration.get(key, defaultValue); + } + get previousKey() { + return this.fixKey(this.configuration.get("previousKeymap", "")); + } + get nextKey() { + return this.fixKey(this.configuration.get("nextKeymap", "")); + } + dispose() { + this.disposable.dispose(); + this.removeAllListeners(); + } + fixKey(key) { + if (validKeys.includes(key)) + return key; + let find = validKeys.find((s) => s.toLowerCase() == key.toLowerCase()); + if (find) + return find; + window_default.showMessage(`Configured key "${key}" not supported.`, "error"); + return null; + } + }; + } +}); + +// src/list/mappings.ts +var import_extensions, logger55, Mappings; +var init_mappings = __esm({ + "src/list/mappings.ts"() { + import_extensions = __toModule(require_extensions()); + init_window(); + init_configuration4(); + logger55 = require_logger2()("list-mappings"); + Mappings = class { + 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", "", () => { + var _a2; + (_a2 = manager.session) == null ? void 0 : _a2.history.next(); + }); + this.add("insert", "", () => { + var _a2; + (_a2 = manager.session) == null ? void 0 : _a2.history.previous(); + }); + this.add("insert", "", async () => { + await prompt.paste(); + }); + this.add("insert", "", () => manager.switchMatcher()); + this.add("insert", ["", ""], async () => { + await manager.doAction(); + }); + this.add("insert", ["", "", " "], () => manager.chooseAction()); + this.add("insert", "", () => { + manager.toggleMode(); + }); + this.add("insert", "", () => { + manager.stop(); + return; + }); + this.add("insert", "", async () => { + var _a2; + await ((_a2 = manager.session) == null ? void 0 : _a2.reloadItems()); + }); + this.add("insert", "", () => { + prompt.moveLeft(); + }); + this.add("insert", "", () => { + prompt.moveRight(); + }); + this.add("insert", ["", ""], () => { + prompt.moveToEnd(); + }); + this.add("insert", ["", ""], () => { + prompt.moveToStart(); + }); + this.add("insert", ["", "", ""], () => { + prompt.onBackspace(); + }); + this.add("insert", "", () => { + prompt.removeWord(); + }); + this.add("insert", "", () => { + prompt.removeAhead(); + }); + this.add("insert", "", () => prompt.insertRegister()); + this.add("insert", "", () => manager.feedkeys("", false)); + this.add("insert", "", () => manager.feedkeys("", false)); + this.add("insert", "", () => manager.feedkeys("", false)); + this.add("insert", "", () => manager.normal("j")); + this.add("insert", "", () => manager.normal("k")); + this.add("insert", [""], this.doScroll.bind(this, "")); + this.add("insert", [""], this.doScroll.bind(this, "")); + this.add("insert", [""], this.doScroll.bind(this, "")); + this.add("insert", [""], this.doScroll.bind(this, "")); + this.add("normal", "t", () => manager.doAction("tabe")); + this.add("normal", "s", () => manager.doAction("split")); + this.add("normal", "d", () => manager.doAction("drop")); + this.add("normal", ["", "", "\r"], () => manager.doAction()); + this.add("normal", "", () => { + var _a2; + return (_a2 = manager.session) == null ? void 0 : _a2.ui.selectAll(); + }); + this.add("normal", " ", () => { + var _a2; + return (_a2 = manager.session) == null ? void 0 : _a2.ui.toggleSelection(); + }); + this.add("normal", "p", () => manager.togglePreview()); + this.add("normal", ["", " ", ""], () => manager.chooseAction()); + this.add("normal", "", () => { + manager.stop(); + }); + this.add("normal", "", () => { + var _a2; + return (_a2 = manager.session) == null ? void 0 : _a2.reloadItems(); + }); + this.add("normal", "", () => { + var _a2; + return (_a2 = manager.session) == null ? void 0 : _a2.jumpBack(); + }); + this.add("normal", "", () => this.scrollPreview("down")); + this.add("normal", "", () => this.scrollPreview("up")); + this.add("normal", ["i", "I", "o", "O", "a", "A"], () => manager.toggleMode()); + this.add("normal", "?", () => { + var _a2; + return (_a2 = manager.session) == null ? void 0 : _a2.showHelp(); + }); + this.add("normal", ":", async () => { + await manager.cancel(false); + await nvim.eval('feedkeys(":")'); + }); + this.add("normal", [""], this.doScroll.bind(this, "")); + this.add("normal", [""], this.doScroll.bind(this, "")); + this.createMappings(); + config.on("change", () => { + this.createMappings(); + }); + } + createMappings() { + let insertMappings = this.config.get("insertMappings", {}); + this.userInsertMappings = this.fixUserMappings(insertMappings); + let normalMappings = this.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 (key.toLowerCase() == "") { + res.set(" ", value); + } else if (key.toLowerCase() == "") { + res.set("", value); + } else if (validKeys.includes(key)) { + res.set(key, value); + } else { + let find = false; + for (let i = 0; i < validKeys.length; i++) { + if (validKeys[i].toLowerCase() == key.toLowerCase()) { + find = true; + res.set(validKeys[i], value); + break; + } + } + if (!find) + window_default.showMessage(`Invalid list mappings key configuration: "${key}"`, "warning"); + } + } else { + window_default.showMessage(`Invalid list mappings key configuration: "${key}"`, "warning"); + } + } + return res; + } + async doInsertKeymap(key) { + let nextKey = this.config.nextKey; + let previousKey = this.config.previousKey; + let { session } = this.manager; + if (!session) + return; + if (key == nextKey) { + session.ui.index = session.ui.index + 1; + return true; + } + if (key == previousKey) { + session.ui.index = session.ui.index - 1; + 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#prompt#stop_prompt", ["list"]); + window_default.showMessage(msg, "error"); + } + async evalExpression(expr, _mode) { + var _a2, _b, _c, _d, _e, _f, _g; + if (typeof expr != "string" || !expr.includes(":")) { + await this.onError(`Invalid list mapping expression: ${expr}`); + return; + } + let { manager } = this; + let { prompt } = manager; + let [key, action] = expr.split(":", 2); + if (key == "do") { + switch (action.toLowerCase()) { + case "switch": + manager.switchMatcher(); + return; + case "selectall": + await ((_a2 = manager.session) == null ? void 0 : _a2.ui.selectAll()); + return; + case "help": + await ((_b = manager.session) == null ? void 0 : _b.showHelp()); + return; + case "refresh": + await ((_c = manager.session) == null ? void 0 : _c.reloadItems()); + return; + case "exit": + await manager.cancel(); + return; + case "stop": + manager.stop(); + return; + case "cancel": + await manager.cancel(false); + return; + case "toggle": + await ((_d = manager.session) == null ? void 0 : _d.ui.toggleSelection()); + return; + case "jumpback": + (_e = manager.session) == null ? void 0 : _e.jumpBack(); + return; + case "previous": + await manager.normal("k"); + return; + case "next": + await manager.normal("j"); + return; + case "defaultaction": + await manager.doAction(); + return; + case "togglemode": + return manager.toggleMode(); + case "previewtoggle": + return manager.togglePreview(); + case "previewup": + return this.scrollPreview("up"); + case "previewdown": + return this.scrollPreview("down"); + default: + await this.onError(`'${action}' not supported`); + } + } else if (key == "prompt") { + switch (action) { + case "previous": + (_f = manager.session) == null ? void 0 : _f.history.previous(); + return; + case "next": + (_g = manager.session) == null ? void 0 : _g.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": + 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 name2 = await manager.call(action); + if (name2) + await manager.doAction(name2); + } else { + await this.onError(`Invalid expression ${expr}`); + } + } + async doScroll(key) { + await this.manager.feedkeys(key); + } + scrollPreview(dir) { + let { nvim } = this; + nvim.pauseNotification(); + nvim.call("coc#list#scroll_preview", [dir], true); + nvim.command("redraw", true); + void nvim.resumeNotification(false, true); + } + }; + } +}); + +// src/list/prompt.ts +var import_vscode_languageserver_protocol64, logger56, Prompt; +var init_prompt = __esm({ + "src/list/prompt.ts"() { + import_vscode_languageserver_protocol64 = __toModule(require_main2()); + logger56 = require_logger2()("list-prompt"); + Prompt = class { + 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 import_vscode_languageserver_protocol64.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; + } + this.nvim.call("coc#prompt#start_prompt", ["list"], true); + this.drawPrompt(); + } + cancel() { + let { nvim } = this; + nvim.call("coc#prompt#stop_prompt", ["list"], 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); + } + } + insertRegister() { + this.requestInput = true; + } + async paste() { + let text = await this.nvim.eval("@*"); + text = text.replace(/\n/g, ""); + if (!text) + return; + this.addText(text); + } + async eval(expression) { + let text = await this.nvim.call("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); + } + }; + } +}); + +// src/util/fuzzy.ts +function getCharCodes(str) { + let res = []; + for (let i = 0, l = str.length; i < l; i++) { + res.push(str.charCodeAt(i)); + } + return res; +} +function wordChar(ch) { + return ch >= 97 && ch <= 122 || ch >= 65 && ch <= 90; +} +function caseMatch(input, code) { + if (input == code) + return true; + if (input >= 97 && input <= 122 && code + 32 === input) + return true; + return false; +} +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; +} +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; + } + if (m >= 97 && m <= 122 && code + 32 === m) { + i = i + 1; + continue; + } + } + return i === totalCount; +} +var init_fuzzy = __esm({ + "src/util/fuzzy.ts"() { + } +}); + +// src/list/history.ts +var logger57, InputHistory; +var init_history = __esm({ + "src/list/history.ts"() { + init_fuzzy(); + init_workspace(); + logger57 = require_logger2()("list-history"); + InputHistory = class { + constructor(prompt, name2) { + this.prompt = prompt; + this.name = name2; + this.index = -1; + this.loaded = []; + this.current = []; + this.db = workspace_default.createDatabase(`list-${name2}-history`); + this.key = Buffer.from(workspace_default.cwd).toString("base64"); + } + filter() { + let { input } = this.prompt; + if (input == this.curr) + return; + this.historyInput = ""; + let codes = getCharCodes(input); + this.current = this.loaded.filter((s) => fuzzyMatch(codes, s)); + this.index = -1; + } + get curr() { + return this.index == -1 ? null : this.current[this.index]; + } + load(input) { + let { db } = this; + input = input || ""; + let arr = db.fetch(this.key); + 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, prompt } = this; + let { input } = prompt; + if (!input || input.length < 2 || input == this.historyInput) + 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(this.key, 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.historyInput = this.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.historyInput = this.prompt.input = current[this.index] || ""; + } + }; + } +}); + +// src/list/ui.ts +var import_debounce5, import_vscode_languageserver_protocol65, logger58, ListUI; +var init_ui = __esm({ + "src/list/ui.ts"() { + import_debounce5 = __toModule(require_debounce()); + import_vscode_languageserver_protocol65 = __toModule(require_main2()); + init_events(); + init_util(); + init_workspace(); + logger58 = require_logger2()("list-ui"); + ListUI = class { + constructor(nvim, name2, listOptions, config) { + this.nvim = nvim; + this.name = name2; + this.listOptions = listOptions; + this.config = config; + this.newTab = false; + this.currIndex = 0; + this.items = []; + this.disposables = []; + this.selected = new Set(); + this._onDidChangeLine = new import_vscode_languageserver_protocol65.Emitter(); + this._onDidOpen = new import_vscode_languageserver_protocol65.Emitter(); + this._onDidClose = new import_vscode_languageserver_protocol65.Emitter(); + this._onDidLineChange = new import_vscode_languageserver_protocol65.Emitter(); + this._onDoubleClick = new import_vscode_languageserver_protocol65.Emitter(); + this.onDidChangeLine = this._onDidChangeLine.event; + this.onDidLineChange = this._onDidLineChange.event; + this.onDidOpen = this._onDidOpen.event; + this.onDidClose = this._onDidClose.event; + this.onDidDoubleClick = this._onDoubleClick.event; + this.signOffset = config.get("signOffset"); + this.matchHighlightGroup = config.get("matchHighlightGroup", "Search"); + this.newTab = listOptions.position == "tab"; + events_default.on("BufWinLeave", async (bufnr) => { + if (bufnr != this.bufnr || this.window == null) + return; + this.window = null; + this._onDidClose.fire(bufnr); + }, null, this.disposables); + events_default.on("CursorMoved", async (bufnr, cursor) => { + if (bufnr != this.bufnr) + return; + this.onLineChange(cursor[0] - 1); + }, null, this.disposables); + let debounced = (0, import_debounce5.default)(async (bufnr) => { + if (bufnr != this.bufnr) + return; + let [winid, start, end] = await nvim.eval('[win_getid(),line("w0"),line("w$")]'); + if (end < 300 || winid != this.winid) + return; + nvim.pauseNotification(); + this.doHighlight(start - 1, end); + nvim.command("redraw", true); + void nvim.resumeNotification(false, true); + }, 100); + this.disposables.push({ + dispose: () => { + debounced.clear(); + } + }); + events_default.on("CursorMoved", debounced, null, this.disposables); + } + get bufnr() { + var _a2; + return (_a2 = this.buffer) == null ? void 0 : _a2.id; + } + get winid() { + var _a2; + return (_a2 = this.window) == null ? void 0 : _a2.id; + } + get limitLines() { + return this.config.get("limitLines", 3e4); + } + onLineChange(index) { + if (this.currIndex == index) + return; + this.currIndex = index; + this._onDidChangeLine.fire(index); + } + set index(n) { + if (n < 0 || n >= this.items.length) + return; + let { nvim } = this; + nvim.pauseNotification(); + this.setCursor(n + 1, 0); + nvim.command("redraw", true); + void nvim.resumeNotification(false, true); + } + get index() { + return this.currIndex; + } + getItem(index) { + return this.items[index]; + } + get item() { + let { window: window2 } = this; + if (!window2) + return Promise.resolve(null); + return window2.cursor.then((cursor) => { + this.currIndex = cursor[0] - 1; + return this.items[this.currIndex]; + }); + } + async echoMessage(item) { + 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) + return; + let obj = Object.assign({ resolved: true }, item); + if (index < this.length) { + this.items[index] = obj; + let { nvim } = this; + nvim.pauseNotification(); + this.buffer.setOption("modifiable", true, true); + nvim.call("setbufline", [this.bufnr, index + 1, obj.label], true); + this.buffer.setOption("modifiable", false, true); + await nvim.resumeNotification(); + } + } + async getItems() { + if (this.length == 0 || !this.window) + 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++) { + let item2 = this.items[i - 1]; + if (item2) + res.push(item2); + } + 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: window2 } = this; + if (!window2) + return; + let [winid, lnum, col] = await nvim.eval(`[v:mouse_winid,v:mouse_lnum,v:mouse_col]`); + if (event == "mouseDown") { + this.mouseDown = { winid, lnum, col, current: winid == window2.id }; + return; + } + let current = winid == window2.id; + if (current && event == "doubleClick") { + this.setCursor(lnum, 0); + this._onDoubleClick.fire(); + } + if (current && event == "mouseDrag") { + if (!this.mouseDown) + return; + await this.selectLines(this.mouseDown.lnum, lnum); + } else if (current && event == "mouseUp") { + if (!this.mouseDown) + return; + if (this.mouseDown.lnum == lnum) { + this.setCursor(lnum, 0); + nvim.command("redraw", true); + } 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); + nvim.command("redraw", true); + void nvim.resumeNotification(false, true); + } + } + async resume() { + var _a2; + let { items, selected, nvim } = this; + await this.drawItems(items, this.height, true); + if (!selected.size) + return; + nvim.pauseNotification(); + for (let lnum of selected) { + (_a2 = this.buffer) == null ? void 0 : _a2.placeSign({ lnum, id: this.signOffset + lnum, name: "CocSelected", group: "coc-list" }); + } + nvim.command("redraw", true); + void nvim.resumeNotification(false, true); + } + async toggleSelection() { + let { nvim } = this; + await nvim.call("win_gotoid", [this.winid]); + let lnum = await nvim.call("line", "."); + let mode = await nvim.call("mode"); + if (mode == "v" || mode == "V") { + let [start, end] = await this.getSelectedRange(); + let reverse = start > end; + if (reverse) + [start, end] = [end, start]; + for (let i = start; i <= end; i++) { + this.toggleLine(i); + } + this.setCursor(end, 0); + nvim.command("redraw", true); + await nvim.resumeNotification(); + return; + } + nvim.pauseNotification(); + this.toggleLine(lnum); + this.setCursor(lnum + 1, 0); + nvim.command("redraw", true); + await nvim.resumeNotification(); + } + toggleLine(lnum) { + let { selected, buffer, signOffset: signOffset2 } = this; + let exists = selected.has(lnum); + if (!exists) { + selected.add(lnum); + buffer.placeSign({ lnum, id: signOffset2 + lnum, name: "CocSelected", group: "coc-list" }); + } else { + selected.delete(lnum); + buffer.unplaceSign({ id: signOffset2 + lnum, group: "coc-list" }); + } + } + async selectLines(start, end) { + let { nvim, signOffset: signOffset2, buffer, 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); + buffer.placeSign({ lnum: i, id: signOffset2 + i, name: "CocSelected", group: "coc-list" }); + } + 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, signOffset: signOffset2, buffer } = this; + if (selected.size > 0) { + let signIds = []; + for (let lnum of selected) { + signIds.push(signOffset2 + lnum); + } + buffer == null ? void 0 : buffer.unplaceSign({ group: "coc-list" }); + this.selected.clear(); + } + } + get ready() { + if (this.window) + return Promise.resolve(); + return new Promise((resolve3) => { + let disposable = this.onDidLineChange(() => { + disposable.dispose(); + resolve3(); + }); + }); + } + async drawItems(items, height, reload = false) { + const { nvim, name: name2, listOptions } = this; + this.items = items.length > this.limitLines ? items.slice(0, this.limitLines) : items; + if (!this.window) { + let { position, numberSelect } = listOptions; + let [bufnr, winid] = await nvim.call("coc#list#create", [position, height, name2, numberSelect]); + this.height = height; + this.buffer = nvim.createBuffer(bufnr); + let win = this.window = nvim.createWindow(winid); + let statusSegments = this.config.get("statusLineSegments"); + if (statusSegments) + win.setOption("statusline", statusSegments.join(" "), true); + this._onDidOpen.fire(this.bufnr); + } + const lines = this.items.map((item) => item.label); + let newIndex = reload ? this.currIndex : 0; + this.setLines(lines, false, newIndex); + this._onDidLineChange.fire(this.currIndex + 1); + } + appendItems(items) { + let curr = this.items.length; + if (curr >= this.limitLines) + return; + let max = this.limitLines - curr; + let append = items.slice(0, max); + this.items = this.items.concat(append); + this.setLines(append.map((item) => item.label), curr > 0, this.currIndex); + } + setLines(lines, append = false, index) { + let { nvim, buffer, window: window2 } = this; + if (!buffer || !window2) + return; + nvim.pauseNotification(); + if (!append) { + nvim.call("coc#compat#clear_matches", [window2.id], true); + if (!lines.length) { + lines = ["No results, press ? on normal mode to get help."]; + nvim.call("coc#compat#matchaddpos", ["Comment", [[1]], 99, window2.id], true); + } + } + buffer.setOption("modifiable", true, true); + void buffer.setLines(lines, { start: append ? -1 : 0, end: -1, strictIndexing: false }, true); + buffer.setOption("modifiable", false, true); + if (!append && index == 0) { + this.doHighlight(0, 299); + } else { + let height = this.newTab ? workspace_default.env.lines : this.height; + this.doHighlight(Math.max(0, index - height), Math.min(index + height + 1, this.length - 1)); + } + if (!append) { + this.currIndex = index; + window2.setCursor([index + 1, 0], true); + } + nvim.command("redraws", true); + void nvim.resumeNotification(false, true); + } + restoreWindow() { + if (this.newTab) + return; + let { winid, height } = this; + if (winid && height) { + this.nvim.call("coc#list#restore", [winid, height], true); + } + } + 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 { items } = this; + let groups = []; + for (let i = start; i <= Math.min(end, items.length - 1); i++) { + let { ansiHighlights, highlights } = items[i]; + if (ansiHighlights) { + for (let hi of ansiHighlights) { + let { span, hlGroup } = hi; + groups.push({ hlGroup, priority: 9, pos: [i + 1, span[0] + 1, span[1] - span[0]] }); + } + } + if (highlights && Array.isArray(highlights.spans)) { + let { spans, hlGroup } = highlights; + for (let span of spans) { + groups.push({ hlGroup: hlGroup || this.matchHighlightGroup, priority: 11, pos: [i + 1, span[0] + 1, span[1] - span[0]] }); + } + } + } + this.nvim.call("coc#compat#matchaddgroups", [this.window.id, groups], true); + } + setCursor(lnum, col) { + var _a2; + let { items } = this; + let max = items.length == 0 ? 1 : items.length; + if (lnum > max) + return; + this.onLineChange(lnum - 1); + (_a2 = this.window) == null ? void 0 : _a2.setCursor([lnum, col], true); + } + async getSelectedRange() { + let { nvim } = this; + await nvim.call("coc#prompt#stop_prompt", ["list"]); + await nvim.eval('feedkeys("\\", "in")'); + let [, start] = await nvim.call("getpos", "'<"); + let [, end] = await nvim.call("getpos", "'>"); + this.nvim.call("coc#prompt#start_prompt", ["list"], true); + return [start, end]; + } + reset() { + if (this.window) { + this.window = null; + this.buffer = null; + } + } + dispose() { + disposeAll(this.disposables); + this.nvim.call("coc#window#close", [this.winid || -1], true); + this.window = null; + this.buffer = null; + this.items = []; + this._onDidChangeLine.dispose(); + this._onDidOpen.dispose(); + this._onDidClose.dispose(); + this._onDidLineChange.dispose(); + this._onDoubleClick.dispose(); + } + }; + } +}); + +// src/util/score.ts +function getMatchResult(text, query, filename = "") { + if (!text) + return { score: 0 }; + if (!query) + return { score: 1 }; + let matches = []; + let codes = getCharCodes(query); + let filenameIdx = filename ? text.indexOf(filename) : -1; + let matchBase = filenameIdx != -1 && fuzzyMatch(codes, filename); + let score5 = 0; + let c = query[0]; + let idx = 0; + if (matchBase) { + if (filename.startsWith(c)) { + score5 = score5 + 2; + idx = filenameIdx + 1; + matches.push(filenameIdx); + } else if (filename[0].toLowerCase() == c) { + score5 = score5 + 1.5; + idx = filenameIdx + 1; + matches.push(filenameIdx); + } else { + for (let i = 1; i < filename.length; i++) { + if (fuzzyChar(c, filename[i])) { + score5 = score5 + 1; + idx = filenameIdx + i + 1; + matches.push(filenameIdx + i); + break; + } + } + } + } else if (text.startsWith(c)) { + score5 = score5 + 1; + matches.push(0); + idx = 1; + } else { + for (let i = 1; i < text.length; i++) { + let pre = text[i - 1]; + if (pre == import_path19.sep && text[i] == c) { + score5 = score5 + 1; + matches.push(i); + idx = i + 1; + break; + } + } + if (idx == 0) { + for (let i = 0; i < text.length; i++) { + if (fuzzyChar(c, text[i])) { + score5 = score5 + 0.5; + matches.push(i); + idx = i + 1; + break; + } + } + } + } + if (idx == 0) + return { score: 0 }; + if (codes.length == 1) + return { score: score5, matches }; + return nextResult(codes.slice(1), text, idx, { score: score5, matches }); +} +function nextResult(codes, text, idx, curr) { + let { score: score5, 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: score5 + 1, matches: matches.concat([idx]) }; + getRemianResult(idx + 1); + } else if (caseMatch(c, followed)) { + result = { score: score5 + 0.5, matches: matches.concat([idx]) }; + getRemianResult(idx + 1); + } + if (idx + 1 < text.length) { + for (let i = idx + 1; i < text.length; i++) { + let ch = text[i].charCodeAt(0); + if (text[i - 1] == import_path19.sep && caseMatch(c, ch)) { + let add = c == ch ? 1 : 0.5; + result = { score: score5 + add, matches: matches.concat([i]) }; + getRemianResult(i + 1); + break; + } + } + for (let i = idx + 1; i < text.length; i++) { + let ch = text[i].charCodeAt(0); + if (caseMatch(c, ch)) { + let add = c == ch ? 0.5 : 0.2; + result = { score: score5 + 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; +} +var import_path19; +var init_score = __esm({ + "src/util/score.ts"() { + import_path19 = __toModule(require("path")); + init_fuzzy(); + } +}); + +// src/list/worker.ts +function getFilterLabel(item) { + return item.filterText != null ? patchLine(item.filterText, item.label) : item.label; +} +function parseInput(input) { + let res = []; + let startIdx = 0; + let currIdx = 0; + let prev = ""; + for (; currIdx < input.length; currIdx++) { + let ch = input[currIdx]; + if (ch.charCodeAt(0) === 32) { + if (prev && prev != "\\" && startIdx != currIdx) { + res.push(input.slice(startIdx, currIdx)); + startIdx = currIdx + 1; + } + } else { + } + prev = ch; + } + if (startIdx != input.length) { + res.push(input.slice(startIdx, input.length)); + } + return res.map((s) => s.replace(/\\\s/g, " ").trim()).filter((s) => s.length > 0); +} +var import_vscode_languageserver_protocol66, logger59, controlCode, Worker; +var init_worker = __esm({ + "src/list/worker.ts"() { + import_vscode_languageserver_protocol66 = __toModule(require_main2()); + init_ansiparse(); + init_diff(); + init_fzy(); + init_score(); + init_string(); + init_window(); + init_workspace(); + logger59 = require_logger2()("list-worker"); + controlCode = ""; + Worker = class { + constructor(nvim, list2, prompt, listOptions, config) { + this.nvim = nvim; + this.list = list2; + this.prompt = prompt; + this.listOptions = listOptions; + this.config = config; + this._loading = false; + this.totalItems = []; + this._onDidChangeItems = new import_vscode_languageserver_protocol66.Emitter(); + this._onDidChangeLoading = new import_vscode_languageserver_protocol66.Emitter(); + this.onDidChangeItems = this._onDidChangeItems.event; + this.onDidChangeLoading = this._onDidChangeLoading.event; + } + set loading(loading) { + if (this._loading == loading) + return; + this._loading = loading; + this._onDidChangeLoading.fire(loading); + } + get isLoading() { + return this._loading; + } + async loadItems(context, reload = false) { + let { list: list2, listOptions } = this; + this.loading = true; + let { interactive } = listOptions; + this.tokenSource = new import_vscode_languageserver_protocol66.CancellationTokenSource(); + let token = this.tokenSource.token; + let items = await list2.loadItems(context, token); + if (token.isCancellationRequested) + return; + if (!items || Array.isArray(items)) { + this.tokenSource = null; + items = items || []; + this.totalItems = items.map((item) => { + item.label = this.fixLabel(item.label); + this.parseListItemAnsi(item); + return item; + }); + this.loading = false; + let filtered; + if (!interactive) { + filtered = this.filterItems(items); + } else { + filtered = this.convertToHighlightItems(items); + } + this._onDidChangeItems.fire({ + items: filtered, + reload, + finished: true + }); + } else { + let task = items; + let totalItems = this.totalItems = []; + let count = 0; + let currInput = context.input; + let timer; + let lastTs; + let _onData = (finished) => { + lastTs = Date.now(); + 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 items2; + if (interactive) { + items2 = this.convertToHighlightItems(totalItems); + } else { + items2 = this.filterItems(totalItems); + } + this._onDidChangeItems.fire({ items: items2, reload, append: false, finished }); + } else { + let remain = totalItems.slice(count); + count = totalItems.length; + let items2; + if (!interactive) { + items2 = this.filterItems(remain); + } else { + items2 = this.convertToHighlightItems(remain); + } + this._onDidChangeItems.fire({ items: items2, append: true, finished }); + } + }; + task.on("data", (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 (!lastTs && totalItems.length == 500 || Date.now() - lastTs > 200) { + _onData(); + } else { + timer = setTimeout(() => _onData(), 50); + } + }); + let onEnd = () => { + if (task == null) + return; + this.tokenSource = null; + task = null; + this.loading = false; + disposable.dispose(); + if (timer) + clearTimeout(timer); + if (totalItems.length == 0) { + this._onDidChangeItems.fire({ items: [], finished: true }); + } else { + _onData(true); + } + }; + let disposable = token.onCancellationRequested(() => { + if (task) { + task.dispose(); + onEnd(); + } + }); + task.on("error", async (error) => { + if (task == null) + return; + task = null; + this.tokenSource = null; + this.loading = false; + disposable.dispose(); + if (timer) + clearTimeout(timer); + this.nvim.call("coc#prompt#stop_prompt", ["list"], true); + window_default.showMessage(`Task error: ${error.toString()}`, "error"); + logger59.error(error); + }); + task.on("end", onEnd); + } + } + drawItems() { + let { totalItems } = this; + let items; + items = this.filterItems(totalItems); + this._onDidChangeItems.fire({ items, finished: true }); + } + stop() { + if (this.tokenSource) { + this.tokenSource.cancel(); + this.tokenSource = null; + } + this.loading = false; + } + get length() { + return this.totalItems.length; + } + get input() { + return this.prompt.input; + } + convertToHighlightItems(items) { + let { input } = this; + if (!input) + return []; + return items.map((item) => { + let filterLabel = getFilterLabel(item); + let res = getMatchResult(filterLabel, input); + if (!(res == null ? void 0 : res.score)) + return item; + let highlights = this.getHighlights(filterLabel, res.matches); + return Object.assign({}, item, { highlights }); + }); + } + filterItems(items) { + let { input } = this; + let { sort, matcher, ignorecase } = this.listOptions; + let inputs = this.config.extendedSearchMode ? parseInput(input) : [input]; + if (input.length == 0 || inputs.length == 0) + return items; + if (matcher == "strict") { + let filtered2 = []; + for (let item of items) { + let spans = []; + let filterLabel = getFilterLabel(item); + let match = true; + for (let input2 of inputs) { + let idx2 = ignorecase ? filterLabel.toLowerCase().indexOf(input2.toLowerCase()) : filterLabel.indexOf(input2); + if (idx2 == -1) { + match = false; + break; + } + spans.push([byteIndex(filterLabel, idx2), byteIndex(filterLabel, idx2 + byteLength(input2))]); + } + if (match) { + filtered2.push(Object.assign({}, item, { + highlights: { spans } + })); + } + } + return filtered2; + } + if (matcher == "regex") { + let filtered2 = []; + let flags = ignorecase ? "iu" : "u"; + let regexes = inputs.reduce((p, c) => { + try { + let regex = new RegExp(c, flags); + p.push(regex); + } catch (e) { + } + return p; + }, []); + for (let item of items) { + let spans = []; + let filterLabel = getFilterLabel(item); + let match = true; + for (let regex of regexes) { + let ms = filterLabel.match(regex); + if (ms == null) { + match = false; + break; + } + spans.push([byteIndex(filterLabel, ms.index), byteIndex(filterLabel, ms.index + byteLength(ms[0]))]); + } + if (match) { + filtered2.push(Object.assign({}, item, { + highlights: { spans } + })); + } + } + return filtered2; + } + let filtered = []; + let idx = 0; + for (let item of items) { + let filterText = item.filterText || item.label; + let matchScore2 = 0; + let matches = []; + let filterLabel = getFilterLabel(item); + let match = true; + for (let input2 of inputs) { + if (!hasMatch(input2, filterText)) { + match = false; + break; + } + matches.push(...positions(input2, filterLabel)); + if (sort) + matchScore2 += score2(input2, filterText); + } + if (!match) + continue; + let obj = Object.assign({}, item, { + sortText: typeof item.sortText === "string" ? item.sortText : String.fromCharCode(idx), + score: matchScore2, + highlights: this.getHighlights(filterLabel, matches) + }); + filtered.push(obj); + idx = idx + 1; + } + if (sort && filtered.length) { + filtered.sort((a, b) => { + if (a.score != b.score) + return b.score - a.score; + if (a.sortText > b.sortText) + return 1; + return -1; + }); + } + return filtered; + } + getHighlights(text, matches) { + let spans = []; + if (matches && 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([byteIndex(text, start), byteIndex(text, curr) + 1]); + start = next; + curr = start; + next = matches.shift(); + } + spans.push([byteIndex(text, start), byteIndex(text, curr) + 1]); + } + return { spans }; + } + parseListItemAnsi(item) { + let { label } = item; + if (item.ansiHighlights || !label.includes(controlCode)) + return; + let { line, highlights } = parseAnsiHighlights(label); + item.label = line; + item.ansiHighlights = highlights; + } + fixLabel(label) { + let { columns } = workspace_default.env; + label = label.split("\n").join(" "); + return label.slice(0, columns * 2); + } + dispose() { + this.stop(); + } + }; + } +}); + +// src/list/session.ts +var import_debounce6, frames2, logger60, ListSession; +var init_session = __esm({ + "src/list/session.ts"() { + import_debounce6 = __toModule(require_debounce()); + init_mutex(); + init_extensions2(); + init_highligher(); + init_util(); + init_workspace(); + init_window(); + init_history(); + init_ui(); + init_worker(); + frames2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"]; + logger60 = require_logger2()("list-session"); + ListSession = class { + constructor(nvim, prompt, list2, listOptions, listArgs = [], config) { + this.nvim = nvim; + this.prompt = prompt; + this.list = list2; + this.listOptions = listOptions; + this.listArgs = listArgs; + this.config = config; + this.loadingFrame = ""; + this.hidden = false; + this.disposables = []; + this.mutex = new Mutex(); + this.args = []; + this.ui = new ListUI(nvim, list2.name, listOptions, config); + this.history = new InputHistory(prompt, list2.name); + this.worker = new Worker(nvim, list2, prompt, listOptions, { + interactiveDebounceTime: config.get("interactiveDebounceTime", 100), + extendedSearchMode: config.get("extendedSearchMode", true) + }); + this.interactiveDebounceTime = config.get("interactiveDebounceTime", 100); + let debouncedChangeLine = (0, import_debounce6.default)(async () => { + let [previewing, currwin, lnum] = await nvim.eval('[coc#list#has_preview(),win_getid(),line(".")]'); + if (previewing && currwin == this.winid) { + await this.doPreview(lnum - 1); + } + }, 50); + this.disposables.push({ + dispose: () => { + debouncedChangeLine.clear(); + } + }); + this.ui.onDidChangeLine(debouncedChangeLine, null, this.disposables); + this.ui.onDidChangeLine(this.resolveItem, this, this.disposables); + this.ui.onDidLineChange(this.resolveItem, this, this.disposables); + let debounced = (0, import_debounce6.default)(async () => { + let { autoPreview } = this.listOptions; + if (!autoPreview) { + let [previewing, mode] = await nvim.eval("[coc#list#has_preview(),mode()]"); + if (!previewing || mode != "n") + return; + } + await this.doAction("preview"); + }, 50); + this.disposables.push({ + dispose: () => { + debounced.clear(); + } + }); + this.ui.onDidLineChange(debounced, null, this.disposables); + this.ui.onDidLineChange(() => { + this.updateStatus(); + }, null, this.disposables); + this.ui.onDidOpen(async () => { + if (typeof this.list.doHighlight == "function") { + this.list.doHighlight(); + } + if (this.listOptions.first) { + await this.doAction(); + } + }, null, this.disposables); + this.ui.onDidClose(async () => { + await this.hide(); + }, null, this.disposables); + this.ui.onDidDoubleClick(async () => { + await this.doAction(); + }, null, this.disposables); + this.worker.onDidChangeItems(async ({ items, reload, append, finished }) => { + let release = await this.mutex.acquire(); + if (!this.hidden) { + try { + if (append) { + this.ui.appendItems(items); + } else { + let height = this.config.get("height", 10); + if (finished && !listOptions.interactive && listOptions.input.length == 0) { + height = Math.min(items.length, height); + } + await this.ui.drawItems(items, Math.max(1, height), reload); + } + } catch (e) { + nvim.echoError(e); + } + } + release(); + }, null, this.disposables); + this.worker.onDidChangeLoading((loading) => { + if (this.hidden) + return; + if (loading) { + this.interval = setInterval(() => { + let idx = Math.floor(new Date().getMilliseconds() / 100); + this.loadingFrame = frames2[idx]; + this.updateStatus(); + }, 100); + } else { + if (this.interval) { + this.loadingFrame = ""; + clearInterval(this.interval); + this.interval = null; + } + this.updateStatus(); + } + }, null, this.disposables); + } + async start(args) { + this.args = args; + this.cwd = workspace_default.cwd; + this.hidden = false; + let { listOptions, listArgs } = this; + let res = await this.nvim.eval('[win_getid(),bufnr("%"),winheight("%")]'); + this.listArgs = listArgs; + this.history.load(listOptions.input || ""); + this.window = this.nvim.createWindow(res[0]); + this.buffer = this.nvim.createBuffer(res[1]); + this.savedHeight = res[2]; + await this.worker.loadItems(this.context); + } + async reloadItems() { + if (!this.window) + return; + let bufnr = await this.nvim.call("winbufnr", [this.window.id]); + if (bufnr == -1) + return; + this.buffer = this.nvim.createBuffer(bufnr); + await this.worker.loadItems(this.context, true); + } + async call(fname) { + var _a2, _b; + await this.nvim.call("coc#prompt#stop_prompt", ["list"]); + let targets = await this.ui.getItems(); + let context = { + name: this.name, + args: this.listArgs, + input: this.prompt.input, + winid: (_a2 = this.window) == null ? void 0 : _a2.id, + bufnr: (_b = this.buffer) == null ? void 0 : _b.id, + targets + }; + let res = await this.nvim.call(fname, [context]); + this.prompt.start(); + return res; + } + async chooseAction() { + let { nvim } = this; + let { actions, defaultAction } = this.list; + 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 = []; + let invalids = []; + for (let name2 of names) { + let i = 0; + for (let ch of name2) { + if (!shortcuts.has(ch)) { + shortcuts.add(ch); + choices.push(`${name2.slice(0, i)}&${name2.slice(i)}`); + break; + } + i++; + } + if (i == name2.length) { + invalids.push(name2); + } + } + if (invalids.length) { + names = names.filter((s) => !invalids.includes(s)); + } + await nvim.call("coc#prompt#stop_prompt", ["list"]); + let n = await nvim.call("confirm", ["Choose action:", choices.join("\n")]); + await wait(10); + this.prompt.start(); + if (n) + await this.doAction(names[n - 1]); + if (invalids.length) { + nvim.echoError(`Can't create shortcut for actions: ${invalids.join(",")} of "${this.name}" list`); + } + } + async doAction(name2) { + let { list: list2 } = this; + name2 = name2 || list2.defaultAction; + let action = list2.actions.find((o) => o.name == name2); + if (!action) { + window_default.showMessage(`Action ${name2} not found`, "error"); + return; + } + let items; + if (name2 == "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 doPreview(index) { + let item = this.ui.getItem(index); + let action = this.list.actions.find((o) => o.name == "preview"); + if (!item || !action) + return; + await this.doItemAction([item], action); + } + async first() { + await this.doDefaultAction(0); + } + async last() { + await this.doDefaultAction(this.ui.length - 1); + } + async previous() { + await this.doDefaultAction(this.ui.index - 1); + } + async next() { + await this.doDefaultAction(this.ui.index + 1); + } + async doDefaultAction(index) { + let { ui } = this; + let item = ui.getItem(index); + if (!item) + return; + ui.index = index; + await this.doItemAction([item], this.defaultAction); + await ui.echoMessage(item); + } + get name() { + return this.list.name; + } + get winid() { + return this.ui.winid; + } + get length() { + return this.ui.length; + } + get defaultAction() { + let { defaultAction, actions } = this.list; + let action = actions.find((o) => o.name == defaultAction); + if (!action) + throw new Error(`default action "${defaultAction}" not found`); + return action; + } + async hide() { + if (this.hidden) + return; + let { nvim, interval } = this; + if (interval) + clearInterval(interval); + this.hidden = true; + this.worker.stop(); + this.history.add(); + let { winid } = this.ui; + this.ui.reset(); + if (this.window && winid) { + await nvim.call("coc#list#hide", [this.window.id, this.savedHeight, winid]); + if (workspace_default.isVim) { + nvim.command("redraw", true); + await wait(10); + } + } + nvim.call("coc#prompt#stop_prompt", ["list"], true); + } + toggleMode() { + let mode = this.prompt.mode == "normal" ? "insert" : "normal"; + this.prompt.mode = mode; + this.listOptions.mode = mode; + this.updateStatus(); + } + stop() { + this.worker.stop(); + } + async resolveItem() { + let index = this.ui.index; + let item = this.ui.getItem(index); + if (!item || item.resolved) + return; + let { list: list2 } = this; + if (typeof list2.resolveItem == "function") { + let resolved = await Promise.resolve(list2.resolveItem(item)); + if (resolved && index == this.ui.index) { + await this.ui.updateItem(resolved, index); + } + } + } + async showHelp() { + await this.hide(); + let { list: list2, nvim } = this; + if (!list2) + return; + nvim.pauseNotification(); + nvim.command(`tabe +setl\\ previewwindow [LIST HELP]`, true); + nvim.command("setl nobuflisted noswapfile buftype=nofile bufhidden=wipe", true); + await nvim.resumeNotification(); + let hasOptions = list2.options && list2.options.length; + let buf = await nvim.buffer; + let highligher = new Highlighter(); + highligher.addLine("NAME", "Label"); + highligher.addLine(` ${list2.name} - ${list2.description || ""} +`); + highligher.addLine("SYNOPSIS", "Label"); + highligher.addLine(` :CocList [LIST OPTIONS] ${list2.name}${hasOptions ? " [ARGUMENTS]" : ""} +`); + if (list2.detail) { + highligher.addLine("DESCRIPTION", "Label"); + let lines = list2.detail.split("\n").map((s) => " " + s); + highligher.addLine(lines.join("\n") + "\n"); + } + if (hasOptions) { + highligher.addLine("ARGUMENTS", "Label"); + highligher.addLine(""); + for (let opt of list2.options) { + highligher.addLine(opt.name, "Special"); + highligher.addLine(` ${opt.description}`); + highligher.addLine(""); + } + highligher.addLine(""); + } + let config = workspace_default.getConfiguration(`list.source.${list2.name}`); + if (Object.keys(config).length) { + highligher.addLine("CONFIGURATIONS", "Label"); + highligher.addLine(""); + let props = {}; + extensions_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 name2 = `list.source.${list2.name}.${key}`; + let description = props[name2] && props[name2].description ? props[name2].description : key; + highligher.addLine(` "${name2}"`, "MoreMsg"); + highligher.addText(` - ${description}, current value: `); + highligher.addText(JSON.stringify(val), "Special"); + } + highligher.addLine(""); + } + highligher.addLine("ACTIONS", "Label"); + highligher.addLine(` ${list2.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!", true); + await nvim.resumeNotification(); + } + switchMatcher() { + let { matcher, interactive } = this.listOptions; + if (interactive) + return; + const list2 = ["fuzzy", "strict", "regex"]; + let idx = list2.indexOf(matcher) + 1; + if (idx >= list2.length) + idx = 0; + this.listOptions.matcher = list2[idx]; + this.prompt.matcher = list2[idx]; + this.worker.drawItems(); + } + updateStatus() { + let { ui, list: list2, nvim } = this; + if (!ui.winid) + return; + let buf = nvim.createBuffer(ui.bufnr); + let status = { + mode: this.prompt.mode.toUpperCase(), + args: this.args.join(" "), + name: list2.name, + cwd: this.cwd, + loading: this.loadingFrame, + total: this.worker.length + }; + nvim.pauseNotification(); + buf.setVar("list_status", status, true); + nvim.command("redraws", true); + nvim.resumeNotification(false, true).logError(); + } + get context() { + let { winid } = this.ui; + return { + options: this.listOptions, + args: this.listArgs, + input: this.prompt.input, + cwd: workspace_default.cwd, + window: this.window, + buffer: this.buffer, + listWindow: winid ? this.nvim.createWindow(winid) : void 0 + }; + } + onMouseEvent(key) { + switch (key) { + case "": + return this.ui.onMouse("mouseDown"); + case "": + return this.ui.onMouse("mouseDrag"); + case "": + return this.ui.onMouse("mouseUp"); + case "<2-LeftMouse>": + return this.ui.onMouse("doubleClick"); + } + } + async doNumberSelect(ch) { + if (!this.listOptions.numberSelect) + return false; + let code = ch.charCodeAt(0); + if (code >= 48 && code <= 57) { + let n = Number(ch); + if (n == 0) + n = 10; + if (this.ui.length >= n) { + this.nvim.pauseNotification(); + this.ui.setCursor(n, 0); + await this.nvim.resumeNotification(); + await this.doAction(); + return true; + } + } + return false; + } + jumpBack() { + let { window: window2, nvim } = this; + if (window2) { + nvim.pauseNotification(); + nvim.call("coc#prompt#stop_prompt", ["list"], true); + this.nvim.call("win_gotoid", [window2.id], true); + nvim.resumeNotification(false, true).logError(); + } + } + async resume() { + if (this.winid) + await this.hide(); + let res = await this.nvim.eval('[win_getid(),bufnr("%"),winheight("%")]'); + this.hidden = false; + this.window = this.nvim.createWindow(res[0]); + this.buffer = this.nvim.createBuffer(res[1]); + this.savedHeight = res[2]; + this.prompt.start(); + await this.ui.resume(); + if (this.listOptions.autoPreview) { + await this.doAction("preview"); + } + } + async doItemAction(items, action) { + let { noQuit } = this.listOptions; + let { nvim } = this; + let persistAction = action.persist === true || action.name == "preview"; + let persist = this.winid && (persistAction || noQuit); + try { + if (persist) { + if (!persistAction) { + nvim.pauseNotification(); + nvim.call("coc#prompt#stop_prompt", ["list"], true); + nvim.call("win_gotoid", [this.context.window.id], true); + await nvim.resumeNotification(); + } + } else { + await this.hide(); + } + if (action.multiple) { + await Promise.resolve(action.execute(items, this.context)); + } else if (action.parallel) { + await Promise.all(items.map((item) => Promise.resolve(action.execute(item, this.context)))); + } else { + for (let item of items) { + await Promise.resolve(action.execute(item, this.context)); + } + } + if (persist) { + this.ui.restoreWindow(); + } + if (action.reload && persist) + await this.worker.loadItems(this.context, true); + } catch (e) { + window_default.showMessage(e.message, "error"); + logger60.error(`Error on action "${action.name}"`, e); + } + } + onInputChange() { + if (this.timer) + clearTimeout(this.timer); + let len = this.worker.length; + this.listOptions.input = this.prompt.input; + if (this.listOptions.interactive) { + this.worker.stop(); + this.timer = setTimeout(async () => { + await this.worker.loadItems(this.context); + }, this.interactiveDebounceTime); + } else if (len) { + let wait2 = Math.max(Math.min(Math.floor(len / 200), 300), 50); + this.timer = setTimeout(() => { + this.worker.drawItems(); + }, wait2); + } + } + dispose() { + if (!this.hidden) { + this.hidden = true; + let { winid } = this.ui; + this.ui.reset(); + if (this.window && winid) { + this.nvim.call("coc#list#hide", [this.window.id, this.savedHeight, winid], true); + } + } + if (this.interval) { + clearInterval(this.interval); + } + if (this.timer) { + clearTimeout(this.timer); + } + disposeAll(this.disposables); + this.worker.dispose(); + this.ui.dispose(); + } + }; + } +}); + +// src/list/commandTask.ts +var import_child_process5, import_events21, import_readline3, logger61, CommandTask; +var init_commandTask = __esm({ + "src/list/commandTask.ts"() { + import_child_process5 = __toModule(require("child_process")); + import_events21 = __toModule(require("events")); + import_readline3 = __toModule(require("readline")); + init_util(); + logger61 = require_logger2()("list-commandTask"); + CommandTask = class extends import_events21.EventEmitter { + constructor(opt) { + super(); + this.opt = opt; + this.disposables = []; + this.start(); + } + start() { + let { cmd, args, cwd, onLine } = this.opt; + let proc = (0, import_child_process5.spawn)(cmd, args, { cwd, windowsHide: true }); + this.disposables.push({ + dispose: () => { + proc.kill(); + } + }); + proc.on("error", (e) => { + this.emit("error", e.message); + }); + proc.stderr.on("data", (chunk) => { + logger61.error(`[${cmd} Error]`, chunk.toString("utf8")); + }); + const rl = import_readline3.default.createInterface(proc.stdout); + rl.on("line", (line) => { + let res = onLine(line); + if (res) + this.emit("data", res); + }); + rl.on("close", () => { + this.emit("end"); + }); + } + dispose() { + disposeAll(this.disposables); + } + }; + } +}); + +// src/list/basic.ts +function getFiletype(filetype) { + switch (filetype) { + case "javascriptreact": + return "javascript"; + case "typescriptreact": + return "typescript"; + case "latex": + return "tex"; + default: + if (filetype.indexOf(".") !== -1) + return filetype.split(".")[0]; + return filetype; + } +} +var import_fs19, import_path20, import_readline4, import_vscode_languageserver_protocol67, logger62, BasicList; +var init_basic = __esm({ + "src/list/basic.ts"() { + import_fs19 = __toModule(require("fs")); + import_path20 = __toModule(require("path")); + import_readline4 = __toModule(require("readline")); + import_vscode_languageserver_protocol67 = __toModule(require_main2()); + init_esm2(); + init_util(); + init_fs(); + init_position(); + init_workspace(); + init_commandTask(); + init_configuration4(); + logger62 = require_logger2()("list-basic"); + BasicList = class { + constructor(nvim) { + this.nvim = nvim; + this.defaultAction = "open"; + this.actions = []; + this.options = []; + this.disposables = []; + this.config = new ListConfiguration(); + } + get alignColumns() { + return this.config.get("alignColumns", false); + } + get hlGroup() { + return this.config.get("previewHighlightGroup", "Search"); + } + get previewHeight() { + return this.config.get("maxPreviewHeight", 12); + } + get splitRight() { + return this.config.get("previewSplitRight", false); + } + get toplineStyle() { + return this.config.get("previewToplineStyle", "offset"); + } + get toplineOffset() { + return this.config.get("previewToplineOffset", 3); + } + 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 name2 = opt.key ? opt.key : parts[parts.length - 1].replace(/^-/, ""); + for (let p of parts) { + this.optionMap.set(p, { name: name2, 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) + continue; + let value = true; + if (def.hasValue) { + value = args[i + 1] || ""; + i = i + 1; + } + res[def.name] = value; + } + return res; + } + getConfig() { + return workspace_default.getConfiguration(`list.source.${this.name}`); + } + addAction(name2, fn, options) { + this.createAction(Object.assign({ + name: name2, + execute: fn + }, options || {})); + } + addMultipleAction(name2, fn, options) { + this.createAction(Object.assign({ + name: name2, + multiple: true, + execute: fn + }, options || {})); + } + createCommandTask(opt) { + return new CommandTask(opt); + } + 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) => this.convertLocation(item.location).then((loc) => workspace_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 name2 of ["open", "tabe", "drop", "vsplit", "split"]) { + this.createAction({ + name: name2, + execute: async (item) => { + await this.jumpTo(item.location, name2 == "open" ? null : name2); + } + }); + } + } + async convertLocation(location) { + if (typeof location == "string") + return import_vscode_languageserver_protocol67.Location.create(location, import_vscode_languageserver_protocol67.Range.create(0, 0, 0, 0)); + if (import_vscode_languageserver_protocol67.Location.is(location)) + return location; + let u = URI.parse(location.uri); + if (u.scheme != "file") + return import_vscode_languageserver_protocol67.Location.create(location.uri, import_vscode_languageserver_protocol67.Range.create(0, 0, 0, 0)); + const rl = import_readline4.default.createInterface({ + input: import_fs19.default.createReadStream(u.fsPath, { encoding: "utf8" }) + }); + let match = location.line; + let n = 0; + let resolved = false; + let line = await new Promise((resolve3) => { + rl.on("line", (line2) => { + if (resolved) + return; + if (line2.includes(match)) { + rl.removeAllListeners(); + rl.close(); + resolved = true; + resolve3(line2); + return; + } + n = n + 1; + }); + rl.on("error", (e) => { + this.nvim.errWriteLine(`Read ${u.fsPath} error: ${e.message}`); + resolve3(null); + }); + }); + if (line != null) { + let character = location.text ? line.indexOf(location.text) : 0; + if (character == 0) + character = line.match(/^\s*/)[0].length; + let end = import_vscode_languageserver_protocol67.Position.create(n, character + (location.text ? location.text.length : 0)); + return import_vscode_languageserver_protocol67.Location.create(location.uri, import_vscode_languageserver_protocol67.Range.create(import_vscode_languageserver_protocol67.Position.create(n, character), end)); + } + return import_vscode_languageserver_protocol67.Location.create(location.uri, import_vscode_languageserver_protocol67.Range.create(0, 0, 0, 0)); + } + async jumpTo(location, command) { + if (typeof location == "string") { + await workspace_default.jumpTo(location, null, command); + return; + } + let { range, uri } = await this.convertLocation(location); + let position = range.start; + if (position.line == 0 && position.character == 0 && comparePosition(position, range.end) == 0) { + position = null; + } + await workspace_default.jumpTo(uri, position, command); + } + createAction(action) { + let { name: name2 } = action; + let idx = this.actions.findIndex((o) => o.name == name2); + if (idx !== -1) + this.actions.splice(idx, 1); + this.actions.push(action); + } + async previewLocation(location, context) { + if (!context.listWindow) + return; + let { nvim } = this; + let { uri, range } = location; + let doc = workspace_default.getDocument(location.uri); + let u = URI.parse(uri); + let lines = []; + if (doc) { + lines = doc.getLines(); + } else if (u.scheme == "file") { + try { + let content = await readFile(u.fsPath, "utf8"); + lines = content.split(/\r?\n/); + } catch (e) { + [`Error on read file ${u.fsPath}`, e.message]; + } + } + let config = { + winid: context.window.id, + range: emptyRange(range) ? null : range, + lnum: range.start.line + 1, + name: u.scheme == "file" ? u.fsPath : uri, + filetype: doc ? doc.filetype : this.getFiletype(u.fsPath), + position: context.options.position, + maxHeight: this.previewHeight, + splitRight: this.splitRight, + hlGroup: this.hlGroup, + scheme: u.scheme, + toplineStyle: this.toplineStyle, + toplineOffset: this.toplineOffset + }; + await nvim.call("coc#list#preview", [lines, config]); + if (workspace_default.isVim) + nvim.command("redraw", true); + } + async preview(options, context) { + let { nvim } = this; + let { bufname, filetype, range, lines, lnum } = options; + let config = { + winid: context.window.id, + lnum: range ? range.start.line + 1 : lnum || 1, + filetype: filetype || "txt", + position: context.options.position, + maxHeight: this.previewHeight, + splitRight: this.splitRight, + hlGroup: this.hlGroup, + toplineStyle: this.toplineStyle, + toplineOffset: this.toplineOffset + }; + if (bufname) + config.name = bufname; + if (range) + config.range = range; + await nvim.call("coc#list#preview", [lines, config]); + if (workspace_default.isVim) + nvim.command("redraw", true); + } + doHighlight() { + } + dispose() { + disposeAll(this.disposables); + } + getFiletype(filepath) { + let extname = import_path20.default.extname(filepath); + if (!extname) + return ""; + for (let doc of workspace_default.documents) { + let fsPath = URI.parse(doc.uri).fsPath; + if (import_path20.default.extname(fsPath) == extname) { + return getFiletype(doc.filetype); + } + } + return ""; + } + }; + } +}); + +// src/list/formatting.ts +function formatListItems(align, list2) { + if (list2.length === 0) { + return []; + } + let processedList = []; + if (align) { + const maxWidths = Array(Math.min(...list2.map((item) => item.label.length))).fill(0); + for (let item of list2) { + for (let i = 0; i < maxWidths.length; i++) { + maxWidths[i] = Math.max(maxWidths[i], item.label[i].length); + } + } + processedList = list2.map((item) => __spreadProps(__spreadValues({}, item), { + label: item.label.map((element, idx) => element.padEnd(maxWidths[idx])).join(" ") + })); + } else { + processedList = list2.map((item) => __spreadProps(__spreadValues({}, item), { label: item.label.join(" ") })); + } + return processedList; +} +function formatPath(format2, pathToFormat) { + var _a2; + if (format2 === "hidden") { + return ""; + } else if (format2 === "full") { + return pathToFormat; + } else if (format2 === "short") { + const segments = pathToFormat.split(import_path21.default.sep); + if (segments.length < 2) { + return pathToFormat; + } + const shortenedInit = segments.slice(0, segments.length - 2).filter((seg) => seg.length > 0).map((seg) => seg[0]); + return [...shortenedInit, segments[segments.length - 1]].join(import_path21.default.sep); + } else { + const segments = pathToFormat.split(import_path21.default.sep); + return (_a2 = segments[segments.length - 1]) != null ? _a2 : ""; + } +} +var import_path21; +var init_formatting = __esm({ + "src/list/formatting.ts"() { + import_path21 = __toModule(require("path")); + } +}); + +// src/list/source/commands.ts +function score3(list2, key) { + let idx = list2.indexOf(key); + return idx == -1 ? -1 : list2.length - idx; +} +var CommandsList; +var init_commands = __esm({ + "src/list/source/commands.ts"() { + init_commands2(); + init_events(); + init_workspace(); + init_basic(); + init_formatting(); + CommandsList = class extends BasicList { + constructor(nvim) { + super(nvim); + this.defaultAction = "run"; + this.description = "registered commands of coc.nvim"; + this.name = "commands"; + this.mru = workspace_default.createMru("commands"); + this.addAction("run", async (item) => { + let { cmd } = item.data; + await events_default.fire("Command", [cmd]); + commands_default.executeCommand(cmd).logError(); + await commands_default.addRecent(cmd); + }); + this.addAction("append", async (item) => { + let { cmd } = item.data; + await nvim.feedKeys(`:CocCommand ${cmd} `, "n", false); + }); + } + async loadItems(_context) { + let items = []; + let mruList = await this.mru.load(); + let { commandList, onCommandList, titles } = commands_default; + let ids = commandList.map((c) => c.id).concat(onCommandList); + for (const id of [...new Set(ids)]) { + items.push({ + label: [id, ...titles.get(id) ? [titles.get(id)] : []], + filterText: id, + data: { cmd: id, score: score3(mruList, id) } + }); + } + items.sort((a, b) => b.data.score - a.data.score); + return formatListItems(this.alignColumns, 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); + void nvim.resumeNotification(false, true); + } + }; + } +}); + +// src/list/source/location.ts +var import_path22, logger63, LocationList; +var init_location = __esm({ + "src/list/source/location.ts"() { + init_main(); + import_path22 = __toModule(require("path")); + init_basic(); + init_workspace(); + init_esm2(); + init_fs(); + init_string(); + logger63 = require_logger2()("list-location"); + LocationList = class extends BasicList { + 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, token) { + let locs = await this.nvim.getVar("coc_jump_locations"); + if (token.isCancellationRequested) + return []; + locs = locs || []; + locs.forEach((loc) => { + if (!loc.uri) { + let fullpath = import_path22.default.isAbsolute(loc.filename) ? loc.filename : import_path22.default.join(context.cwd, loc.filename); + loc.uri = URI.file(fullpath).toString(); + } + if (!loc.bufnr && workspace_default.getDocument(loc.uri) != null) { + loc.bufnr = workspace_default.getDocument(loc.uri).bufnr; + } + if (!loc.range) { + let { lnum, col } = loc; + loc.range = 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 = context.buffer.id; + 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 (import_path22.default.isAbsolute(filename)) { + filename = isParentFolder(context.cwd, filename) ? import_path22.default.relative(context.cwd, filename) : filename; + } + let pre = `${filename} |${loc.type ? loc.type + " " : ""}${loc.lnum} col ${loc.col}| `; + let highlight; + if (loc.range && loc.range.start.line == loc.range.end.line) { + let start = byteLength(pre) + byteLength(loc.text.slice(0, loc.range.start.character)); + let end = byteLength(pre) + byteLength(loc.text.slice(0, loc.range.end.character)); + highlight = { hlGroup: "Search", span: [start, end] }; + } + let label = pre + loc.text; + return { + label, + location: Location.create(loc.uri, loc.range), + filterText, + ansiHighlights: highlight ? [highlight] : void 0 + }; + }); + 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) => { + }); + } + }; + } +}); + +// src/list/source/diagnostics.ts +var import_path23, logger64, DiagnosticsList; +var init_diagnostics = __esm({ + "src/list/source/diagnostics.ts"() { + import_path23 = __toModule(require("path")); + init_manager(); + init_location(); + init_fs(); + init_formatting(); + logger64 = require_logger2()("list-symbols"); + DiagnosticsList = class extends LocationList { + constructor() { + super(...arguments); + this.defaultAction = "open"; + this.description = "diagnostics of current workspace"; + this.name = "diagnostics"; + } + async loadItems(context) { + let list2 = manager_default.getDiagnosticList(); + let { cwd } = context; + const config = this.getConfig(); + const shouldIncludeCode = config.get("includeCode", true); + const pathFormat = config.get("pathFormat", "full"); + const unformatted = list2.map((item) => { + const file = isParentFolder(cwd, item.file) ? import_path23.default.relative(cwd, item.file) : item.file; + const formattedPath = formatPath(pathFormat, file); + const formattedPosition = pathFormat !== "hidden" ? [`${formattedPath}:${item.lnum}`] : []; + const code = shouldIncludeCode ? [`[${item.source}${item.code ? "" : "]"}`, item.code ? `${item.code}]` : ""] : []; + return { + label: [...formattedPosition, ...code, item.severity, item.message], + location: item.location + }; + }); + return formatListItems(this.alignColumns, unformatted); + } + doHighlight() { + let { nvim } = this; + nvim.pauseNotification(); + nvim.command("syntax match CocDiagnosticsFile /\\v^\\s*\\S+/ contained containedin=CocDiagnosticsLine", true); + nvim.command("syntax match CocDiagnosticsError /\\tError\\s*\\t/ contained containedin=CocDiagnosticsLine", true); + nvim.command("syntax match CocDiagnosticsWarning /\\tWarning\\s*\\t/ contained containedin=CocDiagnosticsLine", true); + nvim.command("syntax match CocDiagnosticsInfo /\\tInformation\\s*\\t/ contained containedin=CocDiagnosticsLine", true); + nvim.command("syntax match CocDiagnosticsHint /\\tHint\\s*\\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); + void nvim.resumeNotification(false, true); + } + }; + } +}); + +// src/list/source/extensions.ts +function getPriority(stat) { + switch (stat) { + case "unknown": + return 2; + case "activated": + return 1; + case "disabled": + return -1; + default: + return 0; + } +} +var import_fs_extra7, import_os9, import_path24, logger65, ExtensionList; +var init_extensions = __esm({ + "src/list/source/extensions.ts"() { + import_fs_extra7 = __toModule(require_lib5()); + import_os9 = __toModule(require("os")); + import_path24 = __toModule(require("path")); + init_esm2(); + init_extensions2(); + init_util(); + init_workspace(); + init_window(); + init_basic(); + init_formatting(); + logger65 = require_logger2()("list-extensions"); + ExtensionList = class extends BasicList { + 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") { + await extensions_default.deactivate(id); + } else { + await extensions_default.activate(id); + } + await wait(100); + }, { persist: true, reload: true, parallel: true }); + this.addAction("configuration", async (item) => { + let { root } = item.data; + let jsonFile = import_path24.default.join(root, "package.json"); + if (import_fs_extra7.default.existsSync(jsonFile)) { + let lines = import_fs_extra7.default.readFileSync(jsonFile, "utf8").split(/\r?\n/); + let idx = lines.findIndex((s) => s.includes('"contributes"')); + await workspace_default.jumpTo(URI.file(jsonFile).toString(), { line: idx == -1 ? 0 : idx, character: 0 }); + } + }); + this.addAction("open", async (item) => { + let { root } = item.data; + if (workspace_default.env.isiTerm) { + nvim.call("coc#util#iterm_open", [root], true); + } else { + nvim.call("coc#util#open_url", [root], true); + } + }); + this.addAction("disable", async (item) => { + let { id, state } = item.data; + if (state !== "disabled") + await extensions_default.toggleExtension(id); + }, { persist: true, reload: true, parallel: true }); + this.addAction("enable", async (item) => { + let { id, state } = item.data; + if (state == "disabled") + await extensions_default.toggleExtension(id); + }, { persist: true, reload: true, parallel: true }); + this.addAction("lock", async (item) => { + let { id } = item.data; + await extensions_default.toggleLock(id); + }, { persist: true, reload: true }); + this.addAction("help", async (item) => { + let { root } = item.data; + let files = await import_fs_extra7.default.readdir(root); + let file = files.find((f) => /^readme/i.test(f)); + if (file) + await workspace_default.callAsync("coc#util#jump", ["edit", import_path24.default.join(root, file)]); + }); + this.addAction("reload", async (item) => { + let { id } = item.data; + await extensions_default.reloadExtension(id); + }, { persist: true, reload: true }); + this.addAction("fix", async (item) => { + let { root, isLocal } = item.data; + let { npm } = extensions_default; + if (isLocal) { + window_default.showMessage(`Can't fix for local extension.`, "warning"); + return; + } + if (!npm) + return; + let folder = import_path24.default.join(root, "node_modules"); + if (import_fs_extra7.default.existsSync(folder)) { + import_fs_extra7.default.removeSync(folder); + } + let terminal = await workspace_default.createTerminal({ + cwd: root + }); + let shown = await terminal.show(false); + if (!shown) + return; + workspace_default.nvim.command(`startinsert`, true); + terminal.sendText(`${npm} install --production --ignore-scripts --no-lockfile`, true); + }); + this.addMultipleAction("uninstall", async (items) => { + let ids = []; + for (let item of items) { + if (item.data.isLocal) + continue; + ids.push(item.data.id); + } + extensions_default.uninstallExtension(ids).catch((e) => { + logger65.error(e); + }); + }); + } + async loadItems(_context) { + let items = []; + let list2 = await extensions_default.getExtensionStates(); + let lockedList = await extensions_default.getLockedList(); + for (let stat of list2) { + 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.includes(stat.id); + items.push({ + label: [`${prefix} ${stat.id}${locked ? " \uE0A2" : ""}`, ...stat.isLocal ? ["[RTP]"] : [], stat.version, root.replace(import_os9.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 formatListItems(this.alignColumns, 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) => { + }); + } + }; + } +}); + +// src/list/source/folders.ts +var import_path25, import_fs_extra8, FoldList; +var init_folders = __esm({ + "src/list/source/folders.ts"() { + import_path25 = __toModule(require("path")); + init_esm2(); + import_fs_extra8 = __toModule(require_lib5()); + init_fs(); + init_workspace(); + init_window(); + init_basic(); + FoldList = class extends BasicList { + 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, "dir"]); + let stat = await statAsync(newPath); + if (!stat || !stat.isDirectory()) { + window_default.showMessage(`invalid path: ${newPath}`, "error"); + return; + } + workspace_default.renameWorkspaceFolder(item.label, newPath); + }); + this.addAction("delete", async (item) => { + workspace_default.removeWorkspaceFolder(item.label); + }, { reload: true, persist: true }); + this.addAction("newfile", async (item) => { + let file = await window_default.requestInput("File name", item.label + "/"); + let dir = import_path25.default.dirname(file); + let stat = await statAsync(dir); + if (!stat || !stat.isDirectory()) { + import_fs_extra8.default.mkdirpSync(dir); + } + await workspace_default.createFile(file, { overwrite: false, ignoreIfExists: true }); + await this.jumpTo(URI.file(file).toString()); + }); + } + async loadItems(_context) { + return workspace_default.folderPaths.map((p) => ({ label: p })); + } + }; + } +}); + +// src/list/source/links.ts +function formatUri(uri) { + if (!uri.startsWith("file:")) + return uri; + let filepath = URI.parse(uri).fsPath; + return isParentFolder(workspace_default.cwd, filepath) ? import_path26.default.relative(workspace_default.cwd, filepath) : filepath; +} +var import_path26, LinksList; +var init_links = __esm({ + "src/list/source/links.ts"() { + init_languages(); + init_workspace(); + import_path26 = __toModule(require("path")); + init_basic(); + init_main(); + init_esm2(); + init_fs(); + LinksList = class extends BasicList { + 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 = URI.parse(target); + if (uri.scheme.startsWith("http")) { + await nvim.call("coc#util#open_url", target); + } else { + await workspace_default.jumpTo(target); + } + }); + this.addAction("jump", async (item) => { + let { location } = item.data; + await workspace_default.jumpTo(location.uri, location.range.start); + }); + } + async loadItems(context, token) { + let buf = await context.window.buffer; + let doc = workspace_default.getDocument(buf.id); + if (!doc) + return null; + let items = []; + let links2 = await languages_default.getDocumentLinks(doc.textDocument, token); + if (links2 == null) { + throw new Error("Links provider not found."); + } + let res = []; + for (let link of links2) { + if (link.target) { + items.push({ + label: formatUri(link.target), + data: { + target: link.target, + location: Location.create(doc.uri, link.range) + } + }); + } else { + link = await languages_default.resolveDocumentLink(link); + if (link.target) { + items.push({ + label: formatUri(link.target), + data: { + target: link.target, + location: Location.create(doc.uri, link.range) + } + }); + } + res.push(link); + } + } + return items; + } + }; + } +}); + +// src/list/source/lists.ts +function score4(list2, key) { + let idx = list2.indexOf(key); + return idx == -1 ? -1 : list2.length - idx; +} +var LinksList2; +var init_lists = __esm({ + "src/list/source/lists.ts"() { + init_basic(); + init_mru(); + init_formatting(); + LinksList2 = class extends BasicList { + 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("lists"); + this.addAction("open", async (item) => { + let { name: name2 } = item.data; + await this.mru.add(name2); + await nvim.command(`CocList ${name2}`); + }); + } + async loadItems(_context) { + let items = []; + let mruList = await this.mru.load(); + for (let list2 of this.listMap.values()) { + if (list2.name == "lists") + continue; + items.push({ + label: [list2.name, ...list2.description ? [list2.description] : []], + data: { + name: list2.name, + interactive: list2.interactive, + score: score4(mruList, list2.name) + } + }); + } + items.sort((a, b) => b.data.score - a.data.score); + return formatListItems(this.alignColumns, 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) => { + }); + } + }; + } +}); + +// src/util/convert.ts +function getSymbolKind(kind) { + switch (kind) { + case import_vscode_languageserver_protocol68.SymbolKind.File: + return "File"; + case import_vscode_languageserver_protocol68.SymbolKind.Module: + return "Module"; + case import_vscode_languageserver_protocol68.SymbolKind.Namespace: + return "Namespace"; + case import_vscode_languageserver_protocol68.SymbolKind.Package: + return "Package"; + case import_vscode_languageserver_protocol68.SymbolKind.Class: + return "Class"; + case import_vscode_languageserver_protocol68.SymbolKind.Method: + return "Method"; + case import_vscode_languageserver_protocol68.SymbolKind.Property: + return "Property"; + case import_vscode_languageserver_protocol68.SymbolKind.Field: + return "Field"; + case import_vscode_languageserver_protocol68.SymbolKind.Constructor: + return "Constructor"; + case import_vscode_languageserver_protocol68.SymbolKind.Enum: + return "Enum"; + case import_vscode_languageserver_protocol68.SymbolKind.Interface: + return "Interface"; + case import_vscode_languageserver_protocol68.SymbolKind.Function: + return "Function"; + case import_vscode_languageserver_protocol68.SymbolKind.Variable: + return "Variable"; + case import_vscode_languageserver_protocol68.SymbolKind.Constant: + return "Constant"; + case import_vscode_languageserver_protocol68.SymbolKind.String: + return "String"; + case import_vscode_languageserver_protocol68.SymbolKind.Number: + return "Number"; + case import_vscode_languageserver_protocol68.SymbolKind.Boolean: + return "Boolean"; + case import_vscode_languageserver_protocol68.SymbolKind.Array: + return "Array"; + case import_vscode_languageserver_protocol68.SymbolKind.Object: + return "Object"; + case import_vscode_languageserver_protocol68.SymbolKind.Key: + return "Key"; + case import_vscode_languageserver_protocol68.SymbolKind.Null: + return "Null"; + case import_vscode_languageserver_protocol68.SymbolKind.EnumMember: + return "EnumMember"; + case import_vscode_languageserver_protocol68.SymbolKind.Struct: + return "Struct"; + case import_vscode_languageserver_protocol68.SymbolKind.Event: + return "Event"; + case import_vscode_languageserver_protocol68.SymbolKind.Operator: + return "Operator"; + case import_vscode_languageserver_protocol68.SymbolKind.TypeParameter: + return "TypeParameter"; + default: + return "Unknown"; + } +} +var import_vscode_languageserver_protocol68; +var init_convert = __esm({ + "src/util/convert.ts"() { + import_vscode_languageserver_protocol68 = __toModule(require_main2()); + } +}); + +// src/list/source/outline.ts +function getFilterText(s, kind) { + return `${s.name}${kind ? ` ${kind}` : ""}`; +} +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; +} +var import_path27, import_which3, logger66, Outline; +var init_outline = __esm({ + "src/list/source/outline.ts"() { + import_path27 = __toModule(require("path")); + init_main(); + init_esm2(); + import_which3 = __toModule(require_which()); + init_languages(); + init_util(); + init_fs(); + init_workspace(); + init_location(); + init_convert(); + init_formatting(); + logger66 = require_logger2()("list-symbols"); + Outline = class extends LocationList { + constructor() { + super(...arguments); + this.description = "symbols of current document"; + this.name = "outline"; + this.options = [{ + name: "-k, -kind KIND", + hasValue: true, + description: "filters also by kind" + }]; + } + async loadItems(context, token) { + let buf = await context.window.buffer; + let document2 = workspace_default.getDocument(buf.id); + if (!document2) + return null; + let config = this.getConfig(); + let ctagsFilestypes = config.get("ctagsFilestypes", []); + let symbols; + let args = this.parseArguments(context.args); + if (!ctagsFilestypes.includes(document2.filetype)) { + symbols = await languages_default.getDocumentSymbol(document2.textDocument, token); + } + if (token.isCancellationRequested) + return []; + if (!symbols) + return await this.loadCtagsSymbols(document2); + if (symbols.length == 0) + return []; + let filterKind = args.kind ? args.kind.toLowerCase() : null; + let items = []; + let isSymbols = !symbols[0].hasOwnProperty("location"); + if (isSymbols) { + let addSymbols = function(symbols2, level = 0) { + symbols2.sort(sortSymbols); + for (let s of symbols2) { + let kind = getSymbolKind(s.kind); + let location = Location.create(document2.uri, s.selectionRange); + items.push({ + label: [`${"| ".repeat(level)}${s.name}`, `[${kind}]`, `${s.range.start.line + 1}`], + filterText: getFilterText(s, args.kind == "" ? kind : null), + location, + data: { kind } + }); + if (s.children && s.children.length) { + addSymbols(s.children, level + 1); + } + } + }; + addSymbols(symbols); + if (filterKind) { + items = items.filter((o) => o.data.kind.toLowerCase().indexOf(filterKind) == 0); + } + } 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 = getSymbolKind(s.kind); + if (s.name.endsWith(") callback")) + continue; + if (filterKind && !kind.toLowerCase().startsWith(filterKind)) { + continue; + } + if (s.location.uri === void 0) { + s.location.uri = document2.uri; + } + items.push({ + label: [s.name, `[${kind}]`, `${s.location.range.start.line + 1}`], + filterText: getFilterText(s, args.kind == "" ? kind : null), + location: s.location + }); + } + } + return formatListItems(this.alignColumns, items); + } + doHighlight() { + let { nvim } = this; + nvim.pauseNotification(); + nvim.command("syntax match CocOutlineName /\\v\\s?[^\\t]+\\s/ contained containedin=CocOutlineLine", true); + nvim.command("syntax match CocOutlineIndentLine /\\v\\|/ contained containedin=CocOutlineLine,CocOutlineName", 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 CocOutlineIndentLine Comment", true); + nvim.command("highlight default link CocOutlineKind Typedef", true); + nvim.command("highlight default link CocOutlineLine Comment", true); + nvim.resumeNotification(false, true).logError(); + } + async loadCtagsSymbols(document2) { + if (!import_which3.default.sync("ctags", { nothrow: true })) { + return []; + } + let uri = URI.parse(document2.uri); + let extname = import_path27.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 writeFile(escaped, document2.getDocumentContent()); + try { + content = await runCommand(`ctags -f - --excmd=number --language-force=${document2.filetype} ${escaped}`); + } catch (e) { + } + if (!content.trim().length) { + content = await runCommand(`ctags -f - --excmd=number ${escaped}`); + } + content = content.trim(); + if (!content) + return []; + let lines = content.split(/\r?\n/); + let items = []; + for (let line of lines) { + let parts = line.split(" "); + if (parts.length < 4) + continue; + let lnum = Number(parts[2].replace(/;"$/, "")); + let text = document2.getline(lnum - 1); + if (!text) + continue; + let idx = text.indexOf(parts[0]); + let start = idx == -1 ? 0 : idx; + let range = Range.create(lnum - 1, start, lnum - 1, start + parts[0].length); + items.push({ + label: `${parts[0]} [${parts[3]}] ${lnum}`, + filterText: parts[0], + location: Location.create(document2.uri, range), + data: { line: lnum } + }); + } + items.sort((a, b) => a.data.line - b.data.line); + return items; + } + }; + } +}); + +// src/list/source/services.ts +var ServicesList; +var init_services2 = __esm({ + "src/list/source/services.ts"() { + init_services(); + init_basic(); + init_util(); + init_formatting(); + ServicesList = class extends BasicList { + 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_default.toggle(id); + await wait(100); + }, { persist: true, reload: true }); + } + async loadItems(_context) { + let stats = services_default.getServiceStats(); + stats.sort((a, b) => a.id > b.id ? -1 : 1); + return formatListItems(this.alignColumns, stats.map((stat) => { + let prefix = stat.state == "running" ? "*" : " "; + return { + label: [prefix, stat.id, `[${stat.state}]`, 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) => { + }); + } + }; + } +}); + +// src/list/source/sources.ts +function fixWidth(str, width) { + if (str.length > width) { + return str.slice(0, width - 1) + "."; + } + return str + " ".repeat(width - str.length); +} +var logger67, SourcesList; +var init_sources = __esm({ + "src/list/source/sources.ts"() { + init_main(); + init_esm2(); + init_sources2(); + init_workspace(); + init_basic(); + logger67 = require_logger2()("list-sources"); + SourcesList = class extends BasicList { + constructor(nvim) { + super(nvim); + this.defaultAction = "toggle"; + this.description = "registered completion sources"; + this.name = "sources"; + this.addAction("toggle", async (item) => { + let { name: name2 } = item.data; + sources_default.toggleSource(name2); + }, { persist: true, reload: true }); + this.addAction("refresh", async (item) => { + let { name: name2 } = item.data; + await sources_default.refresh(name2); + }, { persist: true, reload: true }); + this.addAction("open", async (item) => { + let { location } = item; + if (location) + await this.jumpTo(location); + }); + } + async loadItems(context) { + let stats = sources_default.sourceStats(); + let filetype = await context.buffer.getOption("filetype"); + let map = workspace_default.env.disabledSources; + let disables = map ? map[filetype] || [] : []; + 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 ? " " : "*"; + if (disables && disables.includes(stat.name)) { + prefix = "-"; + } + let location; + if (stat.filepath) { + location = Location.create(URI.file(stat.filepath).toString(), Range.create(0, 0, 0, 0)); + } + return { + label: `${prefix} ${fixWidth(stat.name, 22)} ${fixWidth("[" + stat.shortcut + "]", 10)} ${fixWidth(stat.triggerCharacters.join(""), 10)} ${fixWidth(stat.priority.toString(), 3)} ${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%25v.*%36v/ contained containedin=CocSourcesLine", true); + nvim.command("syntax match CocSourcesPriority /\\v%46v.*%50v/ 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 CocSourcesPriority Number", true); + nvim.command("highlight default link CocSourcesFileTypes Comment", true); + nvim.command("highlight default link CocSourcesType Statement", true); + nvim.resumeNotification(false, true); + } + }; + } +}); + +// src/list/source/symbols.ts +var import_path28, import_minimatch5, import_vscode_languageserver_protocol69, logger68, Symbols; +var init_symbols = __esm({ + "src/list/source/symbols.ts"() { + import_path28 = __toModule(require("path")); + import_minimatch5 = __toModule(require_minimatch()); + init_esm2(); + init_languages(); + init_workspace(); + init_location(); + init_convert(); + init_fs(); + init_fzy(); + import_vscode_languageserver_protocol69 = __toModule(require_main2()); + init_formatting(); + logger68 = require_logger2()("list-symbols"); + Symbols = class extends LocationList { + 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"; + this.options = [{ + name: "-k, -kind KIND", + description: "Filter symbols by kind.", + hasValue: true + }]; + } + async loadItems(context, token) { + let { input } = context; + this.cwd = context.cwd; + let args = this.parseArguments(context.args); + let filterKind = args.kind ? args.kind.toLowerCase() : ""; + if (!context.options.interactive) { + throw new Error("Symbols only works on interactive mode"); + } + let symbols = await languages_default.getWorkspaceSymbols(input, token); + if (!symbols) { + throw new Error("No workspace symbols provider registered"); + } + let config = this.getConfig(); + let excludes = config.get("excludes", []); + let items = []; + for (let s of symbols) { + let kind = getSymbolKind(s.kind); + if (filterKind && kind.toLowerCase() != filterKind) { + continue; + } + let file = URI.parse(s.location.uri).fsPath; + if (isParentFolder(workspace_default.cwd, file)) { + file = import_path28.default.relative(workspace_default.cwd, file); + } + if (excludes.some((p) => (0, import_minimatch5.default)(file, p))) { + continue; + } + items.push({ + label: [s.name, `[${kind}]`, file], + filterText: `${s.name}`, + location: s.location, + data: { original: s, kind: s.kind, file, score: score2(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 formatListItems(this.alignColumns, items); + } + async resolveItem(item) { + let s = item.data.original; + if (!s) + return null; + let tokenSource = new import_vscode_languageserver_protocol69.CancellationTokenSource(); + let resolved = await languages_default.resolveWorkspaceSymbol(s, tokenSource.token); + if (!resolved) + return null; + let kind = getSymbolKind(resolved.kind); + let file = URI.parse(resolved.location.uri).fsPath; + if (isParentFolder(this.cwd, file)) { + file = import_path28.default.relative(this.cwd, file); + } + return { + label: `${s.name} [${kind}] ${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\\+\\]\\s*\\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) => { + }); + } + }; + } +}); + +// src/list/manager.ts +var import_debounce7, import_vscode_languageserver_protocol70, logger69, mouseKeys, ListManager, manager_default2; +var init_manager3 = __esm({ + "src/list/manager.ts"() { + import_debounce7 = __toModule(require_debounce()); + import_vscode_languageserver_protocol70 = __toModule(require_main2()); + init_events(); + init_extensions2(); + init_util(); + init_workspace(); + init_window(); + init_configuration4(); + init_mappings(); + init_prompt(); + init_session(); + init_commands(); + init_diagnostics(); + init_extensions(); + init_folders(); + init_links(); + init_lists(); + init_location(); + init_outline(); + init_services2(); + init_sources(); + init_symbols(); + logger69 = require_logger2()("list-manager"); + mouseKeys = ["", "", "", "<2-LeftMouse>"]; + ListManager = class { + constructor() { + this.plugTs = 0; + this.sessionsMap = new Map(); + this.disposables = []; + this.listMap = new Map(); + } + init(nvim) { + this.nvim = nvim; + this.config = new ListConfiguration(); + this.prompt = new Prompt(nvim, this.config); + this.mappings = new Mappings(this, nvim, this.config); + let signText = this.config.get("selectedSignText", "*"); + nvim.command(`sign define CocSelected text=${signText} texthl=CocSelectedText linehl=CocSelectedLine`, true); + events_default.on("InputChar", this.onInputChar, this, this.disposables); + let debounced = (0, import_debounce7.default)(async () => { + let session = await this.getCurrentSession(); + if (session) + this.prompt.drawPrompt(); + }, 100); + events_default.on("FocusGained", debounced, null, this.disposables); + events_default.on("WinEnter", (winid) => { + let session = this.getSessionByWinid(winid); + if (session) + this.prompt.start(session.listOptions); + }, null, this.disposables); + events_default.on("WinLeave", (winid) => { + let session = this.getSessionByWinid(winid); + if (session) + this.prompt.cancel(); + }, null, this.disposables); + this.disposables.push({ + dispose: () => { + debounced.clear(); + } + }); + this.prompt.onDidChangeInput(() => { + let { session } = this; + if (!session) + return; + session.onInputChange(); + session.history.filter(); + }); + this.registerList(new LinksList(nvim)); + this.registerList(new LocationList(nvim)); + this.registerList(new Symbols(nvim)); + this.registerList(new Outline(nvim)); + this.registerList(new CommandsList(nvim)); + this.registerList(new ExtensionList(nvim)); + this.registerList(new DiagnosticsList(nvim)); + this.registerList(new SourcesList(nvim)); + this.registerList(new ServicesList(nvim)); + this.registerList(new LinksList2(nvim, this.listMap)); + this.registerList(new FoldList(nvim)); + } + async start(args) { + let res = this.parseArgs(args); + if (!res) + return; + let { name: name2 } = res.list; + let curr = this.sessionsMap.get(name2); + if (curr) + curr.dispose(); + this.prompt.start(res.options); + let session = new ListSession(this.nvim, this.prompt, res.list, res.options, res.listArgs, this.config); + this.sessionsMap.set(name2, session); + this.lastSession = session; + try { + await session.start(args); + } catch (e) { + this.nvim.call("coc#prompt#stop_prompt", ["list"], true); + let msg = e instanceof Error ? e.message : e.toString(); + window_default.showMessage(`Error on "CocList ${name2}": ${msg}`, "error"); + logger69.error(e); + } + } + getSessionByWinid(winid) { + for (let session of this.sessionsMap.values()) { + if (session && session.winid == winid) { + this.lastSession = session; + return session; + } + } + return null; + } + async getCurrentSession() { + let { id } = await this.nvim.window; + for (let session of this.sessionsMap.values()) { + if (session && session.winid == id) { + this.lastSession = session; + return session; + } + } + return null; + } + async resume(name2) { + var _a2; + if (!name2) { + await ((_a2 = this.session) == null ? void 0 : _a2.resume()); + } else { + let session = this.sessionsMap.get(name2); + if (!session) { + window_default.showMessage(`Can't find exists ${name2} list`); + return; + } + await session.resume(); + } + } + async doAction(name2) { + let lastSession = this.lastSession; + if (!lastSession) + return; + await lastSession.doAction(name2); + } + async first(name2) { + let s = this.getSession(name2); + if (s) + await s.first(); + } + async last(name2) { + let s = this.getSession(name2); + if (s) + await s.last(); + } + async previous(name2) { + let s = this.getSession(name2); + if (s) + await s.previous(); + } + async next(name2) { + let s = this.getSession(name2); + if (s) + await s.next(); + } + getSession(name2) { + if (!name2) + return this.session; + return this.sessionsMap.get(name2); + } + async cancel(close = true) { + this.prompt.cancel(); + if (!close) + return; + if (this.session) + await this.session.hide(); + } + reset() { + this.prompt.cancel(); + this.lastSession = void 0; + for (let session of this.sessionsMap.values()) { + session.dispose(); + } + this.sessionsMap.clear(); + this.nvim.call("coc#prompt#stop_prompt", ["list"], true); + } + switchMatcher() { + var _a2; + (_a2 = this.session) == null ? void 0 : _a2.switchMatcher(); + } + async togglePreview() { + let { nvim } = this; + let winid = await nvim.call("coc#list#get_preview", [0]); + if (winid != -1) { + await nvim.call("coc#window#close", [winid]); + await nvim.command("redraw"); + } else { + await this.doAction("preview"); + } + } + async chooseAction() { + let { lastSession } = this; + if (lastSession) + await lastSession.chooseAction(); + } + parseArgs(args) { + let options = []; + let interactive = false; + let autoPreview = false; + let numberSelect = false; + let noQuit = false; + let first = false; + let name2; + let input = ""; + let matcher = "fuzzy"; + let position = "bottom"; + let listArgs = []; + let listOptions = []; + for (let arg of args) { + if (!name2 && arg.startsWith("-")) { + listOptions.push(arg); + } else if (!name2) { + if (!/^\w+$/.test(arg)) { + window_default.showMessage(`Invalid list option: "${arg}"`, "error"); + return null; + } + name2 = arg; + } else { + listArgs.push(arg); + } + } + name2 = name2 || "lists"; + let config = workspace_default.getConfiguration(`list.source.${name2}`); + 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 if (opt == "--first") { + first = true; + } else if (opt == "--no-quit") { + noQuit = true; + } else { + window_default.showMessage(`Invalid option "${opt}" of list`, "error"); + return null; + } + } + let list2 = this.listMap.get(name2); + if (!list2) { + window_default.showMessage(`List ${name2} not found`, "error"); + return null; + } + if (interactive && !list2.interactive) { + window_default.showMessage(`Interactive mode of "${name2}" list not supported`, "error"); + return null; + } + return { + list: list2, + listArgs, + options: { + numberSelect, + autoPreview, + noQuit, + first, + input, + interactive, + matcher, + position, + ignorecase: options.includes("ignore-case") ? true : false, + mode: !options.includes("normal") ? "insert" : "normal", + sort: !options.includes("no-sort") ? true : false + } + }; + } + async onInputChar(session, ch, charmod) { + if (session != "list") + return; + let { mode } = this.prompt; + let now = Date.now(); + if (ch == "" || this.plugTs && now - this.plugTs < 20) { + this.plugTs = now; + return; + } + if (!ch) + return; + if (ch == "") { + await this.cancel(); + return; + } + if (mode == "insert") { + await this.onInsertInput(ch, charmod); + } else { + await this.onNormalInput(ch, charmod); + } + } + async onInsertInput(ch, charmod) { + let { session } = this; + if (!session) + return; + if (mouseKeys.includes(ch)) { + await this.onMouseEvent(ch); + return; + } + let n = await session.doNumberSelect(ch); + if (n) + return; + let done = await this.mappings.doInsertKeymap(ch); + if (done || charmod) + return; + if (ch.startsWith("<") && ch.endsWith(">")) + return; + for (let s of ch) { + let code = s.codePointAt(0); + if (code == 65533) + return; + if (code < 32 || code >= 127 && code <= 159) + return; + await this.prompt.acceptCharacter(s); + } + } + async onNormalInput(ch, _charmod) { + if (mouseKeys.includes(ch)) { + await this.onMouseEvent(ch); + return; + } + let used = await this.mappings.doNormalKeymap(ch); + if (!used) + await this.feedkeys(ch); + } + onMouseEvent(key) { + if (this.session) + return this.session.onMouseEvent(key); + } + async feedkeys(key, remap = true) { + let { nvim } = this; + key = key.startsWith("<") && key.endsWith(">") ? `\\${key}` : key; + await nvim.call("coc#prompt#stop_prompt", ["list"]); + await nvim.call("eval", [`feedkeys("${key}", "${remap ? "i" : "in"}")`]); + this.prompt.start(); + } + async command(command) { + let { nvim } = this; + await nvim.call("coc#prompt#stop_prompt", ["list"]); + await nvim.command(command); + this.prompt.start(); + } + async normal(command, bang = true) { + let { nvim } = this; + await nvim.call("coc#prompt#stop_prompt", ["list"]); + await nvim.command(`normal${bang ? "!" : ""} ${command}`); + this.prompt.start(); + } + async call(fname) { + if (this.session) + return await this.session.call(fname); + } + get session() { + return this.lastSession; + } + registerList(list2) { + const { name: name2 } = list2; + let exists = this.listMap.get(name2); + if (this.listMap.has(name2)) { + if (exists) { + if (typeof exists.dispose == "function") { + exists.dispose(); + } + this.listMap.delete(name2); + } + window_default.showMessage(`list "${name2}" recreated.`); + } + this.listMap.set(name2, list2); + let config = workspace_default.getConfiguration(`list.source.${name2}`); + let defaultAction = config.get("defaultAction"); + if (defaultAction && list2.actions.find((o) => o.name == defaultAction)) { + list2.defaultAction = defaultAction; + } + extensions_default.addSchemeProperty(`list.source.${name2}.defaultAction`, { + type: "string", + default: null, + description: `Default default action of "${name2}" list.` + }); + extensions_default.addSchemeProperty(`list.source.${name2}.defaultOptions`, { + type: "array", + default: list2.interactive ? ["--interactive"] : [], + description: `Default list options of "${name2}" 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", + "--first", + "--no-quit" + ] + } + }); + extensions_default.addSchemeProperty(`list.source.${name2}.defaultArgs`, { + type: "array", + default: [], + description: `Default argument list of "${name2}" list, only used when list argument is empty.`, + uniqueItems: true, + items: { type: "string" } + }); + return import_vscode_languageserver_protocol70.Disposable.create(() => { + if (typeof list2.dispose == "function") { + list2.dispose(); + } + this.listMap.delete(name2); + }); + } + get names() { + return Array.from(this.listMap.keys()); + } + get descriptions() { + let d = {}; + for (let name2 of this.listMap.keys()) { + let list2 = this.listMap.get(name2); + d[name2] = list2.description; + } + return d; + } + async loadItems(name2) { + let args = [name2]; + let res = this.parseArgs(args); + if (!res) + return; + let { list: list2, options, listArgs } = res; + let source = new import_vscode_languageserver_protocol70.CancellationTokenSource(); + let token = source.token; + let arr = await this.nvim.eval('[win_getid(),bufnr("%")]'); + let items = await list2.loadItems({ + options, + args: listArgs, + input: "", + cwd: workspace_default.cwd, + window: this.nvim.createWindow(arr[0]), + buffer: this.nvim.createBuffer(arr[1]), + listWindow: null + }, token); + return items; + } + toggleMode() { + let lastSession = this.lastSession; + if (lastSession) + lastSession.toggleMode(); + } + get isActivated() { + var _a2; + return ((_a2 = this.session) == null ? void 0 : _a2.winid) != null; + } + stop() { + let lastSession = this.lastSession; + if (lastSession) + lastSession.stop(); + } + dispose() { + for (let session of this.sessionsMap.values()) { + session.dispose(); + } + this.sessionsMap.clear(); + if (this.config) { + this.config.dispose(); + } + this.lastSession = void 0; + disposeAll(this.disposables); + } + }; + manager_default2 = new ListManager(); + } +}); + +// src/snippets/string.ts +var SnippetString; +var init_string2 = __esm({ + "src/snippets/string.ts"() { + SnippetString = class { + constructor(value) { + this._tabstop = 1; + this.value = value || ""; + } + static isSnippetString(thing) { + if (thing instanceof SnippetString) { + return true; + } + if (!thing) { + return false; + } + return typeof thing.value === "string"; + } + static _escape(value) { + return value.replace(/\$|}|\\/g, "\\$&"); + } + appendText(str) { + this.value += SnippetString._escape(str); + return this; + } + appendTabstop(num = this._tabstop++) { + this.value += "$"; + this.value += num; + return this; + } + appendPlaceholder(value, num = this._tabstop++) { + if (typeof value === "function") { + const nested = new SnippetString(); + nested._tabstop = this._tabstop; + value(nested); + this._tabstop = nested._tabstop; + value = nested.value; + } else { + value = SnippetString._escape(value); + } + this.value += "${"; + this.value += num; + this.value += ":"; + this.value += value; + this.value += "}"; + return this; + } + appendChoice(values, num = this._tabstop++) { + const value = values.map((s) => s.replace(/\$|}|\\|,/g, "\\$&")).join(","); + this.value += "${"; + this.value += num; + this.value += "|"; + this.value += value; + this.value += "|}"; + return this; + } + appendVariable(name2, defaultValue) { + if (typeof defaultValue === "function") { + const nested = new SnippetString(); + nested._tabstop = this._tabstop; + defaultValue(nested); + this._tabstop = nested._tabstop; + defaultValue = nested.value; + } else if (typeof defaultValue === "string") { + defaultValue = defaultValue.replace(/\$|}/g, "\\$&"); + } + this.value += "${"; + this.value += name2; + if (defaultValue) { + this.value += ":"; + this.value += defaultValue; + } + this.value += "}"; + return this; + } + }; + } +}); + +// src/tree/index.ts +var init_tree = __esm({ + "src/tree/index.ts"() { + init_TreeItem(); + } +}); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + BasicList: () => BasicList, + Buffer: () => import_neovim.Buffer, + CancellationToken: () => import_vscode_languageserver_protocol71.CancellationToken, + CancellationTokenSource: () => import_vscode_languageserver_protocol71.CancellationTokenSource, + ClientState: () => ClientState, + CloseAction: () => CloseAction, + CodeActionKind: () => import_vscode_languageserver_protocol71.CodeActionKind, + CompletionItemKind: () => import_vscode_languageserver_protocol71.CompletionItemKind, + CompletionTriggerKind: () => import_vscode_languageserver_protocol71.CompletionTriggerKind, + ConfigurationTarget: () => ConfigurationTarget, + Diagnostic: () => import_vscode_languageserver_protocol71.Diagnostic, + DiagnosticSeverity: () => import_vscode_languageserver_protocol71.DiagnosticSeverity, + DiagnosticTag: () => import_vscode_languageserver_protocol71.DiagnosticTag, + Disposable: () => import_vscode_languageserver_protocol71.Disposable, + DocumentHighlightKind: () => import_vscode_languageserver_protocol71.DocumentHighlightKind, + Emitter: () => import_vscode_languageserver_protocol71.Emitter, + ErrorAction: () => ErrorAction, + Event: () => import_vscode_languageserver_protocol71.Event, + FileChangeType: () => import_vscode_languageserver_protocol71.FileChangeType, + FileType: () => FileType, + FloatFactory: () => FloatFactory, + Highligher: () => Highlighter, + InsertTextFormat: () => import_vscode_languageserver_protocol71.InsertTextFormat, + LanguageClient: () => LanguageClient, + Location: () => import_vscode_languageserver_protocol71.Location, + LocationLink: () => import_vscode_languageserver_protocol71.LocationLink, + MarkupKind: () => import_vscode_languageserver_protocol71.MarkupKind, + MessageLevel: () => MessageLevel, + MessageTransports: () => MessageTransports, + Mru: () => Mru, + Mutex: () => Mutex, + Neovim: () => import_neovim.Neovim, + NotificationType: () => import_vscode_languageserver_protocol71.NotificationType, + NotificationType0: () => import_vscode_languageserver_protocol71.NotificationType0, + NullLogger: () => NullLogger, + PatternType: () => PatternType, + Position: () => import_vscode_languageserver_protocol71.Position, + ProgressType: () => import_vscode_languageserver_protocol71.ProgressType, + Range: () => import_vscode_languageserver_protocol71.Range, + RequestType: () => import_vscode_languageserver_protocol71.RequestType, + RequestType0: () => import_vscode_languageserver_protocol71.RequestType0, + RevealOutputChannelOn: () => RevealOutputChannelOn, + ServiceStat: () => ServiceStat, + SettingMonitor: () => SettingMonitor, + SignatureHelpTriggerKind: () => import_vscode_languageserver_protocol71.SignatureHelpTriggerKind, + SnippetString: () => SnippetString, + SourceType: () => SourceType, + State: () => State2, + SymbolKind: () => import_vscode_languageserver_protocol71.SymbolKind, + TextDocumentFeature: () => TextDocumentFeature, + TextEdit: () => import_vscode_languageserver_protocol71.TextEdit, + TransportKind: () => TransportKind, + TreeItem: () => TreeItem, + TreeItemCollapsibleState: () => TreeItemCollapsibleState, + Uri: () => URI, + Watchman: () => Watchman, + Window: () => import_neovim.Window, + ansiparse: () => ansiparse, + commands: () => commands_default, + concurrent: () => concurrent, + diagnosticManager: () => manager_default, + disposeAll: () => disposeAll, + download: () => download, + events: () => events_default, + executable: () => executable, + extensions: () => extensions_default, + fetch: () => fetch, + isRunning: () => isRunning, + languages: () => languages_default, + listManager: () => manager_default2, + runCommand: () => runCommand, + services: () => services_default, + snippetManager: () => manager_default3, + sources: () => sources_default, + wait: () => wait, + watchFile: () => watchFile, + window: () => window_default, + workspace: () => workspace_default +}); +var import_neovim, import_vscode_languageserver_protocol71; +var init_src = __esm({ + "src/index.ts"() { + init_commands2(); + init_events(); + init_languages(); + init_mru(); + init_floatFactory(); + init_fetch(); + init_download(); + init_highligher(); + init_services(); + init_sources2(); + init_workspace(); + init_window(); + init_extensions2(); + init_manager3(); + init_manager4(); + init_string2(); + init_manager(); + init_ansiparse(); + init_watchman(); + init_basic(); + init_mutex(); + init_esm2(); + import_neovim = __toModule(require_lib6()); + import_vscode_languageserver_protocol71 = __toModule(require_main2()); + init_types(); + init_language_client(); + init_util(); + init_tree(); + } +}); + +// src/util/factory.ts +function removedGlobalStub(name2) { + return () => { + throw new Error(`process.${name2}() is not allowed in extension sandbox`); + }; +} +function makeRequireFunction() { + const req = (p) => { + if (p === "coc.nvim") { + return init_src(), src_exports; + } + return this.require(p); + }; + req.resolve = (request2) => Module._resolveFilename(request2, this); + req.main = process.mainModule; + req.extensions = Module._extensions; + req.cache = Module._cache; + return req; +} +function compileInSandbox(sandbox) { + return function(content, filename) { + const require2 = makeRequireFunction.call(this); + const dirname3 = import_path29.default.dirname(filename); + const newContent = content.replace(/^\#\!.*/, ""); + const wrapper = Module.wrap(newContent); + const compiledWrapper = vm.runInContext(wrapper, sandbox, { filename }); + const args = [this.exports, require2, this, filename, dirname3]; + return compiledWrapper.apply(this.exports, args); + }; +} +function createSandbox(filename, logger113) { + const module2 = new Module(filename); + module2.paths = Module._nodeModulePaths(filename); + const sandbox = vm.createContext({ + module: module2, + Buffer, + console: { + debug: (...args) => { + logger113.debug.apply(logger113, args); + }, + log: (...args) => { + logger113.info.apply(logger113, args); + }, + error: (...args) => { + logger113.error.apply(logger113, args); + }, + info: (...args) => { + logger113.info.apply(logger113, args); + }, + warn: (...args) => { + logger113.warn.apply(logger113, args); + } + } + }); + 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; + }; + sandbox.process = new process.constructor(); + for (let key of Object.keys(process)) { + sandbox.process[key] = process[key]; + } + REMOVED_GLOBALS.forEach((name2) => { + sandbox.process[name2] = removedGlobalStub(name2); + }); + sandbox.process["chdir"] = () => { + }; + 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; +} +function createExtension(id, filename, isEmpty2 = false) { + if (isEmpty2 || !import_fs27.default.existsSync(filename)) + return { + activate: () => { + }, + deactivate: null + }; + const sandbox = createSandbox(filename, createLogger(`extension:${id}`)); + delete Module._cache[require.resolve(filename)]; + const defaultImport = sandbox.require(filename); + const activate = defaultImport && defaultImport.activate || defaultImport; + if (typeof activate !== "function") { + return { activate: () => { + }, deactivate: null }; + } + return { + activate, + deactivate: typeof defaultImport.deactivate === "function" ? defaultImport.deactivate : null + }; +} +var import_fs27, import_path29, vm, createLogger, logger70, Module, REMOVED_GLOBALS; +var init_factory = __esm({ + "src/util/factory.ts"() { + import_fs27 = __toModule(require("fs")); + import_path29 = __toModule(require("path")); + vm = __toModule(require("vm")); + init_lodash(); + createLogger = require_logger2(); + logger70 = createLogger("util-factoroy"); + Module = require("module"); + REMOVED_GLOBALS = [ + "reallyExit", + "abort", + "umask", + "setuid", + "setgid", + "setgroups", + "_fatalException", + "exit", + "kill" + ]; + } +}); + +// src/extensions.ts +var import_debounce8, import_fs_extra9, import_isuri2, import_path30, import_semver2, import_vscode_languageserver_protocol72, import_which4, import_extensions7, createLogger2, logger71, ExtensionType, Extensions, extensions_default; +var init_extensions2 = __esm({ + "src/extensions.ts"() { + import_debounce8 = __toModule(require_debounce()); + init_main3(); + import_fs_extra9 = __toModule(require_lib5()); + import_isuri2 = __toModule(require_isuri()); + import_path30 = __toModule(require("path")); + import_semver2 = __toModule(require_semver2()); + import_vscode_languageserver_protocol72 = __toModule(require_main2()); + init_esm2(); + import_which4 = __toModule(require_which()); + init_commands2(); + init_events(); + init_db(); + init_floatFactory(); + init_installBuffer(); + init_installer(); + init_memos(); + init_util(); + init_array(); + import_extensions7 = __toModule(require_extensions()); + init_factory(); + init_fs(); + init_is(); + init_watchman(); + init_workspace(); + init_window(); + createLogger2 = require_logger2(); + logger71 = createLogger2("extensions"); + (function(ExtensionType2) { + ExtensionType2[ExtensionType2["Global"] = 0] = "Global"; + ExtensionType2[ExtensionType2["Local"] = 1] = "Local"; + ExtensionType2[ExtensionType2["SingleFile"] = 2] = "SingleFile"; + ExtensionType2[ExtensionType2["Internal"] = 3] = "Internal"; + })(ExtensionType || (ExtensionType = {})); + Extensions = class { + constructor() { + this.extensions = new Map(); + this.disabled = new Set(); + this._onDidLoadExtension = new import_vscode_languageserver_protocol72.Emitter(); + this._onDidActiveExtension = new import_vscode_languageserver_protocol72.Emitter(); + this._onDidUnloadExtension = new import_vscode_languageserver_protocol72.Emitter(); + this._additionalSchemes = {}; + this.activated = false; + this.disposables = []; + this.ready = true; + this.onDidLoadExtension = this._onDidLoadExtension.event; + this.onDidActiveExtension = this._onDidActiveExtension.event; + this.onDidUnloadExtension = this._onDidUnloadExtension.event; + let folder = global.hasOwnProperty("__TEST__") ? import_path30.default.join(__dirname, "__tests__") : process.env.COC_DATA_HOME; + let root = this.root = import_path30.default.join(folder, "extensions"); + if (!import_fs_extra9.default.existsSync(root)) { + import_fs_extra9.default.mkdirpSync(root); + } + let jsonFile = import_path30.default.join(root, "package.json"); + if (!import_fs_extra9.default.existsSync(jsonFile)) { + import_fs_extra9.default.writeFileSync(jsonFile, '{"dependencies":{}}', "utf8"); + } + let filepath = import_path30.default.join(root, "db.json"); + this.db = new DB(filepath); + } + get outputChannel() { + if (this._outputChannel) + return this._outputChannel; + this._outputChannel = window_default.createOutputChannel("extensions"); + return this._outputChannel; + } + async init() { + let extensionObj = this.db.fetch("extension") || {}; + let keys = Object.keys(extensionObj); + for (let key of keys) { + if (extensionObj[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.map((o) => o.id)); + stats = stats.concat(localStats); + this.memos = new Memos(import_path30.default.resolve(this.root, "../memos.json")); + stats.map((stat) => { + let extensionType = stat.isLocal ? 1 : 0; + try { + this.createExtension(stat.root, stat.packageJSON, extensionType); + } catch (e) { + logger71.error(`Error on create ${stat.root}:`, e); + } + }); + await this.loadFileExtensions(); + commands_default.register({ + id: "extensions.forceUpdateAll", + execute: async () => { + let arr = await this.cleanExtensions(); + logger71.info(`Force update extensions: ${arr}`); + await this.installExtensions(arr); + } + }, false, "remove all global extensions and install them"); + workspace_default.onDidRuntimePathChange(async (paths) => { + for (let p of paths) { + if (p && this.checkDirectory(p) === true) { + await this.loadExtension(p); + } + } + }, null, this.disposables); + } + activateExtensions() { + this.activated = true; + for (let item of this.extensions.values()) { + let { id, packageJSON } = item.extension; + this.setupActiveEvents(id, packageJSON).logError(); + } + let floatFactory = new FloatFactory(workspace_default.nvim); + events_default.on("CursorMoved", (0, import_debounce8.debounce)(async (bufnr) => { + if (this.installBuffer && bufnr == this.installBuffer.bufnr) { + let lnum = await workspace_default.nvim.call("line", ["."]); + let msgs = this.installBuffer.getMessages(lnum - 1); + let docs = msgs && msgs.length ? [{ content: msgs.join("\n"), filetype: "txt" }] : []; + await floatFactory.show(docs, { modes: ["n"] }); + } + }, 500)); + if (global.hasOwnProperty("__TEST__")) + return; + this.checkExtensions().logError(); + let config = workspace_default.getConfiguration("coc.preferences"); + let interval = config.get("extensionUpdateCheck", "never"); + let silent = config.get("silentAutoupdate", true); + 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.outputChannel.appendLine("Start auto update..."); + this.updateExtensions(false, silent).logError(); + } + } + async updateExtensions(sync, silent = false) { + if (!this.npm) + return; + let lockedList = await this.getLockedList(); + let stats = await this.globalExtensionStats(); + stats = stats.filter((o) => ![...lockedList, ...this.disabled].includes(o.id)); + this.db.push("lastUpdate", Date.now()); + if (silent) { + window_default.showMessage("Updating extensions, checkout output:///extensions for details.", "more"); + } + let installBuffer = this.installBuffer = new InstallBuffer(true, sync, silent ? this.outputChannel : void 0); + installBuffer.setExtensions(stats.map((o) => o.id)); + await installBuffer.show(workspace_default.nvim); + let createInstaller = createInstallerFactory(this.npm, this.modulesFolder); + let fn = (stat) => { + let { id } = stat; + installBuffer.startProgress([id]); + let url = stat.exotic ? stat.uri : null; + let installer = createInstaller(id); + installer.on("message", (msg, isProgress) => { + installBuffer.addMessage(id, msg, isProgress); + }); + return installer.update(url).then((directory) => { + installBuffer.finishProgress(id, true); + if (directory) { + this.loadExtension(directory).logError(); + } + }, (err) => { + installBuffer.addMessage(id, err.message); + installBuffer.finishProgress(id, false); + }); + }; + await concurrent(stats, fn, silent ? 1 : 3); + } + async checkExtensions() { + let { globalExtensions } = workspace_default.env; + if (globalExtensions && globalExtensions.length) { + let names = this.filterGlobalExtensions(globalExtensions); + this.installExtensions(names).logError(); + } + } + get installer() { + return createInstallerFactory(this.npm, this.modulesFolder); + } + async installExtensions(list2 = []) { + let { npm } = this; + if (!npm || !list2.length) + return; + list2 = distinct(list2); + let installBuffer = this.installBuffer = new InstallBuffer(); + installBuffer.setExtensions(list2); + await installBuffer.show(workspace_default.nvim); + let createInstaller = createInstallerFactory(this.npm, this.modulesFolder); + let fn = (key) => { + installBuffer.startProgress([key]); + let installer = createInstaller(key); + installer.on("message", (msg, isProgress) => { + installBuffer.addMessage(key, msg, isProgress); + }); + return installer.install().then((name2) => { + installBuffer.finishProgress(key, true); + let directory = import_path30.default.join(this.modulesFolder, name2); + this.loadExtension(directory).logError(); + }, (err) => { + installBuffer.addMessage(key, err.message); + installBuffer.finishProgress(key, false); + logger71.error(`Error on install ${key}`, err); + }); + }; + await concurrent(list2, fn); + } + getMissingExtensions() { + let json = this.loadJson() || { dependencies: {} }; + let ids = []; + for (let key of Object.keys(json.dependencies)) { + let folder = import_path30.default.join(this.modulesFolder, key); + if (!import_fs_extra9.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_default.getConfiguration("npm").get("binPath", "npm"); + npm = workspace_default.expand(npm); + for (let exe of [npm, "yarnpkg", "yarn", "npm"]) { + try { + let res = import_which4.default.sync(exe); + return res; + } catch (e) { + continue; + } + } + window_default.showMessage(`Can't find npm or yarn in your $PATH`, "error"); + return null; + } + get all() { + return Array.from(this.extensions.values()).map((o) => o.extension).filter((o) => !this.isDisabled(o.id)); + } + getExtension(id) { + return this.extensions.get(id); + } + getExtensionState(id) { + let disabled = this.isDisabled(id); + if (disabled) + return "disabled"; + let item = this.extensions.get(id); + if (!item) + return "unknown"; + let { extension } = item; + return extension.isActive ? "activated" : "loaded"; + } + async getExtensionStates() { + let localStats = await this.localExtensionStats([]); + let globalStats = await this.globalExtensionStats(); + return localStats.concat(globalStats.filter((o) => localStats.find((s) => s.id == o.id) == null)); + } + async getLockedList() { + let obj = await this.db.fetch("extension"); + obj = obj || {}; + return Object.keys(obj).filter((id) => 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") { + await this.deactivate(id); + } + let key = `extension.${id}.disabled`; + this.db.push(key, state == "disabled" ? false : true); + if (state != "disabled") { + this.disabled.add(id); + await this.unloadExtension(id); + } else { + this.disabled.delete(id); + let folder = import_path30.default.join(this.modulesFolder, id); + if (import_fs_extra9.default.existsSync(folder)) { + await this.loadExtension(folder); + } + } + await wait(200); + } + async reloadExtension(id) { + let item = this.extensions.get(id); + if (!item) { + window_default.showMessage(`Extension ${id} not registered`, "error"); + return; + } + if (item.type == 3) { + window_default.showMessage(`Can't reload internal extension "${item.id}"`, "warning"); + return; + } + if (item.type == 2) { + await this.loadExtensionFile(item.filepath); + } else if (item.directory) { + await this.loadExtension(item.directory); + } else { + window_default.showMessage(`Can't reload extension ${item.id}`, "warning"); + } + } + async cleanExtensions() { + let dir = this.modulesFolder; + if (!import_fs_extra9.default.existsSync(dir)) + return []; + let ids = this.globalExtensions; + let res = []; + for (let id of ids) { + let directory = import_path30.default.join(dir, id); + let stat = await import_fs_extra9.default.lstat(directory); + if (!stat || stat && stat.isSymbolicLink()) + continue; + await this.unloadExtension(id); + await import_fs_extra9.default.remove(directory); + res.push(id); + } + return res; + } + async uninstallExtension(ids) { + try { + if (!ids.length) + return; + let [globals2, filtered] = splitArray(ids, (id) => this.globalExtensions.includes(id)); + if (filtered.length) { + window_default.showMessage(`Extensions ${filtered} not global extensions, can't uninstall!`, "warning"); + } + let json = this.loadJson() || { dependencies: {} }; + for (let id of globals2) { + await this.unloadExtension(id); + delete json.dependencies[id]; + let folder = import_path30.default.join(this.modulesFolder, id); + if (import_fs_extra9.default.existsSync(folder)) { + await import_fs_extra9.default.remove(folder); + } + } + const sortedObj = { dependencies: {} }; + Object.keys(json.dependencies).sort().forEach((k) => { + sortedObj.dependencies[k] = json.dependencies[k]; + }); + let jsonFile = import_path30.default.join(this.root, "package.json"); + import_fs_extra9.default.writeFileSync(jsonFile, JSON.stringify(sortedObj, null, 2), { encoding: "utf8" }); + window_default.showMessage(`Removed: ${globals2.join(" ")}`); + } catch (e) { + window_default.showMessage(`Uninstall failed: ${e.message}`, "error"); + } + } + isDisabled(id) { + return this.disabled.has(id); + } + has(id) { + return this.extensions.has(id); + } + isActivated(id) { + let item = this.extensions.get(id); + if (item && item.extension.isActive) { + return true; + } + return false; + } + async loadExtension(folder) { + try { + let parentFolder = import_path30.default.dirname(folder); + let isLocal = import_path30.default.normalize(parentFolder) != import_path30.default.normalize(this.modulesFolder); + let jsonFile = import_path30.default.join(folder, "package.json"); + let packageJSON = JSON.parse(import_fs_extra9.default.readFileSync(jsonFile, "utf8")); + let { name: name2 } = packageJSON; + if (this.isDisabled(name2)) + return false; + await this.unloadExtension(name2); + this.createExtension(folder, Object.freeze(packageJSON), isLocal ? 1 : 0); + return true; + } catch (e) { + window_default.showMessage(`Error on load extension from "${folder}": ${e.message}`, "error"); + logger71.error(`Error on load extension from ${folder}`, e); + return false; + } + } + async loadFileExtensions() { + if (!process.env.COC_VIMCONFIG) + return; + let folder = import_path30.default.join(process.env.COC_VIMCONFIG, "coc-extensions"); + if (!import_fs_extra9.default.existsSync(folder)) + return; + let files = await import_fs_extra9.default.readdir(folder); + files = files.filter((f) => f.endsWith(".js")); + for (let file of files) { + await this.loadExtensionFile(import_path30.default.join(folder, file)); + } + } + loadedExtensions() { + return Array.from(this.extensions.keys()); + } + async watchExtension(id) { + let item = this.extensions.get(id); + if (!item) { + window_default.showMessage(`extension ${id} not found`, "error"); + return; + } + if (id.startsWith("single-")) { + window_default.showMessage(`watching ${item.filepath}`); + this.disposables.push(watchFile(item.filepath, async () => { + await this.loadExtensionFile(item.filepath); + window_default.showMessage(`reloaded ${id}`); + })); + } else { + let watchmanPath = workspace_default.getWatchmanPath(); + if (!watchmanPath) { + window_default.showMessage("watchman not found", "error"); + return; + } + let client = await Watchman.createClient(watchmanPath, item.directory); + if (!client) { + window_default.showMessage(`Can't create watchman client, check output:///watchman`); + return; + } + window_default.showMessage(`watching ${item.directory}`); + this.disposables.push(client); + client.subscribe("**/*.js", async () => { + await this.reloadExtension(id); + window_default.showMessage(`reloaded ${id}`); + }).then((disposable) => { + this.disposables.push(disposable); + }, (e) => { + logger71.error(e); + }); + } + } + async loadExtensionFile(filepath) { + let filename = import_path30.default.basename(filepath); + let basename = import_path30.default.basename(filepath, ".js"); + let name2 = "single-" + basename; + if (this.isDisabled(name2)) + return; + let root = import_path30.default.dirname(filepath); + let packageJSON = { + name: name2, + main: filename, + engines: { coc: "^0.0.79" } + }; + let confpath = import_path30.default.join(root, basename + ".json"); + let stat = await statAsync(confpath); + if (stat && stat.isFile()) { + let content = await readFile(confpath, "utf8"); + let obj = JSON.parse(content); + if (obj) { + let attrs = ["activationEvents", "contributes"]; + for (const attr of attrs) { + if (obj[attr]) { + packageJSON[attr] = obj[attr]; + } + } + } + } + await this.unloadExtension(name2); + this.createExtension(root, packageJSON, 2); + } + async activate(id) { + if (this.isDisabled(id)) { + throw new Error(`Extension ${id} is disabled!`); + } + let item = this.extensions.get(id); + if (!item) { + throw new Error(`Extension ${id} not registered!`); + } + let { extension } = item; + if (extension.isActive) + return true; + await Promise.resolve(extension.activate()); + if (extension.isActive) { + this._onDidActiveExtension.fire(extension); + return true; + } + return false; + } + async deactivate(id) { + let item = this.extensions.get(id); + if (!item) + return false; + await Promise.resolve(item.deactivate()); + return true; + } + async call(id, method, args) { + let item = this.extensions.get(id); + if (!item) + throw new Error(`extension ${id} not registered`); + let { extension } = item; + if (!extension.isActive) { + await this.activate(id); + } + let { exports: exports2 } = extension; + if (!exports2 || !exports2.hasOwnProperty(method)) { + throw new Error(`method ${method} not found on extension ${id}`); + } + return await Promise.resolve(exports2[method].apply(null, args)); + } + getExtensionApi(id) { + let item = this.extensions.get(id); + if (!item) + return null; + let { extension } = item; + return extension.isActive ? extension.exports : null; + } + registerExtension(extension, deactivate) { + let { id, packageJSON } = extension; + this.extensions.set(id, { id, type: 3, 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_default.configurations.extendsDefaults(props); + } + } + this._onDidLoadExtension.fire(extension); + this.setupActiveEvents(id, packageJSON).logError(); + } + 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 { modulesFolder } = this; + let res = await Promise.all(Object.keys(json.dependencies).map((key) => new Promise(async (resolve3) => { + try { + let val = json.dependencies[key]; + let root = import_path30.default.join(modulesFolder, key); + let res2 = this.checkDirectory(root); + if (res2 instanceof Error) { + window_default.showMessage(`Unable to load global extension at ${root}: ${res2.message}`, "error"); + logger71.error(`Error on load ${root}`, res2); + return resolve3(null); + } + let content = await readFile(import_path30.default.join(root, "package.json"), "utf8"); + root = await import_fs_extra9.default.realpath(root); + let obj = JSON.parse(content); + let version2 = obj ? obj.version || "" : ""; + let description = obj ? obj.description || "" : ""; + let uri = import_isuri2.default.isValid(val) ? val : ""; + resolve3({ + id: key, + isLocal: false, + version: version2, + description, + exotic: /^https?:/.test(val), + uri: uri.replace(/\.git(#master)?$/, ""), + root, + state: this.getExtensionState(key), + packageJSON: Object.freeze(obj) + }); + } catch (e) { + logger71.error(e); + resolve3(null); + } + }))); + return res.filter((info) => info != null); + } + async localExtensionStats(excludes) { + let runtimepath = await workspace_default.nvim.eval("&runtimepath"); + let paths = runtimepath.split(","); + let res = await Promise.all(paths.map((root) => new Promise(async (resolve3) => { + try { + let res2 = this.checkDirectory(root); + if (res2 !== true) + return resolve3(null); + let jsonFile = import_path30.default.join(root, "package.json"); + let content = await readFile(jsonFile, "utf8"); + let obj = JSON.parse(content); + let exist = this.extensions.get(obj.name); + if (exist && !exist.isLocal) { + logger71.info(`Extension "${obj.name}" in runtimepath already loaded.`); + return resolve3(null); + } + if (excludes.includes(obj.name)) { + logger71.info(`Skipped load vim plugin from "${root}", "${obj.name}" already global extension.`); + return resolve3(null); + } + let version2 = obj ? obj.version || "" : ""; + let description = obj ? obj.description || "" : ""; + resolve3({ + id: obj.name, + isLocal: true, + version: version2, + description, + exotic: false, + root, + state: this.getExtensionState(obj.name), + packageJSON: Object.freeze(obj) + }); + } catch (e) { + logger71.error(e); + resolve3(null); + } + }))); + return res.filter((info) => info != null); + } + loadJson() { + let { root } = this; + let jsonFile = import_path30.default.join(root, "package.json"); + if (!import_fs_extra9.default.existsSync(jsonFile)) + return null; + let errors = []; + let content = import_fs_extra9.default.readFileSync(jsonFile, "utf8"); + let data = parse3(content, errors, { allowTrailingComma: true }); + if (errors && errors.length > 0) { + window_default.showMessage(`Error on parse ${jsonFile}`, "error"); + workspace_default.nvim.call("coc#util#open_file", ["edit", jsonFile], true); + } + return data; + } + get schemes() { + return this._additionalSchemes; + } + addSchemeProperty(key, def) { + this._additionalSchemes[key] = def; + workspace_default.configurations.extendsDefaults({ [key]: def.default }); + } + async setupActiveEvents(id, packageJSON) { + let { activationEvents } = packageJSON; + if (!this.canActivate(id)) + return; + if (!activationEvents || Array.isArray(activationEvents) && activationEvents.includes("*")) { + await this.activate(id).catch((e) => { + window_default.showMessage(`Error on activate extension ${id}: ${e.message}`); + this.outputChannel.appendLine(`Error on activate extension ${id}. +${e.message} + ${e.stack}`); + }); + return; + } + let disposables = []; + let active = () => { + disposeAll(disposables); + return new Promise((resolve3) => { + if (!this.canActivate(id)) { + this.outputChannel.appendLine(`Extension ${id} is disabled or not loaded.`); + return resolve3(); + } + let timer = setTimeout(() => { + this.outputChannel.appendLine(`Extension ${id} activate cost more than 1s`); + resolve3(); + }, 1e3); + this.activate(id).then(() => { + clearTimeout(timer); + resolve3(); + }, (e) => { + clearTimeout(timer); + window_default.showMessage(`Error on activate extension ${id}: ${e.message}`); + this.outputChannel.appendLine(`Error on activate extension ${id}:${e.message} + ${e.stack}`); + resolve3(); + }); + }); + }; + for (let eventName of activationEvents) { + let parts = eventName.split(":"); + let ev = parts[0]; + if (ev == "onLanguage") { + if (workspace_default.filetypes.has(parts[1])) { + await active(); + return; + } + workspace_default.onDidOpenTextDocument((document2) => { + if (document2.languageId == parts[1]) { + void active(); + } + }, null, disposables); + } else if (ev == "onCommand") { + commands_default.onCommandList.push(parts[1]); + events_default.on("Command", async (command) => { + if (command == parts[1]) { + await active(); + await wait(500); + } + }, null, disposables); + } else if (ev == "workspaceContains") { + let check = async () => { + let folders = workspace_default.workspaceFolders.map((o) => URI.parse(o.uri).fsPath); + for (let folder of folders) { + if (inDirectory(folder, parts[1].split(/\s+/))) { + await active(); + return true; + } + } + }; + let res = await check(); + if (res) + return; + workspace_default.onDidChangeWorkspaceFolders(check, null, disposables); + } else if (ev == "onFileSystem") { + for (let doc of workspace_default.documents) { + let u = URI.parse(doc.uri); + if (u.scheme == parts[1]) { + await active(); + return; + } + } + workspace_default.onDidOpenTextDocument((document2) => { + let u = URI.parse(document2.uri); + if (u.scheme == parts[1]) { + void active(); + } + }, null, disposables); + } else { + window_default.showMessage(`Unsupported event ${eventName} of ${id}`, "error"); + } + } + } + createExtension(root, packageJSON, type) { + let id = packageJSON.name; + let isActive = false; + let result; + let filename = import_path30.default.join(root, packageJSON.main || "index.js"); + let ext; + let subscriptions = []; + let exports2; + let extension = { + activate: () => { + if (result) + return result; + let context = { + subscriptions, + extensionPath: root, + globalState: this.memos.createMemento(`${id}|global`), + workspaceState: this.memos.createMemento(`${id}|${workspace_default.rootPath}`), + asAbsolutePath: (relativePath) => import_path30.default.join(root, relativePath), + storagePath: import_path30.default.join(this.root, `${id}-data`), + logger: createLogger2(id) + }; + if (!ext) { + try { + let isEmpty2 = !(packageJSON.engines || {}).hasOwnProperty("coc"); + ext = createExtension(id, filename, isEmpty2); + } catch (e) { + logger71.error(`Error on createExtension ${id} from ${filename}`, e); + return; + } + } + result = new Promise((resolve3, reject) => { + try { + Promise.resolve(ext.activate(context)).then((res) => { + isActive = true; + exports2 = res; + resolve3(res); + }, (e) => { + logger71.error(`Error on active extension ${id}: ${e.message}`, e); + reject(e); + }); + } catch (e) { + logger71.error(`Error on active extension ${id}: ${e.stack}`, e); + reject(e); + } + }); + return result; + } + }; + Object.defineProperties(extension, { + id: { + get: () => id, + enumerable: true + }, + packageJSON: { + get: () => packageJSON, + enumerable: true + }, + extensionPath: { + get: () => root, + enumerable: true + }, + isActive: { + get: () => isActive, + enumerable: true + }, + exports: { + get: () => { + if (!isActive) + throw new Error(`Invalid access to exports, extension "${id}" not activated`); + return exports2; + }, + enumerable: true + } + }); + this.extensions.set(id, { + id, + type, + isLocal: type == 1, + extension, + directory: root, + filepath: filename, + deactivate: () => { + if (!isActive) + return; + result = void 0; + exports2 = void 0; + isActive = false; + disposeAll(subscriptions); + subscriptions.splice(0, subscriptions.length); + subscriptions = []; + if (ext && ext.deactivate) { + try { + return Promise.resolve(ext.deactivate()).catch((e) => { + logger71.error(`Error on ${id} deactivate: `, e); + }); + } catch (e) { + logger71.error(`Error on ${id} deactivate: `, e); + } + } + } + }); + 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_default.configurations.extendsDefaults(props); + } + if (rootPatterns && rootPatterns.length) { + for (let item of rootPatterns) { + workspace_default.addRootPattern(item.filetype, item.patterns); + } + } + if (commands && commands.length) { + for (let cmd of commands) { + commands_default.titles.set(cmd.command, cmd.title); + } + } + } + this._onDidLoadExtension.fire(extension); + if (this.activated) { + this.setupActiveEvents(id, packageJSON).logError(); + } + } + filterGlobalExtensions(names) { + let map = new Map(); + names.forEach((def) => { + let name2 = this.getExtensionName(def); + if (name2) + map.set(name2, def); + }); + let json = this.loadJson(); + let urls = []; + let exists = []; + if (json && json.dependencies) { + for (let key of Object.keys(json.dependencies)) { + let val = json.dependencies[key]; + if (typeof val !== "string") + continue; + if (import_fs_extra9.default.existsSync(import_path30.default.join(this.modulesFolder, key, "package.json"))) { + exists.push(key); + if (/^https?:/.test(val)) { + urls.push(val); + } + } + } + } + for (let name2 of map.keys()) { + if (this.disabled.has(name2) || this.extensions.has(name2)) { + map.delete(name2); + continue; + } + if (/^https?:/.test(name2) && urls.some((url) => url.startsWith(name2)) || exists.includes(name2)) { + map.delete(name2); + } + } + return Array.from(map.values()); + } + getExtensionName(def) { + if (/^https?:/.test(def)) + return def; + if (!def.includes("@")) + return def; + return def.replace(/@[\d.]+$/, ""); + } + get modulesFolder() { + return import_path30.default.join(this.root, global.hasOwnProperty("__TEST__") ? "" : "node_modules"); + } + canActivate(id) { + return !this.disabled.has(id) && this.extensions.has(id); + } + async unloadExtension(id) { + let item = this.extensions.get(id); + if (item) { + await this.deactivate(id); + this.extensions.delete(id); + this._onDidUnloadExtension.fire(id); + } + } + checkDirectory(folder) { + try { + let jsonFile = import_path30.default.join(folder, "package.json"); + if (!import_fs_extra9.default.existsSync(jsonFile)) + throw new Error("package.json not found"); + let packageJSON = JSON.parse(import_fs_extra9.default.readFileSync(jsonFile, "utf8")); + let { name: name2, engines, main } = packageJSON; + if (!name2 || !engines) + throw new Error(`can't find name & engines in package.json`); + if (!engines || !objectLiteral(engines)) { + throw new Error(`invalid engines in ${jsonFile}`); + } + if (main && !import_fs_extra9.default.existsSync(import_path30.default.join(folder, main))) { + throw new Error(`main file ${main} not found, you may need to build the project.`); + } + let keys = Object.keys(engines); + if (!keys.includes("coc") && !keys.includes("vscode")) { + throw new Error(`Engines in package.json doesn't have coc or vscode`); + } + if (keys.includes("coc")) { + let required = engines["coc"].replace(/^\^/, ">="); + if (!import_semver2.default.satisfies(workspace_default.version, required)) { + throw new Error(`Please update coc.nvim, ${packageJSON.name} requires coc.nvim ${engines["coc"]}`); + } + } + return true; + } catch (e) { + return e; + } + } + dispose() { + disposeAll(this.disposables); + } + }; + extensions_default = new Extensions(); + } +}); + +// src/sources/source.ts +var logger72, Source; +var init_source = __esm({ + "src/sources/source.ts"() { + init_types(); + init_string(); + init_workspace(); + logger72 = require_logger2()("sources-source"); + Source = class { + constructor(option) { + this._disabled = false; + this.nvim = workspace_default.nvim; + this.name = option.name; + this.filepath = option.filepath || ""; + this.sourceType = option.sourceType || SourceType.Native; + this.isSnippet = !!option.isSnippet; + this.defaults = option; + } + get priority() { + return this.getConfig("priority", 1); + } + 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); + } + 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) => 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_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}]` : ""; + } + 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; + } + fixStartcol(opt, valids) { + let { col, input, line, bufnr } = opt; + let start = byteSlice(line, 0, col); + let document2 = workspace_default.getDocument(bufnr); + if (!document2) + return col; + let { chars } = document2; + for (let i = start.length - 1; i >= 0; i--) { + let c = start[i]; + if (!chars.isKeywordChar(c) && !valids.includes(c)) { + break; + } + input = `${c}${input}`; + col = col - 1; + } + opt.col = col; + opt.input = input; + return col; + } + async shouldComplete(opt) { + let { disableSyntaxes } = this; + if (opt.synname && disableSyntaxes && disableSyntaxes.length) { + let synname = (opt.synname || "").toLowerCase(); + if (disableSyntaxes.findIndex((s) => synname.includes(s.toLowerCase())) !== -1) { + return false; + } + } + let fn = this.defaults["shouldComplete"]; + if (typeof fn === "function") + return await Promise.resolve(fn.call(this, opt)); + return true; + } + async refresh() { + let fn = this.defaults["refresh"]; + if (typeof fn === "function") + await Promise.resolve(fn.call(this)); + } + async onCompleteDone(item, opt) { + let fn = this.defaults["onCompleteDone"]; + if (typeof fn === "function") + await Promise.resolve(fn.call(this, item, opt)); + } + async doComplete(opt, token) { + let fn = this.defaults["doComplete"]; + if (typeof fn === "function") + return await Promise.resolve(fn.call(this, opt, token)); + return null; + } + }; + } +}); + +// src/sources/source-language.ts +function getStartColumn(line, items) { + let first = items[0]; + if (!first.textEdit) + return null; + let range = import_vscode_languageserver_protocol73.InsertReplaceEdit.is(first.textEdit) ? first.textEdit.replace : first.textEdit.range; + let { character } = range.start; + for (let i = 1; i < Math.min(10, items.length); i++) { + let o = items[i]; + if (!o.textEdit) + return null; + let r = import_vscode_languageserver_protocol73.InsertReplaceEdit.is(o.textEdit) ? o.textEdit.replace : o.textEdit.range; + if (r.start.character !== character) + return null; + } + return byteIndex(line, character); +} +function getKindString(kind, map, defaultValue = "") { + return map.get(kind) || defaultValue; +} +function getWord(item, opt, invalidInsertCharacters) { + let { label, data, insertTextFormat, insertText, textEdit } = item; + let word; + let newText; + if (data && typeof data.word === "string") + return data.word; + if (textEdit) { + let range = import_vscode_languageserver_protocol73.InsertReplaceEdit.is(textEdit) ? textEdit.replace : textEdit.range; + newText = textEdit.newText; + if (range && range.start.line == range.end.line) { + let { line, col, colnr } = opt; + let character = 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 = 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 == import_vscode_languageserver_protocol73.InsertTextFormat.Snippet && newText && newText.includes("$")) { + let parser2 = new SnippetParser(); + let text = parser2.text(newText); + word = text ? getValidWord(text, invalidInsertCharacters) : label; + } else { + word = getValidWord(newText, invalidInsertCharacters) || label; + } + return word || ""; +} +function getValidWord(text, invalidChars) { + if (!text) + return ""; + if (!invalidChars.length) + return text; + for (let i = 0; i < text.length; i++) { + let c = text[i]; + if (invalidChars.includes(c)) { + return text.slice(0, i); + } + } + return text; +} +var import_vscode_languageserver_protocol73, logger73, LanguageSource; +var init_source_language = __esm({ + "src/sources/source-language.ts"() { + import_vscode_languageserver_protocol73 = __toModule(require_main2()); + init_commands2(); + init_manager4(); + init_parser2(); + init_position(); + init_string(); + init_window(); + init_workspace(); + logger73 = require_logger2()("source-language"); + LanguageSource = class { + constructor(name2, shortcut, provider, documentSelector, triggerCharacters, allCommitCharacters, priority, completeConfig) { + this.name = name2; + this.shortcut = shortcut; + this.provider = provider; + this.documentSelector = documentSelector; + this.triggerCharacters = triggerCharacters; + this.allCommitCharacters = allCommitCharacters; + this.completeConfig = completeConfig; + this._enabled = true; + this.resolvedIndexes = new Set(); + this.completeItems = []; + this.priority = typeof priority === "number" ? priority : completeConfig.priority; + } + get enable() { + return this._enabled; + } + toggle() { + this._enabled = !this._enabled; + } + shouldCommit(item, character) { + let completeItem = this.completeItems[item.index]; + if (!completeItem) + return false; + let commitCharacters = [...this.allCommitCharacters, ...completeItem.commitCharacters || []]; + return commitCharacters.includes(character); + } + async doComplete(opt, token) { + let { provider, name: name2 } = this; + let { triggerCharacter, bufnr } = opt; + this.filetype = opt.filetype; + this.resolvedIndexes.clear(); + this.completeItems = []; + let triggerKind = this.getTriggerKind(opt); + let position = this.getPosition(opt); + let context = { triggerKind, option: opt }; + if (triggerKind == import_vscode_languageserver_protocol73.CompletionTriggerKind.TriggerCharacter) + context.triggerCharacter = triggerCharacter; + let result; + try { + let doc = workspace_default.getDocument(bufnr); + result = await Promise.resolve(provider.provideCompletionItems(doc.textDocument, position, token, context)); + } catch (e) { + logger73.error(`Complete "${name2}" error:`, e); + return null; + } + if (!result || token.isCancellationRequested) + return null; + let completeItems = Array.isArray(result) ? result : result.items; + if (!completeItems || completeItems.length == 0) + return null; + this.completeItems = completeItems; + let startcol = getStartColumn(opt.line, completeItems); + let option = Object.assign({}, opt); + let prefix; + if (startcol != null) { + if (startcol < option.col) { + prefix = byteSlice(opt.line, startcol, option.col); + } + option.col = startcol; + } + let items = completeItems.map((o, index) => { + let item = this.convertVimCompleteItem(o, this.shortcut, option, prefix); + item.index = index; + return item; + }); + let isIncomplete = typeof result["isIncomplete"] === "boolean" ? result["isIncomplete"] : false; + return { startcol, isIncomplete, items }; + } + async onCompleteResolve(item, token) { + let { index } = item; + let resolving = this.completeItems[index]; + if (!resolving || this.resolvedIndexes.has(index)) + return; + let hasResolve = typeof this.provider.resolveCompletionItem === "function"; + if (hasResolve) { + this.resolvedIndexes.add(index); + try { + let resolved = await Promise.resolve(this.provider.resolveCompletionItem(Object.assign({}, resolving), token)); + if (!resolved || token.isCancellationRequested) { + this.resolvedIndexes.delete(index); + } else if (resolved !== resolving) { + Object.assign(resolving, resolved); + } + } catch (e) { + this.resolvedIndexes.delete(index); + logger73.error(`Error on complete resolve: ${e.message}`, e.stack); + } + } + if (typeof item.documentation === "undefined") { + 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\n]+$/.test(detail); + docs.push({ filetype: isText ? "txt" : this.filetype, content: detail }); + } + } + if (documentation) { + if (typeof documentation == "string") { + docs.push({ filetype: "markdown", content: documentation }); + } else if (documentation.value) { + docs.push({ + filetype: documentation.kind == "markdown" ? "markdown" : "txt", + content: documentation.value + }); + } + } + item.documentation = docs; + } + } + async onCompleteDone(vimItem, opt) { + let item = this.completeItems[vimItem.index]; + if (!item) + return; + let line = opt.linenr - 1; + if (item.insertText != null && !item.textEdit) { + item.textEdit = { + range: import_vscode_languageserver_protocol73.Range.create(line, opt.col, line, opt.colnr - 1), + newText: item.insertText + }; + } + if (vimItem.line) + Object.assign(opt, { line: vimItem.line }); + try { + let isSnippet = await this.applyTextEdit(item, vimItem.word, opt); + let { additionalTextEdits } = item; + if (additionalTextEdits && item.textEdit) { + let r = import_vscode_languageserver_protocol73.InsertReplaceEdit.is(item.textEdit) ? item.textEdit.replace : item.textEdit.range; + additionalTextEdits = additionalTextEdits.filter((edit2) => { + let er = import_vscode_languageserver_protocol73.InsertReplaceEdit.is(edit2) ? edit2.replace : edit2.range; + if (rangeOverlap(r, er)) { + logger73.error("Filtered overlap additionalTextEdit:", edit2); + return false; + } + return true; + }); + } + await this.applyAdditionalEdits(additionalTextEdits, opt.bufnr, isSnippet); + if (isSnippet) + await manager_default3.selectCurrentPlaceholder(); + if (item.command && commands_default.has(item.command.command)) { + void commands_default.execute(item.command); + } + } catch (e) { + logger73.error("Error on CompleteDone:", e); + } + } + async applyTextEdit(item, word, option) { + let { nvim } = workspace_default; + let { textEdit } = item; + if (!textEdit) + return false; + let { line, bufnr, linenr } = option; + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return false; + let newText = textEdit.newText; + let range = import_vscode_languageserver_protocol73.InsertReplaceEdit.is(textEdit) ? textEdit.replace : textEdit.range; + let isSnippet = item.insertTextFormat === import_vscode_languageserver_protocol73.InsertTextFormat.Snippet; + let start = line.substr(0, range.start.character); + let end = line.substr(range.end.character); + if (isSnippet && this.completeConfig.snippetsSupport === false) { + isSnippet = false; + newText = word; + } + if (isSnippet) { + let currline = doc.getline(linenr - 1); + let endCharacter = currline.length - end.length; + let r = import_vscode_languageserver_protocol73.Range.create(linenr - 1, range.start.character, linenr - 1, endCharacter); + return await manager_default3.insertSnippet(newText, false, r, item.insertTextMode); + } + let newLines = `${start}${newText}${end}`.split(/\r?\n/); + if (newLines.length == 1) { + await nvim.call("coc#util#setline", [linenr, newLines[0]]); + await window_default.moveTo(import_vscode_languageserver_protocol73.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 line2 = linenr - 1 + newLines.length - 1; + let character = newLines[newLines.length - 1].length - end.length; + await window_default.moveTo({ line: line2, character }); + } + return false; + } + getTriggerKind(opt) { + let { triggerCharacters } = this; + let isTrigger = triggerCharacters.includes(opt.triggerCharacter); + let triggerKind = import_vscode_languageserver_protocol73.CompletionTriggerKind.Invoked; + if (opt.triggerForInComplete) { + triggerKind = import_vscode_languageserver_protocol73.CompletionTriggerKind.TriggerForIncompleteCompletions; + } else if (isTrigger) { + triggerKind = import_vscode_languageserver_protocol73.CompletionTriggerKind.TriggerCharacter; + } + return triggerKind; + } + async applyAdditionalEdits(textEdits, bufnr, snippet) { + if (!textEdits || textEdits.length == 0) + return; + let document2 = workspace_default.getDocument(bufnr); + if (!document2) + return; + await document2.patchChange(true); + let changed = null; + let pos = await window_default.getCursorPosition(); + if (!snippet) + changed = getChangedFromEdits(pos, textEdits); + await document2.applyEdits(textEdits); + if (changed) + await window_default.moveTo(import_vscode_languageserver_protocol73.Position.create(pos.line + changed.line, pos.character + changed.character)); + } + convertVimCompleteItem(item, shortcut, opt, prefix) { + var _a2; + let { echodocSupport, detailMaxLength, invalidInsertCharacters, detailField, labels, defaultKindText } = this.completeConfig; + let hasAdditionalEdit = item.additionalTextEdits && item.additionalTextEdits.length > 0; + let isSnippet = item.insertTextFormat === import_vscode_languageserver_protocol73.InsertTextFormat.Snippet || hasAdditionalEdit; + let label = item.label.trim(); + let obj = { + word: getWord(item, opt, invalidInsertCharacters), + abbr: label, + menu: `[${shortcut}]`, + kind: getKindString(item.kind, labels, defaultKindText), + sortText: item.sortText || null, + sourceScore: item["score"] || null, + filterText: item.filterText || label, + isSnippet, + dup: item.data && item.data.dup == 0 ? 0 : 1 + }; + if (prefix) { + if (!obj.filterText.startsWith(prefix)) { + if (item.textEdit && item.textEdit.newText.startsWith(prefix)) { + obj.filterText = item.textEdit.newText.split(/\r?\n/)[0]; + } + } + if (!item.textEdit && !obj.word.startsWith(prefix)) { + obj.word = `${prefix}${obj.word}`; + } + } + if (item && item.detail && detailField != "preview") { + let detail = item.detail.replace(/\n\s*/g, " "); + if (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 == import_vscode_languageserver_protocol73.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.includes("(")) { + obj.signature = s; + break; + } + } + } + if (item.preselect) + obj.preselect = true; + if ((_a2 = item.data) == null ? void 0 : _a2.optional) + obj.abbr = obj.abbr + "?"; + return obj; + } + getPosition(opt) { + let { line, linenr, colnr } = opt; + let part = byteSlice(line, 0, colnr - 1); + return { + line: linenr - 1, + character: part.length + }; + } + }; + } +}); + +// src/sources/source-vim.ts +var logger74, VimSource; +var init_source_vim = __esm({ + "src/sources/source-vim.ts"() { + init_fuzzy(); + init_string(); + init_workspace(); + init_window(); + init_source(); + logger74 = require_logger2()("sources-source-vim"); + VimSource = class extends Source { + async callOptinalFunc(fname, args) { + let exists = this.optionalFns.includes(fname); + if (!exists) + return null; + let name2 = `coc#source#${this.name}#${fname}`; + let res; + try { + res = await this.nvim.call(name2, args); + } catch (e) { + window_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.includes("should_complete")) + return true; + let res = await this.callOptinalFunc("should_complete", [opt]); + return !!res; + } + async refresh() { + await this.callOptinalFunc("refresh", []); + } + async onCompleteDone(item, _opt) { + if (!this.optionalFns.includes("on_complete")) + return; + await this.callOptinalFunc("on_complete", [item]); + } + onEnter(bufnr) { + if (!this.optionalFns.includes("on_enter")) + return; + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return; + let { filetypes } = this; + if (filetypes && !filetypes.includes(doc.filetype)) + return; + this.callOptinalFunc("on_enter", [{ + bufnr, + uri: doc.uri, + languageId: doc.filetype + }]).logError(); + } + 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); + if (isNaN(startcol) || startcol < 0) + startcol = col; + if (startcol !== col) { + input = 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 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; + } + }; + } +}); + +// src/sources/native/around.ts +var around_exports = {}; +__export(around_exports, { + default: () => Around, + regist: () => regist +}); +function regist(sourceMap) { + sourceMap.set("around", new Around()); + return import_vscode_languageserver_protocol74.Disposable.create(() => { + sourceMap.delete("around"); + }); +} +var import_vscode_languageserver_protocol74, logger75, Around; +var init_around = __esm({ + "src/sources/native/around.ts"() { + import_vscode_languageserver_protocol74 = __toModule(require_main2()); + init_source(); + init_workspace(); + logger75 = require_logger2()("sources-around"); + Around = class extends Source { + constructor() { + super({ + name: "around", + filepath: __filename + }); + } + doComplete(opt) { + let { bufnr, input } = opt; + if (input.length === 0) + return null; + let document2 = workspace_default.getDocument(bufnr); + if (!document2) + return null; + let words = document2.words; + let moreWords = document2.getMoreWords(); + words.push(...moreWords); + words = this.filterWords(words, opt); + return Promise.resolve({ + items: words.map((word) => ({ + word, + menu: this.menu + })) + }); + } + }; + } +}); + +// src/sources/native/buffer.ts +var buffer_exports = {}; +__export(buffer_exports, { + default: () => Buffer3, + regist: () => regist2 +}); +function regist2(sourceMap) { + sourceMap.set("buffer", new Buffer3()); + return import_vscode_languageserver_protocol75.Disposable.create(() => { + sourceMap.delete("buffer"); + }); +} +var import_vscode_languageserver_protocol75, logger76, Buffer3; +var init_buffer2 = __esm({ + "src/sources/native/buffer.ts"() { + import_vscode_languageserver_protocol75 = __toModule(require_main2()); + init_source(); + init_workspace(); + logger76 = require_logger2()("sources-buffer"); + Buffer3 = class extends Source { + constructor() { + super({ + name: "buffer", + filepath: __filename + }); + } + get ignoreGitignore() { + return this.getConfig("ignoreGitignore", true); + } + getWords(bufnr) { + let { ignoreGitignore } = this; + let words = []; + workspace_default.documents.forEach((document2) => { + if (document2.bufnr == bufnr) + return; + if (ignoreGitignore && document2.isIgnored) + return; + for (let word of document2.words) { + if (!words.includes(word)) { + words.push(word); + } + } + }); + return words; + } + doComplete(opt) { + let { bufnr, input } = opt; + if (input.length == 0) + return null; + let words = this.getWords(bufnr); + words = this.filterWords(words, opt); + return Promise.resolve({ + items: words.map((word) => ({ + word, + menu: this.menu + })) + }); + } + }; + } +}); + +// src/sources/native/file.ts +var file_exports = {}; +__export(file_exports, { + default: () => File, + regist: () => regist3 +}); +function regist3(sourceMap) { + sourceMap.set("file", new File()); + return import_vscode_languageserver_protocol76.Disposable.create(() => { + sourceMap.delete("file"); + }); +} +var import_fs29, import_minimatch6, import_path31, import_util38, import_vscode_languageserver_protocol76, logger77, pathRe, File; +var init_file = __esm({ + "src/sources/native/file.ts"() { + import_fs29 = __toModule(require("fs")); + import_minimatch6 = __toModule(require_minimatch()); + import_path31 = __toModule(require("path")); + import_util38 = __toModule(require("util")); + import_vscode_languageserver_protocol76 = __toModule(require_main2()); + init_source(); + init_fs(); + init_string(); + init_workspace(); + logger77 = require_logger2()("sources-file"); + pathRe = /(?:\.{0,2}|~|\$HOME|([\w]+)|[a-zA-Z]:|)(\/|\\)(?:[\u4e00-\u9fa5\w.@()-]+(\/|\\))*(?:[\u4e00-\u9fa5\w.@()-])*$/; + File = class extends Source { + constructor() { + super({ + name: "file", + filepath: __filename + }); + } + resolveEnvVariables(str) { + let replaced = str; + replaced = replaced.replace(/%([^%]+)%/g, (_, n) => process.env[n]); + replaced = replaced.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/gi, (_, a, b) => process.env[a || b]); + return replaced; + } + getPathOption(opt) { + let { line, colnr } = opt; + let part = byteSlice(line, 0, colnr - 1); + part = this.resolveEnvVariables(part); + if (!part || part.endsWith("//")) + return null; + let ms = part.match(pathRe); + if (ms && ms.length) { + const pathstr = workspace_default.expand(ms[0]); + 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 = import_path31.default.join(root, filename); + let stat = await 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 && f.startsWith(".")) + return false; + for (let p of ignorePatterns) { + if ((0, import_minimatch6.default)(f, p, { dot: true })) + return false; + } + return true; + }); + } + async getItemsFromRoot(pathstr, root) { + let res = []; + let part = pathstr.endsWith("/") ? pathstr : import_path31.default.dirname(pathstr); + let dir = import_path31.default.isAbsolute(pathstr) ? part : import_path31.default.join(root, part); + try { + let stat = await statAsync(dir); + if (stat && stat.isDirectory()) { + let files = await import_util38.default.promisify(import_fs29.default.readdir)(dir); + files = this.filterFiles(files); + let items = await Promise.all(files.map((filename) => this.getFileItem(dir, filename))); + res = res.concat(items); + } + res = res.filter((item) => item != null); + return res; + } catch (e) { + logger77.error(`Error on list files:`, e); + 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 ? "" : byteSlice(opt.line, opt.col, startcol); + let dirname3 = import_path31.default.dirname(filepath); + let ext = import_path31.default.extname(import_path31.default.basename(filepath)); + let cwd = await this.nvim.call("getcwd", []); + let root; + if (pathstr.startsWith(".")) { + root = filepath ? import_path31.default.dirname(filepath) : cwd; + } else if (pathstr.startsWith("/")) { + root = pathstr.endsWith("/") ? pathstr : import_path31.default.dirname(pathstr); + } else if (part) { + if (import_fs29.default.existsSync(import_path31.default.join(dirname3, part))) { + root = dirname3; + } else if (import_fs29.default.existsSync(import_path31.default.join(cwd, part))) { + root = cwd; + } + } else { + root = cwd; + } + if (!root) + return null; + let items = await this.getItemsFromRoot(pathstr, root); + let trimExt = this.trimSameExts.includes(ext); + let first = input[0]; + if (first && col == startcol) + items = items.filter((o) => o.word[0] === first); + return { + items: items.map((item) => { + let ex = import_path31.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 + }; + }) + }; + } + }; + } +}); + +// src/sources/index.ts +var sources_exports = {}; +__export(sources_exports, { + Sources: () => Sources, + default: () => sources_default +}); +var import_fast_diff3, import_fs31, import_path32, import_util39, import_vscode_languageserver_protocol77, logger78, Sources, sources_default; +var init_sources2 = __esm({ + "src/sources/index.ts"() { + import_fast_diff3 = __toModule(require_diff()); + import_fs31 = __toModule(require("fs")); + import_path32 = __toModule(require("path")); + import_util39 = __toModule(require("util")); + import_vscode_languageserver_protocol77 = __toModule(require_main2()); + init_events(); + init_extensions2(); + init_types(); + init_util(); + init_fs(); + init_match(); + init_object(); + init_string(); + init_window(); + init_workspace(); + init_source(); + init_source_language(); + init_source_vim(); + logger78 = require_logger2()("sources"); + Sources = class { + constructor() { + this.sourceMap = new Map(); + this.disposables = []; + this.remoteSourcePaths = []; + } + init() { + this.loadCompleteConfig(); + workspace_default.onDidChangeConfiguration((e) => { + if (e.affectsConfiguration("suggest")) { + this.loadCompleteConfig(); + } + }, null, this.disposables); + this.createNativeSources(); + this.createRemoteSources(); + events_default.on("BufEnter", this.onDocumentEnter, this, this.disposables); + workspace_default.watchOption("runtimepath", async (oldValue, newValue) => { + let result = (0, import_fast_diff3.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); + } + loadCompleteConfig() { + let suggest = workspace_default.getConfiguration("suggest"); + let labels = suggest.get("completionItemKindLabels", {}); + let map = new Map([ + [import_vscode_languageserver_protocol77.CompletionItemKind.Text, labels["text"] || "v"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Method, labels["method"] || "f"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Function, labels["function"] || "f"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Constructor, typeof labels["constructor"] == "function" ? "f" : labels["constructor"]], + [import_vscode_languageserver_protocol77.CompletionItemKind.Field, labels["field"] || "m"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Variable, labels["variable"] || "v"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Class, labels["class"] || "C"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Interface, labels["interface"] || "I"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Module, labels["module"] || "M"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Property, labels["property"] || "m"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Unit, labels["unit"] || "U"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Value, labels["value"] || "v"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Enum, labels["enum"] || "E"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Keyword, labels["keyword"] || "k"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Snippet, labels["snippet"] || "S"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Color, labels["color"] || "v"], + [import_vscode_languageserver_protocol77.CompletionItemKind.File, labels["file"] || "F"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Reference, labels["reference"] || "r"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Folder, labels["folder"] || "F"], + [import_vscode_languageserver_protocol77.CompletionItemKind.EnumMember, labels["enumMember"] || "m"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Constant, labels["constant"] || "v"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Struct, labels["struct"] || "S"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Event, labels["event"] || "E"], + [import_vscode_languageserver_protocol77.CompletionItemKind.Operator, labels["operator"] || "O"], + [import_vscode_languageserver_protocol77.CompletionItemKind.TypeParameter, labels["typeParameter"] || "T"] + ]); + let floatEnable = suggest.get("floatEnable", true); + let detailField = suggest.get("detailField", "preview"); + if (detailField == "preview" && (!floatEnable || !workspace_default.floatSupported)) { + detailField = "menu"; + } + this.completeConfig = Object.assign(this.completeConfig || {}, { + labels: map, + floatEnable, + detailField, + defaultKindText: labels["default"] || "", + priority: suggest.get("languageSourcePriority", 99), + echodocSupport: suggest.get("echodocSupport", false), + snippetsSupport: suggest.get("snippetsSupport", true), + detailMaxLength: suggest.get("detailMaxLength", 100), + invalidInsertCharacters: suggest.get("invalidInsertCharacters", ["(", "<", "{", "[", "\r", "\n"]) + }); + } + get nvim() { + return workspace_default.nvim; + } + createNativeSources() { + try { + this.disposables.push((init_around(), around_exports).regist(this.sourceMap)); + this.disposables.push((init_buffer2(), buffer_exports).regist(this.sourceMap)); + this.disposables.push((init_file(), file_exports).regist(this.sourceMap)); + } catch (e) { + console.error("Create source error:" + e.message); + } + } + createLanguageSource(name2, shortcut, selector, provider, triggerCharacters, priority, allCommitCharacters) { + let source = new LanguageSource(name2, shortcut, provider, selector, triggerCharacters || [], allCommitCharacters || [], priority, this.completeConfig); + logger78.debug("created service source", name2); + this.sourceMap.set(name2, source); + return { + dispose: () => { + this.sourceMap.delete(name2); + } + }; + } + async createVimSourceExtension(nvim, filepath) { + let name2 = import_path32.default.basename(filepath, ".vim"); + try { + await nvim.command(`source ${filepath}`); + let fns = await nvim.call("coc#util#remote_fns", name2); + for (let fn of ["init", "complete"]) { + if (!fns.includes(fn)) { + window_default.showMessage(`${fn} not found for source ${name2}`, "error"); + return null; + } + } + let props = await nvim.call(`coc#source#${name2}#init`, []); + let packageJSON = { + name: `coc-source-${name2}`, + engines: { + coc: ">= 0.0.1" + }, + activationEvents: props.filetypes ? props.filetypes.map((f) => `onLanguage:${f}`) : ["*"], + contributes: { + configuration: { + properties: { + [`coc.source.${name2}.enable`]: { + type: "boolean", + default: true + }, + [`coc.source.${name2}.firstMatch`]: { + type: "boolean", + default: !!props.firstMatch + }, + [`coc.source.${name2}.triggerCharacters`]: { + type: "number", + default: props.triggerCharacters || [] + }, + [`coc.source.${name2}.priority`]: { + type: "number", + default: props.priority || 9 + }, + [`coc.source.${name2}.shortcut`]: { + type: "string", + default: props.shortcut || name2.slice(0, 3).toUpperCase(), + description: "Shortcut text shown in complete menu." + }, + [`coc.source.${name2}.disableSyntaxes`]: { + type: "array", + default: [], + items: { + type: "string" + } + }, + [`coc.source.${name2}.filetypes`]: { + type: "array", + default: props.filetypes || null, + description: "Enabled filetypes.", + items: { + type: "string" + } + } + } + } + } + }; + let source = new VimSource({ + name: name2, + filepath, + sourceType: SourceType.Remote, + optionalFns: fns.filter((n) => !["init", "complete"].includes(n)) + }); + let isActive = false; + let extension = { + id: packageJSON.name, + packageJSON, + exports: void 0, + extensionPath: filepath, + activate: () => { + isActive = true; + this.addSource(source); + return Promise.resolve(); + } + }; + Object.defineProperty(extension, "isActive", { + get: () => isActive + }); + extensions_default.registerExtension(extension, () => { + isActive = false; + this.removeSource(source); + }); + } catch (e) { + window_default.showMessage(`Error on create vim source ${name2}: ${e.message}`, "error"); + } + } + createRemoteSources() { + let { runtimepath } = workspace_default.env; + let paths = runtimepath.split(","); + for (let path36 of paths) { + this.createVimSources(path36).logError(); + } + } + async createVimSources(pluginPath) { + if (this.remoteSourcePaths.includes(pluginPath)) + return; + this.remoteSourcePaths.push(pluginPath); + let folder = import_path32.default.join(pluginPath, "autoload/coc/source"); + let stat = await statAsync(folder); + if (stat && stat.isDirectory()) { + let arr = await import_util39.default.promisify(import_fs31.default.readdir)(folder); + arr = arr.filter((s) => s.endsWith(".vim")); + let files = arr.map((s) => import_path32.default.join(folder, s)); + if (files.length == 0) + return; + await Promise.all(files.map((p) => this.createVimSourceExtension(this.nvim, p))); + } + } + get names() { + return Array.from(this.sourceMap.keys()); + } + get sources() { + return Array.from(this.sourceMap.values()); + } + has(name2) { + return this.names.findIndex((o) => o == name2) != -1; + } + getSource(name2) { + if (!name2) + return null; + return this.sourceMap.get(name2) || null; + } + shouldCommit(item, commitCharacter) { + if (!item || !item.source) + return false; + let source = this.getSource(item.source); + if (source && source.sourceType == SourceType.Service && typeof source.shouldCommit === "function") { + return source.shouldCommit(item, commitCharacter); + } + return false; + } + getCompleteSources(opt) { + let { filetype } = opt; + let pre = byteSlice(opt.line, 0, opt.colnr - 1); + let isTriggered = opt.input == "" && !!opt.triggerCharacter; + let uri = getUri(opt.filepath, opt.bufnr, "", workspace_default.env.isCygwin); + if (isTriggered) + return this.getTriggerSources(pre, filetype, uri); + return this.getNormalSources(opt.filetype, uri); + } + getNormalSources(filetype, uri) { + return this.sources.filter((source) => { + let { filetypes, triggerOnly, documentSelector, enable } = source; + if (!enable || triggerOnly || filetypes && !filetypes.includes(filetype)) { + return false; + } + if (documentSelector && score(documentSelector, uri, filetype) == 0) { + return false; + } + if (this.disabledByLanguageId(source, filetype)) { + return false; + } + return true; + }); + } + checkTrigger(source, pre, character) { + let { triggerCharacters, triggerPatterns } = source; + if (!triggerCharacters && !triggerPatterns) + return false; + if (character && triggerCharacters && triggerCharacters.includes(character)) { + return true; + } + if (triggerPatterns && triggerPatterns.findIndex((p) => p.test(pre)) !== -1) { + return true; + } + return false; + } + shouldTrigger(pre, languageId, uri) { + let sources = this.getTriggerSources(pre, languageId, uri); + return sources.length > 0; + } + getTriggerSources(pre, languageId, uri) { + let character = pre.length ? pre[pre.length - 1] : ""; + if (!character) + return []; + return this.sources.filter((source) => { + let { filetypes, enable, documentSelector } = source; + if (!enable || filetypes && !filetypes.includes(languageId)) { + return false; + } + if (documentSelector && score(documentSelector, uri, languageId) == 0) { + return false; + } + if (this.disabledByLanguageId(source, languageId)) + return false; + return this.checkTrigger(source, pre, character); + }); + } + addSource(source) { + let { name: name2 } = source; + if (this.names.includes(name2)) { + logger78.warn(`Recreate source ${name2}`); + } + this.sourceMap.set(name2, source); + return import_vscode_languageserver_protocol77.Disposable.create(() => { + this.sourceMap.delete(name2); + }); + } + removeSource(source) { + let name2 = typeof source == "string" ? source : source.name; + this.sourceMap.delete(name2); + } + async refresh(name2) { + for (let source of this.sources) { + if (!name2 || source.name == name2) { + if (typeof source.refresh === "function") { + await Promise.resolve(source.refresh()); + } + } + } + } + toggleSource(name2) { + if (!name2) + return; + let source = this.getSource(name2); + 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, + triggerCharacters: item.triggerCharacters || [], + shortcut: item.shortcut || "", + filetypes: item.filetypes || [], + filepath: item.filepath || "", + type: item.sourceType == SourceType.Native ? "native" : item.sourceType == SourceType.Remote ? "remote" : "service", + disabled: !item.enable + }); + } + return res; + } + onDocumentEnter(bufnr) { + let { sources } = this; + for (let s of sources) { + if (s.enable && typeof s.onEnter == "function") { + s.onEnter(bufnr); + } + } + } + createSource(config) { + if (!config.name || !config.doComplete) { + throw new Error(`name and doComplete required for createSource`); + } + let source = new Source(Object.assign({ sourceType: SourceType.Service }, config)); + return this.addSource(source); + } + disabledByLanguageId(source, languageId) { + let map = workspace_default.env.disabledSources; + if (isEmpty(map)) + return false; + let list2 = map ? map[languageId] : []; + return Array.isArray(list2) && list2.includes(source.name); + } + dispose() { + disposeAll(this.disposables); + } + }; + sources_default = new Sources(); + } +}); + +// src/completion/match.ts +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 (!wordChar(curr)) + return false; + let pre = codes[index - 1]; + if (!wordChar(pre)) + return true; + if (upperCase(curr) && !upperCase(pre)) + return true; + return false; +} +function matchScore(word, input) { + if (input.length == 0 || word.length < input.length) + return 0; + let codes = getCharCodes(word); + let curr = codes[0]; + let score5 = 0; + let first = input[0]; + let idx = 1; + let allowFuzzy = true; + if (caseMatch(first, curr)) { + score5 = first == curr ? 5 : 2.5; + idx = 1; + } else { + let next2 = nextWordIndex(1, codes); + if (next2 != -1) { + if (caseMatch(first, codes[next2])) { + score5 = first == codes[next2] ? 2.5 : 2; + idx = next2 + 1; + } + } + if (score5 == 0) { + for (let i = 1; i < codes.length; i++) { + if (caseMatch(first, codes[i])) { + score5 = first == codes[i] ? 1 : 0.5; + idx = i + 1; + allowFuzzy = false; + } + } + } + } + if (input.length == 1 || score5 == 0) + return score5; + let next = nextScore(codes, idx, input.slice(1), allowFuzzy); + return next == 0 ? 0 : score5 + next; +} +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 (!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 = caseMatch(input, curr); + if (match) { + let score5 = input == curr ? 1 : 0.5; + if (!isFinal) { + let next = nextScore(codes, index + 1, inputCodes.slice(1), allowFuzzy); + score5 = next == 0 ? 0 : score5 + next; + } + scores.push(score5); + } + if (wordChar(input) && !isWordIndex(index, codes)) { + let idx = nextWordIndex(index + 1, codes); + if (idx !== -1) { + let next = codes[idx]; + if (caseMatch(input, next)) { + let score5 = input == next ? 1 : 0.75; + if (!isFinal) { + let next2 = nextScore(codes, idx + 1, inputCodes.slice(1), allowFuzzy); + score5 = next2 == 0 ? 0 : score5 + next2; + } + scores.push(score5); + } + } + } + if (!match && allowFuzzy) { + for (let i = index + 1; i < len; i++) { + let code = codes[i]; + if (caseMatch(input, code)) { + let score5 = input == code ? 0.1 : 0.05; + if (!isFinal) { + let next = nextScore(codes, i + 1, inputCodes.slice(1), false); + score5 = next == 0 ? 0 : score5 + next; + } + scores.push(score5); + } + } + } + if (!scores.length) + return 0; + return Math.max(...scores); +} +var init_match2 = __esm({ + "src/completion/match.ts"() { + init_fuzzy(); + } +}); + +// src/completion/complete.ts +var import_vscode_languageserver_protocol78, logger79, FIRST_TIMEOUT, Complete; +var init_complete = __esm({ + "src/completion/complete.ts"() { + import_vscode_languageserver_protocol78 = __toModule(require_main2()); + init_fuzzy(); + init_string(); + init_match2(); + logger79 = require_logger2()("completion-complete"); + FIRST_TIMEOUT = 500; + Complete = class { + constructor(option, document2, config, sources, nvim) { + this.option = option; + this.document = document2; + this.config = config; + this.sources = sources; + this.nvim = nvim; + this.results = []; + this.completing = new Set(); + this._canceled = false; + this.tokenSources = new Map(); + this._onDidComplete = new import_vscode_languageserver_protocol78.Emitter(); + this.onDidComplete = this._onDidComplete.event; + } + 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) !== -1; + } + async completeSource(source) { + let { col } = this.option; + let opt = Object.assign({}, this.option); + let timeout = this.config.timeout; + timeout = Math.max(Math.min(timeout, 15e3), 500); + 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 import_vscode_languageserver_protocol78.CancellationTokenSource(); + this.tokenSources.set(source.name, tokenSource); + await new Promise((resolve3, reject) => { + let { name: name2 } = 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; + resolve3(void 0); + }, FIRST_TIMEOUT); + let onFinished = () => { + if (called) + return; + called = true; + disposable.dispose(); + clearTimeout(ft); + clearTimeout(timer); + this.tokenSources.delete(name2); + }; + let disposable = tokenSource.token.onCancellationRequested(() => { + disposable.dispose(); + this.completing.delete(name2); + cancelled = true; + onFinished(); + logger79.debug(`Source "${name2}" cancelled`); + resolve3(void 0); + }); + this.completing.add(name2); + Promise.resolve(source.doComplete(opt, tokenSource.token)).then((result) => { + this.completing.delete(name2); + if (cancelled) + return; + onFinished(); + let dt = Date.now() - start; + logger79.debug(`Source "${name2}" takes ${dt}ms`); + if (result && result.items && result.items.length) { + result.priority = source.priority; + result.source = name2; + if (empty && result.startcol && result.startcol != col) { + this.results = [result]; + } else { + let { results } = this; + let idx = results.findIndex((o) => o.source == name2); + if (idx != -1) { + results.splice(idx, 1, result); + } else { + results.push(result); + } + } + if (empty) + this._onDidComplete.fire(); + resolve3(void 0); + } else { + let { results } = this; + this.results = results.filter((res) => res.source != name2); + resolve3(void 0); + } + }, (err) => { + this.completing.delete(name2); + onFinished(); + reject(err); + }); + }); + } catch (err) { + this.nvim.command(`echoerr 'Complete ${source.name} error: ${err.message.replace(/'/g, "''")}'`, true); + logger79.error("Complete error:", source.name, err); + } + } + async completeInComplete(resumeInput) { + let { results, document: document2 } = this; + let remains = results.filter((res) => !res.isIncomplete); + remains.forEach((res) => { + res.items.forEach((item) => delete item.user_data); + }); + let arr = results.filter((res) => res.isIncomplete); + let names = arr.map((o) => o.source); + let { input, colnr, linenr } = this.option; + Object.assign(this.option, { + input: resumeInput, + line: document2.getline(linenr - 1), + colnr: colnr + (resumeInput.length - input.length), + triggerCharacter: null, + triggerForInComplete: true + }); + let sources = this.sources.filter((s) => names.includes(s.name)); + await Promise.all(sources.map((s) => this.completeSource(s))); + return this.filterResults(resumeInput, Math.floor(Date.now() / 1e3)); + } + 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 { snippetIndicator, removeDuplicateItems, fixInsertedWord, asciiCharactersOnly } = this.config; + let followPart = !fixInsertedWord || cid == 0 ? "" : this.getFollowPart(); + if (results.length == 0) + return []; + let arr = []; + let codes = 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; + for (let idx = 0; idx < items.length; idx++) { + let item = items[idx]; + if (!item || typeof item.word !== "string") { + continue; + } + let { word } = item; + if (asciiCharactersOnly && !/^[\x00-\x7F]*$/.test(word)) { + continue; + } + if (!item.dup && words.has(word)) + continue; + if (removeDuplicateItems && !item.isSnippet && words.has(word) && item.line == void 0) + continue; + let filterText = item.filterText || item.word; + item.filterText = filterText; + if (filterText.length < input.length) + continue; + let score5 = item.kind && filterText == input ? 64 : matchScore(filterText, codes); + if (input.length && score5 == 0) + continue; + if (followPart.length && !item.isSnippet) { + if (item.word.endsWith(followPart)) { + let { word: word2 } = item; + item.word = item.word.slice(0, -followPart.length); + item.abbr = item.abbr || word2; + } + } + 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; + } + item.priority = priority; + item.abbr = item.abbr || item.word; + item.score = input.length ? score5 * (item.sourceScore || 1) : 0; + item.localBonus = this.localBonus ? this.localBonus.get(filterText) || 0 : 0; + words.add(word); + if (item.isSnippet && input.length && 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.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; + } + switch (this.config.defaultSortMethod) { + case "none": + return 0; + case "alphabetical": + return a.filterText.localeCompare(b.filterText); + case "length": + default: + 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 = getCharCodes(input); + for (let i = 0, l = results.length; i < l; i++) { + let items = results[i].items; + let idx = items.findIndex((item) => 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 line2 = linenr - 1; + this.localBonus = this.document.getLocalifyBonus(import_vscode_languageserver_protocol78.Position.create(line2, opts.col - 1), import_vscode_languageserver_protocol78.Position.create(line2, 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 = byteSlice(line, startcol, colnr - 1); + this.results = [engrossResult]; + } + logger79.info(`Results from: ${this.results.map((s) => s.source).join(",")}`); + return this.filterResults(opts.input, Math.floor(Date.now() / 1e3)); + } + 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 = characterIndex(line, colnr - 1); + if (idx == line.length) + return ""; + let part = line.slice(idx - line.length); + return part.match(/^\S?[\w-]*/)[0]; + } + dispose() { + if (this._canceled) + return; + this._onDidComplete.dispose(); + this._canceled = true; + for (let tokenSource of this.tokenSources.values()) { + tokenSource.cancel(); + } + this.tokenSources.clear(); + this.sources = []; + this.results = []; + } + }; + } +}); + +// src/completion/floating.ts +var logger80, Floating; +var init_floating = __esm({ + "src/completion/floating.ts"() { + init_markdown(); + logger80 = require_logger2()("floating"); + Floating = class { + constructor(nvim, isVim7) { + this.nvim = nvim; + this.isVim = isVim7; + this.winid = 0; + this.bufnr = 0; + } + async show(docs, bounding, config, token) { + let { nvim } = this; + docs = docs.filter((o) => o.content.trim().length > 0); + let { lines, codes, highlights } = parseDocuments(docs, { excludeImages: config.excludeImages }); + if (lines.length == 0) { + this.close(); + return; + } + let opts = { + codes, + highlights, + maxWidth: config.maxWidth || 80, + pumbounding: bounding + }; + if (config.border) + opts.border = [1, 1, 1, 1]; + if (config.highlight) + opts.highlight = config.highlight; + if (config.borderhighlight) + opts.borderhighlight = config.borderhighlight; + if (!this.isVim) { + if (typeof config.winblend === "number") + opts.winblend = config.winblend; + opts.focusable = config.focusable === true ? 1 : 0; + if (config.shadow) + opts.shadow = 1; + } + let res = await nvim.call("coc#float#create_pum_float", [this.winid, this.bufnr, lines, opts]); + if (this.isVim) + nvim.command("redraw", true); + if (!res || res.length == 0) + return; + this.winid = res[0]; + this.bufnr = res[1]; + if (token.isCancellationRequested) { + this.close(); + return; + } + } + close() { + let { winid, nvim } = this; + this.winid = 0; + if (!winid) + return; + nvim.call("coc#float#close", [winid], true); + if (this.isVim) + nvim.command("redraw", true); + } + }; + } +}); + +// src/completion/index.ts +var import_vscode_languageserver_protocol79, import_debounce9, logger81, completeItemKeys, Completion, completion_default; +var init_completion = __esm({ + "src/completion/index.ts"() { + import_vscode_languageserver_protocol79 = __toModule(require_main2()); + init_events(); + init_sources2(); + init_util(); + init_is(); + init_workspace(); + init_complete(); + init_floating(); + import_debounce9 = __toModule(require_debounce()); + init_string(); + init_object(); + logger81 = require_logger2()("completion"); + completeItemKeys = ["abbr", "menu", "info", "kind", "icase", "dup", "empty", "user_data"]; + Completion = class { + constructor() { + this.activated = false; + this.disposables = []; + this.complete = null; + this.changedTick = 0; + this.insertCharTs = 0; + this.insertLeaveTs = 0; + } + init() { + this.config = this.getCompleteConfig(); + workspace_default.onDidChangeConfiguration((e) => { + if (e.affectsConfiguration("suggest")) { + this.config = this.getCompleteConfig(); + } + }, null, this.disposables); + workspace_default.watchOption("completeopt", async (_, newValue) => { + workspace_default.env.completeOpt = newValue; + if (!this.isActivated) + return; + if (this.config.autoTrigger === "always") { + let content = await this.nvim.call("execute", ["verbose set completeopt"]); + let lines = content.split(/\r?\n/); + console.error(`Some plugin change completeopt during completion: ${lines[lines.length - 1].trim()}!`); + } + }, this.disposables); + this.excludeImages = workspace_default.getConfiguration("coc.preferences").get("excludeImageLinksInMarkdownDocument"); + this.floating = new Floating(workspace_default.nvim, workspace_default.env.isVim); + events_default.on(["InsertCharPre", "MenuPopupChanged", "TextChangedI", "CursorMovedI", "InsertLeave"], () => { + if (this.triggerTimer) { + clearTimeout(this.triggerTimer); + this.triggerTimer = null; + } + }, this, this.disposables); + events_default.on("InsertCharPre", this.onInsertCharPre, this, this.disposables); + events_default.on("InsertLeave", this.onInsertLeave, this, this.disposables); + events_default.on("InsertEnter", this.onInsertEnter, this, this.disposables); + events_default.on("TextChangedP", this.onTextChangedP, this, this.disposables); + events_default.on("TextChangedI", this.onTextChangedI, this, this.disposables); + let fn = (0, import_debounce9.default)(this.onPumChange.bind(this), 20); + this.disposables.push({ + dispose: () => { + fn.clear(); + } + }); + events_default.on("CompleteDone", async (item) => { + this.popupEvent = null; + if (!this.activated) + return; + fn.clear(); + this.cancelResolve(); + this.floating.close(); + await this.onCompleteDone(item); + }, this, this.disposables); + this.cancelResolve(); + events_default.on("MenuPopupChanged", (ev) => { + if (!this.activated || this.isCommandLine) + return; + if (equals(this.popupEvent, ev)) + return; + this.cancelResolve(); + this.popupEvent = ev; + fn(); + }, this, this.disposables); + } + get nvim() { + return workspace_default.nvim; + } + get option() { + if (!this.complete) + return null; + return this.complete.option; + } + get selectedItem() { + if (!this.popupEvent) + return null; + let { completed_item } = this.popupEvent; + return vimCompleteItem(completed_item) ? completed_item : null; + } + get isCommandLine() { + var _a2; + return (_a2 = this.document) == null ? void 0 : _a2.uri.endsWith("%5BCommand%20Line%5D"); + } + get isActivated() { + return this.activated; + } + get document() { + if (!this.option) + return null; + return workspace_default.getDocument(this.option.bufnr); + } + getCompleteConfig() { + let suggest = workspace_default.getConfiguration("suggest"); + function getConfig(key, defaultValue) { + return suggest.get(key, defaultValue); + } + let keepCompleteopt = getConfig("keepCompleteopt", false); + let autoTrigger = getConfig("autoTrigger", "always"); + if (keepCompleteopt && autoTrigger != "none") { + let { completeOpt } = workspace_default; + if (!completeOpt.includes("noinsert") && !completeOpt.includes("noselect")) { + autoTrigger = "none"; + } + } + let floatEnable = workspace_default.floatSupported && getConfig("floatEnable", true); + let acceptSuggestionOnCommitCharacter = workspace_default.env.pumevent && getConfig("acceptSuggestionOnCommitCharacter", false); + return { + autoTrigger, + floatEnable, + keepCompleteopt, + floatConfig: getConfig("floatConfig", {}), + 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), + triggerCompletionWait: getConfig("triggerCompletionWait", 100), + labelMaxLength: getConfig("labelMaxLength", 200), + triggerAfterInsertEnter: getConfig("triggerAfterInsertEnter", false), + noselect: getConfig("noselect", true), + numberSelect: getConfig("numberSelect", false), + maxItemCount: getConfig("maxCompleteItemCount", 50), + timeout: getConfig("timeout", 500), + minTriggerInputLength: getConfig("minTriggerInputLength", 1), + snippetIndicator: getConfig("snippetIndicator", "~"), + fixInsertedWord: getConfig("fixInsertedWord", true), + localityBonus: getConfig("localityBonus", true), + highPrioritySourceLimit: getConfig("highPrioritySourceLimit", null), + lowPrioritySourceLimit: getConfig("lowPrioritySourceLimit", null), + asciiCharactersOnly: getConfig("asciiCharactersOnly", false) + }; + } + async startCompletion(option) { + this.pretext = byteSlice(option.line, 0, option.colnr - 1); + try { + await this._doComplete(option); + } catch (e) { + this.stop(); + logger81.error("Complete error:", e.stack); + } + } + async resumeCompletion(force = false) { + let { document: document2, complete } = this; + if (!document2 || complete.isCanceled || !complete.results || complete.results.length == 0) + return; + let search = this.getResumeInput(); + if (search == this.input && !force) + return; + if (!search || search.endsWith(" ") || !search.startsWith(complete.input)) { + this.stop(); + return; + } + this.input = search; + let items = []; + if (complete.isIncomplete) { + await document2.patchChange(true); + let { changedtick } = document2; + items = await complete.completeInComplete(search); + if (complete.isCanceled || document2.changedtick != changedtick) + return; + } else { + items = complete.filterResults(search); + } + if (!complete.isCompleting && items.length === 0) { + this.stop(); + return; + } + await this.showCompletion(complete.option.col, items); + } + hasSelected() { + if (workspace_default.env.pumevent) + return this.selectedItem != null; + if (!this.config.noselect) + return true; + return false; + } + async showCompletion(col, items) { + let { nvim, document: document2, option } = this; + let { numberSelect, disableKind, labelMaxLength, disableMenuShortcut, disableMenu } = this.config; + let preselect = this.config.enablePreselect ? items.findIndex((o) => o.preselect) : -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 = document2.changedtick; + let validKeys2 = completeItemKeys.slice(); + if (disableKind) + validKeys2 = validKeys2.filter((s) => s != "kind"); + if (disableMenu) + validKeys2 = validKeys2.filter((s) => s != "menu"); + let vimItems = items.map((item) => { + let obj = { word: item.word, equal: 1 }; + for (let key of validKeys2) { + if (item.hasOwnProperty(key)) { + if (disableMenuShortcut && key == "menu") { + obj[key] = item[key].replace(/\[.+\]$/, ""); + } 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 } = this; + let doc = workspace_default.getDocument(option.bufnr); + if (!doc || !doc.attached) + return; + option.filetype = doc.filetype; + this.input = option.input; + let arr = []; + if (source == null) { + arr = sources_default.getCompleteSources(option); + } else { + let s = sources_default.getSource(source); + if (s) + arr.push(s); + } + if (!arr.length) + return; + await doc.patchChange(); + if (doc.changedtick != option.changedtick) + return; + let complete = new Complete(option, doc, 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 () => { + if (this.selectedItem != null) + return; + let search = this.getResumeInput(); + if (complete.isCanceled || search == null) + return; + let { input } = this.option; + if (search == input) { + let items2 = complete.filterResults(search, Math.floor(Date.now() / 1e3)); + await this.showCompletion(option.col, items2); + } else { + await this.resumeCompletion(); + } + }); + if (items.length) { + let search = this.getResumeInput(); + if (search == option.input) { + await this.showCompletion(option.col, items); + } else { + await this.resumeCompletion(true); + } + } + } + async onTextChangedP(bufnr, info) { + let { option, document: document2 } = this; + let pretext = this.pretext = info.pre; + if (!option || option.bufnr != bufnr || info.changedtick == this.changedTick) + return; + let hasInsert = this.latestInsert != null; + this.lastInsert = null; + if (info.pre.match(/^\s*/)[0] !== option.line.match(/^\s*/)[0]) { + logger81.warn("Complete stopped by indent change."); + this.stop(false); + return; + } + if (!hasInsert || !pretext) + return; + if (sources_default.shouldTrigger(pretext, document2.filetype, document2.uri)) { + await this.triggerCompletion(document2, pretext); + } else { + await this.resumeCompletion(); + } + } + async onTextChangedI(bufnr, info) { + let { nvim, latestInsertChar, option } = this; + let noChange = this.pretext == info.pre; + let pretext = this.pretext = info.pre; + this.lastInsert = null; + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return; + if (!this.activated) { + if (!latestInsertChar) + return; + let triggerSources = sources_default.getTriggerSources(pretext, doc.filetype, doc.uri); + if (triggerSources.length) { + await this.triggerCompletion(doc, this.pretext); + return; + } + this.triggerTimer = setTimeout(async () => { + await this.triggerCompletion(doc, pretext); + }, this.config.triggerCompletionWait); + return; + } + if (!option || bufnr != option.bufnr) + return; + if (option.linenr != info.lnum || option.col >= info.col - 1) { + this.stop(); + return; + } + if (noChange && !latestInsertChar) { + this.stop(false); + return; + } + if (pretext && this.selectedItem && this.config.acceptSuggestionOnCommitCharacter && latestInsertChar) { + let resolvedItem = this.getCompleteItem(this.selectedItem); + let last = pretext[pretext.length - 1]; + if (sources_default.shouldCommit(resolvedItem, last)) { + 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]); + await doc.patchChange(); + return; + } + } + if (sources_default.shouldTrigger(pretext, doc.filetype, doc.uri)) { + await this.triggerCompletion(doc, pretext); + } else { + await this.resumeCompletion(); + } + } + async triggerCompletion(doc, pre) { + if (!doc || !doc.attached) { + logger81.warn("Document not attached, suggest disabled."); + return; + } + let shouldTrigger = this.shouldTrigger(doc, pre); + if (!shouldTrigger) + return; + if (doc.getVar("suggest_disable")) { + logger81.warn(`Suggest disabled by b:coc_suggest_disable`); + return; + } + await doc.patchChange(); + let [disabled, option] = await this.nvim.eval('[get(b:,"coc_suggest_disable",0),coc#util#get_complete_option()]'); + if (disabled == 1) { + logger81.warn(`Suggest disabled by b:coc_suggest_disable`); + return; + } + if (option.blacklist && option.blacklist.includes(option.input)) { + logger81.warn(`Suggest disabled by b:coc_suggest_blacklist`, option.blacklist); + return; + } + if (pre.length) { + option.triggerCharacter = pre.slice(-1); + } + logger81.debug("trigger completion with", option); + await this.startCompletion(option); + } + async onCompleteDone(item) { + let { document: document2, isActivated } = this; + if (!isActivated || !document2 || !vimCompleteItem(item)) + 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; + let source = new import_vscode_languageserver_protocol79.CancellationTokenSource(); + await this.doCompleteResolve(resolvedItem, source.token); + source.dispose(); + await wait(50); + if (this.insertCharTs != timestamp || this.insertLeaveTs != insertLeaveTs) + return; + let [visible, lnum, pre] = await this.nvim.eval(`[pumvisible(),line('.'),strpart(getline('.'), 0, col('.') - 1)]`); + if (visible || lnum != opt.linenr || this.activated || !pre.endsWith(resolvedItem.word)) + return; + await document2.patchChange(true); + await this.doCompleteDone(resolvedItem, opt); + } + async doCompleteResolve(item, token) { + let source = sources_default.getSource(item.source); + if (source && typeof source.onCompleteResolve == "function") { + try { + await Promise.resolve(source.onCompleteResolve(item, token)); + } catch (e) { + logger81.error("Error on complete resolve:", e.stack); + } + } + } + async doCompleteDone(item, opt) { + let data = JSON.parse(item.user_data); + let source = sources_default.getSource(data.source); + if (source && typeof source.onCompleteDone === "function") { + await Promise.resolve(source.onCompleteDone(item, opt)); + } + } + async onInsertLeave() { + this.insertLeaveTs = Date.now(); + this.stop(false); + } + async onInsertEnter(bufnr) { + if (!this.config.triggerAfterInsertEnter || this.config.autoTrigger !== "always") + return; + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return; + let pre = await this.nvim.eval(`strpart(getline('.'), 0, col('.') - 1)`); + if (!pre) + return; + await this.triggerCompletion(doc, pre); + } + 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; + } + shouldTrigger(doc, pre) { + let autoTrigger = this.config.autoTrigger; + if (autoTrigger == "none") + return false; + if (sources_default.shouldTrigger(pre, doc.filetype, doc.uri)) + return true; + if (autoTrigger !== "always" || this.isActivated) + return false; + let last = pre.slice(-1); + if (last && (doc.isWord(pre.slice(-1)) || last.codePointAt(0) > 255)) { + let minLength = this.config.minTriggerInputLength; + if (minLength == 1) + return true; + let input = this.getInput(doc, pre); + return input.length >= minLength; + } + return false; + } + async onPumChange() { + if (!this.popupEvent) + return; + let { col, row, height, width, scrollbar } = this.popupEvent; + let bounding = { col, row, height, width, scrollbar }; + let resolvedItem = this.getCompleteItem(this.selectedItem); + if (!resolvedItem) { + this.floating.close(); + return; + } + let source = this.resolveTokenSource = new import_vscode_languageserver_protocol79.CancellationTokenSource(); + let { token } = source; + await this.doCompleteResolve(resolvedItem, token); + if (this.resolveTokenSource == source) { + this.resolveTokenSource = null; + } + source.dispose(); + 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 (this.config.floatEnable) { + let source2 = new import_vscode_languageserver_protocol79.CancellationTokenSource(); + await this.floating.show(docs, bounding, Object.assign({}, this.config.floatConfig, { + excludeImages: this.excludeImages + }), source2.token); + } + if (!this.isActivated) { + this.floating.close(); + } + } + } + start(complete) { + let { activated } = this; + this.activated = true; + if (activated) { + this.complete.dispose(); + } + this.complete = complete; + if (!this.config.keepCompleteopt) { + this.nvim.command(`noa set completeopt=${this.completeOpt}`, true); + } + } + cancelResolve() { + if (this.resolveTokenSource) { + this.resolveTokenSource.cancel(); + this.resolveTokenSource = null; + } + } + stop(hide = true) { + let { nvim } = this; + if (!this.activated) + return; + this.cancelResolve(); + this.floating.close(); + this.activated = false; + if (this.complete) { + this.complete.dispose(); + this.complete = null; + } + nvim.pauseNotification(); + if (hide) { + nvim.call("coc#_hide", [], true); + } + if (this.config.numberSelect) { + nvim.call("coc#_unmap", [], true); + } + if (!this.config.keepCompleteopt) { + nvim.command(`noa set completeopt=${workspace_default.completeOpt}`, true); + } + nvim.command(`let g:coc#_context = {'start': 0, 'preselect': -1,'candidates': []}`, true); + nvim.resumeNotification(false, true); + } + getInput(document2, pre) { + let input = ""; + for (let i = pre.length - 1; i >= 0; i--) { + let ch = i == 0 ? null : pre[i - 1]; + if (!ch || !document2.isWord(ch)) { + input = pre.slice(i, pre.length); + break; + } + } + return input; + } + getResumeInput() { + let { option, pretext } = this; + if (!option) + return null; + let buf = Buffer.from(pretext, "utf8"); + if (buf.length < option.col) + return null; + let input = buf.slice(option.col).toString("utf8"); + if (option.blacklist && option.blacklist.includes(input)) + return null; + return input; + } + get completeOpt() { + let { noselect, enablePreview } = this.config; + let preview = enablePreview && !workspace_default.env.pumevent ? ",preview" : ""; + if (noselect) + return `noselect,menuone${preview}`; + return `noinsert,menuone${preview}`; + } + getCompleteItem(item) { + if (!this.complete || !vimCompleteItem(item)) + return null; + return this.complete.resolveCompletionItem(item); + } + dispose() { + this.resolveTokenSource = null; + disposeAll(this.disposables); + } + }; + completion_default = new Completion(); + } +}); + +// src/snippets/snippet.ts +var import_vscode_languageserver_protocol80, logger82, CocSnippet; +var init_snippet = __esm({ + "src/snippets/snippet.ts"() { + import_vscode_languageserver_protocol80 = __toModule(require_main2()); + init_main2(); + init_position(); + init_parser2(); + init_string(); + logger82 = require_logger2()("snippets-snipet"); + CocSnippet = class { + constructor(_snippetString, position, _variableResolver) { + this._snippetString = _snippetString; + this.position = position; + this._variableResolver = _variableResolver; + this._parser = new SnippetParser(); + } + async init() { + const snippet = this._parser.parse(this._snippetString, true); + let { _variableResolver } = this; + if (_variableResolver) { + await 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(edit2, changedLine) { + let { range, newText } = edit2; + if (comparePosition(this.range.start, range.end) < 0) { + let { start, end } = range; + let overlaped = end.character - this.range.start.character; + if (changedLine && comparePosition(this.range.start, start) > 0 && isSingleLine(range) && start.character - overlaped >= 0 && changedLine.slice(start.character - overlaped, start.character) == changedLine.slice(this.range.start.character, this.range.start.character + overlaped)) { + edit2.range = range = import_vscode_languageserver_protocol80.Range.create(start.line, start.character - overlaped, end.line, end.character - overlaped); + } else { + return false; + } + } + if (!newText.includes("\n") && comparePosition(range.start, range.end) == 0 && comparePosition(this.range.start, range.start) == 0) { + let idx = this._placeholders.findIndex((o) => comparePosition(o.range.start, range.start) == 0); + if (idx !== -1) + return false; + } + let changed = getChangedPosition(this.range.start, edit2); + if (changed.line == 0 && changed.character == 0) + return true; + this.adjustPosition(changed.character, changed.line); + return true; + } + get isPlainText() { + if (this._placeholders.length > 1) + return false; + return this._placeholders.every((o) => o.value == ""); + } + get finalCount() { + return this._placeholders.filter((o) => o.isFinalTabstop).length; + } + toString() { + return this.tmSnippet.toString(); + } + get range() { + let { position } = this; + const content = this.tmSnippet.toString(); + const doc = TextDocument2.create("untitled:/1", "snippet", 0, content); + const pos = doc.positionAt(content.length); + const end = pos.line == 0 ? position.character + pos.character : pos.character; + return import_vscode_languageserver_protocol80.Range.create(position, import_vscode_languageserver_protocol80.Position.create(position.line + pos.line, end)); + } + get firstPlaceholder() { + let index = 0; + for (let p of this._placeholders) { + if (p.index == 0) + continue; + if (index == 0 || p.index < index) { + index = p.index; + } + } + return this.getPlaceholder(index); + } + get lastPlaceholder() { + let index = 0; + for (let p of this._placeholders) { + if (index == 0 || p.index > index) { + index = p.index; + } + } + return this.getPlaceholder(index); + } + 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 indexes = this._placeholders.map((o) => o.index); + let max = Math.max.apply(null, indexes); + 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) => rangeInRange(range, o.range)); + } + insertSnippet(placeholder, snippet, range) { + let { start } = placeholder.range; + let editStart = import_vscode_languageserver_protocol80.Position.create(range.start.line - start.line, range.start.line == start.line ? range.start.character - start.character : range.start.character); + let editEnd = import_vscode_languageserver_protocol80.Position.create(range.end.line - start.line, range.end.line == start.line ? range.end.character - start.character : range.end.character); + let editRange2 = import_vscode_languageserver_protocol80.Range.create(editStart, editEnd); + let first = this.tmSnippet.insertSnippet(snippet, placeholder.id, editRange2); + this.update(); + return first; + } + updatePlaceholder(placeholder, edit2) { + let { range } = this; + let { value, id, index } = placeholder; + let newText = editRange(placeholder.range, value, edit2); + let delta = 0; + if (!newText.includes("\n")) { + 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 + byteLength(text) - byteLength(p.value); + } + } + } + if (placeholder.isVariable) { + this.tmSnippet.updateVariable(id, newText); + } else { + this.tmSnippet.updatePlaceholder(id, newText); + } + let endPosition = adjustPosition(range.end, edit2); + let snippetEdit = { + range: import_vscode_languageserver_protocol80.Range.create(range.start, endPosition), + newText: this.tmSnippet.toString() + }; + this.update(); + return { edits: [snippetEdit], delta }; + } + update() { + const snippet = this.tmSnippet; + const { line, character } = this.position; + const document2 = TextDocument2.create("untitled:/1", "snippet", 0, snippet.toString()); + const { placeholders, variables, maxIndexNumber } = snippet; + const variableIndexMap = new Map(); + let variableIndex = maxIndexNumber + 1; + this._placeholders = [...placeholders, ...variables].map((p, idx) => { + const offset = snippet.offset(p); + const position = document2.positionAt(offset); + const start = { + line: line + position.line, + character: position.line == 0 ? character + position.character : position.character + }; + let index; + if (p instanceof Variable) { + let key = p.name; + if (variableIndexMap.has(key)) { + index = variableIndexMap.get(key); + } else { + variableIndexMap.set(key, variableIndex); + index = variableIndex; + variableIndex = variableIndex + 1; + } + } else { + index = p.index; + } + const value = p.toString(); + const lines = value.split(/\r?\n/); + let res = { + range: import_vscode_languageserver_protocol80.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, + value, + isVariable: p instanceof Variable, + isFinalTabstop: p.index === 0 + }; + Object.defineProperty(res, "snippet", { + enumerable: false + }); + if (p instanceof Placeholder && p.choice) { + let { options } = p.choice; + if (options && options.length) { + res.choice = options.map((o) => o.value); + } + } + return res; + }); + } + }; + } +}); + +// src/snippets/variableResolve.ts +var import_path33, logger83, SnippetVariableResolver; +var init_variableResolve = __esm({ + "src/snippets/variableResolve.ts"() { + import_path33 = __toModule(require("path")); + init_window(); + logger83 = require_logger2()("snippets-variable"); + SnippetVariableResolver = class { + constructor() { + this._variableToValue = {}; + const currentDate = new Date(); + Object.assign(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" }), + TM_FILENAME: null, + TM_FILENAME_BASE: null, + TM_DIRECTORY: null, + TM_FILEPATH: null, + YANK: null, + TM_LINE_INDEX: null, + TM_LINE_NUMBER: null, + TM_CURRENT_LINE: null, + TM_CURRENT_WORD: null, + TM_SELECTED_TEXT: null, + CLIPBOARD: null + }); + } + async resolveValue(name2) { + let { nvim } = window_default; + if (["TM_FILENAME", "TM_FILENAME_BASE", "TM_DIRECTORY", "TM_FILEPATH"].includes(name2)) { + let filepath = await nvim.eval('expand("%:p")'); + if (name2 == "TM_FILENAME") + return import_path33.default.basename(filepath); + if (name2 == "TM_FILENAME_BASE") + return import_path33.default.basename(filepath, import_path33.default.extname(filepath)); + if (name2 == "TM_DIRECTORY") + return import_path33.default.dirname(filepath); + if (name2 == "TM_FILEPATH") + return filepath; + } + if (name2 == "YANK") { + let yank = await nvim.call("getreg", ['""']); + return yank; + } + if (name2 == "TM_LINE_INDEX") { + let lnum = await nvim.call("line", ["."]); + return (lnum - 1).toString(); + } + if (name2 == "TM_LINE_NUMBER") { + let lnum = await nvim.call("line", ["."]); + return lnum.toString(); + } + if (name2 == "TM_CURRENT_LINE") { + let line = await nvim.call("getline", ["."]); + return line; + } + if (name2 == "TM_CURRENT_WORD") { + let word = await nvim.eval(`expand('')`); + return word; + } + if (name2 == "TM_SELECTED_TEXT") { + let text = await nvim.eval(`get(g:,'coc_selected_text', '')`); + return text; + } + if (name2 == "CLIPBOARD") { + return await nvim.eval("@*"); + } + } + async resolve(variable) { + const name2 = variable.name; + let resolved = this._variableToValue[name2]; + if (resolved != null) + return resolved.toString(); + let value = await this.resolveValue(name2); + if (value) + return value; + if (variable.children && variable.children.length) { + return variable.toString(); + } + if (!this._variableToValue.hasOwnProperty(name2)) { + return name2; + } + return ""; + } + }; + } +}); + +// src/util/textedit.ts +function singleLineEdit(edit2) { + let { range, newText } = edit2; + return range.start.line == range.end.line && newText.indexOf("\n") == -1; +} +var init_textedit = __esm({ + "src/util/textedit.ts"() { + } +}); + +// src/snippets/session.ts +function normalizeSnippetString(snippet, indent, opts) { + let lines = snippet.split(/\r?\n/); + let ind = opts.insertSpaces ? " ".repeat(opts.tabSize) : " "; + let tabSize = opts.tabSize || 2; + lines = lines.map((line, idx) => { + let space = line.match(/^\s*/)[0]; + let pre = space; + let isTab = space.startsWith(" "); + 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"); +} +var import_vscode_languageserver_protocol81, logger84, SnippetSession; +var init_session2 = __esm({ + "src/snippets/session.ts"() { + import_vscode_languageserver_protocol81 = __toModule(require_main2()); + init_completion(); + init_position(); + init_string(); + init_workspace(); + init_window(); + init_events(); + init_snippet(); + init_variableResolve(); + init_textedit(); + logger84 = require_logger2()("snippets-session"); + SnippetSession = class { + constructor(nvim, bufnr) { + this.nvim = nvim; + this.bufnr = bufnr; + this._isActive = false; + this._currId = 0; + this.applying = false; + this.preferComplete = false; + this._snippet = null; + this._onCancelEvent = new import_vscode_languageserver_protocol81.Emitter(); + this.onCancel = this._onCancelEvent.event; + let suggest = workspace_default.getConfiguration("suggest"); + this.preferComplete = suggest.get("preferCompleteThanJumpPlaceholder", false); + } + async start(snippetString, select = true, range, insertTextMode) { + const { document: document2 } = this; + if (!document2 || !document2.attached) + return false; + void events_default.fire("InsertSnippet", []); + if (!range) { + let position2 = await window_default.getCursorPosition(); + range = import_vscode_languageserver_protocol81.Range.create(position2, position2); + } + let position = range.start; + const formatOptions = await workspace_default.getFormatOptions(this.document.uri); + await document2.patchChange(true); + const currentLine = document2.getline(position.line); + const currentIndent = currentLine.match(/^\s*/)[0]; + let inserted = ""; + if (insertTextMode === import_vscode_languageserver_protocol81.InsertTextMode.asIs) { + inserted = snippetString; + } else { + inserted = normalizeSnippetString(snippetString, currentIndent, formatOptions); + } + const resolver = new SnippetVariableResolver(); + const snippet = new CocSnippet(inserted, position, resolver); + await snippet.init(); + const edit2 = import_vscode_languageserver_protocol81.TextEdit.replace(range, snippet.toString()); + if (snippetString.endsWith("\n") && currentLine.slice(position.character).length) { + edit2.newText = edit2.newText + currentIndent; + inserted = inserted + currentIndent; + } + this.applying = true; + await document2.applyEdits([edit2]); + this.applying = false; + if (this._isActive) { + let placeholder = this.findPlaceholder(range); + if (placeholder && !placeholder.isFinalTabstop) { + 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; + } + } + if (snippet.isPlainText) { + this.deactivate(); + let placeholder = snippet.finalPlaceholder; + await window_default.moveTo(placeholder.range.start); + return false; + } + 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); + logger84.debug("[SnippetManager::cancel]"); + } + this._onCancelEvent.fire(void 0); + this._onCancelEvent.dispose(); + } + get isActive() { + return this._isActive; + } + async nextPlaceholder() { + if (!this.isActive) + return; + await this.document.patchChange(); + let curr = this.placeholder; + let next = this.snippet.getNextPlaceholder(curr.index); + await this.selectPlaceholder(next); + } + async previousPlaceholder() { + if (!this.isActive) + return; + await this.document.patchChange(); + let curr = this.placeholder; + let prev = this.snippet.getPrevPlaceholder(curr.index); + await this.selectPlaceholder(prev); + } + async synchronizeUpdatedPlaceholders(change, changedLine) { + if (!this.isActive || !this.document || this.applying) + return; + let edit2 = { range: change.range, newText: change.text }; + let { snippet } = this; + let adjusted = snippet.adjustTextEdit(edit2, changedLine); + if (adjusted) + return; + let currRange = this.placeholder.range; + if (changedLine != null && singleLineEdit(edit2) && !rangeInRange(edit2.range, currRange) && isSingleLine(currRange) && changedLine.slice(currRange.start.character, currRange.end.character) == this.placeholder.value && events_default.cursor && events_default.cursor.bufnr == this.bufnr && events_default.cursor.lnum == edit2.range.start.line + 1) { + let col = events_default.cursor.col; + let preText = changedLine.slice(0, currRange.start.character); + let postText = changedLine.slice(currRange.end.character); + let newLine = this.document.getline(edit2.range.start.line); + if (newLine.startsWith(preText) && newLine.endsWith(postText)) { + let endCharacter = newLine.length - postText.length; + let cursorIdx = characterIndex(newLine, col - 1); + if (cursorIdx >= preText.length && cursorIdx <= endCharacter) { + let newText = newLine.slice(preText.length, endCharacter); + edit2 = import_vscode_languageserver_protocol81.TextEdit.replace(currRange, newText); + } + } + } + if (comparePosition(edit2.range.start, snippet.range.end) > 0) { + if (!edit2.newText) + return; + logger84.info("Content change after snippet, cancelling snippet session"); + this.deactivate(); + return; + } + let placeholder = this.findPlaceholder(edit2.range); + if (!placeholder) { + logger84.info("Change outside placeholder, cancelling snippet session"); + this.deactivate(); + return; + } + if (placeholder.isFinalTabstop && snippet.finalCount <= 1) { + logger84.info("Change final placeholder, cancelling snippet session"); + this.deactivate(); + return; + } + this._currId = placeholder.id; + let { edits, delta } = snippet.updatePlaceholder(placeholder, edit2); + if (!edits.length) + return; + this.applying = true; + await this.document.applyEdits(edits); + this.applying = false; + if (delta) { + await this.nvim.call("coc#cursor#move_by_col", 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: document2 } = this; + if (!document2 || !placeholder) + return; + let { start, end } = placeholder.range; + const len = end.character - start.character; + const col = byteLength(document2.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]); + if (triggerAutocmd) + nvim.call("coc#util#do_autocmd", ["CocJumpPlaceholder"], true); + } else { + await this.select(placeholder, triggerAutocmd); + } + } + async select(placeholder, triggerAutocmd = true) { + let { range, value, isFinalTabstop } = placeholder; + let { document: document2, nvim } = this; + let { start, end } = range; + let { textDocument } = document2; + let len = textDocument.offsetAt(end) - textDocument.offsetAt(start); + let line = document2.getline(start.line); + let col = line ? byteLength(line.slice(0, start.character)) : 0; + let endLine = document2.getline(end.line); + let endCol = endLine ? byteLength(endLine.slice(0, end.character)) : 0; + nvim.setVar("coc_last_placeholder", { + bufnr: document2.bufnr, + current_text: value, + start: { line: start.line, col, character: start.character }, + end: { line: end.line, col: endCol, character: end.character } + }, true); + let [ve, selection, pumvisible, mode] = await nvim.eval("[&virtualedit, &selection, pumvisible(), mode()]"); + let move_cmd = ""; + if (pumvisible && this.preferComplete) { + let pre = completion_default.hasSelected() ? "" : "\\"; + await nvim.eval(`feedkeys("${pre}\\", 'in')`); + return; + } + if (mode != "n") + move_cmd += "\\"; + if (len == 0) { + if (col == 0 || !mode.startsWith("i") && col < 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\\`; + } + if (mode == "i" && move_cmd == "\\a") { + move_cmd = ""; + } + nvim.pauseNotification(); + nvim.setOption("virtualedit", "onemore", true); + nvim.call("cursor", [start.line + 1, col + (move_cmd == "a" ? 0 : 1)], true); + if (move_cmd) { + nvim.call("eval", [`feedkeys("${move_cmd}", 'in')`], true); + } + if (mode == "i") { + nvim.call("coc#_cancel", [], true); + } + nvim.setOption("virtualedit", ve, true); + if (isFinalTabstop) { + if (this.snippet.finalCount == 1) { + logger84.info("Jump to final placeholder, cancelling snippet session"); + this.deactivate(); + } else { + nvim.call("coc#snippet#disable", [], true); + } + } + if (workspace_default.env.isVim) + nvim.command("redraw", true); + await nvim.resumeNotification(); + if (triggerAutocmd) + nvim.call("coc#util#do_autocmd", ["CocJumpPlaceholder"], true); + } + async getVirtualCol(line, col) { + let { nvim } = this; + return await nvim.eval(`virtcol([${line}, ${col}])`); + } + async checkPosition() { + if (!this.isActive) + return; + let position = await window_default.getCursorPosition(); + if (this.snippet && positionInRange(position, this.snippet.range) != 0) { + logger84.info("Cursor insert out of range, cancelling snippet session"); + this.deactivate(); + } + } + findPlaceholder(range) { + if (!this.snippet) + return null; + let { placeholder } = this; + if (placeholder && rangeInRange(range, placeholder.range)) + return placeholder; + return this.snippet.getPlaceholderByRange(range) || null; + } + get placeholder() { + if (!this.snippet) + return null; + return this.snippet.getPlaceholderById(this._currId); + } + get snippet() { + return this._snippet; + } + get document() { + return workspace_default.getDocument(this.bufnr); + } + }; + } +}); + +// src/snippets/manager.ts +var logger85, SnippetManager, manager_default3; +var init_manager4 = __esm({ + "src/snippets/manager.ts"() { + init_events(); + init_workspace(); + init_window(); + init_parser2(); + init_session2(); + init_variableResolve(); + init_string2(); + logger85 = require_logger2()("snippets-manager"); + SnippetManager = class { + constructor() { + this.sessionMap = new Map(); + this.disposables = []; + workspace_default.onDidChangeTextDocument(async (e) => { + let session = this.getSession(e.bufnr); + if (session) { + let firstLine = e.originalLines[e.contentChanges[0].range.start.line] || ""; + await session.synchronizeUpdatedPlaceholders(e.contentChanges[0], firstLine); + } + }, null, this.disposables); + workspace_default.onDidCloseTextDocument((textDocument) => { + let doc = workspace_default.getDocument(textDocument.uri); + if (!doc) + return; + let session = this.getSession(doc.bufnr); + if (session) + session.deactivate(); + }, null, this.disposables); + events_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_default.on("InsertEnter", async () => { + let { session } = this; + if (!session) + return; + await session.checkPosition(); + }, null, this.disposables); + } + init() { + let config = workspace_default.getConfiguration("coc.preferences"); + this.statusItem = window_default.createStatusBarItem(0); + this.statusItem.text = config.get("snippetStatusText", "SNIP"); + } + async insertSnippet(snippet, select = true, range, insertTextMode) { + let { bufnr } = workspace_default; + let session = this.getSession(bufnr); + if (!session) { + session = new SnippetSession(workspace_default.nvim, bufnr); + this.sessionMap.set(bufnr, session); + session.onCancel(() => { + this.sessionMap.delete(bufnr); + if (workspace_default.bufnr == bufnr) { + this.statusItem.hide(); + } + }); + } + let snippetStr = SnippetString.isSnippetString(snippet) ? snippet.value : snippet; + let isActive = await session.start(snippetStr, select, range, insertTextMode); + if (isActive) + this.statusItem.show(); + return isActive; + } + async selectCurrentPlaceholder(triggerAutocmd = true) { + let { session } = this; + if (session) + return await session.selectCurrentPlaceholder(triggerAutocmd); + } + async nextPlaceholder() { + let { session } = this; + if (session) { + await session.nextPlaceholder(); + } else { + workspace_default.nvim.call("coc#snippet#disable", [], true); + this.statusItem.hide(); + } + return ""; + } + async previousPlaceholder() { + let { session } = this; + if (session) { + await session.previousPlaceholder(); + } else { + workspace_default.nvim.call("coc#snippet#disable", [], true); + this.statusItem.hide(); + } + return ""; + } + cancel() { + let session = this.getSession(workspace_default.bufnr); + if (session) + return session.deactivate(); + workspace_default.nvim.call("coc#snippet#disable", [], true); + if (this.statusItem) + this.statusItem.hide(); + } + get session() { + let session = this.getSession(workspace_default.bufnr); + return session && session.isActive ? session : null; + } + isActived(bufnr) { + let session = this.getSession(bufnr); + return session && session.isActive ? true : false; + } + 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 parser2 = new SnippetParser(); + const snippet = parser2.parse(body, true); + const resolver = new SnippetVariableResolver(); + await snippet.resolveVariables(resolver); + return snippet; + } + dispose() { + this.cancel(); + for (let d of this.disposables) { + d.dispose(); + } + } + }; + manager_default3 = new SnippetManager(); + } +}); + +// src/commands.ts +var import_vscode_languageserver_protocol82, logger86, CommandItem, CommandManager, commands_default; +var init_commands2 = __esm({ + "src/commands.ts"() { + import_vscode_languageserver_protocol82 = __toModule(require_main2()); + init_esm2(); + init_manager(); + init_manager4(); + init_util(); + init_workspace(); + init_window(); + logger86 = require_logger2()("commands"); + CommandItem = class { + 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; + } + }; + CommandManager = class { + constructor() { + this.commands = new Map(); + this.titles = new Map(); + this.onCommandList = []; + } + init(nvim, plugin) { + this.mru = workspace_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: async () => { + await nvim.command("edit"); + } + }, true); + this.register({ + id: "editor.action.insertSnippet", + execute: async (edit2) => { + nvim.call("coc#_cancel", [], true); + return await manager_default3.insertSnippet(edit2.newText, true, edit2.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 wait(60); + nvim.call("coc#start", [], true); + } + }, true); + this.register({ + id: "editor.action.triggerParameterHints", + execute: async () => { + await 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 wait(30); + nvim.command("CocRestart", true); + } + }, true); + this.register({ + id: "editor.action.showReferences", + execute: async (_filepath, _position, references) => { + await workspace_default.showLocations(references); + } + }, true); + this.register({ + id: "editor.action.rename", + execute: async (uri, position) => { + await workspace_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.clearWatchman", + execute: async () => { + let res = await window_default.runTerminalCommand("watchman watch-del-all"); + if (res.success) + window_default.showMessage("Cleared watchman watching directories."); + } + }, false, "run watch-del-all for watchman to free up memory."); + this.register({ + id: "workspace.workspaceFolders", + execute: async () => { + let folders = workspace_default.workspaceFolders; + let lines = folders.map((folder) => URI.parse(folder.uri).fsPath); + await window_default.echoLines(lines); + } + }, false, "show opened workspaceFolders."); + this.register({ + id: "workspace.renameCurrentFile", + execute: async () => { + await workspace_default.renameCurrent(); + } + }, false, "change current filename to a new name and reload it."); + this.register({ + id: "extensions.toggleAutoUpdate", + execute: async () => { + let config = workspace_default.getConfiguration("coc.preferences"); + let interval = config.get("extensionUpdateCheck", "daily"); + if (interval == "never") { + config.update("extensionUpdateCheck", "daily", true); + window_default.showMessage("Extension auto update enabled.", "more"); + } else { + config.update("extensionUpdateCheck", "never", true); + window_default.showMessage("Extension auto update disabled.", "more"); + } + } + }, false, "toggle auto update of extensions."); + this.register({ + id: "workspace.diagnosticRelated", + execute: () => manager_default.jumpRelated() + }, false, "jump to related locations of current diagnostic."); + this.register({ + id: "workspace.showOutput", + execute: async (name2) => { + if (name2) { + window_default.showOutputChannel(name2); + } else { + let names = workspace_default.channelNames; + if (names.length == 0) + return; + if (names.length == 1) { + window_default.showOutputChannel(names[0]); + } else { + let idx = await window_default.showQuickpick(names); + if (idx == -1) + return; + let name3 = names[idx]; + window_default.showOutputChannel(name3); + } + } + } + }, false, "open output buffer to show output from languageservers or extensions."); + this.register({ + id: "document.showIncomingCalls", + execute: async () => { + await plugin.cocAction("showIncomingCalls"); + } + }, false, "show incoming calls in tree view."); + this.register({ + id: "document.showOutgoingCalls", + execute: async () => { + await plugin.cocAction("showOutgoingCalls"); + } + }, false, "show outgoing calls in tree view."); + this.register({ + id: "document.echoFiletype", + execute: async () => { + let bufnr = await nvim.call("bufnr", "%"); + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return; + await window_default.echoLines([doc.filetype]); + } + }, false, "echo the mapped filetype of the current buffer"); + this.register({ + id: "document.renameCurrentWord", + execute: async () => { + let bufnr = await nvim.call("bufnr", "%"); + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return; + let edit2 = await plugin.cocAction("getWordEdit"); + if (!edit2) { + window_default.showMessage("Invalid position", "warning"); + return; + } + let ranges = []; + let { changes, documentChanges } = edit2; + if (changes) { + let edits = changes[doc.uri]; + if (edits) + ranges = edits.map((e) => e.range); + } else if (documentChanges) { + for (let c of documentChanges) { + if (import_vscode_languageserver_protocol82.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_default.document; + if (!doc) + return; + let ranges = await plugin.cocAction("symbolRanges"); + if (!ranges) + return; + let { textDocument } = doc; + let offset = await window_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 window_default.moveTo(ranges[i].start); + return; + } + } + await window_default.moveTo(ranges[0].start); + } + }, false, "Jump to next symbol highlight position."); + this.register({ + id: "workspace.openLocation", + execute: async (winid, loc, openCommand) => { + if (winid) + await nvim.call("win_gotoid", [winid]); + await workspace_default.jumpTo(loc.uri, loc.range.start, openCommand); + } + }, true); + this.register({ + id: "document.jumpToPrevSymbol", + execute: async () => { + let doc = await workspace_default.document; + if (!doc) + return; + let ranges = await plugin.cocAction("symbolRanges"); + if (!ranges) + return; + let { textDocument } = doc; + let offset = await window_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 = ranges.length - 1; i >= 0; i--) { + if (textDocument.offsetAt(ranges[i].end) < offset) { + await window_default.moveTo(ranges[i].start); + return; + } + } + await window_default.moveTo(ranges[ranges.length - 1].start); + } + }, false, "Jump to previous 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); + return 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); + } + registerCommand(id, impl, thisArg, internal = false) { + if (id.startsWith("_")) + internal = true; + this.commands.set(id, new CommandItem(id, impl, thisArg, internal)); + return import_vscode_languageserver_protocol82.Disposable.create(() => { + this.commands.delete(id); + }); + } + executeCommand(command, ...rest) { + let cmd = this.commands.get(command); + if (!cmd) + throw new Error(`Command: ${command} not found`); + return Promise.resolve(cmd.execute.apply(cmd, rest)); + } + async addRecent(cmd) { + await this.mru.add(cmd); + await workspace_default.nvim.command(`silent! call repeat#set("\\(coc-command-repeat)", -1)`); + } + async repeatCommand() { + let mruList = await this.mru.load(); + let first = mruList[0]; + if (first) { + await this.executeCommand(first); + await workspace_default.nvim.command(`silent! call repeat#set("\\(coc-command-repeat)", -1)`); + } + } + }; + commands_default = new CommandManager(); + } +}); + +// src/cursors/range.ts +var logger87, TextRange; +var init_range = __esm({ + "src/cursors/range.ts"() { + init_main(); + init_position(); + logger87 = require_logger2()("cursors-range"); + TextRange = class { + constructor(line, start, end, text, 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 Range.create(this.line, this.start, this.line, this.end); + } + get currRange() { + return Range.create(this.line, this.currStart, this.line, this.currEnd); + } + applyEdit(edit2) { + let { range, newText } = edit2; + 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); + } + } + adjustFromEdit(edit2) { + let { range, newText } = edit2; + if (comparePosition(range.start, Position.create(this.line, this.currEnd)) > 0) { + return; + } + let newLines = newText.split("\n"); + let changeCount = newLines.length - (range.end.line - range.start.line + 1); + this.line = this.line + changeCount; + if (range.end.line == this.line) { + let remove = range.start.line == range.end.line ? range.end.character - range.start.character : range.end.character; + if (newLines.length > 1 && range.start.line == range.end.line) { + remove = remove + range.start.character; + } + let add = 0; + if (newLines.length > 1) { + add = newLines[newLines.length - 1].length; + } else { + if (range.start.line == range.end.line) { + add = newText.length; + } else { + add = range.start.character + newText.length; + } + } + let delta = add - remove; + for (let key of ["start", "end", "currStart", "currEnd"]) { + this[key] += delta; + } + } + } + sync() { + this.start = this.currStart; + this.end = this.currEnd; + } + get textEdit() { + return { + range: this.range, + newText: this.text + }; + } + }; + } +}); + +// src/cursors/util.ts +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(import_vscode_languageserver_protocol83.Range.create(i, sc, i, ec)); + } + return splited; +} +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(import_vscode_languageserver_protocol83.Range.create(i, sc, i, Math.min(line.length, ec))); + } + return ranges; +} +function adjustPosition2(position, delta) { + let { line, character } = delta; + return import_vscode_languageserver_protocol83.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; +} +var import_vscode_languageserver_protocol83; +var init_util4 = __esm({ + "src/cursors/util.ts"() { + import_vscode_languageserver_protocol83 = __toModule(require_main2()); + } +}); + +// src/cursors/session.ts +var import_fast_diff4, import_vscode_languageserver_protocol84, logger88, CursorSession; +var init_session3 = __esm({ + "src/cursors/session.ts"() { + import_fast_diff4 = __toModule(require_diff()); + import_vscode_languageserver_protocol84 = __toModule(require_main2()); + init_main2(); + init_events(); + init_position(); + init_window(); + init_workspace(); + init_range(); + init_util4(); + logger88 = require_logger2()("cursors-session"); + CursorSession = class { + constructor(nvim, doc, config) { + this.nvim = nvim; + this.doc = doc; + this.config = config; + this._onDidCancel = new import_vscode_languageserver_protocol84.Emitter(); + this.onDidCancel = this._onDidCancel.event; + this.disposables = []; + this.ranges = []; + this.activated = true; + this.changing = false; + this.changed = false; + this.textDocument = this.doc.textDocument; + this.buffer.setVar("coc_cursors_activated", 1, true); + let { cancelKey, nextKey, previousKey } = this.config; + this.disposables.push(workspace_default.registerLocalKeymap("n", cancelKey, () => { + this.cancel(); + }, true)); + this.disposables.push(workspace_default.registerLocalKeymap("n", nextKey, async () => { + if (!this.activated) + return; + let ranges = this.ranges.map((o) => o.currRange); + let curr = await window_default.getCursorPosition(); + for (let r of ranges) { + if (comparePosition(r.start, curr) > 0) { + await window_default.moveTo(r.start); + return; + } + } + if (ranges.length) + await window_default.moveTo(ranges[0].start); + }, true)); + this.disposables.push(workspace_default.registerLocalKeymap("n", previousKey, async () => { + if (!this.activated) + return; + let ranges = this.ranges.map((o) => o.currRange); + ranges.reverse(); + let curr = await window_default.getCursorPosition(); + for (let r of ranges) { + if (comparePosition(r.end, curr) < 0) { + await window_default.moveTo(r.start); + return; + } + } + if (ranges.length) + await window_default.moveTo(ranges[ranges.length - 1].start); + }, true)); + this.doc.onDocumentChange(this.onChange, this, this.disposables); + } + async onChange(e) { + if (!this.activated || this.ranges.length == 0) + return; + if (this.changing) + return; + let change = e.contentChanges[0]; + let { text, range } = change; + let intersect = this.ranges.some((r) => rangeIntersect(range, r.currRange)); + let begin = this.ranges[0].currRange.start; + if (text.endsWith("\n") && comparePosition(begin, range.end) == 0) { + intersect = false; + } + if (!intersect) { + this.ranges.forEach((r) => { + r.adjustFromEdit({ range, newText: text }); + }); + this.doHighlights(); + this.textDocument = this.doc.textDocument; + return; + } + this.changed = true; + let textRange = this.getTextRange(range, text); + if (textRange) { + await this.applySingleEdit(textRange, { range, newText: text }); + } else { + this.applyComposedEdit(e.original, { range, newText: text }); + if (this.activated) { + this.ranges.forEach((r) => { + r.sync(); + }); + this.textDocument = this.doc.textDocument; + } + } + } + doHighlights() { + let { nvim, buffer, ranges } = this; + buffer.clearNamespace("cursors"); + let arr = ranges.map((o) => o.currRange); + buffer.highlightRanges("cursors", "CocCursorRange", arr); + nvim.command("redraw", true); + } + addRanges(ranges) { + let { nvim, doc } = this; + if (this.changed) { + window_default.showMessage(`Can't add ranges after range change.`); + return false; + } + this.ranges = this.ranges.filter((r) => { + let { currRange } = r; + return !ranges.some((range) => rangeOverlap(range, currRange)); + }); + let { textDocument } = doc; + for (let range of ranges) { + let { line } = range.start; + let textRange = new TextRange(line, range.start.character, range.end.character, textDocument.getText(range), 0); + this.ranges.push(textRange); + } + this.ranges.sort((a, b) => comparePosition(a.range.start, b.range.start)); + 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; + } + nvim.pauseNotification(); + this.doHighlights(); + nvim.resumeNotification(false, true); + return true; + } + cancel() { + if (!this.activated) + return; + let { nvim } = this; + this.activated = false; + let { cancelKey, nextKey, previousKey } = this.config; + nvim.pauseNotification(); + this.buffer.clearNamespace("cursors"); + this.buffer.setVar("coc_cursors_activated", 0, true); + nvim.command("redraw", true); + nvim.resumeNotification(false, true); + this._onDidCancel.fire(); + } + dispose() { + if (!this.doc) + return; + this._onDidCancel.dispose(); + for (let disposable of this.disposables) { + disposable.dispose(); + } + this.ranges = []; + this.doc = null; + this.textDocument = null; + } + get buffer() { + return this.nvim.createBuffer(this.doc.bufnr); + } + getTextRange(range, text) { + let { ranges } = this; + 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 (rangeInRange(range, r.currRange)) { + return r; + } + if (r.line != range.start.line) { + continue; + } + if (text.length && range.start.character == r.currRange.end.character) { + let next = ranges[i + 1]; + if (!next) + return r; + return positionInRange(next.currRange.start, range) ? null : r; + } + } + return null; + } + adjustRanges(textRange, range, text) { + let { ranges } = this; + if (range.start.character == range.end.character) { + 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 { + 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) { + if (text.includes(textRange.text)) { + 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.includes(text)) { + 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) { + if (this.changed) { + window_default.showMessage(`Can't add range after range change.`); + return; + } + let { ranges } = this; + let idx = ranges.findIndex((o) => rangeIntersect(o.range, range)); + if (idx !== -1) { + ranges.splice(idx, 1); + 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 idx2 = 0; + let { line } = range.start; + for (let r of ranges) { + if (r.line > line || r.line == line && r.start > range.end.character) { + break; + } + if (r.line == line) + preCount++; + idx2++; + } + let created = new TextRange(line, range.start.character, range.end.character, text, preCount); + ranges.splice(idx2, 0, created); + for (let r of ranges) { + if (r.line == range.start.line && r.start > range.start.character) { + r.preCount = r.preCount + 1; + } + } + } + if (this.ranges.length == 0) { + this.cancel(); + } else { + this.doHighlights(); + } + } + async applySingleEdit(textRange, edit2) { + let { range, newText } = edit2; + let { doc } = this; + this.adjustRanges(textRange, range, newText); + if (this.ranges.length == 1) { + this.doHighlights(); + return; + } + let edits = this.ranges.map((o) => o.textEdit); + let content = TextDocument2.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.changing = true; + await doc.changeLines(arr); + this.changing = false; + if (this.activated) { + this.ranges.forEach((r) => { + r.sync(); + }); + this.textDocument = this.doc.textDocument; + } + nvim.pauseNotification(); + let { cursor } = events_default; + if (textRange.preCount > 0 && cursor.bufnr == doc.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(); + nvim.resumeNotification(false, true); + } + applyComposedEdit(original, edit2) { + let { range, newText } = edit2; + let { ranges } = this; + let doc = TextDocument2.create("file:///1", "", 0, original); + let edits = []; + let diffs = (0, import_fast_diff4.default)(original, newText); + let offset = 0; + for (let i = 0; i < diffs.length; i++) { + let diff = diffs[i]; + let pos = adjustPosition2(range.start, doc.positionAt(offset)); + if (diff[0] == import_fast_diff4.default.EQUAL) { + offset = offset + diff[1].length; + } else if (diff[0] == import_fast_diff4.default.DELETE) { + let end = adjustPosition2(range.start, doc.positionAt(offset + diff[1].length)); + if (diffs[i + 1] && diffs[i + 1][0] == import_fast_diff4.default.INSERT) { + edits.push({ range: import_vscode_languageserver_protocol84.Range.create(pos, end), newText: diffs[i + 1][1] }); + i = i + 1; + } else { + edits.push({ range: import_vscode_languageserver_protocol84.Range.create(pos, end), newText: "" }); + } + offset = offset + diff[1].length; + } else if (diff[0] == import_fast_diff4.default.INSERT) { + edits.push({ range: import_vscode_languageserver_protocol84.Range.create(pos, pos), newText: diff[1] }); + } + } + if (edits.some((edit3) => edit3.newText.includes("\n") || edit3.range.start.line != edit3.range.end.line)) { + this.cancel(); + return; + } + if (edits.length == ranges.length) { + let last; + for (let i = 0; i < edits.length; i++) { + let edit3 = edits[i]; + let textRange = this.ranges[i]; + if (!rangeIntersect(textRange.currRange, edit3.range)) { + this.cancel(); + return; + } + if (last && !equalEdit(edit3, last)) { + this.cancel(); + return; + } + textRange.applyEdit(edit3); + last = edit3; + } + } else if (edits.length == ranges.length * 2) { + for (let i = 0; i < edits.length - 1; i = i + 2) { + let edit3 = edits[i]; + let next = edits[i + 1]; + if (edit3.newText.length == 0 && next.newText.length == 0) { + let textRange = this.ranges[i / 2]; + if (comparePosition(textRange.currRange.end, next.range.end) != 0) { + this.cancel(); + return; + } + let start = edit3.range.start.character - textRange.currRange.start.character; + textRange.replace(start, edit3.range.end.character - edit3.range.start.character, ""); + let offset2 = next.range.end.character - next.range.start.character; + let len = textRange.text.length; + textRange.replace(len - offset2, len); + } else if (emptyRange(edit3.range) && emptyRange(next.range)) { + let textRange = this.ranges[i / 2]; + if (comparePosition(textRange.currRange.end, next.range.start) != 0) { + this.cancel(); + return; + } + let start = edit3.range.start.character - textRange.currRange.start.character; + textRange.add(start, edit3.newText); + let len = textRange.text.length; + textRange.add(len, next.newText); + } else { + this.cancel(); + return; + } + } + } else { + this.cancel(); + return; + } + this.doHighlights(); + } + }; + } +}); + +// src/cursors/index.ts +var logger89, Cursors; +var init_cursors = __esm({ + "src/cursors/index.ts"() { + init_main(); + init_events(); + init_position(); + init_window(); + init_workspace(); + init_session3(); + init_util4(); + logger89 = require_logger2()("cursors"); + Cursors = class { + constructor(nvim) { + this.nvim = nvim; + this.sessionsMap = new Map(); + this.disposables = []; + this.loadConfig(); + workspace_default.onDidChangeConfiguration((e) => { + if (e.affectsConfiguration("cursors")) { + this.loadConfig(); + } + }, null, this.disposables); + events_default.on("BufUnload", (bufnr) => { + let session = this.getSession(bufnr); + if (!session) + return; + session.dispose(); + this.sessionsMap.delete(bufnr); + }, null, this.disposables); + } + loadConfig() { + let config = workspace_default.getConfiguration("cursors"); + this.config = { + nextKey: config.get("nextKey", ""), + previousKey: config.get("previousKey", ""), + cancelKey: config.get("cancelKey", "") + }; + } + getSession(bufnr) { + return this.sessionsMap.get(bufnr); + } + async isActivated() { + let bufnr = await this.nvim.call("bufnr", ["%"]); + return this.sessionsMap.get(bufnr) != null; + } + async select(bufnr, kind, mode) { + let doc = workspace_default.getDocument(bufnr); + if (!doc || !doc.attached) { + window_default.showMessage(`buffer ${bufnr} not attached.`); + return; + } + let { nvim } = this; + let session = this.createSession(doc); + let pos = await window_default.getCursorPosition(); + let range; + if (kind == "operator") { + await nvim.command(`normal! ${mode == "line" ? `'[` : "`["}`); + let start = await window_default.getCursorPosition(); + await nvim.command(`normal! ${mode == "line" ? `']` : "`]"}`); + let end = await window_default.getCursorPosition(); + await window_default.moveTo(pos); + let relative = comparePosition(start, end); + if (relative == 0) + return; + if (relative >= 0) + [start, end] = [end, start]; + let line = doc.getline(end.line); + if (end.character < line.length) { + end.character = end.character + 1; + } + let ranges = splitRange(doc, Range.create(start, end)); + for (let r of ranges) { + let text = doc.textDocument.getText(r); + session.addRange(r, text); + } + } else if (kind == "word") { + range = doc.getWordRangeAtPosition(pos); + if (!range) { + let line2 = doc.getline(pos.line); + if (pos.character == line2.length) { + range = Range.create(pos.line, Math.max(0, line2.length - 1), pos.line, line2.length); + } else { + range = 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); + session.addRange(range, text); + } else if (kind == "position") { + let line = doc.getline(pos.line); + if (pos.character >= line.length) { + range = Range.create(pos.line, line.length - 1, pos.line, line.length); + } else { + range = Range.create(pos.line, pos.character, pos.line, pos.character + 1); + } + session.addRange(range, line.slice(range.start.character, range.end.character)); + } else if (kind == "range") { + await nvim.call("eval", 'feedkeys("\\", "in")'); + let range2 = await workspace_default.getSelectedRange(mode, doc); + if (!range2 || comparePosition(range2.start, range2.end) == 0) + return; + let ranges = mode == "" ? getVisualRanges(doc, range2) : splitRange(doc, range2); + for (let r of ranges) { + let text = doc.textDocument.getText(r); + session.addRange(r, text); + } + } else { + window_default.showMessage(`${kind} not supported`, "error"); + return; + } + if (kind == "word" || kind == "position") { + await nvim.command(`silent! call repeat#set("\\(coc-cursors-${kind})", -1)`); + } + } + createSession(doc) { + let session = this.getSession(doc.bufnr); + if (session) + return session; + session = new CursorSession(this.nvim, doc, this.config); + this.sessionsMap.set(doc.bufnr, session); + session.onDidCancel(() => { + session.dispose(); + this.sessionsMap.delete(doc.bufnr); + }); + return session; + } + async addRanges(ranges) { + let { nvim } = this; + let bufnr = await nvim.call("bufnr", ["%"]); + let doc = workspace_default.getDocument(bufnr); + if (!doc || !doc.attached) { + window_default.showMessage("Document not attached", "error"); + return false; + } + let session = this.createSession(doc); + return session.addRanges(ranges); + } + reset() { + for (let session of this.sessionsMap.values()) { + session.cancel(); + } + this.sessionsMap.clear(); + } + dispose() { + for (let session of this.sessionsMap.values()) { + session.dispose(); + } + this.sessionsMap.clear(); + for (let disposable of this.disposables) { + disposable.dispose(); + } + } + }; + } +}); + +// src/handler/codeActions.ts +var import_vscode_languageserver_protocol85, logger90, CodeActions; +var init_codeActions = __esm({ + "src/handler/codeActions.ts"() { + init_manager(); + import_vscode_languageserver_protocol85 = __toModule(require_main2()); + init_commands2(); + init_workspace(); + init_window(); + init_languages(); + logger90 = require_logger2()("handler-codeActions"); + CodeActions = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + handler.addDisposable(commands_default.registerCommand("editor.action.organizeImport", async (bufnr) => { + await this.organizeImport(bufnr); + })); + commands_default.titles.set("editor.action.organizeImport", "run organize import code action."); + } + async codeActionRange(start, end, only) { + let { doc } = await this.handler.getCurrentState(); + await doc.synchronize(); + let line = doc.getline(end - 1); + let range = import_vscode_languageserver_protocol85.Range.create(start - 1, 0, end - 1, line.length); + let codeActions = await this.getCodeActions(doc, range, only ? [only] : null); + if (!codeActions || codeActions.length == 0) { + window_default.showMessage(`No${only ? " " + only : ""} code action available`, "warning"); + return; + } + let idx = await window_default.showMenuPicker(codeActions.map((o) => o.title), "Choose action"); + let action = codeActions[idx]; + if (action) + await this.applyCodeAction(action); + } + async organizeImport(bufnr) { + let { doc } = await this.handler.getCurrentState(); + if (bufnr && doc.bufnr != bufnr) + return; + await doc.synchronize(); + let actions = await this.getCodeActions(doc, void 0, [import_vscode_languageserver_protocol85.CodeActionKind.SourceOrganizeImports]); + if (actions && actions.length) { + await this.applyCodeAction(actions[0]); + return; + } + throw new Error("Organize import action not found."); + } + async getCodeActions(doc, range, only) { + range = range || import_vscode_languageserver_protocol85.Range.create(0, 0, doc.lineCount, 0); + let diagnostics = manager_default.getDiagnosticsInRange(doc.textDocument, range); + let context = { diagnostics }; + if (only && Array.isArray(only)) + context.only = only; + let codeActions = await this.handler.withRequestToken("code action", (token) => { + return languages_default.getCodeActions(doc.textDocument, range, context, token); + }); + if (!codeActions || codeActions.length == 0) + return []; + codeActions = codeActions.filter((o) => !o.disabled); + codeActions.sort((a, b) => { + if (a.isPreferred && !b.isPreferred) + return -1; + if (b.isPreferred && !a.isPreferred) + return 1; + return 0; + }); + return codeActions; + } + get floatActions() { + if (!workspace_default.floatSupported) + return false; + let config = workspace_default.getConfiguration("coc.preferences"); + return config.get("floatActions", true); + } + async doCodeAction(mode, only) { + let { doc } = await this.handler.getCurrentState(); + let range; + if (mode) + range = await workspace_default.getSelectedRange(mode, doc); + await doc.synchronize(); + let codeActions = await this.getCodeActions(doc, range, Array.isArray(only) ? only : null); + if (typeof only == "string") { + codeActions = codeActions.filter((o) => o.title == only || o.command && o.command.title == only); + } else if (Array.isArray(only)) { + codeActions = codeActions.filter((o) => only.some((k) => o.kind && o.kind.startsWith(k))); + } + if (!codeActions || codeActions.length == 0) { + window_default.showMessage(`No${only ? " " + only : ""} code action available`, "warning"); + return; + } + if (only && codeActions.length == 1) { + await this.applyCodeAction(codeActions[0]); + return; + } + let idx = this.floatActions ? await window_default.showMenuPicker(codeActions.map((o) => o.title), "Choose action") : await window_default.showQuickpick(codeActions.map((o) => o.title)); + let action = codeActions[idx]; + if (action) + await this.applyCodeAction(action); + } + async getCurrentCodeActions(mode, only) { + let { doc } = await this.handler.getCurrentState(); + let range; + if (mode) + range = await workspace_default.getSelectedRange(mode, doc); + return await this.getCodeActions(doc, range, only); + } + async doQuickfix() { + let actions = await this.getCurrentCodeActions("line", [import_vscode_languageserver_protocol85.CodeActionKind.QuickFix]); + if (!actions || actions.length == 0) { + throw new Error("No quickfix action available"); + } + await this.applyCodeAction(actions[0]); + this.nvim.command(`silent! call repeat#set("\\(coc-fix-current)", -1)`, true); + } + async applyCodeAction(action) { + if (action.disabled) { + throw new Error(`Action "${action.title}" is disabled: ${action.disabled.reason}`); + } + action = await this.handler.withRequestToken("resolve codeAction", (token) => { + return languages_default.resolveCodeAction(action, token); + }); + let { edit: edit2, command } = action; + if (edit2) + await workspace_default.applyEdit(edit2); + if (command) + await commands_default.execute(command); + } + }; + } +}); + +// src/handler/codelens/buffer.ts +var import_debounce10, import_vscode_languageserver_protocol86, logger91, CodeLensBuffer; +var init_buffer3 = __esm({ + "src/handler/codelens/buffer.ts"() { + import_debounce10 = __toModule(require_debounce()); + import_vscode_languageserver_protocol86 = __toModule(require_main2()); + init_commands2(); + init_languages(); + init_window(); + init_workspace(); + logger91 = require_logger2()("codelens-buffer"); + CodeLensBuffer = class { + constructor(nvim, bufnr, config) { + this.nvim = nvim; + this.bufnr = bufnr; + this.config = config; + this.fetchCodelenses = (0, import_debounce10.default)(() => { + void this._fetchCodeLenses(); + }, 200); + this.resolveCodeLens = (0, import_debounce10.default)(() => { + void this._resolveCodeLenses(); + }, 200); + this.fetchCodelenses(); + } + currentCodeLens() { + var _a2; + return (_a2 = this.codeLenses) == null ? void 0 : _a2.codeLenses; + } + get enabled() { + return this.textDocument && this.config.enabled && languages_default.hasProvider("codeLens", this.textDocument); + } + async forceFetch() { + this.fetchCodelenses.clear(); + await this._fetchCodeLenses(); + } + get textDocument() { + var _a2; + return (_a2 = workspace_default.getDocument(this.bufnr)) == null ? void 0 : _a2.textDocument; + } + async _fetchCodeLenses() { + var _a2, _b; + if (!this.enabled) + return; + this.cancel(); + let noFetch = !this.isChanged && !((_a2 = this.codeLenses) == null ? void 0 : _a2.hasError); + if (!noFetch) { + let { textDocument } = this; + let version2 = textDocument.version; + let tokenSource = this.tokenSource = new import_vscode_languageserver_protocol86.CancellationTokenSource(); + let token = tokenSource.token; + let codeLenses2 = await languages_default.getCodeLens(textDocument, token); + this.tokenSource = void 0; + if (token.isCancellationRequested) + return; + if (!Array.isArray(codeLenses2) || codeLenses2.length == 0) + return; + let hasError = codeLenses2.some((o) => o == null); + this.codeLenses = { version: version2, codeLenses: codeLenses2.filter((o) => o != null), hasError }; + } + let codeLenses = (_b = this.codeLenses) == null ? void 0 : _b.codeLenses; + if (codeLenses == null ? void 0 : codeLenses.length) { + await this._resolveCodeLenses(); + } + } + async _resolveCodeLenses() { + if (!this.enabled || !this.codeLenses || this.isChanged) + return; + let { codeLenses } = this.codeLenses; + let [bufnr, start, end] = await this.nvim.eval(`[bufnr('%'),line('w0'),line('w$')]`); + if (this.isChanged || bufnr != this.bufnr) + return; + if (this.resolveTokenSource) { + this.resolveTokenSource.cancel(); + } + codeLenses = codeLenses.filter((o) => { + let lnum = o.range.start.line + 1; + return lnum >= start && lnum <= end; + }); + if (codeLenses.length) { + let tokenSource = this.resolveTokenSource = new import_vscode_languageserver_protocol86.CancellationTokenSource(); + let token = tokenSource.token; + await Promise.all(codeLenses.map((codeLens) => languages_default.resolveCodeLens(codeLens, token))); + this.resolveTokenSource = void 0; + if (token.isCancellationRequested || this.isChanged) + return; + } + if (!this.srcId) + this.srcId = await this.nvim.createNamespace("coc-codelens"); + this.nvim.pauseNotification(); + this.clear(start - 1, end); + this.setVirtualText(codeLenses); + await this.nvim.resumeNotification(); + } + get isChanged() { + if (!this.textDocument || !this.codeLenses) + return true; + let { version: version2 } = this.codeLenses; + return this.textDocument.version !== version2; + } + setVirtualText(codeLenses) { + if (codeLenses.length == 0) + return; + let list2 = new Map(); + for (let codeLens of codeLenses) { + let { range, command } = codeLens; + if (!command) + continue; + let { line } = range.start; + if (list2.has(line)) { + list2.get(line).push(codeLens); + } else { + list2.set(line, [codeLens]); + } + } + for (let lnum of list2.keys()) { + let codeLenses2 = list2.get(lnum); + let commands = codeLenses2.map((codeLens) => codeLens.command); + commands = commands.filter((c) => c && c.title); + let chunks = []; + let n_commands = commands.length; + for (let i = 0; i < n_commands; i++) { + let c = commands[i]; + chunks.push([c.title.replace(/(\r\n|\r|\n|\s)+/g, " "), "CocCodeLens"]); + if (i != n_commands - 1) { + chunks.push([this.config.subseparator, "CocCodeLens"]); + } + } + chunks.unshift([`${this.config.separator} `, "CocCodeLens"]); + this.nvim.call("nvim_buf_set_virtual_text", [this.bufnr, this.srcId, lnum, chunks, {}], true); + } + } + clear(start = 0, end = -1) { + if (!this.srcId) + return; + let buf = this.nvim.createBuffer(this.bufnr); + buf.clearNamespace(this.srcId, start, end); + } + cleanUp() { + this.clear(); + this.codeLenses = void 0; + } + getCodelenses() { + var _a2; + return (_a2 = this.codeLenses) == null ? void 0 : _a2.codeLenses; + } + async doAction(line) { + var _a2; + let { codeLenses } = (_a2 = this.codeLenses) != null ? _a2 : {}; + if (!(codeLenses == null ? void 0 : codeLenses.length)) + return; + let commands = []; + for (let codeLens of codeLenses) { + let { range, command } = codeLens; + if (!command || !range) + continue; + if (line == range.start.line) { + commands.push(command); + } + } + if (!commands.length) + return; + if (commands.length == 1) { + await commands_default.execute(commands[0]); + } else { + let res = await window_default.showMenuPicker(commands.map((c) => c.title)); + if (res == -1) + return; + await commands_default.execute(commands[res]); + } + } + cancel() { + this.resolveCodeLens.clear(); + this.fetchCodelenses.clear(); + if (this.tokenSource) { + this.tokenSource.cancel(); + this.tokenSource.dispose(); + this.tokenSource = null; + } + } + onChange() { + this.cancel(); + this.fetchCodelenses(); + } + dispose() { + this.clear(); + this.cancel(); + this.codeLenses = void 0; + } + }; + } +}); + +// src/handler/codelens/index.ts +var logger92, CodeLensManager2; +var init_codelens = __esm({ + "src/handler/codelens/index.ts"() { + init_events(); + init_util(); + init_workspace(); + init_buffer3(); + logger92 = require_logger2()("codelens"); + CodeLensManager2 = class { + constructor(nvim) { + this.nvim = nvim; + this.disposables = []; + this.setConfiguration(); + if (!workspace_default.isNvim) + return; + workspace_default.onDidChangeConfiguration((e) => { + this.setConfiguration(e); + }); + this.buffers = workspace_default.registerBufferSync((doc) => { + if (doc.buftype != "") + return void 0; + return new CodeLensBuffer(nvim, doc.bufnr, this.config); + }); + this.listen(); + } + listen() { + events_default.on("CursorMoved", (bufnr) => { + let buf = this.buffers.getItem(bufnr); + if (buf) + buf.resolveCodeLens(); + }, null, this.disposables); + events_default.on("CursorHold", async (bufnr) => { + let buf = this.buffers.getItem(bufnr); + if (buf) + await buf.forceFetch(); + }, this, this.disposables); + } + async checkProvider() { + for (let buf of this.buffers.items) { + await buf.forceFetch(); + } + } + setConfiguration(e) { + if (e && !e.affectsConfiguration("codeLens")) + return; + let config = workspace_default.getConfiguration("codeLens"); + let enable = this.nvim.hasFunction("nvim_buf_set_virtual_text") && config.get("enable", false); + if (e && enable != this.config.enabled) { + if (enable) { + this.listen(); + } else { + disposeAll(this.disposables); + } + for (let buf of this.buffers.items) { + if (enable) { + buf.fetchCodelenses(); + } else { + buf.cleanUp(); + } + } + } + this.config = Object.assign(this.config || {}, { + enabled: enable, + separator: config.get("separator", "\u2023"), + subseparator: config.get("subseparator", " ") + }); + } + async doAction() { + let [bufnr, line] = await this.nvim.eval(`[bufnr("%"),line(".")-1]`); + let buf = this.buffers.getItem(bufnr); + await (buf == null ? void 0 : buf.doAction(line)); + } + dispose() { + this.buffers.dispose(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/util/color.ts +function pad(str) { + return str.length == 1 ? `0${str}` : str; +} +function toHexString(color) { + let c = toHexColor(color); + return `${pad(c.red.toString(16))}${pad(c.green.toString(16))}${pad(c.blue.toString(16))}`; +} +function toHexColor(color) { + let { red, green, blue: blue2 } = color; + return { + red: Math.round(red * 255), + green: Math.round(green * 255), + blue: Math.round(blue2 * 255) + }; +} +function isDark(color) { + 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; +} +var init_color = __esm({ + "src/util/color.ts"() { + } +}); + +// src/handler/colors/colorBuffer.ts +var import_debounce11, import_vscode_languageserver_protocol87, logger93, ColorBuffer; +var init_colorBuffer = __esm({ + "src/handler/colors/colorBuffer.ts"() { + import_debounce11 = __toModule(require_debounce()); + import_vscode_languageserver_protocol87 = __toModule(require_main2()); + init_languages(); + init_array(); + init_object(); + init_position(); + init_color(); + init_workspace(); + logger93 = require_logger2()("colors-buffer"); + ColorBuffer = class { + constructor(nvim, bufnr, enabled, usedColors) { + this.nvim = nvim; + this.bufnr = bufnr; + this.enabled = enabled; + this.usedColors = usedColors; + this._colors = []; + this.highlight = (0, import_debounce11.default)(() => { + void this.doHighlight(); + }, global.hasOwnProperty("__TEST__") ? 10 : 500); + } + onChange() { + this.cancel(); + this.highlight(); + } + get buffer() { + return this.nvim.createBuffer(this.bufnr); + } + get colors() { + return this._colors; + } + hasColor() { + return this._colors.length > 0; + } + setState(enabled) { + this.enabled = enabled; + if (enabled) { + this.highlight(); + } else { + this.clearHighlight(); + } + } + async doHighlight() { + let doc = workspace_default.getDocument(this.bufnr); + if (!doc || !this.enabled) + return; + try { + this.tokenSource = new import_vscode_languageserver_protocol87.CancellationTokenSource(); + let { token } = this.tokenSource; + if (this.version && doc.version == this.version) + return; + let { version: version2 } = doc; + let colors; + colors = await languages_default.provideDocumentColors(doc.textDocument, token); + colors = colors || []; + if (token.isCancellationRequested) + return; + this.version = version2; + await this.addHighlight(colors); + } catch (e) { + logger93.error("Error on highlight:", e); + } + } + async addHighlight(colors) { + colors = colors || []; + if (equals(this._colors, colors)) + return; + let { nvim } = this; + this._colors = colors; + let groups = group(colors, 100); + nvim.pauseNotification(); + this.buffer.clearNamespace("color"); + this.defineColors(colors); + void nvim.resumeNotification(false, true); + for (let colors2 of groups) { + nvim.pauseNotification(); + let colorRanges = this.getColorRanges(colors2); + for (let o of colorRanges) { + this.highlightColor(o.ranges, o.color); + } + void nvim.resumeNotification(false, true); + } + if (workspace_default.isVim) + this.nvim.command("redraw", true); + } + highlightColor(ranges, color) { + let hlGroup = `BG${toHexString(color)}`; + this.buffer.highlightRanges("color", hlGroup, ranges); + } + defineColors(colors) { + for (let color of colors) { + let hex = toHexString(color.color); + if (!this.usedColors.has(hex)) { + this.nvim.command(`hi BG${hex} guibg=#${hex} guifg=#${isDark(color.color) ? "ffffff" : "000000"}`, true); + this.usedColors.add(hex); + } + } + } + getColorRanges(infos) { + let res = []; + for (let info of infos) { + let { color, range } = info; + let idx = res.findIndex((o) => 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; + } + clearHighlight() { + this.highlight.clear(); + this._colors = []; + this.version = null; + this.buffer.clearNamespace("color"); + } + hasColorAtPosition(position) { + let { colors } = this; + return colors.some((o) => positionInRange(position, o.range) == 0); + } + cancel() { + if (this.tokenSource) { + this.tokenSource.cancel(); + this.tokenSource = null; + } + } + dispose() { + this.highlight.clear(); + this.cancel(); + } + }; + } +}); + +// src/handler/colors/index.ts +var import_vscode_languageserver_protocol88, logger94, Colors; +var init_colors = __esm({ + "src/handler/colors/index.ts"() { + import_vscode_languageserver_protocol88 = __toModule(require_main2()); + init_commands2(); + init_extensions2(); + init_languages(); + init_util(); + init_color(); + init_window(); + init_workspace(); + init_colorBuffer(); + logger94 = require_logger2()("colors-index"); + Colors = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this._enabled = true; + this.disposables = []; + let config = workspace_default.getConfiguration("coc.preferences"); + this._enabled = config.get("colorSupport", true); + let usedColors = new Set(); + this.highlighters = workspace_default.registerBufferSync((doc) => { + let buf = new ColorBuffer(this.nvim, doc.bufnr, this._enabled, usedColors); + buf.highlight(); + return buf; + }); + extensions_default.onDidActiveExtension(() => { + this.highlightAll(); + }, null, this.disposables); + workspace_default.onDidChangeConfiguration(async (e) => { + if (e.affectsConfiguration("coc.preferences.colorSupport")) { + let config2 = workspace_default.getConfiguration("coc.preferences"); + let enabled = config2.get("colorSupport", true); + this._enabled = enabled; + for (let buf of this.highlighters.items) { + buf.setState(enabled); + } + } + }, null, this.disposables); + this.disposables.push(commands_default.registerCommand("editor.action.pickColor", () => { + return this.pickColor(); + })); + commands_default.titles.set("editor.action.pickColor", "pick color from system color picker when possible."); + this.disposables.push(commands_default.registerCommand("editor.action.colorPresentation", () => { + return this.pickPresentation(); + })); + commands_default.titles.set("editor.action.colorPresentation", "change color presentation."); + } + async pickPresentation() { + let { doc } = await this.handler.getCurrentState(); + this.handler.checkProvier("documentColor", doc.textDocument); + let info = await this.getColorInformation(doc.bufnr); + if (!info) + return window_default.showMessage("Color not found at current position", "warning"); + let document2 = await workspace_default.document; + let tokenSource = new import_vscode_languageserver_protocol88.CancellationTokenSource(); + let presentations = await languages_default.provideColorPresentations(info, document2.textDocument, tokenSource.token); + if (!(presentations == null ? void 0 : presentations.length)) + return; + let res = await window_default.showMenuPicker(presentations.map((o) => o.label), "choose color:"); + if (res == -1) + return; + let presentation = presentations[res]; + let { textEdit, additionalTextEdits, label } = presentation; + if (!textEdit) + textEdit = { range: info.range, newText: label }; + await document2.applyEdits([textEdit]); + if (additionalTextEdits) { + await document2.applyEdits(additionalTextEdits); + } + } + async pickColor() { + let { doc } = await this.handler.getCurrentState(); + this.handler.checkProvier("documentColor", doc.textDocument); + let info = await this.getColorInformation(doc.bufnr); + if (!info) + return window_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) + return; + let hex = toHexString({ + red: res[0] / 65535, + green: res[1] / 65535, + blue: res[2] / 65535, + alpha: 1 + }); + let document2 = await workspace_default.document; + await document2.applyEdits([{ + range: info.range, + newText: `#${hex}` + }]); + } + get enabled() { + return this._enabled; + } + clearHighlight(bufnr) { + let highlighter = this.highlighters.getItem(bufnr); + if (!highlighter) + return; + highlighter.clearHighlight(); + } + hasColor(bufnr) { + let highlighter = this.highlighters.getItem(bufnr); + if (!highlighter) + return false; + return highlighter.hasColor(); + } + hasColorAtPosition(bufnr, position) { + let highlighter = this.highlighters.getItem(bufnr); + if (!highlighter) + return false; + return highlighter.hasColorAtPosition(position); + } + highlightAll() { + for (let buf of this.highlighters.items) { + buf.highlight(); + } + } + async doHighlight(bufnr) { + let highlighter = this.highlighters.getItem(bufnr); + if (highlighter) + await highlighter.doHighlight(); + } + async getColorInformation(bufnr) { + let highlighter = this.highlighters.getItem(bufnr); + if (!highlighter) + return null; + let position = await window_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; + } + dispose() { + this.highlighters.dispose(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/commands.ts +var logger95, isVim6, Commands; +var init_commands3 = __esm({ + "src/handler/commands.ts"() { + init_commands2(); + init_events(); + init_manager3(); + logger95 = require_logger2()("handler-commands"); + isVim6 = process.env.VIM_NODE_RPC == "1"; + Commands = class { + constructor(nvim, env) { + this.nvim = nvim; + this.env = env; + for (let item of env.vimCommands) { + this.addVimCommand(item); + } + } + addVimCommand(cmd) { + let id = `vim.${cmd.id}`; + commands_default.registerCommand(id, () => { + this.nvim.command(cmd.cmd, true); + if (isVim6) + this.nvim.command("redraw", true); + }); + if (cmd.title) + commands_default.titles.set(id, cmd.title); + } + getCommandList() { + return commands_default.commandList.map((o) => o.id); + } + async repeat() { + await commands_default.repeatCommand(); + } + async runCommand(id, ...args) { + if (id) { + await events_default.fire("Command", [id]); + let res = await commands_default.executeCommand(id, ...args); + if (args.length == 0) { + await commands_default.addRecent(id); + } + return res; + } else { + await manager_default2.start(["commands"]); + } + } + getCommands() { + let list2 = commands_default.commandList; + let res = []; + let { titles } = commands_default; + for (let item of list2) { + res.push({ + id: item.id, + title: titles.get(item.id) || "" + }); + } + return res; + } + }; + } +}); + +// src/handler/fold.ts +var FoldHandler; +var init_fold = __esm({ + "src/handler/fold.ts"() { + init_languages(); + init_workspace(); + FoldHandler = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + } + async fold(kind) { + let { doc, winid } = await this.handler.getCurrentState(); + this.handler.checkProvier("foldingRange", doc.textDocument); + await doc.synchronize(); + let win = this.nvim.createWindow(winid); + let foldlevel = await this.nvim.eval("&foldlevel"); + let ranges = await this.handler.withRequestToken("foldingrange", (token) => { + return languages_default.provideFoldingRanges(doc.textDocument, {}, token); + }, true); + if (!ranges || !ranges.length) + return false; + if (kind) + ranges = ranges.filter((o) => o.kind == kind); + ranges.sort((a, b) => b.startLine - a.startLine); + this.nvim.pauseNotification(); + win.setOption("foldmethod", "manual", true); + this.nvim.command("normal! zE", true); + for (let range of ranges) { + let { startLine, endLine } = range; + let cmd = `${startLine + 1}, ${endLine + 1}fold`; + this.nvim.command(cmd, true); + } + win.setOption("foldenable", true, true); + win.setOption("foldlevel", foldlevel, true); + if (workspace_default.isVim) + this.nvim.command("redraw", true); + await this.nvim.resumeNotification(); + return true; + } + }; + } +}); + +// src/handler/format.ts +var import_vscode_languageserver_protocol89, logger96, pairs, FormatHandler; +var init_format2 = __esm({ + "src/handler/format.ts"() { + import_vscode_languageserver_protocol89 = __toModule(require_main2()); + init_events(); + init_languages(); + init_manager4(); + init_position(); + init_string(); + init_window(); + init_workspace(); + logger96 = require_logger2()("handler-format"); + pairs = new Map([ + ["<", ">"], + [">", "<"], + ["{", "}"], + ["[", "]"], + ["(", ")"] + ]); + FormatHandler = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.loadPreferences(); + handler.addDisposable(workspace_default.onDidChangeConfiguration(this.loadPreferences, this)); + handler.addDisposable(workspace_default.onWillSaveTextDocument((event) => { + let { languageId } = event.document; + let filetypes = this.preferences.formatOnSaveFiletypes; + if (filetypes.includes(languageId) || filetypes.includes("*")) { + let willSaveWaitUntil = async () => { + if (!languages_default.hasFormatProvider(event.document)) { + logger96.warn(`Format provider not found for ${event.document.uri}`); + return void 0; + } + let options = await workspace_default.getFormatOptions(event.document.uri); + let tokenSource = new import_vscode_languageserver_protocol89.CancellationTokenSource(); + let timer = setTimeout(() => { + logger96.warn(`Format on save ${event.document.uri} timeout after 0.5s`); + tokenSource.cancel(); + }, 500); + let textEdits = await languages_default.provideDocumentFormattingEdits(event.document, options, tokenSource.token); + clearTimeout(timer); + if (!textEdits && !tokenSource.token.isCancellationRequested) { + logger96.want(`Format on save ${event.document.uri} get undefined result.`); + } + return textEdits; + }; + event.waitUntil(willSaveWaitUntil()); + } + })); + let enterTs; + let enterBufnr; + handler.addDisposable(events_default.on("Enter", async (bufnr) => { + enterTs = Date.now(); + enterBufnr = bufnr; + })); + handler.addDisposable(events_default.on("CursorMovedI", async (bufnr) => { + if (bufnr == enterBufnr && Date.now() - enterTs < 100) { + await this.handleEnter(bufnr); + } + })); + let changedTs; + let lastInsert; + handler.addDisposable(events_default.on("InsertCharPre", async () => { + lastInsert = Date.now(); + })); + handler.addDisposable(events_default.on("TextChangedI", async (bufnr, info) => { + changedTs = Date.now(); + if (!lastInsert || changedTs - lastInsert > 300) + return; + lastInsert = null; + let pre = info.pre[info.pre.length - 1]; + if (pre) + await this.tryFormatOnType(pre, bufnr); + })); + let lastEnterBufnr; + let lastEnterTs; + handler.addDisposable(events_default.on("InsertEnter", (bufnr) => { + lastEnterBufnr = bufnr; + lastEnterTs = Date.now(); + })); + handler.addDisposable(events_default.on("TextChangedI", async (bufnr, info) => { + if (!this.preferences.formatOnType && !/^\s*$/.test(info.pre)) + return; + if (lastEnterBufnr != bufnr || !lastEnterTs || Date.now() - lastEnterTs > 30) + return; + lastEnterBufnr = void 0; + await this.tryFormatOnType("\n", bufnr, true); + })); + } + loadPreferences(e) { + if (!e || e.affectsConfiguration("coc.preferences")) { + let config = workspace_default.getConfiguration("coc.preferences"); + this.preferences = { + formatOnType: config.get("formatOnType", false), + formatOnSaveFiletypes: config.get("formatOnSaveFiletypes", []), + formatOnTypeFiletypes: config.get("formatOnTypeFiletypes", []), + bracketEnterImprove: config.get("bracketEnterImprove", true) + }; + } + } + async tryFormatOnType(ch, bufnr, newLine = false) { + if (!ch || isWord(ch) || !this.preferences.formatOnType) + return; + if (manager_default3.getSession(bufnr) != null) + return; + let doc = workspace_default.getDocument(bufnr); + if (!doc || !doc.attached || doc.isCommandLine) + return; + const filetypes = this.preferences.formatOnTypeFiletypes; + if (filetypes.length && !filetypes.includes(doc.filetype) && !filetypes.includes("*")) { + return; + } + if (!languages_default.hasProvider("formatOnType", doc.textDocument)) { + logger96.warn(`Format on type provider not found for buffer: ${doc.uri}`); + return; + } + if (!languages_default.canFormatOnType(ch, doc.textDocument)) + return; + let position; + let edits = await this.handler.withRequestToken("Format on type", async (token) => { + position = await window_default.getCursorPosition(); + let origLine = doc.getline(position.line - 1); + if (newLine && /^\s*$/.test(origLine)) + return; + let pos = newLine ? { line: position.line - 1, character: origLine.length } : position; + await doc.synchronize(); + return await languages_default.provideDocumentOnTypeEdits(ch, doc.textDocument, pos, token); + }); + if (!edits || !edits.length) + return; + let changed = getChangedFromEdits(position, edits); + await doc.applyEdits(edits); + let to = changed ? import_vscode_languageserver_protocol89.Position.create(position.line + changed.line, position.character + changed.character) : null; + if (to && !newLine) + await window_default.moveTo(to); + } + async formatCurrentBuffer() { + let { doc } = await this.handler.getCurrentState(); + return await this.documentFormat(doc); + } + async formatCurrentRange(mode) { + let { doc } = await this.handler.getCurrentState(); + return await this.documentRangeFormat(doc, mode); + } + async documentFormat(doc) { + await doc.synchronize(); + if (!languages_default.hasFormatProvider(doc.textDocument)) { + throw new Error(`Format provider not found for buffer: ${doc.bufnr}`); + } + let options = await workspace_default.getFormatOptions(doc.uri); + let textEdits = await this.handler.withRequestToken("format", (token) => { + return languages_default.provideDocumentFormattingEdits(doc.textDocument, options, token); + }); + if (textEdits && textEdits.length > 0) { + await doc.applyEdits(textEdits); + return true; + } + return false; + } + async handleEnter(bufnr) { + let { nvim } = this; + let { bracketEnterImprove } = this.preferences; + await this.tryFormatOnType("\n", bufnr); + if (bracketEnterImprove) { + let line = await nvim.call("line", ".") - 1; + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return; + await doc.patchChange(); + 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_default.getFormatOptions(doc.uri); + let space = opts.insertSpaces ? " ".repeat(opts.tabSize) : " "; + let currIndent = curr.match(/^\s*/)[0]; + let pos = import_vscode_languageserver_protocol89.Position.create(line - 1, pre.length); + if (doc.filetype == "vim") { + let newText = "\n" + currIndent + space; + edits.push({ range: import_vscode_languageserver_protocol89.Range.create(line, currIndent.length, line, currIndent.length), newText: " \\ " }); + newText = newText + "\\ "; + edits.push({ range: import_vscode_languageserver_protocol89.Range.create(pos, pos), newText }); + await doc.applyEdits(edits); + await window_default.moveTo(import_vscode_languageserver_protocol89.Position.create(line, newText.length - 1)); + } else { + await nvim.eval(`feedkeys("\\O", 'in')`); + } + } + } + } + } + async documentRangeFormat(doc, mode) { + this.handler.checkProvier("formatRange", doc.textDocument); + await doc.synchronize(); + let range; + if (mode) { + range = await workspace_default.getSelectedRange(mode, doc); + if (!range) + return -1; + } else { + let [lnum, count, mode2] = await this.nvim.eval("[v:lnum,v:count,mode()]"); + if (count == 0 || mode2 == "i" || mode2 == "R") + return -1; + range = import_vscode_languageserver_protocol89.Range.create(lnum - 1, 0, lnum - 1 + count, 0); + } + let options = await workspace_default.getFormatOptions(doc.uri); + let textEdits = await this.handler.withRequestToken("Format range", (token) => { + return languages_default.provideDocumentRangeFormattingEdits(doc.textDocument, range, options, token); + }); + if (textEdits && textEdits.length > 0) { + await doc.applyEdits(textEdits); + return 0; + } + return -1; + } + }; + } +}); + +// src/handler/highlights.ts +var import_vscode_languageserver_protocol90, logger97, Highlights; +var init_highlights = __esm({ + "src/handler/highlights.ts"() { + import_vscode_languageserver_protocol90 = __toModule(require_main2()); + init_events(); + init_languages(); + init_util(); + init_workspace(); + logger97 = require_logger2()("documentHighlight"); + Highlights = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.disposables = []; + this.highlights = new Map(); + events_default.on(["CursorMoved", "CursorMovedI"], () => { + this.cancel(); + this.clearHighlights(); + }, null, this.disposables); + } + clearHighlights() { + if (this.highlights.size == 0) + return; + for (let winid of this.highlights.keys()) { + let win = this.nvim.createWindow(winid); + win.clearMatchGroup("^CocHighlight"); + } + this.highlights.clear(); + } + async highlight() { + let { nvim } = this; + this.cancel(); + let [bufnr, winid, pos, cursors] = await nvim.eval(`[bufnr("%"),win_getid(),coc#cursor#position(),get(b:,'coc_cursors_activated',0)]`); + let doc = workspace_default.getDocument(bufnr); + if (!doc || !doc.attached || cursors) + return; + if (!languages_default.hasProvider("documentHighlight", doc.textDocument)) + return; + let highlights = await this.getHighlights(doc, import_vscode_languageserver_protocol90.Position.create(pos[0], pos[1])); + if (!highlights) + return; + let groups = {}; + for (let hl of highlights) { + if (!hl.range) + continue; + let hlGroup = hl.kind == import_vscode_languageserver_protocol90.DocumentHighlightKind.Text ? "CocHighlightText" : hl.kind == import_vscode_languageserver_protocol90.DocumentHighlightKind.Read ? "CocHighlightRead" : "CocHighlightWrite"; + groups[hlGroup] = groups[hlGroup] || []; + groups[hlGroup].push(hl.range); + } + let win = nvim.createWindow(winid); + nvim.pauseNotification(); + win.clearMatchGroup("^CocHighlight"); + for (let hlGroup of Object.keys(groups)) { + win.highlightRanges(hlGroup, groups[hlGroup], -1, true); + } + if (workspace_default.isVim) + nvim.command("redraw", true); + nvim.resumeNotification(false, true); + this.highlights.set(winid, highlights); + } + async getSymbolsRanges() { + let { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("documentHighlight", doc.textDocument); + let highlights = await this.getHighlights(doc, position); + if (!highlights) + return null; + return highlights.map((o) => o.range); + } + hasHighlights(winid) { + return this.highlights.get(winid) != null; + } + async getHighlights(doc, position) { + let line = doc.getline(position.line); + let ch = line[position.character]; + if (!ch || !doc.isWord(ch)) + return null; + await doc.synchronize(); + this.tokenSource = new import_vscode_languageserver_protocol90.CancellationTokenSource(); + let source = this.tokenSource; + let highlights = await languages_default.getDocumentHighLight(doc.textDocument, position, source.token); + if (source == this.tokenSource) { + source.dispose(); + this.tokenSource = null; + } + if (source.token.isCancellationRequested) + return null; + return highlights; + } + cancel() { + if (this.tokenSource) { + this.tokenSource.cancel(); + this.tokenSource.dispose(); + this.tokenSource = null; + } + } + dispose() { + this.highlights.clear(); + this.cancel(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/hover.ts +function addDocument(docs, text, filetype, isPreview = false) { + let content = text.trim(); + if (!content.length) + return; + if (isPreview && filetype !== "markdown") { + content = "``` " + filetype + "\n" + content + "\n```"; + } + docs.push({ content, filetype }); +} +function isDocumentation(obj) { + if (!obj) + return false; + return typeof obj.filetype === "string" && typeof obj.content === "string"; +} +async function readLines(uri, start, end) { + let doc = workspace_default.getDocument(uri); + if (doc) + return doc.getLines(start, end + 1); + let fsPath = URI.parse(uri).fsPath; + if (!import_fs33.default.existsSync(fsPath)) + return []; + return await readFileLines(fsPath, start, end); +} +var import_fs33, import_vscode_languageserver_protocol91, logger98, HoverHandler; +var init_hover = __esm({ + "src/handler/hover.ts"() { + import_fs33 = __toModule(require("fs")); + import_vscode_languageserver_protocol91 = __toModule(require_main2()); + init_esm2(); + init_languages(); + init_floatFactory(); + init_util(); + init_fs(); + init_workspace(); + logger98 = require_logger2()("handler-hover"); + HoverHandler = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.disposables = []; + this.documentLines = []; + this.hasProvider = false; + this.excludeImages = true; + this.loadConfiguration(); + workspace_default.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables); + this.hoverFactory = new FloatFactory(nvim); + this.disposables.push(this.hoverFactory); + } + registerProvider() { + if (this.hasProvider) + return; + this.hasProvider = true; + let { nvim } = this; + 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(`if winnr('j') != winnr('k') | exe "normal! z${Math.min(this.documentLines.length, this.config.previewMaxHeight)}\\ | endif"`, true); + await nvim.resumeNotification(); + return this.documentLines.join("\n"); + } + }; + this.disposables.push(workspace_default.registerTextDocumentContentProvider("coc", provider)); + } + loadConfiguration(e) { + if (!e || e.affectsConfiguration("hover")) { + let config = workspace_default.getConfiguration("hover"); + let target = config.get("target", "float"); + this.config = { + floatConfig: config.get("floatConfig", {}), + autoHide: config.get("autoHide", true), + target: target == "float" && !workspace_default.floatSupported ? "preview" : target, + previewMaxHeight: config.get("previewMaxHeight", 12) + }; + if (this.config.target == "preview") { + this.registerProvider(); + } + let preferences = workspace_default.getConfiguration("coc.preferences"); + this.excludeImages = preferences.get("excludeImageLinksInMarkdownDocument", true); + } + } + async onHover(hoverTarget) { + let { doc, position, winid } = await this.handler.getCurrentState(); + if (hoverTarget == "preview") + this.registerProvider(); + this.handler.checkProvier("hover", doc.textDocument); + await doc.synchronize(); + let hovers = await this.handler.withRequestToken("hover", (token) => { + return languages_default.getHover(doc.textDocument, position, token); + }, true); + if (hovers == null || !hovers.length) + return false; + let hover = hovers.find((o) => import_vscode_languageserver_protocol91.Range.is(o.range)); + if (hover == null ? void 0 : hover.range) { + let win = this.nvim.createWindow(winid); + win.highlightRanges("CocHoverRange", [hover.range], 99, true); + this.timer = setTimeout(() => { + win.clearMatchGroup("CocHoverRange"); + if (workspace_default.isVim) + this.nvim.command("redraw", true); + }, 500); + } + await this.previewHover(hovers, hoverTarget); + return true; + } + async definitionHover(hoverTarget) { + const { doc, position } = await this.handler.getCurrentState(); + if (hoverTarget == "preview") + this.registerProvider(); + this.handler.checkProvier("hover", doc.textDocument); + await doc.synchronize(); + const hovers = await this.handler.withRequestToken("hover", (token) => { + return languages_default.getHover(doc.textDocument, position, token); + }, true); + if (!(hovers == null ? void 0 : hovers.length)) + return false; + const defs = await this.handler.withRequestToken("definitionHover", (token) => { + return languages_default.getDefinitionLinks(doc.textDocument, position, token); + }, false); + if (defs == null ? void 0 : defs.length) { + for (const def of defs) { + if (!def.targetRange) + continue; + const { start, end } = def.targetRange; + const endLine = end.line - start.line >= 100 ? start.line + 100 : end.character == 0 ? end.line - 1 : end.line; + let lines = await readLines(def.targetUri, start.line, endLine); + if (lines.length) { + let indent = lines[0].match(/^\s*/)[0]; + if (indent) + lines = lines.map((l) => l.startsWith(indent) ? l.substring(indent.length) : l); + hovers.push({ content: lines.join("\n"), filetype: doc.filetype }); + } + } + } + await this.previewHover(hovers, hoverTarget); + return true; + } + async previewHover(hovers, target) { + let docs = []; + target = target || this.config.target; + let isPreview = target === "preview"; + for (let hover of hovers) { + if (isDocumentation(hover)) { + docs.push(hover); + continue; + } + let { contents } = hover; + if (Array.isArray(contents)) { + for (let item of contents) { + if (typeof item === "string") { + addDocument(docs, item, "markdown", isPreview); + } else { + addDocument(docs, item.value, item.language, isPreview); + } + } + } else if (import_vscode_languageserver_protocol91.MarkedString.is(contents)) { + if (typeof contents == "string") { + addDocument(docs, contents, "markdown", isPreview); + } else { + addDocument(docs, contents.value, contents.language, isPreview); + } + } else if (import_vscode_languageserver_protocol91.MarkupContent.is(contents)) { + addDocument(docs, contents.value, isMarkdown(contents) ? "markdown" : "txt", isPreview); + } + } + if (target == "float") { + let config = this.hoverFactory.applyFloatConfig({ + modes: ["n"], + autoHide: this.config.autoHide, + excludeImages: this.excludeImages, + maxWidth: 80 + }, this.config.floatConfig); + await this.hoverFactory.show(docs, config); + return; + } + let lines = docs.reduce((p, c) => { + let arr = c.content.split(/\r?\n/); + if (p.length > 0) + p.push(""); + p.push(...arr); + return p; + }, []); + if (target == "echo") { + const msg = lines.join("\n").trim(); + await this.nvim.call("coc#util#echo_hover", [msg]); + } else { + this.documentLines = lines; + await this.nvim.command(`noswapfile pedit coc://document`); + } + } + async getHover() { + let result = []; + let { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("hover", doc.textDocument); + await doc.synchronize(); + let tokenSource = new import_vscode_languageserver_protocol91.CancellationTokenSource(); + let hovers = await languages_default.getHover(doc.textDocument, position, tokenSource.token); + if (Array.isArray(hovers)) { + for (let h of hovers) { + let { contents } = h; + if (Array.isArray(contents)) { + contents.forEach((c) => { + result.push(typeof c === "string" ? c : c.value); + }); + } else if (import_vscode_languageserver_protocol91.MarkupContent.is(contents)) { + result.push(contents.value); + } else { + result.push(typeof contents === "string" ? contents : contents.value); + } + } + } + result = result.filter((s) => s != null && s.length > 0); + return result; + } + dispose() { + if (this.timer) + clearTimeout(this.timer); + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/links.ts +var import_vscode_languageserver_protocol92, Links; +var init_links2 = __esm({ + "src/handler/links.ts"() { + import_vscode_languageserver_protocol92 = __toModule(require_main2()); + init_languages(); + init_position(); + init_workspace(); + Links = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + } + async getLinks() { + let { doc } = await this.handler.getCurrentState(); + this.handler.checkProvier("documentLink", doc.textDocument); + let links2 = await this.handler.withRequestToken("links", (token) => { + return languages_default.getDocumentLinks(doc.textDocument, token); + }); + return links2 || []; + } + async openLink(link) { + if (!link.target) { + link = await languages_default.resolveDocumentLink(link); + if (!link.target) + throw new Error(`Failed to resolve link target`); + } + await workspace_default.openResource(link.target); + } + async openCurrentLink() { + let [line, character] = await this.nvim.call("coc#cursor#position"); + let links2 = await this.getLinks(); + if (!links2 || links2.length == 0) + return false; + let position = import_vscode_languageserver_protocol92.Position.create(line, character); + for (let link of links2) { + if (positionInRange(position, link.range) == 0) { + await this.openLink(link); + return true; + } + } + return false; + } + }; + } +}); + +// src/handler/locations.ts +var import_vscode_languageserver_protocol93, logger99, LocationsHandler; +var init_locations = __esm({ + "src/handler/locations.ts"() { + import_vscode_languageserver_protocol93 = __toModule(require_main2()); + init_esm2(); + init_languages(); + init_services(); + init_workspace(); + logger99 = require_logger2()("handler-hover"); + LocationsHandler = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + } + async request(method, fn) { + let { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier(method, doc.textDocument); + await doc.synchronize(); + return await this.handler.withRequestToken(method, (token) => { + return fn(doc.textDocument, position, token); + }, true); + } + async definitions() { + const { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("definition", doc.textDocument); + await doc.synchronize(); + const tokenSource = new import_vscode_languageserver_protocol93.CancellationTokenSource(); + return languages_default.getDefinition(doc.textDocument, position, tokenSource.token); + } + async declarations() { + const { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("declaration", doc.textDocument); + await doc.synchronize(); + const tokenSource = new import_vscode_languageserver_protocol93.CancellationTokenSource(); + return languages_default.getDeclaration(doc.textDocument, position, tokenSource.token); + } + async typeDefinitions() { + const { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("typeDefinition", doc.textDocument); + await doc.synchronize(); + const tokenSource = new import_vscode_languageserver_protocol93.CancellationTokenSource(); + return languages_default.getTypeDefinition(doc.textDocument, position, tokenSource.token); + } + async implementations() { + const { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("implementation", doc.textDocument); + await doc.synchronize(); + const tokenSource = new import_vscode_languageserver_protocol93.CancellationTokenSource(); + return languages_default.getImplementation(doc.textDocument, position, tokenSource.token); + } + async references() { + const { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("reference", doc.textDocument); + await doc.synchronize(); + const tokenSource = new import_vscode_languageserver_protocol93.CancellationTokenSource(); + return languages_default.getReferences(doc.textDocument, { includeDeclaration: true }, position, tokenSource.token); + } + async gotoDefinition(openCommand) { + let definition = await this.request("definition", (doc, position, token) => { + return languages_default.getDefinition(doc, position, token); + }); + await this.handleLocations(definition, openCommand); + return definition ? definition.length > 0 : false; + } + async gotoDeclaration(openCommand) { + let definition = await this.request("declaration", (doc, position, token) => { + return languages_default.getDeclaration(doc, position, token); + }); + await this.handleLocations(definition, openCommand); + return definition ? Array.isArray(definition) ? definition.length > 0 : true : false; + } + async gotoTypeDefinition(openCommand) { + let definition = await this.request("typeDefinition", (doc, position, token) => { + return languages_default.getTypeDefinition(doc, position, token); + }); + await this.handleLocations(definition, openCommand); + return definition ? definition.length > 0 : false; + } + async gotoImplementation(openCommand) { + let definition = await this.request("implementation", (doc, position, token) => { + return languages_default.getImplementation(doc, position, token); + }); + await this.handleLocations(definition, openCommand); + return definition ? definition.length > 0 : false; + } + async gotoReferences(openCommand, includeDeclaration = true) { + let definition = await this.request("reference", (doc, position, token) => { + return languages_default.getReferences(doc, { includeDeclaration }, position, token); + }); + await this.handleLocations(definition, openCommand); + return definition ? definition.length > 0 : false; + } + async getTagList() { + let { doc, position } = await this.handler.getCurrentState(); + let word = await this.nvim.call("expand", ""); + if (!word) + return null; + if (!languages_default.hasProvider("definition", doc.textDocument)) + return null; + let tokenSource = new import_vscode_languageserver_protocol93.CancellationTokenSource(); + let definitions = await languages_default.getDefinition(doc.textDocument, position, tokenSource.token); + if (!definitions || !definitions.length) + return null; + return definitions.map((location) => { + let parsedURI = URI.parse(location.uri); + const filename = parsedURI.scheme == "file" ? parsedURI.fsPath : parsedURI.toString(); + return { + name: word, + cmd: `keepjumps ${location.range.start.line + 1} | normal ${location.range.start.character + 1}|`, + filename + }; + }); + } + async findLocations(id, method, params, openCommand) { + let { doc, position } = await this.handler.getCurrentState(); + params = params || {}; + Object.assign(params, { + textDocument: { uri: doc.uri }, + position + }); + let res = await services_default.sendRequest(id, method, params); + res = res || []; + let locations = []; + if (Array.isArray(res)) { + locations = res; + } else if (res.hasOwnProperty("location") && res.hasOwnProperty("children")) { + let getLocation2 = (item) => { + locations.push(item.location); + if (item.children && item.children.length) { + for (let loc of item.children) { + getLocation2(loc); + } + } + }; + getLocation2(res); + } + await this.handleLocations(locations, openCommand); + } + async handleLocations(definition, openCommand) { + if (!definition) + return; + let locations = Array.isArray(definition) ? definition : [definition]; + locations = locations.map((o) => import_vscode_languageserver_protocol93.LocationLink.is(o) ? import_vscode_languageserver_protocol93.Location.create(o.targetUri, o.targetRange) : o); + let len = locations.length; + if (len == 0) + return; + if (len == 1 && openCommand !== false) { + let { uri, range } = locations[0]; + await workspace_default.jumpTo(uri, range.start, openCommand); + } else { + await workspace_default.showLocations(locations); + } + } + dispose() { + } + }; + } +}); + +// src/handler/search.ts +function getPathFromArgs(args) { + if (args.length < 2) + return void 0; + let len = args.length; + if (args[len - 1].startsWith("-")) + return void 0; + if (args[len - 2].startsWith("-")) + return void 0; + return args[len - 1]; +} +var import_child_process6, import_events36, import_path34, import_readline5, logger100, defaultArgs, controlCode2, Task2, Search; +var init_search = __esm({ + "src/handler/search.ts"() { + init_mutex(); + import_child_process6 = __toModule(require("child_process")); + import_events36 = __toModule(require("events")); + import_path34 = __toModule(require("path")); + import_readline5 = __toModule(require("readline")); + init_main(); + init_highligher(); + init_ansiparse(); + init_window(); + logger100 = require_logger2()("handler-search"); + defaultArgs = ["--color", "ansi", "--colors", "path:fg:black", "--colors", "line:fg:green", "--colors", "match:fg:red", "--no-messages", "--heading", "-n"]; + controlCode2 = ""; + Task2 = class extends import_events36.EventEmitter { + start(cmd, args, cwd) { + this.process = (0, import_child_process6.spawn)(cmd, args, { cwd }); + this.process.on("error", (e) => { + this.emit("error", e.message); + }); + const rl = import_readline5.default.createInterface(this.process.stdout); + let start; + let fileItem; + let lines = []; + let highlights = []; + let create = true; + rl.on("line", (content) => { + if (content.includes(controlCode2)) { + let items = ansiparse(content); + if (items[0].foreground == "black") { + fileItem = { filepath: import_path34.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 padlen2 = 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 - padlen2; + highlights.push(Range.create(l, c, l, c + item.text.length)); + } + line += item.text; + } + let currline = line.slice(padlen2); + 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(); + } + } + }; + Search = class { + constructor(nvim, cmd = "rg") { + this.nvim = nvim; + this.cmd = cmd; + } + run(args, cwd, refactorBuf) { + let { nvim, cmd } = this; + let { afterContext, beforeContext } = refactorBuf.config; + let argList = ["-A", afterContext.toString(), "-B", beforeContext.toString()].concat(defaultArgs, args); + let p = getPathFromArgs(args); + if (p) + argList.pop(); + argList.push("--", p ? import_path34.default.isAbsolute(p) ? p : `./${p.replace(/^\.\//, "")}` : "./"); + this.task = new Task2(); + this.task.start(cmd, argList, cwd); + let mutex = new Mutex(); + let files = 0; + let matches = 0; + let start = Date.now(); + let fileItems = []; + const addFileItems = async () => { + if (fileItems.length == 0) + return; + let items = fileItems.slice(); + fileItems = []; + const release = await mutex.acquire(); + try { + await refactorBuf.addFileItems(items); + } catch (e) { + logger100.error(e); + } + release(); + }; + return new Promise((resolve3, reject) => { + let interval = setInterval(addFileItems, 300); + this.task.on("item", async (fileItem) => { + files++; + matches = matches + fileItem.ranges.reduce((p2, r) => p2 + r.highlights.length, 0); + fileItems.push(fileItem); + }); + this.task.on("error", (message) => { + clearInterval(interval); + window_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 buf = refactorBuf.buffer; + if (buf) { + nvim.pauseNotification(); + if (files == 0) { + buf.setLines(["No match found"], { start: 1, end: 2, strictIndexing: false }, true); + buf.addHighlight({ line: 1, srcId: -1, colEnd: -1, colStart: 0, hlGroup: "Error" }).logError(); + buf.setOption("modified", false, true); + } else { + let highligher = new Highlighter(); + 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; + } + resolve3(); + }); + }); + } + abort() { + var _a2; + (_a2 = this.task) == null ? void 0 : _a2.dispose(); + } + }; + } +}); + +// src/handler/refactor/buffer.ts +function adjustRange(range, offset) { + let { start, end } = range; + return import_vscode_languageserver_protocol94.Range.create(start.line - offset, start.character, end.line - offset, end.character); +} +var import_fast_diff5, import_path35, import_vscode_languageserver_protocol94, logger101, SEPARATOR, RefactorBuffer; +var init_buffer4 = __esm({ + "src/handler/refactor/buffer.ts"() { + import_fast_diff5 = __toModule(require_diff()); + import_path35 = __toModule(require("path")); + import_vscode_languageserver_protocol94 = __toModule(require_main2()); + init_main2(); + init_esm2(); + init_commands2(); + init_highligher(); + init_util(); + init_fs(); + init_mutex(); + init_object(); + init_string(); + init_window(); + init_workspace(); + logger101 = require_logger2()("handler-refactorBuffer"); + SEPARATOR = "\u3000"; + RefactorBuffer = class { + constructor(bufnr, srcId, nvim, config, opts) { + this.bufnr = bufnr; + this.srcId = srcId; + this.nvim = nvim; + this.config = config; + this.opts = opts; + this.mutex = new Mutex(); + this._disposed = false; + this.disposables = []; + this._fileItems = []; + this.matchIds = new Set(); + this.changing = false; + this.disposables.push(workspace_default.registerLocalKeymap("n", "", this.splitOpen.bind(this), true)); + workspace_default.onDidChangeTextDocument(this.onDocumentChange, this, this.disposables); + } + get fileItems() { + return this._fileItems; + } + onChange(e) { + if (this.changing) + return; + let doc = this.document; + let { nvim, _fileItems: fileItems } = this; + if (!fileItems.length) + return; + let change = e.contentChanges[0]; + if (!("range" in change)) + return; + 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.includes("\u3000")) { + let startLine = range.start.line; + let diffs = (0, import_fast_diff5.default)(original, text); + let offset = 0; + let orig = TextDocument2.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] == import_fast_diff5.default.EQUAL) { + offset = offset + diff[1].length; + } else if (diff[0] == import_fast_diff5.default.DELETE) { + let end = orig.positionAt(offset + diff[1].length); + if (diffs[i + 1] && diffs[i + 1][0] == import_fast_diff5.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] == import_fast_diff5.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; + for (let item of fileItems) { + for (let range2 of item.ranges) { + let arr = lineChanges.filter((o) => o.lnum < range2.lnum - 1); + if (arr.length) { + let total = arr.reduce((p, c) => p + c.delta, 0); + range2.lnum = range2.lnum + total; + changed = true; + } + } + } + if (!changed) + return; + nvim.pauseNotification(); + this.highlightLineNr(); + nvim.resumeNotification().then((res) => { + if (Array.isArray(res) && res[1] != null) { + logger101.error(`Error on highlightLineNr:`, res[1]); + } + }).logError(); + } + async onDocumentChange(e) { + if (e.bufnr == this.bufnr || this.changing) + return; + let { uri } = e.textDocument; + let { range, text } = e.contentChanges[0]; + let filepath = 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 = []; + 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_default.getDocument(uri); + let newLines = doc.getLines(r.start, r.end); + if (!newLines.length) { + fileItem.ranges.splice(i, 1); + edits.push({ + range: this.getFileRangeRange(r, false), + newText: "" + }); + } else { + r.end = r.start + newLines.length; + edits.push({ + range: this.getFileRangeRange(r, true), + newText: newLines.join("\n") + "\n" + }); + } + } + } + this._fileItems = this._fileItems.filter((o) => o.ranges && o.ranges.length > 0); + if (edits.length) { + this.changing = true; + await this.document.applyEdits(edits); + this.changing = false; + } + this.nvim.pauseNotification(); + this.highlightLineNr(); + this.buffer.setOption("modified", false, true); + await this.nvim.resumeNotification(); + } + async getFileChanges() { + if (this._disposed) + return []; + let changes = []; + let lines = await this.buffer.lines; + lines.push(SEPARATOR); + 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.slice(), + lnum + }); + fsPath = void 0; + arr = []; + } + if (line.length > 1) { + let ms = line.match(/^\u3000(.*)/); + if (ms) { + fsPath = this.getAbsolutePath(ms[1].replace(/\s+$/, "")); + lnum = i + 1; + arr = []; + } + } + } else { + arr.push(line); + } + } + return changes; + } + async splitOpen() { + let { nvim } = this; + let win = nvim.createWindow(this.opts.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 - 1; + let bufname = this.getAbsolutePath(filepath); + nvim.pauseNotification(); + if (valid) { + nvim.call("win_gotoid", [this.opts.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) + window_default.showMessage(`Error on open ${filepath}: ${err}`, "error"); + if (!valid) { + this.opts.fromWinid = await nvim.call("win_getid"); + } + break; + } + } + } + async addFileItems(items) { + if (this._disposed) + return; + let { cwd } = this.opts; + let { document: document2 } = this; + const release = await this.mutex.acquire(); + try { + await document2.synchronize(); + 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 = document2.lineCount; + let highligher = new Highlighter(); + 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(`${isParentFolder(cwd, item.filepath) ? import_path35.default.relative(cwd, item.filepath) : item.filepath}`); + 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.changing = true; + nvim.pauseNotification(); + highligher.render(buffer, count); + this.highlightLineNr(); + buffer.setOption("modified", false, true); + buffer.setOption("undolevels", 1e3, true); + if (count == 2 && hlRanges.length) { + let pos = hlRanges[0].start; + nvim.call("coc#cursor#move_to", [pos.line, pos.character], true); + } + if (workspace_default.isVim) { + nvim.command("redraw", true); + } + let [, err] = await nvim.resumeNotification(); + if (err) + throw new Error(err[2]); + await document2.patchChange(); + this.changing = false; + await commands_default.executeCommand("editor.action.addRanges", hlRanges); + } catch (e) { + this.changing = false; + logger101.error(`Error on add file item:`, e); + } + release(); + } + async save() { + let { nvim } = this; + let doc = this.document; + let { buffer } = doc; + await doc.patchChange(); + let changes = await this.getFileChanges(); + if (!changes) + return; + changes.sort((a, b) => a.lnum - b.lnum); + 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 || equals(range.lines, change.lines)) { + removeList.push(i); + if (curr && range) { + 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) { + window_default.showMessage("No change.", "more"); + await buffer.setOption("modified", false); + return false; + } + let changeMap = {}; + for (let change of changes) { + let uri = URI.file(change.filepath).toString(); + let edits = changeMap[uri] || []; + edits.push({ + range: import_vscode_languageserver_protocol94.Range.create(change.start, 0, change.end, 0), + newText: change.lines.join("\n") + "\n" + }); + changeMap[uri] = edits; + } + this.changing = true; + await workspace_default.applyEdit({ changes: changeMap }); + this.changing = false; + nvim.pauseNotification(); + buffer.setOption("modified", false, true); + if (this.config.saveToFile) { + nvim.command("silent noa 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; + } + } + } + } + getLinesRange(lnum) { + for (let item of this._fileItems) { + for (let range of item.ranges) { + if (range.lnum == lnum) { + return [range.start, range.end]; + } + } + } + } + async getLines(fsPath, start, end) { + let uri = URI.file(fsPath).toString(); + let doc = workspace_default.getDocument(uri); + if (doc) + return doc.getLines(start, end); + return await readFileLines(fsPath, start, end - 1); + } + getAbsolutePath(filepath) { + if (import_path35.default.isAbsolute(filepath)) + return filepath; + return import_path35.default.join(this.opts.cwd, filepath); + } + getFileRangeRange(range, lineOnly = true) { + let { document: document2 } = this; + if (!document2) + return null; + let { lnum } = range; + let first = document2.getline(lnum - 1); + if (!first.startsWith("\u3000")) + return null; + let start = lineOnly ? lnum : lnum - 1; + let end = document2.lineCount; + for (let i = lnum; i < document2.lineCount; i++) { + let line = document2.getline(i); + if (line.startsWith("\u3000")) { + end = lineOnly ? i : i + 1; + break; + } + } + return import_vscode_languageserver_protocol94.Range.create(start, 0, end, 0); + } + highlightLineNr() { + let { _fileItems: fileItems, nvim, srcId, bufnr } = this; + let { winid, cwd } = this.opts; + 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#highlight#clear_matches", [winid, Array.from(this.matchIds)], true); + this.matchIds.clear(); + } + let id = 2e3; + for (let item of fileItems) { + let filename = `${cwd ? import_path35.default.relative(cwd, item.filepath) : item.filepath}`; + let col = 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); + } + get valid() { + return this.buffer.valid; + } + get buffer() { + return this.nvim.createBuffer(this.bufnr); + } + get document() { + if (this._disposed) + return null; + return workspace_default.getDocument(this.bufnr); + } + dispose() { + this._disposed = true; + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/refactor/index.ts +function adjustRange2(range, offset) { + let { start, end } = range; + return import_vscode_languageserver_protocol95.Range.create(start.line - offset, start.character, end.line - offset, end.character); +} +function emptyWorkspaceEdit(edit2) { + let { changes, documentChanges } = edit2; + if (documentChanges && documentChanges.length) + return false; + if (changes && Object.keys(changes).length) + return false; + return true; +} +var import_vscode_languageserver_protocol95, logger102, name, refactorId, Refactor; +var init_refactor = __esm({ + "src/handler/refactor/index.ts"() { + import_vscode_languageserver_protocol95 = __toModule(require_main2()); + init_esm2(); + init_languages(); + init_util(); + init_fs(); + init_workspace(); + init_search(); + init_buffer4(); + logger102 = require_logger2()("handler-refactor"); + name = "__coc_refactor__"; + refactorId = 0; + Refactor = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.buffers = new Map(); + this.disposables = []; + this._onCreate = new import_vscode_languageserver_protocol95.Emitter(); + this.onCreate = this._onCreate.event; + if (workspace_default.isNvim && this.nvim.hasFunction("nvim_buf_set_virtual_text")) { + this.srcId = workspace_default.createNameSpace("coc-refactor"); + } + this.setConfiguration(); + workspace_default.onDidChangeConfiguration(this.setConfiguration, this, this.disposables); + workspace_default.onDidCloseTextDocument((e) => { + let buf = this.buffers.get(e.bufnr); + if (buf) { + buf.dispose(); + this.buffers.delete(e.bufnr); + } + }, null, this.disposables); + workspace_default.onDidChangeTextDocument((e) => { + let buf = this.buffers.get(e.bufnr); + if (buf) + buf.onChange(e); + }, null, this.disposables); + } + setConfiguration(e) { + if (e && !e.affectsConfiguration("refactor")) + return; + let config = workspace_default.getConfiguration("refactor"); + this.config = Object.assign(this.config || {}, { + afterContext: config.get("afterContext", 3), + beforeContext: config.get("beforeContext", 3), + openCommand: config.get("openCommand", "edit"), + saveToFile: config.get("saveToFile", true) + }); + } + async doRefactor() { + let { doc, position } = await this.handler.getCurrentState(); + if (!languages_default.hasProvider("rename", doc.textDocument)) { + throw new Error(`Rename provider not found for current buffer`); + } + await doc.synchronize(); + let edit2 = await this.handler.withRequestToken("refactor", async (token) => { + let res = await languages_default.prepareRename(doc.textDocument, position, token); + if (token.isCancellationRequested) + return null; + if (res === false) + throw new Error(`Provider returns null on prepare, unable to rename at current position`); + let edit3 = await languages_default.provideRenameEdits(doc.textDocument, position, "NewName", token); + if (token.isCancellationRequested) + return null; + if (!edit3) + throw new Error("Provider returns null for rename edits."); + return edit3; + }); + if (edit2) { + await this.fromWorkspaceEdit(edit2, doc.filetype); + } + } + async search(args) { + let buf = await this.createRefactorBuffer(); + if (!buf) + return; + let cwd = await this.nvim.call("getcwd", []); + let search = new Search(this.nvim); + await search.run(args, cwd, buf); + } + async save(bufnr) { + let buf = this.buffers.get(bufnr); + if (buf) + return await buf.save(); + } + getBuffer(bufnr) { + return this.buffers.get(bufnr); + } + 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); + let [, err] = await nvim.resumeNotification(); + if (err) + return; + let [bufnr, win] = await nvim.eval('[bufnr("%"),win_getid()]'); + let opts = { fromWinid, winid: win, cwd }; + await workspace_default.document; + let buf = new RefactorBuffer(bufnr, this.srcId, this.nvim, this.config, opts); + this.buffers.set(bufnr, buf); + return buf; + } + async fromLines(lines) { + let buf = await this.createRefactorBuffer(); + if (buf) + await buf.buffer.setLines(lines, { start: 0, end: -1, strictIndexing: false }); + return buf; + } + async fromLocations(locations, filetype) { + if (!locations || locations.length == 0) + return null; + let changes = {}; + let edit2 = { changes }; + for (let location of locations) { + let edits = changes[location.uri] || []; + edits.push({ range: location.range, newText: "" }); + changes[location.uri] = edits; + } + return await this.fromWorkspaceEdit(edit2, filetype); + } + async fromWorkspaceEdit(edit2, filetype) { + if (!edit2 || emptyWorkspaceEdit(edit2)) + return void 0; + let items = []; + let { beforeContext, afterContext } = this.config; + let { changes, documentChanges } = edit2; + if (!changes) { + changes = {}; + for (let change of documentChanges || []) { + if (import_vscode_languageserver_protocol95.TextDocumentEdit.is(change)) { + let { textDocument, edits } = change; + if (textDocument.uri.startsWith("file:")) { + changes[textDocument.uri] = edits; + } + } + } + } + for (let key of Object.keys(changes)) { + let max = await this.getLineCount(key); + let edits = changes[key]; + let ranges = []; + let start = null; + let end = null; + let highlights = []; + edits.sort((a, b) => a.range.start.line - b.range.start.line); + for (let edit3 of edits) { + let { line } = edit3.range.start; + let s = Math.max(0, line - beforeContext); + if (start != null && s < end) { + end = Math.min(max, line + afterContext + 1); + highlights.push(adjustRange2(edit3.range, start)); + } else { + if (start != null) + ranges.push({ start, end, highlights }); + start = s; + end = Math.min(max, line + afterContext + 1); + highlights = [adjustRange2(edit3.range, start)]; + } + } + if (start != null) + ranges.push({ start, end, highlights }); + items.push({ + ranges, + filepath: URI.parse(key).fsPath + }); + } + let buf = await this.createRefactorBuffer(filetype); + await buf.addFileItems(items); + return buf; + } + async getLineCount(uri) { + let doc = workspace_default.getDocument(uri); + if (doc) + return doc.lineCount; + return await getFileLineCount(URI.parse(uri).fsPath); + } + reset() { + if (this.timer) { + clearTimeout(this.timer); + } + for (let buf of this.buffers.values()) { + buf.dispose(); + } + this.buffers.clear(); + } + dispose() { + if (this.timer) { + clearTimeout(this.timer); + } + this._onCreate.dispose(); + for (let buf of this.buffers.values()) { + buf.dispose(); + } + this.buffers.clear(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/rename.ts +var import_vscode_languageserver_protocol96, logger103, Rename; +var init_rename = __esm({ + "src/handler/rename.ts"() { + import_vscode_languageserver_protocol96 = __toModule(require_main2()); + init_languages(); + init_position(); + init_window(); + init_workspace(); + logger103 = require_logger2()("handler-rename"); + Rename = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + } + async getWordEdit() { + let { doc, position } = await this.handler.getCurrentState(); + let range = doc.getWordRangeAtPosition(position); + if (!range || emptyRange(range)) + return null; + let curname = doc.textDocument.getText(range); + if (languages_default.hasProvider("rename", doc.textDocument)) { + await doc.synchronize(); + let requestTokenSource = new import_vscode_languageserver_protocol96.CancellationTokenSource(); + let res = await languages_default.prepareRename(doc.textDocument, position, requestTokenSource.token); + if (res === false) + return null; + let edit2 = await languages_default.provideRenameEdits(doc.textDocument, position, curname, requestTokenSource.token); + if (edit2) + return edit2; + } + window_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) => ({ range: r, newText: curname })) + } + }; + } + async rename(newName) { + let { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("rename", doc.textDocument); + await doc.synchronize(); + let token = new import_vscode_languageserver_protocol96.CancellationTokenSource().token; + let res = await languages_default.prepareRename(doc.textDocument, position, token); + if (res === false) { + window_default.showMessage("Invalid position for rename", "warning"); + return false; + } + let curname; + if (!newName) { + if (import_vscode_languageserver_protocol96.Range.is(res)) { + curname = doc.textDocument.getText(res); + await window_default.moveTo(res.start); + } else if (res && typeof res.placeholder === "string") { + curname = res.placeholder; + } else { + curname = await this.nvim.eval('expand("")'); + } + newName = await window_default.requestInput("New name", curname); + } + if (!newName) + return false; + let edit2 = await languages_default.provideRenameEdits(doc.textDocument, position, newName, token); + if (token.isCancellationRequested || !edit2) + return false; + await workspace_default.applyEdit(edit2); + if (workspace_default.isVim) + this.nvim.command("redraw", true); + return true; + } + }; + } +}); + +// src/handler/selectionRange.ts +var import_vscode_languageserver_protocol97, SelectionRangeHandler; +var init_selectionRange2 = __esm({ + "src/handler/selectionRange.ts"() { + import_vscode_languageserver_protocol97 = __toModule(require_main2()); + init_languages(); + init_object(); + init_position(); + init_window(); + init_workspace(); + SelectionRangeHandler = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.selectionRange = null; + } + async getSelectionRanges() { + let { doc, position } = await this.handler.getCurrentState(); + this.handler.checkProvier("selectionRange", doc.textDocument); + await doc.synchronize(); + let selectionRanges = await this.handler.withRequestToken("selection ranges", (token) => { + return languages_default.getSelectionRanges(doc.textDocument, [position], token); + }); + return selectionRanges; + } + async selectRange(visualmode, forward) { + let { nvim } = this; + let { doc } = await this.handler.getCurrentState(); + this.handler.checkProvier("selectionRange", doc.textDocument); + let positions2 = []; + if (!forward && (!this.selectionRange || !visualmode)) + return; + if (visualmode) { + let range = await workspace_default.getSelectedRange(visualmode, doc); + positions2.push(range.start, range.end); + } else { + let position = await window_default.getCursorPosition(); + positions2.push(position); + } + if (!forward) { + let curr = import_vscode_languageserver_protocol97.Range.create(positions2[0], positions2[1]); + let { selectionRange: selectionRange2 } = this; + while (selectionRange2 && selectionRange2.parent) { + if (equals(selectionRange2.parent.range, curr)) { + break; + } + selectionRange2 = selectionRange2.parent; + } + if (selectionRange2 && selectionRange2.parent) { + await workspace_default.selectRange(selectionRange2.range); + } + return; + } + await doc.synchronize(); + let selectionRanges = await this.handler.withRequestToken("selection ranges", (token) => { + return languages_default.getSelectionRanges(doc.textDocument, positions2, token); + }); + if (!selectionRanges || selectionRanges.length == 0) + return; + let mode = await nvim.eval("mode()"); + if (mode != "n") + await nvim.eval(`feedkeys("\\", 'in')`); + let selectionRange; + if (selectionRanges.length == 1) { + selectionRange = selectionRanges[0]; + } else { + let end = positions2[1] || positions2[0]; + let r = import_vscode_languageserver_protocol97.Range.create(positions2[0], end); + selectionRange = selectionRanges[0]; + while (selectionRange) { + if (equals(r, selectionRange.range)) { + selectionRange = selectionRange.parent; + continue; + } + if (positionInRange(positions2[0], selectionRange.range) == 0 && positionInRange(end, selectionRange.range) == 0) { + break; + } + selectionRange = selectionRange.parent; + } + } + if (!selectionRange) + return; + this.selectionRange = selectionRanges[0]; + await workspace_default.selectRange(selectionRange.range); + } + }; + } +}); + +// src/handler/callHierarchy.ts +function isCallHierarchyItem(item) { + if (item && item.name && item.kind && import_vscode_languageserver_protocol98.Range.is(item.range) && item.uri) + return true; + return false; +} +var import_path36, import_vscode_languageserver_protocol98, logger104, _CallHierarchyHandler, CallHierarchyHandler; +var init_callHierarchy2 = __esm({ + "src/handler/callHierarchy.ts"() { + import_path36 = __toModule(require("path")); + import_vscode_languageserver_protocol98 = __toModule(require_main2()); + init_esm2(); + init_commands2(); + init_events(); + init_languages(); + init_tree(); + init_TreeView(); + init_util(); + init_lodash(); + init_workspace(); + logger104 = require_logger2()("Handler-callHierarchy"); + _CallHierarchyHandler = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.disposables = []; + this.highlightWinids = new Set(); + this.loadConfiguration(); + workspace_default.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables); + this.disposables.push(commands_default.registerCommand(_CallHierarchyHandler.commandId, async (winid, item, openCommand) => { + var _a2; + let { nvim: nvim2 } = this; + await nvim2.call("win_gotoid", [winid]); + await workspace_default.jumpTo(item.uri, item.selectionRange.start, openCommand); + let win = await nvim2.window; + win.clearMatchGroup(_CallHierarchyHandler.rangesHighlight); + win.highlightRanges(_CallHierarchyHandler.rangesHighlight, [item.selectionRange], 10, true); + if (!((_a2 = item.ranges) == null ? void 0 : _a2.length)) + return; + if (item.sourceUri) { + let doc = workspace_default.getDocument(item.sourceUri); + if (!doc) + return; + let winid2 = await nvim2.call("coc#compat#buf_win_id", [doc.bufnr]); + if (winid2 == -1) + return; + if (winid2 != win.id) { + win = nvim2.createWindow(winid2); + win.clearMatchGroup(_CallHierarchyHandler.rangesHighlight); + } + } + win.highlightRanges(_CallHierarchyHandler.rangesHighlight, item.ranges, 100, true); + this.highlightWinids.add(win.id); + }, null, true)); + events_default.on("BufWinEnter", (_, winid) => { + if (this.highlightWinids.has(winid)) { + this.highlightWinids.delete(winid); + let win = nvim.createWindow(winid); + win.clearMatchGroup(_CallHierarchyHandler.rangesHighlight); + } + }, null, this.disposables); + } + loadConfiguration(e) { + if (!e || e.affectsConfiguration("callHierarchy")) { + let c = workspace_default.getConfiguration("callHierarchy"); + this.config = { + splitCommand: c.get("splitCommand"), + openCommand: c.get("openCommand"), + enableTooltip: c.get("enableTooltip") + }; + } + } + createProvider(doc, winid, position, kind) { + let _onDidChangeTreeData = new import_vscode_languageserver_protocol98.Emitter(); + let source; + let rootItems; + const cancel = () => { + if (source) { + source.cancel(); + source.dispose(); + source = null; + } + }; + const findParent = (curr, element) => { + let children = curr.children; + if (!Array.isArray(children)) + return void 0; + let find = children.find((o) => o == element); + if (find) + return curr; + for (let item of children) { + let res = findParent(item, element); + if (res) + return res; + } + }; + let provider = { + kind, + onDidChangeTreeData: _onDidChangeTreeData.event, + getTreeItem: (element) => { + var _a2; + let item = new TreeItem(element.name, element.children ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed); + if (this.config.enableTooltip) { + item.tooltip = import_path36.default.relative(workspace_default.cwd, URI.parse(element.uri).fsPath); + } + item.description = element.detail; + item.deprecated = (_a2 = element.tags) == null ? void 0 : _a2.includes(import_vscode_languageserver_protocol98.SymbolTag.Deprecated); + item.icon = this.handler.getIcon(element.kind); + item.command = { + command: _CallHierarchyHandler.commandId, + title: "open location", + arguments: [winid, element, this.config.openCommand] + }; + return item; + }, + getChildren: async (element) => { + cancel(); + source = new import_vscode_languageserver_protocol98.CancellationTokenSource(); + let { token } = source; + if (!element) { + if (!rootItems) { + rootItems = await this.prepare(doc, position, token); + if (!(rootItems == null ? void 0 : rootItems.length)) + return; + } + for (let o of rootItems) { + let children = await this.getChildren(doc, o, provider.kind, token); + if (token.isCancellationRequested) + break; + if (Array.isArray(children)) + o.children = children; + } + return rootItems; + } + if (element.children) + return element.children; + let items = await this.getChildren(doc, element, provider.kind, token); + source = null; + if (token.isCancellationRequested) + return []; + element.children = items; + return items; + }, + resolveActions: () => { + return [{ + title: "Open in new tab", + handler: async (element) => { + await commands_default.executeCommand(_CallHierarchyHandler.commandId, winid, element, "tabe"); + } + }, { + title: "Show Incoming Calls", + handler: (element) => { + rootItems = [omit(element, ["children", "ranges", "sourceUri"])]; + provider.kind = "incoming"; + _onDidChangeTreeData.fire(void 0); + } + }, { + title: "Show Outgoing Calls", + handler: (element) => { + rootItems = [omit(element, ["children", "ranges", "sourceUri"])]; + provider.kind = "outgoing"; + _onDidChangeTreeData.fire(void 0); + } + }, { + title: "Dismiss", + handler: async (element) => { + let parentElement; + for (let curr of rootItems) { + parentElement = findParent(curr, element); + if (parentElement) + break; + } + if (!parentElement) + return; + let idx = parentElement.children.findIndex((o) => o === element); + parentElement.children.splice(idx, 1); + _onDidChangeTreeData.fire(parentElement); + } + }]; + }, + dispose: () => { + cancel(); + _onDidChangeTreeData.dispose(); + rootItems = void 0; + _onDidChangeTreeData = void 0; + } + }; + return provider; + } + async getChildren(doc, item, kind, token) { + let items = []; + if (kind == "incoming") { + let res = await languages_default.provideIncomingCalls(doc, item, token); + if (res) + items = res.map((o) => Object.assign(o.from, { ranges: o.fromRanges })); + } else { + let res = await languages_default.provideOutgoingCalls(doc, item, token); + if (res) + items = res.map((o) => Object.assign(o.to, { ranges: o.fromRanges, sourceUri: item.uri })); + } + return items; + } + async prepare(doc, position, token) { + this.handler.checkProvier("callHierarchy", doc); + const res = await languages_default.prepareCallHierarchy(doc, position, token); + return isCallHierarchyItem(res) ? [res] : res; + } + async getCallHierarchyItems(item, kind) { + const { doc, position } = await this.handler.getCurrentState(); + const source = new import_vscode_languageserver_protocol98.CancellationTokenSource(); + if (!item) { + await doc.synchronize(); + let res = await this.prepare(doc.textDocument, position, source.token); + item = res ? res[0] : void 0; + if (!res) + return void 0; + } + let method = kind == "incoming" ? "provideIncomingCalls" : "provideOutgoingCalls"; + return await languages_default[method](doc.textDocument, item, source.token); + } + async getIncoming(item) { + return await this.getCallHierarchyItems(item, "incoming"); + } + async getOutgoing(item) { + return await this.getCallHierarchyItems(item, "outgoing"); + } + async showCallHierarchyTree(kind) { + const { doc, position, winid } = await this.handler.getCurrentState(); + await doc.synchronize(); + let provider = this.createProvider(doc.textDocument, winid, position, kind); + let treeView = new BasicTreeView("calls", { treeDataProvider: provider }); + treeView.title = `${kind.toUpperCase()} CALLS`; + provider.onDidChangeTreeData((e) => { + if (!e) + treeView.title = `${provider.kind.toUpperCase()} CALLS`; + }); + treeView.onDidChangeVisibility((e) => { + if (!e.visible) + provider.dispose(); + }); + this.disposables.push(treeView); + await treeView.show(this.config.splitCommand); + } + dispose() { + this.highlightWinids.clear(); + disposeAll(this.disposables); + } + }; + CallHierarchyHandler = _CallHierarchyHandler; + CallHierarchyHandler.commandId = "callHierarchy.reveal"; + CallHierarchyHandler.rangesHighlight = "CocSelectedRange"; + } +}); + +// src/handler/semanticTokensHighlights/buffer.ts +var import_debounce12, import_vscode_languageserver_protocol99, logger105, SEMANTIC_HLGROUP_PREFIX, NAMESPACE, SemanticTokensBuffer; +var init_buffer5 = __esm({ + "src/handler/semanticTokensHighlights/buffer.ts"() { + import_debounce12 = __toModule(require_debounce()); + import_vscode_languageserver_protocol99 = __toModule(require_main2()); + init_languages(); + init_workspace(); + logger105 = require_logger2()("semanticTokens-buffer"); + SEMANTIC_HLGROUP_PREFIX = "CocSem_"; + NAMESPACE = "semanticTokens"; + SemanticTokensBuffer = class { + constructor(nvim, bufnr, config) { + this.nvim = nvim; + this.bufnr = bufnr; + this.config = config; + this.highlight = (0, import_debounce12.default)(() => { + this.doHighlight().catch((e) => { + logger105.error("Error on semanticTokens highlight:", e.stack); + }); + }, global.hasOwnProperty("__TEST__") ? 10 : 2e3); + this.highlight(); + } + onChange() { + this.cancel(); + this.highlight(); + } + async forceHighlight() { + this.cancel(); + this.highlight.clear(); + await this.doHighlight(); + } + get highlights() { + return this._highlights; + } + get enabled() { + if (!this.config.enabled) + return false; + let doc = workspace_default.getDocument(this.bufnr); + if (!doc || !doc.attached) + return false; + return languages_default.hasProvider("semanticTokens", doc.textDocument); + } + get previousVersion() { + if (!this.previousResults) + return void 0; + return this.previousResults.version; + } + get buffer() { + return this.nvim.createBuffer(this.bufnr); + } + checkState() { + if (!this.config.enabled) + throw new Error("SemanticTokens highlights disabled by configuration"); + let doc = workspace_default.getDocument(this.bufnr); + if (!doc || !doc.attached) + throw new Error("Document not attached"); + if (!languages_default.hasProvider("semanticTokens", doc.textDocument)) + throw new Error("SemanticTokens provider not found, your languageserver may not support it"); + } + setState(enabled) { + if (enabled) { + this.highlight(); + } else { + this.highlight.clear(); + this.clearHighlight(); + } + } + async doHighlight() { + if (!this.enabled) + return; + let doc = workspace_default.getDocument(this.bufnr); + const { nvim } = this; + let winid = await nvim.call("bufwinid", [this.bufnr]); + if (winid == -1) + return; + const curr = await this.requestHighlights(doc); + if (!curr) + return; + if (!curr.length) { + this.clearHighlight(); + return; + } + let prev = []; + if (workspace_default.env.updateHighlight) { + prev = await nvim.call("coc#highlight#get_highlights", [this.bufnr, NAMESPACE]); + } + const { highlights, lines } = this.calculateHighlightUpdates(prev, curr); + nvim.pauseNotification(); + if (!workspace_default.env.updateHighlight) { + this.buffer.clearNamespace(NAMESPACE, 0, -1); + } else { + for (const ln of lines) { + this.buffer.clearNamespace(NAMESPACE, ln, ln + 1); + } + } + const groups = {}; + if (highlights.length) { + for (const h of highlights) { + const range = import_vscode_languageserver_protocol99.Range.create(h.lnum, h.colStart, h.lnum, h.colEnd); + groups[h.hlGroup] = groups[h.hlGroup] || []; + groups[h.hlGroup].push(range); + } + } + for (const hlGroup of Object.keys(groups)) { + this.buffer.highlightRanges(NAMESPACE, hlGroup, groups[hlGroup]); + } + nvim.resumeNotification(false, true); + if (workspace_default.isVim) + nvim.command("redraw", true); + } + calculateHighlightUpdates(prev, curr) { + const stringCompare = Intl.Collator("en").compare; + function compare(a, b) { + return a.lnum - b.lnum || a.colStart - b.colStart || a.colEnd - b.colEnd || stringCompare(a.hlGroup, b.hlGroup); + } + prev = prev.slice().sort(compare); + curr = curr.slice().sort(compare); + const prevByLine = new Map(); + for (const hl of prev) { + if (!prevByLine.has(hl.lnum)) + prevByLine.set(hl.lnum, []); + prevByLine.get(hl.lnum).push(hl); + } + const currByLine = new Map(); + for (const hl of curr) { + if (!currByLine.has(hl.lnum)) + currByLine.set(hl.lnum, []); + currByLine.get(hl.lnum).push(hl); + } + const lastLine = Math.max((prev[prev.length - 1] || { lnum: 0 }).lnum, (curr[curr.length - 1] || { lnum: 0 }).lnum); + const lineNumbersToUpdate = new Set(); + for (let i = 0; i <= lastLine; i++) { + const ph = prevByLine.has(i); + const ch = currByLine.has(i); + if (ph !== ch) { + lineNumbersToUpdate.add(i); + continue; + } else if (!ph && !ch) { + continue; + } + const pp = prevByLine.get(i); + const cc = currByLine.get(i); + if (pp.length !== cc.length) { + lineNumbersToUpdate.add(i); + continue; + } + for (let j = 0; j < pp.length; j++) { + if (compare(pp[j], cc[j]) !== 0) { + lineNumbersToUpdate.add(i); + continue; + } + } + } + let highlights = []; + for (const line of lineNumbersToUpdate) { + highlights = highlights.concat(currByLine.get(line) || []); + } + return { highlights, lines: lineNumbersToUpdate }; + } + async requestHighlights(doc, forceFull) { + const legend = languages_default.getLegend(doc.textDocument); + if (!legend) + return void 0; + this.cancel(); + this.tokenSource = new import_vscode_languageserver_protocol99.CancellationTokenSource(); + const { token } = this.tokenSource; + const hasEditProvider = languages_default.hasSemanticTokensEdits(doc.textDocument); + const previousResult = forceFull ? null : this.previousResults; + let result; + let version2 = doc.textDocument.version; + if (hasEditProvider && (previousResult == null ? void 0 : previousResult.resultId)) { + result = await languages_default.provideDocumentSemanticTokensEdits(doc.textDocument, previousResult.resultId, token); + } else { + result = await languages_default.provideDocumentSemanticTokens(doc.textDocument, token); + } + this.tokenSource = null; + if (token.isCancellationRequested || !result) + return void 0; + let tokens = []; + if (import_vscode_languageserver_protocol99.SemanticTokens.is(result)) { + tokens = result.data; + } else { + tokens = previousResult.tokens; + result.edits.forEach((e) => { + if (e.deleteCount > 0) { + tokens.splice(e.start, e.deleteCount, ...e.data); + } else { + tokens.splice(e.start, 0, ...e.data); + } + }); + } + this.previousResults = { resultId: result.resultId, tokens, version: version2 }; + const relatives = []; + for (let i = 0; i < tokens.length; i += 5) { + const deltaLine = tokens[i]; + const deltaStartCharacter = tokens[i + 1]; + const length = tokens[i + 2]; + const tokenType = tokens[i + 3]; + const group2 = SEMANTIC_HLGROUP_PREFIX + legend.tokenTypes[tokenType]; + relatives.push({ + group: group2, + deltaLine, + deltaStartCharacter, + length + }); + } + const res = []; + let currentLine = 0; + let currentCharacter = 0; + for (const { + group: group2, + deltaLine, + deltaStartCharacter, + length + } of relatives) { + const lnum = currentLine + deltaLine; + const colStart = deltaLine === 0 ? currentCharacter + deltaStartCharacter : deltaStartCharacter; + const colEnd = colStart + length; + currentLine = lnum; + currentCharacter = colStart; + res.push({ + hlGroup: group2, + lnum, + colStart, + colEnd + }); + } + this._highlights = res; + return res; + } + clearHighlight() { + this.buffer.clearNamespace(NAMESPACE); + } + cancel() { + if (this.tokenSource) { + this.tokenSource.cancel(); + this.tokenSource = null; + } + } + dispose() { + this.highlight.clear(); + this.previousResults = void 0; + this.cancel(); + } + }; + } +}); + +// src/handler/semanticTokensHighlights/index.ts +var logger106, headGroup, SemanticTokensHighlights; +var init_semanticTokensHighlights = __esm({ + "src/handler/semanticTokensHighlights/index.ts"() { + init_commands2(); + init_events(); + init_languages(); + init_highligher(); + init_util(); + init_window(); + init_workspace(); + init_buffer5(); + logger106 = require_logger2()("semanticTokens"); + headGroup = "Statement"; + SemanticTokensHighlights = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.disposables = []; + this.loadConfiguration(); + workspace_default.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables); + commands_default.register({ + id: "semanticTokens.checkCurrent", + execute: async () => { + try { + let item = await this.getCurrentItem(); + item.checkState(); + } catch (e) { + window_default.showMessage(e.message, "error"); + return; + } + window_default.showMessage("Semantic tokens provider found for current buffer", "more"); + } + }, false, "check semantic tokens provider for current buffer"); + commands_default.register({ + id: "semanticTokens.clearCurrent", + execute: async () => { + let buf = await nvim.buffer; + buf.clearNamespace(NAMESPACE, 0, -1); + } + }, false, "clear semantic tokens highlights of current buffer"); + commands_default.register({ + id: "semanticTokens.clearAll", + execute: async () => { + let bufs = await nvim.buffers; + for (let buf of bufs) { + buf.clearNamespace(NAMESPACE, 0, -1); + } + } + }, false, "clear semantic tokens highlights of all buffers"); + this.disposables.push({ + dispose: () => { + commands_default.unregister("semanticTokens.checkCurrentBuffer"); + } + }); + events_default.on("BufEnter", (bufnr) => { + let item = this.highlighters.getItem(bufnr); + if (!item) + return; + let doc = workspace_default.getDocument(bufnr); + if (!doc || doc.textDocument.version == item.previousVersion) + return; + item.forceHighlight().catch((e) => { + logger106.error(`Error on semantic highlighters:`, e); + }); + }, null, this.disposables); + this.highlighters = workspace_default.registerBufferSync((doc) => { + return new SemanticTokensBuffer(this.nvim, doc.bufnr, this.config); + }); + languages_default.onDidSemanticTokensRefresh((selector) => { + for (let item of this.highlighters.items) { + let doc = workspace_default.getDocument(item.bufnr); + if (doc && workspace_default.match(selector, doc.textDocument)) { + item.highlight(); + } + } + }, null, this.disposables); + } + loadConfiguration(e) { + if (!e || e.affectsConfiguration("coc.preferences")) { + let config = workspace_default.getConfiguration("coc.preferences"); + let enabled = config.get("semanticTokensHighlights", true); + if (workspace_default.isVim && !workspace_default.env.textprop) { + enabled = false; + } + if (this.config && enabled != this.config.enabled) { + if (this.highlighters) { + for (let buf of this.highlighters.items) { + buf.setState(enabled); + } + } + } + if (!this.config) { + this.config = { enabled }; + } else { + this.config.enabled = enabled; + } + } + } + async getCurrentItem() { + let buf = await this.nvim.buffer; + let highlighter = this.highlighters.getItem(buf.id); + if (!highlighter) + throw new Error("current buffer not attached"); + return highlighter; + } + async highlightCurrent() { + let highlighter = await this.getCurrentItem(); + highlighter.checkState(); + await highlighter.forceHighlight(); + } + async showHiglightInfo() { + if (!this.config.enabled) + throw new Error("Semantic highlights is disabled by configuration."); + let item = await this.getCurrentItem(); + item.checkState(); + let highlights = item.highlights || []; + let highlighter = new Highlighter(); + let { nvim } = this; + nvim.pauseNotification(); + nvim.command(`vs +setl\\ buftype=nofile __coc_semantic_highlights_${item.bufnr}__`, true); + nvim.command(`setl bufhidden=wipe noswapfile nobuflisted wrap undolevels=-1`, true); + nvim.call("bufnr", ["%"], true); + let res = await nvim.resumeNotification(); + if (res[1]) + throw new Error(`Error on buffer create: ${res[1]}`); + let bufnr = res[0][2]; + highlighter.addLine("Semantic highlights info", headGroup); + highlighter.addLine(""); + highlighter.addLine("The number of semantic tokens: "); + highlighter.addText(String(highlights.length), "Number"); + highlighter.addLine(""); + highlighter.addLine("Semantic highlight groups used by current buffer", headGroup); + highlighter.addLine(""); + const groups = [...new Set(highlights.map(({ hlGroup }) => hlGroup))]; + for (const hlGroup of groups) { + highlighter.addTexts([{ text: "-", hlGroup: "Comment" }, { text: " " }, { text: hlGroup, hlGroup }]); + highlighter.addLine(""); + } + highlighter.addLine("Tokens types that current Language Server supported:", headGroup); + highlighter.addLine(""); + let doc = workspace_default.getDocument(item.bufnr); + const legend = languages_default.getLegend(doc.textDocument); + if (legend == null ? void 0 : legend.tokenTypes.length) { + for (const t of [...new Set(legend.tokenTypes)]) { + highlighter.addTexts([{ text: "-", hlGroup: "Comment" }, { text: " " }, { text: `CocSem_${t}`, hlGroup: `CocSem_${t}` }]); + highlighter.addLine(""); + } + } else { + highlighter.addLine("No token types supported", "Comment"); + } + highlighter.addLine("Tokens modifiers that current Language Server supported:", headGroup); + highlighter.addLine(""); + if (legend == null ? void 0 : legend.tokenModifiers.length) { + for (const t of [...new Set(legend.tokenModifiers)]) { + highlighter.addTexts([{ text: "-", hlGroup: "Comment" }, { text: " " }, { text: `CocSem_${t}`, hlGroup: `CocSem_${t}` }]); + highlighter.addLine(""); + } + } else { + highlighter.addLine("No token modifiers supported", "Comment"); + } + nvim.pauseNotification(); + highlighter.render(nvim.createBuffer(bufnr)); + nvim.resumeNotification(false, true); + } + dispose() { + this.highlighters.dispose(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/signature.ts +var import_vscode_languageserver_protocol100, logger107, Signature; +var init_signature = __esm({ + "src/handler/signature.ts"() { + import_vscode_languageserver_protocol100 = __toModule(require_main2()); + init_events(); + init_languages(); + init_floatFactory(); + init_util(); + init_string(); + init_workspace(); + logger107 = require_logger2()("handler-signature"); + Signature = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.disposables = []; + this.signatureFactory = new FloatFactory(nvim); + this.loadConfiguration(); + this.disposables.push(this.signatureFactory); + workspace_default.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables); + events_default.on("CursorMovedI", async (bufnr, cursor) => { + let pos = this.lastPosition; + if (!pos) + return; + if (pos.bufnr == bufnr && pos.lnum == cursor[0] && pos.col <= cursor[1]) + return; + this.signatureFactory.close(); + }, null, this.disposables); + events_default.on(["InsertLeave", "BufEnter"], () => { + var _a2; + (_a2 = this.tokenSource) == null ? void 0 : _a2.cancel(); + }, null, this.disposables); + events_default.on("TextChangedI", () => { + if (this.config.hideOnChange) { + this.signatureFactory.close(); + } + }, null, this.disposables); + events_default.on("TextInsert", async (bufnr, info, character) => { + if (!this.config.trigger) + return; + let doc = this.getTextDocument(bufnr); + if (!doc || !languages_default.shouldTriggerSignatureHelp(doc.textDocument, character)) + return; + await this._triggerSignatureHelp(doc, { line: info.lnum - 1, character: info.pre.length }, false); + }, null, this.disposables); + } + getTextDocument(bufnr) { + let doc = workspace_default.getDocument(bufnr); + if (!doc || doc.isCommandLine || !doc.attached) + return; + return doc; + } + loadConfiguration(e) { + if (!e || e.affectsConfiguration("signature")) { + let config = workspace_default.getConfiguration("signature"); + let target = config.get("target", "float"); + if (target == "float" && !workspace_default.floatSupported) { + target = "echo"; + } + this.config = { + target, + floatConfig: config.get("floatConfig", {}), + trigger: config.get("enable", true), + wait: Math.max(config.get("triggerSignatureWait", 500), 200), + preferAbove: config.get("preferShownAbove", true), + hideOnChange: config.get("hideOnTextChange", false) + }; + } + } + async triggerSignatureHelp() { + let { doc, position, mode } = await this.handler.getCurrentState(); + if (!languages_default.hasProvider("signature", doc.textDocument)) + return false; + let offset = 0; + let character = position.character; + if (mode == "s") { + let placeholder = await this.nvim.getVar("coc_last_placeholder"); + if (placeholder) { + let { start, end, bufnr } = placeholder; + if (bufnr == doc.bufnr && start.line == end.line && start.line == position.line) { + position = import_vscode_languageserver_protocol100.Position.create(start.line, start.character); + offset = character - position.character; + } + } + } + return await this._triggerSignatureHelp(doc, position, true, offset); + } + async _triggerSignatureHelp(doc, position, invoke = true, offset = 0) { + var _a2; + (_a2 = this.tokenSource) == null ? void 0 : _a2.cancel(); + let tokenSource = this.tokenSource = new import_vscode_languageserver_protocol100.CancellationTokenSource(); + let token = tokenSource.token; + token.onCancellationRequested(() => { + tokenSource.dispose(); + this.tokenSource = void 0; + }); + let { target } = this.config; + let timer = this.timer = setTimeout(() => { + tokenSource.cancel(); + }, this.config.wait); + await doc.patchChange(true); + let signatureHelp = await languages_default.getSignatureHelp(doc.textDocument, position, token, { + isRetrigger: this.signatureFactory.checkRetrigger(doc.bufnr), + triggerKind: invoke ? import_vscode_languageserver_protocol100.SignatureHelpTriggerKind.Invoked : import_vscode_languageserver_protocol100.SignatureHelpTriggerKind.TriggerCharacter + }); + clearTimeout(timer); + if (token.isCancellationRequested) + return false; + if (!signatureHelp || signatureHelp.signatures.length == 0) { + this.signatureFactory.close(); + return false; + } + let { activeSignature, signatures } = signatureHelp; + if (activeSignature) { + let [active] = signatures.splice(activeSignature, 1); + if (active) + signatures.unshift(active); + } + if (target == "echo") { + this.echoSignature(signatureHelp); + } else { + await this.showSignatureHelp(doc, position, signatureHelp, offset); + } + return true; + } + async showSignatureHelp(doc, position, signatureHelp, offset) { + let { signatures, activeParameter } = signatureHelp; + let paramDoc = null; + let startOffset = offset; + let docs = signatures.reduce((p, c, idx) => { + var _a2; + let activeIndexes = null; + let nameIndex = c.label.indexOf("("); + if (idx == 0 && activeParameter != null) { + let active = (_a2 = c.parameters) == null ? void 0 : _a2[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]; + } + if (offset == startOffset) { + offset = offset + activeIndexes[0] + 1; + } + p.push({ + content: c.label, + filetype: doc.filetype, + active: activeIndexes + }); + if (paramDoc) { + let content2 = typeof paramDoc === "string" ? paramDoc : paramDoc.value; + if (content2.trim().length) { + p.push({ + content: content2, + filetype: isMarkdown(c.documentation) ? "markdown" : "txt" + }); + } + } + if (idx == 0 && c.documentation) { + let { documentation } = c; + let content2 = typeof documentation === "string" ? documentation : documentation.value; + if (content2.trim().length) { + p.push({ + content: content2, + filetype: isMarkdown(c.documentation) ? "markdown" : "txt" + }); + } + } + return p; + }, []); + let content = doc.getline(position.line, false).slice(0, position.character); + this.lastPosition = { bufnr: doc.bufnr, lnum: position.line + 1, col: byteLength(content) + 1 }; + const excludeImages = workspace_default.getConfiguration("coc.preferences").get("excludeImageLinksInMarkdownDocument"); + let config = this.signatureFactory.applyFloatConfig({ + preferTop: this.config.preferAbove, + autoHide: false, + offsetX: offset, + modes: ["i", "ic", "s"], + excludeImages + }, this.config.floatConfig); + await this.signatureFactory.show(docs, config); + } + echoSignature(signatureHelp) { + var _a2; + let { signatures, activeParameter } = signatureHelp; + let columns = workspace_default.env.columns; + signatures = signatures.slice(0, workspace_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 = (_a2 = signature.parameters) == null ? void 0 : _a2[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); + } + dispose() { + disposeAll(this.disposables); + if (this.timer) { + clearTimeout(this.timer); + } + } + }; + } +}); + +// src/handler/symbols/util.ts +function convertSymbols(symbols) { + let res = []; + let arr = symbols.slice(); + arr.sort(sortDocumentSymbols); + arr.forEach((s) => addDocumentSymbol(res, s, 0)); + return res; +} +function sortDocumentSymbols(a, b) { + let ra = a.selectionRange; + let rb = b.selectionRange; + return comparePosition(ra.start, rb.start); +} +function addDocumentSymbol(res, sym, level) { + let { name: name2, selectionRange, kind, children, range } = sym; + let { start } = selectionRange || range; + res.push({ + col: start.character + 1, + lnum: start.line + 1, + text: name2, + level, + kind: getSymbolKind(kind), + range, + selectionRange + }); + if (children && children.length) { + children.sort(sortDocumentSymbols); + for (let sym2 of children) { + addDocumentSymbol(res, sym2, level + 1); + } + } +} +function isDocumentSymbol(a) { + return a && !a.hasOwnProperty("location"); +} +function isDocumentSymbols(a) { + return isDocumentSymbol(a[0]); +} +var init_util5 = __esm({ + "src/handler/symbols/util.ts"() { + init_convert(); + init_position(); + } +}); + +// src/handler/symbols/buffer.ts +var import_debounce13, import_vscode_languageserver_protocol101, SymbolsBuffer; +var init_buffer6 = __esm({ + "src/handler/symbols/buffer.ts"() { + import_debounce13 = __toModule(require_debounce()); + import_vscode_languageserver_protocol101 = __toModule(require_main2()); + init_languages(); + init_util(); + init_workspace(); + init_util5(); + SymbolsBuffer = class { + constructor(bufnr) { + this.bufnr = bufnr; + this.disposables = []; + this.autoUpdate = false; + this._onDidUpdate = new import_vscode_languageserver_protocol101.Emitter(); + this.onDidUpdate = this._onDidUpdate.event; + this.fetchSymbols = (0, import_debounce13.default)(() => { + this._fetchSymbols().logError(); + }, global.hasOwnProperty("__TEST__") ? 10 : 500); + } + async getSymbols() { + var _a2; + let doc = workspace_default.getDocument(this.bufnr); + if (!doc) + return []; + await doc.patchChange(); + this.autoUpdate = true; + if (doc.version == this.version && ((_a2 = this.symbols) == null ? void 0 : _a2.length)) + return this.symbols; + this.cancel(); + await this._fetchSymbols(); + return this.symbols; + } + onChange() { + this.cancel(); + if (this.autoUpdate) { + this.fetchSymbols(); + } + } + get textDocument() { + var _a2; + return (_a2 = workspace_default.getDocument(this.bufnr)) == null ? void 0 : _a2.textDocument; + } + async _fetchSymbols() { + let { textDocument } = this; + if (!textDocument) + return; + let { version: version2 } = textDocument; + let tokenSource = this.tokenSource = new import_vscode_languageserver_protocol101.CancellationTokenSource(); + let { token } = tokenSource; + let symbols = await languages_default.getDocumentSymbol(textDocument, token); + this.tokenSource = void 0; + if (symbols == null || token.isCancellationRequested) + return; + let res; + if (isDocumentSymbols(symbols)) { + res = symbols; + } else { + res = symbols.map((o) => { + let sym = import_vscode_languageserver_protocol101.DocumentSymbol.create(o.name, "", o.kind, o.location.range, o.location.range); + if (o.deprecated) + sym.tags = [import_vscode_languageserver_protocol101.SymbolTag.Deprecated]; + return sym; + }); + } + this.version = version2; + this.symbols = res; + this._onDidUpdate.fire(res); + } + cancel() { + this.fetchSymbols.clear(); + if (this.tokenSource) { + this.tokenSource.cancel(); + this.tokenSource.dispose(); + this.tokenSource = null; + } + } + dispose() { + this.cancel(); + this.symbols = void 0; + this._onDidUpdate.dispose(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/tree/BasicDataProvider.ts +function isIcon(obj) { + if (!obj) + return false; + return typeof obj.text === "string" && typeof obj.hlGroup === "string"; +} +function sameTreeNode(one, two) { + if (one.label === two.label && one.deprecated === two.deprecated && one.key === two.key) { + return true; + } + return false; +} +function sameTreeNodes(one, two) { + if (one.length !== two.length) + return false; + return one.every((v, idx) => sameTreeNode(v, two[idx])); +} +var import_vscode_languageserver_protocol102, BasicDataProvider; +var init_BasicDataProvider = __esm({ + "src/tree/BasicDataProvider.ts"() { + init_esm_node(); + import_vscode_languageserver_protocol102 = __toModule(require_main2()); + init_commands2(); + init_util(); + init_TreeItem(); + BasicDataProvider = class { + constructor(opts) { + this.opts = opts; + this.disposables = []; + this._onDidChangeTreeData = new import_vscode_languageserver_protocol102.Emitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; + this.invokeCommand = `_invoke_${v4_default()}`; + this.disposables.push(commands_default.registerCommand(this.invokeCommand, async (node) => { + if (typeof opts.handleClick === "function") { + await opts.handleClick(node); + } else { + console.error("Handler not found"); + } + }, null, true)); + if (typeof opts.resolveActions === "function") { + this.resolveActions = opts.resolveActions.bind(this); + } + } + iterate(node, parentNode, level, fn) { + let res = fn(node, parentNode, level); + if (res === false) + return false; + if (Array.isArray(node.children)) { + for (let element of node.children) { + let res2 = this.iterate(element, node, level + 1, fn); + if (res2 === false) + return false; + } + } + return res; + } + updateNodes(old, data, parentNode, fireEvent = true) { + let sameNodes = sameTreeNodes(old, data); + const applyNode = (previous, curr, fireEvent2) => { + var _a2, _b, _c, _d, _e, _f; + let changed = false; + for (let key of Object.keys(curr)) { + if (["children", "key"].includes(key)) + continue; + previous[key] = curr[key]; + } + if (((_a2 = previous.children) == null ? void 0 : _a2.length) && !((_b = curr.children) == null ? void 0 : _b.length)) { + delete previous.children; + changed = true; + } + if (!((_c = previous.children) == null ? void 0 : _c.length) && ((_d = curr.children) == null ? void 0 : _d.length)) { + previous.children = curr.children; + changed = true; + } + if (changed) { + if (fireEvent2) + this._onDidChangeTreeData.fire(previous); + return; + } + if (((_e = previous.children) == null ? void 0 : _e.length) && ((_f = curr.children) == null ? void 0 : _f.length)) { + this.updateNodes(previous.children, curr.children, previous, fireEvent2); + } + }; + if (sameNodes) { + for (let i = 0; i < old.length; i++) { + applyNode(old[i], data[i], fireEvent); + } + } else { + let oldNodes = old.splice(0, old.length); + let used = new Set(); + for (let i = 0; i < data.length; i++) { + let curr = data[i]; + let findIndex; + if (curr.key) { + findIndex = oldNodes.findIndex((o, i2) => !used.has(i2) && o.key == curr.key); + } else { + findIndex = oldNodes.findIndex((o, i2) => !used.has(i2) && o.label == curr.label); + } + if (findIndex === -1) { + old[i] = curr; + } else { + used.add(findIndex); + let previous = oldNodes[findIndex]; + applyNode(previous, curr, false); + old[i] = previous; + } + } + if (fireEvent) { + this._onDidChangeTreeData.fire(parentNode); + } + } + } + update(data, reset) { + if (!this.data) + return; + if (reset) { + this.data = data || []; + this._onDidChangeTreeData.fire(void 0); + } else { + this.updateNodes(this.data, data || [], void 0); + } + return this.data; + } + getTreeItem(node) { + var _a2; + let label = node.label; + let { expandLevel } = this.opts; + let item; + if (!((_a2 = node.children) == null ? void 0 : _a2.length)) { + item = new TreeItem(label); + } else { + if (expandLevel && expandLevel > 0) { + let level = this.getLevel(node); + let state = level && level <= expandLevel ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed; + item = new TreeItem(label, state); + } else { + item = new TreeItem(label, TreeItemCollapsibleState.Collapsed); + } + } + item.description = node.description; + if (node.deprecated) + item.deprecated = true; + if (node.tooltip) + item.tooltip = node.tooltip; + if (isIcon(node.icon)) { + item.icon = node.icon; + } else if (typeof this.opts.resolveIcon === "function") { + let res = this.opts.resolveIcon(node); + if (res) + item.icon = res; + } + return item; + } + async getChildren(element) { + if (element) + return element.children || []; + if (this.data) + return this.data; + let data = await Promise.resolve(this.opts.provideData()); + if (!Array.isArray(data)) + throw new Error(`Unable to fetch data`); + this.data = data; + return data; + } + getParent(element) { + if (!this.data) + return void 0; + let find; + for (let item of this.data) { + let res = this.iterate(item, null, 0, (node, parentNode) => { + if (node === element) { + find = parentNode; + return false; + } + }); + if (res === false) + break; + } + return find; + } + getLevel(element) { + if (!this.data) + return void 0; + let level = 0; + for (let item of this.data) { + let res = this.iterate(item, null, 1, (node, _parentNode, l) => { + if (node === element) { + level = l; + return false; + } + }); + if (res === false) + break; + } + return level; + } + async resolveTreeItem(item, element, token) { + if (typeof this.opts.resolveItem === "function") { + let res = await Promise.resolve(this.opts.resolveItem(item, element, token)); + if (res) + Object.assign(item, res); + } + if (!item.command) { + item.command = { + title: `invoke ${element.label}`, + command: this.invokeCommand, + arguments: [element] + }; + } + return item; + } + dispose() { + this.data = []; + this._onDidChangeTreeData.dispose(); + if (typeof this.opts.onDispose === "function") { + this.opts.onDispose(); + } + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/symbols/outline.ts +var import_debounce14, import_vscode_languageserver_protocol103, logger108, SymbolsOutline; +var init_outline2 = __esm({ + "src/handler/symbols/outline.ts"() { + import_debounce14 = __toModule(require_debounce()); + import_vscode_languageserver_protocol103 = __toModule(require_main2()); + init_events(); + init_languages(); + init_BasicDataProvider(); + init_TreeView(); + init_util(); + init_position(); + init_window(); + init_workspace(); + logger108 = require_logger2()("symbols-outline"); + SymbolsOutline = class { + constructor(nvim, buffers, handler) { + this.nvim = nvim; + this.buffers = buffers; + this.handler = handler; + this.providersMap = new Map(); + this.treeViews = new WeakMap(); + this.originalWins = new WeakMap(); + this.disposables = []; + this.loadConfiguration(); + workspace_default.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables); + events_default.on("BufUnload", async (bufnr) => { + let provider = this.providersMap.get(bufnr); + if (!provider) + return; + this.providersMap.delete(bufnr); + provider.dispose(); + let views = this.treeViews.get(provider); + this.treeViews.delete(provider); + for (let view of views) { + if (!view.visible) + continue; + let winid = this.originalWins.get(view); + if (winid && this.config.checkBufferSwitch) { + let nr = await nvim.call("win_id2win", [winid]); + if (nr) { + let win = nvim.createWindow(view.windowId); + win.setVar("target_bufnr", -1, true); + let timer = setTimeout(() => { + if (view.visible) + view.dispose(); + }, 200); + this.disposables.push({ + dispose: () => { + clearTimeout(timer); + } + }); + continue; + } + } + view.dispose(); + } + }, null, this.disposables); + events_default.on("BufEnter", (0, import_debounce14.default)(() => { + void this._onBufEnter(); + }, global.hasOwnProperty("__TEST__") ? 100 : 300), null, this.disposables); + events_default.on("CursorHold", async (bufnr) => { + if (!this.config.followCursor) + return; + let provider = this.providersMap.get(bufnr); + if (!provider) + return; + let views = this.treeViews.get(provider); + if (!views || !views.length) + return; + let winid = await this.nvim.call("coc#window#find", ["cocViewId", "OUTLINE"]); + if (winid == -1) + return; + let view = views.find((o) => o.windowId == winid); + if (!view) + return; + let pos = await window_default.getCursorPosition(); + let curr; + let checkNode = (node) => { + if (positionInRange(pos, node.range) != 0) + return false; + curr = node; + if (Array.isArray(node.children)) { + for (let n of node.children) { + if (checkNode(n)) + break; + } + } + return true; + }; + let nodes = await Promise.resolve(provider.getChildren()); + for (let n of nodes) { + if (checkNode(n)) + break; + } + if (curr) + await view.reveal(curr); + }, null, this.disposables); + } + async _onBufEnter() { + if (!this.config.checkBufferSwitch) + return; + let [curr, bufnr, winid] = await this.nvim.eval(`[win_getid(),bufnr('%'),coc#window#find('cocViewId', 'OUTLINE')]`); + if (curr == winid || winid == -1) + return; + if (!this.buffers.getItem(bufnr)) + return; + let win = this.nvim.createWindow(winid); + let target = await win.getVar("target_bufnr"); + if (target == bufnr) + return; + await this.show(1); + } + loadConfiguration(e) { + if (!e || e.affectsConfiguration("outline")) { + let c = workspace_default.getConfiguration("outline"); + this.config = { + splitCommand: c.get("splitCommand"), + followCursor: c.get("followCursor"), + keepWindow: c.get("keepWindow"), + expandLevel: c.get("expandLevel"), + checkBufferSwitch: c.get("checkBufferSwitch"), + sortBy: c.get("sortBy"), + showLineNumber: c.get("showLineNumber"), + codeActionKinds: c.get("codeActionKinds") + }; + } + } + convertSymbolToNode(documentSymbol, sortFn) { + var _a2; + return { + label: documentSymbol.name, + tooltip: documentSymbol.detail, + description: this.config.showLineNumber ? `${documentSymbol.selectionRange.start.line + 1}` : void 0, + icon: this.handler.getIcon(documentSymbol.kind), + deprecated: (_a2 = documentSymbol.tags) == null ? void 0 : _a2.includes(import_vscode_languageserver_protocol103.SymbolTag.Deprecated), + kind: documentSymbol.kind, + range: documentSymbol.range, + selectRange: documentSymbol.selectionRange, + children: Array.isArray(documentSymbol.children) ? documentSymbol.children.map((o) => { + return this.convertSymbolToNode(o, sortFn); + }).sort(sortFn) : void 0 + }; + } + setMessage(provider, msg) { + let views = this.treeViews.get(provider); + if (views) { + views.forEach((view) => { + view.message = msg; + }); + } + } + createProvider(buf) { + let { bufnr } = buf; + let { sortBy } = this.config; + let { nvim } = this; + let sortFn = (a, b) => { + if (sortBy === "name") { + return a.label < b.label ? -1 : 1; + } + if (sortBy === "category") { + if (a.kind == b.kind) + return a.label < b.label ? -1 : 1; + return a.kind - b.kind; + } + return comparePosition(a.selectRange.start, b.selectRange.start); + }; + let convertSymbols2 = (symbols) => { + return symbols.map((s) => this.convertSymbolToNode(s, sortFn)).sort(sortFn); + }; + let disposable; + let provider = new BasicDataProvider({ + expandLevel: this.config.expandLevel, + provideData: async () => { + let doc = workspace_default.getDocument(bufnr); + if (!languages_default.hasProvider("documentSymbol", doc.textDocument)) { + throw new Error("Document symbol provider not found"); + } + this.setMessage(provider, "Loading document symbols"); + let arr = await buf.getSymbols(); + if (!arr || arr.length == 0) { + throw new Error("Empty symbols returned from language server. "); + } + disposable = buf.onDidUpdate((symbols) => { + provider.update(convertSymbols2(symbols)); + }); + this.setMessage(provider, void 0); + return convertSymbols2(arr); + }, + handleClick: async (item) => { + let winnr = await nvim.call("bufwinnr", [bufnr]); + if (winnr == -1) + return; + nvim.pauseNotification(); + nvim.command(`${winnr}wincmd w`, true); + let pos = item.selectRange.start; + nvim.call("coc#cursor#move_to", [pos.line, pos.character], true); + nvim.command(`normal! zz`, true); + let buf2 = nvim.createBuffer(bufnr); + buf2.highlightRanges("outline-hover", "CocHoverRange", [item.selectRange]); + nvim.command("redraw", true); + await nvim.resumeNotification(); + setTimeout(() => { + buf2.clearNamespace("outline-hover"); + nvim.command("redraw", true); + }, global.hasOwnProperty("__TEST__") ? 10 : 300); + }, + resolveActions: async (_, element) => { + let winnr = await nvim.call("bufwinnr", [bufnr]); + if (winnr == -1) + return; + let doc = workspace_default.getDocument(bufnr); + let actions = await this.handler.getCodeActions(doc, element.range, this.config.codeActionKinds); + let arr = actions.map((o) => { + return { + title: o.title, + handler: async () => { + let position = element.range.start; + await nvim.command(`${winnr}wincmd w`); + await this.nvim.call("coc#cursor#move_to", [position.line, position.character]); + await this.handler.applyCodeAction(o); + } + }; + }); + return [...arr, { + title: "Visual Select", + handler: async (item) => { + await nvim.command(`${winnr}wincmd w`); + await workspace_default.selectRange(item.range); + } + }]; + }, + onDispose: () => { + this.providersMap.delete(buf.bufnr); + if (disposable) + disposable.dispose(); + } + }); + return provider; + } + async show(keep) { + await workspace_default.document; + let [bufnr, winid] = await this.nvim.eval('[bufnr("%"),win_getid()]'); + let buf = this.buffers.getItem(bufnr); + if (!buf) + throw new Error("Document not attached"); + let provider = this.providersMap.get(bufnr); + if (!provider) { + provider = this.createProvider(buf); + this.providersMap.set(bufnr, provider); + } + let treeView = new BasicTreeView("OUTLINE", { + enableFilter: true, + treeDataProvider: provider + }); + this.originalWins.set(treeView, winid); + let arr = this.treeViews.get(provider) || []; + arr.push(treeView); + this.treeViews.set(provider, arr); + treeView.onDidChangeVisibility(({ visible }) => { + if (visible || !this.treeViews.has(provider)) + return; + let arr2 = this.treeViews.get(provider) || []; + arr2 = arr2.filter((s) => s !== treeView); + this.originalWins.delete(treeView); + if (arr2.length) { + this.treeViews.set(provider, arr2); + return; + } + provider.dispose(); + this.treeViews.delete(provider); + }); + await treeView.show(this.config.splitCommand); + if (treeView.windowId) { + let win = this.nvim.createWindow(treeView.windowId); + win.setVar("target_bufnr", bufnr, true); + } + if (keep == 1 || keep === void 0 && this.config.keepWindow) { + await this.nvim.command("wincmd p"); + } + } + has(bufnr) { + return this.providersMap.has(bufnr); + } + async hide() { + let winid = await this.nvim.call("coc#window#find", ["cocViewId", "OUTLINE"]); + if (winid == -1) + return; + await this.nvim.call("coc#window#close", [winid]); + } + dispose() { + for (let provider of this.providersMap.values()) { + provider.dispose(); + for (let view of this.treeViews.get(provider)) { + view.dispose(); + } + } + this.providersMap.clear(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/symbols/index.ts +var import_vscode_languageserver_protocol104, Symbols2; +var init_symbols2 = __esm({ + "src/handler/symbols/index.ts"() { + import_vscode_languageserver_protocol104 = __toModule(require_main2()); + init_events(); + init_languages(); + init_util(); + init_object(); + init_position(); + init_window(); + init_workspace(); + init_buffer6(); + init_outline2(); + init_util5(); + Symbols2 = class { + constructor(nvim, handler) { + this.nvim = nvim; + this.handler = handler; + this.disposables = []; + this.buffers = workspace_default.registerBufferSync((doc) => { + if (doc.buftype != "") + return void 0; + return new SymbolsBuffer(doc.bufnr); + }); + this.outline = new SymbolsOutline(nvim, this.buffers, handler); + events_default.on("CursorHold", async (bufnr) => { + if (!this.functionUpdate || !this.buffers.getItem(bufnr)) + return; + await this.getCurrentFunctionSymbol(bufnr); + }, null, this.disposables); + events_default.on("InsertEnter", (bufnr) => { + let buf = this.buffers.getItem(bufnr); + if (buf) + buf.cancel(); + }, null, this.disposables); + } + get functionUpdate() { + let config = workspace_default.getConfiguration("coc.preferences"); + return config.get("currentFunctionSymbolAutoUpdate", false); + } + get labels() { + return workspace_default.getConfiguration("suggest").get("completionItemKindLabels", {}); + } + async getWorkspaceSymbols(input) { + this.handler.checkProvier("workspaceSymbols", null); + let tokenSource = new import_vscode_languageserver_protocol104.CancellationTokenSource(); + return await languages_default.getWorkspaceSymbols(input, tokenSource.token); + } + async resolveWorkspaceSymbol(symbolInfo) { + var _a2; + if ((_a2 = symbolInfo.location) == null ? void 0 : _a2.uri) + return symbolInfo; + let tokenSource = new import_vscode_languageserver_protocol104.CancellationTokenSource(); + return await languages_default.resolveWorkspaceSymbol(symbolInfo, tokenSource.token); + } + async getDocumentSymbols(bufnr) { + let buf = this.buffers.getItem(bufnr); + if (!buf) + return; + let res = await buf.getSymbols(); + return res ? convertSymbols(res) : void 0; + } + async getCurrentFunctionSymbol(bufnr) { + if (!bufnr) + bufnr = await this.nvim.call("bufnr", ["%"]); + let doc = workspace_default.getDocument(bufnr); + if (!doc || !doc.attached) + return; + if (!languages_default.hasProvider("documentSymbol", doc.textDocument)) + return; + let position = await window_default.getCursorPosition(); + let symbols = await this.getDocumentSymbols(bufnr); + let buffer = this.nvim.createBuffer(bufnr); + 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", + "Struct" + ].includes(s.kind)); + let functionName = ""; + for (let sym of symbols.reverse()) { + if (sym.range && 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; + } + } + if (this.functionUpdate) { + buffer.setVar("coc_current_function", functionName, true); + this.nvim.call("coc#util#do_autocmd", ["CocStatusChange"], true); + } + return functionName; + } + async selectSymbolRange(inner, visualmode, supportedSymbols) { + let { doc } = await this.handler.getCurrentState(); + this.handler.checkProvier("documentSymbol", doc.textDocument); + let range; + if (visualmode) { + range = await workspace_default.getSelectedRange(visualmode, doc); + } else { + let pos = await window_default.getCursorPosition(); + range = import_vscode_languageserver_protocol104.Range.create(pos, pos); + } + let symbols = await this.getDocumentSymbols(doc.bufnr); + if (!symbols || symbols.length === 0) { + window_default.showMessage("No symbols found", "warning"); + return; + } + symbols = symbols.filter((s) => supportedSymbols.includes(s.kind)); + let selectRange; + for (let sym of symbols.reverse()) { + if (sym.range && !equals(sym.range, range) && 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 = import_vscode_languageserver_protocol104.Range.create(start.line + 1, line.match(/^\s*/)[0].length, end.line - 1, endLine.length); + } + if (selectRange) { + await workspace_default.selectRange(selectRange); + } else if (["v", "V", ""].includes(visualmode)) { + await this.nvim.command("normal! gv"); + } + } + async showOutline(keep) { + await this.outline.show(keep); + } + async hideOutline() { + await this.outline.hide(); + } + hasOutline(bufnr) { + return this.outline.has(bufnr); + } + dispose() { + this.outline.dispose(); + this.buffers.dispose(); + disposeAll(this.disposables); + } + }; + } +}); + +// src/handler/index.ts +var import_vscode_languageserver_protocol105, logger109, Handler; +var init_handler = __esm({ + "src/handler/index.ts"() { + import_vscode_languageserver_protocol105 = __toModule(require_main2()); + init_events(); + init_languages(); + init_util(); + init_window(); + init_workspace(); + init_codeActions(); + init_codelens(); + init_colors(); + init_commands3(); + init_fold(); + init_format2(); + init_highlights(); + init_hover(); + init_links2(); + init_locations(); + init_refactor(); + init_rename(); + init_selectionRange2(); + init_callHierarchy2(); + init_semanticTokensHighlights(); + init_signature(); + init_symbols2(); + init_convert(); + logger109 = require_logger2()("Handler"); + Handler = class { + constructor(nvim) { + this.nvim = nvim; + this.disposables = []; + this.requestStatusItem = window_default.createStatusBarItem(0, { progress: true }); + events_default.on(["CursorMoved", "CursorMovedI", "InsertEnter", "InsertSnippet", "InsertLeave"], () => { + if (this.requestTokenSource) { + this.requestTokenSource.cancel(); + this.requestTokenSource = null; + } + }, null, this.disposables); + this.labels = workspace_default.getConfiguration("suggest").get("completionItemKindLabels", {}); + this.fold = new FoldHandler(nvim, this); + this.links = new Links(nvim, this); + this.codeLens = new CodeLensManager2(nvim); + this.colors = new Colors(nvim, this); + this.format = new FormatHandler(nvim, this); + this.symbols = new Symbols2(nvim, this); + this.refactor = new Refactor(nvim, this); + this.hover = new HoverHandler(nvim, this); + this.locations = new LocationsHandler(nvim, this); + this.signature = new Signature(nvim, this); + this.rename = new Rename(nvim, this); + this.codeActions = new CodeActions(nvim, this); + this.commands = new Commands(nvim, workspace_default.env); + this.callHierarchy = new CallHierarchyHandler(nvim, this); + this.documentHighlighter = new Highlights(nvim, this); + this.semanticHighlighter = new SemanticTokensHighlights(nvim, this); + this.selectionRange = new SelectionRangeHandler(nvim, this); + this.disposables.push({ + dispose: () => { + this.callHierarchy.dispose(); + this.codeLens.dispose(); + this.refactor.dispose(); + this.signature.dispose(); + this.symbols.dispose(); + this.hover.dispose(); + this.locations.dispose(); + this.colors.dispose(); + this.documentHighlighter.dispose(); + this.semanticHighlighter.dispose(); + } + }); + } + async getCurrentState() { + let { nvim } = this; + let [bufnr, [line, character], winid, mode] = await nvim.eval("[bufnr('%'),coc#cursor#position(),win_getid(),mode()]"); + let doc = workspace_default.getDocument(bufnr); + if (!doc || !doc.attached) + throw new Error(`current buffer ${bufnr} not attached`); + return { + doc, + mode, + position: import_vscode_languageserver_protocol105.Position.create(line, character), + winid + }; + } + addDisposable(disposable) { + this.disposables.push(disposable); + } + checkProvier(id, document2) { + if (!languages_default.hasProvider(id, document2)) { + throw new Error(`${id} provider not found for current buffer, your language server doesn't support it.`); + } + } + async withRequestToken(name2, fn, checkEmpty) { + if (this.requestTokenSource) { + this.requestTokenSource.cancel(); + this.requestTokenSource.dispose(); + } + if (this.requestTimer) { + clearTimeout(this.requestTimer); + } + let statusItem = this.requestStatusItem; + this.requestTokenSource = new import_vscode_languageserver_protocol105.CancellationTokenSource(); + let { token } = this.requestTokenSource; + token.onCancellationRequested(() => { + statusItem.text = `${name2} request canceled`; + statusItem.isProgress = false; + this.requestTimer = setTimeout(() => { + statusItem.hide(); + }, 500); + }); + statusItem.isProgress = true; + statusItem.text = `requesting ${name2}`; + statusItem.show(); + let res; + try { + res = await Promise.resolve(fn(token)); + } catch (e) { + window_default.showMessage(e.message, "error"); + logger109.error(`Error on ${name2}`, e); + } + if (this.requestTokenSource) { + this.requestTokenSource.dispose(); + this.requestTokenSource = void 0; + } + if (token.isCancellationRequested) + return null; + statusItem.hide(); + if (checkEmpty && (!res || Array.isArray(res) && res.length == 0)) { + window_default.showMessage(`${name2} not found`, "warning"); + return null; + } + return res; + } + getIcon(kind) { + let { labels } = this; + let kindText = getSymbolKind(kind); + let defaultIcon = typeof labels["default"] === "string" ? labels["default"] : kindText[0].toLowerCase(); + let text = kindText == "Unknown" ? "" : labels[kindText[0].toLowerCase() + kindText.slice(1)]; + if (!text || typeof text !== "string") + text = defaultIcon; + return { + text, + hlGroup: kindText == "Unknown" ? "CocSymbolDefault" : `CocSymbol${kindText}` + }; + } + async getCodeActions(doc, range, only) { + return await this.codeActions.getCodeActions(doc, range, only); + } + async applyCodeAction(action) { + await this.codeActions.applyCodeAction(action); + } + async hasProvider(id) { + let bufnr = await this.nvim.call("bufnr", "%"); + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return false; + return languages_default.hasProvider(id, doc.textDocument); + } + dispose() { + if (this.requestTimer) { + clearTimeout(this.requestTimer); + } + disposeAll(this.disposables); + } + }; + } +}); + +// src/plugin.ts +var import_events43, import_fs37, import_path37, import_vscode_languageserver_protocol106, logger110, Plugin; +var init_plugin = __esm({ + "src/plugin.ts"() { + import_events43 = __toModule(require("events")); + import_fs37 = __toModule(require("fs")); + import_path37 = __toModule(require("path")); + import_vscode_languageserver_protocol106 = __toModule(require_main2()); + init_esm2(); + init_commands2(); + init_completion(); + init_cursors(); + init_manager(); + init_events(); + init_extensions2(); + init_handler(); + init_manager3(); + init_services(); + init_manager4(); + init_sources2(); + init_types(); + init_window(); + init_workspace(); + logger110 = require_logger2()("plugin"); + Plugin = class extends import_events43.EventEmitter { + constructor(nvim) { + super(); + this.nvim = nvim; + this._ready = false; + this.actions = new Map(); + Object.defineProperty(workspace_default, "nvim", { + get: () => this.nvim + }); + workspace_default.onDidChangeWorkspaceFolders(() => { + nvim.setVar("WorkspaceFolders", workspace_default.folderPaths, true); + }); + this.cursors = new Cursors(nvim); + commands_default.init(nvim, this); + this.addAction("checkJsonExtension", () => { + if (extensions_default.has("coc-json")) + return; + window_default.showMessage(`Run :CocInstall coc-json for json intellisense`, "more"); + }); + this.addAction("rootPatterns", (bufnr) => { + let doc = workspace_default.getDocument(bufnr); + if (!doc) + return null; + return { + buffer: workspace_default.getRootPatterns(doc, PatternType.Buffer), + server: workspace_default.getRootPatterns(doc, PatternType.LanguageServer), + global: workspace_default.getRootPatterns(doc, PatternType.Global) + }; + }); + this.addAction("getConfig", async (key) => { + let document2 = await workspace_default.document; + return workspace_default.getConfiguration(key, document2 ? document2.uri : void 0); + }); + this.addAction("doAutocmd", async (id, ...args) => { + let autocmd = workspace_default.autocmds.get(id); + if (autocmd) { + try { + await Promise.resolve(autocmd.callback.apply(autocmd.thisArg, args)); + } catch (e) { + logger110.error(`Error on autocmd ${autocmd.event}`, e); + window_default.showMessage(`Error on autocmd ${autocmd.event}: ${e.message}`); + } + } + }); + this.addAction("openLog", async () => { + let file = logger110.getLogFile(); + await workspace_default.jumpTo(URI.file(file).toString()); + }); + this.addAction("attach", () => workspace_default.attach()); + this.addAction("detach", () => workspace_default.detach()); + this.addAction("doKeymap", async (key, defaultReturn = "", pressed) => { + let keymap = workspace_default.keymaps.get(key); + if (!keymap) { + logger110.error(`keymap for ${key} not found`); + this.nvim.command(`silent! unmap ${pressed.startsWith("{") && pressed.endsWith("}") ? `<${pressed.slice(1, -1)}>` : pressed}`, true); + return defaultReturn; + } + let [fn, repeat2] = keymap; + let res = await Promise.resolve(fn()); + if (repeat2) + await nvim.command(`silent! call repeat#set("\\(coc-${key})", -1)`); + return res != null ? res : defaultReturn; + }); + this.addAction("registExtensions", async (...folders) => { + for (let folder of folders) { + await extensions_default.loadExtension(folder); + } + }); + this.addAction("snippetCheck", async (checkExpand, checkJump) => { + if (checkExpand && !extensions_default.has("coc-snippets")) { + console.error("coc-snippets required for check expand status!"); + return false; + } + if (checkJump) { + let jumpable = manager_default3.jumpable(); + if (jumpable) + return true; + } + if (checkExpand) { + let api = extensions_default.getExtensionApi("coc-snippets"); + if (api && api.hasOwnProperty("expandable")) { + let expandable = await Promise.resolve(api.expandable()); + if (expandable) + return true; + } + } + return false; + }); + this.addAction("snippetNext", () => manager_default3.nextPlaceholder()); + this.addAction("snippetPrev", () => manager_default3.previousPlaceholder()); + this.addAction("snippetCancel", () => manager_default3.cancel()); + this.addAction("openLocalConfig", () => window_default.openLocalConfig()); + this.addAction("showInfo", async () => { + if (!this.infoChannel) { + this.infoChannel = window_default.createOutputChannel("info"); + } else { + this.infoChannel.clear(); + } + let channel = this.infoChannel; + channel.appendLine("## versions"); + channel.appendLine(""); + let out = await this.nvim.call("execute", ["version"]); + let first = out.trim().split(/\r?\n/, 2)[0].replace(/\(.*\)/, "").trim(); + channel.appendLine("vim version: " + first + `${workspace_default.isVim ? " " + workspace_default.env.version : ""}`); + channel.appendLine("node version: " + process.version); + channel.appendLine("coc.nvim version: " + this.version); + channel.appendLine("coc.nvim directory: " + import_path37.default.dirname(__dirname)); + channel.appendLine("term: " + (process.env.TERM_PROGRAM || process.env.TERM)); + channel.appendLine("platform: " + process.platform); + channel.appendLine(""); + channel.appendLine("## Log of coc.nvim"); + channel.appendLine(""); + let file = logger110.getLogFile(); + if (import_fs37.default.existsSync(file)) { + let content = import_fs37.default.readFileSync(file, { encoding: "utf8" }); + channel.appendLine(content); + } + channel.show(); + }); + this.addAction("findLocations", (id, method, params, openCommand) => { + return this.handler.locations.findLocations(id, method, params, openCommand); + }); + this.addAction("hasProvider", (id) => this.handler.hasProvider(id)); + this.addAction("getTagList", () => this.handler.locations.getTagList()); + this.addAction("hasSelected", () => completion_default.hasSelected()); + this.addAction("listNames", () => manager_default2.names); + this.addAction("listDescriptions", () => manager_default2.descriptions); + this.addAction("listLoadItems", (name2) => manager_default2.loadItems(name2)); + this.addAction("search", (...args) => this.handler.refactor.search(args)); + this.addAction("cursorsSelect", (bufnr, kind, mode) => this.cursors.select(bufnr, kind, mode)); + this.addAction("fillDiagnostics", (bufnr) => manager_default.setLocationlist(bufnr)); + this.addAction("saveRefactor", (bufnr) => this.handler.refactor.save(bufnr)); + this.addAction("commandList", () => this.handler.commands.getCommandList()); + this.addAction("selectSymbolRange", (inner, visualmode, supportedSymbols) => this.handler.symbols.selectSymbolRange(inner, visualmode, supportedSymbols)); + this.addAction("openList", (...args) => manager_default2.start(args)); + this.addAction("listResume", (name2) => manager_default2.resume(name2)); + this.addAction("listCancel", () => manager_default2.cancel(true)); + this.addAction("listPrev", (name2) => manager_default2.previous(name2)); + this.addAction("listNext", (name2) => manager_default2.next(name2)); + this.addAction("listFirst", (name2) => manager_default2.first(name2)); + this.addAction("listLast", (name2) => manager_default2.last(name2)); + this.addAction("sendRequest", (id, method, params) => services_default.sendRequest(id, method, params)); + this.addAction("sendNotification", (id, method, params) => services_default.sendNotification(id, method, params)); + this.addAction("registNotification", (id, method) => services_default.registNotification(id, method)); + this.addAction("updateConfig", (section2, val) => workspace_default.configurations.updateUserConfig({ [section2]: val })); + this.addAction("links", () => this.handler.links.getLinks()); + this.addAction("openLink", () => this.handler.links.openCurrentLink()); + this.addAction("pickColor", () => this.handler.colors.pickColor()); + this.addAction("colorPresentation", () => this.handler.colors.pickPresentation()); + this.addAction("highlight", () => this.handler.documentHighlighter.highlight()); + this.addAction("fold", (kind) => this.handler.fold.fold(kind)); + this.addAction("startCompletion", (option) => completion_default.startCompletion(option)); + this.addAction("stopCompletion", () => completion_default.stop(false)); + this.addAction("sourceStat", () => sources_default.sourceStats()); + this.addAction("refreshSource", (name2) => sources_default.refresh(name2)); + this.addAction("toggleSource", (name2) => sources_default.toggleSource(name2)); + this.addAction("diagnosticRefresh", (bufnr) => manager_default.refresh(bufnr)); + this.addAction("diagnosticInfo", () => manager_default.echoMessage()); + this.addAction("diagnosticToggle", () => manager_default.toggleDiagnostic()); + this.addAction("diagnosticToggleBuffer", async (bufnr) => { + if (!bufnr) + bufnr = await nvim.call("bufnr", ["%"]); + return manager_default.toggleDiagnosticBuffer(bufnr); + }); + this.addAction("diagnosticNext", (severity) => manager_default.jumpNext(severity)); + this.addAction("diagnosticPrevious", (severity) => manager_default.jumpPrevious(severity)); + this.addAction("diagnosticPreview", () => manager_default.preview()); + this.addAction("diagnosticList", () => manager_default.getDiagnosticList()); + this.addAction("jumpDefinition", (openCommand) => this.handler.locations.gotoDefinition(openCommand)); + this.addAction("definitions", () => this.handler.locations.definitions()); + this.addAction("jumpDeclaration", (openCommand) => this.handler.locations.gotoDeclaration(openCommand)); + this.addAction("declarations", () => this.handler.locations.declarations()); + this.addAction("jumpImplementation", (openCommand) => this.handler.locations.gotoImplementation(openCommand)); + this.addAction("implementations", () => this.handler.locations.implementations()); + this.addAction("jumpTypeDefinition", (openCommand) => this.handler.locations.gotoTypeDefinition(openCommand)); + this.addAction("typeDefinitions", () => this.handler.locations.typeDefinitions()); + this.addAction("jumpReferences", (openCommand) => this.handler.locations.gotoReferences(openCommand)); + this.addAction("references", () => this.handler.locations.references()); + this.addAction("jumpUsed", (openCommand) => this.handler.locations.gotoReferences(openCommand, false)); + this.addAction("doHover", (hoverTarget) => this.handler.hover.onHover(hoverTarget)); + this.addAction("definitionHover", (hoverTarget) => this.handler.hover.definitionHover(hoverTarget)); + this.addAction("getHover", () => this.handler.hover.getHover()); + this.addAction("showSignatureHelp", () => this.handler.signature.triggerSignatureHelp()); + this.addAction("documentSymbols", async (bufnr) => { + if (!bufnr) { + let doc = await workspace_default.document; + bufnr = doc.bufnr; + } + return await this.handler.symbols.getDocumentSymbols(bufnr); + }); + this.addAction("ensureDocument", async () => { + let doc = await workspace_default.document; + return doc && doc.attached; + }); + this.addAction("symbolRanges", () => this.handler.documentHighlighter.getSymbolsRanges()); + this.addAction("selectionRanges", () => this.handler.selectionRange.getSelectionRanges()); + this.addAction("rangeSelect", (visualmode, forward) => this.handler.selectionRange.selectRange(visualmode, forward)); + this.addAction("rename", (newName) => this.handler.rename.rename(newName)); + this.addAction("getWorkspaceSymbols", (input) => this.handler.symbols.getWorkspaceSymbols(input)); + this.addAction("resolveWorkspaceSymbol", (symbolInfo) => this.handler.symbols.resolveWorkspaceSymbol(symbolInfo)); + this.addAction("formatSelected", (mode) => this.handler.format.formatCurrentRange(mode)); + this.addAction("format", () => this.handler.format.formatCurrentBuffer()); + this.addAction("commands", () => this.handler.commands.getCommands()); + this.addAction("services", () => services_default.getServiceStats()); + this.addAction("toggleService", (name2) => services_default.toggle(name2)); + this.addAction("codeAction", (mode, only) => this.handler.codeActions.doCodeAction(mode, only)); + this.addAction("organizeImport", () => this.handler.codeActions.organizeImport()); + this.addAction("fixAll", () => this.handler.codeActions.doCodeAction(null, [import_vscode_languageserver_protocol106.CodeActionKind.SourceFixAll])); + let codeActions = []; + this.addAction("doCodeAction", (codeAction) => { + if (codeAction.index == null) { + throw new Error(`index should exists with codeAction`); + } + let action = codeActions[codeAction.index]; + if (!action) + throw new Error(`invalid codeAction index: ${codeAction.index}`); + return this.handler.codeActions.applyCodeAction(action); + }); + this.addAction("codeActions", async (mode, only) => { + codeActions = await this.handler.codeActions.getCurrentCodeActions(mode, only); + return codeActions.map((o, idx) => Object.assign({ index: idx }, o)); + }); + this.addAction("quickfixes", async (mode) => { + codeActions = await this.handler.codeActions.getCurrentCodeActions(mode, [import_vscode_languageserver_protocol106.CodeActionKind.QuickFix]); + return codeActions.map((o, idx) => Object.assign({ index: idx }, o)); + }); + this.addAction("codeLensAction", () => this.handler.codeLens.doAction()); + this.addAction("runCommand", (...args) => this.handler.commands.runCommand(...args)); + this.addAction("doQuickfix", () => this.handler.codeActions.doQuickfix()); + this.addAction("refactor", () => this.handler.refactor.doRefactor()); + this.addAction("repeatCommand", () => this.handler.commands.repeat()); + this.addAction("installExtensions", (...list2) => extensions_default.installExtensions(list2)); + this.addAction("updateExtensions", (sync) => extensions_default.updateExtensions(sync)); + this.addAction("extensionStats", () => extensions_default.getExtensionStates()); + this.addAction("loadedExtensions", () => extensions_default.loadedExtensions()); + this.addAction("watchExtension", (id) => extensions_default.watchExtension(id)); + this.addAction("activeExtension", (name2) => extensions_default.activate(name2)); + this.addAction("deactivateExtension", (name2) => extensions_default.deactivate(name2)); + this.addAction("reloadExtension", (name2) => extensions_default.reloadExtension(name2)); + this.addAction("toggleExtension", (name2) => extensions_default.toggleExtension(name2)); + this.addAction("uninstallExtension", (...args) => extensions_default.uninstallExtension(args)); + this.addAction("getCurrentFunctionSymbol", () => this.handler.symbols.getCurrentFunctionSymbol()); + this.addAction("showOutline", (keep) => this.handler.symbols.showOutline(keep)); + this.addAction("hideOutline", () => this.handler.symbols.hideOutline()); + this.addAction("getWordEdit", () => this.handler.rename.getWordEdit()); + this.addAction("addCommand", (cmd) => this.handler.commands.addVimCommand(cmd)); + this.addAction("addRanges", (ranges) => this.cursors.addRanges(ranges)); + this.addAction("currentWorkspacePath", () => workspace_default.rootPath); + this.addAction("selectCurrentPlaceholder", (triggerAutocmd) => manager_default3.selectCurrentPlaceholder(!!triggerAutocmd)); + this.addAction("codeActionRange", (start, end, only) => this.handler.codeActions.codeActionRange(start, end, only)); + this.addAction("incomingCalls", (item) => this.handler.callHierarchy.getIncoming(item)); + this.addAction("outgoingCalls", (item) => this.handler.callHierarchy.getOutgoing(item)); + this.addAction("showIncomingCalls", () => this.handler.callHierarchy.showCallHierarchyTree("incoming")); + this.addAction("showOutgoingCalls", () => this.handler.callHierarchy.showCallHierarchyTree("outgoing")); + this.addAction("semanticHighlight", () => this.handler.semanticHighlighter.highlightCurrent()); + this.addAction("showSemanticHighlightInfo", () => this.handler.semanticHighlighter.showHiglightInfo()); + } + addAction(key, fn) { + if (this.actions.has(key)) { + throw new Error(`Action ${key} already exists`); + } + this.actions.set(key, fn); + } + async init() { + let { nvim } = this; + let s = Date.now(); + try { + await extensions_default.init(); + await workspace_default.init(); + manager_default3.init(); + completion_default.init(); + manager_default.init(); + manager_default2.init(nvim); + sources_default.init(); + this.handler = new Handler(nvim); + services_default.init(); + extensions_default.activateExtensions(); + workspace_default.setupDynamicAutocmd(true); + nvim.pauseNotification(); + nvim.setVar("WorkspaceFolders", workspace_default.folderPaths, true); + nvim.setVar("coc_service_initialized", 1, true); + nvim.call("coc#util#do_autocmd", ["CocNvimInit"], true); + nvim.resumeNotification(false, true); + this._ready = true; + await events_default.fire("ready", []); + logger110.info(`coc.nvim ${this.version} initialized with node: ${process.version} after ${Date.now() - s}ms`); + this.emit("ready"); + } catch (e) { + nvim.echoError(e); + } + } + get isReady() { + return this._ready; + } + get ready() { + if (this._ready) + return Promise.resolve(); + return new Promise((resolve3) => { + this.once("ready", () => { + resolve3(); + }); + }); + } + get version() { + return workspace_default.version + (true ? "-f021999eb2" : ""); + } + hasAction(method) { + return this.actions.has(method); + } + async cocAction(method, ...args) { + let fn = this.actions.get(method); + if (!fn) + throw new Error(`Action "${method}" not exists`); + let ts = Date.now(); + let res = await Promise.resolve(fn.apply(null, args)); + let dt = Date.now() - ts; + if (dt > 500) + logger110.warn(`Slow action "${method}" cost ${dt}ms`); + return res; + } + getHandler() { + return this.handler; + } + dispose() { + this.removeAllListeners(); + extensions_default.dispose(); + manager_default2.dispose(); + workspace_default.dispose(); + window_default.dispose(); + sources_default.dispose(); + services_default.stopAll(); + services_default.dispose(); + if (this.handler) { + this.handler.dispose(); + } + manager_default3.dispose(); + commands_default.dispose(); + completion_default.dispose(); + manager_default.dispose(); + } + }; + } +}); + +// src/attach.ts +var attach_exports = {}; +__export(attach_exports, { + default: () => attach_default +}); +var import_neovim2, import_log4js, import_semver3, logger111, isTest, ACTIONS_NO_WAIT, attach_default; +var init_attach = __esm({ + "src/attach.ts"() { + import_neovim2 = __toModule(require_lib6()); + import_log4js = __toModule(require_log4js()); + init_events(); + init_plugin(); + import_semver3 = __toModule(require_semver2()); + init_is(); + init_esm2(); + init_package(); + logger111 = require_logger2()("attach"); + isTest = global.hasOwnProperty("__TEST__"); + ACTIONS_NO_WAIT = ["installExtensions", "updateExtensions"]; + attach_default = (opts, requestApi = true) => { + const nvim = (0, import_neovim2.attach)(opts, import_log4js.default.getLogger("node-client"), requestApi); + if (!global.hasOwnProperty("__TEST__")) { + nvim.call("coc#util#path_replace_patterns").then((prefixes) => { + if (objectLiteral(prefixes)) { + const old_uri = URI.file; + URI.file = (path36) => { + path36 = path36.replace(/\\/g, "/"); + Object.keys(prefixes).forEach((k) => path36 = path36.replace(new RegExp("^" + k), prefixes[k])); + return old_uri(path36); + }; + } + }).logError(); + } + nvim.setVar("coc_process_pid", process.pid, true); + const plugin = new Plugin(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 "Log": { + logger111.debug(...args); + break; + } + case "TaskExit": + case "TaskStderr": + case "TaskStdout": + case "GlobalChange": + case "PromptInsert": + case "InputChar": + case "MenuInput": + case "OptionSet": + case "FloatBtnClick": + await events_default.fire(method, args); + break; + case "CocAutocmd": + logger111.trace("Notification autocmd:", ...args); + await events_default.fire(args[0], args.slice(1)); + break; + default: { + let exists = plugin.hasAction(method); + if (!exists) { + if (global.hasOwnProperty("__TEST__")) + return; + console.error(`action "${method}" not exists`); + return; + } + try { + if (!plugin.isReady) { + logger111.warn(`Plugin not ready when received "${method}"`, args); + } else { + logger111.info("receive notification:", method, args); + } + await plugin.ready; + await plugin.cocAction(method, ...args); + } catch (e) { + console.error(`Error on "${method}": ${e.message || e.toString()}`); + logger111.error(`Notification error:`, method, args, e); + } + } + } + }); + nvim.on("request", async (method, args, resp) => { + if (method == "redraw") { + resp.send(); + return; + } + let timer = setTimeout(() => { + logger111.error("Request cost more than 3s", method, args); + }, 3e3); + try { + if (method == "CocAutocmd") { + logger111.trace("Request autocmd:", ...args); + await events_default.fire(args[0], args.slice(1)); + resp.send(void 0); + } else { + if (!plugin.isReady && !ACTIONS_NO_WAIT.includes(method)) { + logger111.warn(`Plugin not ready on request "${method}"`, args); + resp.send("Plugin not ready", true); + return; + } + logger111.info("Request action:", method, args); + let res = await plugin.cocAction(method, ...args); + resp.send(res); + } + clearTimeout(timer); + } catch (e) { + clearTimeout(timer); + resp.send(e.message || e.toString(), true); + logger111.error(`Request error:`, method, args, e); + } + }); + nvim.channelId.then(async (channelId) => { + clientReady = true; + if (isTest) + nvim.command(`let g:coc_node_channel_id = ${channelId}`, true); + let { major, minor, patch } = import_semver3.default.parse(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}`); + }); + return plugin; + }; + } +}); + +// src/main.ts +require_extensions(); +Object.defineProperty(console, "log", { + value() { + logger112.info(...arguments); + } +}); +var logger112 = require_logger2()("server"); +var attach2 = (init_attach(), attach_exports).default; +attach2({ reader: process.stdin, writer: process.stdout }); +process.on("uncaughtException", function(err) { + let msg = "Uncaught exception: " + err.message; + console.error(msg); + logger112.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); + } + logger112.error("unhandledRejection ", p, reason); +}); /*! * @description Recursive object extending * @author Viacheslav Lotsmanov @@ -300,6 +68543,7 @@ ${s.message} * Copyright(c) 2014-2017 Douglas Christopher Wilson * MIT Licensed */ +/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ /** * event-lite.js - Light-weight EventEmitter (less than 1KB when gzipped) * diff --git a/vim-config/plugins/coc.nvim/data/schema.json b/vim-config/plugins/coc.nvim/data/schema.json index 7723c00c..a4ad1bd6 100644 --- a/vim-config/plugins/coc.nvim/data/schema.json +++ b/vim-config/plugins/coc.nvim/data/schema.json @@ -3,6 +3,62 @@ "description": "Configuration file for coc.nvim", "additionalProperties": false, "definitions": { + "float": { + "type": "object", + "properties": { + "border": { + "type": "boolean", + "default": false, + "description": "Set to true to use borders." + }, + "highlight": { + "type": "string", + "default": "CocFloating", + "description": "Background highlight group of float window." + }, + "title": { + "type": "string", + "default": "", + "description": "Title used by float window." + }, + "borderhighlight": { + "type": "string", + "default": "CocFloating", + "description": "Border highlight group of float window." + }, + "close": { + "type": "boolean", + "default": false, + "description": "Set to true to draw close icon" + }, + "maxWidth": { + "type": "integer", + "description": "Maximum width of float window, include border." + }, + "maxHeight": { + "type": "integer", + "minimum": 2, + "description": "Maximum height of float window, include border." + }, + "focusable": { + "type": "boolean", + "default": true, + "description": "Enable focus by user actions (wincmds, mouse events), neovim only." + }, + "shadow": { + "type": "boolean", + "default": false, + "description": "Drop shadow effect by blending with the background, neovim only." + }, + "winblend": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 100, + "description": "Enables pseudo-transparency by set 'winblend' option of window, neovim only." + } + } + }, "languageServerBase": { "type": "object", "properties": { @@ -304,11 +360,6 @@ "description": "Enable preselect feature of LSP, only works on neovim", "default": false }, - "suggest.maxPreviewWidth": { - "type": "number", - "default": 80, - "description": "Maximum width of floating preview window." - }, "suggest.enablePreview": { "type": "boolean", "description": "Add preview option to completeopt, default: false.", @@ -319,6 +370,21 @@ "description": "Enable floating window for documentation when possible.", "default": true }, + "suggest.floatConfig": { + "type": "object", + "description": "Configure style of documentation window for complete item.", + "allOf": [{ "$ref": "#/definitions/float" }], + "additionalProperties": false, + "properties": { + "border": {}, + "highlight": {}, + "borderhighlight": {}, + "maxWidth": {}, + "winblend": {}, + "focusable": {}, + "shadow": {} + } + }, "suggest.labelMaxLength": { "type": "number", "description": "Max length of abbr that shown as label of complete item.", @@ -404,7 +470,7 @@ "description": "Timeout for completion, in miliseconds." }, "suggest.minTriggerInputLength": { - "type": "number", + "type": "integer", "default": 1, "description": "Mininal input length for trigger completion, default 1" }, @@ -432,7 +498,7 @@ }, "suggest.keepCompleteopt": { "type": "boolean", - "description": "When enabled, completeopt is not overriden, auto completion will be disabled if completeopt doesn't have noinsert and noselect.", + "description": "When enabled, completeopt is not overridden, auto completion will be disabled if completeopt doesn't have noinsert and noselect.", "default": false }, "suggest.lowPrioritySourceLimit": { @@ -458,6 +524,11 @@ "default": "length", "enum": ["length", "alphabetical", "none"] }, + "suggest.snippetsSupport": { + "type": "boolean", + "description": "Set to false to disable snippets support of completion.", + "default": true + }, "suggest.completionItemKindLabels": { "type": "object", "default": {}, @@ -510,6 +581,16 @@ "description": "Set to false to disable diagnostic display", "default": true }, + "diagnostic.highlighLimit": { + "type": "number", + "description": "Limit count for highlighted diagnostics, too many diagnostic highlights could make vim stop responsing", + "default": 1000 + }, + "diagnostic.autoRefresh": { + "type": "boolean", + "description": "Enable automatically refresh diagnostics, use diagnosticRefresh action when it's disabled.", + "default": true + }, "diagnostic.level": { "type": "string", "description": "Used for filter diagnostics by diagnostic severity.", @@ -618,15 +699,23 @@ "description": "Text of hint sign", "default": ">>" }, - "diagnostic.maxWindowHeight": { - "type": "number", - "description": "Maximum height of diagnostics floating window.", - "default": 8 - }, - "diagnostic.maxWindowWidth": { - "type": "number", - "description": "Maximum width of diagnostics floating window.", - "default": 80 + "diagnostic.floatConfig": { + "type": "object", + "description": "Configure float window style of diagnostic message.", + "allOf": [{ "$ref": "#/definitions/float" }], + "additionalProperties": false, + "properties": { + "border": {}, + "highlight": {}, + "borderhighlight": {}, + "title": {}, + "close": {}, + "maxHeight": {}, + "maxWidth": {}, + "winblend": {}, + "focusable": {}, + "shadow": {} + } }, "diagnostic.filetypeMap": { "type": "object", @@ -641,17 +730,17 @@ "diagnostic.separateRelatedInformationAsDiagnostics": { "type": "boolean", "default": false, - "description": "Separate related information as diagnostics" + "description": "Separate related information as diagnostics." }, "diagnostic.showUnused": { "type": "boolean", "default": true, - "description": "Show unused variables" + "description": "Show diagnostics with unused tag." }, "diagnostic.showDeprecated": { "type": "boolean", "default": true, - "description": "Show deprecated variables" + "description": "Show diagnostics with deprecated tag." }, "signature.enable": { "type": "boolean", @@ -671,16 +760,23 @@ "default": "float", "enum": ["float", "echo"] }, - "signature.maxWindowWidth": { - "type": "integer", - "default": 80, - "description": "Maximum width of signature float window (or popup on vim8)." - }, - "signature.maxWindowHeight": { - "type": "number", - "description": "Maximum height of signature float window (or popup on vim8).", - "minimum": 3, - "default": 8 + "signature.floatConfig": { + "type": "object", + "description": "Configure float window style of signature documents.", + "allOf": [{ "$ref": "#/definitions/float" }], + "additionalProperties": false, + "properties": { + "border": {}, + "highlight": {}, + "borderhighlight": {}, + "title": {}, + "close": {}, + "maxHeight": {}, + "maxWidth": {}, + "winblend": {}, + "focusable": {}, + "shadow": {} + } }, "signature.preferShownAbove": { "type": "boolean", @@ -732,14 +828,28 @@ "description": "Target to show hover information, default is floating window when possible.", "enum": ["preview", "echo", "float"] }, - "hover.floatMaxWidth": { + "hover.previewMaxHeight": { "type": "number", - "default": 80, - "description": "Maximum width of hover float window, not bigger than 80." + "default": 12, + "description": "Max height of preview window for hover." }, - "hover.floatMaxHeight": { - "type": "number", - "description": "Maximum width of hover float window, not bigger than 80." + "hover.floatConfig": { + "type": "object", + "description": "Configure float window style of hover documents.", + "allOf": [{ "$ref": "#/definitions/float" }], + "additionalProperties": false, + "properties": { + "border": {}, + "highlight": {}, + "borderhighlight": {}, + "title": {}, + "close": {}, + "maxHeight": {}, + "maxWidth": {}, + "winblend": {}, + "focusable": {}, + "shadow": {} + } }, "hover.autoHide": { "type": "boolean", @@ -907,6 +1017,17 @@ "default": "Search", "description": "Highlight group used for highlight the range in preview window." }, + "list.previewToplineStyle": { + "type": "string", + "default": "offset", + "description": "Topline style for list previews", + "enum": ["offset", "middle"] + }, + "list.previewToplineOffset": { + "type": "number", + "default": 3, + "description": "Topline offset for list previews" + }, "list.nextKeymap": { "type": "string", "default": "", @@ -969,6 +1090,121 @@ "default": "", "description": "Key used for jump to previous cursors position." }, + "tree.closedIcon": { + "type": "string", + "default": "+", + "description": "Closed icon of tree view." + }, + "tree.openedIcon": { + "type": "string", + "default": "-", + "description": "Opend icon of tree view." + }, + "tree.key.toggleSelection": { + "type": "string", + "default": "", + "description": "Trigger key to select/unselect item" + }, + "tree.key.toggle": { + "type": "string", + "default": "t", + "description": "Trigger key to toggle expand state of tree node, does nothing with leaf node." + }, + "tree.key.actions": { + "type": "string", + "default": "", + "description": "Trigger key to invoke actions." + }, + "tree.key.collapseAll": { + "type": "string", + "default": "M", + "description": "Trigger key to collapse all tree node." + }, + "tree.key.invoke": { + "type": "string", + "default": "", + "description": "Trigger key to invoke default command of current node or selection." + }, + "tree.key.close": { + "type": "string", + "default": "", + "description": "Trigger key to dispose the tree and close tree window." + }, + "tree.key.activeFilter": { + "type": "string", + "default": "f", + "description": "Trigger key active filter." + }, + "tree.key.selectNext": { + "type": "string", + "default": "", + "description": "Trigger key to select next item during filter." + }, + "tree.key.selectPrevious": { + "type": "string", + "default": "", + "description": "Trigger key to select previous item during filter." + }, + "outline.showLineNumber": { + "type": "boolean", + "default": true, + "description": "Show line number of symbols." + }, + "outline.splitCommand": { + "type": "string", + "default": "botright 30vs", + "description": "Window split command used by outline." + }, + "outline.followCursor": { + "type": "boolean", + "default": true, + "description": "Reveal item in outline tree on cursor hold." + }, + "outline.keepWindow": { + "type": "boolean", + "default": false, + "description": "Jump back to original window after outline is shown." + }, + "outline.sortBy": { + "type": "string", + "default": "category", + "description": "Sort method for symbols.", + "enum": ["position", "name", "category"] + }, + "outline.expandLevel": { + "type": "number", + "default": 1, + "description": "Expand level of tree nodes." + }, + "outline.checkBufferSwitch": { + "type": "boolean", + "default": true, + "description": "Recreate outline view after user changed to another buffer on current tab." + }, + "outline.codeActionKinds": { + "type": "array", + "default": ["", "quickfix", "refactor"], + "description": "Filter code actions in actions menu by kinds.", + "items": { + "type": "string", + "enum": ["", "quickfix", "refactor", "source"] + } + }, + "callHierarchy.openCommand": { + "type": "string", + "default": "edit", + "description": "Open command for callHierarchy tree view." + }, + "callHierarchy.splitCommand": { + "type": "string", + "default": "botright 30vs", + "description": "Window split command used by callHierarchy tree view." + }, + "callHierarchy.enableTooltip": { + "type": "boolean", + "default": true, + "description": "Enable tooltip to show relative filepath of call hierarchy." + }, "coc.preferences.enableMessageDialog": { "type": "boolean", "default": false, @@ -1011,16 +1247,11 @@ "description": "Enable color highlight if language server support it.", "default": true }, - "coc.preferences.previewAutoClose": { + "coc.preferences.semanticTokensHighlights": { "type": "boolean", - "description": "Auto close preview window on cursor move.", + "description": "Enable semanticTokens highlight if language server support it.", "default": true }, - "coc.preferences.previewMaxHeight": { - "type": "number", - "default": 12, - "description": "Max height of preview window for hover." - }, "coc.preferences.currentFunctionSymbolAutoUpdate": { "type": "boolean", "description": "Automatically update the value of b:coc_current_function on CursorHold event", @@ -1053,9 +1284,22 @@ "default": null }, "coc.preferences.jumpCommand": { - "type": "string", - "description": "Command used for location jump, like goto definition, goto references etc.", - "enum": ["edit", "split", "vsplit", "tabe", "drop", "tab drop", "pedit"], + "anyOf": [ + { + "type": "string", + "enum": [ + "edit", + "split", + "vsplit", + "tabe", + "drop", + "tab drop", + "pedit" + ] + }, + { "type": "string", "minimum": 1 } + ], + "description": "Command used for location jump, like goto definition, goto references etc. Can be also a custom command that gives file as an argument.", "default": "edit" }, "coc.preferences.messageLevel": { @@ -1071,7 +1315,7 @@ }, "coc.preferences.formatOnType": { "type": "boolean", - "description": "Set to true to enable format on type", + "description": "Set to true to enable formatting on typing", "default": false }, "coc.preferences.formatOnTypeFiletypes": { @@ -1082,18 +1326,6 @@ "type": "string" } }, - "coc.preferences.highlightTimeout": { - "type": "integer", - "default": 500, - "minimum": 200, - "maximum": 5000, - "description": "Highlight timeout for buffer in floating window." - }, - "coc.preferences.snippets.enable": { - "type": "boolean", - "description": "Set to false to disable snippets support.", - "default": true - }, "coc.preferences.floatActions": { "type": "boolean", "description": "Set to false to disable float/popup support for actions menu, won't work on vim without float or popup window support.", @@ -1109,6 +1341,11 @@ "description": "Tell the language server that markdown text format is supported, note that markdown text may not rendered as expected.", "default": true }, + "coc.preferences.excludeImageLinksInMarkdownDocument": { + "type": "boolean", + "description": "Exclude image links from markdown text in float window.", + "default": true + }, "coc.preferences.silentAutoupdate": { "type": "boolean", "description": "Not open split window with update status when performing auto update.", @@ -1195,7 +1432,7 @@ }, "coc.source.file.triggerCharacters": { "type": "array", - "default": ["/"], + "default": ["/", "\\"], "items": { "type": "string" } diff --git a/vim-config/plugins/coc.nvim/doc/coc.txt b/vim-config/plugins/coc.nvim/doc/coc.txt index bb71e282..004dab15 100644 --- a/vim-config/plugins/coc.nvim/doc/coc.txt +++ b/vim-config/plugins/coc.nvim/doc/coc.txt @@ -1,4 +1,4 @@ -*coc-nvim.txt* LSP support for Vim & Neovim. +*coc-nvim.txt* NodeJS client for Vim & Neovim. Version: 0.0.80 Author: Qiming Zhao @@ -18,6 +18,9 @@ Interface |coc-interface| Commands |coc-commands| Autocmds |coc-autocmds| Highlights |coc-highlights| +Tree |coc-tree| + Tree mappings |coc-tree-mappings| + Tree filter |coc-tree-filter| List |coc-list| List command |coc-list-command| List command options |coc-list-options| @@ -50,31 +53,39 @@ Changelog |coc-changelog| ============================================================================== INTRODUCTION *coc-introduction* -Coc.nvim enhances your (Neo)Vim to match the user experience provided by VSCode -through rich plugin ecosystem and Language Server Protocol support. +Coc.nvim enhances your (Neo)Vim to match the user experience provided by +VSCode through a rich plugin (or extension) ecosystem and support for Language +Server Protocol. -Some of the features include:~ +Some of its key features include:~ -- APIs that are compatible with both Vim8 and Neovim. +- APIs compatible with both Vim8 and Neovim. - Loading VSCode-like extensions. -- Configuring coc.nvim and its extensions by using JSON configuration file. -- Configuring Language Servers that implement Language Server Protocol (LSP). +- Configuring coc.nvim and its extensions with a JSON configuration file. +- Configuring Language Servers implemented according to Language Server + Protocol (LSP). -It's designed to have a good integration with other Vim plugins as much as -possible. +It is designed for best possible integration with other Vim plugins. -Note: This plugin doesn't comes with any support for specific language, you -have to install extensions or configure languageserver for LSP features. +Note: This plugin doesn't come with support for any specific language. You +will need to install a coc extension or set up the language server yourself. -Note: This plugin doesn't change your key-mappings, you have to configure them -yourself. +Note: This plugin doesn't change any of your existing key-mappings. You will +need to create key-mappings by yourself, see README for examples. + +Note: Automatic completion plugins can't play nicely together, you can disable +automatic completion of coc.nvim through `"suggest.autoTrigger": "none"` (or +`"suggest.autoTrigger": "trigger"`) in your settings file. ============================================================================== REQUIREMENTS *coc-requirements* Neovim >= 0.3.2 or Vim >= 8.0.1453. -NodeJS https://nodejs.org/ >= 10.12.0 +NodeJS https://nodejs.org/ >= 12.12.0. + +Yarn https://yarnpkg.com/ required to build coc.nvim from typescript source +code. ============================================================================== INSTALLATION *coc-installation* @@ -82,21 +93,22 @@ INSTALLATION *coc-installation* If you're using [vim-plug](https://github.com/junegunn/vim-plug), add this to your `init.vim` or `.vimrc`: > - Plug 'neoclide/coc.nvim' - + Plug 'neoclide/coc.nvim', {'branch': 'release'} +< And run: > :PlugInstall -For other plugin managers, use code from the release branch. +For other plugin managers, make sure to use code from the release branch. -Or use Vim's built-in plugin ecosystem like: > +You can also use Vim's native package management: > #!/bin/sh # for vim8 mkdir -p ~/.vim/pack/coc/start cd ~/.vim/pack/coc/start curl --fail -L https://github.com/neoclide/coc.nvim/archive/release.tar.gz|tar xzfv - + # for neovim mkdir -p ~/.local/share/nvim/site/pack/coc/start cd ~/.local/share/nvim/site/pack/coc/start @@ -105,26 +117,35 @@ Or use Vim's built-in plugin ecosystem like: > ============================================================================== CONFIGURATION *coc-configuration* -Configurations of coc.nvim are stored in file names `coc-settings.json` that -can be opened using |:CocConfig| for user configuration file or -|:CocLocalConfig| for local configuration file. +The configuration of coc.nvim is stored in `coc-settings.json` file. You can +open it through |:CocConfig|. This will open (or create) a global settings +files in folder returned by |coc#util#get_config_home()| + +To create a local configuration project for a specific workspace, use +|:CocLocalConfig|: this will create `.vim/coc-settings.json` in the current +workspace folder. -The location of global configuration can be configured by `g:coc_config_home`. +The global configuration file can be created in another directory by setting +`g:coc_config_home` in your `.vimrc` or `init.vim`: > -Configure |b:coc_root_patterns| for project root resolve. + let g:coc_config_home = '/path/you/prefer' -To enable JSON completion and validation support of the settings file, install -the `coc-json` extension by command: +When creating a local configuration file, it's possible to use +|b:coc_root_patterns| for resolve the root directory from the filepath of +opend buffer. - CocInstall coc-json +Since the configuration files are all in JSON format, it's suggested to enable +JSON completion and validation by install the `coc-json` extension: > -Check out https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file + :CocInstall coc-json +< +Check https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file for more details. Built-in configurations:~ *coc-config-http* -"http.proxy":~ +*http.proxy* HTTP proxy URI, used for extensions that send request, default: `""` @@ -133,15 +154,20 @@ Built-in configurations:~ Controls whether the proxy server certificate should be verified against the list of supplied CAs, default: `true` +"http.proxyAuthorization":~ + + The value to send as the `Proxy-Authorization` header for every + network request. + +"http.proxyCA":~ + + CA (file) to use as Certificate Authority. + *coc-config-suggest* "suggest.enablePreselect":~ Enable preselect feature on Neovim, default: `false` -"suggest.maxPreviewWidth":~ - - Maximum width of floating preview window, default: `80` - "suggest.labelMaxLength":~ Maximum length of label shown in 'pum', default: `200` @@ -154,6 +180,11 @@ Built-in configurations:~ Enable floating window for documentation when possible, default: `true` +"suggest.floatConfig":~ + + Configuration of floating window/popup, see |coc-config-float|. + Excludes properties: "title", "close" and "maxHeight". + "suggest.detailMaxLength":~ Max length of detail that will be shown in popup menu, default: `100` @@ -207,6 +238,16 @@ Built-in configurations:~ Confirm completion instead of jump to next placeholder when completion activates, default: `false` +"suggest.snippetsSupport":~ + + Enable snippets expands expand on confirm completion. When set to + `false` coc.nvim would set language client option: + `CompletionClientCapabilities.completionItem.snippetSupport` to + `false` as well. + + Note: the language server may still send completion items with + snippets when falsy. + "suggest.fixInsertedWord":~ Inserted word replaces the next one, default: `true` @@ -233,7 +274,7 @@ Built-in configurations:~ "suggest.triggerCompletionWait":~ Delay between typing the trigger character and completion start which - initiates server synchronization, default: `50` + initiates server synchronization, default: `100` "suggest.echodocSupport":~ @@ -255,8 +296,8 @@ Built-in configurations:~ "suggest.keepCompleteopt":~ When enabled, 'completeopt' is not overridden. Autocompletion will be - disabled if 'completeopt' doesn't have 'noinsert' and 'noselect', default: - `false` + disabled if 'completeopt' doesn't have 'noinsert' and 'noselect', + default: `false` "suggest.lowPrioritySourceLimit":~ @@ -329,6 +370,19 @@ Built-in configurations:~ Display diagnostics, default: `true` +"diagnostic.highlighLimit":~ + + Limit count for highlighted diagnostics, too many diagnostic + highlights could make vim stop responsing. + + default: `1000` + +"diagnostic.autoRefresh":~ + + Enable automatically refresh diagnostics, use + |CocAction('diagnosticRefresh')| action to refresh diagnostics when it's + disabled. + "diagnostic.enableSign":~ Enable signs for diagnostics, default: `true` @@ -370,14 +424,10 @@ Built-in configurations:~ Default: `200` -"diagnostic.maxWindowWidth":~ - - Maximum width of diagnostics floating window, default: `80` - "diagnostic.checkCurrentLine":~ - Show all diagnostics of the current line if none of them are at the current - position, default: `false` + Show all diagnostics of the current line if none of them are at the + current position, default: `false` "diagnostic.messageTarget":~ @@ -392,8 +442,8 @@ Built-in configurations:~ "diagnostic.displayByAle":~ Use ALE for displaying diagnostics. This will disable coc.nvim for - displaying diagnostics. Restart to make changes take the effect, default: - `false` + displaying diagnostics. Restart to make changes take the effect, + default: `false` "diagnostic.virtualText":~ @@ -441,9 +491,9 @@ Built-in configurations:~ Sign of hint diagnostics shown in the 'signcolumn', default: `">>"` -"diagnostic.maxWindowHeight":~ +"diagnostic.floatConfig"~ - Maximum height of diagnostics floating window, default: `8` + Configuration of floating window/popup, see |coc-config-float|. "diagnostic.filetypeMap":~ @@ -464,12 +514,13 @@ Built-in configurations:~ "signature.enable":~ - Enable signature help when trigger character typed. Requires service restart - on change, default: `true` + Enable signature help when trigger character typed. Requires service + restart on change, default: `true` -"signature.maxWindowWidth":~ +"signature.floatConfig":~ - Max width of signature float window, default: `60` + Configuration of floating window/popup for signature documents, see + |coc-config-float|. "signature.triggerSignatureWait":~ @@ -484,23 +535,19 @@ Built-in configurations:~ "signature.preferShownAbove":~ - Show signature help's floating window above cursor when possible. Requires - restart on change, default: `true` + Show signature help's floating window above cursor when possible. + Requires restart on change, default: `true` "signature.hideOnTextChange":~ - Hide signature help's floating window when text changed. Requires restart - on change, default: `false` - -"signature.maxWindowHeight":~ - - Maximum height of floating window with the signature help, default: `8` + Hide signature help's floating window when text changed. Requires + restart on change, default: `false` *coc-config-refactor* "refactor.saveToFile":~ - Save to file when write refactor buffer with ':noa wa' command, set to - false if you want save buffer by yourself. + Save chagnes to file when write refactor buffer with |:write| command, + set to false if you want save buffer by yourself. "refactor.openCommand":~ @@ -517,17 +564,19 @@ Built-in configurations:~ *coc-config-hover* "hover.target":~ - Target to show hover information, default is floating window when possible. + Target to show hover information, default is floating window when + possible. Valid options: ["preview", "echo", "float"] -"hover.floatMaxWidth":~ +"hover.previewMaxHeight":~ - Maximum width of hover float window, not bigger than 80. + Max height of preview window for hover, default: `12` -"hover.floatMaxHeight":~ +"hover.floatConfig":~ - Maximum height of hover float window. + Configuration of floating window/popup for hover documents, see + |coc-config-float|. "hover.autoHide":~ @@ -637,7 +686,8 @@ Built-in configurations:~ "list.signOffset":~ - Sign offset of list, should be different from other plugins, default: `900` + Sign offset of list, should be different from other plugins, default: + `900` "list.selectedSignText":~ @@ -661,6 +711,17 @@ Built-in configurations:~ Highlight group used for highlighting the range in preview window, default: `"Search"` +"list.previewToplineStyle":~ + + Topline style for list previews + default: `"offset"` + Valid options: ["offset","middle"] + +"list.previewToplineOffset":~ + + Topline offset for list previews + default: `3` + "list.nextKeymap":~ Key for selecting next line in the insert mode, default: `""` @@ -671,8 +732,8 @@ Built-in configurations:~ "list.extendedSearchMode": ~ - Enable extended search mode which allows multiple search patterns delimited - by spaces, default: `true` + Enable extended search mode which allows multiple search patterns + delimited by spaces, default: `true` "list.normalMappings":~ @@ -747,14 +808,6 @@ Built-in configurations:~ Default: `"SNIP"` -"coc.preferences.previewAutoClose":~ - - Auto close preview window of hover upon cursor move, default: `true` - -"coc.preferences.previewMaxHeight":~ - - Max height of preview window for hover, default: `12` - "coc.preferences.colorSupport":~ Enable color highlight if Language Server support it, default: `true` @@ -817,18 +870,11 @@ Built-in configurations:~ Note: takes effect when `coc.preferences.formatOnType` set `true`. Note: This is the filetype after mapping by `g:coc_filetype_map`. -"coc.preferences.snippets.enable":~ - - Enables snippets support, default: `true` - "coc.preferences.listOfWorkspaceEdit":~ List should contains changed locations after workspace edit, default to vim's quickfix, default: `quickfix` -"coc.preferences.highlightTimeout":~ - - Highlight timeout for buffer in floating window, default: `500` "coc.preferences.floatActions":~ @@ -850,12 +896,12 @@ Built-in configurations:~ Not open split window with update status when performing auto update. - *coc-config-cursors* - "coc.preferences.willSaveHandlerTimeout"~ Will save handler timeout, default: `500` + *coc-config-cursors* + "cursors.cancelKey":~ Key used for cancel cursors session, default: `` @@ -868,12 +914,129 @@ Built-in configurations:~ Key used for jump to previous cursors position, default: `` + *coc-config-tree* +"tree.closedIcon": ~ + + Closed icon of tree view, use '' to make it looks better when you + have patched font, default: '+'. + +"tree.openedIcon": ~ + + Opened icon of tree view, use '' to make it looks better when you + have patched font, default: '-' + +"tree.key.toggleSelection":~ + + Trigger key to select/unselect item, default: + +"tree.key.toggle":~ + + Trigger key to toggle expand state of tree node, default: 't' + +"tree.key.actions":~ + + Trigger key to invoke actions, default: + +"tree.key.collapseAll":~ + + Trigger key to collapse all tree node, default: 'M' + +"tree.key.invoke":~ + + Trigger key to invoke default command of current node or selection, + default: + +"tree.key.close":~ + + Trigger key to dispose the tree and close tree window, default: + +"tree.key.activeFilter":~ + + Trigger key active filter, only works when tree view support filter, + default: 'f' + +"tree.key.selectNext":~ + + Trigger key to select next item during filter, default + +"tree.key.selectPrevious":~ + + Trigger key to select previous item during filter, default + + *coc-config-outline* +"outline.splitCommand":~ + + Window split command used by outline, default 'botright 30vs' + +"outline.followCursor":~ + + Reveal item in outline tree on cursor hold, default `true` + +"outline.keepWindow":~ + + Jump back to original window after outline is shown, default `false` + +"outline.sortBy":~ + + Sort method for symbols, default: 'category' + Could be 'position', 'name' or 'category'. + +"outline.expandLevel":~ + + Default expand level of tree nodes, default `1` + +"outline.checkBufferSwitch":~ + + Recreate outline view after changed to another buffer on current tab. + Default `true` + +"outline.showLineNumber": ~ + + Show line number of document symbols. + Default `true` + +"outline.codeActionKinds":~ + + Filter code actions in actions menu by kinds. + Default: ["", "quickfix", "refactor", "source"] + + *coc-config-callHierarchy* + +"callHierarchy.openCommand":~ + + Open command for callHierarchy tree view, default to "edit". + +"callHierarchy.splitCommand":~ + + Window split command used by callHierarchy tree view. + +"callHierarchy.enableTooltip":~ + + Enable tooltip to show relative filepath of call hierarchy. + *coc-config-npm* "npm.binPath":~ Command or full path of npm or yarn executable for install/update extensions, default: `npm` + *coc-config-float* + +Used by `suggest.floatConfig`, `diagnostic.floatConfig`, +`signature.floatConfig` and `hover.floatConfig`, following properties are +supported: + + - "border": Change to `true` to enable border. + - "highlight": Background highlight group of float window. + - "title": Title used by float window. + - "borderhighlight": Border highlight group of float window. + - "close": Set to true to draw close icon. + - "maxWidth": Maximum width of float window, contains border. + - "maxHeight": Maximum height of float window, contains border. + - "winblend": Set 'winblend' option of window, neovim only. + - "focusable": Set to false to make window not focusable, neovim only. + - "shadow": Set to true to enable shadow, neovim only. + *coc-config-languageserver* "languageserver":~ @@ -966,7 +1129,7 @@ Language server start with module:~ is used by default. - "execArgv": Argv passed to node on fork, normally used for - debugging, ex: `["--nolazy", "--inspect-brk=6045"]` + debugging, example: `["--nolazy", "--inspect-brk=6045"]` - "transport": Transport kind used by server, could be 'ipc', 'stdio', 'socket' and 'pipe'. 'ipc' is used by default (recommended). @@ -1057,67 +1220,64 @@ INTERFACE *coc-interface* ------------------------------------------------------------------------------ -Coc doesn't come with a default global keymap, you need to configure the -mappings yourself. - Key mappings *coc-key-mappings* -Note: Mappings that start with `i_` works for insert mode `n_` works for -normal mode, `v_` works for visual mode. - -(coc-diagnostic-info) *n_coc-diagnostic-info* - - Show diagnostic message of current position by invoke |coc-action-diagnosticInfo| +Unlike some vim plugins, coc.nvim doesn't create user global key-mappings by +default. However, there're some cases that local key-mappings are enabled for +current buffer. -(coc-diagnostic-next) *n_coc-diagnostic-next* + Snippet jump key-mappings when snippet is activated: + |g:coc_snippet_prev| and |g:coc_snippet_next|. - Jump to next diagnostic position. + Cursor jump and cancel key-mappings when cursors is activated + |coc-config-cursors|. -(coc-diagnostic-prev) *n_coc-diagnostic-prev* + Dialog key-mappings for confirm and cancel dialog window + |coc-config-dialog|. - Jump to previous diagnostic position. + Key-mappings for |CocList| buffer: |coc-list-mappings|. -(coc-diagnostic-next-error) *n_coc-diagnostic-next-error* +Note: Use |:verbose| command to check key-mappings that taking effect. - Jump to next diagnostic error position. +Note: Use 'noremap' with will make the key-mapping not work at all. -(coc-diagnostic-prev-error) *n_coc-diagnostic-prev-error* +Note: key-mappings are provided for convenient, use |CocActionAsync()| or +|CocAction()| for more options. - Jump to previous diagnostic error position. +Normal mode key-mappings:~ -(coc-definition) *n_coc-definition* +*(coc-diagnostic-info)* Show diagnostic message of current position by +invoke |CocAction('diagnosticInfo')| - Jump to definition(s) of current symbol by invoke - |coc-action-jumpDefinition| +*(coc-diagnostic-next)* Jump to next diagnostic position. -(coc-declaration) *n_coc-declaration* +*(coc-diagnostic-prev)* Jump to previous diagnostic position. - Jump to declaration(s) of current symbol by invoke - ||coc-action-jumpDeclaration|| +*(coc-diagnostic-next-error)* Jump to next diagnostic error position. -(coc-implementation) *n_coc-implementation* +*(coc-diagnostic-prev-error)* Jump to previous diagnostic error position. - Jump to implementation(s) of current symbol by invoke - ||coc-action-jumpImplementation|| +*(coc-definition)* Jump to definition(s) of current symbol by invoke +|CocAction('jumpDefinition')| -(coc-type-definition) *n_coc-type-definition* +*(coc-declaration)* Jump to declaration(s) of current symbol by invoke +|CocAction('jumpDeclaration')| - Jump to type definition(s) of current symbol by invoke - ||coc-action-jumpTypeDefinition|| +*(coc-implementation)* Jump to implementation(s) of current symbol by +invoke |CocAction('jumpImplementation')| -(coc-references) *n_coc-references* +*(coc-type-definition)* Jump to type definition(s) of current symbol by +invoke |CocAction('jumpTypeDefinition')| - Jump to references of current symbol by invoke - |coc-action-jumpReferences| +*(coc-references)* Jump to references of current symbol by invoke +|CocAction('jumpReferences')| -(coc-references-used) *n_coc-references-used* +*(coc-references-used)* Jump to references of current symbol exclude +declarations. - Jump to references of current symbol exclude declarations. +*(coc-format-selected)* -(coc-format-selected) *n_coc-format-selected* - *v_coc-format-selected* - - Format selected range, would work in both visual mode and normal mode, + Format selected range, works on both |visual-mode| and |normal-mode|, when used in normal mode, the selection works on the motion object. For example: > @@ -1128,130 +1288,127 @@ normal mode, `v_` works for visual mode. makes `p` format the visually selected range, and you can use `pap` to format a paragraph. -(coc-format) *n_coc-format* +*(coc-format)* - Format the whole buffer by invoke |coc-action-format|, normally you + Format the whole buffer by invoke |CocAction('format')|, normally you would like to use a command like: > command! -nargs=0 Format :call CocAction('format') < - to format the current buffer. - -(coc-rename) *n_coc-rename* - - Rename symbol under cursor to a new word by invoke |coc-action-rename| + to format current buffer. -(coc-codeaction) *n_coc-codeaction* +*(coc-rename)* Rename symbol under cursor to a new word by invoke +|CocAction('rename')| - Get and run code action(s) for current file, use |coc-codeaction-cursor| - for same beharior as VSCode. +*(coc-refactor)* Open refactor window for refactor of current symbol by +invoke |CocAction('refactor')| -(coc-codeaction-line) *n_coc-codeaction-line* +*(coc-command-repeat)* Repeat latest |CocCommand|. - Get and run code action(s) for current line. +*(coc-codeaction)* Get and run code action(s) for current file, use +|coc-codeaction-cursor| for same beharior as VSCode. -(coc-codeaction-cursor) *n_coc-codeaction-cursor* +*(coc-codeaction-line)* Get and run code action(s) for current line. - Get and run code action(s) using empty range at current cursor. +*(coc-codeaction-cursor)* Get and run code action(s) using empty range +at current cursor. -(coc-codeaction-selected) *n_coc-codeaction-selected* - *v_coc-codeaction-selected* +*(Coc-codeaction-selected)* Get and run code action(s) with the selected +region. Works on both |visual-mode| and |normal-mode|. - Get and run code action(s) with the selected region. - Works with both normal and visual mode. +*(coc-openlink)* Open link under cursor. -(coc-openlink) *n_coc-openlink* +*(coc-codelens-action)* Do command from codeLens of current line. - Open link under cursor. +*(coc-fix-current)* Try first quickfix action for diagnostics of current +line. -(coc-codelens-action) *n_coc-codelens-action* +*(coc-float-hide)* Hide all float windows/popups created by coc.nvim. - Do command from codeLens of current line. +*(coc-float-jump)* Jump to first float window (neovim only), use +|CTRL-W_p| for jump to previous window. -(coc-fix-current) *n_coc-fix-current* - - Try first quickfix action for diagnostics on the current line. - -(coc-float-hide) *n_coc-float-hide* - - Hide all float windows. - -(coc-float-jump) *n_coc-float-jump* - - Jump to first float window, works on neovim only since vim's popup - doesn't have support for focus. - -(coc-refactor) *n_coc-refactor* - - Open refactor window for refactor of current symbol. - -(coc-range-select) *n_coc-range-select* -(coc-range-select) *v_coc-range-select* +*(coc-range-select)* Select next selection range. + Works on both |visual-mode| and |normal-mode|. - Note: requires selection ranges feature of language server, like: - coc-tsserver, coc-python - -(coc-range-select-backward) *v_coc-range-select-backward* - - Select previous selection range. - - Note: requires selection ranges feature of language server, like: - coc-tsserver, coc-python - -(coc-funcobj-i) *n_coc-funcobj-i* - *v_coc-funcobj-i* - - Select inside function. Recommend mapping: - - xmap if (coc-funcobj-i) - omap if (coc-funcobj-i) - - Note: Requires 'textDocument.documentSymbol' support from the language - server. + Note: requires selection ranges feature of language server. -(coc-funcobj-a) *n_coc-funcobj-a* - *v_coc-funcobj-a* +*(coc-funcobj-i)* - Select around function. Recommended mapping: + Select inside function. Recommend mapping: + Works on both |visual-mode| and |normal-mode|. + > + xmap if (coc-funcobj-i) + omap if (coc-funcobj-i) +< + Note: Requires 'textDocument.documentSymbol' support from the language + server. +*(coc-funcobj-a)* + + Select around function. Works on both |visual-mode| and + |normal-mode|. Recommended mapping: +> xmap af (coc-funcobj-a) omap af (coc-funcobj-a) - +< Note: Requires 'textDocument.documentSymbol' support from the language server. -(coc-classobj-i) *n_coc-classobj-i* - *v_coc-classobj-i* - - Select inside class/struct/interface. Recommended mapping: +*(coc-classobj-i)* + Select inside class/struct/interface. Works on both |visual-mode| and + |normal-mode|. Recommended mapping: +> xmap ic (coc-classobj-i) omap ic (coc-classobj-i) - +< Note: Requires 'textDocument.documentSymbol' support from the language server. +*(coc-classobj-a)* -(coc-classobj-a) *n_coc-classobj-a* - *v_coc-classobj-a* - - Select around class/struct/interface. Recommended mapping: - + Select around class/struct/interface. Works on both |visual-mode| and + |normal-mode|. Recommended mapping: +> xmap ac (coc-classobj-a) omap ac (coc-classobj-a) - +< Note: Requires 'textDocument.documentSymbol' support from the language server. + +*(coc-cursors-operator)* Add text to cursors session by motion object. + +*(coc-cursors-word)* Add current word to cursors session. + +*(coc-cursors-position)* Add current position as empty range to cursors +session. + +Visual mode key-mappings:~ + +*(coc-range-select-backward)* + + Select previous selection range. + + Note: requires selection ranges feature of language server, like: + coc-tsserver, coc-python + +*(coc-cursors-range)* Add selection to cursors session. + ------------------------------------------------------------------------------ VARIABLES *coc-variables* +------------------------------------------------------------------------------ + +User defined variables:~ + b:coc_enabled *b:coc_enabled* Set to `0` on buffer create if you don't want coc.nvim receive content - from buffer. Normally used with |BufAdd| autocmd, ex: + from buffer. Normally used with |BufAdd| autocmd, example: > " Disable file with size > 1MB autocmd BufAdd * if getfsize(expand('')) > 1024*1024 | @@ -1262,7 +1419,7 @@ b:coc_root_patterns *b:coc_root_patterns* Root patterns used for resolving workspaceFolder for the current file, will be used instead of - `"coc.preferences.rootPatterns"` setting. E.g.: > + `"coc.preferences.rootPatterns"` setting. Example: > autocmd FileType python let b:coc_root_patterns = \ ['.git', '.env'] @@ -1270,7 +1427,7 @@ b:coc_root_patterns *b:coc_root_patterns* b:coc_suggest_disable *b:coc_suggest_disable* - Disable completion support of current buffer. E.g.: > + Disable completion support of current buffer. Example: > " Disable completion for python autocmd FileType python let b:coc_suggest_disable = 1 @@ -1282,30 +1439,18 @@ b:coc_diagnostic_disable *b:coc_diagnostic_disable* b:coc_suggest_blacklist *b:coc_suggest_blacklist* List of input words for which completion should not be triggered. - E.g.: > + Example: > " Disable completion for 'end' in lua files autocmd FileType lua let b:coc_suggest_blacklist = ["end"] b:coc_additional_keywords *b:coc_additional_keywords* - Addition keyword characters for generate keywords. E.g.: > + Addition keyword characters for generate keywords. Example: > " Add keyword characters for css autocmd FileType css let b:coc_additional_keywords = ["-"] -b:coc_current_function *b:coc_current_function* - - Function string that current cursor in. - - Set `"coc.preferences.currentFunctionSymbolAutoUpdate": true` - in coc-settings.json to update it on CursorHold. - -b:coc_cursors_activated *b:coc_cursors_activated* - - Use expression `get(b:, 'coc_cursors_activated',0)` to check if - cursors session is activated for current buffer. - g:coc_disable_startup_warning *g:coc_disable_startup_warning* Disable possible warning on startup for old vim/node version. @@ -1318,6 +1463,13 @@ g:coc_disable_uncaught_error *g:coc_disable_uncaught_error* Default: 0 +g:coc_text_prop_offset *g:coc_text_prop_offset* + + Start |textprop| id offset of highlight namespaces on vim, change to + other value to avoid conflict. + + Default: 1000 + g:coc_channel_timeout *g:coc_channel_timeout* Channel timeout in seconds for request to node client. @@ -1332,12 +1484,6 @@ g:coc_disable_transparent_cursor *g:coc_disable_transparent_cursor* Default: 0 -g:coc_last_hover_message *g:coc_last_hover_message* - - Last message echoed from `doHover`, can be used in statusline. - - Note: not used when floating or preview window used for `doHover`. - g:coc_start_at_startup *g:coc_start_at_startup* Start coc service on startup, use |CocStart| to start server when you @@ -1356,6 +1502,9 @@ g:coc_global_extensions *g:coc_global_extensions* > let g:coc_global_extensions = ['coc-json', 'coc-git'] < + Note: coc.nvim would try to install extensions that not installed in + this list after initialization. + g:coc_uri_prefix_replace_patterns *g:coc_uri_prefix_replace_patterns* This map defines URI prefix replacements. This is useful in the case @@ -1400,7 +1549,7 @@ g:coc_snippet_prev *g:coc_snippet_prev* g:coc_filetype_map *g:coc_filetype_map* Map for document filetypes so the server could handle current document - as another filetype, ex: > + as another filetype, example: > let g:coc_filetype_map = { \ 'html.swig': 'html', @@ -1427,9 +1576,9 @@ g:coc_selectmode_mapping *g:coc_selectmode_mapping* g:coc_node_path *g:coc_node_path* - Path to node executable to start coc service. ex: > + Path to node executable to start coc service, example: > - let g:coc_node_path = '/usr/local/opt/node@10/bin/node' + let g:coc_node_path = '/usr/local/opt/node@12/bin/node' < Use this when coc has problems with your system node, @@ -1439,7 +1588,7 @@ g:coc_node_args *g:coc_node_args* Arguments passed to node when starting coc service from source code. - Useful for starting coc in debug mode, ex: > + Useful for starting coc in debug mode, example: > > let g:coc_node_args = ['--nolazy', '--inspect-brk=6045'] < @@ -1457,16 +1606,6 @@ g:coc_jump_locations *g:coc_jump_locations* 'col': column number(1 based). 'text': line content of location. -g:coc_process_pid *g:coc_process_pid* - - Process pid of coc.nvim service. If your vim doesn't kill coc.nvim - process on exit, use: -> - autocmd VimLeavePre * if get(g:, 'coc_process_pid', 0) - \ | call system('kill -9 '.g:coc_process_pid) | endif -< - in your vimrc. - g:coc_status_error_sign *g:coc_status_error_sign* Error character used for statusline, default: `E` @@ -1492,12 +1631,12 @@ g:WorkspaceFolders *g:WorkspaceFolders* g:node_client_debug *g:node_client_debug* Enable debug mode of node client for check rpc messages between vim - and coc.nvim, use command: > + and coc.nvim. Use environment variable $NODE_CLIENT_LOG_FILE to set + the log file or get the log file after coc.nvim started. + To open the log file, use command: > :call coc#client#open_log() < - to open the log file. - Default: `0` g:coc_config_home *g:coc_config_home* @@ -1516,14 +1655,10 @@ g:coc_data_home *g:coc_data_home* Windows: `~/AppData/Local/coc` Other: `~/.config/coc` -g:coc_last_float_win *g:coc_last_float_win* - - Window id of latest created float/popup window. - g:coc_sources_disable_map *g:coc_sources_disable_map* Configure disabled sources for different filetypes. - Use `:CocList sources` for loaded complete sources. ex: + Use `:CocList sources` for loaded complete sources. Example: > let g:coc_sources_disable_map = { \ 'python': ['omni', 'tag'] \ } @@ -1545,25 +1680,48 @@ g:coc_border_joinchars *g:coc_border_joinchars* g:coc_prompt_win_width *g:coc_prompt_win_width* - Width of input prompt window on neovim >= 0.5.0. Prompt buffer can't - work with vim8's popup yet. + Width of input prompt window, default `32`. -g:coc_markdown_disabled_languages *g:coc_markdown_disabled_languages* +g:coc_markdown_disabled_languages *g:coc_markdown_disabled_languages* - Filetype list that should be disabled for highlight in markdown block, ex: > + Filetype list that should be disabled for highlight in markdown block, + Example: > let g:coc_markdown_disabled_languages = ['html'] -> - -g:coc_install_yarn_cmd *g:coc_install_yarn_cmd* - - Yarn command used for |coc#util#install()| function. ------------------------------------------------------------------------------ Some variables are provided by coc.nvim so you can use them in your statusline. See |coc-status| for detail. +g:coc_process_pid *g:coc_process_pid* + + Process pid of coc.nvim service. If your vim doesn't kill coc.nvim + process on exit, use: +> + autocmd VimLeavePre * if get(g:, 'coc_process_pid', 0) + \ | call system('kill -9 '.g:coc_process_pid) | endif +< + in your vimrc. + +g:coc_service_initialized *g:coc_service_initialized* + + Is `1` when coc.nvim initialized, used with autocmd |CocNvimInit|. + +g:coc_status *g:coc_status* + + Status string contributed by extensions, used for status line. + +g:coc_last_float_win *g:coc_last_float_win* + + Window id of latest created float/popup window. + +g:coc_last_hover_message *g:coc_last_hover_message* + + Last message echoed from `doHover`, can be used in statusline. + + Note: not used when floating or preview window used for `doHover`. + b:coc_diagnostic_info *b:coc_diagnostic_info* Diagnostic information of current buffer, the format would look like: @@ -1572,9 +1730,17 @@ b:coc_diagnostic_info *b:coc_diagnostic_info* can be used to customize statusline. See |coc-status|. -g:coc_status *g:coc_status* +b:coc_current_function *b:coc_current_function* - Status string contributed by extensions, used for status line. + Function string that current cursor in. + + Set `"coc.preferences.currentFunctionSymbolAutoUpdate": true` + in coc-settings.json to update it on CursorHold. + +b:coc_cursors_activated *b:coc_cursors_activated* + + Use expression `get(b:, 'coc_cursors_activated',0)` to check if + cursors session is activated for current buffer. ------------------------------------------------------------------------------ FUNCTIONS *coc-functions* @@ -1595,7 +1761,7 @@ coc#start([{option}]) *coc#start()* - `source` specific completion source name. - ex: > + Example: > inoremap =coc#start({'source': 'word'}) < @@ -1604,7 +1770,7 @@ coc#start([{option}]) *coc#start()* coc#config({section}, {value}) *coc#config()* Change user configuration by Vim script, no changes would be made to - user configuration file. ex: > + user configuration file. Example: > call coc#config('coc.preferences', { \ 'timeout': 1000, @@ -1631,7 +1797,7 @@ coc#add_extension({name}, ...) *coc#add_extension()* Deprecated function for install extensions not exists. Use |g:coc_global_extensions| variable instead. - ex: > + Example: > call coc#add_extension('coc-json', 'coc-tsserver', 'coc-rls') < @@ -1651,7 +1817,7 @@ coc#add_command({id}, {command}, [{title}]) *coc#add_command()* coc#refresh() *coc#refresh()* Start or refresh completion at current cursor position, bind this to - 'imap' to trigger completion, ex: > + 'imap' to trigger completion, example: > inoremap coc#refresh() < @@ -1673,7 +1839,7 @@ coc#on_enter() *coc#on_enter()* Notify coc.nvim that `` has been pressed. - Used for the format on type and improvement of brackets, ex: > + Used for the format on type and improvement of brackets, example: > inoremap pumvisible() ? coc#_select_confirm() \: "\u\\=coc#on_enter()\" @@ -1697,12 +1863,6 @@ coc#_select_confirm() *coc#_select_confirm()* autocmd should exists or only and should be used to select a completion item. - -health#coc#check() *health#coc#check()* - - Neovim only, run health check, triggered by ':checkhealth' - command. - coc#util#api_version() *coc#util#api_version()* Get coc.nvim's vim api version number, start from `1`. @@ -1725,7 +1885,7 @@ coc#util#extension_root() *coc#util#extension_root()* coc#util#rebuild() *coc#util#rebuild()* - Rebuild coc extensions. + Run `npm rebuild` for all coc extensions. coc#util#root_patterns() *coc#util#root_patterns()* @@ -1737,15 +1897,11 @@ coc#util#root_patterns() *coc#util#root_patterns()* < coc#util#get_config({key}) *coc#util#get_config()* - Get configuration (mostly defined in coc-settings.json) by {key}, ex: > + Get configuration (mostly defined in coc-settings.json) by {key}, + example: > :echo coc#util#get_config('coc.preferences') -coc#util#install() *coc#util#install()* - - Install dependencies and compile source code, not needed unless - you need compile typescript code. - coc#float#has_float([{all}]) *coc#float#has_float()* Check if float window/popup exists, check coc.nvim's float @@ -1788,7 +1944,7 @@ coc#float#scroll({forward}, [{amount}]) *coc#float#scroll()* CocRequest({id}, {method}, [{params}]) *CocRequest()* Send a request to language client of {id} with {method} and optional - {params}. ex: > + {params}. Example: > call CocRequest('tslint', 'textDocument/tslint/allFixes', \ {'textDocument': {'uri': 'file:///tmp'}}) @@ -1804,7 +1960,7 @@ CocRequestAsync({id}, {method}, [{params}, [{callback}]]) CocNotify({id}, {method}, [{params}]) *CocNotify()* - Send notification to remote language server, ex: + Send notification to remote language server, example: > call CocNotify('ccls', '$ccls/reload') < @@ -1850,15 +2006,22 @@ CocAction({action}, [...{args}]) *CocAction()* Run {action} of coc with optional extra {args}. + Checkout |coc-actions| for available actions. + + Note: it's recommended to use |CocActionAsync()| unless you need + result from |CocAction()|. + *CocActionAsync()* CocActionAsync({action}, [...{args}, [{callback}]]) - Call CocAction without blocking vim. + Call CocAction by send notification to server of coc.nvim. Optional callback is called with `error` as the first argument and `response` as the second argument. + Checkout |coc-actions| for available actions. + CocHasProvider({feature}) *CocHasProvider()* Check if provider exists for specified feature. Supported features: @@ -1880,46 +2043,69 @@ CocTagFunc({pattern}, {flags}, {info}) *CocTagFunc()* :echo exists('&tagfunc') < ------------------------------------------------------------------------------ - *coc-action* + *coc-actions* Available Actions ~ Acceptable {action} names for |CocAction()| and |CocActionAsync|. -"sourceStat" *coc-action-sourceStat* - - get the list of completion source stats for the current buffer. +"ensureDocument" *CocAction('ensureDocument')* -"refreshSource" [{source}] *coc-action-refreshSource* - - refresh all sources or a source with a name of {source}. + Ensure current document is attached to coc.nvim, should be used when + you need invoke action of current document just after document + created. -"toggleSource" {source} *coc-action-toggleSource* + Return `v:false` when the document can't be attached, the document + won't be attached for one of these reasons: - enable/disable {source}. + 1. The 'buftype' option is neither nor acwrite. + 2. Buffer variable `b:coc_enabled` is set to `0`. + 3. Size of buffer bigger than `coc.preferences.maxFileSize` + configuration. + 4. The buffer is used for command line window. -"diagnosticList" *coc-action-diagnosticList* +"diagnosticList" *CocAction('diagnosticList')* Get all diagnostic items of the current Neovim session. -"diagnosticInfo" *coc-action-diagnosticInfo* +"diagnosticInfo" *CocAction('diagnosticInfo')* Show diagnostic message at the current position, do not truncate. -"diagnosticToggle" *coc-action-diagnosticToggle* +"diagnosticToggle" *CocAction('diagnosticToggle')* Enable/disable diagnostics on the fly, not work when `displayByAle` is enabled. -"diagnosticPreview" *coc-action-diagnosticPreview* +"diagnosticPreview" *CocAction('diagnosticPreview')* Show diagnostics under current cursor in preview window. -"jumpDefinition" [{openCommand}] *coc-action-jumpDefinition* +"diagnosticRefresh" [{bufnr}] *CocAction('diagnosticRefresh')* + + Force refresh diagnostics for special buffer with {bufnr} or all buffers + when {bufnr} not exists, returns `v:null` before diagnostics are shown. + + Useful when `diagnostic.autoRefresh` is `false`. + +"refreshSource" [{source}] *CocAction('refreshSource')* + + refresh all sources or a source with a name of {source}. + +"sourceStat" *CocAction('sourceStat')* + + get the list of completion source stats for the current buffer. + +"toggleSource" {source} *CocAction('toggleSource')* + + enable/disable {source}. + +"jumpDefinition" [{openCommand}] *CocAction('jumpDefinition')* jump to definition position of the current symbol. Return `v:false` when location not found. - |coc-list-location| is used when more than one position is available. + |coc-list-location| is used when more than one position is available, + for custom location list, use variable: |g:coc_enable_locationlist|. To always use |coc-list-location|| for locations, use `v:false` for {openCommand}. @@ -1927,7 +2113,7 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. {openCommand}: optional command to open buffer, default to `coc.preferences.jumpCommand` in `coc-settings.json` -"jumpDeclaration" [{openCommand}] *coc-action-jumpDeclaration* +"jumpDeclaration" [{openCommand}] *CocAction('jumpDeclaration')* jump to declaration position of the current symbol. Return `v:false` when location not found. @@ -1936,42 +2122,47 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. When {openCommand} is `v:false`, location list would be always used. -"jumpImplementation" [{openCommand}] *coc-action-jumpImplementation* +"jumpImplementation" [{openCommand}] *CocAction('jumpImplementation')* Jump to implementation position of the current symbol. Return `v:false` when location not found. same behavior as "jumpDefinition" -"jumpTypeDefinition" [{openCommand}] *coc-action-jumpTypeDefinition* +"jumpTypeDefinition" [{openCommand}] *CocAction('jumpTypeDefinition')* Jump to type definition position of the current symbol. Return `v:false` when location not found. same behavior as "jumpDefinition" -"jumpReferences" [{openCommand}] *coc-action-jumpReferences* +"jumpReferences" [{openCommand}] *CocAction('jumpReferences')* Jump to references position of the current symbol. Return `v:false` when location not found. same behavior as "jumpDefinition" -"doHover" [{hoverTarget}] *coc-action-doHover* +"getHover" *CocAction('getHover')* + + Get documentation text array on current position, returns array of + string. - Show documentation of the current word in a preview window. - Return `v:false` when hover not found. +"doHover" [{hoverTarget}] *CocAction('doHover')* + + Show documentation of current symbol, return `v:false` when hover not + found. {hoverTarget}: optional specification for where to show hover info, defaults to `coc.preferences.hoverTarget` in `coc-settings.json`. Valid options: ["preview", "echo", "float"] + +"definitionHover" [{hoverTarget}] *CocAction('definitionHover')* -"getHover" *coc-action-getHover* - - Get documentation text array on current position, returns array of - string. + Same as |CocAction('doHover')|, but includes definition contents from + definition provider when possible. -"showSignatureHelp" *coc-action-showSignatureHelp* +"showSignatureHelp" *CocAction('showSignatureHelp')* Echo signature help of current function, return `v:false` when signature not found. You may want to set up an autocmd like this: > @@ -1979,30 +2170,15 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. autocmd User CocJumpPlaceholder call \ CocActionAsync('showSignatureHelp') < -"getCurrentFunctionSymbol" *coc-action-getCurrentFunctionSymbol* +"getCurrentFunctionSymbol" *CocAction('getCurrentFunctionSymbol')* Return the function string that current cursor in. -"documentSymbols" [{bufnr}] *coc-action-documentSymbols* +"documentSymbols" [{bufnr}] *CocAction('documentSymbols')* Get a list of symbols of current buffer or specific {bufnr}. -"ensureDocument" *coc-action-ensureDocument* - - Ensure current document is attached to coc.nvim, should be used when - you need invoke action of current document just after document - created. - - Return `v:false` when the document can't be attached, the document - won't be attached for one of these reasons: - - 1. The 'buftype' option is neither nor acwrite. - 2. Buffer variable `b:coc_enabled` is set to `0`. - 3. Size of buffer bigger than `coc.preferences.maxFileSize` - configuration. - 4. The buffer is used for command line window. - -"rename" *coc-action-rename* +"rename" *CocAction('rename')* Rename the symbol under the cursor position, user will be prompted for a new name. @@ -2010,24 +2186,18 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. Note: coc.nvim supports rename for disk files, but your language server may not. -"selectionRanges" *coc-action-selectionRanges* - - Get selection ranges of current position from language server. - -"services" *coc-action-services* - - Get an information list for all services. - -"toggleService" {serviceId} *coc-action-toggleService* +"refactor" *CocAction('refactor')* - Start or stop a service. + Open refactor windows with current symbol as activated cursor ranges. + Check |coc-config-cursors| and |coc-config-refactor| for related + configuration. -"format" *coc-action-format* +"format" *CocAction('format')* Format current buffer using the language server. Return `v:false` when format failed. -"formatSelected" [{mode}] *coc-action-formatSelected* +"formatSelected" [{mode}] *CocAction('formatSelected')* Format the selected range, {mode} should be one of visual mode: `v` , `V`, `char`, `line`. @@ -2035,7 +2205,19 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. When {mode} is omitted, it should be called using |formatexpr|. -"codeAction" [{mode}] [{only}] *coc-action-codeAction* +"selectionRanges" *CocAction('selectionRanges')* + + Get selection ranges of current position from language server. + +"services" *CocAction('services')* + + Get an information list for all services. + +"toggleService" {serviceId} *CocAction('toggleService')* + + Start or stop a service. + +"codeAction" [{mode}] [{only}] *CocAction('codeAction')* Prompt for a code action and do it. @@ -2044,26 +2226,26 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. {only} can be title of a codeAction or list of CodeActionKind. -"codeActionRange" {start} {end} [{kind}] *coc-action-codeActionRange* +"codeActionRange" {start} {end} [{kind}] *CocAction('codeActionRange')* Run code action for range. {start} start line number of range. {end} end line number of range. - {kind} code action kind, see |coc-action-codeActions| for available + {kind} code action kind, see |CocAction('codeActions')| for available action kind. -"codeLensAction" *coc-action-codeLensAction* +"codeLensAction" *CocAction('codeLensAction')* Invoke the command for codeLens of current line (or the line that contains codeLens just above). Prompt would be shown when multiple actions are available. -"commands" *coc-action-commands* +"commands" *CocAction('commands')* Get a list of available service commands for the current buffer. -"runCommand" [{name}] [...{args}] *coc-action-runCommand* +"runCommand" [{name}] [...{args}] *CocAction('runCommand')* Run a global command provided by the language server. If {name} is not provided, a prompt with a list of commands is shown to be selected. @@ -2075,24 +2257,24 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. command! -nargs=0 OrganizeImport \ :call CocActionAsync('runCommand', 'tsserver.organizeImports') -"fold" {{kind}} *coc-action-fold* +"fold" {{kind}} *CocAction('fold')* Fold the current buffer, optionally use {kind} for filtering folds, {kind} could be either 'comment', 'imports' or 'region' Return `v:false` when failed. -"highlight" *coc-action-highlight* +"highlight" *CocAction('highlight')* Highlight the symbols under the cursor. - Overwrite the highlight groups `CocHighlightText`, `CocHighlightRead` - and `CocHighlightWrite` for customizing the colors. + Overwrite the highlight groups |CocHighlightText|, |CocHighlightRead| + and |CocHighlightWrite| for customizing the colors. To enable highlight on CursorHold, create an autocmd like this: > autocmd CursorHold * silent call CocActionAsync('highlight') < -"openLink" [{command}] *coc-action-openlink* +"openLink" [{command}] *CocAction('openlink')* Open a link under the cursor with {command}. {command} default to `edit`. @@ -2101,34 +2283,34 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. Note: it needs language server support documentLink feature to work. -"extensionStats" *coc-action-extensionStats* +"extensionStats" *CocAction('extensionStats')* Get all extension states as a list. Including `id`, `root` and `state`. State could be `disabled`, `activated` and `loaded`. -"toggleExtension" {id} *coc-action-toggleExtension* +"toggleExtension" {id} *CocAction('toggleExtension')* Enable/disable an extension. -"uninstallExtension" {id} *coc-action-uninstallExtension* +"uninstallExtension" {id} *CocAction('uninstallExtension')* Uninstall an extension. -"reloadExtension" {id} *coc-action-reloadExtension* +"reloadExtension" {id} *CocAction('reloadExtension')* Reload an activated extension. -"activeExtension" {id} *coc-action-activeExtension* +"activeExtension" {id} *CocAction('activeExtension')* Activate extension of {id}. -"deactivateExtension" {id} *coc-action-deactivateExtension* +"deactivateExtension" {id} *CocAction('deactivateExtension')* Deactivate extension of {id}. -"pickColor" *coc-action-pickColor* +"pickColor" *CocAction('pickColor')* Change the color at the current cursor position. @@ -2137,14 +2319,14 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. Note: only works on mac or when you have python support on Vim and have the gtk module installed. -"colorPresentation" *coc-action-colorPresentation* +"colorPresentation" *CocAction('colorPresentation')* Change the color presentation at the current color position. Requires a language server that supports color representation requests. -"codeActions" [{mode}] [{only}] *coc-action-codeActions* +"codeActions" [{mode}] [{only}] *CocAction('codeActions')* Get and invoke codeActions on current document, quickpick menu would be shown when there're many codeActions. @@ -2165,48 +2347,52 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. {only} can also be string, which means filter by tilte of codeAction. -"organizeImport" *coc-action-organizeImport* +"organizeImport" *CocAction('organizeImport')* Run organize import codeAction for current buffer. Show warning when codeAction not found. -"fixAll" *coc-action-fixAll* +"fixAll" *CocAction('fixAll')* Run fixAll codeAction for current buffer. Show warning when codeAction not found. -"quickfixes" [{visualmode}] *coc-action-quickfixes* +"quickfixes" [{visualmode}] *CocAction('quickfixes')* Get quickfix codeActions of current buffer. Add {visualmode} as second argument get quickfix actions with range of latest |visualmode()| -"doCodeAction" {codeAction} *coc-action-doCodeAction* +"doCodeAction" {codeAction} *CocAction('doCodeAction')* Do a codeAction. -"doQuickfix" *coc-action-doQuickfix* +"doQuickfix" *CocAction('doQuickfix')* - Do the first quickfix action for the current line. - Return `v:false` when no quickfix action found. + Do the first preferred quickfix action on current line. -"addRanges" {ranges} *coc-action-addRanges* + Throw error when no quickfix action found. + +"addRanges" {ranges} *CocAction('addRanges')* Ranges must be provided as array of range type: https://git.io/fjiEG -"getWordEdit" *coc-action-getWordEdit* +"getWordEdit" *CocAction('getWordEdit')* Get workspaceEdit of current word, language server used when possible, extract word from current buffer as fallback. -"getWorkspaceSymbols" {input} [{bufnr}] *coc-action-getWorkspaceSymbols* +"getWorkspaceSymbols" {input} *CocAction(getWorkspaceSymbols)* + + Get workspace symbols from {input}. + +"resolveWorkspaceSymbol" {symbol} *CocAction('resolveWorkspaceSymbol')* - Get workspace symbols from {input} and optional {bufnr} (use current - bufnr when empty). + Resolve location for workspace {symbol}. -"toggleDiagnosticBuffer" [{bufnr}] *coc-action-toggleDiagnosticBuffer* +"diagnosticToggleBuffer" [{bufnr}] *CocAction('diagnosticToggleBuffer')* Toggle diagnostics for specific buffer, current buffer is used when {bufnr} not provided. @@ -2214,6 +2400,74 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync|. Note: this will only affect diagnostics shown in the UI, list of all diagnostics won't change. +"showOutline" [{keep}] *CocAction('showOutline')* + + Show outline tree view for current buffer. Old outline window on current + tab would be replaced. + Outline view has Window variable `cocViewId` set to `OUTLINE`. + + {keep} override `"outline.keepWindow"` configuration when specified. + Could be 0 or 1. + + Returns after window is shown (document symbol request is still in + progress). + + Note: like VSCode, outline would try to reload document symbols after + 500ms when provider not registered, which avoid the necessary to check + provider existence. + + Note: error is shown when current buffer is not attatched, checkout + |CocAction('ensureDocument')|, for possible reasons. + + Checkout |coc-config-tree| and |coc-config-outline| for available + configurations. + + Checkout |CocTree| and |CocSymbol| for customize highlights. + + Use configuration `"suggest.completionItemKindLabels"` for custom icons. + + To show outline for each tab automatically, use |autocmd|: +> + autocmd VimEnter,Tabnew * + \ if empty(&buftype) | call CocActionAsync('showOutline', 1) | endif +< +"hideOutline" *CocAction('hideOutline')* + + Close outline window on current tab. Throws vim error when it can't + be closed by vim. + +"incomingCalls" [{CallHierarchyItem}] *CocAction('incomingCalls')* + + Retrieve incoming calls from {CallHierarchyItem} or current position + when not provided. + +"outgoingCalls" [{CallHierarchyItem}] *CocAction('outgoingCalls')* + + Retrieve outgoing calls from {CallHierarchyItem} or current position + when not provided. + +"showIncomingCalls" *CocAction('showIncomingCalls')* + + Show incoming calls of current function with |coc-tree|, + Configured by |CocSymbol|, |coc-config-callHierarchy| and + |coc-config-tree|. + + Related ranges are highlighted with |CocSelectedRange| highlight + group. + + |coc-dialog-menu| could be invoked by key configured by + `"tree.key.actions". Available actions: + + - Dismiss. + - Open in new tab. + - Show Incoming Calls. + - Show Outgoing Calls. + + +"showOutgoingCalls" *CocAction('showOutgoingCalls')* + + Show outgoing calls of current function with |coc-tree|. + ------------------------------------------------------------------------------ COMMANDS *coc-commands* @@ -2315,7 +2569,7 @@ COMMANDS *coc-commands* let $NVIM_COC_LOG_LEVEL='debug' < - to the beggining of your `.vimrc` + to the beginning of your `.vimrc` :CocInfo *:CocInfo* @@ -2384,6 +2638,10 @@ COMMANDS *coc-commands* Watch loaded [extension] for reload on file change, use for complete extension id. +:CocOutline *:CocOutline* + + Invoke |CocAction('showOutline')| by notification. + ------------------------------------------------------------------------------ AUTOCMD *coc-autocmds* @@ -2400,7 +2658,7 @@ AUTOCMD *coc-autocmds* let g:coc_enable_locationlist = 0 autocmd User CocLocationsChange CocList --normal location < - *CocNvimInit* + *CocNvimInit* :autocmd User CocNvimInit {command} Triggered after the coc services have started. @@ -2408,14 +2666,14 @@ AUTOCMD *coc-autocmds* If you want to trigger an action of coc after Vim has started, this autocmd should be used because coc is always started asynchronously. - *CocStatusChange* + *CocStatusChange* :autocmd User CocStatusChange {command} Triggered after `g:coc_status` changed, can be used for refresh stautsline. - *CocDiagnosticChange* + *CocDiagnosticChange* :autocmd User CocDiagnosticChange {command} @@ -2423,7 +2681,7 @@ AUTOCMD *coc-autocmds* Could be used for updating the statusline. - *CocJumpPlaceholder* + *CocJumpPlaceholder* :autocmd User CocJumpPlaceholder {command} @@ -2432,14 +2690,21 @@ AUTOCMD *coc-autocmds* autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp') < - *CocOpenFloat* + *CocOpenFloat* :autocmd User CocOpenFloat {command} Triggered when a floating window is opened. The window is not focused, use |g:coc_last_float_win| to get window id. - *CocTerminalOpen* + *CocOpenFloatPrompt* + +:autocmd User CocOpenFloatPrompt {command} + + Triggered when a floating prompt window is opened (triggered after + CocOpenFloat). + + *CocTerminalOpen* :autocmd User CocTerminalOpen {command} Triggered when the terminal is shown, can be used for adjusting the @@ -2449,250 +2714,229 @@ AUTOCMD *coc-autocmds* HIGHLIGHTS *coc-highlights* -To customize a highlight, simply use |:highlight| command of Vim in your -vimrc, like: > - +To customize a highlight, simply use |:highlight| command in your vimrc, like: +> " make error texts have a red color highlight CocErrorHighlight ctermfg=Red guifg=#ff0000 < -Note: don't use `:hi default` for overwriting the highlights. - -Note: highlight commands should appear after the |:colorscheme| command or use -|ColorScheme| autocmd to make sure customized highlight works after color -scheme change. - -CocUnderline *CocUnderline* - - Default: `hi default CocUnderline cterm=underline gui=underline` - - Used for underlined text. - -CocFadeOut *CocFadeOut* - - Default: `hi default CocFadeOut guifg=#928374 ctermfg=245` - - Used for highlight unnecessary code. - -CocStrikeThrough *CocStrikeThrough* - - Default: `hi default CocStrikeThrough guifg=#989898 ctermfg=gray` - `\ cterm=strikethrough gui=strikethrough` - - Used for strikethrough text, like usage of deprecated API. - Default color is used since strikethrough may not work. - -CocBold *CocBold* - - Default: `hi default CocBold term=bold cterm=bold gui=bold` - - Used for bold text. - -CocItalic *CocItalic* - - Default: `hi default CocItalic term=italic cterm=italic gui=italic` - - Used for italic text. - -CocMarkdownCode *CocMarkdownCode* - - Default: `hi default link CocMarkdownCode markdownCode` - - Used for markdown code in floating window/popup. - -CocMarkdownHeader *CocMarkdownHeader* - - Default: `hi default link CocMarkdownHeader markdownH1` - - Used for markdown header in floating window/popup. - -CocMarkdownLink *CocMarkdownLink* - - Default: `hi default CocMarkdownLink ctermfg=Blue guifg=#15aabf guibg=NONE` - - Used for markdown link text in floating window/popup. - -CocErrorSign *CocErrorSign* - - Default: `hi CocErrorSign ctermfg=Red guifg=#ff0000` - - Used for error signs. - -CocWarningSign *CocWarningSign* - - Default: `hi CocWarningSign ctermfg=Brown guifg=#ff922b` - - Used for warning signs. - -CocInfoSign *CocInfoSign* - - Default: `hi CocInfoSign ctermfg=Yellow guifg=#fab005` - - Used for information signs. - -CocHintSign *CocHintSign* - - Default: `hi CocHintSign ctermfg=Blue guifg=#15aabf` - - Used for hint signs. - -CocErrorVirtualText *CocErrorVirtualText* - - Default: `hi default link CocErrorVirtualText CocErrorSign` - - Used for error signs. - -CocWarningVirtualText *CocWarningVirtualText* - - Default: `hi default link CocWarningVirtualText CocWarningSign` - - Used for warning signs. - -CocInfoVirtualText *CocInfoVirtualText* - - Default: `hi default link CocInfoVirtualText CocInfoSign` - - Used for information signs. - -CocHintVirtualText *CocHintVirtualText* - - Default: `hi default link CocHintVirtualText CocHintSign` - - Used for hint signs. - -CocErrorHighlight *CocErrorHighlight* +Type |:highlight| command with group name to check current highlight. - Default: `hi default link CocErrorHighlight CocUnderline` - - Used for error text. - -CocWarningHighlight *CocWarningHighlight* - - Default: `hi default link CocWarningHighlight CocUnderline` - - Used for warning text. - -CocInfoHighlight *CocInfoHighlight* - - Default: `hi default link CocInfoHighlight CocUnderline` - - Used for information text. - -CocHintHighlight *CocHintHighlight* - - Default: `hi default link CocHintHighlight CocUnderline` - - Used for hint text. - -CocHighlightText *CocHighlightText* - - Default `hi default link CursorColumn` - - Used for document highlight feature. Normally used for - highlighting same symbols in the buffer at the current cursor position. - -CocHighlightRead *CocHighlightRead* - - Default `hi default link CocHighlightRead CocHighlightText` - - Highlight for `Read` kind of document symbol. - -CocHighlightWrite *CocHighlightWrite* - - Default `hi default link CocHighlightWrite CocHighlightText` - - Highlight for `Write` kind of document symbol. - -CocErrorLine *CocErrorLine* - - Default `undefined` - - Line highlight of sign for a line that contains error diagnostic. - -CocWarningLine *CocWarningLine* - - Default `undefined` - - Line highlight of sign for a line that contains warning diagnostic. - -CocInfoLine *CocInfoLine* - - Default `undefined` - - Line highlight of sign for a line that contains info diagnostic. - -CocHintLine *CocHintLine* - - Default `undefined` - - Highlight for a line with diagnostic hint. - -CocCodeLens *CocCodeLens* - - Default: `ctermfg=Gray guifg=#999999` - - Highlight group of virtual text for codeLens. - -CocFloating *CocFloating* - - Default: `NormalFloat` on neovim, `Pmenu` on vim. - - Normal highlight group of floating windows/popups. - -CocErrorFloat *CocErrorFloat* - - Default: `hi default link CocErrorFloat CocErrorSign` - - Used for floating windows/popups with errors. - -CocWarningFloat *CocWarningFloat* - - Default: `hi default link CocWarningFloat CocWarningSign` - - Used for warnings in floating windows/popups. - -CocInfoFloat *CocInfoFloat* - - Default: `hi default link CocInfoFloat CocInfoSign` - - Used for infos in floating windows/popups. - -CocHintFloat *CocHintFloat* +Note: don't use `:hi default` for overwriting the highlights. - Default: `hi default link CocHintFloat CocHintSign` +Note: user defined highlight commands should appear after the |:colorscheme| +command and use |ColorScheme| autocmd to make sure customized highlights works +after color scheme change. + +Markdown related~ + +*CocBold* for bold text. +*CocItalic* for italic text. +*CocUnderline* for underlined text. +*CocStrikeThrough* for strikethrough text, like usage of deprecated API. +*CocMarkdownCode* for inline code in markdown content. +*CocMarkdownHeader* for markdown header in floating window/popup. +*CocMarkdownLink* for markdown link text in floating window/popup. + +Diagnostics related~ + +*CocFadeOut* for faded out text, such as for highlighting unnecessary code. +*CocErrorSign* for error signs. +*CocWarningSign* for warning signs. +*CocInfoSign* for information signs. +*CocHintSign* for hint signs. +*CocErrorVirtualText* for error virtual text. +*CocWarningVirtualText* for warning virtual text. +*CocInfoVirtualText* for information virtual text. +*CocHintVirtualText* for hint virtual text. +*CocErrorHighlight* for error code range. +*CocWarningHighlight* for warning code range. +*CocInfoHighlight* for information code range. +*CocHintHighlight* for hint code range. +*CocDeprecatedHighlight* for deprecated code range, links to +|CocStrikeThrough| by default. +*CocUnusedHighlight* for unnecessary code range, links to |CocFadeOut| by +default. +*CocErrorLine* line highlight of sign which contains error. +*CocWarningLine* line highlight of sign which contains warning. +*CocInfoLine* line highlight of sign which information. +*CocHintLine* line highlight of sign which contains hint. + +Document highlight related~ + +Highlights used for highlighting same symbols in the buffer at the current +cursor position. + +*CocHighlightText* default symbol highlight. +*CocHighlightRead* for `Read` kind of document symbol. +*CocHighlightWrite* for `Write` kind of document symbol. + +Float window/popup related~ + +*CocFloating* default highlight group of floating windows/popups. +Default link to |NormalFloat| on neovim and|`Pmenu| on vim. +*CocErrorFloat* for errors in floating windows/popups. +*CocWarningFloat* for warnings in floating windows/popups. +*CocInfoFloat* for infos in floating windows/popups. +*CocHintFloat* for hints in floating windows/popups. + +List related~ + +*CocSelectedText* for sign text of selected lines. +*CocSelectedLine* for line highlight of selected lines. +*CocListMode* for mode in statusline of CocList. +*CocListPath* for current cwd in statusline of CocList. + +Tree view related~ + +CocTree* *CocTree* + +*CocTreeTitle* for title in tree view. +*CocTreeDescription* for description beside label. +*CocTreeOpenClose* for open and close icon in tree view. +*CocTreeSelected* for highlight lines contains selected node. + +Symbol icons~ + +CocSymbol* *CocSymbol* + +Highlight groups for symbol icons, including: + +*CocSymbolFile* +*CocSymbolModule* +*CocSymbolNamespace* +*CocSymbolPackage* +*CocSymbolClass* +*CocSymbolMethod* +*CocSymbolProperty* +*CocSymbolField* +*CocSymbolConstructor* +*CocSymbolEnum* +*CocSymbolInterface* +*CocSymbolFunction* +*CocSymbolVariable* +*CocSymbolConstant* +*CocSymbolString* +*CocSymbolNumber* +*CocSymbolBoolean* +*CocSymbolArray* +*CocSymbolObject* +*CocSymbolKey* +*CocSymbolNull* +*CocSymbolEnumMember* +*CocSymbolStruct* +*CocSymbolEvent* +*CocSymbolOperator* +*CocSymbolTypeParameter* +*CocSymbolDefault* + +Note: Use configuration `suggest.completionItemKindLabels` for customized icon +characters. + +Others~ + +*CocCodeLens* for virtual text of codeLens. +*CocCursorRange* for ranges of activated cursors. +*CocHoverRange* for range of current hovered symbol. +*CocMenuSel* for current menu item in menu dialog, works on neovim only since +vim doesn't support change highlight group of cursorline inside popup. +*CocSelectedRange* for highlight ranges of outgoing calls. + +Semantic highlights~ + +CocSem_* *CocSem* + + Used for words whose semantics are provided by the language server, which + typically analyzes source code more deeply than vim's builtin syntax parser. + + Basic defaults are provided for the "standard" token kinds, but any kind + supported by the server can be highlighted by creating the highlight group. + + Default (enabled by setting `g:coc_default_semantic_highlight_groups = 1`): + `hi default link CocSem_namespace Identifier` + `hi default link CocSem_type Type` + `hi default link CocSem_class Structure` + `hi default link CocSem_enum Type` + `hi default link CocSem_interface Type` + `hi default link CocSem_struct Structure` + `hi default link CocSem_typeParameter Type` + `hi default link CocSem_parameter Identifier` + `hi default link CocSem_variable Identifier` + `hi default link CocSem_property Identifier` + `hi default link CocSem_enumMember Constant` + `hi default link CocSem_event Identifier` + `hi default link CocSem_function Function` + `hi default link CocSem_method Function` + `hi default link CocSem_macro Macro` + `hi default link CocSem_keyword Keyword` + `hi default link CocSem_modifier StorageClass` + `hi default link CocSem_comment Comment` + `hi default link CocSem_string String` + `hi default link CocSem_number Number` + `hi default link CocSem_regexp Normal` + `hi default link CocSem_operator Operator` - Used for hints in floating windows/popups. +============================================================================== +TREE SUPPORT *coc-tree* -CocCursorRange *CocCursorRange* +Tree view is used for render outline and call hierarchy, following features +are supported: - Default: `hi default link CocCursorRange Search` +- Data update while keep tree node open/close state. +- Auto refresh on load error. +- Click open/close icon to toggle collapse state. +- Click node to invoke default command. +- Show tooltip in float window on |CursorHold| when possible. +- Key-mappings support |coc-tree-mappings| +- Optional multiple selection. +- Optional node reveal support. +- Optional fuzzy filter support. +- Provide api `window.createTreeView` for extensions. - Used for cursor ranges. +Check |coc-config-tree| for related configurations. -CocHoverRange *CocHoverRange* +The filetype is `'coctree'`, which can be used to overwrite buffer and window +options. - Default: `hi default link CocHoverRange Search` +Use variable |w:cocViewId| to detect the kind of tree. - Used for current hover range. +------------------------------------------------------------------------------ -CocMenuSel *CocMenuSel* +TREE KEY MAPPINGS *coc-tree-mappings* - Default: `hi default link CocMenuSel PmenuSel` +Default key-mappings are provided for 'coctree' buffer, which can be changed +by configuration |coc-config-tree|. - Used for current menu item in menu dialog, - works on neovim only since vim doesn't support change highlight - group of cursorline inside popup. + - Select/unselect item, configured by `"tree.key.toggleSelection"`. + - Invoke actions of current item, configured by `"tree.key.actions"`. + - Close tree window, configured by `"tree.key.close"`. + - Invoke command of current item, configured by `"tree.key.invoke"`. + - Move cursor to original window. +f - Activate filter, configured by `"tree.key.activeFilter"`. +t - Trigger key to toggle expand state of tree node, configured by + `tree.key.toggle`. +M - Collapse all tree node, configured by `"tree.key.collapseAll"`. -CocListMode *CocListMode* +------------------------------------------------------------------------------ - Default: `hi default link CocListMode ModeMsg` +TREE FILTER *coc-tree-filter* - Used for mode in statusline of CocList. +Filter mode is used for search for specific node by fuzzy filter, invoke the +key configured by `"tree.key.activeFilter"` to activate filter mode. -CocListPath *CocListPath* +Note: some tree views not have filter mode supported. - Default: `hi default link CocListPath Comment` +When filter mode is activated, type normal character to insert filter input +and following special keys are supported: - Used for current cwd in statusline of CocList. + - Delete last filter character when possible. + - Clean up filter text. + - Navigate to previous filter text (stored on command invoke). + - Navigate to next filter text (stored on command invoke). + - exit filter mode. + - exit filter mode. + or `"tree.key.selectPrevious"` - Select previous node. + or `"tree.key.selectNext"` - Select next node. + or `"key.key.invoke"` - Invoke command of selected node. ============================================================================== LIST SUPPORT *coc-list* @@ -2701,20 +2945,20 @@ Built-in list support to make working with lists of items easier. The following features are supported: -* Insert & normal mode. -* Default key-mappings for insert & normal mode. -* Customize key-mappings for insert & normal mode. -* Commands for reopening & doing actions with a previous list. -* Different match modes. -* Interactive mode. -* Auto preview on cursor move. -* Number select support. -* Built-in actions for locations. -* Parse ANSI code. -* Mouse support. -* Select actions using . -* Multiple selections using in normal mode. -* Select lines by visual selection. +- Insert & normal mode. +- Default key-mappings for insert & normal mode. +- Customize key-mappings for insert & normal mode. +- Commands for reopening & doing actions with a previous list. +- Different match modes. +- Interactive mode. +- Auto preview on cursor move. +- Number select support. +- Built-in actions for locations. +- Parse ANSI code. +- Mouse support. +- Select actions using . +- Multiple selections using in normal mode. +- Select lines by visual selection. ------------------------------------------------------------------------------ @@ -2722,7 +2966,7 @@ LIST COMMAND *coc-list-command* :CocList [{...options}] [{source}] [{...args}] *:CocList* - Open coc list of {source}, Ex: > + Open coc list of {source}, example: > :CocList --normal location < @@ -2842,12 +3086,21 @@ Use `coc-settings.json` for configuration of lists. The general configuration of list starts with 'list.'. Checkout |coc-config-list| or type `list.` in your settings file to get completion -list. +list (requires coc-json installed). For configuration of a specified list, use section that starts with: `list.source.{name}`, where `{name}` is the name of list. -Configure default options:~ +Change default action:~ + +If you want to use `tabe` as default action of symbols list, you can use: +> + // change default action of symbols + "list.source.symbols.defaultAction": "tabe" +< +in your coc-settings.json + +Change default options:~ Use `list.source.{name}.defaultOptions` setting like: > @@ -2855,12 +3108,12 @@ Use `list.source.{name}.defaultOptions` setting like: > "list.source.symbols.defaultOptions": ["--interactive", "--number-select"], < Note: some list like symbols only work in interactive mode, you must -include `--interactive` to `defaultOptions`. +include `--interactive` in `defaultOptions`. Note: default options will not be used when there're options passed with |:CocList| command. -Config default arguments:~ +Change default arguments:~ Use `list.source.{name}.defaultArgs` setting like: > @@ -2878,58 +3131,58 @@ LIST MAPPINGS *coc-list-mappings* Default mappings on insert mode: - - cancel list session. - - do default action with selected items or current item. - - stop loading task. - - paste text from system clipboard. - - reload list. - - change to normal mode. - - select next line. - - select previous line. - - move cursor left. - - move cursor right. - - move cursor to end of prompt. - - same as . - - move cursor to start of prompt. - - same as . - - scroll window forward. - - scroll window backward. - - remove previous character of cursor. - - remove previous character of cursor. - - remove previous word of cursor. - - remove characters before cursor. - - navigate to next input in history. - - navigate to previous input in history. - - switch matcher for filter items. - - insert content from Vim register. - - select action. + - Cancel list session. + - Do default action with selected items or current item. + - Stop loading task. + - Paste text from system clipboard. + - Reload list. + - Change to normal mode. + - Select next line. + - Select previous line. + - Move cursor left. + - Move cursor right. + - Move cursor to end of prompt. + - Same as . + - Move cursor to start of prompt. + - Same as . + - Scroll window forward. + - Scroll window backward. + - Remove previous character of cursor. + - Remove previous character of cursor. + - Remove previous word of cursor. + - Remove characters before cursor. + - Navigate to next input in history. + - Navigate to previous input in history. + - Switch matcher for filter items. + - Insert content from vim's register. + - Select action. Default mappings on normal mode: - - cancel list session. - - do default action with selected items or current item. - - stop source from fetching more items. - - reload list. - - mark all visible items selected. - - jump to original window on list create. - - select action. - - scroll preview window down. - - scroll preview window up. - - toggle select of current item. -i,I,o,O,a,A - change to insert mode. -p - preview action. -: - cancel list session without closing window. -? - show help of current list. -t - do 'tabe' action. -d - do 'drop' action. -s - do 'split' action. + - Cancel list session. + - Do default action with selected items or current item. + - Stop source from fetching more items. + - Reload list. + - Mark all visible items selected. + - Jump to original window on list create. + - Select action. + - Scroll preview window down. + - Scroll preview window up. + - Toggle select of current item. +i,I,o,O,a,A - Change to insert mode. +p - Preview action. +: - Cancel list session without closing window. +? - Show help of current list. +t - Do 'tabe' action. +d - Do 'drop' action. +s - Do 'split' action. Use |coc-list-mappings-custom| to override default mappings. *coc-list-mappings-custom* Configurations `"list.normalMappings"` and `"list.insertMappings"` are used -for customizing the list key-mappings, ex: > +for customizing the list key-mappings, example: > "list.insertMappings": { "": "do:refresh", @@ -2986,7 +3239,8 @@ The mapping expression should be `command:arguments`, available commands: 'paste' - append text from system clipboard to prompt. 'eval' - append text to prompt from result of VimL expression. 'action' - execute action of list, use to find available actions. -'feedkeys' - feedkeys to list window, use `\\` in JSON to escape special characters. +'feedkeys' - feedkeys to list window, use `\\` in JSON to escape special + characters. 'normal' - execute normal command in list window. 'normal!' - execute normal command without remap. 'command' - execute command. @@ -2997,7 +3251,7 @@ The mapping expression should be `command:arguments`, available commands: Context argument contains the following properties: -'name' - name of the list, ex: `'location'`. +'name' - name of the list, example: `'location'`. 'args' - arguments of the list. 'input' - current input of prompt. 'winid' - window id on list activated. @@ -3135,8 +3389,8 @@ See |coc-config-dialog| for available configurations. *coc-dialog-basic* -A basic dialog is create by 'window.showDialog' api, which is just some texts -with optional buttons. +A basic dialog is create by javascript api `window.showDialog` , which is just +some texts with optional buttons. ------------------------------------------------------------------------------ @@ -3222,7 +3476,7 @@ STATUSLINE SUPPORT *coc-status* Diagnostics info and other status info contributed by extensions could be shown in statusline. -The easiest way is add `%{coc#status()}` to your 'statusline' option. Ex: > +The easiest way is add `%{coc#status()}` to your 'statusline' option. Example: > set statusline^=%{coc#status()} > diff --git a/vim-config/plugins/coc.nvim/doc/tags b/vim-config/plugins/coc.nvim/doc/tags index d1e0e370..faba9333 100644 --- a/vim-config/plugins/coc.nvim/doc/tags +++ b/vim-config/plugins/coc.nvim/doc/tags @@ -15,6 +15,7 @@ :CocLocalConfig coc.txt /*:CocLocalConfig* :CocNext coc.txt /*:CocNext* :CocOpenLog coc.txt /*:CocOpenLog* +:CocOutline coc.txt /*:CocOutline* :CocPrev coc.txt /*:CocPrev* :CocRebuild coc.txt /*:CocRebuild* :CocRestart coc.txt /*:CocRestart* @@ -24,11 +25,107 @@ :CocUpdate coc.txt /*:CocUpdate* :CocUpdateSync coc.txt /*:CocUpdateSync* :CocWatch coc.txt /*:CocWatch* +(coc-classobj-i) coc.txt /*(coc-classobj-i)* +(coc-cursors-position) coc.txt /*(coc-cursors-position)* +(coc-cursors-word) coc.txt /*(coc-cursors-word)* +(coc-funcobj-a) coc.txt /*(coc-funcobj-a)* +(Coc-codeaction-selected) coc.txt /*(Coc-codeaction-selected)* +(coc-classobj-a) coc.txt /*(coc-classobj-a)* +(coc-codeaction) coc.txt /*(coc-codeaction)* +(coc-codeaction-cursor) coc.txt /*(coc-codeaction-cursor)* +(coc-codeaction-line) coc.txt /*(coc-codeaction-line)* +(coc-codelens-action) coc.txt /*(coc-codelens-action)* +(coc-command-repeat) coc.txt /*(coc-command-repeat)* +(coc-cursors-operator) coc.txt /*(coc-cursors-operator)* +(coc-cursors-range) coc.txt /*(coc-cursors-range)* +(coc-declaration) coc.txt /*(coc-declaration)* +(coc-definition) coc.txt /*(coc-definition)* +(coc-diagnostic-info) coc.txt /*(coc-diagnostic-info)* +(coc-diagnostic-next) coc.txt /*(coc-diagnostic-next)* +(coc-diagnostic-next-error) coc.txt /*(coc-diagnostic-next-error)* +(coc-diagnostic-prev) coc.txt /*(coc-diagnostic-prev)* +(coc-diagnostic-prev-error) coc.txt /*(coc-diagnostic-prev-error)* +(coc-fix-current) coc.txt /*(coc-fix-current)* +(coc-float-hide) coc.txt /*(coc-float-hide)* +(coc-float-jump) coc.txt /*(coc-float-jump)* +(coc-format) coc.txt /*(coc-format)* +(coc-format-selected) coc.txt /*(coc-format-selected)* +(coc-funcobj-i) coc.txt /*(coc-funcobj-i)* +(coc-implementation) coc.txt /*(coc-implementation)* +(coc-openlink) coc.txt /*(coc-openlink)* +(coc-range-select) coc.txt /*(coc-range-select)* +(coc-range-select-backward) coc.txt /*(coc-range-select-backward)* +(coc-refactor) coc.txt /*(coc-refactor)* +(coc-references) coc.txt /*(coc-references)* +(coc-references-used) coc.txt /*(coc-references-used)* +(coc-rename) coc.txt /*(coc-rename)* +(coc-type-definition) coc.txt /*(coc-type-definition)* +CocAction('activeExtension') coc.txt /*CocAction('activeExtension')* +CocAction('addRanges') coc.txt /*CocAction('addRanges')* +CocAction('codeAction') coc.txt /*CocAction('codeAction')* +CocAction('codeActionRange') coc.txt /*CocAction('codeActionRange')* +CocAction('codeActions') coc.txt /*CocAction('codeActions')* +CocAction('codeLensAction') coc.txt /*CocAction('codeLensAction')* +CocAction('colorPresentation') coc.txt /*CocAction('colorPresentation')* +CocAction('commands') coc.txt /*CocAction('commands')* +CocAction('deactivateExtension') coc.txt /*CocAction('deactivateExtension')* +CocAction('definitionHover') coc.txt /*CocAction('definitionHover')* +CocAction('diagnosticInfo') coc.txt /*CocAction('diagnosticInfo')* +CocAction('diagnosticList') coc.txt /*CocAction('diagnosticList')* +CocAction('diagnosticPreview') coc.txt /*CocAction('diagnosticPreview')* +CocAction('diagnosticRefresh') coc.txt /*CocAction('diagnosticRefresh')* +CocAction('diagnosticToggle') coc.txt /*CocAction('diagnosticToggle')* +CocAction('diagnosticToggleBuffer') coc.txt /*CocAction('diagnosticToggleBuffer')* +CocAction('doCodeAction') coc.txt /*CocAction('doCodeAction')* +CocAction('doHover') coc.txt /*CocAction('doHover')* +CocAction('doQuickfix') coc.txt /*CocAction('doQuickfix')* +CocAction('documentSymbols') coc.txt /*CocAction('documentSymbols')* +CocAction('ensureDocument') coc.txt /*CocAction('ensureDocument')* +CocAction('extensionStats') coc.txt /*CocAction('extensionStats')* +CocAction('fixAll') coc.txt /*CocAction('fixAll')* +CocAction('fold') coc.txt /*CocAction('fold')* +CocAction('format') coc.txt /*CocAction('format')* +CocAction('formatSelected') coc.txt /*CocAction('formatSelected')* +CocAction('getCurrentFunctionSymbol') coc.txt /*CocAction('getCurrentFunctionSymbol')* +CocAction('getHover') coc.txt /*CocAction('getHover')* +CocAction('getWordEdit') coc.txt /*CocAction('getWordEdit')* +CocAction('hideOutline') coc.txt /*CocAction('hideOutline')* +CocAction('highlight') coc.txt /*CocAction('highlight')* +CocAction('incomingCalls') coc.txt /*CocAction('incomingCalls')* +CocAction('jumpDeclaration') coc.txt /*CocAction('jumpDeclaration')* +CocAction('jumpDefinition') coc.txt /*CocAction('jumpDefinition')* +CocAction('jumpImplementation') coc.txt /*CocAction('jumpImplementation')* +CocAction('jumpReferences') coc.txt /*CocAction('jumpReferences')* +CocAction('jumpTypeDefinition') coc.txt /*CocAction('jumpTypeDefinition')* +CocAction('openlink') coc.txt /*CocAction('openlink')* +CocAction('organizeImport') coc.txt /*CocAction('organizeImport')* +CocAction('outgoingCalls') coc.txt /*CocAction('outgoingCalls')* +CocAction('pickColor') coc.txt /*CocAction('pickColor')* +CocAction('quickfixes') coc.txt /*CocAction('quickfixes')* +CocAction('refactor') coc.txt /*CocAction('refactor')* +CocAction('refreshSource') coc.txt /*CocAction('refreshSource')* +CocAction('reloadExtension') coc.txt /*CocAction('reloadExtension')* +CocAction('rename') coc.txt /*CocAction('rename')* +CocAction('resolveWorkspaceSymbol') coc.txt /*CocAction('resolveWorkspaceSymbol')* +CocAction('runCommand') coc.txt /*CocAction('runCommand')* +CocAction('selectionRanges') coc.txt /*CocAction('selectionRanges')* +CocAction('services') coc.txt /*CocAction('services')* +CocAction('showIncomingCalls') coc.txt /*CocAction('showIncomingCalls')* +CocAction('showOutgoingCalls') coc.txt /*CocAction('showOutgoingCalls')* +CocAction('showOutline') coc.txt /*CocAction('showOutline')* +CocAction('showSignatureHelp') coc.txt /*CocAction('showSignatureHelp')* +CocAction('sourceStat') coc.txt /*CocAction('sourceStat')* +CocAction('toggleExtension') coc.txt /*CocAction('toggleExtension')* +CocAction('toggleService') coc.txt /*CocAction('toggleService')* +CocAction('toggleSource') coc.txt /*CocAction('toggleSource')* +CocAction('uninstallExtension') coc.txt /*CocAction('uninstallExtension')* CocAction() coc.txt /*CocAction()* +CocAction(getWorkspaceSymbols) coc.txt /*CocAction(getWorkspaceSymbols)* CocActionAsync() coc.txt /*CocActionAsync()* CocBold coc.txt /*CocBold* CocCodeLens coc.txt /*CocCodeLens* CocCursorRange coc.txt /*CocCursorRange* +CocDeprecatedHighlight coc.txt /*CocDeprecatedHighlight* CocDiagnosticChange coc.txt /*CocDiagnosticChange* CocErrorFloat coc.txt /*CocErrorFloat* CocErrorHighlight coc.txt /*CocErrorHighlight* @@ -66,14 +163,53 @@ CocMenuSel coc.txt /*CocMenuSel* CocNotify() coc.txt /*CocNotify()* CocNvimInit coc.txt /*CocNvimInit* CocOpenFloat coc.txt /*CocOpenFloat* +CocOpenFloatPrompt coc.txt /*CocOpenFloatPrompt* CocRegistNotification() coc.txt /*CocRegistNotification()* CocRequest() coc.txt /*CocRequest()* CocRequestAsync() coc.txt /*CocRequestAsync()* +CocSelectedLine coc.txt /*CocSelectedLine* +CocSelectedRange coc.txt /*CocSelectedRange* +CocSelectedText coc.txt /*CocSelectedText* +CocSem coc.txt /*CocSem* CocStatusChange coc.txt /*CocStatusChange* CocStrikeThrough coc.txt /*CocStrikeThrough* +CocSymbol coc.txt /*CocSymbol* +CocSymbolArray coc.txt /*CocSymbolArray* +CocSymbolBoolean coc.txt /*CocSymbolBoolean* +CocSymbolClass coc.txt /*CocSymbolClass* +CocSymbolConstant coc.txt /*CocSymbolConstant* +CocSymbolConstructor coc.txt /*CocSymbolConstructor* +CocSymbolDefault coc.txt /*CocSymbolDefault* +CocSymbolEnum coc.txt /*CocSymbolEnum* +CocSymbolEnumMember coc.txt /*CocSymbolEnumMember* +CocSymbolEvent coc.txt /*CocSymbolEvent* +CocSymbolField coc.txt /*CocSymbolField* +CocSymbolFile coc.txt /*CocSymbolFile* +CocSymbolFunction coc.txt /*CocSymbolFunction* +CocSymbolInterface coc.txt /*CocSymbolInterface* +CocSymbolKey coc.txt /*CocSymbolKey* +CocSymbolMethod coc.txt /*CocSymbolMethod* +CocSymbolModule coc.txt /*CocSymbolModule* +CocSymbolNamespace coc.txt /*CocSymbolNamespace* +CocSymbolNull coc.txt /*CocSymbolNull* +CocSymbolNumber coc.txt /*CocSymbolNumber* +CocSymbolObject coc.txt /*CocSymbolObject* +CocSymbolOperator coc.txt /*CocSymbolOperator* +CocSymbolPackage coc.txt /*CocSymbolPackage* +CocSymbolProperty coc.txt /*CocSymbolProperty* +CocSymbolString coc.txt /*CocSymbolString* +CocSymbolStruct coc.txt /*CocSymbolStruct* +CocSymbolTypeParameter coc.txt /*CocSymbolTypeParameter* +CocSymbolVariable coc.txt /*CocSymbolVariable* CocTagFunc() coc.txt /*CocTagFunc()* CocTerminalOpen coc.txt /*CocTerminalOpen* +CocTree coc.txt /*CocTree* +CocTreeDescription coc.txt /*CocTreeDescription* +CocTreeOpenClose coc.txt /*CocTreeOpenClose* +CocTreeSelected coc.txt /*CocTreeSelected* +CocTreeTitle coc.txt /*CocTreeTitle* CocUnderline coc.txt /*CocUnderline* +CocUnusedHighlight coc.txt /*CocUnusedHighlight* CocWarningFloat coc.txt /*CocWarningFloat* CocWarningHighlight coc.txt /*CocWarningHighlight* CocWarningLine coc.txt /*CocWarningLine* @@ -109,77 +245,30 @@ coc#util#extension_root() coc.txt /*coc#util#extension_root()* coc#util#get_config() coc.txt /*coc#util#get_config()* coc#util#get_config_home() coc.txt /*coc#util#get_config_home()* coc#util#get_data_home() coc.txt /*coc#util#get_data_home()* -coc#util#install() coc.txt /*coc#util#install()* coc#util#job_command() coc.txt /*coc#util#job_command()* coc#util#rebuild() coc.txt /*coc#util#rebuild()* coc#util#root_patterns() coc.txt /*coc#util#root_patterns()* -coc-action coc.txt /*coc-action* -coc-action-activeExtension coc.txt /*coc-action-activeExtension* -coc-action-addRanges coc.txt /*coc-action-addRanges* -coc-action-codeAction coc.txt /*coc-action-codeAction* -coc-action-codeActionRange coc.txt /*coc-action-codeActionRange* -coc-action-codeActions coc.txt /*coc-action-codeActions* -coc-action-codeLensAction coc.txt /*coc-action-codeLensAction* -coc-action-colorPresentation coc.txt /*coc-action-colorPresentation* -coc-action-commands coc.txt /*coc-action-commands* -coc-action-deactivateExtension coc.txt /*coc-action-deactivateExtension* -coc-action-diagnosticInfo coc.txt /*coc-action-diagnosticInfo* -coc-action-diagnosticList coc.txt /*coc-action-diagnosticList* -coc-action-diagnosticPreview coc.txt /*coc-action-diagnosticPreview* -coc-action-diagnosticToggle coc.txt /*coc-action-diagnosticToggle* -coc-action-doCodeAction coc.txt /*coc-action-doCodeAction* -coc-action-doHover coc.txt /*coc-action-doHover* -coc-action-doQuickfix coc.txt /*coc-action-doQuickfix* -coc-action-documentSymbols coc.txt /*coc-action-documentSymbols* -coc-action-ensureDocument coc.txt /*coc-action-ensureDocument* -coc-action-extensionStats coc.txt /*coc-action-extensionStats* -coc-action-fixAll coc.txt /*coc-action-fixAll* -coc-action-fold coc.txt /*coc-action-fold* -coc-action-format coc.txt /*coc-action-format* -coc-action-formatSelected coc.txt /*coc-action-formatSelected* -coc-action-getCurrentFunctionSymbol coc.txt /*coc-action-getCurrentFunctionSymbol* -coc-action-getHover coc.txt /*coc-action-getHover* -coc-action-getWordEdit coc.txt /*coc-action-getWordEdit* -coc-action-getWorkspaceSymbols coc.txt /*coc-action-getWorkspaceSymbols* -coc-action-highlight coc.txt /*coc-action-highlight* -coc-action-jumpDeclaration coc.txt /*coc-action-jumpDeclaration* -coc-action-jumpDefinition coc.txt /*coc-action-jumpDefinition* -coc-action-jumpImplementation coc.txt /*coc-action-jumpImplementation* -coc-action-jumpReferences coc.txt /*coc-action-jumpReferences* -coc-action-jumpTypeDefinition coc.txt /*coc-action-jumpTypeDefinition* -coc-action-openlink coc.txt /*coc-action-openlink* -coc-action-organizeImport coc.txt /*coc-action-organizeImport* -coc-action-pickColor coc.txt /*coc-action-pickColor* -coc-action-quickfixes coc.txt /*coc-action-quickfixes* -coc-action-refreshSource coc.txt /*coc-action-refreshSource* -coc-action-reloadExtension coc.txt /*coc-action-reloadExtension* -coc-action-rename coc.txt /*coc-action-rename* -coc-action-runCommand coc.txt /*coc-action-runCommand* -coc-action-selectionRanges coc.txt /*coc-action-selectionRanges* -coc-action-services coc.txt /*coc-action-services* -coc-action-showSignatureHelp coc.txt /*coc-action-showSignatureHelp* -coc-action-sourceStat coc.txt /*coc-action-sourceStat* -coc-action-toggleDiagnosticBuffer coc.txt /*coc-action-toggleDiagnosticBuffer* -coc-action-toggleExtension coc.txt /*coc-action-toggleExtension* -coc-action-toggleService coc.txt /*coc-action-toggleService* -coc-action-toggleSource coc.txt /*coc-action-toggleSource* -coc-action-uninstallExtension coc.txt /*coc-action-uninstallExtension* +coc-actions coc.txt /*coc-actions* coc-autocmds coc.txt /*coc-autocmds* coc-commands coc.txt /*coc-commands* coc-completion coc.txt /*coc-completion* +coc-config-callHierarchy coc.txt /*coc-config-callHierarchy* coc-config-codelens coc.txt /*coc-config-codelens* coc-config-cursors coc.txt /*coc-config-cursors* coc-config-diagnostic coc.txt /*coc-config-diagnostic* coc-config-dialog coc.txt /*coc-config-dialog* +coc-config-float coc.txt /*coc-config-float* coc-config-hover coc.txt /*coc-config-hover* coc-config-http coc.txt /*coc-config-http* coc-config-languageserver coc.txt /*coc-config-languageserver* coc-config-list coc.txt /*coc-config-list* coc-config-notification coc.txt /*coc-config-notification* coc-config-npm coc.txt /*coc-config-npm* +coc-config-outline coc.txt /*coc-config-outline* coc-config-preferences coc.txt /*coc-config-preferences* coc-config-refactor coc.txt /*coc-config-refactor* coc-config-suggest coc.txt /*coc-config-suggest* +coc-config-tree coc.txt /*coc-config-tree* coc-configuration coc.txt /*coc-configuration* coc-contents coc.txt /*coc-contents* coc-custom-source coc.txt /*coc-custom-source* @@ -221,6 +310,9 @@ coc-status coc.txt /*coc-status* coc-status-airline coc.txt /*coc-status-airline* coc-status-lightline coc.txt /*coc-status-lightline* coc-status-manual coc.txt /*coc-status-manual* +coc-tree coc.txt /*coc-tree* +coc-tree-filter coc.txt /*coc-tree-filter* +coc-tree-mappings coc.txt /*coc-tree-mappings* coc-variables coc.txt /*coc-variables* g:WorkspaceFolders coc.txt /*g:WorkspaceFolders* g:coc_border_joinchars coc.txt /*g:coc_border_joinchars* @@ -234,7 +326,6 @@ g:coc_disable_uncaught_error coc.txt /*g:coc_disable_uncaught_error* g:coc_enable_locationlist coc.txt /*g:coc_enable_locationlist* g:coc_filetype_map coc.txt /*g:coc_filetype_map* g:coc_global_extensions coc.txt /*g:coc_global_extensions* -g:coc_install_yarn_cmd coc.txt /*g:coc_install_yarn_cmd* g:coc_jump_locations coc.txt /*g:coc_jump_locations* g:coc_last_float_win coc.txt /*g:coc_last_float_win* g:coc_last_hover_message coc.txt /*g:coc_last_hover_message* @@ -245,6 +336,7 @@ g:coc_process_pid coc.txt /*g:coc_process_pid* g:coc_prompt_win_width coc.txt /*g:coc_prompt_win_width* g:coc_quickfix_open_command coc.txt /*g:coc_quickfix_open_command* g:coc_selectmode_mapping coc.txt /*g:coc_selectmode_mapping* +g:coc_service_initialized coc.txt /*g:coc_service_initialized* g:coc_snippet_next coc.txt /*g:coc_snippet_next* g:coc_snippet_prev coc.txt /*g:coc_snippet_prev* g:coc_sources_disable_map coc.txt /*g:coc_sources_disable_map* @@ -252,44 +344,8 @@ g:coc_start_at_startup coc.txt /*g:coc_start_at_startup* g:coc_status coc.txt /*g:coc_status* g:coc_status_error_sign coc.txt /*g:coc_status_error_sign* g:coc_status_warning_sign coc.txt /*g:coc_status_warning_sign* +g:coc_text_prop_offset coc.txt /*g:coc_text_prop_offset* g:coc_uri_prefix_replace_patterns coc.txt /*g:coc_uri_prefix_replace_patterns* g:coc_user_config coc.txt /*g:coc_user_config* g:node_client_debug coc.txt /*g:node_client_debug* -health#coc#check() coc.txt /*health#coc#check()* -n_coc-classobj-a coc.txt /*n_coc-classobj-a* -n_coc-classobj-i coc.txt /*n_coc-classobj-i* -n_coc-codeaction coc.txt /*n_coc-codeaction* -n_coc-codeaction-cursor coc.txt /*n_coc-codeaction-cursor* -n_coc-codeaction-line coc.txt /*n_coc-codeaction-line* -n_coc-codeaction-selected coc.txt /*n_coc-codeaction-selected* -n_coc-codelens-action coc.txt /*n_coc-codelens-action* -n_coc-declaration coc.txt /*n_coc-declaration* -n_coc-definition coc.txt /*n_coc-definition* -n_coc-diagnostic-info coc.txt /*n_coc-diagnostic-info* -n_coc-diagnostic-next coc.txt /*n_coc-diagnostic-next* -n_coc-diagnostic-next-error coc.txt /*n_coc-diagnostic-next-error* -n_coc-diagnostic-prev coc.txt /*n_coc-diagnostic-prev* -n_coc-diagnostic-prev-error coc.txt /*n_coc-diagnostic-prev-error* -n_coc-fix-current coc.txt /*n_coc-fix-current* -n_coc-float-hide coc.txt /*n_coc-float-hide* -n_coc-float-jump coc.txt /*n_coc-float-jump* -n_coc-format coc.txt /*n_coc-format* -n_coc-format-selected coc.txt /*n_coc-format-selected* -n_coc-funcobj-a coc.txt /*n_coc-funcobj-a* -n_coc-funcobj-i coc.txt /*n_coc-funcobj-i* -n_coc-implementation coc.txt /*n_coc-implementation* -n_coc-openlink coc.txt /*n_coc-openlink* -n_coc-range-select coc.txt /*n_coc-range-select* -n_coc-refactor coc.txt /*n_coc-refactor* -n_coc-references coc.txt /*n_coc-references* -n_coc-references-used coc.txt /*n_coc-references-used* -n_coc-rename coc.txt /*n_coc-rename* -n_coc-type-definition coc.txt /*n_coc-type-definition* -v_coc-classobj-a coc.txt /*v_coc-classobj-a* -v_coc-classobj-i coc.txt /*v_coc-classobj-i* -v_coc-codeaction-selected coc.txt /*v_coc-codeaction-selected* -v_coc-format-selected coc.txt /*v_coc-format-selected* -v_coc-funcobj-a coc.txt /*v_coc-funcobj-a* -v_coc-funcobj-i coc.txt /*v_coc-funcobj-i* -v_coc-range-select coc.txt /*v_coc-range-select* -v_coc-range-select-backward coc.txt /*v_coc-range-select-backward* +http.proxy coc.txt /*http.proxy* diff --git a/vim-config/plugins/coc.nvim/esbuild.js b/vim-config/plugins/coc.nvim/esbuild.js new file mode 100755 index 00000000..9ab20185 --- /dev/null +++ b/vim-config/plugins/coc.nvim/esbuild.js @@ -0,0 +1,75 @@ +const cp = require('child_process') +const fs = require('fs') +const path = require('path') +let revision = '' +try { + let res = cp.execSync('git rev-parse HEAD', {encoding: 'utf8'}) + revision = res.trim().slice(0, 10) +} catch (e) { + // ignore +} + +let envPlugin = { + name: 'env', + setup(build) { + build.onResolve({filter: /\/appenders/}, args => { + let fullpath = path.join(args.resolveDir, args.path) + return { + path: path.relative(__dirname, fullpath).replace(/\\/g, '/'), + namespace: 'env-ns' + } + }) + build.onLoad({filter: /^node_modules\/log4js\/lib\/appenders$/, namespace: 'env-ns'}, args => { + let content = fs.readFileSync(path.join(args.path, 'index.js'), 'utf8') + return { + contents: content.replace(/require\.main/g, '""'), + resolveDir: args.path + } + }) + } +} + +async function start(watch) { + await require('esbuild').build({ + entryPoints: ['src/main.ts'], + bundle: true, + watch, + minify: process.env.NODE_ENV === 'production', + sourcemap: process.env.NODE_ENV === 'development', + define: {REVISION: '"' + revision + '"', ESBUILD: 'true'}, + mainFields: ['module', 'main'], + platform: 'node', + target: 'node12.12', + outfile: 'build/index.js', + banner: { + js: `(function () { + var v = process.version + var parts = v.slice(1).split('.') + var major = parseInt(parts[0], 10) + var minor = parseInt(parts[1], 10) + if (major < 12 || (major == 12 && minor < 12)) { + throw new Error('coc.nvim requires node >= v12.12.0, current version: ' + v) + } +})(); ` + }, + plugins: [envPlugin] + }) +} + +let watch = false +if (process.argv.length > 2 && process.argv[2] === '--watch') { + console.log('watching...') + watch = { + onRebuild(error) { + if (error) { + console.error('watch build failed:', error) + } else { + console.log('watch build succeeded') + } + }, + } +} + +start(watch).catch(e => { + console.error(e) +}) diff --git a/vim-config/plugins/coc.nvim/jest.js b/vim-config/plugins/coc.nvim/jest.js new file mode 100644 index 00000000..97e40400 --- /dev/null +++ b/vim-config/plugins/coc.nvim/jest.js @@ -0,0 +1,17 @@ +const path = require('path') +const os = require('os') +const fs = require('fs') + +process.on('uncaughtException', function (err) { + let msg = 'Uncaught exception: ' + err.stack + console.error(msg) +}) + +module.exports = async () => { + let dataHome = path.join(os.tmpdir(), `coc-test/${process.pid}`) + fs.mkdirSync(dataHome, {recursive: true}) + process.env.NODE_ENV = 'test' + process.env.COC_DATA_HOME = dataHome + process.env.COC_VIMCONFIG = path.join(__dirname, 'src/__tests__') + process.env.TMPDIR = '/tmp/coc-test' +} diff --git a/vim-config/plugins/coc.nvim/package.json b/vim-config/plugins/coc.nvim/package.json index e704458b..04a4872d 100644 --- a/vim-config/plugins/coc.nvim/package.json +++ b/vim-config/plugins/coc.nvim/package.json @@ -1,12 +1,20 @@ { - "name": "coc.nvim", + "name": "coc.nvim-master", "version": "0.0.80", "description": "LSP based intellisense engine for neovim & vim8.", "main": "./lib/index.js", "engines": { - "node": ">=8.10.0" + "node": ">=12.12.0" + }, + "scripts": { + "clean": "rimraf lib build", + "lint": "eslint . --ext .ts --quiet", + "lint:typecheck": "tsc -p tsconfig.json", + "build": "node esbuild.js", + "test": "./node_modules/.bin/jest --forceExit", + "test-build": "./node_modules/.bin/jest --coverage --forceExit", + "prepare": "node esbuild.js" }, - "scripts": {}, "repository": { "type": "git", "url": "git+https://github.com/neoclide/coc.nvim.git" @@ -32,6 +40,13 @@ "clearMocks": true, "globalSetup": "./jest.js", "testEnvironment": "node", + "coveragePathIgnorePatterns": [ + "/src/__tests__/*" + ], + "coverageReporters": [ + "text", + "lcov" + ], "moduleFileExtensions": [ "ts", "tsx", @@ -44,7 +59,63 @@ "testRegex": "src/__tests__/.*\\.(test|spec)\\.ts$", "coverageDirectory": "./coverage/" }, - "devDependencies": {}, - "dependencies": {} + "devDependencies": { + "@types/cli-table": "^0.3.0", + "@types/debounce": "^3.0.0", + "@types/fb-watchman": "^2.0.0", + "@types/fs-extra": "^9.0.6", + "@types/jest": "^27.0.1", + "@types/marked": "^2.0.4", + "@types/minimatch": "^3.0.3", + "@types/mkdirp": "^1.0.1", + "@types/node": "12.12.12", + "@types/semver": "^7.3.4", + "@types/tar": "^4.0.5", + "@types/uuid": "^8.3.0", + "@types/which": "^1.3.2", + "@typescript-eslint/eslint-plugin": "^4.11.1", + "@typescript-eslint/parser": "^4.11.1", + "bser": "^2.1.1", + "esbuild": "^0.12.7", + "eslint": "^7.15.0", + "eslint-plugin-jest": "^24.1.3", + "eslint-plugin-jsdoc": "^30.7.13", + "jest": "27.0.6", + "ts-jest": "^27.0.5", + "typescript": "^4.3.5", + "vscode-languageserver": "7.0.0" + }, + "dependencies": { + "@chemzqm/neovim": "^5.4.0", + "bytes": "^3.1.0", + "tslib": "^2.0.3", + "ansi-styles": "^5.0.0", + "cli-table": "^0.3.4", + "debounce": "^1.2.0", + "fast-diff": "^1.2.0", + "fb-watchman": "^2.0.1", + "fs-extra": "^9.0.1", + "follow-redirects": "^1.13.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "isuri": "^2.0.3", + "jsonc-parser": "^3.0.0", + "log4js": "^6.3.0", + "marked": "^2.1.3", + "minimatch": "^3.0.4", + "rc": "^1.2.8", + "semver": "^7.3.2", + "strip-ansi": "^6.0.0", + "tar": "^6.1.9", + "unzip-stream": "^0.3.1", + "content-disposition": "^0.5.3", + "decompress-response": "^6.0.0", + "uuid": "^7.0.3", + "which": "^2.0.2", + "vscode-uri": "^2.1.2", + "vscode-jsonrpc": "^6.0.0", + "vscode-languageserver-protocol": "^3.16.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0" + } } - diff --git a/vim-config/plugins/coc.nvim/plugin/coc.vim b/vim-config/plugins/coc.nvim/plugin/coc.vim index ff6790aa..66f995d1 100644 --- a/vim-config/plugins/coc.nvim/plugin/coc.vim +++ b/vim-config/plugins/coc.nvim/plugin/coc.vim @@ -39,7 +39,6 @@ endfunction call s:checkVersion() let g:did_coc_loaded = 1 -let g:coc_workspace_initialized = 0 let g:coc_service_initialized = 0 let s:is_win = has('win32') || has('win64') let s:root = expand(':h:h') @@ -169,6 +168,20 @@ function! s:OpenConfig() end endif execute 'edit '.home.'/coc-settings.json' + call coc#rpc#notify('checkJsonExtension', []) +endfunction + +function! s:get_color(item, fallback) abort + let t = type(a:item) + if t == 1 + return a:item + endif + if t == 4 + let item = get(a:item, 'gui', {}) + let color = get(item, &background, a:fallback) + return type(color) == 1 ? color : a:fallback + endif + return a:fallback endfunction function! s:AddAnsiGroups() abort @@ -178,26 +191,26 @@ function! s:AddAnsiGroups() abort for i in range(0, len(names) - 1) let name = names[i] if exists('g:terminal_ansi_colors') - let color_map[name] = get(g:terminal_ansi_colors, i, colors[i]) + let color_map[name] = s:get_color(get(g:terminal_ansi_colors, i, colors[i]), colors[i]) else let color_map[name] = get(g:, 'terminal_color_'.i, colors[i]) endif endfor - for name in keys(color_map) - let foreground = toupper(name[0]).name[1:] - let foregroundColor = color_map[name] - for key in keys(color_map) - let background = toupper(key[0]).key[1:] - let backgroundColor = color_map[key] - exe 'hi default CocList'.foreground.background.' guifg='.foregroundColor.' guibg='.backgroundColor - endfor - try + try + for name in keys(color_map) + let foreground = toupper(name[0]).name[1:] + let foregroundColor = color_map[name] + for key in keys(color_map) + let background = toupper(key[0]).key[1:] + let backgroundColor = color_map[key] + exe 'hi default CocList'.foreground.background.' guifg='.foregroundColor.' guibg='.backgroundColor + endfor exe 'hi default CocListFg'.foreground. ' guifg='.foregroundColor. ' ctermfg='.foreground exe 'hi default CocListBg'.foreground. ' guibg='.foregroundColor. ' ctermbg='.foreground - catch /.*/ - " ignore invalid color - endtry - endfor + endfor + catch /.*/ + " ignore invalid color + endtry endfunction function! s:CursorRangeFromSelected(type, ...) abort @@ -230,21 +243,17 @@ function! s:Disable() abort endfunction function! s:Autocmd(...) abort - if !g:coc_workspace_initialized + if !g:coc_service_initialized return endif call coc#rpc#notify('CocAutocmd', a:000) endfunction function! s:SyncAutocmd(...) - if !g:coc_workspace_initialized + if !g:coc_service_initialized return endif - if g:coc_service_initialized - call coc#rpc#request('CocAutocmd', a:000) - else - call coc#rpc#notify('CocAutocmd', a:000) - endif + call coc#rpc#request('CocAutocmd', a:000) endfunction function! s:Enable(initialize) @@ -283,6 +292,7 @@ function! s:Enable(initialize) autocmd WinEnter * call coc#float#nvim_win_enter(win_getid()) if exists('##WinClosed') autocmd WinClosed * call coc#float#close_related(+expand('')) + autocmd WinClosed * call s:Autocmd('WinClosed', +expand('')) endif endif if has('nvim-0.4.0') || has('patch-8.1.1719') @@ -294,7 +304,7 @@ function! s:Enable(initialize) autocmd BufWinEnter * call s:Autocmd('BufWinEnter', +expand(''), win_getid()) autocmd FileType * call s:Autocmd('FileType', expand(''), +expand('')) autocmd CompleteDone * call s:Autocmd('CompleteDone', get(v:, 'completed_item', {})) - autocmd InsertCharPre * call s:Autocmd('InsertCharPre', v:char) + autocmd InsertCharPre * call s:Autocmd('InsertCharPre', v:char, bufnr('%')) if exists('##TextChangedP') autocmd TextChangedP * call s:Autocmd('TextChangedP', +expand(''), {'lnum': line('.'), 'col': col('.'), 'pre': strpart(getline('.'), 0, col('.') - 1), 'changedtick': b:changedtick}) endif @@ -313,6 +323,7 @@ function! s:Enable(initialize) autocmd BufUnload * call s:Autocmd('BufUnload', +expand('')) autocmd BufWritePre * call s:SyncAutocmd('BufWritePre', +expand('')) autocmd FocusGained * if mode() !~# '^c' | call s:Autocmd('FocusGained') | endif + autocmd FocusLost * call s:Autocmd('FocusLost') autocmd VimResized * call s:Autocmd('VimResized', &columns, &lines) autocmd VimLeavePre * let g:coc_vim_leaving = 1 autocmd BufReadCmd,FileReadCmd,SourceCmd list://* call coc#list#setup(expand('')) @@ -337,9 +348,13 @@ function! s:Hi() abort hi default CocUnderline cterm=underline gui=underline hi default CocBold term=bold cterm=bold gui=bold hi default CocItalic term=italic cterm=italic gui=italic - hi default CocStrikeThrough guifg=#989898 ctermfg=gray cterm=strikethrough gui=strikethrough - hi default CocFadeOut guifg=#928374 ctermfg=245 + if s:is_vim || has('nvim-0.4.0') + hi default CocStrikeThrough cterm=strikethrough gui=strikethrough + else + hi default CocStrikeThrough guifg=#989898 ctermfg=gray + endif hi default CocMarkdownLink ctermfg=Blue guifg=#15aabf guibg=NONE + hi default link CocFadeOut Conceal hi default link CocMarkdownCode markdownCode hi default link CocMarkdownHeader markdownH1 hi default link CocMenuSel PmenuSel @@ -351,6 +366,8 @@ function! s:Hi() abort hi default link CocWarningHighlight CocUnderline hi default link CocInfoHighlight CocUnderline hi default link CocHintHighlight CocUnderline + hi default link CocDeprecatedHighlight CocStrikeThrough + hi default link CocUnusedHighlight CocFadeOut hi default link CocListMode ModeMsg hi default link CocListPath Comment hi default link CocHighlightText CursorColumn @@ -358,6 +375,41 @@ function! s:Hi() abort hi default link CocCursorRange Search hi default link CocHighlightRead CocHighlightText hi default link CocHighlightWrite CocHighlightText + " Tree view highlights + hi default link CocTreeTitle Title + hi default link CocTreeDescription Comment + hi default link CocTreeOpenClose CocBold + hi default link CocTreeSelected CursorLine + hi default link CocSelectedRange CocHighlightText + " Symbol highlights + hi default link CocSymbolDefault MoreMsg + hi default link CocSymbolFile Statement + hi default link CocSymbolModule Statement + hi default link CocSymbolNamespace Statement + hi default link CocSymbolPackage Statement + hi default link CocSymbolClass Statement + hi default link CocSymbolMethod Function + hi default link CocSymbolProperty Keyword + hi default link CocSymbolField CocSymbolDefault + hi default link CocSymbolConstructor Function + hi default link CocSymbolEnum CocSymbolDefault + hi default link CocSymbolInterface CocSymbolDefault + hi default link CocSymbolFunction Function + hi default link CocSymbolVariable CocSymbolDefault + hi default link CocSymbolConstant Constant + hi default link CocSymbolString String + hi default link CocSymbolNumber Number + hi default link CocSymbolBoolean Boolean + hi default link CocSymbolArray CocSymbolDefault + hi default link CocSymbolObject CocSymbolDefault + hi default link CocSymbolKey Keyword + hi default link CocSymbolNull Type + hi default link CocSymbolEnumMember CocSymbolDefault + hi default link CocSymbolStruct Keyword + hi default link CocSymbolEvent Keyword + hi default link CocSymbolOperator Operator + hi default link CocSymbolTypeParameter Operator + if has('nvim') hi default link CocFloating NormalFloat else @@ -366,6 +418,9 @@ function! s:Hi() abort if !exists('*sign_getdefined') || empty(sign_getdefined('CocCurrentLine')) sign define CocCurrentLine linehl=CocMenuSel endif + if !exists('*sign_getdefined') || empty(sign_getdefined('CocTreeSelected')) + sign define CocTreeSelected linehl=CocTreeSelected + endif if has('nvim-0.5.0') hi default CocCursorTransparent gui=strikethrough blend=100 endif @@ -379,6 +434,31 @@ function! s:Hi() abort endfor endif call s:AddAnsiGroups() + + if get(g:, 'coc_default_semantic_highlight_groups', 0) == 1 + hi default link CocSem_namespace Identifier + hi default link CocSem_type Type + hi default link CocSem_class Structure + hi default link CocSem_enum Type + hi default link CocSem_interface Type + hi default link CocSem_struct Structure + hi default link CocSem_typeParameter Type + hi default link CocSem_parameter Identifier + hi default link CocSem_variable Identifier + hi default link CocSem_property Identifier + hi default link CocSem_enumMember Constant + hi default link CocSem_event Identifier + hi default link CocSem_function Function + hi default link CocSem_method Function + hi default link CocSem_macro Macro + hi default link CocSem_keyword Keyword + hi default link CocSem_modifier StorageClass + hi default link CocSem_comment Comment + hi default link CocSem_string String + hi default link CocSem_number Number + hi default link CocSem_regexp Normal + hi default link CocSem_operator Operator + endif endfunction function! s:FormatFromSelected(type) @@ -401,8 +481,8 @@ function! s:ShowInfo() else let output = trim(system(node . ' --version')) let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)') - if empty(ms) || str2nr(ms[1]) < 10 || (str2nr(ms[1]) == 10 && str2nr(ms[2]) < 12) - call add(lines, 'Error: Node version '.output.' < 10.12.0, please upgrade node.js') + if empty(ms) || str2nr(ms[1]) < 12 || (str2nr(ms[1]) == 12 && str2nr(ms[2]) < 12) + call add(lines, 'Error: Node version '.output.' < 12.12.0, please upgrade node.js') endif endif " check bundle @@ -411,7 +491,7 @@ function! s:ShowInfo() call add(lines, 'Error: javascript bundle not found, please compile code of coc.nvim by esbuild.') endif if !empty(lines) - belowright vnew + botright vnew setl filetype=nofile call setline(1, lines) else @@ -424,6 +504,7 @@ function! s:ShowInfo() endif endfunction +command! -nargs=0 CocOutline :call coc#rpc#notify('showOutline', []) command! -nargs=? CocDiagnostics :call s:OpenDiagnostics() command! -nargs=0 CocInfo :call s:ShowInfo() command! -nargs=0 CocOpenLog :call coc#rpc#notify('openLog', []) @@ -440,7 +521,7 @@ command! -nargs=+ -complete=custom,s:ExtensionList CocUninstall :call CocAction command! -nargs=* -complete=custom,s:CommandList -range CocCommand :call coc#rpc#notify('runCommand', []) command! -nargs=* -complete=custom,coc#list#options CocList :call coc#rpc#notify('openList', []) command! -nargs=? -complete=custom,coc#list#names CocListResume :call coc#rpc#notify('listResume', []) -command! -nargs=0 -complete=custom,coc#list#names CocListCancel :call coc#rpc#notify('listCancel', []) +command! -nargs=? -complete=custom,coc#list#names CocListCancel :call coc#rpc#notify('listCancel', []) command! -nargs=? -complete=custom,coc#list#names CocPrev :call coc#rpc#notify('listPrev', []) command! -nargs=? -complete=custom,coc#list#names CocNext :call coc#rpc#notify('listNext', []) command! -nargs=? -complete=custom,coc#list#names CocFirst :call coc#rpc#notify('listFirst', []) @@ -487,16 +568,16 @@ nnoremap (coc-refactor) :call CocActionAs inoremap CocRefresh =coc#_complete() nnoremap (coc-cursors-operator) :set operatorfunc=CursorRangeFromSelectedg@ -vnoremap (coc-cursors-range) :call coc#rpc#request('cursorsSelect', [bufnr('%'), 'range', visualmode()]) -nnoremap (coc-cursors-word) :call coc#rpc#request('cursorsSelect', [bufnr('%'), 'word', 'n']) -nnoremap (coc-cursors-position) :call coc#rpc#request('cursorsSelect', [bufnr('%'), 'position', 'n']) - -vnoremap (coc-funcobj-i) :call coc#rpc#request('selectSymbolRange', [v:true, visualmode(), ['Method', 'Function']]) -vnoremap (coc-funcobj-a) :call coc#rpc#request('selectSymbolRange', [v:false, visualmode(), ['Method', 'Function']]) -onoremap (coc-funcobj-i) :call coc#rpc#request('selectSymbolRange', [v:true, '', ['Method', 'Function']]) -onoremap (coc-funcobj-a) :call coc#rpc#request('selectSymbolRange', [v:false, '', ['Method', 'Function']]) - -vnoremap (coc-classobj-i) :call coc#rpc#request('selectSymbolRange', [v:true, visualmode(), ['Interface', 'Struct', 'Class']]) -vnoremap (coc-classobj-a) :call coc#rpc#request('selectSymbolRange', [v:false, visualmode(), ['Interface', 'Struct', 'Class']]) -onoremap (coc-classobj-i) :call coc#rpc#request('selectSymbolRange', [v:true, '', ['Interface', 'Struct', 'Class']]) -onoremap (coc-classobj-a) :call coc#rpc#request('selectSymbolRange', [v:false, '', ['Interface', 'Struct', 'Class']]) +vnoremap (coc-cursors-range) :call CocAction('cursorsSelect', bufnr('%'), 'range', visualmode()) +nnoremap (coc-cursors-word) :call CocAction('cursorsSelect', bufnr('%'), 'word', 'n') +nnoremap (coc-cursors-position) :call CocAction('cursorsSelect', bufnr('%'), 'position', 'n') + +vnoremap (coc-funcobj-i) :call CocAction('selectSymbolRange', v:true, visualmode(), ['Method', 'Function']) +vnoremap (coc-funcobj-a) :call CocAction('selectSymbolRange', v:false, visualmode(), ['Method', 'Function']) +onoremap (coc-funcobj-i) :call CocAction('selectSymbolRange', v:true, '', ['Method', 'Function']) +onoremap (coc-funcobj-a) :call CocAction('selectSymbolRange', v:false, '', ['Method', 'Function']) + +vnoremap (coc-classobj-i) :call CocAction('selectSymbolRange', v:true, visualmode(), ['Interface', 'Struct', 'Class']) +vnoremap (coc-classobj-a) :call CocAction('selectSymbolRange', v:false, visualmode(), ['Interface', 'Struct', 'Class']) +onoremap (coc-classobj-i) :call CocAction('selectSymbolRange', v:true, '', ['Interface', 'Struct', 'Class']) +onoremap (coc-classobj-a) :call CocAction('selectSymbolRange', v:false, '', ['Interface', 'Struct', 'Class']) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/autoload/coc/source/email.vim b/vim-config/plugins/coc.nvim/src/__tests__/autoload/coc/source/email.vim new file mode 100644 index 00000000..de932ee7 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/autoload/coc/source/email.vim @@ -0,0 +1,17 @@ +" vim source for emails +function! coc#source#email#init() abort + return { + \ 'priority': 9, + \ 'shortcut': 'Email', + \ 'triggerCharacters': ['@'] + \} +endfunction + +function! coc#source#email#should_complete(opt) abort + return 1 +endfunction + +function! coc#source#email#complete(opt, cb) abort + let items = ['foo@gmail.com', 'bar@yahoo.com'] + call a:cb(items) +endfunction diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/changedFiles.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/client/changedFiles.test.ts new file mode 100644 index 00000000..f2c78fd6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/changedFiles.test.ts @@ -0,0 +1,62 @@ +/* eslint-disable */ +import helper from '../helper' +// import * as assert from 'assert' +import fs from 'fs' +import * as lsclient from '../../language-client' +import * as path from 'path' +import { URI } from 'vscode-uri' +// import which from 'which' + +beforeAll(async () => { + await helper.setup() +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('Client integration', () => { + + it('should send file change notification', (done) => { + if (global.hasOwnProperty('__TEST__')) return done() + let serverModule = path.join(__dirname, './server/testFileWatcher.js') + let serverOptions: lsclient.ServerOptions = { + module: serverModule, + transport: lsclient.TransportKind.ipc + } + let clientOptions: lsclient.LanguageClientOptions = { + documentSelector: ['css'], + synchronize: {}, initializationOptions: {}, + middleware: { + } + } + let client = new lsclient.LanguageClient('css', 'Test Language Server', serverOptions, clientOptions) + let disposable = client.start() + + client.onReady().then(_ => { + setTimeout(async () => { + let file = path.join(__dirname, 'test.js') + fs.writeFileSync(file, '', 'utf8') + await helper.wait(300) + let res = await client.sendRequest('custom/received') + expect(res).toEqual({ + changes: [{ + uri: URI.file(file).toString(), + type: 1 + }] + }) + fs.unlinkSync(file) + disposable.dispose() + done() + }, 200) + }, e => { + disposable.dispose() + done(e) + }) + }) + +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/connection.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/client/connection.test.ts new file mode 100644 index 00000000..de88dd8b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/connection.test.ts @@ -0,0 +1,140 @@ +import { Duplex } from 'stream' +import { ProgressType } from 'vscode-jsonrpc' +import { createProtocolConnection, DocumentSymbolParams, DocumentSymbolRequest, InitializeParams, InitializeRequest, InitializeResult, ProtocolConnection, StreamMessageReader, StreamMessageWriter } from 'vscode-languageserver-protocol/node' +import { SymbolInformation, SymbolKind } from 'vscode-languageserver-types' +import { NullLogger } from '../../language-client/client' + +class TestStream extends Duplex { + public _write(chunk: string, _encoding: string, done: () => void): void { + this.emit('data', chunk) + done() + } + + public _read(_size: number): void { + } +} + +let serverConnection: ProtocolConnection +let clientConnection: ProtocolConnection +let progressType: ProgressType = new ProgressType() + +beforeEach(() => { + const up = new TestStream() + const down = new TestStream() + const logger = new NullLogger() + serverConnection = createProtocolConnection(new StreamMessageReader(up), new StreamMessageWriter(down), logger) + clientConnection = createProtocolConnection(new StreamMessageReader(down), new StreamMessageWriter(up), logger) + serverConnection.listen() + clientConnection.listen() +}) + +afterEach(() => { + serverConnection.dispose() + clientConnection.dispose() +}) + +describe('Connection Tests', () => { + it('should ensure proper param passing', async () => { + let paramsCorrect = false + serverConnection.onRequest(InitializeRequest.type, params => { + paramsCorrect = !Array.isArray(params) + let result: InitializeResult = { + capabilities: { + } + } + return result + }) + + const init: InitializeParams = { + rootUri: 'file:///home/dirkb', + processId: 1, + capabilities: {}, + workspaceFolders: null, + } + await clientConnection.sendRequest(InitializeRequest.type, init) + expect(paramsCorrect).toBe(true) + }) + + it('should provid token', async () => { + serverConnection.onRequest(DocumentSymbolRequest.type, params => { + expect(params.partialResultToken).toBe('3b1db4c9-e011-489e-a9d1-0653e64707c2') + return [] + }) + + const params: DocumentSymbolParams = { + textDocument: { uri: 'file:///abc.txt' }, + partialResultToken: '3b1db4c9-e011-489e-a9d1-0653e64707c2' + } + await clientConnection.sendRequest(DocumentSymbolRequest.type, params) + }) + + it('should report result', async () => { + let result: SymbolInformation = { + name: 'abc', + kind: SymbolKind.Class, + location: { + uri: 'file:///abc.txt', + range: { start: { line: 0, character: 1 }, end: { line: 2, character: 3 } } + } + } + serverConnection.onRequest(DocumentSymbolRequest.type, params => { + expect(params.partialResultToken).toBe('3b1db4c9-e011-489e-a9d1-0653e64707c2') + serverConnection.sendProgress(progressType, params.partialResultToken, [result]) + return [] + }) + + const params: DocumentSymbolParams = { + textDocument: { uri: 'file:///abc.txt' }, + partialResultToken: '3b1db4c9-e011-489e-a9d1-0653e64707c2' + } + let progressOK = false + clientConnection.onProgress(progressType, '3b1db4c9-e011-489e-a9d1-0653e64707c2', values => { + progressOK = (values !== undefined && values.length === 1) + }) + await clientConnection.sendRequest(DocumentSymbolRequest.type, params) + expect(progressOK).toBeTruthy() + }) + + it('should provide workDoneToken', async () => { + serverConnection.onRequest(DocumentSymbolRequest.type, params => { + expect(params.workDoneToken).toBe('3b1db4c9-e011-489e-a9d1-0653e64707c2') + return [] + }) + + const params: DocumentSymbolParams = { + textDocument: { uri: 'file:///abc.txt' }, + workDoneToken: '3b1db4c9-e011-489e-a9d1-0653e64707c2' + } + await clientConnection.sendRequest(DocumentSymbolRequest.type, params) + }) + + it('should report work done progress', async () => { + serverConnection.onRequest(DocumentSymbolRequest.type, params => { + expect(params.workDoneToken).toBe('3b1db4c9-e011-489e-a9d1-0653e64707c2') + serverConnection.sendProgress(progressType, params.workDoneToken, { + kind: 'begin', + title: 'progress' + }) + serverConnection.sendProgress(progressType, params.workDoneToken, { + kind: 'report', + message: 'message' + }) + serverConnection.sendProgress(progressType, params.workDoneToken, { + kind: 'end', + message: 'message' + }) + return [] + }) + + const params: DocumentSymbolParams = { + textDocument: { uri: 'file:///abc.txt' }, + workDoneToken: '3b1db4c9-e011-489e-a9d1-0653e64707c2' + } + let result = '' + clientConnection.onProgress(progressType, '3b1db4c9-e011-489e-a9d1-0653e64707c2', value => { + result += value.kind + }) + await clientConnection.sendRequest(DocumentSymbolRequest.type, params) + expect(result).toBe('beginreportend') + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/converter.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/client/converter.test.ts new file mode 100644 index 00000000..564b8381 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/converter.test.ts @@ -0,0 +1,89 @@ +import { CompletionTriggerKind, Position, TextDocumentItem, TextDocumentSaveReason } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import * as cv from '../../language-client/utils/converter' + +describe('converter', () => { + + function createDocument(): TextDocument { + return TextDocument.create('file:///1', 'css', 1, '') + } + + it('should asLanguageIds', () => { + let selector = ['css', { language: 'javascript' }] + expect(cv.asLanguageIds(selector)).toEqual(['css', 'javascript']) + }) + + it('should convertToTextDocumentItem', () => { + let doc = createDocument() + expect(cv.convertToTextDocumentItem(doc).uri).toBe(doc.uri) + expect(TextDocumentItem.is(cv.convertToTextDocumentItem(doc))).toBe(true) + }) + + it('should asCloseTextDocumentParams', () => { + let doc = createDocument() + expect(cv.asCloseTextDocumentParams(doc).textDocument.uri).toBe(doc.uri) + }) + + it('should asChangeTextDocumentParams', () => { + let doc = createDocument() + expect(cv.asChangeTextDocumentParams(doc).textDocument.uri).toBe(doc.uri) + }) + + it('should asWillSaveTextDocumentParams', () => { + let res = cv.asWillSaveTextDocumentParams({ document: createDocument(), reason: TextDocumentSaveReason.Manual, waitUntil: () => { } }) + expect(res.textDocument).toBeDefined() + expect(res.reason).toBeDefined() + }) + + it('should asVersionedTextDocumentIdentifier', () => { + let res = cv.asVersionedTextDocumentIdentifier(createDocument()) + expect(res.uri).toBeDefined() + expect(res.version).toBeDefined() + }) + + it('should asSaveTextDocumentParams', () => { + let res = cv.asSaveTextDocumentParams(createDocument(), true) + expect(res.textDocument.uri).toBeDefined() + expect(res.text).toBeDefined() + }) + + it('should asUri', () => { + let uri = URI.file('/tmp/a') + expect(cv.asUri(uri)).toBe(uri.toString()) + }) + + it('should asCompletionParams', () => { + let params = cv.asCompletionParams(createDocument(), Position.create(0, 0), { triggerKind: CompletionTriggerKind.Invoked }) + expect(params.textDocument).toBeDefined() + expect(params.position).toBeDefined() + expect(params.context).toBeDefined() + }) + + it('should asTextDocumentPositionParams', () => { + let params = cv.asTextDocumentPositionParams(createDocument(), Position.create(0, 0)) + expect(params.textDocument).toBeDefined() + expect(params.position).toBeDefined() + }) + + it('should asTextDocumentIdentifier', () => { + let doc = cv.asTextDocumentIdentifier(createDocument()) + expect(doc.uri).toBeDefined() + }) + + it('should asReferenceParams', () => { + let params = cv.asReferenceParams(createDocument(), Position.create(0, 0), { includeDeclaration: false }) + expect(params.textDocument.uri).toBeDefined() + expect(params.position).toBeDefined() + }) + + it('should asDocumentSymbolParams', () => { + let doc = cv.asDocumentSymbolParams(createDocument()) + expect(doc.textDocument.uri).toBeDefined() + }) + + it('should asCodeLensParams', () => { + let doc = cv.asCodeLensParams(createDocument()) + expect(doc.textDocument.uri).toBeDefined() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/delayer.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/client/delayer.test.ts new file mode 100644 index 00000000..3f196976 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/delayer.test.ts @@ -0,0 +1,154 @@ +/* eslint-disable */ +import assert from 'assert' +import { Delayer } from '../../language-client/utils/async' + +test('Delayer', () => { + let count = 0 + let factory = () => { + return Promise.resolve(++count) + } + + let delayer = new Delayer(0) + let promises: Thenable[] = [] + + assert(!delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then((result) => { assert.equal(result, 1); assert(!delayer.isTriggered()) })) + assert(delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then((result) => { assert.equal(result, 1); assert(!delayer.isTriggered()) })) + assert(delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then((result) => { assert.equal(result, 1); assert(!delayer.isTriggered()) })) + assert(delayer.isTriggered()) + + return Promise.all(promises).then(() => { + assert(!delayer.isTriggered()) + }).finally(() => { + delayer.dispose() + }) +}) + +/* +test('Delayer - simple cancel', async () => { + let count = 0 + let factory = () => { + return Promise.resolve(++count) + } + + let delayer = new Delayer(10) + + assert(!delayer.isTriggered()) + + const p = delayer.trigger(factory).then(() => { + assert(false) + }, () => { + assert(true, 'yes, it was cancelled') + }) + assert(delayer.isTriggered()) + delayer.cancel() + assert(!delayer.isTriggered()) + await p +}) + +test('Delayer - cancel should cancel all calls to trigger', function() { + let count = 0 + let factory = () => { + return Promise.resolve(++count) + } + + let delayer = new Delayer(0) + let promises: Thenable[] = [] + + assert(!delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then(null, () => { assert(true, 'yes, it was cancelled') })) + assert(delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then(null, () => { assert(true, 'yes, it was cancelled') })) + assert(delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then(null, () => { assert(true, 'yes, it was cancelled') })) + assert(delayer.isTriggered()) + + delayer.cancel() + + return Promise.all(promises).then(() => { + assert(!delayer.isTriggered()) + }) +}) + +test('Delayer - trigger, cancel, then trigger again', function() { + let count = 0 + let factory = () => { + return Promise.resolve(++count) + } + + let delayer = new Delayer(0) + let promises: Thenable[] = [] + + assert(!delayer.isTriggered()) + + const p = delayer.trigger(factory).then((result) => { + assert.equal(result, 1) + assert(!delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then(null, () => { assert(true, 'yes, it was cancelled') })) + assert(delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then(null, () => { assert(true, 'yes, it was cancelled') })) + assert(delayer.isTriggered()) + + delayer.cancel() + + const p = Promise.all(promises).then(() => { + promises = [] + + assert(!delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then(() => { assert.equal(result, 1); assert(!delayer.isTriggered()) })) + assert(delayer.isTriggered()) + + promises.push(delayer.trigger(factory).then(() => { assert.equal(result, 1); assert(!delayer.isTriggered()) })) + assert(delayer.isTriggered()) + + const p = Promise.all(promises).then(() => { + assert(!delayer.isTriggered()) + }) + + assert(delayer.isTriggered()) + + return p + }) + + return p + }) + + assert(delayer.isTriggered()) + + return p +}) +*/ + +test('Delayer - last task should be the one getting called', function() { + let factoryFactory = (n: number) => () => { + return Promise.resolve(n) + } + + let delayer = new Delayer(0) + let promises: Thenable[] = [] + + assert(!delayer.isTriggered()) + + promises.push(delayer.trigger(factoryFactory(1)).then((n) => { assert.equal(n, 3) })) + promises.push(delayer.trigger(factoryFactory(2)).then((n) => { assert.equal(n, 3) })) + promises.push(delayer.trigger(factoryFactory(3)).then((n) => { assert.equal(n, 3) })) + + const p = Promise.all(promises).then(() => { + assert(!delayer.isTriggered()) + }) + + assert(delayer.isTriggered()) + + return p +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/features.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/client/features.test.ts new file mode 100644 index 00000000..8dc95dfb --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/features.test.ts @@ -0,0 +1,1054 @@ +import * as assert from 'assert' +import path from 'path' +import { URI } from 'vscode-uri' +import { LanguageClient, ServerOptions, TransportKind, Middleware, LanguageClientOptions } from '../../language-client/index' +import { CancellationTokenSource, Color, DocumentSelector, Position, Range, DefinitionRequest, Location, HoverRequest, Hover, CompletionRequest, CompletionTriggerKind, CompletionItem, SignatureHelpRequest, SignatureHelpTriggerKind, SignatureInformation, ParameterInformation, ReferencesRequest, DocumentHighlightRequest, DocumentHighlight, DocumentHighlightKind, CodeActionRequest, CodeAction, WorkDoneProgressBegin, WorkDoneProgressReport, WorkDoneProgressEnd, ProgressToken, DocumentFormattingRequest, TextEdit, DocumentRangeFormattingRequest, DocumentOnTypeFormattingRequest, RenameRequest, WorkspaceEdit, DocumentLinkRequest, DocumentLink, DocumentColorRequest, ColorInformation, ColorPresentation, DeclarationRequest, FoldingRangeRequest, FoldingRange, ImplementationRequest, SelectionRangeRequest, SelectionRange, TypeDefinitionRequest, ProtocolRequestType, CallHierarchyPrepareRequest, CallHierarchyItem, CallHierarchyIncomingCall, CallHierarchyOutgoingCall, SemanticTokensRegistrationType, LinkedEditingRangeRequest, WillCreateFilesRequest, DidCreateFilesNotification, WillRenameFilesRequest, DidRenameFilesNotification, WillDeleteFilesRequest, DidDeleteFilesNotification, TextDocumentEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import helper from '../helper' +import workspace from '../../workspace' + +describe('Client integration', () => { + let client!: LanguageClient + let middleware: Middleware + let uri!: string + let document!: TextDocument + let tokenSource!: CancellationTokenSource + const position: Position = Position.create(1, 1) + const range: Range = Range.create(1, 1, 1, 2) + + function rangeEqual(range: Range, sl: number, sc: number, el: number, ec: number): void { + assert.strictEqual(range.start.line, sl) + assert.strictEqual(range.start.character, sc) + assert.strictEqual(range.end.line, el) + assert.strictEqual(range.end.character, ec) + } + + function colorEqual(color: Color, red: number, green: number, blue: number, alpha: number): void { + assert.strictEqual(color.red, red) + assert.strictEqual(color.green, green) + assert.strictEqual(color.blue, blue) + assert.strictEqual(color.alpha, alpha) + } + + function uriEqual(actual: string, expected: string): void { + assert.strictEqual(actual, expected) + } + + function isArray(value: Array | undefined | null, clazz: any, length = 1): asserts value is Array { + assert.ok(Array.isArray(value), `value is array`) + assert.strictEqual(value!.length, length, 'value has given length') + if (clazz && typeof clazz.is === 'function') { + for (let item of value) { + assert.ok(clazz.is(item)) + } + } + } + + function isDefined(value: T | undefined | null): asserts value is Exclude { + if (value === undefined || value === null) { + throw new Error(`Value is null or undefined`) + } + } + + beforeAll(async () => { + await helper.setup() + workspace.registerTextDocumentContentProvider('lsptests', { + provideTextDocumentContent: (_uri: URI) => { + return [ + 'REM @ECHO OFF', + 'cd c:\\source', + 'REM This is the location of the files that you want to sort', + 'FOR %%f IN (*.doc *.txt) DO XCOPY c:\\source\\"%%f" c:\\text /m /y', + 'REM This moves any files with a .doc or', + 'REM .txt extension from c:\\source to c:\\text', + 'REM %%f is a variable', + 'FOR %%f IN (*.jpg *.png *.bmp) DO XCOPY C:\\source\\"%%f" c:\\images /m /y', + 'REM This moves any files with a .jpg, .png,', + 'REM or .bmp extension from c:\\source to c:\\images;;', + ].join('\n') + } + }) + + uri = URI.parse('lsptests://localhost/test.bat').toString() + let doc = await workspace.loadFile(uri.toString()) + document = doc.textDocument + tokenSource = new CancellationTokenSource() + const serverModule = path.join(__dirname, './server/testServer.js') + const serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { module: serverModule, transport: TransportKind.ipc, options: { execArgv: ['--nolazy', '--inspect=6014'] } } + } + const documentSelector: DocumentSelector = [{ scheme: 'lsptests' }] + + middleware = {} + const clientOptions: LanguageClientOptions = { + documentSelector, synchronize: {}, initializationOptions: {}, middleware + } + + client = new LanguageClient('test svr', 'Test Language Server', serverOptions, clientOptions) + client.start() + await client.onReady() + }) + + afterAll(async () => { + await client.stop() + await helper.shutdown() + }) + + test('InitializeResult', () => { + let expected = { + capabilities: { + textDocumentSync: 1, + definitionProvider: true, + hoverProvider: true, + completionProvider: { resolveProvider: true, triggerCharacters: ['"', ':'] }, + signatureHelpProvider: { + triggerCharacters: [':'], + retriggerCharacters: [':'] + }, + referencesProvider: true, + documentHighlightProvider: true, + codeActionProvider: { + resolveProvider: true + }, + documentFormattingProvider: true, + documentRangeFormattingProvider: true, + documentOnTypeFormattingProvider: { + firstTriggerCharacter: ':' + }, + renameProvider: { + prepareProvider: true + }, + documentLinkProvider: { + resolveProvider: true + }, + colorProvider: true, + declarationProvider: true, + foldingRangeProvider: true, + implementationProvider: true, + selectionRangeProvider: true, + typeDefinitionProvider: true, + callHierarchyProvider: true, + semanticTokensProvider: { + legend: { + tokenTypes: [], + tokenModifiers: [] + }, + range: true, + full: { + delta: true + } + }, + workspace: { + fileOperations: { + didCreate: { filters: [{ scheme: 'file', pattern: { glob: '**/created-static/**{/,/*.txt}' } }] }, + didRename: { + filters: [ + { scheme: 'file', pattern: { glob: '**/renamed-static/**/', matches: 'folder' } }, + { scheme: 'file', pattern: { glob: '**/renamed-static/**/*.txt', matches: 'file' } } + ] + }, + didDelete: { filters: [{ scheme: 'file', pattern: { glob: '**/deleted-static/**{/,/*.txt}' } }] }, + willCreate: { filters: [{ scheme: 'file', pattern: { glob: '**/created-static/**{/,/*.txt}' } }] }, + willRename: { + filters: [ + { scheme: 'file', pattern: { glob: '**/renamed-static/**/', matches: 'folder' } }, + { scheme: 'file', pattern: { glob: '**/renamed-static/**/*.txt', matches: 'file' } } + ] + }, + willDelete: { filters: [ {scheme: 'file', pattern: { glob: '**/deleted-static/**{/,/*.txt}' } }] }, + }, + }, + linkedEditingRangeProvider: true + }, + customResults: { + hello: 'world' + } + } + assert.deepEqual(client.initializeResult, expected) + }) + + test('Goto Definition', async () => { + const provider = client.getFeature(DefinitionRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.provideDefinition(document, position, tokenSource.token)) as Location + assert.strictEqual(Location.is(result), true) + uriEqual(result.uri, uri) + rangeEqual(result.range, 0, 0, 0, 1) + let middlewareCalled = false + middleware.provideDefinition = (document, position, token, next) => { + middlewareCalled = true + return next(document, position, token) + } + await provider.provideDefinition(document, position, tokenSource.token) + middleware.provideDefinition = undefined + assert.strictEqual(middlewareCalled, true) + }) + + test('Hover', async () => { + const provider = client.getFeature(HoverRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideHover(document, position, tokenSource.token) + assert.ok(Hover.is(result)) + assert.strictEqual((result.contents as any).kind, 'plaintext') + assert.strictEqual((result.contents as any).value, 'foo') + let middlewareCalled = false + middleware.provideHover = (document, position, token, next) => { + middlewareCalled = true + return next(document, position, token) + } + await provider.provideHover(document, position, tokenSource.token) + middleware.provideHover = undefined + assert.strictEqual(middlewareCalled, true) + }) + + test('Completion', async () => { + const provider = client.getFeature(CompletionRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.provideCompletionItems(document, position, tokenSource.token, { triggerKind: CompletionTriggerKind.Invoked, triggerCharacter: ':' })) as CompletionItem[] + + isArray(result, CompletionItem) + const item = result[0] + assert.strictEqual(item.label, 'item') + assert.strictEqual(item.insertText, 'text') + assert.strictEqual(item.detail, undefined) + isDefined(provider.resolveCompletionItem) + + const resolved = await provider.resolveCompletionItem(item, tokenSource.token) + isDefined(resolved) + assert.strictEqual(resolved.detail, 'detail') + + let middlewareCalled = 0 + middleware.provideCompletionItem = (document, position, context, token, next) => { + middlewareCalled++ + return next(document, position, context, token) + } + middleware.resolveCompletionItem = (item, token, next) => { + middlewareCalled++ + return next(item, token) + } + await provider.provideCompletionItems(document, position, tokenSource.token, { triggerKind: CompletionTriggerKind.Invoked, triggerCharacter: ':' }) + await provider.resolveCompletionItem(item, tokenSource.token) + middleware.provideCompletionItem = undefined + middleware.resolveCompletionItem = undefined + assert.strictEqual(middlewareCalled, 2) + }) + + test('SignatureHelpRequest', async () => { + const provider = client.getFeature(SignatureHelpRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideSignatureHelp(document, position, tokenSource.token, + { + isRetrigger: false, + triggerKind: SignatureHelpTriggerKind.Invoked, + triggerCharacter: ':' + } + ) + + assert.strictEqual(result.activeSignature, 1) + assert.strictEqual(result.activeParameter, 1) + isArray(result.signatures, SignatureInformation) + + const signature = result.signatures[0] + assert.strictEqual(signature.label, 'label') + assert.strictEqual(signature.documentation, 'doc') + isArray(signature.parameters, ParameterInformation) + + const parameter = signature.parameters[0] + assert.strictEqual(parameter.label, 'label') + assert.strictEqual(parameter.documentation, 'doc') + + let middlewareCalled = false + middleware.provideSignatureHelp = (d, p, c, t, n) => { + middlewareCalled = true + return n(d, p, c, t) + } + await provider.provideSignatureHelp(document, position, tokenSource.token, + { + isRetrigger: false, + triggerKind: SignatureHelpTriggerKind.Invoked, + triggerCharacter: ':' + } + ) + middleware.provideSignatureHelp = undefined + assert.ok(middlewareCalled) + }) + + test('References', async () => { + const provider = client.getFeature(ReferencesRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideReferences(document, position, { + includeDeclaration: true + }, tokenSource.token) + + isArray(result, Location, 2) + for (let i = 0; i < result.length; i++) { + const location = result[i] + rangeEqual(location.range, i, i, i, i) + assert.strictEqual(location.uri.toString(), document.uri.toString()) + } + + let middlewareCalled = false + middleware.provideReferences = (d, p, c, t, n) => { + middlewareCalled = true + return n(d, p, c, t) + } + await provider.provideReferences(document, position, { + includeDeclaration: true + }, tokenSource.token) + middleware.provideReferences = undefined + assert.ok(middlewareCalled) + }) + + test('Document Highlight', async () => { + const provider = client.getFeature(DocumentHighlightRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideDocumentHighlights(document, position, tokenSource.token) + + isArray(result, DocumentHighlight, 1) + + const highlight = result[0] + assert.strictEqual(highlight.kind, DocumentHighlightKind.Read) + rangeEqual(highlight.range, 2, 2, 2, 2) + + let middlewareCalled = false + middleware.provideDocumentHighlights = (d, p, t, n) => { + middlewareCalled = true + return n(d, p, t) + } + await provider.provideDocumentHighlights(document, position, tokenSource.token) + middleware.provideDocumentHighlights = undefined + assert.ok(middlewareCalled) + }) + + test('Code Actions', async () => { + const provider = client.getFeature(CodeActionRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.provideCodeActions(document, range, { + diagnostics: [] + }, tokenSource.token)) as CodeAction[] + + isArray(result, CodeAction) + const action = result[0] + assert.strictEqual(action.title, 'title') + assert.strictEqual(action.command?.title, 'title') + assert.strictEqual(action.command?.command, 'id') + + const resolved = (await provider.resolveCodeAction(result[0], tokenSource.token)) + assert.strictEqual(resolved?.title, 'resolved') + + let middlewareCalled = false + middleware.provideCodeActions = (d, r, c, t, n) => { + middlewareCalled = true + return n(d, r, c, t) + } + + await provider.provideCodeActions(document, range, { diagnostics: [] }, tokenSource.token) + middleware.provideCodeActions = undefined + assert.ok(middlewareCalled) + + middlewareCalled = false + middleware.resolveCodeAction = (c, t, n) => { + middlewareCalled = true + return n(c, t) + } + + await provider.resolveCodeAction!(result[0], tokenSource.token) + middleware.resolveCodeAction = undefined + assert.ok(middlewareCalled) + }) + + test('Progress', async () => { + const progressToken = 'TEST-PROGRESS-TOKEN' + const middlewareEvents: Array = [] + let currentProgressResolver: (value: unknown) => void | undefined + + // Set up middleware that calls the current resolve function when it gets its 'end' progress event. + middleware.handleWorkDoneProgress = (token: ProgressToken, params, next) => { + if (token === progressToken) { + middlewareEvents.push(params) + if (params.kind === 'end') { + setImmediate(currentProgressResolver) + } + } + return next(token, params) + } + + // Trigger multiple sample progress events. + for (let i = 0; i < 2; i++) { + await new Promise((resolve, reject) => { + currentProgressResolver = resolve + client.sendRequest( + new ProtocolRequestType('testing/sendSampleProgress'), + {}, + tokenSource.token, + ).catch(reject) + }) + } + + middleware.handleWorkDoneProgress = undefined + + // Ensure all events were handled. + assert.deepStrictEqual( + middlewareEvents.map(p => p.kind), + ['begin', 'report', 'end', 'begin', 'report', 'end'], + ) + }) + + test('Document Formatting', async () => { + const provider = client.getFeature(DocumentFormattingRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideDocumentFormattingEdits(document, { tabSize: 4, insertSpaces: false }, tokenSource.token) + + isArray(result, TextEdit) + const edit = result[0] + assert.strictEqual(edit.newText, 'insert') + rangeEqual(edit.range, 0, 0, 0, 0) + + let middlewareCalled = true + middleware.provideDocumentFormattingEdits = (d, c, t, n) => { + middlewareCalled = true + return n(d, c, t) + } + await provider.provideDocumentFormattingEdits(document, { tabSize: 4, insertSpaces: false }, tokenSource.token) + middleware.provideDocumentFormattingEdits = undefined + assert.ok(middlewareCalled) + }) + + test('Document Range Formatting', async () => { + const provider = client.getFeature(DocumentRangeFormattingRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideDocumentRangeFormattingEdits(document, range, { tabSize: 4, insertSpaces: false }, tokenSource.token) + + isArray(result, TextEdit) + const edit = result[0] + assert.strictEqual(edit.newText, '') + rangeEqual(edit.range, 1, 1, 1, 2) + + let middlewareCalled = true + middleware.provideDocumentRangeFormattingEdits = (d, r, c, t, n) => { + middlewareCalled = true + return n(d, r, c, t) + } + await provider.provideDocumentRangeFormattingEdits(document, range, { tabSize: 4, insertSpaces: false }, tokenSource.token) + middleware.provideDocumentFormattingEdits = undefined + assert.ok(middlewareCalled) + }) + + test('Document on Type Formatting', async () => { + const provider = client.getFeature(DocumentOnTypeFormattingRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideOnTypeFormattingEdits(document, position, 'a', { tabSize: 4, insertSpaces: false }, tokenSource.token) + + isArray(result, TextEdit) + const edit = result[0] + assert.strictEqual(edit.newText, 'replace') + rangeEqual(edit.range, 2, 2, 2, 3) + + let middlewareCalled = true + middleware.provideOnTypeFormattingEdits = (d, p, s, c, t, n) => { + middlewareCalled = true + return n(d, p, s, c, t) + } + await provider.provideOnTypeFormattingEdits(document, position, 'a', { tabSize: 4, insertSpaces: false }, tokenSource.token) + middleware.provideDocumentFormattingEdits = undefined + assert.ok(middlewareCalled) + }) + + test('Rename', async () => { + const provider = client.getFeature(RenameRequest.method).getProvider(document) + isDefined(provider) + isDefined(provider.prepareRename) + const prepareResult = await provider.prepareRename(document, position, tokenSource.token) as Range + + rangeEqual(prepareResult, 1, 1, 1, 2) + const renameResult = await provider.provideRenameEdits(document, position, 'newName', tokenSource.token) + assert.ok(WorkspaceEdit.is(renameResult)) + let middlewareCalled = 0 + middleware.prepareRename = (d, p, t, n) => { + middlewareCalled++ + return n(d, p, t) + } + await provider.prepareRename(document, position, tokenSource.token) + middleware.prepareRename = undefined + middleware.provideRenameEdits = (d, p, w, t, n) => { + middlewareCalled++ + return n(d, p, w, t) + } + await provider.provideRenameEdits(document, position, 'newName', tokenSource.token) + middleware.provideRenameEdits = undefined + assert.strictEqual(middlewareCalled, 2) + }) + + test('Document Link', async () => { + const provider = client.getFeature(DocumentLinkRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideDocumentLinks(document, tokenSource.token) + + isArray(result, DocumentLink) + const documentLink = result[0] + rangeEqual(documentLink.range, 1, 1, 1, 2) + + let middlewareCalled = 0 + middleware.provideDocumentLinks = (d, t, n) => { + middlewareCalled++ + return n(d, t) + } + await provider.provideDocumentLinks(document, tokenSource.token) + middleware.provideDocumentLinks = undefined + + isDefined(provider.resolveDocumentLink) + const resolved = await provider.resolveDocumentLink(documentLink, tokenSource.token) + isDefined(resolved.target) + assert.strictEqual(resolved.target.toString(), URI.file('/target.txt').toString()) + + middleware.resolveDocumentLink = (i, t, n) => { + middlewareCalled++ + return n(i, t) + } + await provider.resolveDocumentLink(documentLink, tokenSource.token) + middleware.resolveDocumentLink = undefined + assert.strictEqual(middlewareCalled, 2) + }) + + test('Document Color', async () => { + const provider = client.getFeature(DocumentColorRequest.method).getProvider(document) + isDefined(provider) + const colors = await provider.provideDocumentColors(document, tokenSource.token) + + isArray(colors, ColorInformation) + const color = colors[0] + + rangeEqual(color.range, 1, 1, 1, 2) + colorEqual(color.color, 1, 1, 1, 1) + + let middlewareCalled = 0 + middleware.provideDocumentColors = (d, t, n) => { + middlewareCalled++ + return n(d, t) + } + await provider.provideDocumentColors(document, tokenSource.token) + middleware.provideDocumentColors = undefined + + const presentations = await provider.provideColorPresentations(color.color, { document, range }, tokenSource.token) + + isArray(presentations, ColorPresentation) + const presentation = presentations[0] + assert.strictEqual(presentation.label, 'label') + + middleware.provideColorPresentations = (c, x, t, n) => { + middlewareCalled++ + return n(c, x, t) + } + await provider.provideColorPresentations(color.color, { document, range }, tokenSource.token) + middleware.provideColorPresentations = undefined + assert.strictEqual(middlewareCalled, 2) + }) + + test('Goto Declaration', async () => { + const provider = client.getFeature(DeclarationRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.provideDeclaration(document, position, tokenSource.token)) as Location + + uriEqual(result.uri, uri) + rangeEqual(result.range, 1, 1, 1, 2) + + let middlewareCalled = false + middleware.provideDeclaration = (document, position, token, next) => { + middlewareCalled = true + return next(document, position, token) + } + await provider.provideDeclaration(document, position, tokenSource.token) + middleware.provideDeclaration = undefined + assert.strictEqual(middlewareCalled, true) + }) + + test('Folding Ranges', async () => { + const provider = client.getFeature(FoldingRangeRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.provideFoldingRanges(document, {}, tokenSource.token)) + + isArray(result, FoldingRange, 1) + const range = result[0] + assert.strictEqual(range.startLine, 1) + assert.strictEqual(range.endLine, 2) + let middlewareCalled = true + middleware.provideFoldingRanges = (d, c, t, n) => { + middlewareCalled = true + return n(d, c, t) + } + await provider.provideFoldingRanges(document, {}, tokenSource.token) + middleware.provideFoldingRanges = undefined + assert.ok(middlewareCalled) + }) + + test('Goto Implementation', async () => { + const provider = client.getFeature(ImplementationRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.provideImplementation(document, position, tokenSource.token)) as Location + + uriEqual(result.uri, uri) + rangeEqual(result.range, 2, 2, 3, 3) + + let middlewareCalled = false + middleware.provideImplementation = (document, position, token, next) => { + middlewareCalled = true + return next(document, position, token) + } + await provider.provideImplementation(document, position, tokenSource.token) + middleware.provideImplementation = undefined + assert.strictEqual(middlewareCalled, true) + }) + + test('Selection Range', async () => { + const provider = client.getFeature(SelectionRangeRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.provideSelectionRanges(document, [position], tokenSource.token)) + + isArray(result, SelectionRange, 1) + const range = result[0] + rangeEqual(range.range, 1, 2, 3, 4) + let middlewareCalled = false + middleware.provideSelectionRanges = (d, p, t, n) => { + middlewareCalled = true + return n(d, p, t) + } + await provider.provideSelectionRanges(document, [position], tokenSource.token) + middleware.provideSelectionRanges = undefined + assert.strictEqual(middlewareCalled, true) + }) + + test('Type Definition', async () => { + const provider = client.getFeature(TypeDefinitionRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.provideTypeDefinition(document, position, tokenSource.token)) as Location + + uriEqual(result.uri, uri) + rangeEqual(result.range, 2, 2, 3, 3) + + let middlewareCalled = false + middleware.provideTypeDefinition = (document, position, token, next) => { + middlewareCalled = true + return next(document, position, token) + } + await provider.provideTypeDefinition(document, position, tokenSource.token) + middleware.provideTypeDefinition = undefined + assert.strictEqual(middlewareCalled, true) + }) + + test('Call Hierarchy', async () => { + const provider = client.getFeature(CallHierarchyPrepareRequest.method).getProvider(document) + isDefined(provider) + const result = (await provider.prepareCallHierarchy(document, position, tokenSource.token)) as CallHierarchyItem[] + expect(result.length).toBe(1) + + let middlewareCalled = false + middleware.prepareCallHierarchy = (d, p, t, n) => { + middlewareCalled = true + return n(d, p, t) + } + await provider.prepareCallHierarchy(document, position, tokenSource.token) + middleware.prepareCallHierarchy = undefined + assert.strictEqual(middlewareCalled, true) + + const item = result[0] + const incoming = (await provider.provideCallHierarchyIncomingCalls(item, tokenSource.token)) as CallHierarchyIncomingCall[] + expect(incoming.length).toBe(1) + assert.deepEqual(incoming[0].from, item) + middlewareCalled = false + middleware.provideCallHierarchyIncomingCalls = (i, t, n) => { + middlewareCalled = true + return n(i, t) + } + await provider.provideCallHierarchyIncomingCalls(item, tokenSource.token) + middleware.provideCallHierarchyIncomingCalls = undefined + assert.strictEqual(middlewareCalled, true) + + const outgoing = (await provider.provideCallHierarchyOutgoingCalls(item, tokenSource.token)) as CallHierarchyOutgoingCall[] + expect(outgoing.length).toBe(1) + assert.deepEqual(outgoing[0].to, item) + middlewareCalled = false + middleware.provideCallHierarchyOutgoingCalls = (i, t, n) => { + middlewareCalled = true + return n(i, t) + } + await provider.provideCallHierarchyOutgoingCalls(item, tokenSource.token) + middleware.provideCallHierarchyOutgoingCalls = undefined + assert.strictEqual(middlewareCalled, true) + }) + + const referenceFileUri = URI.parse('/dummy-edit') + function ensureReferenceEdit(edits: WorkspaceEdit, type: string, expectedLines: string[]) { + // // Ensure the edits are as expected. + assert.strictEqual(edits.documentChanges?.length, 1) + const edit = edits.documentChanges[0] as TextDocumentEdit + assert.strictEqual(edit.edits.length, 1) + assert.strictEqual(edit.textDocument.uri, referenceFileUri.path) + assert.strictEqual(edit.edits[0].newText.trim(), `${type}:\n${expectedLines.join('\n')}`.trim()) + } + async function ensureNotificationReceived(type: string, params: any) { + const result = await client.sendRequest( + new ProtocolRequestType('testing/lastFileOperationRequest'), + {}, + tokenSource.token, + ) + assert.strictEqual(result.type, type) + assert.deepEqual(result.params, params) + assert.deepEqual(result, { + type, + params + }) + } + + const createFiles = [ + '/my/file.txt', + '/my/file.js', + '/my/folder/', + // Static registration for tests is [operation]-static and *.txt + '/my/created-static/file.txt', + '/my/created-static/file.js', + '/my/created-static/folder/', + // Dynamic registration for tests is [operation]-dynamic and *.js + '/my/created-dynamic/file.txt', + '/my/created-dynamic/file.js', + '/my/created-dynamic/folder/', + ].map(p => URI.file(p)) + + const renameFiles = [ + ['/my/file.txt', '/my-new/file.txt'], + ['/my/file.js', '/my-new/file.js'], + ['/my/folder/', '/my-new/folder/'], + // Static registration for tests is [operation]-static and *.txt + ['/my/renamed-static/file.txt', '/my-new/renamed-static/file.txt'], + ['/my/renamed-static/file.js', '/my-new/renamed-static/file.js'], + ['/my/renamed-static/folder/', '/my-new/renamed-static/folder/'], + // Dynamic registration for tests is [operation]-dynamic and *.js + ['/my/renamed-dynamic/file.txt', '/my-new/renamed-dynamic/file.txt'], + ['/my/renamed-dynamic/file.js', '/my-new/renamed-dynamic/file.js'], + ['/my/renamed-dynamic/folder/', '/my-new/renamed-dynamic/folder/'], + ].map(([o, n]) => ({ oldUri: URI.file(o), newUri: URI.file(n) })) + + const deleteFiles = [ + '/my/file.txt', + '/my/file.js', + '/my/folder/', + // Static registration for tests is [operation]-static and *.txt + '/my/deleted-static/file.txt', + '/my/deleted-static/file.js', + '/my/deleted-static/folder/', + // Dynamic registration for tests is [operation]-dynamic and *.js + '/my/deleted-dynamic/file.txt', + '/my/deleted-dynamic/file.js', + '/my/deleted-dynamic/folder/', + ].map(p => URI.file(p)) + + test('File Operations - Will Create Files', async () => { + const feature = client.getFeature(WillCreateFilesRequest.method) + isDefined(feature) + + const sendCreateRequest = () => new Promise(async (resolve, reject) => { + void feature.send({ files: createFiles, waitUntil: resolve }) + // If feature.send didn't call waitUntil synchronously then something went wrong. + reject(new Error('Feature unexpectedly did not call waitUntil synchronously')) + }) + + // Send the event and ensure the server responds with an edit referencing the + // correct files. + let edits = await sendCreateRequest() + ensureReferenceEdit( + edits, + 'WILL CREATE', + [ + 'file:///my/created-static/file.txt', + 'file:///my/created-static/folder/', + 'file:///my/created-dynamic/file.js', + 'file:///my/created-dynamic/folder/', + ], + ) + + // Add middleware that strips out any folders. + middleware.workspace = middleware.workspace || {} + middleware.workspace.willCreateFiles = (event, next) => next({ + ...event, + files: event.files.filter(f => !f.path.endsWith('/')), + }) + + // Ensure we get the same results minus the folders that the middleware removed. + edits = await sendCreateRequest() + ensureReferenceEdit( + edits, + 'WILL CREATE', + [ + 'file:///my/created-static/file.txt', + 'file:///my/created-dynamic/file.js', + ], + ) + + middleware.workspace.willCreateFiles = undefined + }) + + test('File Operations - Did Create Files', async () => { + const feature = client.getFeature(DidCreateFilesNotification.method) + isDefined(feature) + + // Send the event and ensure the server reports the notification was sent. + await feature.send({ files: createFiles }) + await ensureNotificationReceived( + 'create', + { + files: [ + { uri: 'file:///my/created-static/file.txt' }, + { uri: 'file:///my/created-static/folder/' }, + { uri: 'file:///my/created-dynamic/file.js' }, + { uri: 'file:///my/created-dynamic/folder/' }, + ], + }, + ) + + // Add middleware that strips out any folders. + middleware.workspace = middleware.workspace || {} + middleware.workspace.didCreateFiles = (event, next) => next({ + files: event.files.filter(f => !f.path.endsWith('/')), + }) + + // Ensure we get the same results minus the folders that the middleware removed. + await feature.send({ files: createFiles }) + await ensureNotificationReceived( + 'create', + { + files: [ + { uri: 'file:///my/created-static/file.txt' }, + { uri: 'file:///my/created-dynamic/file.js' }, + ], + }, + ) + + middleware.workspace.didCreateFiles = undefined + }) + + test('File Operations - Will Rename Files', async () => { + const feature = client.getFeature(WillRenameFilesRequest.method) + isDefined(feature) + + const sendRenameRequest = () => new Promise(async (resolve, reject) => { + void feature.send({ files: renameFiles, waitUntil: resolve }) + // If feature.send didn't call waitUntil synchronously then something went wrong. + reject(new Error('Feature unexpectedly did not call waitUntil synchronously')) + }) + + // Send the event and ensure the server responds with an edit referencing the + // correct files. + let edits = await sendRenameRequest() + ensureReferenceEdit( + edits, + 'WILL RENAME', + [ + 'file:///my/renamed-static/file.txt -> file:///my-new/renamed-static/file.txt', + 'file:///my/renamed-static/folder/ -> file:///my-new/renamed-static/folder/', + 'file:///my/renamed-dynamic/file.js -> file:///my-new/renamed-dynamic/file.js', + 'file:///my/renamed-dynamic/folder/ -> file:///my-new/renamed-dynamic/folder/', + ], + ) + + // Add middleware that strips out any folders. + middleware.workspace = middleware.workspace || {} + middleware.workspace.willRenameFiles = (event, next) => next({ + ...event, + files: event.files.filter(f => !f.oldUri.path.endsWith('/')), + }) + + // Ensure we get the same results minus the folders that the middleware removed. + edits = await sendRenameRequest() + ensureReferenceEdit( + edits, + 'WILL RENAME', + [ + 'file:///my/renamed-static/file.txt -> file:///my-new/renamed-static/file.txt', + 'file:///my/renamed-dynamic/file.js -> file:///my-new/renamed-dynamic/file.js', + ], + ) + + middleware.workspace.willRenameFiles = undefined + }) + + test('File Operations - Did Rename Files', async () => { + const feature = client.getFeature(DidRenameFilesNotification.method) + isDefined(feature) + + // Send the event and ensure the server reports the notification was sent. + await feature.send({ files: renameFiles }) + await ensureNotificationReceived( + 'rename', + { + files: [ + { oldUri: 'file:///my/renamed-static/file.txt', newUri: 'file:///my-new/renamed-static/file.txt' }, + { oldUri: 'file:///my/renamed-static/folder/', newUri: 'file:///my-new/renamed-static/folder/' }, + { oldUri: 'file:///my/renamed-dynamic/file.js', newUri: 'file:///my-new/renamed-dynamic/file.js' }, + { oldUri: 'file:///my/renamed-dynamic/folder/', newUri: 'file:///my-new/renamed-dynamic/folder/' }, + ], + }, + ) + + // Add middleware that strips out any folders. + middleware.workspace = middleware.workspace || {} + middleware.workspace.didRenameFiles = (event, next) => next({ + files: event.files.filter(f => !f.oldUri.path.endsWith('/')), + }) + + // Ensure we get the same results minus the folders that the middleware removed. + await feature.send({ files: renameFiles }) + await ensureNotificationReceived( + 'rename', + { + files: [ + { oldUri: 'file:///my/renamed-static/file.txt', newUri: 'file:///my-new/renamed-static/file.txt' }, + { oldUri: 'file:///my/renamed-dynamic/file.js', newUri: 'file:///my-new/renamed-dynamic/file.js' }, + ], + }, + ) + + middleware.workspace.didRenameFiles = undefined + }) + + test('File Operations - Will Delete Files', async () => { + const feature = client.getFeature(WillDeleteFilesRequest.method) + isDefined(feature) + + const sendDeleteRequest = () => new Promise(async (resolve, reject) => { + void feature.send({ files: deleteFiles, waitUntil: resolve }) + // If feature.send didn't call waitUntil synchronously then something went wrong. + reject(new Error('Feature unexpectedly did not call waitUntil synchronously')) + }) + + // Send the event and ensure the server responds with an edit referencing the + // correct files. + let edits = await sendDeleteRequest() + ensureReferenceEdit( + edits, + 'WILL DELETE', + [ + 'file:///my/deleted-static/file.txt', + 'file:///my/deleted-static/folder/', + 'file:///my/deleted-dynamic/file.js', + 'file:///my/deleted-dynamic/folder/', + ], + ) + + // Add middleware that strips out any folders. + middleware.workspace = middleware.workspace || {} + middleware.workspace.willDeleteFiles = (event, next) => next({ + ...event, + files: event.files.filter(f => !f.path.endsWith('/')), + }) + + // Ensure we get the same results minus the folders that the middleware removed. + edits = await sendDeleteRequest() + ensureReferenceEdit( + edits, + 'WILL DELETE', + [ + 'file:///my/deleted-static/file.txt', + 'file:///my/deleted-dynamic/file.js', + ], + ) + + middleware.workspace.willDeleteFiles = undefined + }) + + test('File Operations - Did Delete Files', async () => { + const feature = client.getFeature(DidDeleteFilesNotification.method) + isDefined(feature) + + // Send the event and ensure the server reports the notification was sent. + await feature.send({ files: deleteFiles }) + await ensureNotificationReceived( + 'delete', + { + files: [ + { uri: 'file:///my/deleted-static/file.txt' }, + { uri: 'file:///my/deleted-static/folder/' }, + { uri: 'file:///my/deleted-dynamic/file.js' }, + { uri: 'file:///my/deleted-dynamic/folder/' }, + ], + }, + ) + + // Add middleware that strips out any folders. + middleware.workspace = middleware.workspace || {} + middleware.workspace.didDeleteFiles = (event, next) => next({ + files: event.files.filter(f => !f.path.endsWith('/')), + }) + + // Ensure we get the same results minus the folders that the middleware removed. + await feature.send({ files: deleteFiles }) + await ensureNotificationReceived( + 'delete', + { + files: [ + { uri: 'file:///my/deleted-static/file.txt' }, + { uri: 'file:///my/deleted-dynamic/file.js' }, + ], + }, + ) + + middleware.workspace.didDeleteFiles = undefined + }) + + test('Semantic Tokens', async () => { + const provider = client.getFeature(SemanticTokensRegistrationType.method).getProvider(document) + const rangeProvider = provider?.range + isDefined(rangeProvider) + const rangeResult = await rangeProvider.provideDocumentRangeSemanticTokens(document, range, tokenSource.token) + assert.ok(rangeResult !== undefined) + + let middlewareCalled = false + middleware.provideDocumentRangeSemanticTokens = (d, r, t, n) => { + middlewareCalled = true + return n(d, r, t) + } + await rangeProvider.provideDocumentRangeSemanticTokens(document, range, tokenSource.token) + middleware.provideDocumentRangeSemanticTokens = undefined + assert.strictEqual(middlewareCalled, true) + + const fullProvider = provider?.full + isDefined(fullProvider) + const fullResult = await fullProvider.provideDocumentSemanticTokens(document, tokenSource.token) + assert.ok(fullResult !== undefined) + + middlewareCalled = false + middleware.provideDocumentSemanticTokens = (d, t, n) => { + middlewareCalled = true + return n(d, t) + } + await fullProvider.provideDocumentSemanticTokens(document, tokenSource.token) + middleware.provideDocumentSemanticTokens = undefined + assert.strictEqual(middlewareCalled, true) + + middlewareCalled = false + middleware.provideDocumentSemanticTokensEdits = (d, i, t, n) => { + middlewareCalled = true + return n(d, i, t) + } + await fullProvider.provideDocumentSemanticTokensEdits!(document, '2', tokenSource.token) + middleware.provideDocumentSemanticTokensEdits = undefined + assert.strictEqual(middlewareCalled, true) + }) + + test('Linked Editing Ranges', async () => { + const provider = client.getFeature(LinkedEditingRangeRequest.method).getProvider(document) + isDefined(provider) + const result = await provider.provideLinkedEditingRanges(document, position, tokenSource.token) + + isArray(result.ranges, Range, 1) + rangeEqual(result.ranges[0], 1, 1, 1, 1) + + let middlewareCalled = false + middleware.provideLinkedEditingRange = (document, position, token, next) => { + middlewareCalled = true + return next(document, position, token) + } + await provider.provideLinkedEditingRanges(document, position, tokenSource.token) + middleware.provideTypeDefinition = undefined + assert.strictEqual(middlewareCalled, true) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/integration.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/client/integration.test.ts new file mode 100644 index 00000000..168ff552 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/integration.test.ts @@ -0,0 +1,128 @@ +/* eslint-disable */ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict' + +import helper from '../helper' +import * as assert from 'assert' +import * as lsclient from '../../language-client' +import path from 'path' + +beforeAll(async () => { + await helper.setup() +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +async function testLanguageServer(serverOptions: lsclient.ServerOptions): Promise { + let clientOptions: lsclient.LanguageClientOptions = { + documentSelector: ['css'], + synchronize: {}, + initializationOptions: {} + } + let client = new lsclient.LanguageClient('css', 'Test Language Server', serverOptions, clientOptions) + client.start() + await client.onReady() + expect(client.initializeResult).toBeDefined() +} + +describe('Client integration', () => { + + it('should initialize use IPC channel', (done) => { + let serverModule = path.join(__dirname, './server/testInitializeResult.js') + let serverOptions: lsclient.ServerOptions = { + run: { module: serverModule, transport: lsclient.TransportKind.ipc }, + debug: { module: serverModule, transport: lsclient.TransportKind.ipc, options: { execArgv: ['--nolazy', '--inspect=6014'] } } + } + let clientOptions: lsclient.LanguageClientOptions = { + documentSelector: ['css'], + synchronize: {}, initializationOptions: {}, + middleware: { + handleDiagnostics: (uri, diagnostics, next) => { + assert.equal(uri, "uri:/test.ts") + assert.ok(Array.isArray(diagnostics)) + assert.equal(diagnostics.length, 0) + next(uri, diagnostics) + disposable.dispose() + done() + } + } + } + let client = new lsclient.LanguageClient('css', 'Test Language Server', serverOptions, clientOptions) + let disposable = client.start() + + assert.equal(client.initializeResult, undefined) + + client.onReady().then(_ => { + try { + let expected = { + capabilities: { + textDocumentSync: 1, + completionProvider: { resolveProvider: true, triggerCharacters: ['"', ':'] }, + hoverProvider: true, + renameProvider: { + prepareProvider: true + } + }, + customResults: { + "hello": "world" + } + } + assert.deepEqual(client.initializeResult, expected) + } catch (e) { + disposable.dispose() + done(e) + } + }, e => { + disposable.dispose() + done(e) + }) + }) + + it('should initialize use stdio', async () => { + let serverModule = path.join(__dirname, './server/testInitializeResult.js') + let serverOptions: lsclient.ServerOptions = { + module: serverModule, + transport: lsclient.TransportKind.stdio + } + await testLanguageServer(serverOptions) + }) + + it('should initialize use pipe', async () => { + let serverModule = path.join(__dirname, './server/testInitializeResult.js') + let serverOptions: lsclient.ServerOptions = { + module: serverModule, + transport: lsclient.TransportKind.pipe + } + await testLanguageServer(serverOptions) + }) + + it('should initialize use socket', async () => { + let serverModule = path.join(__dirname, './server/testInitializeResult.js') + let serverOptions: lsclient.ServerOptions = { + module: serverModule, + transport: { + kind: lsclient.TransportKind.socket, + port: 8088 + } + } + await testLanguageServer(serverOptions) + }) + + it('should initialize as command', async () => { + let serverModule = path.join(__dirname, './server/testInitializeResult.js') + let serverOptions: lsclient.ServerOptions = { + command: 'node', + args: [serverModule, '--stdio'] + } + await testLanguageServer(serverOptions) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/server/testFileWatcher.js b/vim-config/plugins/coc.nvim/src/__tests__/client/server/testFileWatcher.js new file mode 100644 index 00000000..6ac96e6f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/server/testFileWatcher.js @@ -0,0 +1,35 @@ +const languageserver = require('vscode-languageserver') +let connection = languageserver.createConnection() +let documents = new languageserver.TextDocuments() +documents.listen(connection) + +connection.onInitialize(() => { + let capabilities = { + textDocumentSync: documents.syncKind + } + return { capabilities } +}) + +connection.onInitialized(() => { + connection.sendRequest('client/registerCapability', { + registrations: [{ + id: 'didChangeWatchedFiles', + method: 'workspace/didChangeWatchedFiles', + registerOptions: { + watchers: [{ globPattern: "**" }] + } + }] + }) +}) + +let received + +connection.onNotification('workspace/didChangeWatchedFiles', params => { + received = params +}) + +connection.onRequest('custom/received', async () => { + return received +}) + +connection.listen() diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/server/testInitializeResult.js b/vim-config/plugins/coc.nvim/src/__tests__/client/server/testInitializeResult.js new file mode 100644 index 00000000..705561a6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/server/testInitializeResult.js @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict' +Object.defineProperty(exports, "__esModule", {value: true}) +const tslib_1 = require("tslib") +const assert = tslib_1.__importStar(require("assert")) +const vscode_languageserver_1 = require("vscode-languageserver") +let connection = vscode_languageserver_1.createConnection() + +let documents = new vscode_languageserver_1.TextDocuments() +documents.listen(connection) +connection.onInitialize((params) => { + assert.equal(params.capabilities.workspace.applyEdit, true) + assert.equal(params.capabilities.workspace.workspaceEdit.documentChanges, true) + assert.deepEqual(params.capabilities.workspace.workspaceEdit.resourceOperations, [vscode_languageserver_1.ResourceOperationKind.Create, vscode_languageserver_1.ResourceOperationKind.Rename, vscode_languageserver_1.ResourceOperationKind.Delete]) + assert.equal(params.capabilities.workspace.workspaceEdit.failureHandling, vscode_languageserver_1.FailureHandlingKind.TextOnlyTransactional) + assert.equal(params.capabilities.textDocument.completion.completionItem.deprecatedSupport, true) + assert.equal(params.capabilities.textDocument.completion.completionItem.preselectSupport, true) + assert.equal(params.capabilities.textDocument.signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport, true) + assert.equal(params.capabilities.textDocument.rename.prepareSupport, true) + let valueSet = params.capabilities.textDocument.completion.completionItemKind.valueSet + assert.equal(valueSet[0], 1) + assert.equal(valueSet[valueSet.length - 1], vscode_languageserver_1.CompletionItemKind.TypeParameter) + let capabilities = { + textDocumentSync: documents.syncKind, + completionProvider: {resolveProvider: true, triggerCharacters: ['"', ':']}, + hoverProvider: true, + renameProvider: { + prepareProvider: true + } + } + return {capabilities, customResults: {"hello": "world"}} +}) +connection.onInitialized(() => { + connection.sendDiagnostics({uri: "uri:/test.ts", diagnostics: []}) +}) +// Listen on the connection +connection.listen() diff --git a/vim-config/plugins/coc.nvim/src/__tests__/client/server/testServer.js b/vim-config/plugins/coc.nvim/src/__tests__/client/server/testServer.js new file mode 100644 index 00000000..07e2edd8 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/client/server/testServer.js @@ -0,0 +1,414 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const assert = require('assert') +const {URI} = require('vscode-uri') +const { + createConnection, CompletionItemKind, ResourceOperationKind, FailureHandlingKind, + DiagnosticTag, CompletionItemTag, TextDocumentSyncKind, MarkupKind, SignatureInformation, ParameterInformation, + Location, Range, DocumentHighlight, DocumentHighlightKind, CodeAction, Command, TextEdit, Position, DocumentLink, + ColorInformation, Color, ColorPresentation, FoldingRange, SelectionRange, SymbolKind, ProtocolRequestType, WorkDoneProgress, + WorkDoneProgressCreateRequest} = require('vscode-languageserver') + +const { + DidCreateFilesNotification, + DidRenameFilesNotification, + DidDeleteFilesNotification, + WillCreateFilesRequest, WillRenameFilesRequest, WillDeleteFilesRequest +} = require('vscode-languageserver-protocol') + +let connection = createConnection() + +console.log = connection.console.log.bind(connection.console) +console.error = connection.console.error.bind(connection.console) + +connection.onInitialize(params => { + assert.equal((params.capabilities.workspace).applyEdit, true) + assert.equal(params.capabilities.workspace.workspaceEdit.documentChanges, true) + assert.equal(params.capabilities.workspace.workspaceEdit.failureHandling, FailureHandlingKind.TextOnlyTransactional) + assert.equal(params.capabilities.textDocument.completion.completionItem.deprecatedSupport, true) + assert.equal(params.capabilities.textDocument.completion.completionItem.preselectSupport, true) + assert.equal(params.capabilities.textDocument.completion.completionItem.tagSupport.valueSet.length, 1) + assert.equal(params.capabilities.textDocument.completion.completionItem.tagSupport.valueSet[0], CompletionItemTag.Deprecated) + assert.equal(params.capabilities.textDocument.signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport, true) + // assert.equal(params.capabilities.textDocument.definition.linkSupport, true) + // assert.equal(params.capabilities.textDocument.declaration.linkSupport, true) + // assert.equal(params.capabilities.textDocument.implementation.linkSupport, true) + // assert.equal(params.capabilities.textDocument.typeDefinition.linkSupport, true) + assert.equal(params.capabilities.textDocument.rename.prepareSupport, true) + assert.equal(params.capabilities.textDocument.publishDiagnostics.relatedInformation, true) + assert.equal(params.capabilities.textDocument.publishDiagnostics.tagSupport.valueSet.length, 2) + assert.equal(params.capabilities.textDocument.publishDiagnostics.tagSupport.valueSet[0], DiagnosticTag.Unnecessary) + assert.equal(params.capabilities.textDocument.publishDiagnostics.tagSupport.valueSet[1], DiagnosticTag.Deprecated) + assert.equal(params.capabilities.textDocument.documentLink.tooltipSupport, true) + let valueSet = params.capabilities.textDocument.completion.completionItemKind.valueSet + assert.equal(valueSet[0], 1) + assert.equal(valueSet[valueSet.length - 1], CompletionItemKind.TypeParameter) + assert.deepEqual(params.capabilities.workspace.workspaceEdit.resourceOperations, [ResourceOperationKind.Create, ResourceOperationKind.Rename, ResourceOperationKind.Delete]) + assert.equal(params.capabilities.workspace.fileOperations.willCreate, true) + + let capabilities = { + textDocumentSync: TextDocumentSyncKind.Full, + definitionProvider: true, + hoverProvider: true, + completionProvider: {resolveProvider: true, triggerCharacters: ['"', ':']}, + signatureHelpProvider: { + triggerCharacters: [':'], + retriggerCharacters: [':'] + }, + referencesProvider: true, + documentHighlightProvider: true, + codeActionProvider: { + resolveProvider: true + }, + documentFormattingProvider: true, + documentRangeFormattingProvider: true, + documentOnTypeFormattingProvider: { + firstTriggerCharacter: ':' + }, + renameProvider: { + prepareProvider: true + }, + documentLinkProvider: { + resolveProvider: true + }, + colorProvider: true, + declarationProvider: true, + foldingRangeProvider: true, + implementationProvider: true, + selectionRangeProvider: true, + typeDefinitionProvider: true, + callHierarchyProvider: true, + semanticTokensProvider: { + legend: { + tokenTypes: [], + tokenModifiers: [] + }, + range: true, + full: { + delta: true + } + }, + workspace: { + fileOperations: { + // Static reg is folders + .txt files with operation kind in the path + didCreate: { + filters: [{ scheme: 'file', pattern: { glob: '**/created-static/**{/,/*.txt}' }}] + }, + didRename: { + filters: [ + { scheme: 'file', pattern: { glob: '**/renamed-static/**/', matches: 'folder' } }, + { scheme: 'file', pattern: { glob: '**/renamed-static/**/*.txt', matches: 'file' } } + ] + }, + didDelete: { + filters: [{ scheme: 'file', pattern: { glob: '**/deleted-static/**{/,/*.txt}' } }] + }, + willCreate: { + filters: [{ scheme: 'file', pattern: { glob: '**/created-static/**{/,/*.txt}' } }] + }, + willRename: { + filters: [ + { scheme: 'file', pattern: { glob: '**/renamed-static/**/', matches: 'folder' } }, + { scheme: 'file', pattern: { glob: '**/renamed-static/**/*.txt', matches: 'file' } } + ] + }, + willDelete: { + filters: [{ scheme: 'file', pattern: { glob: '**/deleted-static/**{/,/*.txt}' } }] + }, + }, + }, + linkedEditingRangeProvider: true + } + return {capabilities, customResults: {hello: 'world'}} +}) + +connection.onInitialized(() => { + // Dynamic reg is folders + .js files with operation kind in the path + connection.client.register(DidCreateFilesNotification.type, { + filters: [{ scheme: 'file', pattern: { glob: '**/created-dynamic/**{/,/*.js}' } }] + }); + connection.client.register(DidRenameFilesNotification.type, { + filters: [ + { scheme: 'file', pattern: { glob: '**/renamed-dynamic/**/', matches: 'folder' } }, + { scheme: 'file', pattern: { glob: '**/renamed-dynamic/**/*.js', matches: 'file' } } + ] + }); + connection.client.register(DidDeleteFilesNotification.type, { + filters: [{ scheme: 'file', pattern: { glob: '**/deleted-dynamic/**{/,/*.js}' } }] + }); + connection.client.register(WillCreateFilesRequest.type, { + filters: [{ scheme: 'file', pattern: { glob: '**/created-dynamic/**{/,/*.js}' } }] + }); + connection.client.register(WillRenameFilesRequest.type, { + filters: [ + { scheme: 'file', pattern: { glob: '**/renamed-dynamic/**/', matches: 'folder' } }, + { scheme: 'file', pattern: { glob: '**/renamed-dynamic/**/*.js', matches: 'file' } } + ] + }); + connection.client.register(WillDeleteFilesRequest.type, { + filters: [{ scheme: 'file', pattern: { glob: '**/deleted-dynamic/**{/,/*.js}' } }] + }); +}) + +connection.onDeclaration((params) => { + assert.equal(params.position.line, 1) + assert.equal(params.position.character, 1) + return {uri: params.textDocument.uri, range: {start: {line: 1, character: 1}, end: {line: 1, character: 2}}} +}) + +connection.onDefinition((params) => { + assert.equal(params.position.line, 1) + assert.equal(params.position.character, 1) + return {uri: params.textDocument.uri, range: {start: {line: 0, character: 0}, end: {line: 0, character: 1}}} +}) + +connection.onHover((_params) => { + return { + contents: { + kind: MarkupKind.PlainText, + value: 'foo' + } + } +}) + +connection.onCompletion((_params) => { + return [ + {label: 'item', insertText: 'text'} + ] +}) + +connection.onCompletionResolve((item) => { + item.detail = 'detail' + return item +}) + +connection.onSignatureHelp((_params) => { + const result = { + signatures: [ + SignatureInformation.create('label', 'doc', ParameterInformation.create('label', 'doc')) + ], + activeSignature: 1, + activeParameter: 1 + } + return result +}) + +connection.onReferences((params) => { + return [ + Location.create(params.textDocument.uri, Range.create(0, 0, 0, 0)), + Location.create(params.textDocument.uri, Range.create(1, 1, 1, 1)) + ] +}) + +connection.onDocumentHighlight((_params) => { + return [ + DocumentHighlight.create(Range.create(2, 2, 2, 2), DocumentHighlightKind.Read) + ] +}) + +connection.onCodeAction((_params) => { + return [ + CodeAction.create('title', Command.create('title', 'id')) + ] +}) + +connection.onCodeActionResolve((codeAction) => { + codeAction.title = 'resolved' + return codeAction +}) + +connection.onDocumentFormatting((_params) => { + return [ + TextEdit.insert(Position.create(0, 0), 'insert') + ] +}) + +connection.onDocumentRangeFormatting((_params) => { + return [ + TextEdit.del(Range.create(1, 1, 1, 2)) + ] +}) + +connection.onDocumentOnTypeFormatting((_params) => { + return [ + TextEdit.replace(Range.create(2, 2, 2, 3), 'replace') + ] +}) + +connection.onPrepareRename((_params) => { + return Range.create(1, 1, 1, 2) +}) + +connection.onRenameRequest((_params) => { + return {documentChanges: []} +}) + +connection.onDocumentLinks((_params) => { + return [ + DocumentLink.create(Range.create(1, 1, 1, 2)) + ] +}) + +connection.onDocumentLinkResolve((link) => { + link.target = URI.file('/target.txt').toString() + return link +}) + +connection.onDocumentColor((_params) => { + return [ + ColorInformation.create(Range.create(1, 1, 1, 2), Color.create(1, 1, 1, 1)) + ] +}) + +connection.onColorPresentation((_params) => { + return [ + ColorPresentation.create('label') + ] +}) + +connection.onFoldingRanges((_params) => { + return [ + FoldingRange.create(1, 2) + ] +}) + +connection.onImplementation((params) => { + assert.equal(params.position.line, 1) + assert.equal(params.position.character, 1) + return {uri: params.textDocument.uri, range: {start: {line: 2, character: 2}, end: {line: 3, character: 3}}} +}) + +connection.onSelectionRanges((_params) => { + return [ + SelectionRange.create(Range.create(1, 2, 3, 4)) + ] +}) + +let lastFileOperationRequest +connection.workspace.onDidCreateFiles((params) => {lastFileOperationRequest = {type: 'create', params}}) +connection.workspace.onDidRenameFiles((params) => {lastFileOperationRequest = {type: 'rename', params}}) +connection.workspace.onDidDeleteFiles((params) => {lastFileOperationRequest = {type: 'delete', params}}) + +connection.onRequest( + new ProtocolRequestType('testing/lastFileOperationRequest'), + () => { + return lastFileOperationRequest + }, +) + +connection.workspace.onWillCreateFiles((params) => { + const createdFilenames = params.files.map((f) => `${f.uri}`).join('\n') + return { + documentChanges: [{ + textDocument: {uri: '/dummy-edit', version: null}, + edits: [ + TextEdit.insert(Position.create(0, 0), `WILL CREATE:\n${createdFilenames}`), + ] + }], + } +}) + +connection.workspace.onWillRenameFiles((params) => { + const renamedFilenames = params.files.map((f) => `${f.oldUri} -> ${f.newUri}`).join('\n') + return { + documentChanges: [{ + textDocument: {uri: '/dummy-edit', version: null}, + edits: [ + TextEdit.insert(Position.create(0, 0), `WILL RENAME:\n${renamedFilenames}`), + ] + }], + } +}) + +connection.workspace.onWillDeleteFiles((params) => { + const deletedFilenames = params.files.map((f) => `${f.uri}`).join('\n') + return { + documentChanges: [{ + textDocument: {uri: '/dummy-edit', version: null}, + edits: [ + TextEdit.insert(Position.create(0, 0), `WILL DELETE:\n${deletedFilenames}`), + ] + }], + } +}) + +connection.onTypeDefinition((params) => { + assert.equal(params.position.line, 1) + assert.equal(params.position.character, 1) + return {uri: params.textDocument.uri, range: {start: {line: 2, character: 2}, end: {line: 3, character: 3}}} +}) + +connection.languages.callHierarchy.onPrepare((params) => { + return [ + { + kind: SymbolKind.Function, + name: 'name', + range: Range.create(1, 1, 1, 1), + selectionRange: Range.create(2, 2, 2, 2), + uri: params.textDocument.uri + } + ] +}) + +connection.languages.callHierarchy.onIncomingCalls((params) => { + return [ + { + from: params.item, + fromRanges: [Range.create(1, 1, 1, 1)] + } + ] +}) + +connection.languages.callHierarchy.onOutgoingCalls((params) => { + return [ + { + to: params.item, + fromRanges: [Range.create(1, 1, 1, 1)] + } + ] +}) + +connection.languages.semanticTokens.onRange(() => { + return { + resultId: '1', + data: [] + } +}) + +connection.languages.semanticTokens.on(() => { + return { + resultId: '2', + data: [] + } +}) + +connection.languages.semanticTokens.onDelta(() => { + return { + resultId: '3', + data: [] + } +}) + +connection.languages.onLinkedEditingRange(() => { + return { + ranges: [Range.create(1, 1, 1, 1)], + wordPattern: '\\w' + } +}) + +connection.onRequest( + new ProtocolRequestType('testing/sendSampleProgress'), + async (_, __) => { + const progressToken = 'TEST-PROGRESS-TOKEN' + await connection.sendRequest(WorkDoneProgressCreateRequest.type, {token: progressToken}) + connection.sendProgress(WorkDoneProgress.type, progressToken, {kind: 'begin', title: 'Test Progress'}) + connection.sendProgress(WorkDoneProgress.type, progressToken, {kind: 'report', percentage: 50, message: 'Halfway!'}) + connection.sendProgress(WorkDoneProgress.type, progressToken, {kind: 'end', message: 'Completed!'}) + }, +) + +// Listen on the connection +connection.listen() diff --git a/vim-config/plugins/coc.nvim/src/__tests__/coc-settings.json b/vim-config/plugins/coc.nvim/src/__tests__/coc-settings.json new file mode 100644 index 00000000..365a52e8 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/coc-settings.json @@ -0,0 +1,5 @@ +{ + "suggest.timeout": 5000, + "suggest.triggerCompletionWait": 10, + "tslint.enable": false +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/completion/basic.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/completion/basic.test.ts new file mode 100644 index 00000000..6ee1aa8c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/completion/basic.test.ts @@ -0,0 +1,446 @@ +import { Neovim } from '@chemzqm/neovim' +import { ISource, SourceType, CompleteResult, CompleteOption } from '../../types' +import helper from '../helper' +import sources from '../../sources' +import { CancellationToken } from 'vscode-jsonrpc' + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('completion', () => { + + it('should not show word of word source on empty input', async () => { + await nvim.setLine('foo bar') + await helper.wait(200) + await nvim.input('of') + let res = await helper.visible('foo', 'around') + expect(res).toBe(true) + await nvim.input('') + await helper.wait(200) + res = await helper.notVisible('foo') + expect(res).toBe(true) + }) + + it('should trigger on first letter insert', async () => { + await helper.edit() + await nvim.setLine('foo bar') + await helper.wait(30) + await nvim.input('of') + let res = await helper.visible('foo', 'around') + expect(res).toBe(true) + }) + + it('should trigger on force refresh', async () => { + await helper.edit() + await nvim.setLine('foo f') + await helper.wait(100) + await nvim.input('A') + await helper.wait(10) + await nvim.call('coc#start') + let res = await helper.visible('foo', 'around') + expect(res).toBe(true) + }) + + it('should filter and sort on increment search', async () => { + await helper.edit() + await nvim.setLine('forceDocumentSync format fallback') + await helper.wait(30) + await nvim.input('of') + await helper.waitPopup() + let items = await helper.getItems() + let l = items.length + await nvim.input('oa') + await helper.wait(100) + items = await helper.getItems() + expect(items.findIndex(o => o.word == 'fallback')).toBe(-1) + expect(items.length).toBeLessThan(l) + }) + + it('should filter on character remove by backspace', async () => { + await helper.edit() + await nvim.setLine('forceDocumentSync format fallback') + await helper.wait(30) + await nvim.input('ofa') + + await helper.waitPopup() + let items = await helper.getItems() + let words = items.map(o => o.word) + expect(words).toContain('fallback') + expect(words).toContain('format') + await nvim.input('') + await helper.wait(100) + items = await helper.getItems() + words = items.map(o => o.word) + expect(words).toEqual([]) + }) + + it('should not trigger on insert enter', async () => { + await helper.edit() + await nvim.setLine('foo bar') + await helper.wait(30) + await nvim.input('o') + let visible = await nvim.call('pumvisible') + expect(visible).toBe(0) + }) + + it('should filter on fast input', async () => { + await helper.edit() + await nvim.setLine('foo bar') + await helper.wait(60) + await nvim.input('oba') + await helper.waitPopup() + let items = await helper.getItems() + let item = items.find(o => o.word == 'foo') + expect(item).toBeFalsy() + expect(items[0].word).toBe('bar') + }) + + it('should fix start column', async () => { + await helper.edit() + let source: ISource = { + name: 'test', + priority: 10, + enable: true, + firstMatch: false, + sourceType: SourceType.Native, + triggerCharacters: [], + doComplete: async (): Promise => { + let result: CompleteResult = { + startcol: 0, + items: [{ word: 'foo.bar' }] + } + return Promise.resolve(result) + } + } + let disposable = sources.addSource(source) + await nvim.setLine('foo.') + await nvim.input('Ab') + await helper.waitPopup() + let val = await nvim.getVar('coc#_context') as any + expect(val.start).toBe(0) + disposable.dispose() + }) + + it('should stop completion when type none trigger character', async () => { + await helper.edit() + let source: ISource = { + name: 'test', + priority: 10, + enable: true, + firstMatch: false, + sourceType: SourceType.Native, + triggerCharacters: [], + doComplete: async (): Promise => { + let result: CompleteResult = { + items: [{ word: 'if(' }] + } + return Promise.resolve(result) + } + } + let disposable = sources.addSource(source) + await nvim.setLine('') + await nvim.input('iif') + await helper.waitPopup() + await nvim.input('(') + await helper.wait(300) + let res = await helper.pumvisible() + expect(res).toBe(true) + disposable.dispose() + }) + + it('should trigger on triggerCharacters', async () => { + await helper.edit() + let source: ISource = { + name: 'trigger', + priority: 10, + enable: true, + sourceType: SourceType.Native, + triggerCharacters: ['.'], + doComplete: async (): Promise => Promise.resolve({ + items: [{ word: 'foo' }] + }) + } + sources.addSource(source) + await nvim.input('i') + await helper.wait(30) + await nvim.input('.') + await helper.waitPopup() + sources.removeSource(source) + let res = await helper.visible('foo', 'trigger') + expect(res).toBe(true) + }) + + it('should should complete items without input', async () => { + await helper.edit() + let source: ISource = { + enable: true, + name: 'trigger', + priority: 10, + sourceType: SourceType.Native, + doComplete: async (): Promise => Promise.resolve({ + items: [{ word: 'foo' }, { word: 'bar' }] + }) + } + let disposable = sources.addSource(source) + await nvim.command('inoremap coc#refresh()') + await nvim.input('i') + await helper.wait(30) + await nvim.input('') + await helper.waitPopup() + let items = await helper.getItems() + expect(items.length).toBeGreaterThan(1) + disposable.dispose() + await helper.wait(300) + }) + + it('should show float window', async () => { + await helper.edit() + let source: ISource = { + name: 'float', + priority: 10, + enable: true, + sourceType: SourceType.Native, + doComplete: (): Promise => Promise.resolve({ + items: [{ word: 'foo', info: 'bar' }] + }) + } + sources.addSource(source) + await nvim.input('i') + await helper.wait(30) + await nvim.input('f') + await helper.waitPopup() + await nvim.eval('feedkeys("\\","in")') + await helper.wait(800) + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(1) + sources.removeSource(source) + let res = await helper.visible('foo', 'float') + expect(res).toBe(true) + }) + + it('should trigger on triggerPatterns', async () => { + await helper.edit() + let source: ISource = { + name: 'pattern', + priority: 10, + enable: true, + sourceType: SourceType.Native, + triggerPatterns: [/\w+\.$/], + doComplete: async (): Promise => Promise.resolve({ + items: [{ word: 'foo' }] + }) + } + sources.addSource(source) + await nvim.input('i') + await helper.wait(10) + await nvim.input('.') + await helper.wait(30) + let pumvisible = await nvim.call('pumvisible') + expect(pumvisible).toBe(0) + await nvim.input('a') + await helper.wait(30) + await nvim.input('.') + await helper.waitPopup() + sources.removeSource(source) + let res = await helper.visible('foo', 'pattern') + expect(res).toBe(true) + }) + + it('should not trigger triggerOnly source', async () => { + await helper.edit() + await nvim.setLine('foo bar') + let source: ISource = { + name: 'pattern', + triggerOnly: true, + priority: 10, + enable: true, + sourceType: SourceType.Native, + triggerPatterns: [/^From:\s*/], + doComplete: async (): Promise => Promise.resolve({ + items: [{ word: 'foo' }] + }) + } + let disposable = sources.addSource(source) + await nvim.input('o') + await helper.wait(10) + await nvim.input('f') + await helper.wait(10) + let res = await helper.visible('foo', 'around') + expect(res).toBe(true) + let items = await helper.items() + expect(items.length).toBe(1) + disposable.dispose() + }) + + it('should not trigger when cursor moved', async () => { + await helper.edit() + let source: ISource = { + name: 'trigger', + priority: 10, + enable: true, + sourceType: SourceType.Native, + triggerCharacters: ['.'], + doComplete: async (): Promise => Promise.resolve({ + items: [{ word: 'foo' }] + }) + } + sources.addSource(source) + await nvim.setLine('.a') + await nvim.input('A') + await nvim.eval('feedkeys("\\")') + await helper.wait(10) + await nvim.eval('feedkeys("\\")') + await helper.wait(200) + let visible = await nvim.call('pumvisible') + expect(visible).toBe(0) + sources.removeSource(source) + }) + + it('should trigger when completion is not completed', async () => { + await helper.edit() + let token: CancellationToken + let source: ISource = { + name: 'completion', + priority: 10, + enable: true, + sourceType: SourceType.Native, + triggerCharacters: ['.'], + doComplete: async (opt, cancellationToken): Promise => { + if (opt.triggerCharacter != '.') { + token = cancellationToken + return new Promise((resolve, reject) => { + let timer = setTimeout(() => { + resolve({ items: [{ word: 'foo' }] }) + }, 200) + if (cancellationToken.isCancellationRequested) { + clearTimeout(timer) + reject(new Error('Cancelled')) + } + }) + } + return Promise.resolve({ + items: [{ word: 'bar' }] + }) + } + } + let disposable = sources.addSource(source) + await nvim.input('if') + await helper.wait(100) + await nvim.input('.') + await helper.visible('bar', 'completion') + expect(token.isCancellationRequested).toBe(true) + disposable.dispose() + }) + + it('should limit results for low priority source', async () => { + helper.updateConfiguration('suggest.lowPrioritySourceLimit', 2) + await nvim.setLine('filename filepath find filter findIndex') + await helper.wait(200) + await nvim.input('of') + await helper.waitPopup() + let items = await helper.getItems() + items = items.filter(o => o.menu == '[A]') + expect(items.length).toBe(2) + }) + + it('should limit result for high priority source', async () => { + helper.updateConfiguration('suggest.highPrioritySourceLimit', 2) + await helper.edit() + let source: ISource = { + name: 'high', + priority: 90, + enable: true, + sourceType: SourceType.Native, + triggerCharacters: ['.'], + doComplete: async (): Promise => Promise.resolve({ + items: ['filename', 'filepath', 'filter', 'file'].map(key => ({ word: key })) + }) + } + let disposable = sources.addSource(source) + await nvim.input('i') + await helper.wait(30) + await nvim.input('.') + await helper.waitPopup() + let items = await helper.getItems() + expect(items.length).toBeGreaterThan(1) + disposable.dispose() + }) + + it('should truncate label of complete items', async () => { + helper.updateConfiguration('suggest.labelMaxLength', 10) + await helper.edit() + let source: ISource = { + name: 'high', + priority: 90, + enable: true, + sourceType: SourceType.Native, + triggerCharacters: ['.'], + doComplete: async (): Promise => Promise.resolve({ + items: ['a', 'b', 'c', 'd'].map(key => ({ word: key.repeat(20) })) + }) + } + let disposable = sources.addSource(source) + await nvim.input('i') + await helper.wait(30) + await nvim.input('.') + await helper.waitPopup() + let items = await helper.getItems() + for (let item of items) { + expect(item.abbr.length).toBeLessThanOrEqual(10) + } + disposable.dispose() + }) + + it('should delete previous items if complete item is null', async () => { + await helper.edit() + let source1: ISource = { + name: 'source1', + priority: 90, + enable: true, + sourceType: SourceType.Native, + triggerCharacters: ['.'], + doComplete: async (): Promise => Promise.resolve({ + items: [ {word: 'foo', dup: 1} ] + }) + } + let source2: ISource = { + name: 'source2', + priority: 90, + enable: true, + sourceType: SourceType.Native, + triggerCharacters: ['.'], + doComplete: async (opt: CompleteOption): Promise => { + let result: CompleteResult = opt.input == 'foo' ? null : { + items: [{ word: 'foo', dup: 1 }], isIncomplete: true + } + return Promise.resolve(result) + } + } + let disposable1 = sources.addSource(source1) + let disposable2 = sources.addSource(source2) + await nvim.input('i') + await helper.wait(30) + await nvim.input('.f') + await helper.waitPopup() + let items = await helper.getItems() + expect(items.length).toEqual(2) + await nvim.input('oo') + await helper.waitPopup() + items = await helper.getItems() + expect(items.length).toEqual(1) + expect(items[0].word).toBe('foo') + disposable1.dispose() + disposable2.dispose() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/completion/float.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/completion/float.test.ts new file mode 100644 index 00000000..049bdcae --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/completion/float.test.ts @@ -0,0 +1,122 @@ +import { Neovim } from '@chemzqm/neovim' +import sources from '../../sources' +import { CompleteResult, ISource, SourceType } from '../../types' +import helper from '../helper' + +let nvim: Neovim +let source: ISource +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + source = { + name: 'float', + priority: 10, + enable: true, + sourceType: SourceType.Native, + doComplete: (): Promise => Promise.resolve({ + items: [{ + word: 'foo', + info: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' + }, { + word: 'foot', + info: 'foot' + }, { + word: 'football', + }] + }) + } + sources.addSource(source) +}) + +afterAll(async () => { + sources.removeSource(source) + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('completion float', () => { + + it('should not show float window when disabled', async () => { + helper.updateConfiguration('suggest.floatEnable', false) + await helper.edit() + await nvim.input('if') + await helper.visible('foo', 'float') + helper.updateConfiguration('suggest.floatEnable', true) + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(0) + }) + + it('should cancel float window', async () => { + await helper.edit() + await nvim.input('if') + await helper.visible('foo', 'float') + let items = await helper.getItems() + expect(items[0].word).toBe('foo') + expect(items[0].info.length > 0).toBeTruthy() + await nvim.input('') + await helper.wait(500) + await nvim.input('') + await helper.wait(100) + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(0) + }) + + it('should adjust float window position', async () => { + await helper.edit() + await nvim.setLine(' '.repeat(70)) + await nvim.input('Af') + await helper.visible('foo', 'float') + await nvim.input('') + await helper.wait(300) + let floatWin = await helper.getFloat() + let config = await floatWin.getConfig() + expect(config.col + config.width).toBeLessThan(180) + }) + + it('should redraw float window on item change', async () => { + await helper.edit() + await nvim.setLine(' '.repeat(70)) + await nvim.input('Af') + await helper.visible('foo', 'float') + await nvim.input('') + await helper.wait(50) + await nvim.input('') + await helper.wait(300) + let floatWin = await helper.getFloat() + let buf = await floatWin.buffer + let lines = await buf.lines + expect(lines.length).toBeGreaterThan(0) + expect(lines[0]).toMatch('foot') + }) + + it('should hide float window when item info is empty', async () => { + await helper.edit() + await nvim.setLine(' '.repeat(70)) + await nvim.input('Af') + await helper.visible('foo', 'float') + await nvim.input('') + await helper.wait(10) + await nvim.input('') + await helper.wait(10) + await nvim.input('') + await helper.wait(100) + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(0) + }) + + it('should hide float window after completion', async () => { + await helper.edit() + await nvim.setLine(' '.repeat(70)) + await nvim.input('Af') + await helper.visible('foo', 'float') + await nvim.input('') + await helper.wait(100) + await nvim.input('') + await helper.wait(30) + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(0) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/completion/match.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/completion/match.test.ts new file mode 100644 index 00000000..91c7083d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/completion/match.test.ts @@ -0,0 +1,66 @@ +import { matchScore } from '../../completion/match' +import { getCharCodes } from '../../util/fuzzy' + +function score(word: string, input: string): number { + return matchScore(word, getCharCodes(input)) +} + +describe('matchScore', () => { + + it('should match score for last letter', () => { + expect(score('#!3', '3')).toBe(1) + }) + + it('should match first letter', () => { + expect(score('abc', 'a')).toBe(5) + expect(score('Abc', 'a')).toBe(2.5) + expect(score('__abc', 'a')).toBe(2.5) + expect(score('$Abc', 'a')).toBe(2) + expect(score('$Abc', 'A')).toBe(2.5) + expect(score('$Abc', '$A')).toBe(6) + expect(score('$Abc', '$a')).toBe(5.5) + expect(score('foo_bar', 'b')).toBe(2.5) + expect(score('foo_Bar', 'b')).toBe(2) + expect(score('_foo_Bar', 'b')).toBe(0.5) + expect(score('_foo_Bar', 'f')).toBe(2.5) + expect(score('bar', 'a')).toBe(1) + expect(score('fooBar', 'B')).toBe(2.5) + expect(score('fooBar', 'b')).toBe(2) + }) + + it('should match follow letters', () => { + expect(score('abc', 'ab')).toBe(6) + expect(score('adB', 'ab')).toBe(5.75) + expect(score('adb', 'ab')).toBe(5.1) + expect(score('adCB', 'ab')).toBe(5.05) + expect(score('a_b_c', 'ab')).toBe(6) + expect(score('FooBar', 'fb')).toBe(3.25) + expect(score('FBar', 'fb')).toBe(3) + expect(score('FooBar', 'FB')).toBe(6) + expect(score('FBar', 'FB')).toBe(6) + expect(score('a__b', 'a__b')).toBe(8) + expect(score('aBc', 'ab')).toBe(5.5) + expect(score('a_B_c', 'ab')).toBe(5.75) + expect(score('abc', 'abc')).toBe(7) + expect(score('abc', 'aC')).toBe(0) + expect(score('abc', 'ac')).toBe(5.1) + expect(score('abC', 'ac')).toBe(5.75) + expect(score('abC', 'aC')).toBe(6) + }) + + it('should only allow search once', () => { + expect(score('foobar', 'fbr')).toBe(0) + expect(score('foobaRow', 'fbr')).toBe(5.85) + expect(score('foobaRow', 'fbR')).toBe(6.1) + expect(score('foobar', 'fa')).toBe(5.1) + }) + + it('should have higher score for strict match', () => { + expect(score('language-client-protocol', 'lct')).toBe(6.1) + expect(score('language-client-types', 'lct')).toBe(7) + }) + + it('should find highest score', () => { + expect(score('ArrayRotateTail', 'art')).toBe(4) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/completion/sources.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/completion/sources.test.ts new file mode 100644 index 00000000..478e24dc --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/completion/sources.test.ts @@ -0,0 +1,92 @@ +import { Neovim } from '@chemzqm/neovim' +import helper from '../helper' +import { ISource, SourceType, CompleteResult } from '../../types' +import sources from '../../sources' + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('native sources', () => { + + it('should works for around source', async () => { + await helper.createDocument() + await nvim.setLine('foo ') + await helper.wait(100) + let { mode } = await nvim.mode + expect(mode).toBe('n') + await nvim.input('Af') + let res = await helper.visible('foo', 'around') + expect(res).toBe(true) + await nvim.input('') + }) + + it('should works for buffer source', async () => { + await nvim.command('set hidden') + await helper.createDocument() + await helper.createDocument() + await nvim.setLine('other') + await nvim.command('bp') + await helper.wait(300) + let { mode } = await nvim.mode + expect(mode).toBe('n') + await nvim.input('io') + let res = await helper.visible('other', 'buffer') + expect(res).toBe(true) + }) + + it('should works for file source', async () => { + await helper.edit() + await nvim.input('i/') + await helper.waitPopup() + let items = await helper.getItems() + expect(items.length).toBeGreaterThan(0) + let res = await helper.visible(items[0].word, 'file') + expect(res).toBe(true) + await nvim.input('') + await nvim.input('o./') + await helper.waitPopup() + items = await helper.getItems() + let item = items.find(o => o.word == 'vimrc') + expect(item).toBeTruthy() + }) + + it('should works for file source with other source use same triggerCharacter', async () => { + await helper.edit() + let source: ISource = { + name: 'test', + priority: 50, + enable: true, + firstMatch: false, + sourceType: SourceType.Native, + triggerCharacters: ['.', '/'], + doComplete: async (): Promise => { + let result: CompleteResult = { + items: [{ word: 'foo' }] + } + return Promise.resolve(result) + } + } + let disposable = sources.addSource(source) + await nvim.input('i.') + await helper.waitPopup() + let items = await helper.getItems() + expect(items.length).toBe(1) + await nvim.input('/') + await helper.waitPopup() + items = await helper.getItems() + expect(items.length).toBeGreaterThan(1) + expect(items[0].word).toBe('foo') + disposable.dispose() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/completion/util.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/completion/util.test.ts new file mode 100644 index 00000000..477f7cdf --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/completion/util.test.ts @@ -0,0 +1,32 @@ +import { CompletionItemKind, TextEdit, Position } from 'vscode-languageserver-types' +import { getStartColumn, getKindString } from '../../sources/source-language' + +describe('getKindString()', () => { + it('should get kind text', async () => { + let map = new Map() + map.set(CompletionItemKind.Enum, 'E') + let res = getKindString(CompletionItemKind.Enum, map, '') + expect(res).toBe('E') + }) + + it('should get default value', async () => { + let map = new Map() + let res = getKindString(CompletionItemKind.Enum, map, 'D') + expect(res).toBe('D') + }) +}) + +describe('getStartColumn()', () => { + it('should get start col', async () => { + expect(getStartColumn('', [{ label: 'foo' }])).toBe(null) + expect(getStartColumn('', [ + { label: 'foo', textEdit: TextEdit.insert(Position.create(0, 0), 'a') }, + { label: 'bar' }])).toBe(null) + expect(getStartColumn('foo', [ + { label: 'foo', textEdit: TextEdit.insert(Position.create(0, 0), 'a') }, + { label: 'bar', textEdit: TextEdit.insert(Position.create(0, 1), 'b') }])).toBe(null) + expect(getStartColumn('foo', [ + { label: 'foo', textEdit: TextEdit.insert(Position.create(0, 2), 'a') }, + { label: 'bar', textEdit: TextEdit.insert(Position.create(0, 2), 'b') }])).toBe(2) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/extensions/global/index.js b/vim-config/plugins/coc.nvim/src/__tests__/extensions/global/index.js new file mode 100644 index 00000000..e48cb515 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/extensions/global/index.js @@ -0,0 +1,7 @@ +exports.activate = async context => { + return { + getContext: () => { + return context + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/extensions/global/package.json b/vim-config/plugins/coc.nvim/src/__tests__/extensions/global/package.json new file mode 100644 index 00000000..784d43bd --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/extensions/global/package.json @@ -0,0 +1,7 @@ +{ + "name": "global", + "version": "1.0.0", + "engines": { + "coc": "^0.0.46" + } +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/extensions/package.json b/vim-config/plugins/coc.nvim/src/__tests__/extensions/package.json new file mode 100644 index 00000000..cc903b48 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/extensions/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "global": ">=1.0.0", + "test": ">=1.0.0" + } +} \ No newline at end of file diff --git a/vim-config/plugins/coc.nvim/src/__tests__/extensions/root.js b/vim-config/plugins/coc.nvim/src/__tests__/extensions/root.js new file mode 100644 index 00000000..0e76809f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/extensions/root.js @@ -0,0 +1,7 @@ +exports.activate = context => { + return { + root: () => { + return context.extensionPath + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/extensions/test/index.js b/vim-config/plugins/coc.nvim/src/__tests__/extensions/test/index.js new file mode 100644 index 00000000..f8d2f71a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/extensions/test/index.js @@ -0,0 +1,13 @@ +exports.activate = async context => { + return { + asAbsolutePath: p => { + return context.asAbsolutePath(p) + }, + getContext: () => { + return context + }, + echo: x => { + return x + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/extensions/test/package.json b/vim-config/plugins/coc.nvim/src/__tests__/extensions/test/package.json new file mode 100644 index 00000000..4993d0aa --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/extensions/test/package.json @@ -0,0 +1,33 @@ +{ + "name": "test", + "version": "1.0.0", + "engines": { + "coc": "^0.0.46" + }, + "contributes": { + "rootPatterns": [ + { + "filetype": "javascript", + "patterns": [ + "package.json", + "jsconfig.json" + ] + } + ], + "commands": [ + { + "title": "Test", + "command": "test.run" + } + ], + "configuration": { + "properties": { + "test.enable": { + "type": "boolean", + "default": true, + "description": "Enable test" + } + } + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/extensions/vim/local/index.js b/vim-config/plugins/coc.nvim/src/__tests__/extensions/vim/local/index.js new file mode 100644 index 00000000..e48cb515 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/extensions/vim/local/index.js @@ -0,0 +1,7 @@ +exports.activate = async context => { + return { + getContext: () => { + return context + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/extensions/vim/local/package.json b/vim-config/plugins/coc.nvim/src/__tests__/extensions/vim/local/package.json new file mode 100644 index 00000000..95a64e73 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/extensions/vim/local/package.json @@ -0,0 +1,7 @@ +{ + "name": "local", + "version": "1.0.0", + "engines": { + "coc": "^0.0.46" + } +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/callHierarchy.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/callHierarchy.test.ts new file mode 100644 index 00000000..f0048e11 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/callHierarchy.test.ts @@ -0,0 +1,398 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, CallHierarchyItem, SymbolKind, Range, SymbolTag } from 'vscode-languageserver-protocol' +import CallHierarchyHandler from '../../handler/callHierarchy' +import languages from '../../languages' +import workspace from '../../workspace' +import { disposeAll } from '../../util' +import { URI } from 'vscode-uri' +import helper, { createTmpFile } from '../helper' + +let nvim: Neovim +let callHierarchy: CallHierarchyHandler +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + callHierarchy = helper.plugin.getHandler().callHierarchy +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + await helper.createDocument() +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +function createCallItem(name: string, kind: SymbolKind, uri: string, range: Range): CallHierarchyItem { + return { + name, + kind, + uri, + range, + selectionRange: range + } +} + +describe('CallHierarchy', () => { + it('should throw for when provider not exists', async () => { + let err + try { + await callHierarchy.getIncoming() + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should get undefined when prepare failed', async () => { + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return undefined + }, + provideCallHierarchyIncomingCalls() { + return [] + }, + provideCallHierarchyOutgoingCalls() { + return [] + } + })) + let res = await callHierarchy.getOutgoing() + expect(res).toBeUndefined() + }) + + it('should get incoming & outgoing callHierarchy items', async () => { + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return createCallItem('foo', SymbolKind.Class, 'test:///foo', Range.create(0, 0, 0, 5)) + }, + provideCallHierarchyIncomingCalls() { + return [{ + from: createCallItem('bar', SymbolKind.Class, 'test:///bar', Range.create(1, 0, 1, 5)), + fromRanges: [Range.create(0, 0, 0, 5)] + }] + }, + provideCallHierarchyOutgoingCalls() { + return [{ + to: createCallItem('bar', SymbolKind.Class, 'test:///bar', Range.create(1, 0, 1, 5)), + fromRanges: [Range.create(1, 0, 1, 5)] + }] + } + })) + let res = await callHierarchy.getIncoming() + expect(res.length).toBe(1) + expect(res[0].from.name).toBe('bar') + let outgoing = await callHierarchy.getOutgoing() + expect(outgoing.length).toBe(1) + res = await callHierarchy.getIncoming(outgoing[0].to) + expect(res.length).toBe(1) + }) + + it('should show message when provider not exists', async () => { + await callHierarchy.showCallHierarchyTree('incoming') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines[0]).toMatch('callHierarchy provider not found') + await nvim.command('wincmd p') + }) + + it('should no results when no result returned.', async () => { + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return [] + }, + provideCallHierarchyIncomingCalls() { + return [] + }, + provideCallHierarchyOutgoingCalls() { + return [] + } + })) + await callHierarchy.showCallHierarchyTree('incoming') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines[0]).toBe('No results') + await nvim.command('wincmd p') + }) + + it('should render description and support default action', async () => { + let doc = await workspace.document + let bufnr = doc.bufnr + await doc.buffer.setLines(['foo'], { start: 0, end: -1, strictIndexing: false }) + let fsPath = await createTmpFile('foo\nbar\ncontent\n') + let uri = URI.file(fsPath).toString() + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return createCallItem('foo', SymbolKind.Class, doc.uri, Range.create(0, 0, 0, 3)) + }, + provideCallHierarchyIncomingCalls() { + let item = createCallItem('bar', SymbolKind.Class, uri, Range.create(1, 0, 1, 3)) + item.detail = 'Detail' + item.tags = [SymbolTag.Deprecated] + return [{ + from: item, + fromRanges: [Range.create(2, 0, 2, 5)] + }] + }, + provideCallHierarchyOutgoingCalls() { + return [] + } + })) + await callHierarchy.showCallHierarchyTree('incoming') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual([ + 'INCOMING CALLS', + '- c foo', + ' + c bar Detail' + ]) + await nvim.command('exe 3') + await nvim.input('t') + await helper.wait(50) + let line = await nvim.line + expect(line).toEqual(' - c bar Detail') + await nvim.input('') + await helper.wait(50) + doc = await workspace.document + expect(doc.uri).toBe(uri) + let res = await nvim.call('coc#cursor#position') + expect(res).toEqual([1, 0]) + let matches = await nvim.call('getmatches') as any[] + expect(matches.length).toBe(2) + await nvim.command(`b ${bufnr}`) + await helper.wait(50) + matches = await nvim.call('getmatches') + expect(matches.length).toBe(0) + await nvim.command(`wincmd o`) + await helper.wait(50) + }) + + it('should invoke open in new tab action', async () => { + let doc = await workspace.document + await doc.buffer.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + let fsPath = await createTmpFile('foo\nbar\ncontent\n') + let uri = URI.file(fsPath).toString() + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return createCallItem('foo', SymbolKind.Class, doc.uri, Range.create(0, 0, 0, 3)) + }, + provideCallHierarchyIncomingCalls() { + return [] + }, + provideCallHierarchyOutgoingCalls() { + let item = createCallItem('bar', SymbolKind.Class, uri, Range.create(0, 0, 0, 1)) + item.detail = 'Detail' + return [{ + to: item, + fromRanges: [Range.create(1, 0, 1, 3)] + }] + } + })) + let win = await nvim.window + let tab = await nvim.call('tabpagenr') + await callHierarchy.showCallHierarchyTree('outgoing') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual([ + 'OUTGOING CALLS', + '- c foo', + ' + c bar Detail' + ]) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + await nvim.input('') + await helper.wait(200) + let newTab = await nvim.call('tabpagenr') + expect(newTab != tab).toBe(true) + doc = await workspace.document + expect(doc.uri).toBe(uri) + let res = await nvim.call('getmatches', [win.id]) + expect(res.length).toBe(1) + }) + + it('should invoke show incoming calls action', async () => { + let doc = await workspace.document + await doc.buffer.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + let fsPath = await createTmpFile('foo\nbar\ncontent\n') + let uri = URI.file(fsPath).toString() + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return createCallItem('foo', SymbolKind.Class, doc.uri, Range.create(0, 0, 0, 3)) + }, + provideCallHierarchyIncomingCalls() { + return [{ + from: createCallItem('test', SymbolKind.Class, 'test:///bar', Range.create(1, 0, 1, 5)), + fromRanges: [Range.create(0, 0, 0, 5)] + }] + }, + provideCallHierarchyOutgoingCalls() { + let item = createCallItem('bar', SymbolKind.Class, uri, Range.create(0, 0, 0, 1)) + item.detail = 'Detail' + return [{ + to: item, + fromRanges: [Range.create(1, 0, 1, 3)] + }] + } + })) + await callHierarchy.showCallHierarchyTree('outgoing') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual([ + 'OUTGOING CALLS', + '- c foo', + ' + c bar Detail' + ]) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + await nvim.input('2') + await helper.wait(200) + lines = await buf.lines + expect(lines).toEqual([ + 'INCOMING CALLS', + '- c bar Detail', + ' + c test' + ]) + await nvim.command('bd!') + }) + + it('should invoke show outgoing calls action', async () => { + let doc = await workspace.document + await doc.buffer.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + let fsPath = await createTmpFile('foo\nbar\ncontent\n') + let uri = URI.file(fsPath).toString() + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return createCallItem('foo', SymbolKind.Class, doc.uri, Range.create(0, 0, 0, 3)) + }, + provideCallHierarchyIncomingCalls() { + return [{ + from: createCallItem('test', SymbolKind.Class, 'test:///bar', Range.create(1, 0, 1, 5)), + fromRanges: [Range.create(0, 0, 0, 5)] + }] + }, + provideCallHierarchyOutgoingCalls() { + let item = createCallItem('bar', SymbolKind.Class, uri, Range.create(0, 0, 0, 1)) + item.detail = 'Detail' + return [{ + to: item, + fromRanges: [Range.create(1, 0, 1, 3)] + }] + } + })) + await callHierarchy.showCallHierarchyTree('incoming') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual([ + 'INCOMING CALLS', + '- c foo', + ' + c test' + ]) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + await nvim.input('3') + await helper.wait(200) + lines = await buf.lines + expect(lines).toEqual([ + 'OUTGOING CALLS', + '- c test', + ' + c bar Detail' + ]) + await nvim.command('bd!') + }) + + it('should invoke dismiss action #1', async () => { + let doc = await workspace.document + await doc.buffer.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + let fsPath = await createTmpFile('foo\nbar\ncontent\n') + let uri = URI.file(fsPath).toString() + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return createCallItem('foo', SymbolKind.Class, doc.uri, Range.create(0, 0, 0, 3)) + }, + provideCallHierarchyIncomingCalls() { + return [] + }, + provideCallHierarchyOutgoingCalls() { + let item = createCallItem('bar', SymbolKind.Class, uri, Range.create(0, 0, 0, 1)) + item.detail = 'Detail' + return [{ + to: item, + fromRanges: [Range.create(1, 0, 1, 3)] + }] + } + })) + await callHierarchy.showCallHierarchyTree('outgoing') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual([ + 'OUTGOING CALLS', + '- c foo', + ' + c bar Detail' + ]) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + await nvim.input('4') + await helper.wait(200) + lines = await buf.lines + expect(lines).toEqual([ + 'OUTGOING CALLS', + '- c foo' + ]) + await nvim.command('wincmd c') + }) + + it('should invoke dismiss action #2', async () => { + let doc = await workspace.document + await doc.buffer.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + let fsPath = await createTmpFile('foo\nbar\ncontent\n') + let uri = URI.file(fsPath).toString() + disposables.push(languages.registerCallHierarchyProvider([{ language: '*' }], { + prepareCallHierarchy() { + return createCallItem('foo', SymbolKind.Class, doc.uri, Range.create(0, 0, 0, 3)) + }, + provideCallHierarchyIncomingCalls() { + return [] + }, + provideCallHierarchyOutgoingCalls() { + let item = createCallItem('bar', SymbolKind.Class, uri, Range.create(0, 0, 0, 1)) + item.detail = 'Detail' + return [{ + to: item, + fromRanges: [Range.create(1, 0, 1, 3)] + }] + } + })) + await callHierarchy.showCallHierarchyTree('outgoing') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual([ + 'OUTGOING CALLS', + '- c foo', + ' + c bar Detail' + ]) + await nvim.command('exe 3') + await nvim.input('t') + await helper.wait(50) + await nvim.command('exe 4') + await nvim.input('') + await helper.wait(50) + await nvim.input('4') + await helper.wait(200) + lines = await buf.lines + expect(lines).toEqual([ + 'OUTGOING CALLS', + '- c foo', + ' - c bar Detail' + ]) + await nvim.command('wincmd c') + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/codeActions.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/codeActions.test.ts new file mode 100644 index 00000000..d0b70c76 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/codeActions.test.ts @@ -0,0 +1,386 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationToken, CodeAction, Command, CodeActionContext, CodeActionKind, TextEdit, Disposable, Range, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import commands from '../../commands' +import ActionsHandler from '../../handler/codeActions' +import languages from '../../languages' +import { ProviderResult } from '../../provider' +import { disposeAll } from '../../util' +import { rangeInRange } from '../../util/position' +import helper from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] +let codeActions: ActionsHandler +let currActions: CodeAction[] +let resolvedAction: CodeAction +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + codeActions = helper.plugin.getHandler().codeActions +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + disposables.push(languages.registerCodeActionProvider([{ language: '*' }], { + provideCodeActions: ( + _document: TextDocument, + _range: Range, + _context: CodeActionContext, + _token: CancellationToken + ) => currActions, + resolveCodeAction: ( + _action: CodeAction, + _token: CancellationToken + ): ProviderResult => resolvedAction + }, undefined)) +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +describe('handler codeActions', () => { + describe('organizeImport', () => { + it('should throw error when organize import action not found', async () => { + currActions = [] + await helper.createDocument() + let err + try { + await codeActions.organizeImport() + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should perform organize import action', async () => { + let doc = await helper.createDocument() + await doc.buffer.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + let edits: TextEdit[] = [] + edits.push(TextEdit.replace(Range.create(0, 0, 0, 3), 'bar')) + edits.push(TextEdit.replace(Range.create(1, 0, 1, 3), 'foo')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('organize import', edit, CodeActionKind.SourceOrganizeImports) + currActions = [action, CodeAction.create('another action')] + await codeActions.organizeImport() + let lines = await doc.buffer.lines + expect(lines).toEqual(['bar', 'foo']) + }) + + it('should register editor.action.organizeImport command', async () => { + let doc = await helper.createDocument() + await doc.buffer.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + let edits: TextEdit[] = [] + edits.push(TextEdit.replace(Range.create(0, 0, 0, 3), 'bar')) + edits.push(TextEdit.replace(Range.create(1, 0, 1, 3), 'foo')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('organize import', edit, CodeActionKind.SourceOrganizeImports) + currActions = [action, CodeAction.create('another action')] + await commands.executeCommand('editor.action.organizeImport') + let lines = await doc.buffer.lines + expect(lines).toEqual(['bar', 'foo']) + }) + }) + + describe('codeActionRange', () => { + it('should show warning when no action available', async () => { + await helper.createDocument() + currActions = [] + await codeActions.codeActionRange(1, 2, CodeActionKind.QuickFix) + let line = await helper.getCmdline() + expect(line).toMatch(/No quickfix code action/) + }) + + it('should apply choosen action', async () => { + let doc = await helper.createDocument() + let edits: TextEdit[] = [] + edits.push(TextEdit.insert(Position.create(0, 0), 'bar')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('code fix', edit, CodeActionKind.QuickFix) + currActions = [action] + let p = codeActions.codeActionRange(1, 2, CodeActionKind.QuickFix) + await helper.wait(50) + await nvim.input('') + await p + let buf = nvim.createBuffer(doc.bufnr) + let lines = await buf.lines + expect(lines[0]).toBe('bar') + }) + }) + + describe('getCodeActions', () => { + it('should get empty actions', async () => { + currActions = [] + let doc = await helper.createDocument() + let res = await codeActions.getCodeActions(doc) + expect(res.length).toBe(0) + }) + + it('should filter disabled actions', async () => { + currActions = [] + let action = CodeAction.create('foo', CodeActionKind.QuickFix) + action.disabled = { reason: 'disabled' } + currActions.push(action) + action = CodeAction.create('foo', CodeActionKind.QuickFix) + action.disabled = { reason: 'disabled' } + currActions.push(action) + let doc = await helper.createDocument() + let res = await codeActions.getCodeActions(doc) + expect(res.length).toBe(0) + }) + + it('should get all actions', async () => { + let doc = await helper.createDocument() + await doc.buffer.setLines(['', '', ''], { start: 0, end: -1, strictIndexing: false }) + let action = CodeAction.create('curr action', CodeActionKind.Empty) + currActions = [action] + let range: Range + disposables.push(languages.registerCodeActionProvider([{ language: '*' }], { + provideCodeActions: ( + _document: TextDocument, + r: Range, + _context: CodeActionContext, _token: CancellationToken + ) => { + range = r + return [CodeAction.create('a'), CodeAction.create('b'), CodeAction.create('c')] + }, + }, undefined)) + let res = await codeActions.getCodeActions(doc) + expect(range).toEqual(Range.create(0, 0, 3, 0)) + expect(res.length).toBe(4) + }) + + it('should filter actions by range', async () => { + let doc = await helper.createDocument() + await doc.buffer.setLines(['', '', ''], { start: 0, end: -1, strictIndexing: false }) + currActions = [] + let range: Range + disposables.push(languages.registerCodeActionProvider([{ language: '*' }], { + provideCodeActions: ( + _document: TextDocument, + r: Range, + _context: CodeActionContext, _token: CancellationToken + ) => { + range = r + if (rangeInRange(r, Range.create(0, 0, 1, 0))) return [CodeAction.create('a')] + return [CodeAction.create('a'), CodeAction.create('b'), CodeAction.create('c')] + }, + }, undefined)) + let res = await codeActions.getCodeActions(doc, Range.create(0, 0, 0, 0)) + expect(range).toEqual(Range.create(0, 0, 0, 0)) + expect(res.length).toBe(1) + }) + + it('should filter actions by kind prefix', async () => { + let doc = await helper.createDocument() + let action = CodeAction.create('my action', CodeActionKind.SourceFixAll) + currActions = [action] + let res = await codeActions.getCodeActions(doc, undefined, [CodeActionKind.Source]) + expect(res.length).toBe(1) + expect(res[0].kind).toBe(CodeActionKind.SourceFixAll) + }) + }) + + describe('getCurrentCodeActions', () => { + let range: Range + beforeEach(() => { + disposables.push(languages.registerCodeActionProvider([{ language: '*' }], { + provideCodeActions: ( + _document: TextDocument, + r: Range, + _context: CodeActionContext, _token: CancellationToken + ) => { + range = r + return [CodeAction.create('a'), CodeAction.create('b'), CodeAction.create('c')] + }, + }, undefined)) + }) + + it('should get codeActions by line', async () => { + currActions = [] + await helper.createDocument() + let res = await codeActions.getCurrentCodeActions('line') + expect(range).toEqual(Range.create(0, 0, 1, 0)) + expect(res.length).toBe(3) + }) + + it('should get codeActions by cursor', async () => { + currActions = [] + await helper.createDocument() + let res = await codeActions.getCurrentCodeActions('cursor') + expect(range).toEqual(Range.create(0, 0, 0, 0)) + expect(res.length).toBe(3) + }) + + it('should get codeActions by visual mode', async () => { + currActions = [] + await helper.createDocument() + await nvim.setLine('foo') + await nvim.command('normal! 0v$') + await nvim.input('') + let res = await codeActions.getCurrentCodeActions('v') + expect(range).toEqual(Range.create(0, 0, 0, 4)) + expect(res.length).toBe(3) + }) + }) + + describe('doCodeAction', () => { + it('should not throw when no action exists', async () => { + currActions = [] + await helper.createDocument() + let err + try { + await codeActions.doCodeAction(undefined) + } catch (e) { + err = e + } + expect(err).toBeUndefined() + }) + + it('should apply single code action when only is title', async () => { + let doc = await helper.createDocument() + let edits: TextEdit[] = [] + edits.push(TextEdit.insert(Position.create(0, 0), 'bar')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('code fix', edit, CodeActionKind.QuickFix) + currActions = [action] + await codeActions.doCodeAction(undefined, 'code fix') + let lines = await doc.buffer.lines + expect(lines).toEqual(['bar']) + }) + + it('should apply single code action when only is codeAction array', async () => { + let doc = await helper.createDocument() + let edits: TextEdit[] = [] + edits.push(TextEdit.insert(Position.create(0, 0), 'bar')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('code fix', edit, CodeActionKind.QuickFix) + currActions = [action] + await codeActions.doCodeAction(undefined, [CodeActionKind.QuickFix]) + let lines = await doc.buffer.lines + expect(lines).toEqual(['bar']) + }) + + it('should action dialog to choose action', async () => { + let doc = await helper.createDocument() + let edits: TextEdit[] = [] + edits.push(TextEdit.insert(Position.create(0, 0), 'bar')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('code fix', edit, CodeActionKind.QuickFix) + currActions = [action, CodeAction.create('foo')] + let promise = codeActions.doCodeAction(null) + await helper.wait(50) + let ids = await nvim.call('coc#float#get_float_win_list') as number[] + expect(ids.length).toBeGreaterThan(0) + await nvim.input('') + await promise + let lines = await doc.buffer.lines + expect(lines).toEqual(['bar']) + }) + + it('should choose code actions by range', async () => { + let range: Range + disposables.push(languages.registerCodeActionProvider([{ language: '*' }], { + provideCodeActions: ( + _document: TextDocument, + r: Range, + _context: CodeActionContext, _token: CancellationToken + ) => { + range = r + return [CodeAction.create('my title'), CodeAction.create('b'), CodeAction.create('c')] + }, + }, undefined)) + await helper.createDocument() + await nvim.setLine('abc') + await nvim.command('normal! 0v$') + await nvim.input('') + await codeActions.doCodeAction('v', 'my title') + expect(range).toEqual({ start: { line: 0, character: 0 }, end: { line: 0, character: 4 } }) + }) + }) + + describe('doQuickfix', () => { + it('should throw when quickfix action not exists', async () => { + let err + currActions = [] + await helper.createDocument() + try { + await codeActions.doQuickfix() + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should do preferred quickfix action', async () => { + let doc = await helper.createDocument() + let edits: TextEdit[] = [] + edits.push(TextEdit.insert(Position.create(0, 0), 'bar')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('code fix', edit, CodeActionKind.QuickFix) + action.isPreferred = true + currActions = [CodeAction.create('foo', CodeActionKind.QuickFix), action, CodeAction.create('bar')] + await codeActions.doQuickfix() + let lines = await doc.buffer.lines + expect(lines).toEqual(['bar']) + }) + }) + + describe('applyCodeAction', () => { + it('should resolve codeAction', async () => { + let doc = await helper.createDocument() + let edits: TextEdit[] = [] + edits.push(TextEdit.insert(Position.create(0, 0), 'bar')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('code fix', CodeActionKind.QuickFix) + action.isPreferred = true + currActions = [action] + resolvedAction = Object.assign({ edit }, action) + let arr = await codeActions.getCurrentCodeActions('line', [CodeActionKind.QuickFix]) + await codeActions.applyCodeAction(arr[0]) + let lines = await doc.buffer.lines + expect(lines).toEqual(['bar']) + }) + + it('should throw for disabled action', async () => { + let action = CodeAction.create('my action', CodeActionKind.Empty) + action.disabled = { reason: 'disabled' } + let err + try { + await codeActions.applyCodeAction(action) + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should invoke registered command after apply edit', async () => { + let called + disposables.push(commands.registerCommand('test.execute', async (s: string) => { + called = s + await nvim.command(s) + })) + let doc = await helper.createDocument() + let edits: TextEdit[] = [] + edits.push(TextEdit.insert(Position.create(0, 0), 'bar')) + let edit = { changes: { [doc.uri]: edits } } + let action = CodeAction.create('code fix', CodeActionKind.QuickFix) + action.isPreferred = true + currActions = [action] + resolvedAction = Object.assign({ + edit, + command: Command.create('run vim command', 'test.execute', 'normal! $') + }, action) + let arr = await codeActions.getCurrentCodeActions('line', [CodeActionKind.QuickFix]) + await codeActions.applyCodeAction(arr[0]) + let lines = await doc.buffer.lines + expect(lines).toEqual(['bar']) + expect(called).toBe('normal! $') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/codelens.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/codelens.test.ts new file mode 100644 index 00000000..899ca01c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/codelens.test.ts @@ -0,0 +1,269 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, Range, Command, TextEdit, Position } from 'vscode-languageserver-protocol' +import { disposeAll } from '../../util' +import languages from '../../languages' +import commands from '../../commands' +import CodeLens from '../../handler/codelens/index' +import helper, { createTmpFile } from '../helper' +import events from '../../events' + +let nvim: Neovim +let codeLens: CodeLens +let disposables: Disposable[] = [] +let srcId: number + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + srcId = await nvim.createNamespace('coc-codelens') + codeLens = helper.plugin.getHandler().codeLens + helper.updateConfiguration('codeLens.enable', true) +}) + +afterAll(async () => { + helper.updateConfiguration('codeLens.enable', false) + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('codeLenes featrue', () => { + + it('should do codeLenes request and resolve codeLenes', async () => { + disposables.push(languages.registerCodeLensProvider([{ language: 'javascript' }], { + provideCodeLenses: () => { + return [{ + range: Range.create(0, 0, 0, 1) + }, { + range: Range.create(1, 0, 1, 1) + }] + }, + resolveCodeLens: codeLens => { + codeLens.command = Command.create('save', '__save') + return codeLens + } + })) + let doc = await helper.createDocument('example.js') + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await codeLens.checkProvider() + let buf = codeLens.buffers.getItem(doc.bufnr) + let codelens = buf.getCodelenses() + expect(codelens).toBeDefined() + expect(codelens[0].command).toBeDefined() + expect(codelens[1].command).toBeDefined() + let markers = await helper.getMarkers(doc.bufnr, srcId) + expect(markers.length).toBe(2) + }) + + it('should refresh codeLens on CursorHold', async () => { + disposables.push(languages.registerCodeLensProvider([{ language: 'javascript' }], { + provideCodeLenses: document => { + let n = document.lineCount + let arr: any[] = [] + for (let i = 0; i <= n - 2; i++) { + arr.push({ + range: Range.create(i, 0, i, 1), + command: Command.create('save', '__save', i) + }) + } + return arr + } + })) + let doc = await helper.createDocument('example.js') + await helper.wait(100) + let markers = await helper.getMarkers(doc.bufnr, srcId) + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await doc.synchronize() + await events.fire('CursorHold', [doc.bufnr]) + await helper.wait(200) + markers = await helper.getMarkers(doc.bufnr, srcId) + expect(markers.length).toBe(3) + }) + + it('should cancel codeLenes request on document change', async () => { + let cancelled = false + disposables.push(languages.registerCodeLensProvider([{ language: 'javascript' }], { + provideCodeLenses: (_, token) => { + return new Promise(resolve => { + token.onCancellationRequested(() => { + cancelled = true + clearTimeout(timer) + resolve(null) + }) + let timer = setTimeout(() => { + resolve([{ + range: Range.create(0, 0, 0, 1) + }, { + range: Range.create(1, 0, 1, 1) + }]) + }, 2000) + }) + }, + resolveCodeLens: codeLens => { + codeLens.command = Command.create('save', '__save') + return codeLens + } + })) + let doc = await helper.createDocument('codelens.js') + await doc.applyEdits([TextEdit.insert(Position.create(0, 0), 'a\nb\nc')]) + let p = codeLens.checkProvider() + await doc.applyEdits([TextEdit.replace(Range.create(0, 0, 0, 1), 'foo')]) + await p + expect(cancelled).toBe(true) + let buf = codeLens.buffers.getItem(doc.bufnr) + let codelens = buf.getCodelenses() + expect(codelens).toBeUndefined() + }) + + it('should resolve on CursorMoved', async () => { + disposables.push(languages.registerCodeLensProvider([{ language: 'javascript' }], { + provideCodeLenses: () => { + return [{ + range: Range.create(90, 0, 90, 1) + }, { + range: Range.create(91, 0, 91, 1) + }] + }, + resolveCodeLens: async codeLens => { + await helper.wait(50) + codeLens.command = Command.create('save', '__save') + return codeLens + } + })) + let doc = await helper.createDocument('example.js') + let arr = new Array(100) + arr.fill('') + await nvim.call('setline', [1, arr]) + await doc.synchronize() + await codeLens.checkProvider() + await nvim.command('normal! gg') + await helper.wait(300) + await nvim.command('normal! G') + await helper.wait(300) + let buf = codeLens.buffers.getItem(doc.bufnr) + let codelens = buf.getCodelenses() + expect(codelens).toBeDefined() + expect(codelens[0].command).toBeDefined() + expect(codelens[1].command).toBeDefined() + }) + + it('should invoke codeLenes action', async () => { + let fn = jest.fn() + disposables.push(commands.registerCommand('__save', (...args) => { + fn(...args) + })) + disposables.push(languages.registerCodeLensProvider([{ language: 'javascript' }], { + provideCodeLenses: () => { + return [{ + range: Range.create(0, 0, 0, 1) + }] + }, + resolveCodeLens: codeLens => { + codeLens.command = Command.create('save', '__save', 1, 2, 3) + return codeLens + } + })) + await helper.createDocument('example.js') + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await codeLens.checkProvider() + await helper.doAction('codeLensAction') + expect(fn).toBeCalledWith(1, 2, 3) + }) + + it('should use picker fo multiple codeLenses', async () => { + let fn = jest.fn() + disposables.push(commands.registerCommand('__save', (...args) => { + fn(...args) + })) + disposables.push(commands.registerCommand('__delete', (...args) => { + fn(...args) + })) + disposables.push(languages.registerCodeLensProvider([{ language: 'javascript' }], { + provideCodeLenses: () => { + return [{ + range: Range.create(0, 0, 0, 1), + command: Command.create('save', '__save', 1, 2, 3) + }, { + range: Range.create(0, 1, 0, 2), + command: Command.create('save', '__delete', 4, 5, 6) + }] + } + })) + let doc = await helper.createDocument('example.js') + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await doc.synchronize() + await codeLens.checkProvider() + let p = helper.doAction('codeLensAction') + await helper.wait(30) + await nvim.input('') + await p + expect(fn).toBeCalledWith(1, 2, 3) + }) + + it('should refresh for failed codeLens request', async () => { + let called = 0 + let fn = jest.fn() + disposables.push(commands.registerCommand('__save', (...args) => { + fn(...args) + })) + disposables.push(commands.registerCommand('__foo', (...args) => { + fn(...args) + })) + disposables.push(languages.registerCodeLensProvider([{ language: '*' }], { + provideCodeLenses: () => { + called++ + if (called == 1) { + return null + } + return [{ + range: Range.create(0, 0, 0, 1), + command: Command.create('foo', '__foo') + }] + } + })) + disposables.push(languages.registerCodeLensProvider([{ language: '*' }], { + provideCodeLenses: () => { + return [{ + range: Range.create(0, 0, 0, 1), + command: Command.create('save', '__save') + }] + } + })) + let doc = await helper.createDocument('example.js') + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await codeLens.checkProvider() + let markers = await helper.getMarkers(doc.buffer.id, srcId) + expect(markers.length).toBeGreaterThan(0) + let codeLensBuffer = codeLens.buffers.getItem(doc.buffer.id) + await codeLensBuffer.forceFetch() + let curr = codeLensBuffer.currentCodeLens() + expect(curr.length).toBeGreaterThan(1) + expect(called).toBe(2) + }) + + it('should refresh on configuration change', async () => { + disposables.push(languages.registerCodeLensProvider([{ language: '*' }], { + provideCodeLenses: () => { + return [{ + range: Range.create(0, 0, 0, 1), + command: Command.create('save', '__save') + }] + } + })) + let filepath = await createTmpFile('abc') + let buffer = await helper.edit(filepath) + await codeLens.checkProvider() + helper.updateConfiguration('codeLens.enable', false) + await helper.wait(10) + let markers = await helper.getMarkers(buffer.id, srcId) + expect(markers.length).toBe(0) + helper.updateConfiguration('codeLens.enable', true) + await helper.wait(300) + markers = await helper.getMarkers(buffer.id, srcId) + expect(markers.length).toBeGreaterThan(0) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/colors.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/colors.test.ts new file mode 100644 index 00000000..48accb36 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/colors.test.ts @@ -0,0 +1,254 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationToken, Color, ColorInformation, ColorPresentation, Disposable, Position, Range } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import commands from '../../commands' +import { toHexString } from '../../util/color' +import Colors from '../../handler/colors/index' +import languages from '../../languages' +import { ProviderResult } from '../../provider' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let state = 'normal' +let colors: Colors +let disposables: Disposable[] = [] +let colorPresentations: ColorPresentation[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + colors = helper.plugin.getHandler().colors + disposables.push(languages.registerDocumentColorProvider([{ language: '*' }], { + provideColorPresentations: ( + _color: Color, + _context: { document: TextDocument; range: Range }, + _token: CancellationToken + ): ColorPresentation[] => colorPresentations, + provideDocumentColors: ( + document: TextDocument, + _token: CancellationToken + ): ProviderResult => { + if (state == 'empty') return [] + if (state == 'error') return Promise.reject(new Error('no color')) + let matches = Array.from((document.getText() as any).matchAll(/#\w{6}/g)) as any + return matches.map(o => { + let start = document.positionAt(o.index) + let end = document.positionAt(o.index + o[0].length) + return { + range: Range.create(start, end), + color: getColor(255, 255, 255) + } + }) + } + })) +}) + +afterAll(async () => { + disposeAll(disposables) + await helper.shutdown() +}) + +afterEach(async () => { + colorPresentations = [] + await helper.reset() +}) + +function getColor(r: number, g: number, b: number): Color { + return { red: r / 255, green: g / 255, blue: b / 255, alpha: 1 } +} + +describe('Colors', () => { + describe('utils', () => { + it('should get hex string', () => { + let color = getColor(255, 255, 255) + let hex = toHexString(color) + expect(hex).toBe('ffffff') + }) + }) + + describe('configuration', () => { + it('should toggle enable state on configuration change', async () => { + await helper.createDocument() + helper.updateConfiguration('coc.preferences.colorSupport', false) + expect(colors.enabled).toBe(false) + helper.updateConfiguration('coc.preferences.colorSupport', true) + expect(colors.enabled).toBe(true) + }) + }) + + describe('commands', () => { + it('should register editor.action.pickColor command', async () => { + await helper.mockFunction('coc#util#pick_color', [0, 0, 0]) + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + doc.forceSync() + await colors.doHighlight(doc.bufnr) + await commands.executeCommand('editor.action.pickColor') + let line = await nvim.getLine() + expect(line).toBe('#000000') + }) + + it('should register editor.action.colorPresentation command', async () => { + colorPresentations = [ColorPresentation.create('red'), ColorPresentation.create('#ff0000')] + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + doc.forceSync() + await colors.doHighlight(doc.bufnr) + let p = commands.executeCommand('editor.action.colorPresentation') + await helper.wait(100) + await nvim.input('1') + await p + let line = await nvim.getLine() + expect(line).toBe('red') + }) + }) + + describe('doHighlight', () => { + it('should clearHighlight on empty result', async () => { + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + state = 'empty' + await colors.doHighlight(doc.bufnr) + let res = colors.hasColor(doc.bufnr) + expect(res).toBe(false) + state = 'normal' + }) + + it('should not highlight on error result', async () => { + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + state = 'error' + await colors.doHighlight(doc.bufnr) + let res = colors.hasColor(doc.bufnr) + expect(res).toBe(false) + state = 'normal' + }) + + it('should highlight after document changed', async () => { + let doc = await helper.createDocument() + doc.forceSync() + await colors.doHighlight(doc.bufnr) + expect(colors.hasColor(doc.bufnr)).toBe(false) + expect(colors.hasColorAtPosition(doc.bufnr, Position.create(0, 1))).toBe(false) + await nvim.setLine('#ffffff #ff0000') + doc.forceSync() + await helper.wait(300) + expect(colors.hasColorAtPosition(doc.bufnr, Position.create(0, 1))).toBe(true) + expect(colors.hasColor(doc.bufnr)).toBe(true) + }) + + it('should clearHighlight on clearHighlight', async () => { + let doc = await helper.createDocument() + await nvim.setLine('#ffffff #ff0000') + doc.forceSync() + await colors.doHighlight(doc.bufnr) + expect(colors.hasColor(doc.bufnr)).toBe(true) + colors.clearHighlight(doc.bufnr) + expect(colors.hasColor(doc.bufnr)).toBe(false) + }) + + it('should highlight colors', async () => { + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + await colors.doHighlight(doc.bufnr) + let exists = await nvim.call('hlexists', 'BGffffff') + expect(exists).toBe(1) + }) + }) + + describe('hasColor()', () => { + it('should return false when bufnr not exists', async () => { + let res = colors.hasColor(99) + colors.clearHighlight(99) + expect(res).toBe(false) + }) + }) + + describe('getColorInformation()', () => { + it('should return null when highlighter not exists', async () => { + let res = await colors.getColorInformation(99) + expect(res).toBe(null) + }) + + it('should return null when color not found', async () => { + let doc = await helper.createDocument() + await nvim.setLine('#ffffff foo ') + doc.forceSync() + await colors.doHighlight(doc.bufnr) + await nvim.call('cursor', [1, 12]) + let res = await colors.getColorInformation(doc.bufnr) + expect(res).toBe(null) + }) + }) + + describe('hasColorAtPosition()', () => { + it('should return false when bufnr not exists', async () => { + let res = colors.hasColorAtPosition(99, Position.create(0, 0)) + expect(res).toBe(false) + }) + }) + + describe('pickPresentation()', () => { + it('should show warning when color not exists', async () => { + await helper.createDocument() + await colors.pickPresentation() + let msg = await helper.getCmdline() + expect(msg).toMatch('Color not found') + }) + + it('should not throw when presentations not exists', async () => { + colorPresentations = [] + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + doc.forceSync() + await colors.doHighlight(99) + await colors.doHighlight(doc.bufnr) + await helper.doAction('colorPresentation') + }) + + it('should pick presentations', async () => { + colorPresentations = [ColorPresentation.create('red'), ColorPresentation.create('#ff0000')] + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + doc.forceSync() + await colors.doHighlight(doc.bufnr) + let p = helper.doAction('colorPresentation') + await helper.wait(100) + await nvim.input('1') + await p + let line = await nvim.getLine() + expect(line).toBe('red') + }) + }) + + describe('pickColor()', () => { + it('should show warning when color not exists', async () => { + await helper.createDocument() + await colors.pickColor() + let msg = await helper.getCmdline() + expect(msg).toMatch('not found') + }) + + it('should pickColor', async () => { + await helper.mockFunction('coc#util#pick_color', [0, 0, 0]) + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + doc.forceSync() + await colors.doHighlight(doc.bufnr) + await helper.doAction('pickColor') + let line = await nvim.getLine() + expect(line).toBe('#000000') + }) + + it('should not throw when pick color return 0', async () => { + await helper.mockFunction('coc#util#pick_color', 0) + let doc = await helper.createDocument() + await nvim.setLine('#ffffff') + doc.forceSync() + await colors.doHighlight(doc.bufnr) + await helper.doAction('pickColor') + let line = await nvim.getLine() + expect(line).toBe('#ffffff') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/commands.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/commands.test.ts new file mode 100644 index 00000000..f9026edf --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/commands.test.ts @@ -0,0 +1,82 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import CommandsHandler from '../../handler/commands' +import commandManager from '../../commands' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let commands: CommandsHandler +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + commands = (helper.plugin as any).handler.commands +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + await helper.createDocument() +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +describe('Commands', () => { + describe('addVimCommand', () => { + it('should register global vim commands', async () => { + await commandManager.executeCommand('vim.config') + await helper.wait(50) + let bufname = await nvim.call('bufname', ['%']) + expect(bufname).toMatch('coc-settings.json') + let list = commands.getCommandList() + expect(list.includes('vim.config')).toBe(true) + }) + + it('should add vim command with title', async () => { + commands.addVimCommand({ id: 'list', cmd: 'CocList', title: 'list of coc.nvim' }) + let res = commandManager.titles.get('vim.list') + expect(res).toBe('list of coc.nvim') + commandManager.unregister('vim.list') + }) + }) + + describe('getCommands', () => { + it('should get command items', async () => { + let res = commands.getCommands() + let idx = res.findIndex(o => o.id == 'workspace.showOutput') + expect(idx != -1).toBe(true) + }) + }) + + describe('repeat', () => { + it('should repeat command', async () => { + // let buf = await nvim.buffer + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await nvim.call('cursor', [1, 1]) + commands.addVimCommand({ id: 'remove', cmd: 'normal! dd' }) + await commands.runCommand('vim.remove') + await helper.wait(50) + let res = await nvim.call('getline', [1, '$']) + expect(res).toEqual(['b', 'c']) + await commands.repeat() + await helper.wait(50) + res = await nvim.call('getline', [1, '$']) + expect(res).toEqual(['c']) + }) + }) + + describe('runCommand', () => { + it('should open command list without id', async () => { + await commands.runCommand() + await helper.wait(100) + let bufname = await nvim.call('bufname', ['%']) + expect(bufname).toBe('list:///commands') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/fold.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/fold.test.ts new file mode 100644 index 00000000..8ddc23df --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/fold.test.ts @@ -0,0 +1,71 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, FoldingRange } from 'vscode-languageserver-protocol' +import FoldHandler from '../../handler/fold' +import languages from '../../languages' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let folds: FoldHandler +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + folds = (helper.plugin as any).handler.fold +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + await helper.createDocument() +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +describe('Folds', () => { + + it('should return false when no fold ranges found', async () => { + disposables.push(languages.registerFoldingRangeProvider([{ language: '*' }], { + provideFoldingRanges(_doc) { + return [] + } + })) + let res = await folds.fold() + expect(res).toBe(false) + }) + + it('should fold all fold ranges', async () => { + disposables.push(languages.registerFoldingRangeProvider([{ language: '*' }], { + provideFoldingRanges(_doc) { + return [FoldingRange.create(1, 3), FoldingRange.create(4, 6, 0, 0, 'comment')] + } + })) + await nvim.call('setline', [1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']]) + let res = await folds.fold() + expect(res).toBe(true) + let closed = await nvim.call('foldclosed', [2]) + expect(closed).toBe(2) + closed = await nvim.call('foldclosed', [5]) + expect(closed).toBe(5) + }) + + it('should fold comment ranges', async () => { + disposables.push(languages.registerFoldingRangeProvider([{ language: '*' }], { + provideFoldingRanges(_doc) { + return [FoldingRange.create(1, 3), FoldingRange.create(4, 6, 0, 0, 'comment')] + } + })) + await nvim.call('setline', [1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']]) + let res = await folds.fold('comment') + expect(res).toBe(true) + let closed = await nvim.call('foldclosed', [2]) + expect(closed).toBe(-1) + closed = await nvim.call('foldclosed', [5]) + expect(closed).toBe(5) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/format.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/format.test.ts new file mode 100644 index 00000000..111265b9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/format.test.ts @@ -0,0 +1,253 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' +import languages from '../../languages' +import { disposeAll } from '../../util' +import window from '../../window' +import workspace from '../../workspace' +import Format from '../../handler/format' +import helper, { createTmpFile } from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] +let format: Format + +beforeAll(async () => { + let { configurations } = workspace + configurations.updateUserConfig({ 'coc.preferences.formatOnType': true }) + await helper.setup() + nvim = helper.nvim + format = helper.plugin.getHandler().format +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + helper.updateConfiguration('coc.preferences.formatOnSaveFiletypes', []) + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('format handler', () => { + describe('documentFormat', () => { + it('should throw when provider not found', async () => { + let doc = await helper.createDocument() + let err + try { + await format.documentFormat(doc) + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should return false when get empty edits ', async () => { + disposables.push(languages.registerDocumentFormatProvider(['*'], { + provideDocumentFormattingEdits: () => { + return [] + } + })) + let doc = await helper.createDocument() + let res = await format.documentFormat(doc) + expect(res).toBe(false) + }) + }) + + describe('formatOnSave', () => { + it('should not throw when provider not found', async () => { + helper.updateConfiguration('coc.preferences.formatOnSaveFiletypes', ['javascript']) + let filepath = await createTmpFile('') + await helper.edit(filepath) + await nvim.command('setf javascript') + await nvim.setLine('foo') + await nvim.command('silent w') + await helper.wait(100) + }) + + it('should invoke format on save', async () => { + helper.updateConfiguration('coc.preferences.formatOnSaveFiletypes', ['text']) + disposables.push(languages.registerDocumentFormatProvider(['text'], { + provideDocumentFormattingEdits: document => { + let lines = document.getText().replace(/\n$/, '').split(/\n/) + let edits: TextEdit[] = [] + for (let i = 0; i < lines.length; i++) { + let text = lines[i] + if (!text.startsWith(' ')) { + edits.push(TextEdit.insert(Position.create(i, 0), ' ')) + } + } + return edits + } + })) + let filepath = await createTmpFile('a\nb\nc\n') + let buf = await helper.edit(filepath) + await nvim.command('setf text') + await nvim.command('w') + let lines = await buf.lines + expect(lines).toEqual([' a', ' b', ' c']) + }) + + it('should cancel when timeout', async () => { + helper.updateConfiguration('coc.preferences.formatOnSaveFiletypes', ['*']) + disposables.push(languages.registerDocumentFormatProvider(['*'], { + provideDocumentFormattingEdits: () => { + return new Promise(resolve => { + setTimeout(() => { + resolve(undefined) + }, 2000) + }) + } + })) + let filepath = await createTmpFile('a\nb\nc\n') + await helper.edit(filepath) + let n = Date.now() + await nvim.command('w') + expect(Date.now() - n).toBeLessThan(1000) + }) + }) + + describe('rangeFormat', () => { + it('should invoke range format', async () => { + disposables.push(languages.registerDocumentRangeFormatProvider(['text'], { + provideDocumentRangeFormattingEdits: (_document, range) => { + let lines: number[] = [] + for (let i = range.start.line; i <= range.end.line; i++) { + lines.push(i) + } + return lines.map(i => { + return TextEdit.insert(Position.create(i, 0), ' ') + }) + } + })) + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await nvim.command('setf text') + await nvim.command('normal! ggvG') + await nvim.input('') + await helper.doAction('formatSelected', 'v') + let buf = nvim.createBuffer(doc.bufnr) + let lines = await buf.lines + expect(lines).toEqual([' a', ' b', ' c']) + }) + + it('should format range by formatexpr option', async () => { + let range: Range + disposables.push(languages.registerDocumentRangeFormatProvider(['text'], { + provideDocumentRangeFormattingEdits: (_document, r) => { + range = r + return [] + } + })) + await helper.createDocument() + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await nvim.command('setf text') + await nvim.command(`setl formatexpr=CocAction('formatSelected')`) + await nvim.command('normal! ggvGgq') + expect(range).toEqual({ + start: { line: 0, character: 0 }, end: { line: 3, character: 0 } + }) + }) + }) + + describe('formatOnType', () => { + it('should invoke format', async () => { + disposables.push(languages.registerDocumentFormatProvider(['text'], { + provideDocumentFormattingEdits: () => { + return [TextEdit.insert(Position.create(0, 0), ' ')] + } + })) + await helper.createDocument() + await nvim.setLine('foo') + await nvim.command('setf text') + await helper.doAction('format') + let line = await nvim.line + expect(line).toEqual(' foo') + }) + + it('should does format on type', async () => { + disposables.push(languages.registerOnTypeFormattingEditProvider(['text'], { + provideOnTypeFormattingEdits: () => { + return [TextEdit.insert(Position.create(0, 0), ' ')] + } + }, ['|'])) + await helper.edit() + await nvim.command('setf text') + await nvim.input('i|') + await helper.wait(200) + let line = await nvim.line + expect(line).toBe(' |') + let cursor = await window.getCursorPosition() + expect(cursor).toEqual({ line: 0, character: 3 }) + }) + + it('should format on new line inserted', async () => { + disposables.push(languages.registerOnTypeFormattingEditProvider(['text'], { + provideOnTypeFormattingEdits: (doc, position) => { + let text = doc.getText() + if (text.startsWith(' ')) return [] + return [TextEdit.insert(Position.create(position.line, 0), ' ')] + } + }, ['\n'])) + let buf = await helper.edit() + await nvim.command('setf text') + await nvim.setLine('foo') + await nvim.input('o') + await helper.wait(100) + let lines = await buf.lines + expect(lines).toEqual([' foo', '']) + }) + + it('should adjust cursor after format on type', async () => { + disposables.push(languages.registerOnTypeFormattingEditProvider(['text'], { + provideOnTypeFormattingEdits: () => { + return [ + TextEdit.insert(Position.create(0, 0), ' '), + TextEdit.insert(Position.create(0, 2), 'end') + ] + } + }, ['|'])) + await helper.edit() + await nvim.command('setf text') + await nvim.setLine('"') + await nvim.input('i|') + await helper.wait(100) + let line = await nvim.line + expect(line).toBe(' |"end') + let cursor = await window.getCursorPosition() + expect(cursor).toEqual({ line: 0, character: 3 }) + }) + }) + + describe('bracketEnterImprove', () => { + afterEach(() => { + nvim.command('iunmap ', true) + }) + + it('should format vim file on enter', async () => { + let buf = await helper.edit('foo.vim') + await nvim.command(`inoremap pumvisible() ? coc#_select_confirm() : "\\u\\\\=coc#on_enter()\\"`) + await nvim.setLine('let foo={}') + await nvim.command(`normal! gg$`) + await nvim.input('i') + await nvim.eval(`feedkeys("\\", 'im')`) + await helper.wait(100) + let lines = await buf.lines + expect(lines).toEqual(['let foo={', ' \\ ', ' \\ }']) + }) + + it('should add new line between bracket', async () => { + let buf = await helper.edit() + await nvim.command(`inoremap pumvisible() ? coc#_select_confirm() : "\\u\\\\=coc#on_enter()\\"`) + await nvim.setLine(' {}') + await nvim.command(`normal! gg$`) + await nvim.input('i') + await nvim.eval(`feedkeys("\\", 'im')`) + await helper.wait(100) + let lines = await buf.lines + expect(lines).toEqual([' {', ' ', ' }']) + }) + }) +}) + diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/highlights.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/highlights.test.ts new file mode 100644 index 00000000..cbcd1890 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/highlights.test.ts @@ -0,0 +1,138 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, DocumentHighlightKind, Position, Range } from 'vscode-languageserver-protocol' +import Highlights from '../../handler/highlights' +import languages from '../../languages' +import workspace from '../../workspace' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] +let highlights: Highlights + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + highlights = helper.plugin.getHandler().documentHighlighter +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +function registProvider(): void { + disposables.push(languages.registerDocumentHighlightProvider([{ language: '*' }], { + provideDocumentHighlights: async document => { + let word = await nvim.eval('expand("")') + // let word = document.get + let matches = Array.from((document.getText() as any).matchAll(/\w+/g)) as any[] + let filtered = matches.filter(o => o[0] == word) + return filtered.map((o, i) => { + let start = document.positionAt(o.index) + let end = document.positionAt(o.index + o[0].length) + return { + range: Range.create(start, end), + kind: i % 2 == 0 ? DocumentHighlightKind.Read : DocumentHighlightKind.Write + } + }) + } + })) +} + +describe('document highlights', () => { + + it('should return null when highlights provide not exists', async () => { + let doc = await helper.createDocument() + let res = await highlights.getHighlights(doc, Position.create(0, 0)) + expect(res).toBeNull() + }) + + it('should cancel request on CursorMoved', async () => { + let fn = jest.fn() + languages.registerDocumentHighlightProvider([{ language: '*' }], { + provideDocumentHighlights: (_document, _position, token) => { + return new Promise(resolve => { + token.onCancellationRequested(() => { + clearTimeout(timer) + fn() + resolve([]) + }) + let timer = setTimeout(() => { + resolve([{ range: Range.create(0, 0, 0, 3) }]) + }, 3000) + }) + } + }) + await helper.edit() + await nvim.setLine('foo') + let p = highlights.highlight() + await helper.wait(50) + await nvim.call('cursor', [1, 2]) + await p + expect(fn).toBeCalled() + }) + + it('should add highlights to symbols', async () => { + registProvider() + await helper.createDocument() + await nvim.setLine('foo bar foo') + await helper.doAction('highlight') + let winid = await nvim.call('win_getid') as number + expect(highlights.hasHighlights(winid)).toBe(true) + }) + + it('should return highlight ranges', async () => { + registProvider() + await helper.createDocument() + await nvim.setLine('foo bar foo') + let res = await helper.doAction('symbolRanges') + expect(res.length).toBe(2) + }) + + it('should return null when cursor not in word range', async () => { + disposables.push(languages.registerDocumentHighlightProvider([{ language: '*' }], { + provideDocumentHighlights: () => { + return [{ range: Range.create(0, 0, 0, 3) }] + } + })) + let doc = await helper.createDocument() + await nvim.setLine(' oo') + await nvim.call('cursor', [1, 2]) + let res = await highlights.getHighlights(doc, Position.create(0, 0)) + expect(res).toBeNull() + }) + + it('should not throw when document is command line', async () => { + await nvim.call('feedkeys', ['q:', 'in']) + let doc = await workspace.document + expect(doc.isCommandLine).toBe(true) + let err + try { + await highlights.highlight() + } catch (e) { + err = e + } + await nvim.input('') + expect(err).toBeUndefined() + }) + + it('should not throw when provider not found', async () => { + disposeAll(disposables) + await helper.createDocument() + await nvim.setLine(' oo') + await nvim.call('cursor', [1, 2]) + let err + try { + await highlights.highlight() + } catch (e) { + err = e + } + expect(err).toBeUndefined() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/hover.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/hover.test.ts new file mode 100644 index 00000000..545d2a20 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/hover.test.ts @@ -0,0 +1,178 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, MarkedString, Hover, Range, TextEdit, Position } from 'vscode-languageserver-protocol' +import HoverHandler from '../../handler/hover' +import { URI } from 'vscode-uri' +import languages from '../../languages' +import { disposeAll } from '../../util' +import helper, { createTmpFile } from '../helper' + +let nvim: Neovim +let hover: HoverHandler +let disposables: Disposable[] = [] +let hoverResult: Hover +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + hover = helper.plugin.getHandler().hover +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + await helper.createDocument() + disposables.push(languages.registerHoverProvider([{ language: '*' }], { + provideHover: (_doc, _pos, _token) => { + return hoverResult + } + })) +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +async function getDocumentText(): Promise { + let lines = await nvim.call('getbufline', ['coc://document', 1, '$']) as string[] + return lines.join('\n') +} + +describe('Hover', () => { + describe('onHover', () => { + it('should return false when hover not found', async () => { + hoverResult = null + let res = await hover.onHover('preview') + expect(res).toBe(false) + }) + + it('should show MarkupContent hover', async () => { + hoverResult = { contents: { kind: 'plaintext', value: 'my hover' } } + await hover.onHover('preview') + let res = await getDocumentText() + expect(res).toMatch('my hover') + }) + + it('should show MarkedString hover', async () => { + hoverResult = { contents: 'string hover' } + disposables.push(languages.registerHoverProvider([{ language: '*' }], { + provideHover: (_doc, _pos, _token) => { + return { contents: { language: 'typescript', value: 'language hover' } } + } + })) + await hover.onHover('preview') + let res = await getDocumentText() + expect(res).toMatch('string hover') + expect(res).toMatch('language hover') + }) + + it('should show MarkedString hover array', async () => { + hoverResult = { contents: ['foo', { language: 'typescript', value: 'bar' }] } + await hover.onHover('preview') + let res = await getDocumentText() + expect(res).toMatch('foo') + expect(res).toMatch('bar') + }) + + it('should highlight hover range', async () => { + await nvim.setLine('var') + await nvim.command('normal! 0') + hoverResult = { contents: ['foo'], range: Range.create(0, 0, 0, 3) } + await hover.onHover('preview') + let res = await nvim.call('getmatches') as any[] + expect(res.length).toBe(1) + expect(res[0].group).toBe('CocHoverRange') + await helper.wait(600) + res = await nvim.call('getmatches') + expect(res.length).toBe(0) + }) + }) + + describe('previewHover', () => { + it('should echo hover message', async () => { + hoverResult = { contents: ['foo'] } + let res = await hover.onHover('echo') + expect(res).toBe(true) + let msg = await helper.getCmdline() + expect(msg).toMatch('foo') + }) + + it('should show hover in float window', async () => { + hoverResult = { contents: { kind: 'markdown', value: '```typescript\nconst foo:number\n```' } } + await hover.onHover('float') + let win = await helper.getFloat() + expect(win).toBeDefined() + let lines = await nvim.eval(`getbufline(winbufnr(${win.id}),1,'$')`) + expect(lines).toEqual(['const foo:number']) + }) + }) + + describe('getHover', () => { + it('should get hover from MarkedString array', async () => { + hoverResult = { contents: ['foo', { language: 'typescript', value: 'bar' }] } + disposables.push(languages.registerHoverProvider([{ language: '*' }], { + provideHover: (_doc, _pos, _token) => { + return { contents: { language: 'typescript', value: 'MarkupContent hover' } } + } + })) + disposables.push(languages.registerHoverProvider([{ language: '*' }], { + provideHover: (_doc, _pos, _token) => { + return { contents: MarkedString.fromPlainText('MarkedString hover') } + } + })) + let res = await hover.getHover() + expect(res.includes('foo')).toBe(true) + expect(res.includes('bar')).toBe(true) + expect(res.includes('MarkupContent hover')).toBe(true) + expect(res.includes('MarkedString hover')).toBe(true) + }) + + it('should filter empty hover message', async () => { + hoverResult = { contents: [''] } + let res = await hover.getHover() + expect(res.length).toBe(0) + }) + }) + + describe('definitionHover', () => { + it('should load definition from buffer', async () => { + hoverResult = { contents: 'string hover' } + let doc = await helper.createDocument() + await nvim.call('cursor', [1, 1]) + await doc.applyEdits([TextEdit.insert(Position.create(0, 0), 'foo\nbar')]) + disposables.push(languages.registerDefinitionProvider([{ language: '*' }], { + provideDefinition() { + return [{ + targetUri: doc.uri, + targetRange: Range.create(0, 0, 1, 3), + targetSelectionRange: Range.create(0, 0, 0, 3), + }] + } + })) + await hover.definitionHover('preview') + let res = await getDocumentText() + expect(res).toBe('string hover\n\nfoo\nbar') + }) + + it('should load definition link from file', async () => { + let fsPath = await createTmpFile('foo\nbar\n') + hoverResult = { contents: 'string hover' } + let doc = await helper.createDocument() + await nvim.call('cursor', [1, 1]) + await doc.applyEdits([TextEdit.insert(Position.create(0, 0), 'foo\nbar')]) + disposables.push(languages.registerDefinitionProvider([{ language: '*' }], { + provideDefinition() { + return [{ + targetUri: URI.file(fsPath).toString(), + targetRange: Range.create(0, 0, 1, 3), + targetSelectionRange: Range.create(0, 0, 0, 3), + }] + } + })) + await hover.definitionHover('preview') + let res = await getDocumentText() + expect(res).toBe('string hover\n\nfoo\nbar') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/index.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/index.test.ts new file mode 100644 index 00000000..a66ddc46 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/index.test.ts @@ -0,0 +1,93 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import Handler from '../../handler/index' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let handler: Handler +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + handler = (helper.plugin as any).handler +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + await helper.createDocument() +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +describe('Handler', () => { + describe('hasProvider', () => { + it('should check provider for document', async () => { + let res = await handler.hasProvider('definition') + expect(res).toBe(false) + }) + }) + + describe('checkProvier', () => { + it('should throw error when provider not found', async () => { + let doc = await helper.createDocument() + let err + try { + handler.checkProvier('definition', doc.textDocument) + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + }) + + describe('withRequestToken', () => { + it('should cancel previous request when called again', async () => { + let cancelled = false + let p = handler.withRequestToken('test', token => { + return new Promise(s => { + token.onCancellationRequested(() => { + cancelled = true + clearTimeout(timer) + s(undefined) + }) + let timer = setTimeout(() => { + s(undefined) + }, 3000) + }) + }, false) + setTimeout(async () => { + await handler.withRequestToken('test', () => { + return Promise.resolve(undefined) + }, false) + }, 50) + await p + expect(cancelled).toBe(true) + }) + + it('should cancel request on insert start', async () => { + let cancelled = false + let p = handler.withRequestToken('test', token => { + return new Promise(s => { + token.onCancellationRequested(() => { + cancelled = true + clearTimeout(timer) + s(undefined) + }) + let timer = setTimeout(() => { + s(undefined) + }, 3000) + }) + }, false) + await nvim.input('i') + await p + expect(cancelled).toBe(true) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/links.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/links.test.ts new file mode 100644 index 00000000..5fe97761 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/links.test.ts @@ -0,0 +1,99 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, DocumentLink, Range } from 'vscode-languageserver-protocol' +import LinksHandler from '../../handler/links' +import languages from '../../languages' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let links: LinksHandler +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + links = (helper.plugin as any).handler.links +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + await helper.createDocument() +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +describe('Links', () => { + it('should get document links', async () => { + disposables.push(languages.registerDocumentLinkProvider([{ language: '*' }], { + provideDocumentLinks: (_doc, _token) => { + return [ + DocumentLink.create(Range.create(0, 0, 0, 5), 'test:///foo'), + DocumentLink.create(Range.create(1, 0, 1, 5), 'test:///bar') + ] + } + })) + let res = await links.getLinks() + expect(res.length).toBe(2) + }) + + it('should throw error when link target not resolved', async () => { + disposables.push(languages.registerDocumentLinkProvider([{ language: '*' }], { + provideDocumentLinks(_doc, _token) { + return [ + DocumentLink.create(Range.create(0, 0, 0, 5)) + ] + }, + resolveDocumentLink(link) { + return link + } + })) + let res = await links.getLinks() + let err + try { + await links.openLink(res[0]) + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should open link at current position', async () => { + await nvim.setLine('foo') + await nvim.command('normal! 0') + disposables.push(languages.registerDocumentLinkProvider([{ language: '*' }], { + provideDocumentLinks(_doc, _token) { + return [ + DocumentLink.create(Range.create(0, 0, 0, 5)), + ] + }, + resolveDocumentLink(link) { + link.target = 'test:///foo' + return link + } + })) + await links.openCurrentLink() + let bufname = await nvim.call('bufname', '%') + expect(bufname).toBe('test:///foo') + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await nvim.call('cursor', [3, 1]) + let res = await links.openCurrentLink() + expect(res).toBe(false) + }) + + it('should return false when current links not found', async () => { + await nvim.setLine('foo') + await nvim.command('normal! 0') + disposables.push(languages.registerDocumentLinkProvider([{ language: '*' }], { + provideDocumentLinks(_doc, _token) { + return [] + } + })) + let res = await links.openCurrentLink() + expect(res).toBe(false) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/locations.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/locations.test.ts new file mode 100644 index 00000000..b45ddcbb --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/locations.test.ts @@ -0,0 +1,308 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, LocationLink, Location, Range } from 'vscode-languageserver-protocol' +import LocationHandler from '../../handler/locations' +import languages from '../../languages' +import services from '../../services' +import workspace from '../../workspace' +import { disposeAll } from '../../util' +import helper from '../helper' +import { URI } from 'vscode-uri' + +let nvim: Neovim +let locations: LocationHandler +let disposables: Disposable[] = [] +let currLocations: Location[] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + Object.assign(workspace.env, { + locationlist: false + }) + locations = helper.plugin.getHandler().locations +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + await helper.createDocument() +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +function createLocation(name: string, sl: number, sc: number, el: number, ec: number): Location { + return Location.create(`test://${name}`, Range.create(sl, sc, el, ec)) +} + +describe('locations', () => { + describe('reference', () => { + beforeEach(() => { + disposables.push(languages.registerReferencesProvider([{ language: '*' }], { + provideReferences: () => { + return currLocations + } + })) + }) + + it('should get references', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0), createLocation('bar', 0, 0, 0, 0)] + let res = await locations.references() + expect(res.length).toBe(2) + }) + + it('should jump to references', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0)] + let res = await locations.gotoReferences('edit', true) + expect(res).toBe(true) + let name = await nvim.call('bufname', ['%']) + expect(name).toBe('test://foo') + }) + + it('should return false when references not found', async () => { + currLocations = [] + let res = await locations.gotoReferences('edit', true) + expect(res).toBe(false) + }) + }) + + describe('definition', () => { + beforeEach(() => { + disposables.push(languages.registerDefinitionProvider([{ language: '*' }], { + provideDefinition: () => { + return currLocations + } + })) + }) + + it('should get definitions', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0), createLocation('bar', 0, 0, 0, 0)] + let res = await locations.definitions() + expect(res.length).toBe(2) + }) + + it('should jump to definitions', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0)] + let res = await locations.gotoDefinition('edit') + expect(res).toBe(true) + let name = await nvim.call('bufname', ['%']) + expect(name).toBe('test://foo') + }) + + it('should return false when definitions not found', async () => { + currLocations = [] + let res = await locations.gotoDefinition('edit') + expect(res).toBe(false) + }) + }) + + describe('declaration', () => { + beforeEach(() => { + disposables.push(languages.registerDeclarationProvider([{ language: '*' }], { + provideDeclaration: () => { + return currLocations + } + })) + }) + + it('should get declarations', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0), createLocation('bar', 0, 0, 0, 0)] + let res = await locations.declarations() as Location[] + expect(res.length).toBe(2) + }) + + it('should jump to declaration', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0)] + let res = await locations.gotoDeclaration('edit') + expect(res).toBe(true) + let name = await nvim.call('bufname', ['%']) + expect(name).toBe('test://foo') + }) + + it('should return false when declaration not found', async () => { + currLocations = [] + let res = await locations.gotoDeclaration('edit') + expect(res).toBe(false) + }) + }) + + describe('typeDefinition', () => { + beforeEach(() => { + disposables.push(languages.registerTypeDefinitionProvider([{ language: '*' }], { + provideTypeDefinition: () => { + return currLocations + } + })) + }) + + it('should get type definition', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0), createLocation('bar', 0, 0, 0, 0)] + let res = await locations.typeDefinitions() as Location[] + expect(res.length).toBe(2) + }) + + it('should jump to type definition', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0)] + let res = await locations.gotoTypeDefinition('edit') + expect(res).toBe(true) + let name = await nvim.call('bufname', ['%']) + expect(name).toBe('test://foo') + }) + + it('should return false when type definition not found', async () => { + currLocations = [] + let res = await locations.gotoTypeDefinition('edit') + expect(res).toBe(false) + }) + }) + + describe('implementation', () => { + beforeEach(() => { + disposables.push(languages.registerImplementationProvider([{ language: '*' }], { + provideImplementation: () => { + return currLocations + } + })) + }) + + it('should get implementations', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0), createLocation('bar', 0, 0, 0, 0)] + let res = await locations.implementations() as Location[] + expect(res.length).toBe(2) + }) + + it('should jump to implementation', async () => { + currLocations = [createLocation('foo', 0, 0, 0, 0)] + let res = await locations.gotoImplementation('edit') + expect(res).toBe(true) + let name = await nvim.call('bufname', ['%']) + expect(name).toBe('test://foo') + }) + + it('should return false when implementation not found', async () => { + currLocations = [] + let res = await locations.gotoImplementation('edit') + expect(res).toBe(false) + }) + }) + + describe('getTagList', () => { + it('should return null when cword not exists', async () => { + let res = await locations.getTagList() + expect(res).toBe(null) + }) + + it('should return null when provider not exists', async () => { + await nvim.setLine('foo') + await nvim.command('normal! ^') + let res = await locations.getTagList() + expect(res).toBe(null) + }) + + it('should return null when result is empty', async () => { + disposables.push(languages.registerDefinitionProvider([{ language: '*' }], { + provideDefinition: () => { + return [] + } + })) + await nvim.setLine('foo') + await nvim.command('normal! ^') + let res = await locations.getTagList() + expect(res).toBe(null) + }) + + it('should return tag definitions', async () => { + disposables.push(languages.registerDefinitionProvider([{ language: '*' }], { + provideDefinition: () => { + return [createLocation('bar', 2, 0, 2, 5), Location.create(URI.file('/foo').toString(), Range.create(1, 0, 1, 5))] + } + })) + await nvim.setLine('foo') + await nvim.command('normal! ^') + let res = await locations.getTagList() + expect(res).toEqual([ + { + name: 'foo', + cmd: 'keepjumps 3 | normal 1|', + filename: 'test://bar' + }, + { name: 'foo', cmd: 'keepjumps 2 | normal 1|', filename: '/foo' } + ]) + }) + }) + + describe('findLocations', () => { + // hook result + let fn + let result: any + beforeAll(() => { + fn = services.sendRequest + services.sendRequest = () => { + return Promise.resolve(result) + } + }) + + afterAll(() => { + services.sendRequest = fn + }) + + it('should handle locations from language client', async () => { + result = [createLocation('bar', 2, 0, 2, 5)] + await locations.findLocations('foo', 'mylocation', {}, false) + let res = await nvim.getVar('coc_jump_locations') + expect(res).toEqual([{ + uri: 'test://bar', + lnum: 3, + end_lnum: 3, + col: 1, + end_col: 6, + filename: 'test://bar', + text: '', + range: Range.create(2, 0, 2, 5) + }]) + }) + + it('should handle nested locations', async () => { + let location: any = { + location: createLocation('file', 0, 0, 0, 0), + children: [{ + location: createLocation('foo', 3, 0, 3, 5), + children: [] + }, { + location: createLocation('bar', 4, 0, 4, 5), + children: [] + }] + } + result = location + await locations.findLocations('foo', 'mylocation', {}, false) + let res = await nvim.getVar('coc_jump_locations') as any[] + expect(res.length).toBe(3) + }) + }) + + describe('handleLocations', () => { + it('should not throw when location is undefined', async () => { + await locations.handleLocations(null) + }) + + it('should not throw when locations is empty array', async () => { + await locations.handleLocations([]) + }) + + it('should handle single location', async () => { + await locations.handleLocations(createLocation('single', 0, 0, 0, 0)) + let bufname = await nvim.call('bufname', ['%']) + expect(bufname).toBe('test://single') + }) + + it('should handle location link', async () => { + let link = LocationLink.create('test://link', Range.create(0, 0, 0, 3), Range.create(1, 0, 1, 3)) + await locations.handleLocations([link]) + let bufname = await nvim.call('bufname', ['%']) + expect(bufname).toBe('test://link') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/outline.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/outline.test.ts new file mode 100644 index 00000000..c8e29dea --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/outline.test.ts @@ -0,0 +1,426 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import { CancellationToken, CodeAction, CodeActionContext, CodeActionKind, Disposable, Range, SymbolTag, TextEdit } from 'vscode-languageserver-protocol' +import events from '../../events' +import Symbols from '../../handler/symbols/index' +import languages from '../../languages' +import { ProviderResult } from '../../provider' +import { disposeAll } from '../../util' +import workspace from '../../workspace' +import helper from '../helper' +import Parser from './parser' + +let nvim: Neovim +let symbols: Symbols +let disposables: Disposable[] = [] + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + symbols = helper.plugin.getHandler().symbols +}) + +beforeEach(() => { + disposables.push(languages.registerDocumentSymbolProvider([{ language: 'javascript' }], { + provideDocumentSymbols: document => { + let parser = new Parser(document.getText()) + let res = parser.parse() + if (res.length) { + res[0].tags = [SymbolTag.Deprecated] + } + return Promise.resolve(res) + } + })) +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +async function getOutlineBuffer(): Promise { + let winid = await nvim.call('coc#window#find', ['cocViewId', 'OUTLINE']) + if (winid == -1) return undefined + let bufnr = await nvim.call('winbufnr', [winid]) + if (bufnr == -1) return undefined + return nvim.createBuffer(bufnr) +} + +describe('symbols outline', () => { + + let defaultCode = `class myClass { + fun1() { } + fun2() {} +}` + + async function createBuffer(code = defaultCode): Promise { + await helper.edit() + let buf = await nvim.buffer + await nvim.command('setf javascript') + await buf.setLines(code.split('\n'), { start: 0, end: -1, strictIndexing: false }) + let doc = await workspace.document + doc.forceSync() + return buf + } + + describe('configuration', () => { + afterEach(() => { + let { configurations } = workspace + configurations.updateUserConfig({ + 'outline.splitCommand': 'botright 30vs', + 'outline.followCursor': true, + 'outline.keepWindow': false, + 'outline.sortBy': 'category', + 'outline.expandLevel': 1, + 'outline.checkBufferSwitch': true + }) + }) + + it('should follow cursor', async () => { + await createBuffer() + let curr = await nvim.call('bufnr', ['%']) + await symbols.showOutline(0) + let bufnr = await nvim.call('bufnr', ['%']) + await nvim.command('wincmd p') + await nvim.command('exe 3') + await events.fire('CursorHold', [curr]) + await helper.wait(50) + let buf = nvim.createBuffer(bufnr) + let lines = await buf.getLines() + expect(lines).toEqual([ + 'OUTLINE', '- c myClass 1', ' m fun1 2', ' m fun2 3' + ]) + let signs = await buf.getSigns({ group: 'CocTree' }) + expect(signs.length).toBe(1) + expect(signs[0]).toEqual({ + lnum: 2, + id: 3001, + name: 'CocTreeSelected', + priority: 10, + group: 'CocTree' + }) + }) + + it('should not follow cursor', async () => { + workspace.configurations.updateUserConfig({ + 'outline.followCursor': false, + }) + await createBuffer() + let curr = await nvim.call('bufnr', ['%']) + await symbols.showOutline(0) + let bufnr = await nvim.call('bufnr', ['%']) + await nvim.command('wincmd p') + await nvim.command('exe 3') + await events.fire('CursorHold', [curr]) + await helper.wait(50) + let buf = nvim.createBuffer(bufnr) + let signs = await buf.getSigns({ group: 'CocTree' }) + expect(signs.length).toBe(0) + }) + + it('should keep current window', async () => { + workspace.configurations.updateUserConfig({ + 'outline.keepWindow': true, + }) + await createBuffer() + let curr = await nvim.call('bufnr', ['%']) + await symbols.showOutline() + let bufnr = await nvim.call('bufnr', ['%']) + expect(curr).toBe(bufnr) + }) + + it('should check on buffer switch', async () => { + workspace.configurations.updateUserConfig({ + 'outline.checkBufferSwitch': true, + }) + await createBuffer() + await symbols.showOutline(1) + await helper.edit('unnamed') + await helper.wait(300) + let buf = await getOutlineBuffer() + let lines = await buf.lines + expect(lines).toEqual(['Document symbol provider not found']) + }) + + it('should not check on buffer switch', async () => { + workspace.configurations.updateUserConfig({ + 'outline.checkBufferSwitch': false + }) + await helper.wait(30) + await createBuffer() + await symbols.showOutline(1) + await helper.edit('unnamed') + await helper.wait(100) + let buf = await getOutlineBuffer() + let lines = await buf.lines + expect(lines).toEqual([ + 'OUTLINE', '- c myClass 1', ' m fun1 2', ' m fun2 3' + ]) + }) + + it('should not check on buffer reload', async () => { + workspace.configurations.updateUserConfig({ + 'outline.checkBufferSwitch': false + }) + await symbols.showOutline(1) + await helper.wait(50) + await createBuffer() + await helper.wait(50) + let buf = await getOutlineBuffer() + expect(buf).toBeUndefined() + }) + + it('should sort by position', async () => { + let code = `class myClass { + fun2() { } + fun1() {} +}` + workspace.configurations.updateUserConfig({ + 'outline.sortBy': 'position', + }) + await createBuffer(code) + await symbols.showOutline(1) + let buf = await getOutlineBuffer() + let lines = await buf.lines + expect(lines).toEqual([ + 'OUTLINE', '- c myClass 1', ' m fun2 2', ' m fun1 3' + ]) + }) + + it('should sort by name', async () => { + let code = `class myClass { + fun2() {} + fun1() {} +}` + workspace.configurations.updateUserConfig({ + 'outline.sortBy': 'name', + }) + await createBuffer(code) + await symbols.showOutline(1) + let buf = await getOutlineBuffer() + let lines = await buf.lines + expect(lines).toEqual([ + 'OUTLINE', '- c myClass 1', ' m fun1 3', ' m fun2 2' + ]) + }) + }) + + describe('events', () => { + + it('should dispose on buffer unload', async () => { + await createBuffer() + let curr = await nvim.call('bufnr', ['%']) + await symbols.showOutline(0) + await nvim.command('tabe') + await nvim.command(`bd! ${curr}`) + await helper.wait(30) + let buf = await getOutlineBuffer() + expect(buf).toBeUndefined() + }) + + it('should check current window on BufEnter', async () => { + await createBuffer() + await symbols.showOutline(0) + let winid = await nvim.call('win_getid', []) + await nvim.command('enew') + await helper.wait(200) + let win = await nvim.window + expect(win.id).toBe(winid) + }) + + it('should recreated when original window exists', async () => { + await symbols.showOutline(1) + await helper.wait(50) + await createBuffer() + await helper.wait(50) + let buf = await getOutlineBuffer() + expect(buf).toBeDefined() + }) + + it('should keep old outline when new buffer not attached', async () => { + await createBuffer() + await symbols.showOutline(1) + await nvim.command(`vnew +setl\\ buftype=nofile`) + await helper.wait(50) + let buf = await getOutlineBuffer() + expect(buf).toBeDefined() + let lines = await buf.lines + expect(lines).toEqual([ + 'OUTLINE', '- c myClass 1', ' m fun1 2', ' m fun2 3' + ]) + }) + + it('should not reload when switch to original buffer', async () => { + await createBuffer() + await symbols.showOutline(0) + let buf = await getOutlineBuffer() + let name = await buf.name + await nvim.command('wincmd p') + await helper.wait(50) + buf = await getOutlineBuffer() + let curr = await buf.name + expect(curr).toBe(name) + }) + + it('should dispose provider on outline hide', async () => { + await createBuffer() + let bufnr = await nvim.call('bufnr', ['%']) + await symbols.showOutline(0) + await nvim.command('q') + await helper.wait(30) + let exists = symbols.hasOutline(bufnr) + expect(exists).toBe(false) + }) + }) + + describe('show()', () => { + it('should throw when document not attached', async () => { + await nvim.command(`edit +setl\\ buftype=nofile t`) + await helper.wait(50) + let err + try { + await symbols.showOutline(1) + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should not throw when provider not exists', async () => { + await symbols.showOutline(1) + let buf = await getOutlineBuffer() + expect(buf).toBeDefined() + }) + + it('should not throw when symbols is empty', async () => { + await createBuffer('') + await symbols.showOutline(1) + let buf = await getOutlineBuffer() + expect(buf).toBeDefined() + }) + + it('should jump to selected symbol', async () => { + await createBuffer() + let bufnr = await nvim.call('bufnr', ['%']) + await symbols.showOutline(0) + await helper.wait(50) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + let curr = await nvim.call('bufnr', ['%']) + expect(curr).toBe(bufnr) + let cursor = await nvim.call('coc#cursor#position') + expect(cursor).toEqual([1, 2]) + }) + + it('should update symbols', async () => { + await createBuffer() + let doc = await workspace.document + let bufnr = await nvim.call('bufnr', ['%']) + await symbols.showOutline(1) + await helper.wait(10) + let buf = nvim.createBuffer(bufnr) + let code = 'class foo{}' + await buf.setLines(code.split('\n'), { + start: 0, + end: -1, + strictIndexing: false + }) + await doc.synchronize() + await helper.wait(200) + buf = await getOutlineBuffer() + let lines = await buf.lines + expect(lines).toEqual([ + 'No results', + '', + 'OUTLINE' + ]) + }) + }) + + describe('actions', () => { + it('should invoke visual select', async () => { + await createBuffer() + let bufnr = await nvim.call('bufnr', ['%']) + await symbols.showOutline(0) + await helper.wait(50) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + let m = await nvim.mode + expect(m.mode).toBe('v') + let buf = await nvim.buffer + expect(buf.id).toBe(bufnr) + }) + + it('should invoke selected code action', async () => { + const codeAction = CodeAction.create('my action', CodeActionKind.Refactor) + let uri: string + disposables.push(languages.registerCodeActionProvider([{ language: '*' }], { + provideCodeActions: ( + _document, + _range: Range, + _context: CodeActionContext, + _token: CancellationToken + ) => [codeAction], + resolveCodeAction: (action): ProviderResult => { + action.edit = { + changes: { + [uri]: [TextEdit.del(Range.create(0, 0, 0, 5))] + } + } + return action + } + }, undefined)) + await createBuffer() + let bufnr = await nvim.call('bufnr', ['%']) + let doc = workspace.getDocument(bufnr) + uri = doc.uri + await symbols.showOutline(0) + await helper.wait(50) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + await nvim.input('') + await helper.wait(200) + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines[0]).toBe(' myClass {') + }) + }) + + describe('hide()', () => { + it('should hide outline', async () => { + await createBuffer('') + await symbols.showOutline(0) + await symbols.hideOutline() + let buf = await getOutlineBuffer() + expect(buf).toBeUndefined() + }) + + it('should not throw when outline not exists', async () => { + await symbols.hideOutline() + let buf = await getOutlineBuffer() + expect(buf).toBeUndefined() + }) + }) + + describe('dispose', () => { + it('should dispose provider and views', async () => { + await createBuffer('') + let bufnr = await nvim.call('bufnr', ['%']) + await symbols.showOutline(1) + symbols.dispose() + await helper.wait(50) + expect(symbols.hasOutline(bufnr)).toBe(false) + let buf = await getOutlineBuffer() + expect(buf).toBeUndefined() + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/parser.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/parser.ts new file mode 100644 index 00000000..a4a29fae --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/parser.ts @@ -0,0 +1,117 @@ +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentSymbol, SymbolKind, Range } from 'vscode-languageserver-protocol' + +/** + * A syntax parser that parse `class` and `method` only. + */ +export default class Parser { + private _curr = 0 + private _symbols: DocumentSymbol[] = [] + private currSymbol: DocumentSymbol | undefined + private len: number + private textDocument: TextDocument + constructor(private _content: string) { + this.len = _content.length + this.textDocument = TextDocument.create('test:///a', 'txt', 1, _content) + } + + public parse(): DocumentSymbol[] { + while (this._curr <= this.len - 1) { + this.parseToken() + } + return this._symbols + } + + /** + * Parse a symbol, reset currSymbol & _curr + */ + private parseToken(): void { + this.skipSpaces() + if (this.currSymbol) { + let endOffset = this.textDocument.offsetAt(this.currSymbol.range.end) + if (this._curr > endOffset) { + this.currSymbol = undefined + } + } + let remain = this.getLineRemian() + let ms = remain.match(/^(class)\s(\w+)\s\{\s*/) + if (ms) { + // find class + let start = this._curr + 6 + let end = start + ms[2].length + let selectionRange = Range.create(this.textDocument.positionAt(start), this.textDocument.positionAt(end)) + let endPosition = this.findMatchedIndex(this._curr + ms[0].length) + let range = Range.create(this.textDocument.positionAt(this._curr), this.textDocument.positionAt(endPosition)) + let symbolInfo: DocumentSymbol = { + range, + selectionRange, + kind: SymbolKind.Class, + name: ms[2], + children: [] + } + if (this.currSymbol && this.currSymbol.children) { + this.currSymbol.children.push(symbolInfo) + } else { + this._symbols.push(symbolInfo) + } + this.currSymbol = symbolInfo + } else if (this.currSymbol && this.currSymbol.kind == SymbolKind.Class) { + let ms = remain.match(/(\w+)\(.*\)\s*\{/) + if (ms) { + // find method + let start = this._curr + let end = start + ms[1].length + let selectionRange = Range.create(this.textDocument.positionAt(start), this.textDocument.positionAt(end)) + let endPosition = this.findMatchedIndex(this._curr + ms[0].length) + let range = Range.create(this.textDocument.positionAt(this._curr), this.textDocument.positionAt(endPosition)) + let symbolInfo: DocumentSymbol = { + range, + selectionRange, + kind: SymbolKind.Method, + name: ms[1] + } + if (this.currSymbol && this.currSymbol.children) { + this.currSymbol.children.push(symbolInfo) + } else { + this._symbols.push(symbolInfo) + } + } + } + this._curr = this._curr + remain.length + 1 + } + + private findMatchedIndex(start: number): number { + let level = 0 + for (let i = start; i < this.len; i++) { + let ch = this._content[i] + if (ch == '{') { + level = level + 1 + } + if (ch == '}') { + if (level == 0) return i + level = level - 1 + } + } + throw new Error(`Can't find matched }`) + } + + private getLineRemian(): string { + let chars = '' + for (let i = this._curr; i < this.len; i++) { + let ch = this._content[i] + if (ch == '\n') break + chars = chars + ch + } + return chars + } + + private skipSpaces(): void { + for (let i = this._curr; i < this.len; i++) { + let ch = this._content[i] + if (!ch || /\S/.test(ch)) { + this._curr = i + break + } + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/refactor.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/refactor.test.ts new file mode 100644 index 00000000..63046445 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/refactor.test.ts @@ -0,0 +1,347 @@ +import { Neovim } from '@chemzqm/neovim' +import fs from 'fs' +import { URI } from 'vscode-uri' +import Refactor, { FileItem } from '../../handler/refactor/index' +import helper, { createTmpFile } from '../helper' +import languages from '../../languages' +import { WorkspaceEdit, Range } from 'vscode-languageserver-types' +import { Disposable } from '@chemzqm/neovim/lib/api/Buffer' + +let nvim: Neovim +let refactor: Refactor + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + refactor = helper.plugin.getHandler().refactor +}) + +beforeEach(async () => { +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + refactor.reset() + await helper.reset() +}) + +describe('refactor', () => { + describe('create', () => { + it('should create from workspaceEdit', async () => { + let changes = { + [URI.file(__filename).toString()]: [{ + range: Range.create(0, 0, 0, 6), + newText: '' + }, { + range: Range.create(1, 0, 1, 6), + newText: '' + }] + } + let edit: WorkspaceEdit = { changes } + let buf = await refactor.fromWorkspaceEdit(edit) + let shown = await buf.valid + expect(shown).toBe(true) + let items = buf.fileItems + expect(items.length).toBe(1) + }) + + it('should create from locations', async () => { + let uri = URI.file(__filename).toString() + let locations = [{ + uri, + range: Range.create(0, 0, 0, 6), + }, { + uri, + range: Range.create(1, 0, 1, 6), + }] + let buf = await refactor.fromLocations(locations) + let shown = await buf.valid + expect(shown).toBe(true) + let items = buf.fileItems + expect(items.length).toBe(1) + }) + }) + + describe('onChange', () => { + it('should ignore when change after range', async () => { + let doc = await helper.createDocument() + await doc.buffer.append(['foo', 'bar']) + await refactor.fromLocations([{ uri: doc.uri, range: Range.create(0, 0, 0, 3) }]) + let lines = await nvim.call('getline', [1, '$']) + await doc.buffer.append(['def']) + doc.forceSync() + await helper.wait(100) + let newLines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(newLines) + }) + + it('should adjust when change before range', async () => { + let doc = await helper.createDocument() + await doc.buffer.append(['', '', '', '', 'foo', 'bar']) + await helper.wait(50) + doc.forceSync() + let buf = await refactor.fromLocations([{ uri: doc.uri, range: Range.create(4, 0, 4, 3) }]) + await doc.buffer.setLines(['def'], { start: 0, end: 0, strictIndexing: false }) + doc.forceSync() + await helper.wait(100) + let fileRange = buf.getFileRange(4) + expect(fileRange.start).toBe(2) + expect(fileRange.end).toBe(8) + }) + + it('should removed when lines empty', async () => { + let doc = await helper.createDocument() + await doc.buffer.append(['', '', '', '', 'foo', 'bar']) + await helper.wait(50) + doc.forceSync() + let buf = await refactor.fromLocations([{ uri: doc.uri, range: Range.create(4, 0, 4, 3) }]) + await doc.buffer.setLines([], { start: 0, end: -1, strictIndexing: false }) + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines.length).toBe(3) + let items = buf.fileItems + expect(items.length).toBe(0) + }) + + it('should change when liens changed', async () => { + let doc = await helper.createDocument() + await doc.buffer.append(['', '', '', '', 'foo', 'bar']) + await helper.wait(50) + doc.forceSync() + await refactor.fromLocations([{ uri: doc.uri, range: Range.create(4, 0, 4, 3) }]) + await doc.buffer.setLines(['def'], { start: 5, end: 6, strictIndexing: false }) + doc.forceSync() + await helper.wait(30) + let lines = await nvim.call('getline', [1, '$']) + expect(lines[lines.length - 2]).toBe('def') + }) + }) + + describe('refactor#getFileChanges', () => { + it('should get changes #1', async () => { + await helper.createDocument() + let lines = ` +Save current buffer to make changes +\u3000 +\u3000 +\u3000/a.ts + }) + } ` + let buf = await refactor.fromLines(lines.split('\n')) + let changes = await buf.getFileChanges() + expect(changes).toEqual([{ lnum: 5, filepath: '/a.ts', lines: [' })', ' } '] }]) + }) + + it('should get changes #2', async () => { + let lines = ` +\u3000/a.ts + }) + } ` + let buf = await refactor.fromLines(lines.split('\n')) + let changes = await buf.getFileChanges() + expect(changes).toEqual([{ lnum: 2, filepath: '/a.ts', lines: [' })', ' } '] }]) + }) + + it('should get changes #3', async () => { + let lines = ` +\u3000/a.ts + }) + } +\u3000` + let buf = await refactor.fromLines(lines.split('\n')) + let changes = await buf.getFileChanges() + expect(changes).toEqual([{ lnum: 2, filepath: '/a.ts', lines: [' })', ' }'] }]) + }) + + it('should get changes #4', async () => { + let lines = ` +\u3000/a.ts +foo +\u3000/b.ts +bar +\u3000` + let buf = await refactor.fromLines(lines.split('\n')) + let changes = await buf.getFileChanges() + expect(changes).toEqual([ + { filepath: '/a.ts', lnum: 2, lines: ['foo'] }, + { filepath: '/b.ts', lnum: 4, lines: ['bar'] } + ]) + }) + }) + + describe('Refactor#createRefactorBuffer', () => { + it('should create refactor buffer', async () => { + await helper.createDocument() + let winid = await nvim.call('win_getid') + let buf = await refactor.createRefactorBuffer() + let curr = await nvim.call('win_getid') + expect(curr).toBeGreaterThan(winid) + let valid = await buf.valid + expect(valid).toBe(true) + }) + + it('should jump to position by ', async () => { + await helper.createDocument() + let buf = await refactor.createRefactorBuffer() + let fileItem: FileItem = { + filepath: __filename, + ranges: [{ start: 10, end: 11 }, { start: 15, end: 20 }] + } + await buf.addFileItems([fileItem]) + await nvim.call('cursor', [5, 1]) + await buf.splitOpen() + let line = await nvim.eval('line(".")') + let bufname = await nvim.eval('bufname("%")') + expect(bufname).toMatch('refactor.test.ts') + expect(line).toBe(11) + }) + }) + + describe('Refactor#saveRefactor', () => { + it('should adjust line ranges after change', async () => { + let filename = await createTmpFile('foo\n\nbar\n') + let fileItem: FileItem = { + filepath: filename, + ranges: [{ start: 0, end: 1 }, { start: 2, end: 3 }] + } + let buf = await refactor.createRefactorBuffer() + await buf.addFileItems([fileItem]) + nvim.pauseNotification() + nvim.call('setline', [5, ['xyz']], true) + nvim.command('undojoin', true) + nvim.call('append', [5, ['de']], true) + nvim.command('undojoin', true) + nvim.call('append', [8, ['bar']], true) + await nvim.resumeNotification() + await helper.wait(100) + let res = await refactor.save(buf.buffer.id) + expect(res).toBe(true) + let content = fs.readFileSync(filename, 'utf8') + expect(content).toBe('xyz\nde\n\nbar\nbar\n') + }) + + it('should not save when no change made', async () => { + let buf = await refactor.createRefactorBuffer() + let fileItem: FileItem = { + filepath: __filename, + ranges: [{ start: 10, end: 11 }, { start: 15, end: 20 }] + } + await buf.addFileItems([fileItem]) + let res = await buf.save() + expect(res).toBe(false) + }) + + it('should sync buffer change to file', async () => { + let doc = await helper.createDocument() + await doc.buffer.replace(['foo', 'bar', 'line'], 0) + await helper.wait(30) + let filename = URI.parse(doc.uri).fsPath + let fileItem: FileItem = { + filepath: filename, + ranges: [{ start: 0, end: 2 }] + } + let buf = await refactor.createRefactorBuffer() + await buf.addFileItems([fileItem]) + await nvim.call('setline', [5, 'changed']) + let res = await buf.save() + expect(res).toBe(true) + expect(fs.existsSync(filename)).toBe(true) + let content = fs.readFileSync(filename, 'utf8') + let lines = content.split('\n') + expect(lines).toEqual(['changed', 'bar', 'line', '']) + fs.unlinkSync(filename) + }) + }) + + describe('doRefactor', () => { + let disposable: Disposable + + afterEach(() => { + if (disposable) disposable.dispose() + disposable = null + }) + + it('should throw when rename provider not found', async () => { + await helper.createDocument() + let err + try { + await refactor.doRefactor() + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should show message when prepare failed', async () => { + await helper.createDocument() + disposable = languages.registerRenameProvider(['*'], { + prepareRename: () => { + return undefined + }, + provideRenameEdits: () => { + return null + } + }) + await refactor.doRefactor() + let res = await helper.getCmdline() + expect(res).toMatch(/unable to rename/) + }) + + it('should show message when returned edits is null', async () => { + await helper.createDocument() + disposable = languages.registerRenameProvider(['*'], { + provideRenameEdits: () => { + return null + } + }) + await refactor.doRefactor() + let res = await helper.getCmdline() + expect(res).toMatch(/returns null/) + }) + + it('should open refactor window when edits is valid', async () => { + let filepath = __filename + disposable = languages.registerRenameProvider(['*'], { + provideRenameEdits: () => { + let changes = { + [URI.file(filepath).toString()]: [{ + range: Range.create(0, 0, 0, 6), + newText: '' + }, { + range: Range.create(1, 0, 1, 6), + newText: '' + }] + } + let edit: WorkspaceEdit = { changes } + return edit + } + }) + await helper.createDocument(filepath) + let winid = await nvim.call('win_getid') + await refactor.doRefactor() + let currWin = await nvim.call('win_getid') + expect(currWin - winid).toBeGreaterThan(0) + let bufnr = await nvim.call('bufnr', ['%']) + let b = refactor.getBuffer(bufnr) + expect(b).toBeDefined() + }) + }) + + describe('search', () => { + it('should open refactor buffer from search result', async () => { + let escaped = await nvim.call('fnameescape', [__dirname]) + await nvim.command(`cd ${escaped}`) + await helper.createDocument() + await refactor.search(['registerRenameProvider']) + let buf = await nvim.buffer + let name = await buf.name + expect(name).toMatch(/__coc_refactor__/) + let lines = await buf.lines + expect(lines[0]).toMatch(/Save current buffer/) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/rename.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/rename.test.ts new file mode 100644 index 00000000..6560ca8f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/rename.test.ts @@ -0,0 +1,263 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import Rename from '../../handler/rename' +import languages from '../../languages' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] +let rename: Rename + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + rename = helper.plugin.getHandler().rename +}) + +function getWordRangeAtPosition(doc: TextDocument, position: Position): Range | null { + let lines = doc.getText().split(/\r?\n/) + let line = lines[position.line] + if (line.length == 0 || position.character >= line.length) return null + if (!/\w/.test(line[position.character])) return null + let start = position.character + let end = position.character + 1 + if (!/\w/.test(line[start])) { + return Range.create(position, { line: position.line, character: position.character + 1 }) + } + while (start >= 0) { + let ch = line[start - 1] + if (!ch || !/\w/.test(ch)) break + start = start - 1 + } + while (end <= line.length) { + let ch = line[end] + if (!ch || !/\w/.test(ch)) break + end = end + 1 + } + return Range.create(position.line, start, position.line, end) +} + +function getSymbolRanges(textDocument: TextDocument, word: string): Range[] { + let res: Range[] = [] + let str = '' + let content = textDocument.getText() + for (let i = 0, l = content.length; i < l; i++) { + let ch = content[i] + if ('-' == ch && str.length == 0) { + continue + } + let isKeyword = /\w/.test(ch) + if (isKeyword) { + str = str + ch + } + if (str.length > 0 && !isKeyword && str == word) { + res.push(Range.create(textDocument.positionAt(i - str.length), textDocument.positionAt(i))) + } + if (!isKeyword) { + str = '' + } + } + return res +} + +beforeEach(() => { + disposables.push(languages.registerRenameProvider([{ language: 'javascript' }], { + provideRenameEdits: (doc, position: Position, newName: string) => { + let range = getWordRangeAtPosition(doc, position) + if (range) { + let word = doc.getText(range) + if (word) { + let ranges = getSymbolRanges(doc, word) + return { + changes: { + [doc.uri]: ranges.map(o => TextEdit.replace(o, newName)) + } + } + } + } + return undefined + }, + prepareRename: (doc, position) => { + let range = getWordRangeAtPosition(doc, position) + return range ? { range, placeholder: doc.getText(range) } : null + } + })) +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('rename handler', () => { + describe('getWordEdit', () => { + it('should not throw when provider not found', async () => { + await helper.edit() + let res = await rename.getWordEdit() + expect(res).toBe(null) + }) + + it('should return null when prepare failed', async () => { + let doc = await helper.createDocument('t.js') + await nvim.setLine('你') + await doc.synchronize() + let res = await rename.getWordEdit() + expect(res).toBe(null) + }) + + it('should return workspace edit', async () => { + let doc = await helper.createDocument('t.js') + await nvim.setLine('foo foo') + await doc.synchronize() + let res = await rename.getWordEdit() + expect(res).toBeDefined() + expect(res.changes[doc.uri].length).toBe(2) + }) + + it('should extract words from buffer', async () => { + let doc = await helper.createDocument('t') + await nvim.setLine('你 你 你') + await doc.synchronize() + let res = await rename.getWordEdit() + expect(res).toBeDefined() + expect(res.changes[doc.uri].length).toBe(3) + }) + }) + + describe('rename', () => { + it('should throw when provider not found', async () => { + await helper.edit() + let err + try { + await rename.rename('foo') + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should return false for invalid position', async () => { + await helper.createDocument('t.js') + let res = await rename.rename('foo') + expect(res).toBe(false) + }) + + it('should use newName from placeholder', async () => { + await helper.createDocument('t.js') + await nvim.setLine('foo foo foo') + let p = rename.rename() + await helper.wait(50) + await nvim.input('') + await helper.wait(10) + await nvim.input('bar') + await nvim.input('') + let res = await p + expect(res).toBe(true) + }) + + it('should return false for empty name', async () => { + await helper.createDocument('t.js') + await nvim.setLine('foo foo foo') + let p = rename.rename() + await helper.wait(50) + await nvim.input('') + await helper.wait(20) + await nvim.input('') + let res = await p + expect(res).toBe(false) + }) + + it('should use newName from range', async () => { + disposables.push(languages.registerRenameProvider([{ language: '*' }], { + provideRenameEdits: (doc, position: Position, newName: string) => { + let range = getWordRangeAtPosition(doc, position) + if (range) { + let word = doc.getText(range) + if (word) { + let ranges = getSymbolRanges(doc, word) + return { + changes: { + [doc.uri]: ranges.map(o => TextEdit.replace(o, newName)) + } + } + } + } + return undefined + }, + prepareRename: (doc, position) => { + let range = getWordRangeAtPosition(doc, position) + return range ? range : null + } + })) + await helper.createDocument() + await nvim.setLine('foo foo foo') + let p = rename.rename() + await helper.wait(50) + await nvim.input('') + await helper.wait(10) + await nvim.input('bar') + await nvim.input('') + let res = await p + expect(res).toBe(true) + let line = await nvim.getLine() + expect(line).toBe('bar bar bar') + }) + + it('should use newName from cword', async () => { + disposables.push(languages.registerRenameProvider([{ language: '*' }], { + provideRenameEdits: (doc, position: Position, newName: string) => { + let range = getWordRangeAtPosition(doc, position) + if (range) { + let word = doc.getText(range) + if (word) { + let ranges = getSymbolRanges(doc, word) + return { + changes: { + [doc.uri]: ranges.map(o => TextEdit.replace(o, newName)) + } + } + } + } + return undefined + } + })) + await helper.createDocument() + await nvim.setLine('foo foo foo') + let p = rename.rename() + await helper.wait(50) + await nvim.input('') + await helper.wait(10) + await nvim.input('bar') + await nvim.input('') + let res = await p + expect(res).toBe(true) + let line = await nvim.getLine() + expect(line).toBe('bar bar bar') + }) + + it('should return false when result is empty', async () => { + disposables.push(languages.registerRenameProvider([{ language: '*' }], { + provideRenameEdits: () => { + return null + } + })) + await helper.createDocument() + await nvim.setLine('foo foo foo') + let p = rename.rename() + await helper.wait(50) + await nvim.input('') + await helper.wait(10) + await nvim.input('bar') + await nvim.input('') + let res = await p + expect(res).toBe(false) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/search.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/search.test.ts new file mode 100644 index 00000000..bf8ab667 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/search.test.ts @@ -0,0 +1,101 @@ +import { Neovim } from '@chemzqm/neovim' +import Refactor from '../../handler/refactor' +import Search, { getPathFromArgs } from '../../handler/search' +import helper from '../helper' +import path from 'path' + +let nvim: Neovim +let refactor: Refactor +// use fake rg command +let cmd = path.resolve(__dirname, '../rg') +let cwd = process.cwd() + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + refactor = helper.plugin.getHandler().refactor +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + refactor.reset() + await helper.reset() +}) + +describe('getPathFromArgs', () => { + it('should get undefined path', async () => { + let res = getPathFromArgs(['a']) + expect(res).toBeUndefined() + res = getPathFromArgs(['a', 'b', '-c']) + expect(res).toBeUndefined() + res = getPathFromArgs(['a', '-b', 'c']) + expect(res).toBeUndefined() + }) +}) + +describe('search', () => { + + it('should open refactor window', async () => { + let search = new Search(nvim, cmd) + let buf = await refactor.createRefactorBuffer() + await search.run([], cwd, buf) + await helper.wait(50) + let fileItems = buf.fileItems + expect(fileItems.length).toBe(2) + expect(fileItems[0].ranges.length).toBe(2) + }) + + it('should abort task', async () => { + let search = new Search(nvim, cmd) + let buf = await refactor.createRefactorBuffer() + let p = search.run(['--sleep', '1000'], cwd, buf) + search.abort() + await p + let fileItems = buf.fileItems + expect(fileItems.length).toBe(0) + }) + + it('should work with CocAction search', async () => { + await helper.doAction('search', ['CocAction']) + let bufnr = await nvim.call('bufnr', ['%']) + let buf = refactor.getBuffer(bufnr) + expect(buf).toBeDefined() + }) + + it('should fail on invalid command', async () => { + let search = new Search(nvim, 'rrg') + let buf = await refactor.createRefactorBuffer() + let err + try { + await search.run([], cwd, buf) + } catch (e) { + err = e + } + expect(err).toBeDefined() + let msg = await helper.getCmdline() + expect(msg).toMatch(/Error on command "rrg"/) + }) + + it('should show empty result when no result found', async () => { + await helper.doAction('search', ['should found ' + ' no result']) + let bufnr = await nvim.call('bufnr', ['%']) + let buf = refactor.getBuffer(bufnr) + expect(buf).toBeDefined() + let buffer = await nvim.buffer + let lines = await buffer.lines + expect(lines[1]).toMatch(/No match found/) + }) + + it('should use corrent search folder for rg', async () => { + let search = new Search(nvim, 'rg') + await helper.createDocument() + let buf = await refactor.createRefactorBuffer() + await search.run(['-w', 'createRefactorBuffer', 'src/__tests__'], cwd, buf) + let buffer = await nvim.buffer + let lines = await buffer.lines + expect(lines[1].startsWith('Files: ')).toBe(true) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/selectionRange.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/selectionRange.test.ts new file mode 100644 index 00000000..ec43b39d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/selectionRange.test.ts @@ -0,0 +1,143 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, Position, Range, TextEdit } from 'vscode-languageserver-protocol' +import SelectionRange from '../../handler/selectionRange' +import languages from '../../languages' +import workspace from '../../workspace' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] +let selection: SelectionRange + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + selection = helper.plugin.getHandler().selectionRange +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('selectionRange', () => { + describe('getSelectionRanges()', () => { + it('should throw error when selectionRange provider not exists', async () => { + let doc = await helper.createDocument() + await doc.synchronize() + let err + try { + await selection.getSelectionRanges() + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should return ranges', async () => { + await helper.createDocument() + disposables.push(languages.registerSelectionRangeProvider([{ language: '*' }], { + provideSelectionRanges: _doc => { + return [{ + range: Range.create(0, 0, 0, 1) + }] + } + })) + let res = await selection.getSelectionRanges() + expect(res).toBeDefined() + expect(Array.isArray(res)).toBe(true) + }) + }) + + describe('selectRange()', () => { + async function getSelectedRange(): Promise { + let m = await nvim.mode + expect(m.mode).toBe('v') + let bufnr = await nvim.call('bufnr', ['%']) + await nvim.input('') + let doc = workspace.getDocument(bufnr) + let res = await workspace.getSelectedRange('v', doc) + return res + } + + it('should select ranges forward', async () => { + let doc = await helper.createDocument() + let called = 0 + await doc.applyEdits([TextEdit.insert(Position.create(0, 0), 'foo\nbar\ntest\n')]) + await nvim.call('cursor', [1, 1]) + disposables.push(languages.registerSelectionRangeProvider([{ language: '*' }], { + provideSelectionRanges: _doc => { + called += 1 + let arr = [{ + range: Range.create(0, 0, 0, 1) + }, { + range: Range.create(0, 0, 0, 3) + }, { + range: Range.create(0, 0, 1, 3) + }] + return arr + } + })) + await doc.synchronize() + await selection.selectRange('', false) + await selection.selectRange('', true) + expect(called).toBe(1) + let res = await getSelectedRange() + expect(res).toEqual(Range.create(0, 0, 0, 1)) + await selection.selectRange('v', true) + expect(called).toBe(2) + res = await getSelectedRange() + expect(res).toEqual(Range.create(0, 0, 0, 3)) + await selection.selectRange('v', true) + expect(called).toBe(3) + res = await getSelectedRange() + expect(res).toEqual(Range.create(0, 0, 1, 3)) + await selection.selectRange('v', true) + expect(called).toBe(4) + let m = await nvim.mode + expect(m.mode).toBe('n') + }) + + it('should select ranges backward', async () => { + let doc = await helper.createDocument() + await doc.applyEdits([TextEdit.insert(Position.create(0, 0), 'foo\nbar\ntest\n')]) + await nvim.call('cursor', [1, 1]) + disposables.push(languages.registerSelectionRangeProvider([{ language: '*' }], { + provideSelectionRanges: _doc => { + let arr = [{ + range: Range.create(0, 0, 0, 1) + }, { + range: Range.create(0, 0, 0, 3) + }, { + range: Range.create(0, 0, 1, 3) + }] + return arr + } + })) + await doc.synchronize() + await selection.selectRange('', true) + let mode = await nvim.call('mode') + expect(mode).toBe('v') + await nvim.input('') + await workspace.selectRange(Range.create(0, 0, 1, 3)) + await nvim.input('') + await selection.selectRange('v', false) + let r = await getSelectedRange() + expect(r).toEqual(Range.create(0, 0, 0, 3)) + await nvim.input('') + await selection.selectRange('v', false) + r = await getSelectedRange() + expect(r).toEqual(Range.create(0, 0, 0, 1)) + await nvim.input('') + await selection.selectRange('v', false) + mode = await nvim.call('mode') + expect(mode).toBe('n') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/semanticTokens.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/semanticTokens.test.ts new file mode 100644 index 00000000..4d4a20e1 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/semanticTokens.test.ts @@ -0,0 +1,180 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import { Disposable, SemanticTokensLegend } from 'vscode-languageserver-protocol' +import languages from '../../languages' +import SemanticTokensHighlights from '../../handler/semanticTokensHighlights/index' +import { disposeAll } from '../../util' +import workspace from '../../workspace' +import helper from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] +let highlighter: SemanticTokensHighlights +let legend: SemanticTokensLegend = { + tokenTypes: [ + "comment", + "keyword", + "string", + "number", + "regexp", + "operator", + "namespace", + "type", + "struct", + "class", + "interface", + "enum", + "enumMember", + "typeParameter", + "function", + "method", + "property", + "macro", + "variable", + "parameter", + "angle", + "arithmetic", + "attribute", + "bitwise", + "boolean", + "brace", + "bracket", + "builtinType", + "character", + "colon", + "comma", + "comparison", + "constParameter", + "dot", + "escapeSequence", + "formatSpecifier", + "generic", + "label", + "lifetime", + "logical", + "operator", + "parenthesis", + "punctuation", + "selfKeyword", + "semicolon", + "typeAlias", + "union", + "unresolvedReference" + ], + tokenModifiers: [ + "documentation", + "declaration", + "definition", + "static", + "abstract", + "deprecated", + "readonly", + "constant", + "controlFlow", + "injected", + "mutable", + "consuming", + "async", + "library", + "public", + "unsafe", + "attribute", + "trait", + "callable", + "intraDocLink" + ] +} + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + highlighter = helper.plugin.getHandler().semanticHighlighter +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + async function createBuffer(code: string): Promise { + let buf = await nvim.buffer + await nvim.command('setf rust') + await buf.setLines(code.split('\n'), { start: 0, end: -1, strictIndexing: false }) + let doc = await workspace.document + doc.forceSync() + return buf + } + + disposables.push(languages.registerDocumentSemanticTokensProvider([{ language: 'rust' }], { + provideDocumentSemanticTokens: () => { + return { + resultId: '1', + data: [ + 0, 0, 2, 1, 0, + 0, 3, 4, 14, 2, + 0, 4, 1, 41, 0, + 0, 1, 1, 41, 0, + 0, 2, 1, 25, 0, + 1, 4, 8, 17, 0, + 0, 8, 1, 41, 0, + 0, 1, 3, 2, 0, + 0, 3, 1, 41, 0, + 0, 1, 1, 44, 0, + 1, 0, 1, 25, 0, + ] + } + } + }, legend)) + await createBuffer(`fn main() { + println!("H"); +}`) +}) + +afterEach(async () => { + workspace.configurations.updateUserConfig({ + 'coc.preferences.semanticTokensHighlights': true + }) + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('semanticTokens', () => { + describe('triggerSemanticTokens', () => { + it('should be disabled', async () => { + await helper.createDocument() + workspace.configurations.updateUserConfig({ + 'coc.preferences.semanticTokensHighlights': false + }) + const curr = await highlighter.getCurrentItem() + let err + try { + curr.checkState() + } catch (e) { + err = e + } + expect(err).toBeDefined() + expect(err.message).toMatch('disabled by configuration') + }) + + it('should get legend by API', async () => { + const doc = await workspace.document + const l = languages.getLegend(doc.textDocument) + expect(l).toEqual(legend) + }) + + it('should get semanticTokens by API', async () => { + // const doc = await workspace.document + // const highlights = await highlighter.getHighlights(doc.bufnr) + // expect(highlights.length).toBe(11) + // expect(highlights[0].hlGroup).toBe('CocSem_keyword') + }) + + it('should doHighlight', async () => { + const doc = await workspace.document + await nvim.call('CocAction', 'semanticHighlight') + const highlights = await nvim.call("coc#highlight#get_highlights", [doc.bufnr, 'semanticTokens']) + expect(highlights.length).toBe(11) + expect(highlights[0].hlGroup).toBe('CocSem_keyword') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/signature.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/signature.test.ts new file mode 100644 index 00000000..18b9bbad --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/signature.test.ts @@ -0,0 +1,376 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, Position, ParameterInformation, SignatureInformation } from 'vscode-languageserver-protocol' +import languages from '../../languages' +import { disposeAll } from '../../util' +import Signature from '../../handler/signature' +import workspace from '../../workspace' +import helper from '../helper' + +let nvim: Neovim +let signature: Signature +let disposables: Disposable[] = [] + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + signature = helper.plugin.getHandler().signature +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('signatureHelp', () => { + + describe('triggerSignatureHelp', () => { + it('should show signature by api', async () => { + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + } + } + }, [])) + await helper.createDocument() + await nvim.input('foo') + await signature.triggerSignatureHelp() + let win = await helper.getFloat() + expect(win).toBeDefined() + let lines = await helper.getWinLines(win.id) + expect(lines[2]).toMatch('my signature') + }) + + it('should trigger by space', async () => { + let called = false + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + called = true + return { + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + } + } + }, [' '])) + await helper.createDocument() + await nvim.input('i') + await helper.wait(30) + await nvim.input(' ') + await helper.wait(50) + expect(called).toBe(true) + }) + + it('should show signature help with param label as string', async () => { + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [ + SignatureInformation.create('foo()', 'my signature'), + SignatureInformation.create('foo(a, b)', 'my signature', ParameterInformation.create('a', 'description')), + ], + activeParameter: 0, + activeSignature: 1 + } + } + }, [])) + await helper.createDocument() + await nvim.input('foo') + await signature.triggerSignatureHelp() + let win = await helper.getFloat() + expect(win).toBeDefined() + let lines = await helper.getWinLines(win.id) + expect(lines.join('\n')).toMatch(/description/) + }) + + it('should consider coc_last_placeholder on select mode', async () => { + let pos: Position + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, position) => { + pos = position + return { + signatures: [ + SignatureInformation.create('foo(a, b)', 'my signature', ParameterInformation.create('a', 'description')), + ], + activeParameter: 1, + activeSignature: null + } + } + }, [])) + let doc = await helper.createDocument() + let line = await nvim.call('line', ['.']) + await nvim.setLine(' fn(abc, def)') + await nvim.command('normal! 0fave') + await nvim.input('') + let placeholder = { + bufnr: doc.bufnr, + start: Position.create(line - 1, 5), + end: Position.create(line - 1, 8) + } + await nvim.setVar('coc_last_placeholder', placeholder) + let m = await nvim.mode + expect(m.mode).toBe('s') + await signature.triggerSignatureHelp() + let win = await helper.getFloat() + expect(win).toBeDefined() + expect(pos).toEqual(Position.create(0, 5)) + }) + }) + + describe('events', () => { + it('should trigger signature help', async () => { + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [SignatureInformation.create('foo(x, y)', 'my signature')], + activeParameter: 0, + activeSignature: 0 + } + } + }, ['(', ','])) + await helper.createDocument() + await nvim.input('foo') + await nvim.input('(') + await helper.wait(100) + let win = await helper.getFloat() + expect(win).toBeDefined() + let lines = await helper.getWinLines(win.id) + expect(lines[2]).toMatch('my signature') + }) + + it('should cancel trigger on InsertLeave', async () => { + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: async (_doc, _position, token) => { + await helper.wait(1000) + if (token.isCancellationRequested) return undefined + return { + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + } + } + }, ['(', ','])) + await helper.createDocument() + await nvim.input('foo') + let p = signature.triggerSignatureHelp() + await helper.wait(10) + await nvim.command('stopinsert') + await nvim.call('feedkeys', [String.fromCharCode(27), 'in']) + let res = await p + expect(res).toBe(false) + }) + + it('should not close signature on type', async () => { + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + } + } + }, ['(', ','])) + await helper.createDocument() + await nvim.input('foo(') + await helper.wait(100) + await nvim.input('bar') + await helper.wait(100) + let win = await helper.getFloat() + expect(win).toBeDefined() + let lines = await helper.getWinLines(win.id) + expect(lines[2]).toMatch('my signature') + }) + + it('should close signature float when empty signatures returned', async () => { + let empty = false + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + if (empty) return undefined + return { + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + } + } + }, ['(', ','])) + await helper.createDocument() + await nvim.input('foo(') + await helper.wait(100) + let win = await helper.getFloat() + expect(win).toBeDefined() + empty = true + await signature.triggerSignatureHelp() + await helper.wait(50) + let res = await nvim.call('coc#float#valid', [win.id]) + expect(res).toBe(0) + }) + }) + + describe('float window', () => { + it('should align signature window to top', async () => { + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + } + } + }, ['(', ','])) + await helper.createDocument() + let buf = await nvim.buffer + await buf.setLines(['', '', '', '', ''], { start: 0, end: -1, strictIndexing: true }) + await nvim.call('cursor', [5, 1]) + await nvim.input('foo(') + await helper.wait(100) + let win = await helper.getFloat() + expect(win).toBeDefined() + let lines = await helper.getWinLines(win.id) + expect(lines[2]).toMatch('my signature') + let res = await nvim.call('coc#float#cursor_relative', [win.id]) as any + expect(res.row).toBeLessThan(0) + }) + + it('should show parameter docs', async () => { + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [SignatureInformation.create('foo(a, b)', 'my signature', + ParameterInformation.create('a', 'foo'), + ParameterInformation.create([7, 8], 'bar'))], + activeParameter: 1, + activeSignature: null + } + } + }, ['(', ','])) + await helper.createDocument() + let buf = await nvim.buffer + await buf.setLines(['', '', '', '', ''], { start: 0, end: -1, strictIndexing: true }) + await nvim.call('cursor', [5, 1]) + await nvim.input('foo(a,') + await helper.wait(100) + let win = await helper.getFloat() + expect(win).toBeDefined() + let lines = await helper.getWinLines(win.id) + expect(lines.join('\n')).toMatch('bar') + }) + }) + + describe('configurations', () => { + let { configurations } = workspace + afterEach(() => { + configurations.updateUserConfig({ + 'signature.target': 'float', + 'signature.hideOnTextChange': false, + 'signature.enable': true, + 'signature.triggerSignatureWait': 500 + }) + }) + + it('should cancel signature on timeout', async () => { + configurations.updateUserConfig({ 'signature.triggerSignatureWait': 50 }) + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position, token) => { + return new Promise(resolve => { + token.onCancellationRequested(() => { + clearTimeout(timer) + resolve(undefined) + }) + let timer = setTimeout(() => { + resolve({ + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + }) + }, 200) + }) + } + }, ['(', ','])) + await helper.createDocument() + await signature.triggerSignatureHelp() + let win = await helper.getFloat() + expect(win).toBeUndefined() + configurations.updateUserConfig({ 'signature.triggerSignatureWait': 100 }) + }) + + it('should hide signature window on text change', async () => { + configurations.updateUserConfig({ 'signature.hideOnTextChange': true }) + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + } + } + }, ['(', ','])) + await helper.createDocument() + await nvim.input('ifoo(') + let winid = await helper.waitFloat() + await nvim.input('x') + await helper.wait(100) + let res = await nvim.call('coc#float#valid', [winid]) + expect(res).toBe(0) + configurations.updateUserConfig({ 'signature.hideOnTextChange': false }) + }) + + it('should disable signature help trigger', async () => { + configurations.updateUserConfig({ 'signature.enable': false }) + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [SignatureInformation.create('foo()', 'my signature')], + activeParameter: null, + activeSignature: null + } + } + }, ['(', ','])) + await helper.createDocument() + await nvim.input('foo') + await nvim.input('(') + await helper.wait(100) + let win = await helper.getFloat() + expect(win).toBeUndefined() + }) + + it('should echo simple signature help', async () => { + let idx = 0 + let activeSignature = null + configurations.updateUserConfig({ 'signature.target': 'echo' }) + disposables.push(languages.registerSignatureHelpProvider([{ scheme: 'file' }], { + provideSignatureHelp: (_doc, _position) => { + return { + signatures: [SignatureInformation.create('foo(a, b)', 'my signature', + ParameterInformation.create('a', 'foo'), + ParameterInformation.create([7, 8], 'bar')), + SignatureInformation.create('a'.repeat(workspace.env.columns + 10)) + ], + activeParameter: idx, + activeSignature + } + } + }, [])) + await helper.createDocument() + await nvim.input('foo(') + await signature.triggerSignatureHelp() + let line = await helper.getCmdline() + expect(line).toMatch('(a, b)') + await nvim.input('a,') + idx = 1 + await signature.triggerSignatureHelp() + line = await helper.getCmdline() + expect(line).toMatch('foo(a, b)') + activeSignature = 1 + await signature.triggerSignatureHelp() + line = await helper.getCmdline() + expect(line).toMatch('aaaaaa') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/handler/symbols.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/handler/symbols.test.ts new file mode 100644 index 00000000..4adc00f4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/handler/symbols.test.ts @@ -0,0 +1,284 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import { Disposable, SymbolInformation, SymbolKind, Range } from 'vscode-languageserver-protocol' +import Symbols from '../../handler/symbols/index' +import languages from '../../languages' +import workspace from '../../workspace' +import events from '../../events' +import { disposeAll } from '../../util' +import helper from '../helper' +import Parser from './parser' + +let nvim: Neovim +let symbols: Symbols +let disposables: Disposable[] = [] + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + symbols = helper.plugin.getHandler().symbols +}) + +beforeEach(() => { + disposables.push(languages.registerDocumentSymbolProvider([{ language: 'javascript' }], { + provideDocumentSymbols: document => { + let parser = new Parser(document.getText()) + let res = parser.parse() + return Promise.resolve(res) + } + })) +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('Parser', () => { + it('should parse content', async () => { + let code = `class myClass { + fun1() { } + }` + let parser = new Parser(code) + let res = parser.parse() + expect(res.length).toBeGreaterThan(0) + }) +}) + +describe('symbols handler', () => { + + async function createBuffer(code: string): Promise { + let buf = await nvim.buffer + await nvim.command('setf javascript') + await buf.setLines(code.split('\n'), { start: 0, end: -1, strictIndexing: false }) + let doc = await workspace.document + doc.forceSync() + return buf + } + + describe('configuration', () => { + afterEach(() => { + helper.updateConfiguration('coc.preferences.currentFunctionSymbolAutoUpdate', false) + helper.updateConfiguration('coc.preferences.currentFunctionSymbolAutoUpdate', false) + }) + + it('should get configuration', async () => { + let functionUpdate = symbols.functionUpdate + expect(functionUpdate).toBe(false) + helper.updateConfiguration('coc.preferences.currentFunctionSymbolAutoUpdate', true) + functionUpdate = symbols.functionUpdate + expect(functionUpdate).toBe(true) + }) + + it('should update symbols automatically', async () => { + helper.updateConfiguration('coc.preferences.currentFunctionSymbolAutoUpdate', true) + let code = `class myClass { + fun1() { + } + }` + let buf = await createBuffer(code) + await nvim.call('cursor', [2, 8]) + await events.fire('CursorHold', [buf.id]) + let val = await buf.getVar('coc_current_function') + expect(val).toBe('fun1') + await nvim.call('cursor', [1, 8]) + await events.fire('CursorHold', [buf.id]) + val = await buf.getVar('coc_current_function') + expect(val).toBe('myClass') + }) + }) + + describe('documentSymbols', () => { + it('should get symbols of current buffer', async () => { + let code = `class myClass { + fun1() { } + }` + await createBuffer(code) + let res = await helper.plugin.cocAction('documentSymbols') + expect(res.length).toBe(2) + }) + + it('should get current function symbols', async () => { + let code = `class myClass { + fun1() { + } + fun2() { + } + } + ` + await createBuffer(code) + await nvim.call('cursor', [3, 0]) + let res = await helper.doAction('getCurrentFunctionSymbol') + expect(res).toBe('fun1') + await nvim.command('normal! G') + res = await helper.doAction('getCurrentFunctionSymbol') + expect(res).toBe('') + }) + + it('should reset coc_current_function when symbols not exists', async () => { + let code = `class myClass { + fun1() { + } + }` + await createBuffer(code) + await nvim.call('cursor', [3, 0]) + let res = await helper.doAction('getCurrentFunctionSymbol') + expect(res).toBe('fun1') + await nvim.command('normal! ggdG') + res = await symbols.getCurrentFunctionSymbol() + expect(res).toBe('') + }) + + it('should support SymbolInformation', async () => { + disposables.push(languages.registerDocumentSymbolProvider(['*'], { + provideDocumentSymbols: () => { + return [ + SymbolInformation.create('root', SymbolKind.Function, Range.create(0, 0, 0, 10)), + SymbolInformation.create('child', SymbolKind.Function, Range.create(0, 0, 0, 10), '', 'root') + ] + } + })) + let doc = await helper.createDocument() + let res = await symbols.getDocumentSymbols(doc.bufnr) + expect(res.length).toBe(2) + expect(res[0].text).toBe('root') + expect(res[1].text).toBe('child') + }) + }) + + describe('selectSymbolRange', () => { + it('should show warning when no symbols exists', async () => { + disposables.push(languages.registerDocumentSymbolProvider(['*'], { + provideDocumentSymbols: () => { + return [] + } + })) + await helper.createDocument() + await nvim.call('cursor', [3, 0]) + await symbols.selectSymbolRange(false, '', ['Function']) + let msg = await helper.getCmdline() + expect(msg).toMatch(/No symbols found/) + }) + + it('should select symbol range at cursor position', async () => { + let code = `class myClass { + fun1() { + } + }` + let buf = await createBuffer(code) + await nvim.call('cursor', [3, 0]) + await helper.doAction('selectSymbolRange', false, '', ['Function', 'Method']) + let mode = await nvim.mode + expect(mode.mode).toBe('v') + let doc = workspace.getDocument(buf.id) + await nvim.input('') + let res = await workspace.getSelectedRange('v', doc) + expect(res).toEqual({ start: { line: 1, character: 6 }, end: { line: 2, character: 6 } }) + }) + + it('should select inner range', async () => { + let code = `class myClass { + fun1() { + let foo; + } +}` + let buf = await createBuffer(code) + await nvim.call('cursor', [3, 3]) + await symbols.selectSymbolRange(true, '', ['Method']) + let mode = await nvim.mode + expect(mode.mode).toBe('v') + let doc = workspace.getDocument(buf.id) + await nvim.input('') + let res = await workspace.getSelectedRange('v', doc) + expect(res).toEqual({ + start: { line: 2, character: 8 }, end: { line: 2, character: 16 } + }) + }) + + it('should reset visualmode when selection not found', async () => { + let code = `class myClass {}` + await createBuffer(code) + await nvim.call('cursor', [1, 1]) + await nvim.command('normal! gg0v$') + let mode = await nvim.mode + expect(mode.mode).toBe('v') + await nvim.input('') + await symbols.selectSymbolRange(true, 'v', ['Method']) + mode = await nvim.mode + expect(mode.mode).toBe('v') + }) + + it('should select symbol range from select range', async () => { + let code = `class myClass { + fun1() { + } + }` + let buf = await createBuffer(code) + await nvim.call('cursor', [2, 8]) + await nvim.command('normal! viw') + await nvim.input('') + await helper.doAction('selectSymbolRange', false, 'v', ['Class']) + let mode = await nvim.mode + expect(mode.mode).toBe('v') + let doc = workspace.getDocument(buf.id) + await nvim.input('') + let res = await workspace.getSelectedRange('v', doc) + expect(res).toEqual({ start: { line: 0, character: 0 }, end: { line: 3, character: 4 } }) + }) + }) + + describe('cancel', () => { + it('should cancel symbols request on insert', async () => { + let cancelled = false + disposables.push(languages.registerDocumentSymbolProvider([{ language: 'text' }], { + provideDocumentSymbols: (_doc, token) => { + return new Promise(s => { + token.onCancellationRequested(() => { + if (timer) clearTimeout(timer) + cancelled = true + s(undefined) + }) + let timer = setTimeout(() => { + s(undefined) + }, 3000) + }) + } + })) + let doc = await helper.createDocument('t.txt') + let p = symbols.getDocumentSymbols(doc.bufnr) + setTimeout(async () => { + await nvim.input('i') + }, 500) + await p + expect(cancelled).toBe(true) + }) + }) + + describe('workspaceSymbols', () => { + it('should get workspace symbols', async () => { + disposables.push(languages.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols: (_query, _token) => { + return [SymbolInformation.create('far', SymbolKind.Class, Range.create(0, 0, 0, 0))] + }, + resolveWorkspaceSymbol: sym => { + let res = Object.assign({}, sym) + res.location.uri = 'test:///foo' + return res + } + })) + disposables.push(languages.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols: (_query, _token) => { + return [SymbolInformation.create('bar', SymbolKind.Function, Range.create(0, 0, 0, 0))] + } + })) + let res = await symbols.getWorkspaceSymbols('a') + expect(res.length).toBe(2) + let resolved = await symbols.resolveWorkspaceSymbol(res[0]) + expect(resolved?.location?.uri).toBe('test:///foo') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/helper.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/helper.test.ts new file mode 100644 index 00000000..2c1e10ed --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/helper.test.ts @@ -0,0 +1,22 @@ +import { Neovim } from '@chemzqm/neovim' +import Plugin from '../plugin' +import helper from './helper' + +let nvim: Neovim +let plugin: Plugin +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + plugin = helper.plugin +}) + +describe('Helper', () => { + it('should setup', () => { + expect(nvim).toBeTruthy() + expect(plugin.isReady).toBeTruthy() + }) +}) + +afterAll(async () => { + await helper.shutdown() +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/helper.ts b/vim-config/plugins/coc.nvim/src/__tests__/helper.ts new file mode 100644 index 00000000..795f45b0 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/helper.ts @@ -0,0 +1,248 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +import { Buffer, Neovim, Window } from '@chemzqm/neovim' +import * as cp from 'child_process' +import { EventEmitter } from 'events' +import fs from 'fs' +import os from 'os' +import path from 'path' +import util from 'util' +import attach from '../attach' +import Document from '../model/document' +import Plugin from '../plugin' +import workspace from '../workspace' +import { v4 as uuid } from 'uuid' +import { VimCompleteItem } from '../types' + +export interface CursorPosition { + bufnum: number + lnum: number + col: number +} + +process.on('uncaughtException', err => { + let msg = 'Uncaught exception: ' + err.stack + console.error(msg) +}) +export class Helper extends EventEmitter { + public nvim: Neovim + public proc: cp.ChildProcess + public plugin: Plugin + + constructor() { + super() + this.setMaxListeners(99) + } + + public setup(): Promise { + const vimrc = path.resolve(__dirname, 'vimrc') + let proc = this.proc = cp.spawn('nvim', ['-u', vimrc, '-i', 'NONE', '--embed'], { + cwd: __dirname + }) + let plugin = this.plugin = attach({ proc }) + this.nvim = plugin.nvim + this.nvim.uiAttach(160, 80, {}).catch(_e => { + // noop + }) + proc.on('exit', () => { + this.proc = null + }) + this.nvim.on('notification', (method, args) => { + if (method == 'redraw') { + for (let arg of args) { + let event = arg[0] + this.emit(event, arg.slice(1)) + } + } + }) + return new Promise(resolve => { + plugin.once('ready', resolve) + }) + } + + public async shutdown(): Promise { + this.plugin.dispose() + await this.nvim.quit() + if (this.proc) { + this.proc.kill('SIGKILL') + } + await this.wait(60) + } + + public async waitPopup(): Promise { + for (let i = 0; i < 40; i++) { + await this.wait(50) + let visible = await this.nvim.call('pumvisible') + if (visible) return + } + throw new Error('timeout after 2s') + } + + public async waitFloat(): Promise { + for (let i = 0; i < 40; i++) { + await this.wait(50) + let winid = await this.nvim.call('coc#float#get_float_win') + if (winid) return winid + } + throw new Error('timeout after 2s') + } + + public async selectCompleteItem(idx: number): Promise { + await this.nvim.call('nvim_select_popupmenu_item', [idx, true, true, {}]) + } + + public async doAction(method: string, ...args: any[]): Promise { + return await this.plugin.cocAction(method, ...args) + } + + public async reset(): Promise { + let mode = await this.nvim.mode + if (mode.mode != 'n' || mode.blocking) { + await this.nvim.command('stopinsert') + await this.nvim.call('feedkeys', [String.fromCharCode(27), 'in']) + } + await this.nvim.command('silent! %bwipeout!') + await this.wait(80) + } + + public async pumvisible(): Promise { + let res = await this.nvim.call('pumvisible', []) as number + return res == 1 + } + + public wait(ms = 30): Promise { + return new Promise(resolve => { + setTimeout(() => { + resolve() + }, ms) + }) + } + + public async visible(word: string, source?: string): Promise { + await this.waitPopup() + let context = await this.nvim.getVar('coc#_context') as any + let items = context.candidates + if (!items) return false + let item = items.find(o => o.word == word) + if (!item || !item.user_data) return false + try { + let o = JSON.parse(item.user_data) + if (source && o.source !== source) { + return false + } + } catch (e) { + return false + } + return true + } + + public async notVisible(word: string): Promise { + let items = await this.getItems() + return items.findIndex(o => o.word == word) == -1 + } + + public async getItems(): Promise { + let visible = await this.pumvisible() + if (!visible) return [] + let context = await this.nvim.getVar('coc#_context') as any + let items = context.candidates + return items || [] + } + + public async edit(file?: string): Promise { + if (!file || !path.isAbsolute(file)) { + file = path.join(__dirname, file ? file : `${uuid()}`) + } + let escaped = await this.nvim.call('fnameescape', file) as string + await this.nvim.command(`edit ${escaped}`) + await this.wait(60) + let bufnr = await this.nvim.call('bufnr', ['%']) as number + return this.nvim.createBuffer(bufnr) + } + + public async createDocument(name?: string): Promise { + let buf = await this.edit(name) + let doc = workspace.getDocument(buf.id) + if (!doc) return await workspace.document + return doc + } + + public async getMarkers(bufnr: number, ns: number): Promise<[number, number, number][]> { + return await this.nvim.call('nvim_buf_get_extmarks', [bufnr, ns, 0, -1, {}]) as [number, number, number][] + } + + public async getCmdline(): Promise { + let str = '' + for (let i = 1, l = 70; i < l; i++) { + let ch = await this.nvim.call('screenchar', [79, i]) + if (ch == -1) break + str += String.fromCharCode(ch) + } + return str.trim() + } + + public updateConfiguration(key: string, value: any): () => void { + let { configurations } = workspace as any + let curr = workspace.getConfiguration(key) + configurations.updateUserConfig({ [key]: value }) + return () => { + configurations.updateUserConfig({ [key]: curr }) + } + } + + public async mockFunction(name: string, result: string | number | any): Promise { + let content = ` + function! ${name}(...) + return ${typeof result == 'number' ? result : JSON.stringify(result)} + endfunction + ` + let file = await createTmpFile(content) + await this.nvim.command(`source ${file}`) + } + + public async items(): Promise { + let context = await this.nvim.getVar('coc#_context') + return context['candidates'] || [] + } + + public async screenLine(line: number): Promise { + let res = '' + for (let i = 1; i <= 80; i++) { + let ch = await this.nvim.call('screenchar', [line, i]) + res = res + String.fromCharCode(ch) + } + return res + } + + public async getWinLines(winid: number): Promise { + return await this.nvim.eval(`getbufline(winbufnr(${winid}), 1, '$')`) as string[] + } + + public async getFloat(): Promise { + let wins = await this.nvim.windows + let floatWin: Window + for (let win of wins) { + let f = await win.getVar('float') + if (f) floatWin = win + } + return floatWin + } + + public async getFloats(): Promise { + let ids = await this.nvim.call('coc#float#get_float_win_list', []) + if (!ids) return [] + return ids.map(id => this.nvim.createWindow(id)) + } +} + +export async function createTmpFile(content: string): Promise { + let tmpFolder = path.join(os.tmpdir(), `coc-${process.pid}`) + if (!fs.existsSync(tmpFolder)) { + fs.mkdirSync(tmpFolder) + } + let filename = path.join(tmpFolder, uuid()) + await util.promisify(fs.writeFile)(filename, content, 'utf8') + return filename +} + +export default new Helper() diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/basicList.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/basicList.test.ts new file mode 100644 index 00000000..5f05063e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/basicList.test.ts @@ -0,0 +1,175 @@ +import { Neovim } from '@chemzqm/neovim' +import { URI } from 'vscode-uri' +import { Disposable, Range, Location } from 'vscode-languageserver-protocol' +import BasicList, { getFiletype, PreviewOptions } from '../../list/basic' +import manager from '../../list/manager' +import { ListItem } from '../../types' +import { disposeAll } from '../../util' +import helper from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] +let previewOptions: PreviewOptions + +let list: SimpleList +class SimpleList extends BasicList { + public name = 'simple' + public defaultAction: 'preview' + constructor(nvim: Neovim) { + super(nvim) + this.addAction('preview', async (_item, context) => { + await this.preview(previewOptions, context) + }) + } + public loadItems(): Promise { + return Promise.resolve(['a', 'b', 'c'].map((s, idx) => { + return { label: s, location: Location.create('test:///a', Range.create(idx, 0, idx + 1, 0)) } as ListItem + })) + } +} + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(() => { + list = new SimpleList(nvim) + disposables.push(manager.registerList(list)) +}) + +afterEach(async () => { + disposeAll(disposables) + manager.reset() + await helper.reset() +}) + +describe('getFiletype()', () => { + it('should get filetype', async () => { + expect(getFiletype('javascriptreact')).toBe('javascript') + expect(getFiletype('typescriptreact')).toBe('typescript') + expect(getFiletype('latex')).toBe('tex') + expect(getFiletype('foo.bar')).toBe('foo') + expect(getFiletype('foo')).toBe('foo') + }) +}) + +describe('BasicList', () => { + async function doPreview(opts: PreviewOptions): Promise { + previewOptions = opts + await manager.start(['--normal', 'simple']) + await manager.session.ui.ready + await manager.doAction('preview') + let res = await nvim.call('coc#list#has_preview') as number + expect(res).toBeGreaterThan(0) + let winid = await nvim.call('win_getid', [res]) + return winid + } + + describe('preview()', () => { + it('should preview lines', async () => { + await doPreview({ filetype: '', lines: ['foo', 'bar'] }) + }) + + it('should preview with bufname', async () => { + await doPreview({ + bufname: 't.js', + filetype: 'typescript', + lines: ['foo', 'bar'] + }) + }) + + it('should preview with range highlight', async () => { + let winid = await doPreview({ + bufname: 't.js', + filetype: 'typescript', + lines: ['foo', 'bar'], + range: Range.create(0, 0, 0, 3) + }) + let res = await nvim.call('getmatches', [winid]) + expect(res.length).toBeGreaterThan(0) + }) + + }) + + describe('createAction()', () => { + it('should overwrite action', async () => { + let idx: number + list.createAction({ + name: 'foo', + execute: () => { idx = 0 } + }) + list.createAction({ + name: 'foo', + execute: () => { idx = 1 } + }) + await manager.start(['--normal', 'simple']) + await manager.session.ui.ready + await manager.doAction('foo') + expect(idx).toBe(1) + }) + }) + + describe('jumpTo()', () => { + it('should jump to uri', async () => { + let uri = URI.file(__filename).toString() + await list.jumpTo(uri, 'edit') + let bufname = await nvim.call('bufname', ['%']) + expect(bufname).toMatch('basicList.test.ts') + }) + + it('should jump to location', async () => { + let uri = URI.file(__filename).toString() + let loc = Location.create(uri, Range.create(0, 0, 1, 0)) + await list.jumpTo(loc, 'edit') + let bufname = await nvim.call('bufname', ['%']) + expect(bufname).toMatch('basicList.test.ts') + }) + + it('should jump to location with empty range', async () => { + let uri = URI.file(__filename).toString() + let loc = Location.create(uri, Range.create(0, 0, 0, 0)) + await list.jumpTo(loc, 'edit') + let bufname = await nvim.call('bufname', ['%']) + expect(bufname).toMatch('basicList.test.ts') + }) + }) + + describe('convertLocation()', () => { + it('should convert uri', async () => { + let uri = URI.file(__filename).toString() + let res = await list.convertLocation(uri) + expect(res.uri).toBe(uri) + }) + + it('should convert location with line', async () => { + let uri = URI.file(__filename).toString() + let res = await list.convertLocation({ uri, line: 'convertLocation()', text: 'convertLocation' }) + expect(res.uri).toBe(uri) + res = await list.convertLocation({ uri, line: 'convertLocation()' }) + expect(res.uri).toBe(uri) + }) + + it('should convert location with custom schema', async () => { + let uri = 'test:///foo' + let res = await list.convertLocation({ uri, line: 'convertLocation()'}) + expect(res.uri).toBe(uri) + }) + }) + + describe('quickfix action', () => { + it('should invoke quickfix action', async () => { + list.addLocationActions() + await manager.start(['--normal', 'simple', '-arg']) + await manager.session.ui.ready + await manager.session.ui.selectAll() + await manager.doAction('quickfix') + let res = await nvim.call('getqflist') + expect(res.length).toBeGreaterThan(1) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/commandTask.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/commandTask.test.ts new file mode 100644 index 00000000..37f2e00c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/commandTask.test.ts @@ -0,0 +1,134 @@ +import { Neovim } from '@chemzqm/neovim' +import path from 'path' +import { ListContext, ListTask } from '../../types' +import manager from '../../list/manager' +import helper, { createTmpFile } from '../helper' +import BasicList from '../../list/basic' +import { Disposable } from 'vscode-languageserver-protocol' +import { disposeAll } from '../../util' + +class DataList extends BasicList { + public name = 'data' + public async loadItems(_context: ListContext): Promise { + let fsPath = await createTmpFile(`console.log('foo');console.log('');console.log('bar');`) + return this.createCommandTask({ + cmd: 'node', + args: [fsPath], + cwd: path.dirname(fsPath), + onLine: line => { + if (!line) return undefined + return { + label: line + } + } + }) + } +} + +class SleepList extends BasicList { + public name = 'sleep' + public loadItems(_context: ListContext): Promise { + return Promise.resolve(this.createCommandTask({ + cmd: 'sleep', + args: ['10'], + cwd: __dirname, + onLine: line => { + return { + label: line + } + } + })) + } +} + +class StderrList extends BasicList { + public name = 'stderr' + public async loadItems(_context: ListContext): Promise { + let fsPath = await createTmpFile(`console.error('stderr');console.log('stdout')`) + return Promise.resolve(this.createCommandTask({ + cmd: 'node', + args: [fsPath], + cwd: path.dirname(fsPath), + onLine: line => { + return { + label: line + } + } + })) + } +} + +class ErrorTask extends BasicList { + public name = 'error' + public async loadItems(_context: ListContext): Promise { + return Promise.resolve(this.createCommandTask({ + cmd: 'NOT_EXISTS', + args: [], + cwd: __dirname, + onLine: line => { + return { + label: line + } + } + })) + } +} + +let nvim: Neovim +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + disposeAll(disposables) + manager.reset() + await helper.reset() +}) + +describe('Command task', () => { + it('should not show stderr', async () => { + disposables.push(manager.registerList(new StderrList(nvim))) + await manager.start(['stderr']) + await manager.session.ui.ready + let lines = await nvim.call('getline', [1, '$']) as string[] + expect(lines).toEqual(['stdout']) + }) + + it('should not show error', async () => { + disposables.push(manager.registerList(new ErrorTask(nvim))) + await manager.start(['error']) + await helper.wait(100) + let res = await helper.getCmdline() + expect(res).toMatch('NOT_EXISTS ENOENT') + }) + + it('should create command task', async () => { + let list = new DataList(nvim) + disposables.push(manager.registerList(list)) + await manager.start(['data']) + await helper.wait(500) + let lines = await nvim.call('getline', [1, '$']) as string[] + expect(lines).toEqual(['foo', 'bar']) + }) + + it('should stop command task', async () => { + let list = new SleepList(nvim) + disposables.push(manager.registerList(list)) + await manager.start(['sleep']) + manager.session.stop() + }) + + it('should show error for bad key', async () => { + let list = new DataList(nvim) + list.config.fixKey('') + await helper.wait(500) + let msg = await helper.getCmdline() + expect(msg).toMatch('not supported') + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/formatting.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/formatting.test.ts new file mode 100644 index 00000000..b9a78433 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/formatting.test.ts @@ -0,0 +1,32 @@ +import { formatPath, UnformattedListItem, formatListItems } from '../../list/formatting' + +describe('formatPath()', () => { + it('should format path', async () => { + expect(formatPath('hidden', 'path')).toBe('') + expect(formatPath('full', __filename)).toMatch('formatting.test.ts') + expect(formatPath('short', __filename)).toMatch('formatting.test.ts') + expect(formatPath('filename', __filename)).toMatch('formatting.test.ts') + }) +}) + +describe('formatListItems', () => { + it('should format list items', async () => { + expect(formatListItems(false, [])).toEqual([]) + let items: UnformattedListItem[] = [{ + label: ['a', 'b', 'c'] + }] + expect(formatListItems(false, items)).toEqual([{ + label: 'a\tb\tc' + }]) + items = [{ + label: ['a', 'b', 'c'] + }, { + label: ['foo', 'bar', 'go'] + }] + expect(formatListItems(true, items)).toEqual([{ + label: 'a \tb \tc ' + }, { + label: 'foo\tbar\tgo' + }]) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/location.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/location.test.ts new file mode 100644 index 00000000..ef9a6eac --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/location.test.ts @@ -0,0 +1,79 @@ +import { Neovim } from '@chemzqm/neovim' +import manager from '../../list/manager' +import { Range } from 'vscode-languageserver-protocol' +import events from '../../events' +import helper from '../helper' + +let nvim: Neovim +const locations: any[] = [{ + filename: __filename, + range: Range.create(0, 0, 0, 6), + text: 'foo' +}, { + filename: __filename, + range: Range.create(2, 0, 2, 6), + text: 'Bar' +}, { + filename: __filename, + range: Range.create(3, 0, 4, 6), + text: 'multiple' +}] + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + await nvim.setVar('coc_jump_locations', locations) +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + manager.reset() + await helper.reset() + await helper.wait(100) +}) + +describe('list commands', () => { + it('should highlight ranges', async () => { + await manager.start(['--normal', '--auto-preview', 'location']) + await manager.session.ui.ready + await helper.wait(200) + manager.prompt.cancel() + await nvim.command('wincmd k') + let name = await nvim.eval('bufname("%")') + expect(name).toMatch('location.test.ts') + let res = await nvim.call('getmatches') + expect(res.length).toBe(1) + }) + + it('should change highlight on cursor move', async () => { + await manager.start(['--normal', '--auto-preview', 'location']) + await manager.session.ui.ready + await helper.wait(200) + await nvim.command('exe 2') + let bufnr = await nvim.eval('bufnr("%")') + await events.fire('CursorMoved', [bufnr, [2, 1]]) + await helper.wait(300) + await nvim.command('wincmd k') + let res = await nvim.call('getmatches') + expect(res.length).toBe(1) + expect(res[0]['pos1']).toEqual([3, 1, 6]) + }) + + it('should highlight multiple line range', async () => { + await manager.start(['--normal', '--auto-preview', 'location']) + await manager.session.ui.ready + await helper.wait(200) + await nvim.command('exe 3') + let bufnr = await nvim.eval('bufnr("%")') + await events.fire('CursorMoved', [bufnr, [2, 1]]) + await helper.wait(300) + await nvim.command('wincmd k') + let res = await nvim.call('getmatches') + expect(res.length).toBe(1) + expect(res[0]['pos1']).toBeDefined() + expect(res[0]['pos2']).toBeDefined() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/manager.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/manager.test.ts new file mode 100644 index 00000000..b6b7a863 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/manager.test.ts @@ -0,0 +1,509 @@ +import { Neovim } from '@chemzqm/neovim' +import path from 'path' +import manager from '../../list/manager' +import events from '../../events' +import { QuickfixItem, IList, ListItem } from '../../types' +import helper from '../helper' + +let nvim: Neovim +const locations: ReadonlyArray = [{ + filename: __filename, + col: 2, + lnum: 1, + text: 'foo' +}, { + filename: __filename, + col: 1, + lnum: 2, + text: 'Bar' +}, { + filename: __filename, + col: 1, + lnum: 3, + text: 'option' +}] + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + await nvim.setVar('coc_jump_locations', locations) +}) + +afterEach(async () => { + manager.reset() + await helper.reset() +}) + +afterAll(async () => { + await helper.shutdown() +}) + +describe('list', () => { + describe('events', () => { + it('should cancel and enable prompt', async () => { + let winid = await nvim.call('win_getid') + await manager.start(['location']) + await manager.session.ui.ready + await nvim.call('win_gotoid', [winid]) + await helper.wait(50) + let res = await nvim.call('coc#prompt#activated') + expect(res).toBe(0) + await nvim.command('wincmd p') + await helper.wait(50) + res = await nvim.call('coc#prompt#activated') + expect(res).toBe(1) + }) + }) + + describe('list commands', () => { + it('should be activated', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await helper.wait(50) + expect(manager.isActivated).toBe(true) + let line = await nvim.getLine() + expect(line).toMatch(/manager.test.ts/) + }) + + it('should get list names', () => { + let names = manager.names + expect(names.length > 0).toBe(true) + }) + + it('should resume list', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await helper.wait(30) + await nvim.eval('feedkeys("j", "in")') + await helper.wait(30) + let line = await nvim.call('line', '.') + expect(line).toBe(2) + await manager.cancel() + await helper.wait(30) + await manager.resume() + await helper.wait(30) + line = await nvim.call('line', '.') + expect(line).toBe(2) + }) + + it('should not quit list with --no-quit', async () => { + await manager.start(['--normal', '--no-quit', 'location']) + await manager.session.ui.ready + let winnr = await nvim.eval('win_getid()') as number + await manager.doAction() + await helper.wait(100) + let wins = await nvim.windows + let ids = wins.map(o => o.id) + expect(ids).toContain(winnr) + }) + + it('should do default action for first item', async () => { + await manager.start(['--normal', '--first', 'location']) + await helper.wait(300) + let name = await nvim.eval('bufname("%")') as string + let filename = path.basename(__filename) + expect(name.includes(filename)).toBe(true) + let pos = await nvim.eval('getcurpos()') + expect(pos[1]).toBe(1) + expect(pos[2]).toBe(2) + }) + + it('should goto next & previous', async () => { + await manager.start(['location']) + await manager.session?.ui.ready + await helper.wait(60) + await manager.doAction() + await manager.cancel() + let bufname = await nvim.eval('expand("%:p")') + expect(bufname).toMatch('manager.test.ts') + await manager.next() + let line = await nvim.call('line', '.') + expect(line).toBe(2) + await helper.wait(60) + await manager.previous() + line = await nvim.call('line', '.') + expect(line).toBe(1) + }) + + it('should parse arguments', async () => { + await manager.start(['--input=test', '--normal', '--no-sort', '--ignore-case', '--top', '--number-select', '--auto-preview', '--strict', 'location']) + await helper.wait(30) + let opts = manager.session?.listOptions + expect(opts).toEqual({ + numberSelect: true, + autoPreview: true, + first: false, + input: 'test', + interactive: false, + matcher: 'strict', + ignorecase: true, + position: 'top', + mode: 'normal', + noQuit: false, + sort: false + }) + }) + }) + + describe('list options', () => { + it('should respect input option', async () => { + await manager.start(['--input=foo', 'location']) + await manager.session.ui.ready + await helper.wait(30) + let line = await helper.getCmdline() + expect(line).toMatch('foo') + expect(manager.isActivated).toBe(true) + }) + + it('should respect regex filter', async () => { + await manager.start(['--input=f.o', '--regex', 'location']) + await helper.wait(200) + let item = await manager.session?.ui.item + expect(item.label).toMatch('foo') + }) + + it('should respect normal option', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + let line = await helper.getCmdline() + expect(line).toBe('') + }) + + it('should respect nosort option', async () => { + await manager.start(['--ignore-case', '--no-sort', 'location']) + await manager.session.ui.ready + expect(manager.isActivated).toBe(true) + await nvim.input('oo') + await helper.wait(100) + let line = await nvim.call('getline', ['.']) + expect(line).toMatch('foo') + }) + + it('should respect ignorecase option', async () => { + await manager.start(['--ignore-case', '--strict', 'location']) + await manager.session.ui.ready + expect(manager.isActivated).toBe(true) + await nvim.input('bar') + await helper.wait(100) + let n = manager.session?.ui.length + expect(n).toBe(1) + let line = await nvim.line + expect(line).toMatch('Bar') + }) + + it('should respect top option', async () => { + await manager.start(['--top', 'location']) + await manager.session.ui.ready + let nr = await nvim.call('winnr') + expect(nr).toBe(1) + }) + + it('should respect number select option', async () => { + await manager.start(['--number-select', 'location']) + await manager.session.ui.ready + await helper.wait(100) + await nvim.eval('feedkeys("2", "in")') + await helper.wait(100) + let lnum = locations[1].lnum + let curr = await nvim.call('line', '.') + expect(lnum).toBe(curr) + }) + + it('should respect auto preview option', async () => { + await manager.start(['--auto-preview', 'location']) + await helper.wait(300) + let previewWinnr = await nvim.call('coc#list#has_preview') + expect(previewWinnr).toBe(2) + let bufnr = await nvim.call('winbufnr', previewWinnr) + let buf = nvim.createBuffer(bufnr) + let name = await buf.name + expect(name).toMatch('manager.test.ts') + await nvim.eval('feedkeys("j", "in")') + await helper.wait(100) + let winnr = await nvim.call('coc#list#has_preview') + expect(winnr).toBe(previewWinnr) + }) + + it('should respect tab option', async () => { + await manager.start(['--tab', '--auto-preview', 'location']) + await manager.session.ui.ready + await helper.wait(200) + await nvim.command('wincmd l') + let previewwindow = await nvim.eval('w:previewwindow') + expect(previewwindow).toBe(1) + }) + }) + + describe('list configuration', () => { + it('should change indicator', async () => { + helper.updateConfiguration('list.indicator', '>>') + await manager.start(['location']) + await helper.wait(200) + let line = await helper.getCmdline() + expect(line).toMatch('>>') + }) + + it('should split right for preview window', async () => { + helper.updateConfiguration('list.previewSplitRight', true) + let win = await nvim.window + await manager.start(['location']) + await helper.wait(100) + await manager.doAction('preview') + await helper.wait(100) + manager.prompt.cancel() + await helper.wait(10) + await nvim.call('win_gotoid', [win.id]) + await nvim.command('wincmd l') + let curr = await nvim.window + let isPreview = await curr.getVar('previewwindow') + expect(isPreview).toBe(1) + helper.updateConfiguration('list.previewSplitRight', false) + }) + + it('should toggle selection mode', async () => { + await manager.start(['--normal', 'location']) + await manager.session?.ui.ready + await nvim.input('V') + await helper.wait(30) + await nvim.input('1') + await helper.wait(30) + await nvim.input('j') + await helper.wait(100) + await manager.session?.ui.toggleSelection() + let items = await manager.session?.ui.getItems() + expect(items.length).toBe(2) + }) + + it('should change next/previous keymap', async () => { + helper.updateConfiguration('list.nextKeymap', '') + helper.updateConfiguration('list.previousKeymap', '') + await manager.start(['location']) + await manager.session.ui.ready + await helper.wait(100) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + let line = await nvim.line + expect(line).toMatch('Bar') + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + line = await nvim.line + expect(line).toMatch('foo') + }) + + it('should respect mouse events', async () => { + async function setMouseEvent(line: number): Promise { + let winid = manager.session?.ui.winid + await nvim.command(`let v:mouse_winid = ${winid}`) + await nvim.command(`let v:mouse_lnum = ${line}`) + await nvim.command(`let v:mouse_col = 1`) + } + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await helper.wait(100) + await setMouseEvent(1) + await manager.onNormalInput('') + await setMouseEvent(2) + await manager.onNormalInput('') + await setMouseEvent(3) + await manager.onNormalInput('') + await helper.wait(100) + let items = await manager.session?.ui.getItems() + expect(items.length).toBe(3) + }) + + it('should toggle preview', async () => { + await manager.start(['--normal', '--auto-preview', 'location']) + await manager.session.ui.ready + await helper.wait(100) + await manager.togglePreview() + await helper.wait(100) + await manager.togglePreview() + await helper.wait(100) + let has = await nvim.call('coc#list#has_preview') + expect(has).toBeGreaterThan(0) + }) + + it('should show help of current list', async () => { + await manager.start(['--normal', '--auto-preview', 'location']) + await helper.wait(200) + await manager.session?.showHelp() + let bufname = await nvim.call('bufname', '%') + expect(bufname).toBe('[LIST HELP]') + }) + + it('should resolve list item', async () => { + let list: IList = { + name: 'test', + actions: [{ + name: 'open', execute: _item => { + // noop + } + }], + defaultAction: 'open', + loadItems: () => Promise.resolve([{ label: 'foo' }, { label: 'bar' }]), + resolveItem: item => { + item.label = item.label.slice(0, 1) + return Promise.resolve(item) + } + } + let disposable = manager.registerList(list) + await manager.start(['--normal', 'test']) + await manager.session.ui.ready + await helper.wait(50) + let line = await nvim.line + expect(line).toBe('f') + disposable.dispose() + }) + }) + + describe('descriptions', () => { + it('should get descriptions', async () => { + let res = manager.descriptions + expect(res).toBeDefined() + expect(res.location).toBeDefined() + }) + }) + + describe('loadItems()', () => { + it('should load items for list', async () => { + let res = await manager.loadItems('location') + expect(res.length).toBeGreaterThan(0) + ; (manager as any).lastSession = undefined + manager.toggleMode() + manager.stop() + }) + }) + + describe('onInsertInput()', () => { + it('should handle insert input', async () => { + await manager.onInsertInput('k') + await manager.onInsertInput('') + await manager.start(['--number-select', 'location']) + await manager.session.ui.ready + await manager.onInsertInput('1') + await helper.wait(300) + let bufname = await nvim.call('expand', ['%:p']) + expect(bufname).toMatch('manager.test.ts') + }) + + it('should ignore invalid input', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await manager.onInsertInput('') + await manager.onInsertInput(String.fromCharCode(65533)) + await manager.onInsertInput(String.fromCharCode(30)) + expect(manager.isActivated).toBe(true) + }) + + it('should ignore insert', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\x", "in")') + await helper.wait(50) + expect(manager.isActivated).toBe(true) + }) + }) + + describe('parseArgs()', () => { + it('should show error for bad option', async () => { + manager.parseArgs(['$x', 'location']) + let msg = await helper.getCmdline() + expect(msg).toMatch('Invalid list option') + }) + + it('should show error for option not exists', async () => { + manager.parseArgs(['-xyz', 'location']) + let msg = await helper.getCmdline() + expect(msg).toMatch('Invalid option') + }) + + it('should show error for interactive with list not support interactive', async () => { + manager.parseArgs(['--interactive', 'location']) + let msg = await helper.getCmdline() + expect(msg).toMatch('not supported') + }) + }) + + describe('resume()', () => { + it('should resume by name', async () => { + await events.fire('FocusGained', []) + await manager.start(['location']) + await manager.session.ui.ready + await helper.wait(50) + await manager.session.hide() + await helper.wait(100) + await manager.resume('location') + expect(manager.isActivated).toBe(true) + }) + }) + + describe('start()', () => { + it('should show error when loadItems throws', async () => { + let list: IList = { + name: 'test', + actions: [{ + name: 'open', + execute: (_item: ListItem) => { + } + }], + defaultAction: 'open', + loadItems: () => { + throw new Error('test error') + } + } + manager.registerList(list) + await manager.start(['test']) + await helper.wait(50) + let msg = await helper.getCmdline() + expect(msg).toMatch('test error') + }) + }) + + describe('first(), last()', () => { + it('should get session by name', async () => { + let last: string + let list: IList = { + name: 'test', + actions: [{ + name: 'open', + execute: (item: ListItem) => { + last = item.label + } + }], + defaultAction: 'open', + loadItems: () => Promise.resolve([{ label: 'foo' }, { label: 'bar' }]) + } + manager.registerList(list) + await manager.start(['test']) + await manager.session.ui.ready + await manager.first('a') + await manager.last('a') + await manager.first('test') + expect(last).toBe('foo') + await manager.last('test') + expect(last).toBe('bar') + }) + }) + + describe('registerList()', () => { + it('should recreat list', async () => { + let list: IList = { + name: 'test', + actions: [{ + name: 'open', execute: _item => { + // noop + } + }], + defaultAction: 'open', + loadItems: () => Promise.resolve([{ label: 'foo' }, { label: 'bar' }]) + } + manager.registerList(list) + helper.updateConfiguration('list.source.test.defaultAction', 'open') + let disposable = manager.registerList(list) + disposable.dispose() + await helper.wait(30) + let msg = await helper.getCmdline() + expect(msg).toMatch('recreated') + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/mappings.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/mappings.test.ts new file mode 100644 index 00000000..3cce87c3 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/mappings.test.ts @@ -0,0 +1,903 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationToken } from 'vscode-jsonrpc' +import BasicList from '../../list/basic' +import manager from '../../list/manager' +import window from '../../window' +import { ListContext, IList, ListItem, QuickfixItem } from '../../types' +import helper from '../helper' + +class TestList extends BasicList { + public name = 'test' + public timeout = 3000 + public text = 'test' + public detail = 'detail' + public loadItems(_context: ListContext, token: CancellationToken): Promise { + return new Promise(resolve => { + let timer = setTimeout(() => { + resolve([{ label: this.text }]) + }, this.timeout) + token.onCancellationRequested(() => { + if (timer) { + clearTimeout(timer) + resolve([]) + } + }) + }) + } +} + +let nvim: Neovim +const locations: ReadonlyArray = [{ + filename: __filename, + col: 2, + lnum: 1, + text: 'foo' +}, { + filename: __filename, + col: 1, + lnum: 2, + text: 'Bar' +}, { + filename: __filename, + col: 1, + lnum: 3, + text: 'option' +}] + +const lineList: IList = { + name: 'lines', + actions: [{ + name: 'open', + execute: async item => { + await window.moveTo({ + line: (item as ListItem).data.line, + character: 0 + }) + // noop + } + }], + defaultAction: 'open', + async loadItems(_context, _token): Promise { + let lines = [] + for (let i = 0; i < 100; i++) { + lines.push(i.toString()) + } + return lines.map((line, idx) => ({ + label: line, + data: { line: idx } + })) + } +} + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + await nvim.setVar('coc_jump_locations', locations) +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + manager.reset() + await helper.reset() +}) + +describe('list normal mappings', () => { + it('should tabopen by t', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(100) + let nr = await nvim.call('tabpagenr') + expect(nr).toBe(2) + }) + + it('should open by ', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + let bufname = await nvim.call('expand', ['%:p']) + expect(bufname).toMatch('mappings.test.ts') + }) + + it('should stop by ', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(50) + let loading = manager.session?.worker.isLoading + expect(loading).toBe(false) + }) + + it('should jump back by ', async () => { + let doc = await helper.createDocument() + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(50) + let bufnr = await nvim.call('bufnr', ['%']) + expect(bufnr).toBe(doc.bufnr) + }) + + it('should scroll preview window by , ', async () => { + await helper.createDocument() + await manager.start(['--auto-preview', '--normal', 'location']) + await manager.session.ui.ready + await helper.wait(100) + let winnr = await nvim.call('coc#list#has_preview') as number + expect(winnr).toBeGreaterThan(0) + let winid = await nvim.call('win_getid', [winnr]) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(50) + let res = await nvim.call('getwininfo', [winid]) + expect(res[0].topline).toBeGreaterThan(1) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(50) + res = await nvim.call('getwininfo', [winid]) + expect(res[0].topline).toBeLessThan(7) + }) + + it('should insert command by :', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys(":", "in")') + await helper.wait(50) + await nvim.eval('feedkeys("let g:x = 1\\", "in")') + await helper.wait(50) + let res = await nvim.getVar('x') + expect(res).toBe(1) + }) + + it('should select action by ', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + await nvim.input('t') + await helper.wait(300) + let nr = await nvim.call('tabpagenr') + expect(nr).toBe(2) + }) + + it('should preview by p', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await helper.wait(50) + await nvim.eval('feedkeys("p", "in")') + await helper.wait(200) + let winnr = await nvim.call('coc#list#has_preview') + expect(winnr).toBe(2) + }) + + it('should stop task by ', async () => { + let disposable = manager.registerList(new TestList(nvim)) + let p = manager.start(['--normal', 'test']) + await helper.wait(200) + await nvim.input('') + await helper.wait(200) + await p + let len = manager.session?.ui.length + expect(len).toBe(0) + disposable.dispose() + }) + + it('should cancel list by ', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(200) + expect(manager.isActivated).toBe(false) + }) + + it('should reload list by ', async () => { + let list = new TestList(nvim) + list.timeout = 0 + let disposable = manager.registerList(list) + await manager.start(['--normal', 'test']) + await manager.session.ui.ready + list.text = 'new' + await nvim.input('') + await helper.wait(30) + let line = await nvim.line + expect(line).toMatch('new') + disposable.dispose() + }) + + it('should select all items by ', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.input('') + await helper.wait(30) + let selected = manager.session?.ui.selectedItems + expect(selected.length).toBe(locations.length) + }) + + it('should toggle selection ', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + let selected = manager.session?.ui.selectedItems + expect(selected.length).toBe(1) + await nvim.eval('feedkeys("k", "in")') + await helper.wait(100) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + selected = manager.session?.ui.selectedItems + expect(selected.length).toBe(0) + }) + + it('should change to insert mode by i, o, a', async () => { + let keys = ['i', 'I', 'o', 'O', 'a', 'A'] + for (let key of keys) { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await helper.wait(50) + await nvim.eval(`feedkeys("${key}", "in")`) + await helper.wait(100) + let mode = manager.prompt.mode + expect(mode).toBe('insert') + } + }) + + it('should show help by ?', async () => { + await manager.start(['--normal', 'location']) + await helper.wait(30) + await nvim.eval('feedkeys("?", "in")') + await helper.wait(30) + await nvim.input('') + await helper.wait(100) + let bufname = await nvim.call('bufname', '%') + expect(bufname).toBe('[LIST HELP]') + }) + + it('should drop by d', async () => { + await manager.start(['--normal', 'location']) + await helper.wait(30) + await nvim.eval('feedkeys("d", "in")') + await helper.wait(100) + let nr = await nvim.call('tabpagenr') + expect(nr).toBe(1) + }) + + it('should split by s', async () => { + await manager.start(['--normal', 'location']) + await helper.wait(30) + await nvim.eval('feedkeys("s", "in")') + await helper.wait(100) + let nr = await nvim.call('winnr') + expect(nr).toBe(1) + }) +}) + +describe('list insert mappings', () => { + it('should open by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + let bufname = await nvim.call('expand', ['%:p']) + expect(bufname).toMatch('mappings.test.ts') + }) + + it('should paste input by ', async () => { + await nvim.call('setreg', ['*', 'foo']) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + let input = manager.prompt.input + expect(input).toBe('foo') + }) + + it('should insert register content by ', async () => { + await nvim.call('setreg', ['*', 'foo']) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("*", "in")') + await helper.wait(100) + let input = manager.prompt.input + expect(input).toBe('foo') + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("<", "in")') + await helper.wait(100) + input = manager.prompt.input + expect(input).toBe('foo') + manager.prompt.reset() + }) + + it('should cancel by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + expect(manager.isActivated).toBe(false) + }) + + it('should select action by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await helper.wait(100) + nvim.call('eval', 'feedkeys("\\", "in")', true) + await helper.wait(100) + await nvim.input('t') + await helper.wait(500) + let pages = await nvim.tabpages + expect(pages.length).toBe(2) + }) + + it('should select action for visual selected items', async () => { + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await helper.wait(100) + await nvim.input('V') + await helper.wait(30) + await nvim.input('2') + await helper.wait(30) + await nvim.input('j') + await helper.wait(30) + await manager.doAction('tabe') + let nr = await nvim.call('tabpagenr') + expect(nr).toBeGreaterThan(3) + }) + + it('should stop loading by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + + it('should reload by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + + it('should change to normal mode by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + expect(manager.isActivated).toBe(true) + let line = await helper.getCmdline() + expect(line).toBe('') + }) + + it('should select line by and ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(50) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(50) + expect(manager.isActivated).toBe(true) + let line = await nvim.line + expect(line).toMatch('foo') + }) + + it('should move cursor by and ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("f", "in")') + await helper.wait(10) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(10) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(10) + await nvim.eval('feedkeys("a", "in")') + await helper.wait(10) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(10) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(10) + await nvim.eval('feedkeys("c", "in")') + await helper.wait(10) + let input = manager.prompt.input + expect(input).toBe('afc') + }) + + it('should move cursor by and ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("\\a", "in")') + await helper.wait(30) + let input = manager.prompt.input + expect(input).toBe('a') + }) + + it('should move cursor by ', async () => { + let disposable = manager.registerList(lineList) + await manager.start(['lines']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + let line = await nvim.eval('line(".")') + expect(line).toBeGreaterThan(1) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + disposable.dispose() + }) + + it('should scroll window by and ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await helper.wait(30) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + }) + + it('should change input by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("f", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + let input = manager.prompt.input + expect(input).toBe('') + }) + + it('should change input by ', async () => { + let revert = helper.updateConfiguration('list.insertMappings', { + '': 'prompt:removetail', + }) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("foo", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + let input = manager.prompt.input + revert() + expect(input).toBe('') + }) + + it('should change input by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("f", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + let input = manager.prompt.input + expect(input).toBe('') + }) + + it('should change input by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("f", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("a", "in")') + await helper.wait(30) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + let input = manager.prompt.input + expect(input).toBe('') + }) + + it('should change input by ', async () => { + await manager.start(['--input=a', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + let input = manager.prompt.input + expect(input).toBe('') + }) + + it('should change input by and ', async () => { + async function session(input: string): Promise { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("${input}", "in")`) + await helper.wait(100) + await manager.cancel() + } + await session('foo') + await session('bar') + await manager.start(['location']) + await manager.session.ui.ready + await helper.wait(50) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + let input = manager.prompt.input + expect(input.length).toBeGreaterThan(0) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + input = manager.prompt.input + expect(input.length).toBeGreaterThan(0) + }) + + it('should change matcher by ', async () => { + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(10) + let matcher = manager.session?.listOptions.matcher + expect(matcher).toBe('strict') + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(10) + matcher = manager.session?.listOptions.matcher + expect(matcher).toBe('regex') + await nvim.eval('feedkeys("f", "in")') + await helper.wait(30) + let len = manager.session?.ui.length + expect(len).toBeGreaterThan(0) + }) +}) + +describe('evalExpression', () => { + it('should throw for bad expression', async () => { + let revert = helper.updateConfiguration('list.normalMappings', { + t: 'expr', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(30) + revert() + let msg = await helper.getCmdline() + expect(msg).toMatch('Invalid list mapping expression') + }) + + it('should show help', async () => { + helper.updateConfiguration('list.normalMappings', { + t: 'do:help', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(50) + let bufname = await nvim.call('bufname', ['%']) + expect(bufname).toMatch('[LIST HELP]') + }) + + it('should exit list', async () => { + helper.updateConfiguration('list.normalMappings', { + t: 'do:exit', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(50) + expect(manager.isActivated).toBe(false) + }) + + it('should cancel prompt', async () => { + helper.updateConfiguration('list.normalMappings', { + t: 'do:cancel', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(50) + let res = await nvim.call('coc#prompt#activated') + expect(res).toBe(0) + }) + + it('should jump back', async () => { + let doc = await helper.createDocument() + helper.updateConfiguration('list.normalMappings', { + t: 'do:jumpback', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(50) + let bufnr = await nvim.call('bufnr', ['%']) + expect(bufnr).toBe(doc.bufnr) + }) + + it('should invoke normal command', async () => { + let revert = helper.updateConfiguration('list.normalMappings', { + x: 'normal!:G' + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("x", "in")`) + await helper.wait(50) + revert() + let lnum = await nvim.call('line', ['.']) + expect(lnum).toBeGreaterThan(1) + }) + + it('should toggle, scroll preview', async () => { + let revert = helper.updateConfiguration('list.normalMappings', { + '': 'do:toggle', + a: 'do:toggle', + b: 'do:previewtoggle', + c: 'do:previewup', + d: 'do:previewdown', + e: 'prompt:insertregister', + f: 'do:stop', + g: 'do:togglemode', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys(" ", "in")`) + await helper.wait(50) + for (let key of ['a', 'b', 'c', 'd', 'e', 'f', 'g']) { + await nvim.eval(`feedkeys("${key}", "in")`) + await helper.wait(50) + } + revert() + expect(manager.isActivated).toBe(true) + }) + + it('should show error when action not exists', async () => { + helper.updateConfiguration('list.normalMappings', { + t: 'do:invalid', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(50) + let cmd = await helper.getCmdline() + expect(cmd).toMatch('not supported') + }) + + it('should show error when prompt action not exists', async () => { + helper.updateConfiguration('list.normalMappings', { + t: 'prompt:invalid', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(50) + let cmd = await helper.getCmdline() + expect(cmd).toMatch('not supported') + }) + + it('should show error for invalid expression ', async () => { + helper.updateConfiguration('list.normalMappings', { + t: 'x:y', + }) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("t", "in")') + await helper.wait(50) + let cmd = await helper.getCmdline() + expect(cmd).toMatch('Invalid expression') + }) +}) + +describe('User mappings', () => { + it('should show warning for invalid key', async () => { + let revert = helper.updateConfiguration('list.insertMappings', { + xy: 'action:tabe', + }) + await helper.wait(30) + let msg = await helper.getCmdline() + revert() + await nvim.command('echo ""') + expect(msg).toMatch('Invalid list mappings key') + revert = helper.updateConfiguration('list.insertMappings', { + '': 'action:tabe', + }) + await helper.wait(30) + msg = await helper.getCmdline() + revert() + expect(msg).toMatch('Invalid list mappings key') + }) + + it('should execute action keymap', async () => { + await helper.wait(200) + let revert = helper.updateConfiguration('list.insertMappings', { + '': 'action:tabe', + }) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(200) + let nr = await nvim.call('tabpagenr') + expect(nr).toBe(2) + revert() + }) + + it('should execute expr keymap', async () => { + await helper.mockFunction('TabOpen', 'tabe') + helper.updateConfiguration('list.insertMappings', { + '': 'expr:TabOpen', + }) + helper.updateConfiguration('list.normalMappings', { + t: 'expr:TabOpen', + }) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(100) + let nr = await nvim.call('tabpagenr') + expect(nr).toBe(2) + await manager.start(['--normal', 'location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("t", "in")`) + await helper.wait(100) + nr = await nvim.call('tabpagenr') + expect(nr).toBe(3) + }) + + it('should execute do mappings', async () => { + helper.updateConfiguration('list.previousKeymap', '') + helper.updateConfiguration('list.nextKeymap', '') + helper.updateConfiguration('list.insertMappings', { + '': 'do:refresh', + '': 'do:selectall', + '': 'do:switch', + '': 'do:cancel', + '': 'do:toggle', + '': 'do:next', + '': 'do:previous', + '': 'do:defaultaction', + '': 'do:help', + '': 'do:exit', + '': 'do:toggleMode' + }) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + expect(manager.isActivated).toBe(true) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + expect(manager.session?.ui.selectedItems.length).toBe(locations.length) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + expect(manager.session?.listOptions.matcher).toBe('strict') + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + let item = await manager.session?.ui.item + expect(item.label).toMatch(locations[1].text) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + item = await manager.session?.ui.item + expect(item.label).toMatch(locations[0].text) + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(30) + expect(manager.isActivated).toBe(false) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(50) + let res = await nvim.call('coc#prompt#activated') + expect(res).toBe(0) + await manager.session.hide() + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("?", "in")') + await helper.wait(30) + await nvim.input('') + await manager.cancel() + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + expect(manager.isActivated).toBe(false) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(100) + expect(manager.isActivated).toBe(true) + await nvim.call('coc#prompt#stop_prompt', ['list']) + }, 20000) + + it('should execute prompt mappings', async () => { + helper.updateConfiguration('list.insertMappings', { + '': 'prompt:previous', + '': 'prompt:next', + '': 'prompt:start', + '': 'prompt:end', + '': 'prompt:left', + '': 'prompt:right', + '': 'prompt:deleteforward', + '': 'prompt:deletebackward', + '': 'prompt:removetail', + '': 'prompt:removeahead', + }) + await manager.start(['location']) + await manager.session.ui.ready + for (let key of ['', '', '', '', '', '', '', '', '', '']) { + await nvim.input(key) + await helper.wait(30) + } + expect(manager.isActivated).toBe(true) + }) + + it('should execute feedkeys keymap', async () => { + helper.updateConfiguration('list.insertMappings', { + '': 'feedkeys:\\', + }) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(30) + let line = await nvim.call('line', '.') + expect(line).toBe(locations.length) + }) + + it('should execute normal keymap', async () => { + helper.updateConfiguration('list.insertMappings', { + '': 'normal:G', + }) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(30) + let line = await nvim.call('line', '.') + expect(line).toBe(locations.length) + }) + + it('should execute command keymap', async () => { + helper.updateConfiguration('list.insertMappings', { + '': 'command:wincmd p', + }) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(30) + expect(manager.isActivated).toBe(true) + let winnr = await nvim.call('winnr') + expect(winnr).toBe(1) + }) + + it('should execute call keymap', async () => { + await helper.mockFunction('Test', 1) + helper.updateConfiguration('list.insertMappings', { + '': 'call:Test', + }) + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(30) + expect(manager.isActivated).toBe(true) + }) + + it('should insert clipboard register to prompt', async () => { + helper.updateConfiguration('list.insertMappings', { + '': 'prompt:paste', + }) + await nvim.command('let @* = "foobar"') + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(100) + let { input } = manager.prompt + expect(input).toMatch('foobar') + await nvim.command('let @* = ""') + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(100) + expect(manager.prompt.input).toMatch('foobar') + }) + + it('should insert text from default register to prompt', async () => { + helper.updateConfiguration('list.insertMappings', { + '': 'eval:@@', + }) + await nvim.command('let @@ = "bar"') + await manager.start(['location']) + await manager.session.ui.ready + await nvim.eval(`feedkeys("\\", "in")`) + await helper.wait(200) + let { input } = manager.prompt + expect(input).toMatch('bar') + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/session.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/session.test.ts new file mode 100644 index 00000000..5d4c3ef1 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/session.test.ts @@ -0,0 +1,246 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import BasicList from '../../list/basic' +import manager from '../../list/manager' +import ListSession from '../../list/session' +import { ListItem } from '../../types' +import { disposeAll } from '../../util' +import helper from '../helper' + +let labels: string[] = [] +let lastItem: string +let lastItems: ListItem[] + +class SimpleList extends BasicList { + public name = 'simple' + public detail = 'detail' + public options = [{ + name: 'foo', + description: 'foo' + }] + constructor(nvim: Neovim) { + super(nvim) + this.addAction('open', item => { + lastItem = item.label + }) + this.addMultipleAction('multiple', items => { + lastItems = items + }) + this.addAction('parallel', async () => { + await helper.wait(100) + }, { parallel: true }) + this.addAction('reload', item => { + lastItem = item.label + }, { persist: true, reload: true }) + } + public loadItems(): Promise { + return Promise.resolve(labels.map(s => { + return { label: s } as ListItem + })) + } +} + +let nvim: Neovim +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + disposeAll(disposables) + manager.reset() + await helper.reset() +}) + +describe('list session', () => { + describe('doDefaultAction()', () => { + it('should throw error when default action not exists', async () => { + labels = ['a', 'b', 'c'] + let list = new SimpleList(nvim) + list.defaultAction = 'foo' + disposables.push(manager.registerList(list)) + await manager.start(['--normal', 'simple']) + let ui = manager.session.ui + await ui.ready + let err + try { + await manager.session.first() + } catch (e) { + err = e + } + expect(err).toBeDefined() + err = null + try { + await manager.session.last() + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + }) + + describe('doItemAction()', () => { + it('should invoke multiple action', async () => { + labels = ['a', 'b', 'c'] + let list = new SimpleList(nvim) + disposables.push(manager.registerList(list)) + await manager.start(['--normal', 'simple']) + let ui = manager.session.ui + await ui.ready + await ui.selectAll() + await manager.doAction('multiple') + expect(lastItems.length).toBe(3) + lastItems = undefined + }) + + it('should invoke parallel action', async () => { + labels = ['a', 'b', 'c'] + let list = new SimpleList(nvim) + disposables.push(manager.registerList(list)) + await manager.start(['--normal', 'simple']) + let ui = manager.session.ui + await ui.ready + await ui.selectAll() + let d = Date.now() + await manager.doAction('parallel') + expect(Date.now() - d).toBeLessThan(300) + }) + + it('should invoke reload action', async () => { + labels = ['a', 'b', 'c'] + let list = new SimpleList(nvim) + disposables.push(manager.registerList(list)) + await manager.start(['--normal', 'simple']) + let ui = manager.session.ui + await ui.ready + labels = ['d', 'e'] + await manager.doAction('reload') + await helper.wait(50) + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual(['d', 'e']) + }) + }) + + describe('resume()', () => { + it('should do preview on resume', async () => { + labels = ['a', 'b', 'c'] + let lastItem + let list = new SimpleList(nvim) + list.actions.push({ + name: 'preview', + execute: item => { + lastItem = item + } + }) + disposables.push(manager.registerList(list)) + await manager.start(['--normal', '--auto-preview', 'simple']) + let ui = manager.session.ui + await ui.ready + await ui.selectLines(1, 2) + await helper.wait(50) + await nvim.call('coc#window#close', [ui.winid]) + await helper.wait(100) + await manager.session.resume() + await helper.wait(100) + expect(lastItem).toBeDefined() + }) + }) + + describe('jumpBack()', () => { + it('should jump back', async () => { + let win = await nvim.window + labels = ['a', 'b', 'c'] + let list = new SimpleList(nvim) + disposables.push(manager.registerList(list)) + await manager.start(['--normal', 'simple']) + let ui = manager.session.ui + await ui.ready + manager.session.jumpBack() + await helper.wait(50) + let winid = await nvim.call('win_getid') + expect(winid).toBe(win.id) + }) + }) + + describe('doNumberSelect()', () => { + async function create(len: number): Promise { + labels = [] + for (let i = 0; i < len; i++) { + let code = 'a'.charCodeAt(0) + i + labels.push(String.fromCharCode(code)) + } + let list = new SimpleList(nvim) + disposables.push(manager.registerList(list)) + await manager.start(['--normal', '--number-select', 'simple']) + let ui = manager.session.ui + await ui.ready + return manager.session + } + + it('should return false for invalid number', async () => { + let session = await create(5) + let res = await session.doNumberSelect('a') + expect(res).toBe(false) + res = await session.doNumberSelect('8') + expect(res).toBe(false) + }) + + it('should consider 0 as 10', async () => { + let session = await create(15) + let res = await session.doNumberSelect('0') + expect(res).toBe(true) + expect(lastItem).toBe('j') + }) + }) +}) + +describe('showHelp()', () => { + it('should show description and options in help', async () => { + labels = ['a', 'b', 'c'] + let list = new SimpleList(nvim) + disposables.push(manager.registerList(list)) + await manager.start(['--normal', 'simple']) + let ui = manager.session.ui + await ui.ready + await manager.session.showHelp() + let lines = await nvim.call('getline', [1, '$']) + expect(lines.indexOf('DESCRIPTION')).toBeGreaterThan(0) + expect(lines.indexOf('ARGUMENTS')).toBeGreaterThan(0) + }) +}) + +describe('chooseAction()', () => { + it('should filter actions not have shortcuts', async () => { + labels = ['a', 'b', 'c'] + let list = new SimpleList(nvim) + list.actions.push({ + name: 'a', + execute: () => { + } + }) + list.actions.push({ + name: 'b', + execute: () => { + } + }) + list.actions.push({ + name: 'ab', + execute: () => { + } + }) + disposables.push(manager.registerList(list)) + await manager.start(['--normal', 'simple']) + let ui = manager.session.ui + await ui.ready + let p = manager.session.chooseAction() + await helper.wait(100) + await nvim.input('a') + await p + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/sources.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/sources.test.ts new file mode 100644 index 00000000..5ba84333 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/sources.test.ts @@ -0,0 +1,203 @@ +import { Neovim } from '@chemzqm/neovim' +import { ListContext, ListItem, ListArgument } from '../../types' +import manager from '../../list/manager' +import languages from '../../languages' +import helper from '../helper' +import workspace from '../../workspace' +import { CancellationToken } from 'vscode-jsonrpc' +import { Location, Range } from 'vscode-languageserver-types' +import BasicList from '../../list/basic' + +let listItems: ListItem[] = [] +class OptionList extends BasicList { + public name = 'option' + public options: ListArgument[] = [{ + name: '-w, -word', + description: 'word' + }, { + name: '-i, -input INPUT', + hasValue: true, + description: 'input' + }] + constructor(nvim) { + super(nvim) + this.addLocationActions() + } + public loadItems(_context: ListContext, _token: CancellationToken): Promise { + return Promise.resolve(listItems) + } +} +jest.setTimeout(3000) + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + manager.dispose() + await helper.shutdown() +}) + +afterEach(async () => { + manager.reset() + await helper.reset() + await helper.wait(100) +}) + +describe('BasicList', () => { + describe('parse arguments', () => { + it('should parse args #1', () => { + let list = new OptionList(nvim) + let res = list.parseArguments(['-w']) + expect(res).toEqual({ word: true }) + }) + + it('should parse args #2', () => { + let list = new OptionList(nvim) + let res = list.parseArguments(['-word']) + expect(res).toEqual({ word: true }) + }) + + it('should parse args #3', () => { + let list = new OptionList(nvim) + let res = list.parseArguments(['-input', 'foo']) + expect(res).toEqual({ input: 'foo' }) + }) + }) + + describe('preview()', () => { + it('should preview sketch buffer', async () => { + await nvim.command('new') + await nvim.setLine('foo') + let buffer = await nvim.buffer + await helper.wait(30) + let doc = workspace.getDocument(buffer.id) + expect(doc.uri).toMatch('untitled') + let list = new OptionList(nvim) + listItems.push({ + label: 'foo', + location: Location.create(doc.uri, Range.create(0, 0, 0, 0)) + }) + let disposable = manager.registerList(list) + await manager.start(['option']) + await helper.wait(100) + await manager.doAction('preview') + await helper.wait(100) + await nvim.command('wincmd p') + let win = await nvim.window + let isPreview = await win.getVar('previewwindow') + expect(isPreview).toBe(1) + let line = await nvim.line + expect(line).toBe('foo') + disposable.dispose() + }) + }) +}) + +describe('list sources', () => { + + describe('commands', () => { + it('should load commands source', async () => { + await manager.start(['commands']) + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + + it('should do run action', async () => { + await manager.start(['commands']) + await helper.wait(100) + await manager.doAction() + }) + }) + + describe('diagnostics', () => { + it('should load diagnostics source', async () => { + await manager.start(['diagnostics']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + }) + + describe('extensions', () => { + it('should load extensions source', async () => { + await manager.start(['extensions']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + }) + + describe('folders', () => { + it('should load folders source', async () => { + await manager.start(['folders']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + }) + + describe('lists', () => { + it('should load lists source', async () => { + await manager.start(['lists']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + }) + + describe('outline', () => { + it('should load outline source', async () => { + await manager.start(['outline']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + }) + + describe('services', () => { + it('should load services source', async () => { + await manager.start(['services']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + }) + + describe('sources', () => { + it('should load sources source', async () => { + await manager.start(['sources']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + }) + }) + + describe('symbols', () => { + it('should load symbols source', async () => { + let disposable = languages.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols: () => [] + }) + await manager.start(['symbols']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + disposable.dispose() + }) + }) + + describe('links', () => { + it('should load links source', async () => { + let disposable = languages.registerDocumentLinkProvider([{ scheme: 'file' }, { scheme: 'untitled' }], { + provideDocumentLinks: () => [] + }) + await manager.start(['links']) + await manager.session?.ui.ready + await helper.wait(100) + expect(manager.isActivated).toBe(true) + disposable.dispose() + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/ui.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/ui.test.ts new file mode 100644 index 00000000..345f028f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/ui.test.ts @@ -0,0 +1,140 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import BasicList from '../../list/basic' +import events from '../../events' +import manager from '../../list/manager' +import { ListItem } from '../../types' +import { disposeAll } from '../../util' +import helper from '../helper' + +let labels: string[] = [] +let lastItem: string + +class SimpleList extends BasicList { + public name = 'simple' + constructor(nvim: Neovim) { + super(nvim) + this.addAction('open', item => { + lastItem = item.label + }) + } + public loadItems(): Promise { + return Promise.resolve(labels.map(s => { + return { label: s, ansiHighlights: [{ span: [0, 1], hlGroup: 'Search' }] } as ListItem + })) + } +} + +let nvim: Neovim +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + disposeAll(disposables) + manager.reset() + await helper.reset() +}) + +describe('list ui', () => { + describe('selectLines()', () => { + it('should select lines', async () => { + labels = ['foo', 'bar'] + disposables.push(manager.registerList(new SimpleList(nvim))) + await manager.start(['simple']) + let ui = manager.session.ui + await ui.ready + await ui.selectLines(3, 1) + let buf = await nvim.buffer + let res = await buf.getSigns({ group: 'coc-list' }) + expect(res.length).toBe(2) + }) + }) + + describe('resume()', () => { + it('should resume with selected lines', async () => { + labels = ['foo', 'bar'] + disposables.push(manager.registerList(new SimpleList(nvim))) + await manager.start(['simple']) + let ui = manager.session.ui + await ui.ready + await ui.selectLines(1, 2) + await nvim.call('coc#window#close', [ui.winid]) + await helper.wait(100) + await manager.session.resume() + await helper.wait(100) + let buf = await nvim.buffer + let res = await buf.getSigns({ group: 'coc-list' }) + expect(res.length).toBe(2) + }) + }) + + describe('events', () => { + async function mockMouse(winid: number, lnum: number): Promise { + await nvim.command(`let v:mouse_winid = ${winid}`) + await nvim.command(`let v:mouse_lnum = ${lnum}`) + await nvim.command('let v:mouse_col = 1') + } + + it('should fire action on double click', async () => { + labels = ['foo', 'bar'] + disposables.push(manager.registerList(new SimpleList(nvim))) + await manager.start(['simple']) + let ui = manager.session.ui + await ui.ready + await mockMouse(ui.winid, 1) + await manager.session.onMouseEvent('<2-LeftMouse>') + await helper.wait(100) + expect(lastItem).toBe('foo') + }) + + it('should select clicked line', async () => { + labels = ['foo', 'bar'] + disposables.push(manager.registerList(new SimpleList(nvim))) + await manager.start(['simple']) + let ui = manager.session.ui + await ui.ready + await mockMouse(ui.winid, 2) + await ui.onMouse('mouseDown') + await helper.wait(50) + await mockMouse(ui.winid, 2) + await ui.onMouse('mouseUp') + await helper.wait(50) + let item = await ui.item + expect(item.label).toBe('bar') + }) + + it('should jump to original window on click', async () => { + labels = ['foo', 'bar'] + let win = await nvim.window + disposables.push(manager.registerList(new SimpleList(nvim))) + await manager.start(['simple']) + let ui = manager.session.ui + await ui.ready + await mockMouse(win.id, 1) + await ui.onMouse('mouseUp') + await helper.wait(50) + let curr = await nvim.window + expect(curr.id).toBe(win.id) + }) + + it('should highlights items on CursorMoved', async () => { + labels = (new Array(400)).fill('a') + disposables.push(manager.registerList(new SimpleList(nvim))) + await manager.start(['simple', '--normal']) + let ui = manager.session.ui + await ui.ready + await nvim.call('cursor', [350, 1]) + await events.fire('CursorMoved', [ui.bufnr, [350, 1]]) + await helper.wait(300) + let res = await nvim.call('getmatches') + expect(res.length).toBeGreaterThan(300) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/list/worker.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/list/worker.test.ts new file mode 100644 index 00000000..bbcf9a75 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/list/worker.test.ts @@ -0,0 +1,204 @@ +import { Neovim } from '@chemzqm/neovim' +import manager from '../../list/manager' +import { parseInput } from '../../list/worker' +import helper from '../helper' +import { ListContext, ListTask, ListItem } from '../../types' +import { CancellationToken, Disposable } from 'vscode-languageserver-protocol' +import { EventEmitter } from 'events' +import colors from 'colors/safe' +import BasicList from '../../list/basic' +import { disposeAll } from '../../util' + +let items: ListItem[] = [] + +class DataList extends BasicList { + public name = 'data' + public loadItems(): Promise { + return Promise.resolve(items) + } +} + +class IntervalTaskList extends BasicList { + public name = 'task' + public timeout = 3000 + public loadItems(_context: ListContext, token: CancellationToken): Promise { + let emitter: any = new EventEmitter() + let i = 0 + let interval = setInterval(() => { + emitter.emit('data', { label: i.toFixed() }) + i++ + }, 50) + emitter.dispose = () => { + clearInterval(interval) + emitter.emit('end') + } + token.onCancellationRequested(() => { + emitter.dispose() + }) + return emitter + } +} + +class DelayTask extends BasicList { + public name = 'delay' + public interactive = true + public loadItems(_context: ListContext, token: CancellationToken): Promise { + let emitter: any = new EventEmitter() + let disposed = false + setTimeout(() => { + if (disposed) return + emitter.emit('data', { label: 'ahead' }) + }, 100) + setTimeout(() => { + if (disposed) return + emitter.emit('data', { label: 'abort' }) + }, 200) + emitter.dispose = () => { + disposed = true + emitter.emit('end') + } + token.onCancellationRequested(() => { + emitter.dispose() + }) + return emitter + } +} + +class InteractiveList extends BasicList { + public name = 'test' + public interactive = true + public loadItems(context: ListContext, _token: CancellationToken): Promise { + return Promise.resolve([{ + label: colors.magenta(context.input || '') + }]) + } +} + +class ErrorList extends BasicList { + public name = 'error' + public interactive = true + public loadItems(_context: ListContext, _token: CancellationToken): Promise { + return Promise.reject(new Error('test error')) + } +} + +class ErrorTaskList extends BasicList { + public name = 'task' + public loadItems(_context: ListContext, _token: CancellationToken): Promise { + let emitter: any = new EventEmitter() + let timeout = setTimeout(() => { + emitter.emit('error', new Error('task error')) + }, 100) + emitter.dispose = () => { + clearTimeout(timeout) + } + return emitter + } +} + +let nvim: Neovim +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + disposeAll(disposables) + manager.reset() + await helper.reset() +}) + +describe('parseInput', () => { + it('should parse input with space', async () => { + let res = parseInput('a b') + expect(res).toEqual(['a', 'b']) + }) + + it('should parse input with escaped space', async () => { + let res = parseInput('a\\ b') + expect(res).toEqual(['a b']) + }) +}) + +describe('list worker', () => { + + it('should work with long running task', async () => { + disposables.push(manager.registerList(new IntervalTaskList(nvim))) + await manager.start(['task']) + await helper.wait(300) + let len = manager.session?.length + expect(len > 2).toBe(true) + await manager.cancel() + }) + + it('should sort by sortText', async () => { + items = [{ + label: 'abc', + sortText: 'b' + }, { + label: 'ade', + sortText: 'a' + }] + disposables.push(manager.registerList(new DataList(nvim))) + await manager.start(['data']) + await helper.wait(100) + await nvim.input('a') + await helper.wait(100) + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual(['ade', 'abc']) + await manager.cancel() + }) + + it('should cancel task by use CancellationToken', async () => { + disposables.push(manager.registerList(new IntervalTaskList(nvim))) + await manager.start(['task']) + expect(manager.session?.worker.isLoading).toBe(true) + await helper.wait(100) + manager.session?.stop() + expect(manager.session?.worker.isLoading).toBe(false) + }) + + it('should render slow interactive list', async () => { + disposables.push(manager.registerList(new DelayTask(nvim))) + await manager.start(['delay']) + await nvim.input('a') + await helper.wait(600) + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual(['ahead', 'abort']) + }) + + it('should work with interactive list', async () => { + disposables.push(manager.registerList(new InteractiveList(nvim))) + await manager.start(['-I', 'test']) + await manager.session?.ui.ready + expect(manager.isActivated).toBe(true) + await nvim.eval('feedkeys("f", "in")') + await helper.wait(100) + await nvim.eval('feedkeys("a", "in")') + await helper.wait(100) + await nvim.eval('feedkeys("x", "in")') + await helper.wait(300) + let item = await manager.session?.ui.item + expect(item.label).toBe('fax') + }) + + it('should not activate on load error', async () => { + disposables.push(manager.registerList(new ErrorList(nvim))) + await manager.start(['test']) + expect(manager.isActivated).toBe(false) + }) + + it('should deactivate on task error', async () => { + disposables.push(manager.registerList(new ErrorTaskList(nvim))) + await manager.start(['task']) + await helper.wait(500) + expect(manager.isActivated).toBe(false) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/markdown/index.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/markdown/index.test.ts new file mode 100644 index 00000000..52653e28 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/markdown/index.test.ts @@ -0,0 +1,151 @@ +import { getHighlightItems, parseMarkdown, parseDocuments } from '../../markdown/index' + +describe('getHighlightItems', () => { + it('should get highlights in single line', async () => { + let res = getHighlightItems('this line has highlights', 0, [10, 15]) + expect(res).toEqual([{ + colStart: 10, + colEnd: 15, + lnum: 0, + hlGroup: 'CocUnderline' + }]) + }) + + it('should get highlights when active end extended', async () => { + let res = getHighlightItems('this line', 0, [5, 30]) + expect(res).toEqual([{ + colStart: 5, + colEnd: 9, + lnum: 0, + hlGroup: 'CocUnderline' + }]) + }) + + it('should get highlights across line', async () => { + let res = getHighlightItems('this line\nhas highlights', 0, [5, 15]) + expect(res).toEqual([{ + colStart: 5, colEnd: 9, lnum: 0, hlGroup: 'CocUnderline' + }, { + colStart: 0, colEnd: 5, lnum: 1, hlGroup: 'CocUnderline' + }]) + }) +}) + +describe('parseMarkdown', () => { + it('should parse code blocks', async () => { + let content = ` +\`\`\`js +var global = globalThis +\`\`\` +\`\`\`ts +let str:string +\`\`\` +` + let res = parseMarkdown(content, {}) + expect(res.lines).toEqual([ + 'var global = globalThis', + '', + 'let str:string' + ]) + expect(res.codes).toEqual([ + { filetype: 'javascript', startLine: 0, endLine: 1 }, + { filetype: 'typescript', startLine: 2, endLine: 3 } + ]) + }) + + it('should parse html code block', async () => { + let content = ` +example: +\`\`\`html +
    code
    +\`\`\` + ` + let res = parseMarkdown(content, {}) + expect(res.lines).toEqual(['example:', '', '
    code
    ']) + expect(res.codes).toEqual([{ filetype: 'html', startLine: 2, endLine: 3 }]) + }) + + it('should compose empty lines', async () => { + let content = 'foo\n\n\nbar\n\n\n' + let res = parseMarkdown(content, {}) + expect(res.lines).toEqual(['foo', '', 'bar']) + }) + + it('should parse ansi highlights', async () => { + let content = '__foo__\n[link](link)' + let res = parseMarkdown(content, {}) + expect(res.lines).toEqual(['foo', 'link']) + expect(res.highlights).toEqual([ + { hlGroup: 'CocBold', lnum: 0, colStart: 0, colEnd: 3 }, + { hlGroup: 'CocUnderline', lnum: 1, colStart: 0, colEnd: 4 } + ]) + }) + + it('should exclude images by option', async () => { + let content = 'head\n![img](img)\ncontent ![img](img) ![img](img)' + let res = parseMarkdown(content, { excludeImages: true }) + expect(res.lines).toEqual(['head', '', 'content']) + }) +}) + +describe('parseDocuments', () => { + it('should parse documents with diagnostic filetypes', async () => { + let docs = [{ + filetype: 'Error', + content: 'Error text' + }, { + filetype: 'Warning', + content: 'Warning text' + }] + let res = parseDocuments(docs) + expect(res.lines).toEqual([ + 'Error text', + '─', + 'Warning text' + ]) + expect(res.codes).toEqual([ + { hlGroup: 'CocErrorFloat', startLine: 0, endLine: 1 }, + { hlGroup: 'CocWarningFloat', startLine: 2, endLine: 3 } + ]) + }) + + it('should parse markdown document with filetype document', async () => { + let docs = [{ + filetype: 'typescript', + content: 'const workspace' + }, { + filetype: 'markdown', + content: '**header**' + }] + let res = parseDocuments(docs) + expect(res.lines).toEqual([ + 'const workspace', + '─', + 'header' + ]) + expect(res.highlights).toEqual([{ + hlGroup: 'CocBold', + lnum: 2, + colStart: 0, + colEnd: 6 + }]) + expect(res.codes).toEqual([ + { filetype: 'typescript', startLine: 0, endLine: 1 } + ]) + }) + + it('should parse documents with active highlights', async () => { + let docs = [{ + filetype: 'javascript', + content: 'func(foo, bar)', + active: [5, 8] + }, { + filetype: 'javascript', + content: 'func()', + active: [15, 20] + }] + let res = parseDocuments(docs as any) + expect(res.highlights).toEqual([{ colStart: 5, colEnd: 8, lnum: 0, hlGroup: 'CocUnderline' } + ]) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/markdown/renderer.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/markdown/renderer.test.ts new file mode 100644 index 00000000..95dbbffd --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/markdown/renderer.test.ts @@ -0,0 +1,119 @@ +import marked from 'marked' +import Renderer from '../../markdown/renderer' +import * as styles from '../../markdown/styles' +import { parseAnsiHighlights, AnsiResult } from '../../util/ansiparse' + +marked.setOptions({ + renderer: new Renderer() +}) + +function parse(text: string): AnsiResult { + let m = marked(text) + let res = parseAnsiHighlights(m.split(/\n/)[0], true) + return res +} + +describe('styles', () => { + it('should add styles', async () => { + let keys = ['gray', 'magenta', 'bold', 'underline', 'italic', 'strikethrough', 'yellow', 'green', 'blue'] + for (let key of keys) { + let res = styles[key]('text') + expect(res).toContain('text') + } + }) +}) + +describe('Renderer of marked', () => { + it('should create bold highlights', async () => { + let res = parse('**note**.') + expect(res.highlights[0]).toEqual({ + span: [0, 4], + hlGroup: 'CocBold' + }) + }) + + it('should create italic highlights', async () => { + let res = parse('_note_.') + expect(res.highlights[0]).toEqual({ + span: [0, 4], + hlGroup: 'CocItalic' + }) + }) + + it('should create underline highlights for link', async () => { + let res = parse('[baidu](https://baidu.com)') + expect(res.highlights[0]).toEqual({ + span: [0, 5], + hlGroup: 'CocMarkdownLink' + }) + res = parse('https://baidu.com') + expect(res.highlights[0]).toEqual({ + span: [0, 17], + hlGroup: 'CocUnderline' + }) + }) + + it('should parse link', async () => { + // let res = parse('https://doc.rust-lang.org/nightly/core/iter/traits/iterator/Iterator.t.html#map.v') + // console.log(JSON.stringify(res, null, 2)) + let link = 'https://doc.rust-lang.org/nightly/core/iter/traits/iterator/Iterator.t.html#map.v' + let parsed = marked(link) + let res = parseAnsiHighlights(parsed.split(/\n/)[0], true) + expect(res.line).toEqual(link) + expect(res.highlights.length).toBeGreaterThan(0) + expect(res.highlights[0].hlGroup).toBe('CocUnderline') + }) + + it('should create highlight for code span', async () => { + let res = parse('`let foo = "bar"`') + expect(res.highlights[0]).toEqual({ + span: [0, 15], + hlGroup: 'CocMarkdownCode' + }) + }) + + it('should create header highlights', async () => { + let res = parse('# header') + expect(res.highlights[0]).toEqual({ + span: [0, 8], + hlGroup: 'CocMarkdownHeader' + }) + res = parse('## header') + expect(res.highlights[0]).toEqual({ + span: [0, 9], + hlGroup: 'CocMarkdownHeader' + }) + res = parse('### header') + expect(res.highlights[0]).toEqual({ + span: [0, 10], + hlGroup: 'CocMarkdownHeader' + }) + }) + + it('should indent blockquote', async () => { + let res = parse('> header') + expect(res.line).toBe(' header') + }) + + it('should preserve code block', async () => { + let text = '``` js\nconsole.log("foo")\n```' + let m = marked(text) + expect(m.split('\n')).toEqual([ + '``` js', + 'console.log("foo")', + '```', + '' + ]) + }) + + it('should renderer table', async () => { + let text = ` +| Syntax | Description | +| ----------- | ----------- | +| Header | Title | +| Paragraph | Text | +` + let res = marked(text) + expect(res).toContain('Syntax') + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/memos.json b/vim-config/plugins/coc.nvim/src/__tests__/memos.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/memos.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/array.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/array.test.ts new file mode 100644 index 00000000..ad3f0c32 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/array.test.ts @@ -0,0 +1,35 @@ +import * as assert from 'assert' +import * as arrays from '../../util/array' + +describe('Arrays', () => { + + test('distinct', () => { + function compare(a: string): string { + return a + } + + assert.deepStrictEqual(arrays.distinct(['32', '4', '5'], compare), ['32', '4', '5']) + assert.deepStrictEqual(arrays.distinct(['32', '4', '5', '4'], compare), ['32', '4', '5']) + assert.deepStrictEqual(arrays.distinct(['32', 'constructor', '5', '1'], compare), ['32', 'constructor', '5', '1']) + assert.deepStrictEqual(arrays.distinct(['32', 'constructor', 'proto', 'proto', 'constructor'], compare), ['32', 'constructor', 'proto']) + assert.deepStrictEqual(arrays.distinct(['32', '4', '5', '32', '4', '5', '32', '4', '5', '5'], compare), ['32', '4', '5']) + }) + + test('tail', () => { + assert.strictEqual(arrays.tail([1, 2, 3]), 3) + }) + + test('lastIndex', () => { + let res = arrays.lastIndex([1, 2, 3], x => x < 3) + assert.strictEqual(res, 1) + }) + + test('flatMap', () => { + let objs: { [key: string]: number[] }[] = [{ x: [1, 2] }, { y: [3, 4] }, { z: [5, 6] }] + function values(item: { [key: string]: number[] }): number[] { + return Object.keys(item).reduce((p, c) => p.concat(item[c]), []) + } + let res = arrays.flatMap(objs, values) + assert.deepStrictEqual(res, [1, 2, 3, 4, 5, 6]) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/attach.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/attach.test.ts new file mode 100644 index 00000000..55f0d544 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/attach.test.ts @@ -0,0 +1,53 @@ +import { Neovim } from '@chemzqm/neovim' +import events from '../../events' +import helper from '../helper' + +function wait(ms: number): Promise { + return new Promise(resolve => { + setTimeout(() => { + resolve() + }, ms) + }) +} +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('attach', () => { + + it('should listen CocInstalled', async () => { + nvim.emit('notification', 'VimEnter') + await helper.wait(100) + }) + + it('should not throw on event handler error', async () => { + events.on('CursorHold', async () => { + throw new Error('error') + }) + let fn = jest.fn() + nvim.emit('request', 'CocAutocmd', ['CursorHold'], { + send: fn + }) + await wait(100) + expect(fn).toBeCalled() + }) + + it('should not throw when plugin method not found', async () => { + let fn = jest.fn() + nvim.emit('request', 'NotExists', [], { + send: fn + }) + await wait(100) + expect(fn).toBeCalled() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/chars.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/chars.test.ts new file mode 100644 index 00000000..df716001 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/chars.test.ts @@ -0,0 +1,78 @@ +import { Chars } from '../../model/chars' + +describe('chars keyword option', () => { + it('should match @', () => { + let chars = new Chars('@') + expect(chars.isKeywordChar('a')).toBe(true) + expect(chars.isKeywordChar('z')).toBe(true) + expect(chars.isKeywordChar('A')).toBe(true) + expect(chars.isKeywordChar('Z')).toBe(true) + }) + + it('should match letter range', () => { + let chars = new Chars('a-z') + expect(chars.isKeywordChar('a')).toBe(true) + expect(chars.isKeywordChar('A')).toBe(false) + }) + + it('should match code range', () => { + let chars = new Chars('48-57') + expect(chars.isKeywordChar('a')).toBe(false) + expect(chars.isKeywordChar('0')).toBe(true) + expect(chars.isKeywordChar('9')).toBe(true) + }) + + it('should match @-@', () => { + let chars = new Chars('@-@') + expect(chars.isKeywordChar('@')).toBe(true) + }) + + it('should match single code', () => { + let chars = new Chars('58') + expect(chars.isKeywordChar(':')).toBe(true) + }) + + it('should match single character', () => { + let chars = new Chars('_') + expect(chars.isKeywordChar('_')).toBe(true) + }) +}) + +describe('chars addKeyword', () => { + it('should add keyword', () => { + let chars = new Chars('_') + chars.addKeyword(':') + expect(chars.isKeywordChar(':')).toBe(true) + }) +}) + +describe('chars change keyword', () => { + it('should change keyword', () => { + let chars = new Chars('_') + chars.setKeywordOption(':') + expect(chars.isKeywordChar(':')).toBe(true) + expect(chars.isKeywordChar('_')).toBe(false) + }) +}) + +describe('chars match keywords', () => { + it('should match keywords', () => { + let chars = new Chars('@') + let res = chars.matchKeywords('foo bar') + expect(res).toEqual(['foo', 'bar']) + }) + + it('should consider unicode character as word', () => { + let chars = new Chars('@') + let res = chars.matchKeywords('blackкофе') + expect(res).toEqual(['blackкофе']) + }) +}) + +describe('chars isKeyword', () => { + it('should check isKeyword', () => { + let chars = new Chars('@') + expect(chars.isKeyword('foo')).toBe(true) + expect(chars.isKeyword('f@')).toBe(false) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/client.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/client.test.ts new file mode 100644 index 00000000..887f4f88 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/client.test.ts @@ -0,0 +1,35 @@ +import { Neovim } from '@chemzqm/neovim' +import helper from '../helper' + +let nvim: Neovim + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('node client pauseNotification', () => { + it('should work with notify & request', async () => { + nvim.pauseNotification() + nvim.call('setline', [1, 'foo'], true) + nvim.call('append', [1, ['bar']], true) + await nvim.resumeNotification(false, true) + await helper.wait(500) + let buffer = await nvim.buffer + let lines = await buffer.lines + expect(lines).toEqual(['foo', 'bar']) + nvim.pauseNotification() + nvim.call('eval', ['&buftype'], true) + nvim.call('bufnr', ['%'], true) + let res = await nvim.resumeNotification() + expect(res).toEqual([['', buffer.id], null]) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/completion.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/completion.test.ts new file mode 100644 index 00000000..5c307795 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/completion.test.ts @@ -0,0 +1,756 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-jsonrpc' +import { CompletionItem, InsertTextFormat, Position, Range, TextEdit, CompletionList } from 'vscode-languageserver-types' +import completion from '../../completion' +import languages from '../../languages' +import { CompletionItemProvider } from '../../provider' +import snippetManager from '../../snippets/manager' +import sources from '../../sources' +import { CompleteOption, CompleteResult, ISource, SourceType } from '../../types' +import { disposeAll } from '../../util' +import workspace from '../../workspace' +import helper from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +beforeEach(async () => { + disposables = [] + await helper.createDocument() + await nvim.call('feedkeys', [String.fromCharCode(27), 'in']) +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + disposeAll(disposables) + await helper.reset() +}) + +describe('completion events', () => { + + it('should load preferences', () => { + let minTriggerInputLength = completion.config.minTriggerInputLength + expect(minTriggerInputLength).toBe(1) + }) + + it('should reload preferences onChange', () => { + let { configurations } = workspace + configurations.updateUserConfig({ 'suggest.maxCompleteItemCount': 30 }) + let snippetIndicator = completion.config.maxItemCount + expect(snippetIndicator).toBe(30) + }) +}) + +describe('completion start', () => { + + it('should deactivate on doComplete error', async () => { + let fn = (completion as any)._doComplete + ; (completion as any)._doComplete = async () => { + throw new Error('fake') + } + let option: CompleteOption = await nvim.call('coc#util#get_complete_option') + await completion.startCompletion(option) + ; (completion as any)._doComplete = fn + expect(completion.isActivated).toBe(false) + }) + + it('should start completion', async () => { + await nvim.setLine('foo football') + await nvim.input('a') + await nvim.call('cursor', [1, 2]) + let option: CompleteOption = await nvim.call('coc#util#get_complete_option') + await completion.startCompletion(option) + expect(completion.isActivated).toBe(true) + }) + + it('should show slow source', async () => { + let source: ISource = { + priority: 0, + enable: true, + name: 'slow', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: (_opt: CompleteOption): Promise => new Promise(resolve => { + setTimeout(() => { + resolve({ items: [{ word: 'foo' }, { word: 'bar' }] }) + }, 600) + }) + } + disposables.push(sources.addSource(source)) + await helper.edit() + await nvim.input('i.') + await helper.waitPopup() + expect(completion.isActivated).toBe(true) + let items = await helper.items() + expect(items.length).toBe(2) + }) +}) + +describe('completion resumeCompletion', () => { + + it('should stop if no filtered items', async () => { + await nvim.setLine('foo ') + await helper.wait(50) + await nvim.input('Af') + await helper.waitPopup() + expect(completion.isActivated).toBe(true) + await nvim.input('d') + await helper.wait(60) + expect(completion.isActivated).toBe(false) + }) + + it('should deactivate without filtered items', async () => { + await nvim.setLine('foo fbi ') + await nvim.input('Af') + await helper.waitPopup() + await nvim.input('c') + await helper.wait(100) + let items = await helper.items() + expect(items.length).toBe(0) + expect(completion.isActivated).toBe(false) + }) + + it('should deactivate when insert space', async () => { + let source: ISource = { + priority: 0, + enable: true, + name: 'empty', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: (_opt: CompleteOption): Promise => new Promise(resolve => { + resolve({ items: [{ word: 'foo bar' }] }) + }) + } + sources.addSource(source) + await helper.edit() + await nvim.input('i.') + await helper.waitPopup() + expect(completion.isActivated).toBe(true) + sources.removeSource(source) + let items = await helper.items() + expect(items[0].word).toBe('foo bar') + await nvim.input(' ') + await helper.wait(60) + expect(completion.isActivated).toBe(false) + }) + + it('should use resume input to filter', async () => { + let source: ISource = { + priority: 0, + enable: true, + name: 'source', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: (): Promise => new Promise(resolve => { + setTimeout(() => { + resolve({ items: [{ word: 'foo' }, { word: 'bar' }] }) + }, 60) + }) + } + sources.addSource(source) + await helper.edit() + await nvim.input('i.') + await helper.wait(20) + await nvim.input('f') + await helper.waitPopup() + expect(completion.isActivated).toBe(true) + let items = await helper.items() + expect(items.length).toBe(1) + expect(items[0].word).toBe('foo') + sources.removeSource(source) + }) + + it('should filter slow source', async () => { + let source: ISource = { + priority: 0, + enable: true, + name: 'slow', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: (): Promise => new Promise(resolve => { + setTimeout(() => { + resolve({ items: [{ word: 'foo' }, { word: 'bar' }] }) + }, 600) + }) + } + disposables.push(sources.addSource(source)) + await helper.edit() + await nvim.input('i.') + await helper.wait(60) + await nvim.input('f') + await helper.waitPopup() + await nvim.input('o') + await helper.wait(100) + expect(completion.isActivated).toBe(true) + let items = await helper.items() + expect(items.length).toBe(1) + expect(items[0].word).toBe('foo') + }) + + it('should complete inComplete source', async () => { + let source: ISource = { + priority: 0, + enable: true, + name: 'inComplete', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: async (opt: CompleteOption): Promise => { + await helper.wait(30) + if (opt.input.length <= 1) { + return { isIncomplete: true, items: [{ word: 'foo' }, { word: opt.input }] } + } + return { isIncomplete: false, items: [{ word: 'foo' }, { word: opt.input }] } + } + } + disposables.push(sources.addSource(source)) + await helper.edit() + await nvim.input('i.') + await helper.waitPopup() + expect(completion.isActivated).toBe(true) + await nvim.input('a') + await helper.wait(30) + await nvim.input('b') + await helper.wait(100) + }) + + it('should not complete inComplete source when isIncomplete is false', async () => { + await helper.createDocument() + let lastOption: CompleteOption + let source: ISource = { + priority: 0, + enable: true, + name: 'inComplete', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: async (opt: CompleteOption): Promise => { + lastOption = opt + await helper.wait(30) + if (opt.input.length <= 1) { + return { isIncomplete: true, items: [{ word: 'foobar' }] } + } + return { isIncomplete: false, items: [{ word: 'foobar' }] } + } + } + disposables.push(sources.addSource(source)) + await helper.edit() + await nvim.input('i.') + await helper.waitPopup() + expect(completion.isActivated).toBe(true) + await nvim.input('fo') + await helper.wait(100) + await nvim.input('b') + await helper.wait(200) + expect(completion.isActivated).toBe(true) + }) +}) + +describe('completion InsertEnter', () => { + it('should trigger completion if triggerAfterInsertEnter is true', async () => { + await helper.createDocument() + await nvim.setLine('foo fo') + let config = workspace.getConfiguration('suggest') + config.update('triggerAfterInsertEnter', true) + await helper.wait(100) + let triggerAfterInsertEnter = completion.config.triggerAfterInsertEnter + expect(triggerAfterInsertEnter).toBe(true) + await nvim.input('A') + await helper.waitPopup() + expect(completion.isActivated).toBe(true) + config.update('triggerAfterInsertEnter', undefined) + }) + + it('should not trigger when input length too small', async () => { + let config = workspace.getConfiguration('suggest') + config.update('triggerAfterInsertEnter', true) + await helper.wait(100) + let triggerAfterInsertEnter = completion.config.triggerAfterInsertEnter + expect(triggerAfterInsertEnter).toBe(true) + await nvim.setLine('foo ') + await nvim.input('A') + await helper.wait(100) + expect(completion.isActivated).toBe(false) + config.update('triggerAfterInsertEnter', undefined) + }) +}) + +describe('completion TextChangedP', () => { + it('should stop when input length below option input length', async () => { + await helper.edit() + await nvim.setLine('foo fbi ') + await nvim.input('Af') + await helper.waitPopup() + await nvim.input('') + await helper.wait(100) + expect(completion.isActivated).toBe(false) + }) + + it('should fix cursor position with plain text on additionalTextEdits', async () => { + let provider: CompletionItemProvider = { + provideCompletionItems: async (): Promise => [{ + label: 'foo', + filterText: 'foo', + additionalTextEdits: [TextEdit.insert(Position.create(0, 0), 'a\nbar')] + }] + } + disposables.push(languages.registerCompletionItemProvider('edits', 'edit', null, provider)) + await nvim.input('if') + await helper.waitPopup() + await helper.selectCompleteItem(0) + await helper.wait(200) + let line = await nvim.line + expect(line).toBe('barfoo') + let [, lnum, col] = await nvim.call('getcurpos') + expect(lnum).toBe(2) + expect(col).toBe(7) + }) + + it('should filter in complete request', async () => { + let provider: CompletionItemProvider = { + provideCompletionItems: async (doc, pos, token, context): Promise => { + let option = (context as any).option + if (context.triggerCharacter == '.') { + return { + isIncomplete: true, + items: [ + { + label: 'foo' + }, { + label: 'bar' + } + ] + } + } + if (option.input == 'f') { + await helper.wait(100) + if (token.isCancellationRequested) return + return { + isIncomplete: true, + items: [ + { + label: 'foo' + } + ] + } + } + if (option.input == 'fo') { + await helper.wait(100) + if (token.isCancellationRequested) return + return { + isIncomplete: false, + items: [ + { + label: 'foo' + } + ] + } + } + } + } + disposables.push(languages.registerCompletionItemProvider('edits', 'edit', null, provider, ['.'])) + await nvim.input('i.') + await helper.waitPopup() + await nvim.input('f') + await helper.wait(60) + await nvim.input('o') + await helper.wait(300) + let res = await helper.getItems() + expect(res.length).toBe(1) + }) + + it('should provide word when textEdit after startcol', async () => { + // some LS would send textEdit after first character, + // need fix the word from newText + let provider: CompletionItemProvider = { + provideCompletionItems: async (_, position): Promise => { + if (position.line != 0) return null + return [{ + label: 'bar', + filterText: 'ar', + textEdit: { + range: Range.create(0, 1, 0, 1), + newText: 'ar' + } + }] + } + } + disposables.push(languages.registerCompletionItemProvider('edits', 'edit', null, provider)) + await nvim.input('ib') + await helper.waitPopup() + let context = await nvim.getVar('coc#_context') as any + expect(context.start).toBe(1) + expect(context.candidates[0].word).toBe('ar') + }) + + it('should adjust completion position by textEdit start position', async () => { + let provider: CompletionItemProvider = { + provideCompletionItems: async (_document, _position, _token, context): Promise => { + if (!context.triggerCharacter) return + return [{ + label: 'foo', + textEdit: { + range: Range.create(0, 0, 0, 1), + newText: '?foo' + } + }] + } + } + disposables.push(languages.registerCompletionItemProvider('fix', 'f', null, provider, ['?'])) + await nvim.input('i?') + await helper.waitPopup() + await nvim.eval('feedkeys("\\", "in")') + await helper.wait(200) + let line = await nvim.line + expect(line).toBe('?foo') + }) + + it('should fix cursor position with snippet on additionalTextEdits', async () => { + await helper.createDocument() + let provider: CompletionItemProvider = { + provideCompletionItems: async (): Promise => [{ + label: 'if', + insertTextFormat: InsertTextFormat.Snippet, + textEdit: { range: Range.create(0, 0, 0, 2), newText: 'if($1)' }, + additionalTextEdits: [TextEdit.insert(Position.create(0, 0), 'bar ')], + preselect: true + }] + } + disposables.push(languages.registerCompletionItemProvider('edits', 'edit', null, provider)) + await nvim.input('ii') + await helper.waitPopup() + let res = await helper.getItems() + let idx = res.findIndex(o => o.menu == '[edit]') + await helper.selectCompleteItem(idx) + await helper.wait(800) + let line = await nvim.line + expect(line).toBe('bar if()') + let [, lnum, col] = await nvim.call('getcurpos') + expect(lnum).toBe(1) + expect(col).toBe(8) + }) + + it('should fix cursor position with plain text snippet on additionalTextEdits', async () => { + let provider: CompletionItemProvider = { + provideCompletionItems: async (): Promise => [{ + label: 'if', + insertTextFormat: InsertTextFormat.Snippet, + textEdit: { range: Range.create(0, 0, 0, 2), newText: 'do$0' }, + additionalTextEdits: [TextEdit.insert(Position.create(0, 0), 'bar ')], + preselect: true + }] + } + disposables.push(languages.registerCompletionItemProvider('edits', 'edit', null, provider)) + await nvim.input('iif') + await helper.waitPopup() + await helper.selectCompleteItem(0) + await helper.wait(200) + let line = await nvim.line + let [, lnum, col] = await nvim.call('getcurpos') + expect(line).toBe('bar do') + expect(lnum).toBe(1) + expect(col).toBe(7) + }) + + it('should fix cursor position with nested snippet on additionalTextEdits', async () => { + await helper.createDocument() + let res = await snippetManager.insertSnippet('func($1)$0') + expect(res).toBe(true) + let provider: CompletionItemProvider = { + provideCompletionItems: async (): Promise => [{ + label: 'if', + insertTextFormat: InsertTextFormat.Snippet, + insertText: 'do$0', + additionalTextEdits: [TextEdit.insert(Position.create(0, 0), 'bar ')], + preselect: true + }] + } + disposables.push(languages.registerCompletionItemProvider('edits', 'edit', null, provider)) + await nvim.input('if') + await helper.waitPopup() + await helper.selectCompleteItem(0) + await helper.wait(200) + let line = await nvim.line + let [, lnum, col] = await nvim.call('getcurpos') + expect(line).toBe('bar func(do)') + expect(lnum).toBe(1) + expect(col).toBe(12) + }) + + it('should fix cursor position and keep placeholder with snippet on additionalTextEdits', async () => { + let doc = await helper.createDocument() + let text = 'foo0bar1' + await nvim.setLine(text) + let provider: CompletionItemProvider = { + provideCompletionItems: async (): Promise => [{ + label: 'var', + insertTextFormat: InsertTextFormat.Snippet, + textEdit: { range: Range.create(0, text.length + 1, 0, text.length + 1), newText: '${1:foo} = foo0bar1' }, + additionalTextEdits: [TextEdit.del(Range.create(0, 0, 0, text.length + 1))], + preselect: true + }] + } + disposables.push(languages.registerCompletionItemProvider('edits', 'edit', null, provider, ['.'])) + await nvim.input('A.') + await helper.waitPopup() + let res = await helper.getItems() + let idx = res.findIndex(o => o.menu == '[edit]') + await helper.selectCompleteItem(idx) + await helper.wait(800) + let line = await nvim.line + expect(line).toBe('foo = foo0bar1') + expect(snippetManager.isActived(doc.bufnr)).toBe(true) + let [, lnum, col] = await nvim.call('getcurpos') + expect(lnum).toBe(1) + expect(col).toBe(3) + }) + + it('should fix input for snippet item', async () => { + let provider: CompletionItemProvider = { + provideCompletionItems: async (): Promise => [{ + label: 'foo', + filterText: 'foo', + insertText: '${1:foo}($2)', + insertTextFormat: InsertTextFormat.Snippet, + }] + } + disposables.push(languages.registerCompletionItemProvider('snippets-test', 'st', null, provider)) + await nvim.input('if') + await helper.waitPopup() + await nvim.input('') + await helper.wait(100) + let line = await nvim.line + expect(line).toBe('foo') + }) + + it('should filter on none keyword input', async () => { + let source: ISource = { + priority: 99, + enable: true, + name: 'temp', + sourceType: SourceType.Service, + doComplete: (_opt: CompleteOption): Promise => Promise.resolve({ items: [{ word: 'foo#abc' }] }), + } + disposables.push(sources.addSource(source)) + await nvim.input('if') + await helper.waitPopup() + await nvim.input('#') + await helper.wait(100) + let items = await helper.getItems() + expect(items[0].word).toBe('foo#abc') + }) + + it('should use source-provided score', async () => { + let source: ISource = { + priority: 0, + enable: true, + name: 'source', + sourceType: SourceType.Service, + doComplete: (_opt: CompleteOption): Promise => Promise.resolve({ + items: [ + { word: 'candidate_a', sourceScore: 0.1 }, + { word: 'candidate_b', sourceScore: 10 }, + { word: 'candidate_c' }, + ] + }), + } + disposables.push(sources.addSource(source)) + await nvim.input('ocand') + await helper.waitPopup() + let items = await helper.getItems() + expect(items[0].word).toBe('candidate_b') + expect(items[1].word).toBe('candidate_c') + expect(items[2].word).toBe('candidate_a') + }) + + it('should do resolve for complete item', async () => { + let source: ISource = { + priority: 0, + enable: true, + name: 'resolve', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: (_opt: CompleteOption): Promise => Promise.resolve({ items: [{ word: 'foo' }] }), + onCompleteResolve: item => { + item.info = 'detail' + } + } + sources.addSource(source) + await nvim.input('i.') + await helper.waitPopup() + await helper.wait(100) + await nvim.input('') + await helper.wait(100) + // let items = completion.completeItems + // expect(items[0].info).toBe('detail') + sources.removeSource(source) + }) +}) + +describe('completion done', () => { + it('should fix word on CompleteDone', async () => { + await nvim.setLine('fball football') + await nvim.input('i') + await nvim.call('cursor', [1, 2]) + let option: CompleteOption = await nvim.call('coc#util#get_complete_option') + await completion.startCompletion(option) + let items = await helper.items() + expect(items.length).toBe(1) + await nvim.input('') + await helper.wait(30) + await nvim.call('coc#_select') + await helper.wait(100) + let line = await nvim.line + expect(line).toBe('football football') + }) +}) + +describe('completion option', () => { + it('should hide kind and menu when configured', async () => { + helper.updateConfiguration('suggest.disableKind', true) + helper.updateConfiguration('suggest.disableMenu', true) + await nvim.setLine('fball football') + await nvim.input('of') + await helper.waitPopup() + let items = await helper.getItems() + expect(items[0].kind).toBeUndefined() + expect(items[0].menu).toBeUndefined() + helper.updateConfiguration('suggest.disableKind', false) + helper.updateConfiguration('suggest.disableMenu', false) + }) +}) + +describe('completion trigger', () => { + it('should trigger completion on type trigger character', async () => { + let source: ISource = { + priority: 1, + enable: true, + name: 'trigger', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: (opt: CompleteOption): Promise => { + if (opt.triggerCharacter == '.') { + return Promise.resolve({ items: [{ word: 'bar' }] }) + } + return Promise.resolve({ items: [{ word: 'foo#bar' }] }) + } + } + sources.addSource(source) + await nvim.input('i') + await helper.wait(30) + await nvim.input('.') + await helper.waitPopup() + let items = await helper.items() + expect(items.length).toBeGreaterThan(0) + sources.removeSource(source) + }) + + it('should not trigger if autoTrigger is none', async () => { + let config = workspace.getConfiguration('suggest') + config.update('autoTrigger', 'none') + let autoTrigger = completion.config.autoTrigger + expect(autoTrigger).toBe('none') + await nvim.setLine('foo fo') + await nvim.input('A') + await helper.wait(100) + expect(completion.isActivated).toBe(false) + config.update('autoTrigger', 'always') + }) + + it('should trigger complete on trigger patterns match', async () => { + let source: ISource = { + priority: 99, + enable: true, + name: 'temp', + triggerPatterns: [/EM/], + sourceType: SourceType.Service, + doComplete: (opt: CompleteOption): Promise => { + if (!opt.input.startsWith('EM')) return null + return Promise.resolve({ + items: [ + { word: 'foo', filterText: 'EMfoo' }, + { word: 'bar', filterText: 'EMbar' } + ] + }) + }, + } + disposables.push(sources.addSource(source)) + await nvim.input('i') + await nvim.input('EM') + await helper.waitPopup() + let items = await helper.getItems() + expect(items.length).toBe(2) + }) + + it('should trigger complete when pumvisible and triggerPatterns match', async () => { + await nvim.setLine('EnumMember') + let source: ISource = { + priority: 99, + enable: true, + name: 'temp', + triggerPatterns: [/EM/], + sourceType: SourceType.Service, + doComplete: (opt: CompleteOption): Promise => { + if (!opt.input.startsWith('EM')) return null + return Promise.resolve({ + items: [ + { word: 'a', filterText: 'EMa' }, + { word: 'b', filterText: 'EMb' } + ] + }) + }, + } + disposables.push(sources.addSource(source)) + await nvim.input('o') + await helper.wait(10) + await nvim.input('E') + await helper.wait(30) + await nvim.input('M') + await helper.waitPopup() + let items = await helper.getItems() + expect(items.length).toBeGreaterThan(2) + }) +}) + +describe('completion TextChangedI', () => { + it('should respect commitCharacter on TextChangedI', async () => { + let source: ISource = { + priority: 0, + enable: true, + name: 'slow', + sourceType: SourceType.Service, + triggerCharacters: ['.'], + doComplete: (opt: CompleteOption): Promise => { + if (opt.triggerCharacter == '.') { + return Promise.resolve({ items: [{ word: 'bar' }] }) + } + return Promise.resolve({ items: [{ word: 'foo' }] }) + }, + shouldCommit: (_item, character) => character == '.' + } + sources.addSource(source) + await nvim.input('if') + await helper.pumvisible() + await helper.wait(100) + await nvim.input('.') + await helper.wait(100) + sources.removeSource(source) + }) + + it('should cancel completion with same pretext', async () => { + await nvim.setLine('foo') + await nvim.input('of') + await helper.pumvisible() + await helper.wait(30) + await nvim.call('coc#_cancel', []) + let line = await nvim.line + let visible = await nvim.call('pumvisible') + expect(line).toBe('f') + expect(visible).toBe(0) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/configurations.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/configurations.test.ts new file mode 100644 index 00000000..d6cfb646 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/configurations.test.ts @@ -0,0 +1,247 @@ +import fs from 'fs' +import os from 'os' +import { ParseError } from 'jsonc-parser' +import path from 'path' +import Configurations from '../../configuration' +import { convertErrors, getChangedKeys, getConfigurationValue, getKeys, parseConfiguration } from '../../configuration/util' +import { IConfigurationModel } from '../../types' +import { URI } from 'vscode-uri' +import { v1 as uuidv1 } from 'uuid' +import { CONFIG_FILE_NAME } from '../../util' + +const config = fs.readFileSync(path.join(__dirname, './settings.json'), 'utf8') +const workspaceConfigFile = path.resolve(__dirname, `../sample/.vim/${CONFIG_FILE_NAME}`) + +function getConfigurationModel(): IConfigurationModel { + let [, contents] = parseConfiguration(config) + return { contents } +} + +function createConfigurations(): Configurations { + let userConfigFile = path.join(__dirname, './settings.json') + return new Configurations(userConfigFile) +} + +describe('Configurations', () => { + it('should convert errors', () => { + let errors: ParseError[] = [] + for (let i = 0; i < 17; i++) { + errors.push({ + error: i, + offset: 0, + length: 10 + }) + } + let res = convertErrors('file:///1', 'abc', errors) + expect(res.length).toBe(17) + }) + + it('should get all keys', () => { + let res = getKeys({ + foo: { + bar: 1, + from: { + to: 2 + } + }, + bar: [1, 2] + }) + expect(res).toEqual(['foo', 'foo.bar', 'foo.from', 'foo.from.to', 'bar']) + }) + + it('should get configuration value', () => { + let root = { + foo: { + bar: 1, + from: { + to: 2 + } + }, + bar: [1, 2] + } + let res = getConfigurationValue(root, 'foo.from.to', 1) + expect(res).toBe(2) + res = getConfigurationValue(root, 'foo.from', 1) + expect(res).toEqual({ to: 2 }) + }) + + it('should add folder as workspace configuration', () => { + let configurations = createConfigurations() + configurations.onDidChange(e => { + let affects = e.affectsConfiguration('coc') + expect(affects).toBe(true) + }) + configurations.addFolderFile(workspaceConfigFile) + let o = configurations.configuration.workspace.contents + expect(o.coc.preferences.rootPath).toBe('./src') + configurations.dispose() + }) + + it('should get changed keys #1', () => { + let res = getChangedKeys({ y: 2 }, { x: 1 }) + expect(res).toEqual(['x', 'y']) + }) + + it('should get changed keys #2', () => { + let res = getChangedKeys({ x: 1, c: { d: 4 } }, { x: 1, b: { x: 5 } }) + expect(res).toEqual(['b', 'b.x', 'c', 'c.d']) + }) + + it('should load default configurations', () => { + let conf = new Configurations() + expect(conf.defaults.contents.coc).toBeDefined() + let c = conf.getConfiguration('languageserver') + expect(c).toEqual({}) + conf.dispose() + }) + + it('should parse configurations', () => { + let { contents } = getConfigurationModel() + expect(contents.foo.bar).toBe(1) + expect(contents.bar.foo).toBe(2) + expect(contents.schema).toEqual({ 'https://example.com': '*.yaml' }) + }) + + it('should update user config #1', () => { + let conf = new Configurations() + let fn = jest.fn() + conf.onDidChange(e => { + expect(e.affectsConfiguration('x')).toBe(true) + fn() + }) + conf.updateUserConfig({ x: 1 }) + let config = conf.configuration.user + expect(config.contents).toEqual({ x: 1 }) + expect(fn).toBeCalled() + }) + + it('should update user config #2', () => { + let conf = new Configurations() + conf.updateUserConfig({ x: 1 }) + conf.updateUserConfig({ x: undefined }) + let config = conf.configuration.user + expect(config.contents).toEqual({}) + }) + + it('should update workspace config', () => { + let conf = new Configurations() + conf.updateUserConfig({ foo: { bar: 1 } }) + let curr = conf.getConfiguration('foo') + curr.update('bar', 2, false) + curr = conf.getConfiguration('foo') + let n = curr.get('bar') + expect(n).toBe(2) + }) + + it('should handle errors', () => { + let tmpFile = path.join(os.tmpdir(), uuidv1()) + fs.writeFileSync(tmpFile, '{"x":', 'utf8') + let conf = new Configurations(tmpFile) + let errors = conf.errorItems + expect(errors.length > 1).toBe(true) + conf.dispose() + }) + + it('should change to new folder configuration', () => { + let conf = new Configurations() + conf.addFolderFile(workspaceConfigFile) + let configFile = path.join(__dirname, './settings.json') + conf.addFolderFile(configFile) + let file = path.resolve(__dirname, '../sample/tmp.js') + let fn = jest.fn() + conf.onDidChange(fn) + conf.setFolderConfiguration(URI.file(file).toString()) + let { contents } = conf.workspace + expect(contents.foo).toBeUndefined() + expect(fn).toBeCalled() + conf.dispose() + }) + + it('should get nested property', () => { + let config = createConfigurations() + let conf = config.getConfiguration('servers.c') + let res = conf.get('trace.server', '') + expect(res).toBe('verbose') + config.dispose() + }) + + it('should get user and workspace configuration', () => { + let userConfigFile = path.join(__dirname, './settings.json') + let configurations = new Configurations(userConfigFile) + let data = configurations.configuration.toData() + expect(data.user).toBeDefined() + expect(data.workspace).toBeDefined() + expect(data.defaults).toBeDefined() + let value = configurations.configuration.getValue() + expect(value.foo).toBeDefined() + expect(value.foo.bar).toBe(1) + configurations.dispose() + }) + + it('should override with new value', () => { + let configurations = createConfigurations() + configurations.configuration.defaults.setValue('foo', 1) + let { contents } = configurations.defaults + expect(contents.foo).toBe(1) + configurations.dispose() + }) + + it('should extends defaults', () => { + let configurations = createConfigurations() + configurations.extendsDefaults({ 'a.b': 1 }) + configurations.extendsDefaults({ 'a.b': 2 }) + let o = configurations.defaults.contents + expect(o.a.b).toBe(2) + configurations.dispose() + }) + + it('should update configuration', async () => { + let configurations = createConfigurations() + configurations.addFolderFile(workspaceConfigFile) + let fn = jest.fn() + configurations.onDidChange(e => { + expect(e.affectsConfiguration('foo')).toBe(true) + expect(e.affectsConfiguration('foo.bar')).toBe(true) + expect(e.affectsConfiguration('foo.bar', 'file://tmp/foo.js')).toBe(false) + fn() + }) + let config = configurations.getConfiguration('foo') + let o = config.get('bar') + expect(o).toBe(1) + config.update('bar', 6) + config = configurations.getConfiguration('foo') + expect(config.get('bar')).toBe(6) + expect(fn).toBeCalledTimes(1) + configurations.dispose() + }) + + it('should remove configuration', async () => { + let configurations = createConfigurations() + configurations.addFolderFile(workspaceConfigFile) + let fn = jest.fn() + configurations.onDidChange(e => { + expect(e.affectsConfiguration('foo')).toBe(true) + expect(e.affectsConfiguration('foo.bar')).toBe(true) + fn() + }) + let config = configurations.getConfiguration('foo') + let o = config.get('bar') + expect(o).toBe(1) + config.update('bar', null, true) + config = configurations.getConfiguration('foo') + expect(config.get('bar')).toBeUndefined() + expect(fn).toBeCalledTimes(1) + configurations.dispose() + }) +}) + +describe('parse configuration', () => { + it('should only split top level dot keys', () => { + let o = { 'x.y': 'foo' } + let [, contents] = parseConfiguration(JSON.stringify(o)) + expect(contents).toEqual({ x: { y: 'foo' } }) + let schema = { 'my.schema': { 'foo.bar': 1 } } + let [, obj] = parseConfiguration(JSON.stringify(schema)) + expect(obj).toEqual({ my: { schema: { 'foo.bar': 1 } } }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/cursors.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/cursors.test.ts new file mode 100644 index 00000000..ef37424b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/cursors.test.ts @@ -0,0 +1,421 @@ +import { Neovim } from '@chemzqm/neovim' +import { Range } from 'vscode-languageserver-types' +import Cursors from '../../cursors' +import Document from '../../model/document' +import helper from '../helper' + +let nvim: Neovim +let cursors: Cursors +let ns: number + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + ns = await nvim.createNamespace('coc-cursors') + cursors = new Cursors(nvim) +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + nvim.pauseNotification() + cursors.reset() + await nvim.resumeNotification() + await helper.reset() +}) + +async function rangeCount(): Promise { + let buf = await nvim.buffer + let markers = await helper.getMarkers(buf.id, ns) + return markers.length +} + +describe('cursors#select', () => { + + it('should select by position', async () => { + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['a', 'b']]) + await nvim.call('cursor', [1, 1]) + await helper.wait(100) + doc.forceSync() + await helper.wait(100) + await cursors.select(doc.bufnr, 'position', 'n') + await helper.wait(30) + let n = await rangeCount() + expect(n).toBe(1) + await nvim.setOption('virtualedit', 'onemore') + await nvim.call('cursor', [2, 2]) + await cursors.select(doc.bufnr, 'position', 'n') + n = await rangeCount() + expect(n).toBe(2) + await cursors.select(doc.bufnr, 'position', 'n') + n = await rangeCount() + expect(n).toBe(1) + }) + + it('should select by word', async () => { + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['foo', 'bar']]) + await nvim.call('cursor', [1, 1]) + await helper.wait(30) + doc.forceSync() + await cursors.select(doc.bufnr, 'word', 'n') + let n = await rangeCount() + expect(n).toBe(1) + await nvim.call('cursor', [2, 2]) + await cursors.select(doc.bufnr, 'word', 'n') + n = await rangeCount() + expect(n).toBe(2) + await cursors.select(doc.bufnr, 'word', 'n') + n = await rangeCount() + expect(n).toBe(1) + }) + + it('should select last character', async () => { + let doc = await helper.createDocument() + await nvim.setOption('virtualedit', 'onemore') + await nvim.call('setline', [1, ['}', '{']]) + await nvim.call('cursor', [1, 2]) + await helper.wait(30) + doc.forceSync() + await cursors.select(doc.bufnr, 'word', 'n') + let n = await rangeCount() + expect(n).toBe(1) + await nvim.call('cursor', [2, 1]) + await helper.wait(30) + doc.forceSync() + await cursors.select(doc.bufnr, 'word', 'n') + n = await rangeCount() + expect(n).toBe(2) + }) + + it('should select by visual range', async () => { + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['"foo"', '"bar"']]) + await nvim.call('cursor', [1, 1]) + await nvim.command('normal! vE') + await helper.wait(30) + doc.forceSync() + await cursors.select(doc.bufnr, 'range', 'v') + let n = await rangeCount() + expect(n).toBe(1) + await nvim.call('cursor', [2, 1]) + await nvim.command('normal! vE') + await cursors.select(doc.bufnr, 'range', 'v') + n = await rangeCount() + expect(n).toBe(2) + await cursors.select(doc.bufnr, 'range', 'v') + n = await rangeCount() + expect(n).toBe(1) + }) + + it('should select by operator', async () => { + await nvim.command('nmap x (coc-cursors-operator)') + await helper.createDocument() + await nvim.call('setline', [1, ['"short"', '"long"']]) + await nvim.call('cursor', [1, 2]) + await nvim.input('xa"') + await helper.wait(30) + await nvim.call('cursor', [2, 2]) + await nvim.input('xa"') + await helper.wait(30) + await nvim.command('nunmap x') + }) +}) + +describe('cursors#addRanges', () => { + it('should add ranges', async () => { + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['foo foo foo', 'bar bar']]) + await helper.wait(30) + doc.forceSync() + let ranges = [ + Range.create(0, 0, 0, 3), + Range.create(0, 4, 0, 7), + Range.create(0, 8, 0, 11), + Range.create(1, 0, 1, 3), + Range.create(1, 4, 1, 7) + ] + await cursors.addRanges(ranges) + let n = await rangeCount() + expect(n).toBe(5) + }) +}) + +describe('cursors#onchange', () => { + + async function setup(): Promise { + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['foo foo foo', 'bar bar']]) + await helper.wait(30) + doc.forceSync() + let ranges = [ + Range.create(0, 0, 0, 3), + Range.create(0, 4, 0, 7), + Range.create(0, 8, 0, 11), + Range.create(1, 0, 1, 3), + Range.create(1, 4, 1, 7) + ] + await cursors.addRanges(ranges) + await nvim.call('cursor', [1, 1]) + return doc + } + + it('should ignore change after last range', async () => { + let doc = await setup() + await doc.buffer.append(['append']) + doc.forceSync() + await helper.wait(50) + let n = await rangeCount() + expect(n).toBe(5) + }) + + it('should adjust ranges on change before first line', async () => { + let doc = await setup() + await doc.buffer.setLines(['prepend'], { start: 0, end: 0, strictIndexing: false }) + doc.forceSync() + await helper.wait(200) + let n = await rangeCount() + expect(n).toBe(5) + await nvim.call('cursor', [2, 1]) + await nvim.input('ia') + await helper.wait(100) + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['prepend', 'afoo afoo afoo', 'abar abar']) + }) + + it('should work when change made to unrelated line', async () => { + let doc = await setup() + await doc.buffer.setLines(['prepend'], { start: 0, end: 0, strictIndexing: false }) + doc.forceSync() + await helper.wait(200) + let n = await rangeCount() + expect(n).toBe(5) + await nvim.call('cursor', [1, 1]) + await nvim.input('ia') + await helper.wait(200) + doc.forceSync() + await helper.wait(100) + await nvim.call('cursor', [2, 1]) + await nvim.input('a') + await helper.wait(100) + await doc.synchronize() + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['aprepend', 'afoo afoo afoo', 'abar abar']) + }) + + it('should add text before', async () => { + let doc = await setup() + await nvim.input('iabc') + await helper.wait(30) + await doc.synchronize() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['abcfoo abcfoo abcfoo', 'abcbar abcbar']) + }) + + it('should add text after', async () => { + let doc = await setup() + await nvim.call('cursor', [1, 4]) + await nvim.input('iabc') + await helper.wait(30) + await doc.synchronize() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['fooabc fooabc fooabc', 'barabc barabc']) + }) + + it('should add text around', async () => { + let doc = await setup() + await nvim.setLine('"foo" foo foo') + await helper.wait(30) + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['"foo" "foo" "foo"', '"bar" "bar"']) + }) + + it('should remove text before', async () => { + let doc = await setup() + await nvim.command('normal! x') + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['oo oo oo', 'ar ar']) + }) + + it('should remove text middle', async () => { + let doc = await setup() + await nvim.call('cursor', [2, 2]) + await nvim.command('normal! x') + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['fo fo fo', 'br br']) + }) + + it('should remove text after', async () => { + let doc = await setup() + await nvim.call('cursor', [1, 3]) + await nvim.command('normal! x') + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['fo fo fo', 'ba ba']) + }) + + it('should remove text around', async () => { + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['"foo" "bar"']]) + await helper.wait(30) + doc.forceSync() + let ranges = [ + Range.create(0, 0, 0, 5), + Range.create(0, 6, 0, 11) + ] + await cursors.addRanges(ranges) + await nvim.call('cursor', [1, 2]) + await nvim.setLine('foo "bar"') + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['foo bar']) + }) + + it('should replace text before', async () => { + let doc = await setup() + await nvim.call('cursor', [1, 1]) + await nvim.command('normal! ra') + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['aoo aoo aoo', 'aar aar']) + }) + + it('should replace text after', async () => { + let doc = await setup() + await nvim.call('cursor', [1, 3]) + await nvim.command('normal! ra') + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['foa foa foa', 'baa baa']) + }) + + it('should replace text middle', async () => { + let doc = await setup() + await nvim.call('cursor', [1, 2]) + await nvim.input('sab') + await helper.wait(30) + doc.forceSync() + await helper.wait(100) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['fabo fabo fabo', 'babr babr']) + }) + + it('should adjust undo & redo on add & remove', async () => { + let doc = await setup() + await nvim.call('cursor', [1, 4]) + await nvim.input('iabc') + await helper.wait(30) + doc.forceSync() + let n = await rangeCount() + expect(n).toBe(5) + await helper.wait(30) + await nvim.command('undo') + await helper.wait(30) + doc.forceSync() + n = await rangeCount() + expect(n).toBe(5) + await helper.wait(30) + await nvim.command('redo') + await helper.wait(30) + doc.forceSync() + expect(await rangeCount()).toBe(5) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['fooabc fooabc fooabc', 'barabc barabc']) + }) + + it('should adjust undo & redo on change around', async () => { + let doc = await setup() + await nvim.setLine('"foo" foo foo') + await helper.wait(30) + doc.forceSync() + expect(await rangeCount()).toBe(5) + await helper.wait(30) + await nvim.command('undo') + await helper.wait(30) + doc.forceSync() + expect(await rangeCount()).toBe(5) + await helper.wait(30) + await nvim.command('redo') + await helper.wait(30) + doc.forceSync() + expect(await rangeCount()).toBe(5) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['"foo" "foo" "foo"', '"bar" "bar"']) + }) +}) + +describe('cursors#keymaps', () => { + async function setup(): Promise { + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['a', 'b', 'c']]) + await helper.wait(30) + doc.forceSync() + await nvim.call('cursor', [1, 1]) + await cursors.select(doc.bufnr, 'position', 'n') + await helper.wait(30) + await nvim.call('cursor', [2, 1]) + await cursors.select(doc.bufnr, 'position', 'n') + await helper.wait(30) + await nvim.call('cursor', [3, 1]) + await cursors.select(doc.bufnr, 'position', 'n') + } + + async function hasKeymap(key): Promise { + let buf = await nvim.buffer + let keymaps = await buf.getKeymap('n') as any + return keymaps.find(o => o.lhs == key) != null + } + + it('should setup cancel keymap', async () => { + await setup() + let count = await rangeCount() + expect(count).toBe(3) + await nvim.input('') + await helper.wait(100) + count = await rangeCount() + expect(count).toBe(0) + let has = await hasKeymap('') + expect(has).toBe(false) + }) + + it('should setup next key', async () => { + await setup() + await nvim.input('') + await helper.wait(50) + let cursor = await nvim.call('coc#cursor#position') + expect(cursor).toEqual([0, 0]) + await nvim.input('') + await helper.wait(50) + cursor = await nvim.call('coc#cursor#position') + expect(cursor).toEqual([1, 0]) + }) + + it('should setup previous key', async () => { + await setup() + await nvim.input('') + await helper.wait(50) + let cursor = await nvim.call('coc#cursor#position') + expect(cursor).toEqual([1, 0]) + await nvim.input('') + await helper.wait(50) + cursor = await nvim.call('coc#cursor#position') + expect(cursor).toEqual([0, 0]) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/db.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/db.test.ts new file mode 100644 index 00000000..a948293d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/db.test.ts @@ -0,0 +1,60 @@ +import DB from '../../model/db' +import path from 'path' + +let db: DB +beforeAll(async () => { + db = new DB(path.join(__dirname, 'db.json')) +}) + +afterAll(async () => { + db.destroy() +}) + +afterEach(async () => { + db.clear() +}) + +describe('DB', () => { + + test('db.exists()', async () => { + let exists = db.exists('a.b') + expect(exists).toBe(false) + db.push('a.b', { foo: 1 }) + exists = db.exists('a.b.foo') + expect(exists).toBe(true) + }) + + test('db.fetch()', async () => { + let res = await db.fetch('x') + expect(res).toBeUndefined() + db.push('x', 1) + res = await db.fetch('x') + expect(res).toBe(1) + db.push('x', { foo: 1 }) + res = await db.fetch('x') + expect(res).toEqual({ foo: 1 }) + }) + + test('db.delete()', async () => { + db.push('foo.bar', 1) + db.delete('foo.bar') + let exists = db.exists('foo.bar') + expect(exists).toBe(false) + }) + + test('db.push()', async () => { + db.push('foo.x', 1) + db.push('foo.y', '2') + db.push('foo.z', true) + db.push('foo.n', null) + db.push('foo.o', { x: 1 }) + let res = db.fetch('foo') + expect(res).toEqual({ + x: 1, + y: '2', + z: true, + n: null, + o: { x: 1 } + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/decorator.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/decorator.test.ts new file mode 100644 index 00000000..85e58948 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/decorator.test.ts @@ -0,0 +1,27 @@ +import * as decorator from '../../util/decorator' + +class CallTest { + public count = 0 + + @decorator.memorize + public async memorized(): Promise { return ++this.count } +} + +describe('memorize', () => { + test('overlapping', async () => { + const c = new CallTest() + + const first = c.memorized() + const second = c.memorized() + expect(await first).toBe(1) + expect(await second).toBe(2) + }) + test('nonoverlapping', async () => { + const c = new CallTest() + + const first = c.memorized() + expect(await first).toBe(1) + const second = c.memorized() + expect(await second).toBe(1) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticBuffer.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticBuffer.test.ts new file mode 100644 index 00000000..9f6bdfbd --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticBuffer.test.ts @@ -0,0 +1,250 @@ +import helper from '../helper' +import { Neovim } from '@chemzqm/neovim' +import { DiagnosticBuffer } from '../../diagnostic/buffer' +import { Range, DiagnosticSeverity, Diagnostic, DiagnosticTag, Position } from 'vscode-languageserver-types' +import workspace from '../../workspace' + +let nvim: Neovim +const config: any = { + autoRefresh: true, + checkCurrentLine: false, + locationlistUpdate: true, + enableSign: true, + enableHighlightLineNumber: true, + enableMessage: 'always', + messageTarget: 'echo', + messageDelay: 250, + refreshOnInsertMode: false, + virtualTextSrcId: 99, + virtualText: false, + virtualTextCurrentLineOnly: true, + virtualTextPrefix: " ", + virtualTextLines: 3, + virtualTextLineSeparator: " \\ ", + displayByAle: false, + level: DiagnosticSeverity.Hint, + signPriority: 11, + errorSign: '>>', + warningSign: '>>', + infoSign: '>>', + hintSign: '>>', + filetypeMap: { + default: '' + }, +} + +async function createDiagnosticBuffer(): Promise { + let doc = await helper.createDocument() + return new DiagnosticBuffer(nvim, doc.bufnr, doc.uri, config, () => { + // noop + }) +} + +function createDiagnostic(msg: string, range?: Range, severity?: DiagnosticSeverity, tags?: DiagnosticTag[]): Diagnostic & { collection: string } { + range = range ? range : Range.create(0, 0, 0, 1) + return Object.assign(Diagnostic.create(range, msg, severity || DiagnosticSeverity.Error, 999, 'test'), { collection: 'test', tags }) +} + +let ns: number +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + ns = await nvim.createNamespace('coc-diagnostic') +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('diagnostic buffer', () => { + describe('refresh()', () => { + it('should add signs', async () => { + let diagnostics = [createDiagnostic('foo'), createDiagnostic('bar')] + let buf = await createDiagnosticBuffer() + buf.addSigns('a', diagnostics) + await helper.wait(30) + let res = await nvim.call('sign_getplaced', [buf.bufnr, { group: 'CocDiagnostica' }]) + let signs = res[0].signs + expect(signs).toBeDefined() + expect(signs[0].name).toBe('CocError') + }) + + it('should set diagnostic info', async () => { + let r = Range.create(0, 1, 0, 2) + let diagnostics = [ + createDiagnostic('foo', r, DiagnosticSeverity.Error), + createDiagnostic('bar', r, DiagnosticSeverity.Warning), + createDiagnostic('foo', r, DiagnosticSeverity.Hint), + createDiagnostic('bar', r, DiagnosticSeverity.Information) + ] + let buf = await createDiagnosticBuffer() + await buf.refresh({ '': diagnostics }) + let buffer = await nvim.buffer + let res = await buffer.getVar('coc_diagnostic_info') + expect(res).toEqual({ + lnums: [1, 1, 1, 1], + information: 1, + hint: 1, + warning: 1, + error: 1 + }) + }) + + it('should add highlight', async () => { + let buf = await createDiagnosticBuffer() + let doc = workspace.getDocument(buf.bufnr) + await nvim.setLine('abc') + await doc.patchChange(true) + nvim.pauseNotification() + buf.updateHighlights('', [ + createDiagnostic('foo', Range.create(0, 0, 0, 1), DiagnosticSeverity.Error), + createDiagnostic('bar', Range.create(0, 0, 0, 1), DiagnosticSeverity.Warning) + ]) + await nvim.resumeNotification() + let res = await nvim.call('nvim_buf_get_extmarks', [buf.bufnr, ns, 0, -1, { details: true }]) as any + expect(res).toEqual([ + [ + 1, + 0, + 0, + { + hl_group: 'CocWarningHighlight', + priority: 4096, + end_col: 1, + end_row: 0 + } + ], + [ + 2, + 0, + 0, + { + hl_group: 'CocErrorHighlight', + priority: 4096, + end_col: 1, + end_row: 0 + } + ] + ]) + nvim.pauseNotification() + buf.updateHighlights('', []) + await nvim.resumeNotification() + res = await nvim.call('nvim_buf_get_extmarks', [buf.bufnr, ns, 0, -1, { details: true }]) as any[] + expect(res.length).toBe(0) + }) + + it('should add deprecated highlight', async () => { + let diagnostic = createDiagnostic('foo', Range.create(0, 0, 0, 1), DiagnosticSeverity.Information, [DiagnosticTag.Deprecated]) + let buf = await createDiagnosticBuffer() + let doc = workspace.getDocument(buf.bufnr) + await nvim.setLine('foo') + await doc.patchChange(true) + nvim.pauseNotification() + buf.updateHighlights('', [diagnostic]) + await nvim.resumeNotification() + let res = await nvim.call('nvim_buf_get_extmarks', [buf.bufnr, ns, 0, -1, {}]) as [number, number, number][] + expect(res.length).toBe(1) + }) + }) + + describe('showVirtualText()', () => { + beforeEach(async () => { + config.virtualText = true + config.virtualTextSrcId = await nvim.createNamespace('diagnostics-virtualText') + }) + afterEach(() => { + config.virtualText = false + config.virtualTextCurrentLineOnly = true + }) + + it('should show virtual text on current line', async () => { + let diagnostic = createDiagnostic('foo') + let buf = await createDiagnosticBuffer() + let diagnostics = [diagnostic] + await buf.refresh({ '': diagnostics }) + let ns = config.virtualTextSrcId + let res = await nvim.call('nvim_buf_get_extmarks', [buf.bufnr, ns, 0, -1, { details: true }]) as any + expect(res.length).toBe(1) + let texts = res[0][3].virt_text + expect(texts[0]).toEqual([' foo', 'CocErrorVirtualText']) + }) + + it('should virtual text on all lines', async () => { + config.virtualTextCurrentLineOnly = false + let buf = await createDiagnosticBuffer() + let diagnostics = [ + createDiagnostic('foo', Range.create(0, 0, 0, 1)), + createDiagnostic('bar', Range.create(1, 0, 1, 1)), + ] + await buf.refresh({ '': diagnostics }) + let ns = config.virtualTextSrcId + let res = await nvim.call('nvim_buf_get_extmarks', [buf.bufnr, ns, 0, -1, { details: true }]) as any + expect(res.length).toBe(2) + }) + }) + + describe('updateLocationList()', () => { + beforeEach(async () => { + config.locationlistUpdate = true + }) + afterEach(() => { + config.locationlistUpdate = false + }) + + it('should update location list', async () => { + let buf = await createDiagnosticBuffer() + await nvim.call('setloclist', [0, [], 'r', { title: 'Diagnostics of coc', items: [] }]) + await buf.refresh({ + a: [createDiagnostic('foo')] + }) + let res = await nvim.eval(`getloclist(bufwinid(${buf.bufnr}))`) as any[] + expect(res.length).toBe(1) + expect(res[0].text).toBe('[test 999] foo [E]') + }) + }) + + describe('clear()', () => { + let config = workspace.getConfiguration('diagnostic') + beforeEach(() => { + config.update('virtualText', true) + }) + afterEach(() => { + config.update('virtualText', false) + }) + + it('should clear all diagnostics', async () => { + let diagnostic = createDiagnostic('foo') + let buf = await createDiagnosticBuffer() + let diagnostics = [diagnostic] + await buf.refresh({ '': diagnostics }) + buf.clear() + await helper.wait(50) + let buffer = await nvim.buffer + let res = await buffer.getVar("coc_diagnostic_info") + expect(res == null).toBe(true) + }) + }) + + describe('getDiagnostics()', () => { + it('should get sorted diagnostics', async () => { + let buf = await createDiagnosticBuffer() + let diagnostics = [ + createDiagnostic('three', Range.create(0, 1, 0, 2), DiagnosticSeverity.Error), + createDiagnostic('one', Range.create(0, 0, 0, 2), DiagnosticSeverity.Warning), + createDiagnostic('two', Range.create(0, 0, 0, 2), DiagnosticSeverity.Error), + ] + diagnostics[0].tags = [DiagnosticTag.Unnecessary] + await buf.refresh({ + x: diagnostics, + y: [createDiagnostic('four', Range.create(0, 0, 0, 2), DiagnosticSeverity.Error)] + }) + let res = buf.getDiagnosticsAt(Position.create(0, 1), false) + let arr = res.map(o => o.message) + expect(arr).toEqual(['four', 'two', 'three', 'one']) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticCollection.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticCollection.test.ts new file mode 100644 index 00000000..1321b5bb --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticCollection.test.ts @@ -0,0 +1,98 @@ +import DiagnosticCollection from '../../diagnostic/collection' +import { Diagnostic, Range } from 'vscode-languageserver-types' + +function createDiagnostic(msg: string, range?: Range): Diagnostic { + range = range ? range : Range.create(0, 0, 0, 1) + return Diagnostic.create(range, msg) +} + +describe('diagnostic collection', () => { + + it('should create collection', () => { + let collection = new DiagnosticCollection('test') + expect(collection.name).toBe('test') + }) + + it('should set diagnostic with uri', () => { + let collection = new DiagnosticCollection('test') + let diagnostic = createDiagnostic('error') + let uri = 'file:///1' + collection.set(uri, [diagnostic]) + expect(collection.get(uri).length).toBe(1) + collection.set(uri, []) + expect(collection.get(uri).length).toBe(0) + }) + + it('should clear diagnostics with null as diagnostics', () => { + let collection = new DiagnosticCollection('test') + let diagnostic = createDiagnostic('error') + let uri = 'file:///1' + collection.set(uri, [diagnostic]) + expect(collection.get(uri).length).toBe(1) + collection.set(uri, null) + expect(collection.get(uri).length).toBe(0) + }) + + it('should clear diagnostics with undefined as diagnostics in entries', () => { + let collection = new DiagnosticCollection('test') + let diagnostic = createDiagnostic('error') + let entries: [string, Diagnostic[] | null][] = [ + ['file:1', [diagnostic]], + ['file:1', undefined] + ] + let uri = 'file:///1' + collection.set(entries) + expect(collection.get(uri).length).toBe(0) + }) + + it('should set diagnostics with entries', () => { + let collection = new DiagnosticCollection('test') + let diagnostic = createDiagnostic('error') + let uri = 'file:///1' + let other = 'file:///2' + let entries: [string, Diagnostic[]][] = [ + [uri, [diagnostic]], + [other, [diagnostic]], + [uri, [createDiagnostic('other')]] + ] + collection.set(entries) + expect(collection.get(uri).length).toBe(2) + expect(collection.get(other).length).toBe(1) + }) + + it('should delete diagnostics for uri', () => { + let collection = new DiagnosticCollection('test') + let diagnostic = createDiagnostic('error') + let uri = 'file:///1' + collection.set(uri, [diagnostic]) + collection.delete(uri) + expect(collection.get(uri).length).toBe(0) + }) + + it('should clear all diagnostics', () => { + let collection = new DiagnosticCollection('test') + let diagnostic = createDiagnostic('error') + let uri = 'file:///1' + collection.set(uri, [diagnostic]) + collection.clear() + expect(collection.get(uri).length).toBe(0) + }) + + it('should call for every uri with diagnostics', () => { + let collection = new DiagnosticCollection('test') + let diagnostic = createDiagnostic('error') + let uri = 'file:///1' + let other = 'file:///2' + let entries: [string, Diagnostic[]][] = [ + [uri, [diagnostic]], + [other, [diagnostic]], + [uri, [createDiagnostic('other')]] + ] + collection.set(entries) + let arr: string[] = [] + collection.forEach(uri => { + arr.push(uri) + }) + expect(arr).toEqual([uri, other]) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticManager.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticManager.test.ts new file mode 100644 index 00000000..14e5fe82 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/diagnosticManager.test.ts @@ -0,0 +1,556 @@ +import { Neovim } from '@chemzqm/neovim' +import path from 'path' +import { severityLevel, getNameFromSeverity } from '../../diagnostic/util' +import { Range, DiagnosticSeverity, Diagnostic, Location, DiagnosticTag } from 'vscode-languageserver-types' +import { URI } from 'vscode-uri' +import Document from '../../model/document' +import workspace from '../../workspace' +import window from '../../window' +import manager from '../../diagnostic/manager' +import helper, { createTmpFile } from '../helper' + +let nvim: Neovim +function createDiagnostic(msg: string, range?: Range, severity?: DiagnosticSeverity): Diagnostic { + range = range ? range : Range.create(0, 0, 0, 1) + return Diagnostic.create(range, msg, severity || DiagnosticSeverity.Error) +} + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + manager.reset() + await helper.reset() +}) + +async function createDocument(name?: string): Promise { + let doc = await helper.createDocument(name) + let collection = manager.create('test') + let diagnostics: Diagnostic[] = [] + await doc.buffer.setLines(['foo bar foo bar', 'foo bar', 'foo', 'bar'], { + start: 0, + end: -1, + strictIndexing: false + }) + diagnostics.push(createDiagnostic('error', Range.create(0, 2, 0, 4), DiagnosticSeverity.Error)) + diagnostics.push(createDiagnostic('warning', Range.create(0, 5, 0, 6), DiagnosticSeverity.Warning)) + diagnostics.push(createDiagnostic('information', Range.create(1, 0, 1, 1), DiagnosticSeverity.Information)) + diagnostics.push(createDiagnostic('hint', Range.create(1, 2, 1, 3), DiagnosticSeverity.Hint)) + diagnostics.push(createDiagnostic('error', Range.create(2, 0, 2, 2), DiagnosticSeverity.Error)) + collection.set(doc.uri, diagnostics) + doc.forceSync() + return doc +} + +describe('diagnostic manager', () => { + describe('refresh()', () => { + it('should refresh on buffer create', async () => { + let uri = URI.file(path.join(path.dirname(__dirname), 'doc')).toString() + let fn = jest.fn() + let disposable = manager.onDidRefresh(() => { + fn() + }) + let collection = manager.create('tmp') + let diagnostic = createDiagnostic('My Error') + collection.set(uri, [diagnostic]) + let doc = await helper.createDocument('doc') + let val = await doc.buffer.getVar('coc_diagnostic_info') as any + expect(fn).toBeCalled() + expect(val).toBeDefined() + expect(val.error).toBe(1) + collection.dispose() + disposable.dispose() + }) + + it('should delay refresh on InsertLeave', async () => { + let doc = await helper.createDocument() + await nvim.input('i') + let collection = manager.create('test') + let diagnostics: Diagnostic[] = [] + await doc.buffer.setLines(['foo bar foo bar', 'foo bar', 'foo', 'bar'], { + start: 0, + end: -1, + strictIndexing: false + }) + diagnostics.push(createDiagnostic('error', Range.create(0, 2, 0, 4), DiagnosticSeverity.Error)) + collection.set(doc.uri, diagnostics) + await helper.wait(10) + await nvim.input('') + await helper.wait(100) + let val = await doc.buffer.getVar('coc_diagnostic_info') as any + expect(val).toBe(null) + await helper.wait(600) + val = await doc.buffer.getVar('coc_diagnostic_info') as any + expect(val).toBeDefined() + }) + }) + + describe('toggleDiagnostic()', () => { + it('should toggle diagnostics', async () => { + let doc = await createDocument() + await helper.wait(50) + manager.toggleDiagnostic() + await helper.wait(50) + let val = await doc.buffer.getVar('coc_diagnostic_info') as any + expect(val).toBe(null) + manager.toggleDiagnostic() + await helper.wait(50) + val = await doc.buffer.getVar('coc_diagnostic_info') as any + expect(val).toBeDefined() + expect(val.error).toBe(2) + }) + }) + + describe('getDiagnosticList()', () => { + it('should get all diagnostics', async () => { + await createDocument() + let list = manager.getDiagnosticList() + expect(list).toBeDefined() + expect(list.length).toBeGreaterThanOrEqual(5) + expect(list[0].severity).toBe('Error') + expect(list[1].severity).toBe('Error') + expect(list[2].severity).toBe('Warning') + expect(list[3].severity).toBe('Information') + expect(list[4].severity).toBe('Hint') + }) + + it('should filter diagnostics by configuration', async () => { + let config = workspace.getConfiguration('diagnostic') + config.update('level', 'warning') + config.update('showUnused', false) + config.update('showDeprecated', false) + let doc = await createDocument() + let diagnostics = manager.getDiagnostics(doc.uri)['test'] + diagnostics[0].tags = [DiagnosticTag.Unnecessary] + diagnostics[2].tags = [DiagnosticTag.Deprecated] + let collection = manager.getCollectionByName('test') + collection.set(doc.uri, diagnostics) + let list = manager.getDiagnosticList() + expect(list.length).toBe(1) + expect(list[0].severity).toBe('Warning') + let res = manager.getDiagnostics(doc.uri)['test'] + expect(res.length).toBe(1) + helper.updateConfiguration('diagnostic.level', 'hint') + helper.updateConfiguration('diagnostic.showUnused', true) + helper.updateConfiguration('diagnostic.showDeprecated', true) + let ranges = manager.getSortedRanges(doc.uri) + expect(ranges.length).toBe(3) + }) + }) + + describe('preview()', () => { + it('should not throw with empty diagnostics', async () => { + await helper.createDocument() + await manager.preview() + let tabpage = await nvim.tabpage + let wins = await tabpage.windows + expect(wins.length).toBe(1) + }) + + it('should open preview window', async () => { + await createDocument() + await nvim.call('cursor', [1, 3]) + await manager.preview() + let res = await nvim.call('coc#window#find', ['&previewwindow', 1]) + expect(res).toBeDefined() + await nvim.call('win_gotoid', [res]) + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines[0]).toEqual('[test] [E]') + }) + }) + + describe('setLocationlist()', () => { + it('should set location list', async () => { + let doc = await createDocument() + await manager.setLocationlist(doc.bufnr) + await nvim.command('lopen') + let buftype = await nvim.eval('&buftype') as string + expect(buftype).toBe('quickfix') + }) + }) + + describe('setConfigurationErrors()', () => { + it('should set configuration errors', async () => { + let doc = await helper.createDocument() + let errors = [{ + location: Location.create(doc.uri, Range.create(0, 0, 1, 0)), + message: 'foo', + }, { + location: Location.create(doc.uri, Range.create(1, 0, 2, 0)), + message: 'bar', + }] + manager.setConfigurationErrors(errors) + await helper.wait(50) + let res = manager.getDiagnostics(doc.uri, 'config')['config'] + expect(res.length).toBe(2) + manager.setConfigurationErrors() + await helper.wait(50) + res = manager.getDiagnostics(doc.uri, 'config')['config'] + expect(res.length).toBe(0) + }) + }) + + describe('create()', () => { + it('should create diagnostic collection', async () => { + let doc = await helper.createDocument() + let collection = manager.create('test') + collection.set(doc.uri, [createDiagnostic('foo')]) + await helper.wait(50) + let info = await doc.buffer.getVar('coc_diagnostic_info') + expect(info).toBeDefined() + await nvim.command('bd!') + await helper.wait(50) + }) + }) + + describe('getSortedRanges()', () => { + it('should get sorted ranges of document', async () => { + let doc = await helper.createDocument() + await nvim.call('setline', [1, ['a', 'b', 'c']]) + let collection = manager.create('test') + let diagnostics: Diagnostic[] = [] + diagnostics.push(createDiagnostic('x', Range.create(0, 0, 0, 1))) + diagnostics.push(createDiagnostic('y', Range.create(0, 1, 0, 2))) + diagnostics.push(createDiagnostic('z', Range.create(1, 0, 1, 2))) + collection.set(doc.uri, diagnostics) + let ranges = manager.getSortedRanges(doc.uri) + expect(ranges[0]).toEqual(Range.create(0, 0, 0, 1)) + expect(ranges[1]).toEqual(Range.create(0, 1, 0, 2)) + expect(ranges[2]).toEqual(Range.create(1, 0, 1, 2)) + ranges = manager.getSortedRanges(doc.uri, 'error') + expect(ranges.length).toBe(3) + expect(manager.getSortedRanges(doc.uri, 'warning').length).toBe(0) + }) + }) + + describe('getDiagnosticsInRange', () => { + it('should get diagnostics in range', async () => { + let doc = await helper.createDocument() + let collection = manager.create('test') + let diagnostics: Diagnostic[] = [] + await doc.buffer.setLines(['foo bar foo bar', 'foo bar'], { + start: 0, + end: -1, + strictIndexing: false + }) + await helper.wait(300) + diagnostics.push(createDiagnostic('a', Range.create(0, 0, 0, 1))) + diagnostics.push(createDiagnostic('b', Range.create(0, 2, 0, 3))) + diagnostics.push(createDiagnostic('c', Range.create(1, 0, 1, 2))) + collection.set(doc.uri, diagnostics) + let res = manager.getDiagnosticsInRange(doc.textDocument, Range.create(0, 0, 0, 3)) + expect(res.length).toBe(2) + }) + }) + + describe('getCurrentDiagnostics', () => { + it('should get diagnostics under corsor', async () => { + let config = workspace.getConfiguration('diagnostic') + await createDocument() + let diagnostics = await manager.getCurrentDiagnostics() + expect(diagnostics.length).toBe(0) + await nvim.call('cursor', [1, 4]) + diagnostics = await manager.getCurrentDiagnostics() + expect(diagnostics.length).toBe(1) + config.update('checkCurrentLine', true) + await nvim.call('cursor', [1, 2]) + diagnostics = await manager.getCurrentDiagnostics() + expect(diagnostics.length).toBe(2) + config.update('checkCurrentLine', false) + }) + + it('should get empty diagnostic at end of line', async () => { + let doc = await helper.createDocument() + await nvim.setLine('foo') + doc.forceSync() + await nvim.command('normal! $') + let diagnostic = Diagnostic.create(Range.create(0, 3, 1, 0), 'error', DiagnosticSeverity.Error) + let collection = manager.create('empty') + collection.set(doc.uri, [diagnostic]) + await manager.refreshBuffer(doc.bufnr, true) + let diagnostics = await manager.getCurrentDiagnostics() + expect(diagnostics.length).toBeGreaterThanOrEqual(1) + expect(diagnostics[0].message).toBe('error') + collection.dispose() + }) + + it('should get diagnostic next to end of line', async () => { + let doc = await helper.createDocument() + await nvim.setLine('foo') + doc.forceSync() + await nvim.command('normal! $') + let diagnostic = Diagnostic.create(Range.create(0, 3, 0, 4), 'error', DiagnosticSeverity.Error) + let collection = manager.create('empty') + collection.set(doc.uri, [diagnostic]) + await manager.refreshBuffer(doc.bufnr, true) + let diagnostics = await manager.getCurrentDiagnostics() + expect(diagnostics.length).toBeGreaterThanOrEqual(1) + expect(diagnostics[0].message).toBe('error') + collection.dispose() + }) + + it('should get diagnostic with empty range at end of line', async () => { + let doc = await helper.createDocument() + await nvim.setLine('foo') + doc.forceSync() + await nvim.command('normal! $') + let diagnostic = Diagnostic.create(Range.create(0, 3, 1, 0), 'error', DiagnosticSeverity.Error) + let collection = manager.create('empty') + collection.set(doc.uri, [diagnostic]) + await manager.refreshBuffer(doc.bufnr, true) + let diagnostics = await manager.getCurrentDiagnostics() + expect(diagnostics.length).toBeGreaterThanOrEqual(1) + expect(diagnostics[0].message).toBe('error') + collection.dispose() + }) + + it('should get diagnostic pass end of the buffer lines', async () => { + let doc = await helper.createDocument() + await nvim.setLine('foo') + doc.forceSync() + await nvim.command('normal! ^') + let diagnostic = Diagnostic.create(Range.create(1, 0, 1, 0), 'error', DiagnosticSeverity.Error) + let collection = manager.create('empty') + collection.set(doc.uri, [diagnostic]) + await manager.refreshBuffer(doc.bufnr, true) + let diagnostics = await manager.getCurrentDiagnostics() + expect(diagnostics.length).toBeGreaterThanOrEqual(1) + expect(diagnostics[0].message).toBe('error') + collection.dispose() + }) + + }) + + describe('jumpRelated', () => { + it('should jump to related position', async () => { + let doc = await helper.createDocument() + let range = Range.create(0, 0, 0, 10) + let location = Location.create(URI.file(__filename).toString(), range) + let diagnostic = Diagnostic.create(range, 'msg', DiagnosticSeverity.Error, 1000, 'test', + [{ location, message: 'test' }]) + let collection = manager.create('positions') + collection.set(doc.uri, [diagnostic]) + await manager.refreshBuffer(doc.uri, true) + await nvim.call('cursor', [1, 1]) + await manager.jumpRelated() + await helper.wait(100) + let bufname = await nvim.call('bufname', '%') + expect(bufname).toMatch('diagnosticManager') + }) + + it('should open location list', async () => { + let doc = await helper.createDocument() + let range = Range.create(0, 0, 0, 10) + let diagnostic = Diagnostic.create(range, 'msg', DiagnosticSeverity.Error, 1000, 'test', + [{ + location: Location.create(URI.file(__filename).toString(), Range.create(1, 0, 1, 10)), + message: 'foo' + }, { + location: Location.create(URI.file(__filename).toString(), Range.create(2, 0, 2, 10)), + message: 'bar' + }]) + let collection = manager.create('positions') + collection.set(doc.uri, [diagnostic]) + await manager.refreshBuffer(doc.uri, true) + await nvim.call('cursor', [1, 1]) + await manager.jumpRelated() + await helper.wait(100) + let bufname = await nvim.call('bufname', '%') + expect(bufname).toBe('list:///location') + }) + }) + + describe('jumpPrevious & jumpNext', () => { + it('should jump to previous', async () => { + let doc = await createDocument() + await nvim.command('normal! G$') + let ranges = manager.getSortedRanges(doc.uri) + ranges.reverse() + for (let i = 0; i < ranges.length; i++) { + await manager.jumpPrevious() + let pos = await window.getCursorPosition() + expect(pos).toEqual(ranges[i].start) + } + await manager.jumpPrevious() + }) + + it('should jump to next', async () => { + let doc = await createDocument() + await nvim.call('cursor', [0, 0]) + let ranges = manager.getSortedRanges(doc.uri) + for (let i = 0; i < ranges.length; i++) { + await manager.jumpNext() + let pos = await window.getCursorPosition() + expect(pos).toEqual(ranges[i].start) + } + await manager.jumpNext() + }) + }) + + describe('diagnostic configuration', () => { + it('should use filetype map from config', async () => { + let config = workspace.getConfiguration('diagnostic') + config.update('filetypeMap', { default: 'bufferType' }) + let doc = await createDocument('foo.js') + let collection = manager.getCollectionByName('test') + let diagnostics = [createDiagnostic('99', Range.create(0, 0, 0, 2), DiagnosticSeverity.Error)] + collection.set(doc.uri, diagnostics) + await nvim.call('cursor', [1, 1]) + await nvim.command('doautocmd CursorHold') + let winid = await helper.waitFloat() + await nvim.call('win_gotoid', [winid]) + await nvim.command('normal! $') + let res = await nvim.eval('synIDattr(synID(line("."),col("."),1),"name")') + expect(res).toMatch(/javascript/i) + config.update('filetypeMap', {}) + }) + + it('should show floating window on cursor hold', async () => { + let config = workspace.getConfiguration('diagnostic') + config.update('messageTarget', 'float') + await createDocument() + await nvim.call('cursor', [1, 3]) + await nvim.command('doautocmd CursorHold') + let winid = await helper.waitFloat() + let bufnr = await nvim.call('nvim_win_get_buf', winid) as number + let buf = nvim.createBuffer(bufnr) + let lines = await buf.lines + expect(lines.join('\n')).toMatch('error') + }) + + it('should echo messages on cursor hold', async () => { + let config = workspace.getConfiguration('diagnostic') + config.update('messageTarget', 'echo') + await createDocument() + await nvim.call('cursor', [1, 3]) + await helper.wait(600) + let line = await helper.getCmdline() + expect(line).toMatch('error') + config.update('messageTarget', 'float') + }) + + it('should show diagnostics of current line', async () => { + let config = workspace.getConfiguration('diagnostic') + config.update('checkCurrentLine', true) + await createDocument() + await nvim.call('cursor', [1, 1]) + let winid = await helper.waitFloat() + let bufnr = await nvim.call('nvim_win_get_buf', winid) as number + let buf = nvim.createBuffer(bufnr) + let lines = await buf.lines + expect(lines.length).toBe(3) + config.update('checkCurrentLine', false) + }) + + it('should filter diagnostics by level', async () => { + helper.updateConfiguration('diagnostic.level', 'warning') + let doc = await createDocument() + let diagnosticsMap = manager.getDiagnostics(doc.uri) + for (let diagnostics of Object.values(diagnosticsMap)) { + for (let diagnostic of diagnostics) { + expect(diagnostic.severity != DiagnosticSeverity.Hint).toBe(true) + expect(diagnostic.severity != DiagnosticSeverity.Information).toBe(true) + } + } + helper.updateConfiguration('diagnostic.level', 'hint') + }) + + it('should send ale diagnostic items', async () => { + let config = workspace.getConfiguration('diagnostic') + config.update('displayByAle', true) + let content = ` + function! MockAleResults(bufnr, collection, items) + let g:collection = a:collection + let g:items = a:items + endfunction + ` + let file = await createTmpFile(content) + await nvim.command(`source ${file}`) + await createDocument() + await helper.wait(50) + let items = await nvim.getVar('items') as any[] + expect(Array.isArray(items)).toBe(true) + expect(items.length).toBeGreaterThan(0) + await nvim.command('bd!') + await helper.wait(50) + items = await nvim.getVar('items') as any[] + expect(items).toEqual([]) + config.update('displayByAle', false) + }) + }) + + describe('severityLevel & getNameFromSeverity', () => { + it('should get severity level', () => { + expect(severityLevel('hint')).toBe(DiagnosticSeverity.Hint) + expect(severityLevel('error')).toBe(DiagnosticSeverity.Error) + expect(severityLevel('warning')).toBe(DiagnosticSeverity.Warning) + expect(severityLevel('information')).toBe(DiagnosticSeverity.Information) + expect(severityLevel('')).toBe(DiagnosticSeverity.Hint) + }) + + it('should get severity name', () => { + expect(getNameFromSeverity(null as any)).toBe('CocError') + }) + }) + + describe('toggleDiagnosticBuffer', () => { + it('should toggle diagnostics for buffer', async () => { + let doc = await createDocument() + // required to wait refresh finish + await helper.wait(50) + await manager.toggleDiagnosticBuffer(doc.bufnr) + await helper.wait(50) + let buf = nvim.createBuffer(doc.bufnr) + let res = await buf.getVar('coc_diagnostic_info') as any + expect(res == null).toBe(true) + await manager.toggleDiagnosticBuffer(doc.bufnr) + await helper.wait(50) + res = await buf.getVar('coc_diagnostic_info') as any + expect(res.error).toBe(2) + }) + }) + + describe('refresh', () => { + let config = workspace.getConfiguration('diagnostic') + beforeEach(() => { + config.update('autoRefresh', false) + }) + afterEach(() => { + config.update('autoRefresh', true) + }) + + it('should refresh by bufnr', async () => { + let doc = await createDocument() + let buf = nvim.createBuffer(doc.bufnr) + let res = await buf.getVar('coc_diagnostic_info') as any + // should not refresh + expect(res == null).toBe(true) + manager.refresh(doc.bufnr) + await helper.wait(100) + res = await buf.getVar('coc_diagnostic_info') as any + expect(res?.error).toBe(2) + }) + + it('should refresh all buffers', async () => { + let one = await helper.createDocument('one') + let two = await helper.createDocument('two') + let collection = manager.create('tmp') + collection.set([[one.uri, [createDiagnostic('Error one')]], [two.uri, [createDiagnostic('Error two')]]]) + manager.refresh() + await helper.wait(50) + for (let bufnr of [one.bufnr, two.bufnr]) { + let buf = nvim.createBuffer(bufnr) + let res = await buf.getVar('coc_diagnostic_info') as any + expect(res?.error).toBe(1) + } + collection.dispose() + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/dialog.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/dialog.test.ts new file mode 100644 index 00000000..eb9954e9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/dialog.test.ts @@ -0,0 +1,60 @@ +import { Neovim } from '@chemzqm/neovim' +import Dialog, { DialogButton } from '../../model/dialog' +import helper from '../helper' + +let nvim: Neovim + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('Dialog module', () => { + it('should show dialog', async () => { + let dialog = new Dialog(nvim, { content: '你好' }) + await dialog.show({}) + let winid = await dialog.winid + let win = nvim.createWindow(winid) + let width = await win.width + expect(width).toBe(4) + await nvim.call('coc#float#close', [winid]) + }) + + it('should invoke callback with index -1', async () => { + let callback = jest.fn() + let dialog = new Dialog(nvim, { content: '你好', callback }) + await dialog.show({}) + let winid = await dialog.winid + await nvim.call('coc#float#close', [winid]) + await helper.wait(50) + expect(callback).toHaveBeenCalledWith(-1) + }) + + it('should invoke callback on click', async () => { + let callback = jest.fn() + let buttons: DialogButton[] = [{ + index: 0, + text: 'yes' + }, { + index: 1, + text: 'no' + }] + let dialog = new Dialog(nvim, { content: '你好', buttons, callback }) + await dialog.show({}) + let winid = await dialog.winid + let btnwin = await nvim.call('coc#float#get_related', [winid, 'buttons']) + await nvim.call('win_gotoid', [btnwin]) + await nvim.call('cursor', [2, 1]) + await nvim.call('coc#float#nvim_float_click', []) + await helper.wait(50) + expect(callback).toHaveBeenCalledWith(0) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/diff.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/diff.test.ts new file mode 100644 index 00000000..51ea5a39 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/diff.test.ts @@ -0,0 +1,178 @@ +import { TextEdit } from 'vscode-languageserver-types' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { diffLines, getChange, patchLine, ChangedLines } from '../../util/diff' + +describe('diff lines', () => { + function diff(oldStr: string, newStr: string): ChangedLines { + let oldLines = oldStr.split('\n') + return diffLines(oldLines, newStr.split('\n'), oldLines.length - 2) + } + + it('should diff changed lines', () => { + let res = diff('a\n', 'b\n') + expect(res).toEqual({ start: 0, end: 1, replacement: ['b'] }) + }) + + it('should diff added lines', () => { + let res = diff('a\n', 'a\nb\n') + expect(res).toEqual({ + start: 1, + end: 1, + replacement: ['b'] + }) + }) + + it('should diff remove lines', () => { + let res = diff('a\n\n', 'a\n') + expect(res).toEqual({ + start: 1, + end: 2, + replacement: [] + }) + }) + + it('should diff remove multiple lines', () => { + let res = diff('a\n\n\n', 'a\n') + expect(res).toEqual({ + start: 1, + end: 3, + replacement: [] + }) + }) + + it('should diff removed line', () => { + let res = diff('a\n\n\nb', 'a\n\nb') + expect(res).toEqual({ + start: 2, + end: 3, + replacement: [] + }) + }) + + it('should reduce changed lines', async () => { + let res = diffLines(['a', 'b', 'c'], ['a', 'b', 'c', 'd'], 0) + expect(res).toEqual({ + start: 3, + end: 3, + replacement: ['d'] + }) + }) +}) + +describe('patch line', () => { + it('should patch line', () => { + let res = patchLine('foo', 'bar foo bar') + expect(res.length).toBe(7) + expect(res).toBe(' foo') + }) +}) + +describe('should get text edits', () => { + + function applyEdits(oldStr: string, newStr: string): void { + let doc = TextDocument.create('untitled://1', 'markdown', 0, oldStr) + let change = getChange(doc.getText(), newStr) + let start = doc.positionAt(change.start) + let end = doc.positionAt(change.end) + let edit: TextEdit = { + range: { start, end }, + newText: change.newText + } + let res = TextDocument.applyEdits(doc, [edit]) + expect(res).toBe(newStr) + } + + it('should get diff for comments ', async () => { + let oldStr = '/*\n *\n * \n' + let newStr = '/*\n *\n *\n * \n' + let doc = TextDocument.create('untitled://1', 'markdown', 0, oldStr) + let change = getChange(doc.getText(), newStr, 1) + let start = doc.positionAt(change.start) + let end = doc.positionAt(change.end) + let edit: TextEdit = { + range: { start, end }, + newText: change.newText + } + let res = TextDocument.applyEdits(doc, [edit]) + expect(res).toBe(newStr) + }) + + it('should return null for same content', () => { + let change = getChange('', '') + expect(change).toBeNull() + change = getChange('abc', 'abc') + expect(change).toBeNull() + }) + + it('should get diff for added', () => { + applyEdits('1\n2', '1\n2\n3\n4') + }) + + it('should get diff for added #0', () => { + applyEdits('\n\n', '\n\n\n') + }) + + it('should get diff for added #1', () => { + applyEdits('1\n2\n3', '5\n1\n2\n3') + }) + + it('should get diff for added #2', () => { + applyEdits('1\n2\n3', '1\n2\n4\n3') + }) + + it('should get diff for added #3', () => { + applyEdits('1\n2\n3', '4\n1\n2\n3\n5') + }) + + it('should get diff for added #4', () => { + applyEdits(' ', ' ') + }) + + it('should get diff for replace', () => { + applyEdits('1\n2\n3\n4\n5', '1\n5\n3\n6\n7') + }) + + it('should get diff for replace #1', () => { + applyEdits('1\n2\n3\n4\n5', '1\n5\n3\n6\n7') + }) + + it('should get diff for remove #0', () => { + applyEdits('1\n2\n3\n4', '1\n4') + }) + + it('should get diff for remove #1', () => { + applyEdits('1\n2\n3\n4', '1') + }) + + it('should get diff for remove #2', () => { + applyEdits(' ', ' ') + }) + + it('should prefer cursor position for change', async () => { + let res = getChange(' int n', ' n', 0) + expect(res).toEqual({ start: 1, end: 5, newText: '' }) + res = getChange(' int n', ' n') + expect(res).toEqual({ start: 0, end: 4, newText: '' }) + }) + + it('should prefer next line for change', async () => { + let res = getChange('a\nb', 'a\nc\nb') + expect(res).toEqual({ start: 2, end: 2, newText: 'c\n' }) + applyEdits('a\nb', 'a\nc\nb') + }) + + it('should prefer previous line for change', async () => { + let res = getChange('\n\na', '\na') + expect(res).toEqual({ start: 0, end: 1, newText: '' }) + }) + + it('should consider cursor', () => { + let res = getChange('\n\n\n', '\n\n\n\n', 1) + expect(res).toEqual({ start: 2, end: 2, newText: '\n' }) + }) + + it('should get minimal diff', () => { + let res = getChange('foo\nbar', 'fab\nbar', 2) + expect(res).toEqual({ start: 1, end: 3, newText: 'ab' }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/document.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/document.test.ts new file mode 100644 index 00000000..11535de4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/document.test.ts @@ -0,0 +1,413 @@ +import fs from 'fs' +import path from 'path' +import { Neovim } from '@chemzqm/neovim' +import { Position, Range, TextEdit } from 'vscode-languageserver-protocol' +import workspace from '../../workspace' +import helper from '../helper' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { Disposable } from '@chemzqm/neovim/lib/api/Buffer' +import { disposeAll } from '../../util' +import Document from '../../model/document' +import { URI } from 'vscode-uri' + +let nvim: Neovim +jest.setTimeout(5000) + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('properties', () => { + it('should parse iskeyword', async () => { + let doc = await helper.createDocument() + await nvim.setLine('foo bar') + doc.forceSync() + let words = doc.words + expect(words).toEqual(['foo', 'bar']) + }) + + it('should applyEdits', async () => { + let doc = await helper.createDocument() + let edits: TextEdit[] = [] + edits.push({ + range: Range.create(0, 0, 0, 0), + newText: 'a\n' + }) + edits.push({ + range: Range.create(0, 0, 0, 0), + newText: 'b\n' + }) + await doc.applyEdits(edits) + let content = doc.getDocumentContent() + expect(content).toBe('a\nb\n\n') + }) + + it('should applyEdits with changed lines', async () => { + let doc = await helper.createDocument() + await nvim.setLine('a') + await doc.patchChange() + let edits: TextEdit[] = [] + edits.push({ + range: Range.create(0, 1, 0, 1), + newText: `\n\nd` + }) + await doc.applyEdits(edits) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['a', '', 'd']) + }) + + it('should parse iskeyword of character range', async () => { + await nvim.setOption('iskeyword', 'a-z,A-Z,48-57,_') + let doc = await helper.createDocument() + let opt = await nvim.getOption('iskeyword') + expect(opt).toBe('a-z,A-Z,48-57,_') + await nvim.setLine('foo bar') + doc.forceSync() + await helper.wait(100) + let words = doc.words + expect(words).toEqual(['foo', 'bar']) + }) + + it('should get word range', async () => { + await helper.createDocument() + await nvim.setLine('foo bar') + await helper.wait(30) + let doc = await workspace.document + let range = doc.getWordRangeAtPosition({ line: 0, character: 0 }) + expect(range).toEqual(Range.create(0, 0, 0, 3)) + range = doc.getWordRangeAtPosition({ line: 0, character: 3 }) + expect(range).toBeNull() + range = doc.getWordRangeAtPosition({ line: 0, character: 4 }) + expect(range).toEqual(Range.create(0, 4, 0, 7)) + range = doc.getWordRangeAtPosition({ line: 0, character: 7 }) + expect(range).toBeNull() + }) + + it('should get symbol ranges', async () => { + let doc = await helper.createDocument() + await nvim.setLine('foo bar foo') + let ranges = doc.getSymbolRanges('foo') + expect(ranges.length).toBe(2) + }) + + it('should get localify bonus', async () => { + let doc = await helper.createDocument() + let { buffer } = doc + await buffer.setLines(['context content clearTimeout', '', 'product confirm'], + { start: 0, end: -1, strictIndexing: false }) + await helper.wait(100) + let pos: Position = { line: 1, character: 0 } + let res = doc.getLocalifyBonus(pos, pos) + expect(res.has('confirm')).toBe(true) + expect(res.has('clearTimeout')).toBe(true) + }) + + it('should get current line', async () => { + let doc = await helper.createDocument() + let { buffer } = doc + await buffer.setLines(['first line', 'second line'], + { start: 0, end: -1, strictIndexing: false }) + await helper.wait(30) + let line = doc.getline(1, true) + expect(line).toBe('second line') + }) + + it('should get cached line', async () => { + let doc = await helper.createDocument() + let { buffer } = doc + await buffer.setLines(['first line', 'second line'], + { start: 0, end: -1, strictIndexing: false }) + await helper.wait(30) + doc.forceSync() + let line = doc.getline(0, false) + expect(line).toBe('first line') + }) + + it('should get variable form buffer', async () => { + await nvim.command('autocmd BufNewFile,BufRead * let b:coc_enabled = 1') + let doc = await helper.createDocument() + let val = doc.getVar('enabled') + expect(val).toBe(1) + }) + + it('should attach change events', async () => { + let doc = await helper.createDocument() + await nvim.setLine('abc') + await helper.wait(50) + let content = doc.getDocumentContent() + expect(content.indexOf('abc')).toBe(0) + }) + + it('should not attach change events when b:coc_enabled is false', async () => { + await nvim.command('autocmd BufNewFile,BufRead *.dis let b:coc_enabled = 0') + let doc = await helper.createDocument('a.dis') + let val = doc.getVar('enabled', 0) + expect(val).toBe(0) + await nvim.setLine('abc') + await helper.wait(50) + let content = doc.getDocumentContent() + expect(content.indexOf('abc')).toBe(-1) + }) + + it('should get lineCount, previewwindow, winid', async () => { + let doc = await helper.createDocument() + let { lineCount, winid, previewwindow } = doc + expect(lineCount).toBe(1) + expect(winid != -1).toBe(true) + expect(previewwindow).toBe(false) + }) + + it('should set filetype', async () => { + let doc = await helper.createDocument() + doc.setFiletype('javascript.jsx') + expect(doc.filetype).toBe('javascriptreact') + doc.setFiletype('typescript.jsx') + expect(doc.filetype).toBe('typescriptreact') + doc.setFiletype('typescript.tsx') + expect(doc.filetype).toBe('typescriptreact') + doc.setFiletype('tex') + expect(doc.filetype).toBe('latex') + doc.setFiletype('foo') + expect(doc.filetype).toBe('foo') + }) +}) + +describe('synchronize', () => { + it('should synchronize on lines change', async () => { + let document = await helper.createDocument() + let doc = TextDocument.create('untitled:1', 'txt', 1, document.getDocumentContent()) + let disposables = [] + document.onDocumentChange(e => { + TextDocument.update(doc, e.contentChanges, 2) + }, null, disposables) + // document.on + await nvim.setLine('abc') + document.forceSync() + expect(doc.getText()).toBe('abc\n') + disposeAll(disposables) + }) + + it('should synchronize changes after applyEdits', async () => { + let document = await helper.createDocument() + let doc = TextDocument.create('untitled:1', 'txt', 1, document.getDocumentContent()) + let disposables = [] + document.onDocumentChange(e => { + TextDocument.update(doc, e.contentChanges, e.textDocument.version) + }, null, disposables) + await nvim.setLine('abc') + await document.patchChange() + await document.applyEdits([TextEdit.insert({ line: 0, character: 0 }, 'd')]) + expect(doc.getText()).toBe('dabc\n') + disposeAll(disposables) + }) +}) + +describe('recreate', () => { + async function assertDocument(fn: (doc: Document) => Promise): Promise { + let disposables: Disposable[] = [] + let fsPath = path.join(__dirname, 'document.txt') + fs.writeFileSync(fsPath, '{\nfoo\n}\n', 'utf8') + await helper.edit(fsPath) + let document = await workspace.document + document.forceSync() + let doc = TextDocument.create(document.uri, 'txt', document.version, document.getDocumentContent()) + let uri = doc.uri + workspace.onDidOpenTextDocument(e => { + if (e.uri == uri) { + doc = TextDocument.create(e.uri, 'txt', e.version, e.getText()) + } + }, null, disposables) + workspace.onDidCloseTextDocument(e => { + if (e.uri == doc.uri) doc = null + }, null, disposables) + workspace.onDidChangeTextDocument(e => { + TextDocument.update(doc, e.contentChanges, e.textDocument.version) + }, null, disposables) + await fn(document) + document = await workspace.document + document.forceSync() + let text = document.getDocumentContent() + expect(doc).toBeDefined() + expect(doc.getText()).toBe(text) + disposeAll(disposables) + fs.unlinkSync(fsPath) + } + + it('should synchronize after make changes', async () => { + await assertDocument(async () => { + await nvim.call('setline', [1, 'a']) + await nvim.call('setline', [2, 'b']) + }) + }) + + it('should synchronize after edit', async () => { + await assertDocument(async doc => { + let fsPath = URI.parse(doc.uri).fsPath + fs.writeFileSync(fsPath, '{\n}\n', 'utf8') + await nvim.command('edit') + await helper.wait(50) + await nvim.call('deletebufline', [doc.bufnr, 1]) + doc = await workspace.document + let content = doc.getDocumentContent() + expect(content).toBe('}\n') + }) + }) + + it('should synchronize after force edit', async () => { + await assertDocument(async doc => { + let fsPath = URI.parse(doc.uri).fsPath + fs.writeFileSync(fsPath, '{\n}\n', 'utf8') + await nvim.command('edit') + await helper.wait(50) + await nvim.call('deletebufline', [doc.bufnr, 1]) + doc = await workspace.document + let content = doc.getDocumentContent() + expect(content).toBe('}\n') + }) + }) +}) + +describe('getEndOffset', () => { + it('should getEndOffset #1', async () => { + let doc = await helper.createDocument() + await doc.buffer.setLines(['', ''], { start: 0, end: -1, strictIndexing: false }) + await helper.wait(30) + let end = doc.getEndOffset(1, 1, false) + expect(end).toBe(2) + end = doc.getEndOffset(2, 1, false) + expect(end).toBe(1) + }) + + it('should getEndOffset #2', async () => { + let doc = await helper.createDocument() + await doc.buffer.setLines(['a', ''], { start: 0, end: -1, strictIndexing: false }) + await helper.wait(30) + let end = doc.getEndOffset(1, 1, false) + expect(end).toBe(2) + }) + + it('should getEndOffset #3', async () => { + let doc = await helper.createDocument() + await doc.buffer.setLines(['a'], { start: 0, end: -1, strictIndexing: false }) + await helper.wait(30) + let end = doc.getEndOffset(1, 2, false) + expect(end).toBe(1) + }) + + it('should getEndOffset #4', async () => { + let doc = await helper.createDocument() + await doc.buffer.setLines(['你好', ''], { start: 0, end: -1, strictIndexing: false }) + await helper.wait(30) + let end = doc.getEndOffset(1, 1, false) + expect(end).toBe(3) + end = doc.getEndOffset(1, 1, true) + expect(end).toBe(4) + }) +}) + +describe('applyEdits', () => { + it('should synchronize content added', async () => { + let doc = await helper.createDocument() + let buffer = doc.buffer + await doc.buffer.setLines(['foo f'], { start: 0, end: -1, strictIndexing: false }) + await doc.synchronize() + await nvim.command('normal! gg^2l') + await nvim.input('a') + await buffer.detach() + await nvim.input('r') + await doc.applyEdits([{ + range: Range.create(0, 0, 0, 5), + newText: 'foo foo' + }]) + await helper.wait(100) + let line = await nvim.line + expect(line).toBe('foor foo') + }) + + it('should synchronize content delete', async () => { + let doc = await helper.createDocument() + let buffer = doc.buffer + await doc.buffer.setLines(['foo f'], { start: 0, end: -1, strictIndexing: false }) + await doc.synchronize() + await nvim.command('normal! gg^2l') + await nvim.input('a') + await buffer.detach() + await nvim.input('') + await doc.applyEdits([{ + range: Range.create(0, 0, 0, 5), + newText: 'foo foo' + }]) + await helper.wait(100) + let line = await nvim.line + expect(line).toBe('fo foo') + }) +}) + +describe('highlights', () => { + it('should add highlights to document', async () => { + await helper.createDocument() + let buf = await nvim.buffer + await buf.setLines(['你好', 'world'], { start: 0, end: -1, strictIndexing: false }) + let ranges = [ + Range.create(0, 0, 0, 2), + Range.create(1, 0, 1, 3) + ] + let ns = await nvim.createNamespace('coc-highlight') + nvim.pauseNotification() + buf.highlightRanges('highlight', 'Search', ranges) + await nvim.resumeNotification() + let markers = await helper.getMarkers(buf.id, ns) + expect(markers.length).toBe(2) + nvim.pauseNotification() + buf.clearNamespace('highlight') + await nvim.resumeNotification() + markers = await helper.getMarkers(buf.id, ns) + expect(markers.length).toBe(0) + }) + + it('should add/clear highlights of current window', async () => { + await helper.createDocument() + let buf = await nvim.buffer + await buf.setLines(['你好', 'world'], { start: 0, end: -1, strictIndexing: false }) + let win = await nvim.window + let ranges = [ + Range.create(0, 0, 0, 2), + Range.create(1, 0, 1, 3) + ] + let res = await win.highlightRanges('Search', ranges) + expect(res.length).toBe(2) + let matches = await nvim.call('getmatches', [win.id]) + expect(matches.length).toBe(2) + nvim.pauseNotification() + win.clearMatchGroup('Search') + await nvim.resumeNotification() + matches = await nvim.call('getmatches', [win.id]) + expect(matches.length).toBe(0) + }) + + it('should clear matches by ids', async () => { + await helper.createDocument() + let buf = await nvim.buffer + await buf.setLines(['你好', 'world'], { start: 0, end: -1, strictIndexing: false }) + let win = await nvim.window + let ranges = [ + Range.create(0, 0, 0, 2), + Range.create(1, 0, 1, 3) + ] + let ids = await win.highlightRanges('Search', ranges) + nvim.pauseNotification() + win.clearMatches(ids) + await nvim.resumeNotification() + let matches = await nvim.call('getmatches', [win.id]) + expect(matches.length).toBe(0) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/events.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/events.test.ts new file mode 100644 index 00000000..653f6e2a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/events.test.ts @@ -0,0 +1,67 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import events from '../../events' +import { disposeAll } from '../../util' +let disposables: Disposable[] = [] +import helper from '../helper' + +let nvim: Neovim + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + disposeAll(disposables) +}) + +describe('register handler', () => { + it('should register single handler', async () => { + let fn = jest.fn() + let obj = {} + let disposable = events.on('BufEnter', fn, obj) + disposables.push(disposable) + await events.fire('BufEnter', ['a', 'b']) + expect(fn).toBeCalledWith('a', 'b') + }) + + it('should register multiple events', async () => { + let fn = jest.fn() + let disposable = events.on(['TaskExit', 'TaskStderr'], fn) + disposables.push(disposable) + await events.fire('TaskExit', []) + await events.fire('TaskStderr', []) + expect(fn).toBeCalledTimes(2) + }) + + it('should resolve after timeout', async () => { + let fn = (): Promise => new Promise(resolve => { + setTimeout(() => { + resolve() + }, 100) + }) + let disposable = events.on('FocusGained', fn, {}) + disposables.push(disposable) + let ts = Date.now() + await events.fire('FocusGained', []) + expect(Date.now() - ts >= 100).toBe(true) + }) + + it('should emit TextInsert after TextChangedI', async () => { + let arr: string[] = [] + events.on('TextInsert', () => { + arr.push('insert') + }, null, disposables) + events.on('TextChangedI', () => { + arr.push('change') + }, null, disposables) + await nvim.input('ia') + await helper.wait(300) + expect(arr).toEqual(['change', 'insert']) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/extensions.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/extensions.test.ts new file mode 100644 index 00000000..2fd8260c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/extensions.test.ts @@ -0,0 +1,221 @@ +import { Neovim } from '@chemzqm/neovim' +import fs from 'fs' +import path from 'path' +import events from '../../events' +import extensions, { API, Extension } from '../../extensions' +import helper from '../helper' +import { v1 as uuidv1 } from 'uuid' + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +jest.setTimeout(30000) + +describe('extensions', () => { + + it('should load global extensions', async () => { + let stat = extensions.getExtensionState('test') + expect(stat).toBe('activated') + }) + + it('should filter global extensions', async () => { + let res = extensions.filterGlobalExtensions(['test', 'foo']) + expect(res).toEqual(['foo']) + }) + + it('should load local extensions from &rtp', async () => { + let folder = path.resolve(__dirname, '../extensions/vim/local') + await nvim.command(`set runtimepath^=${folder}`) + await helper.wait(300) + let stat = extensions.getExtensionState('local') + expect(stat).toBe('activated') + }) + + it('should install/uninstall npm extension', async () => { + await extensions.installExtensions(['coc-omni']) + let folder = path.join(__dirname, '../extensions/coc-omni') + let exists = fs.existsSync(folder) + expect(exists).toBe(true) + await helper.wait(200) + await extensions.uninstallExtension(['coc-omni']) + exists = fs.existsSync(folder) + expect(exists).toBe(false) + }) + + it('should install/uninstall extension by url', async () => { + await extensions.installExtensions(['https://github.com/hollowtree/vscode-vue-snippets']) + let folder = path.join(__dirname, '../extensions/vue-snippets') + let exists = fs.existsSync(folder) + expect(exists).toBe(true) + await extensions.uninstallExtension(['vue-snippets']) + exists = fs.existsSync(folder) + expect(exists).toBe(false) + }) + + it('should install/uninstall extension by url with branch', async () => { + await extensions.installExtensions(['https://github.com/sdras/vue-vscode-snippets@main']) + let folder = path.join(__dirname, '../extensions/vue-vscode-snippets') + let exists = fs.existsSync(folder) + expect(exists).toBe(true) + await extensions.uninstallExtension(['vue-vscode-snippets']) + exists = fs.existsSync(folder) + expect(exists).toBe(false) + }) + + it('should parse extension info', () => { + const installer = extensions.installer + const scoped = installer('@yaegassy/coc-intelephense').info + expect(scoped.name).toBe('@yaegassy/coc-intelephense') + + const scopedVer = installer('@yaegassy/coc-intelephense@0.2.1').info + expect(scopedVer.name).toBe('@yaegassy/coc-intelephense') + expect(scopedVer.version).toBe('0.2.1') + }) + + it('should get all extensions', () => { + let list = extensions.all + expect(Array.isArray(list)).toBe(true) + }) + + it('should get extensions stat', async () => { + let stats = await extensions.getExtensionStates() + expect(stats.length).toBeGreaterThan(0) + }) + + it('should toggle extension', async () => { + await extensions.toggleExtension('test') + let stat = extensions.getExtensionState('test') + expect(stat).toBe('disabled') + await extensions.toggleExtension('test') + stat = extensions.getExtensionState('test') + expect(stat).toBe('activated') + }) + + it('should reload extension', async () => { + await extensions.reloadExtension('test') + await helper.wait(100) + let stat = extensions.getExtensionState('test') + expect(stat).toBe('activated') + }) + + it('should has extension', () => { + let res = extensions.has('test') + expect(res).toBe(true) + }) + + it('should be activated', async () => { + let res = extensions.has('test') + expect(res).toBe(true) + }) + + it('should activate & deactivate extension', async () => { + await extensions.deactivate('test') + let stat = extensions.getExtensionState('test') + expect(stat).toBe('loaded') + await extensions.activate('test') + stat = extensions.getExtensionState('test') + expect(stat).toBe('activated') + }) + + it('should call extension API', async () => { + let res = await extensions.call('test', 'echo', ['5']) + expect(res).toBe('5') + let p: string = await extensions.call('test', 'asAbsolutePath', ['..']) + expect(p.endsWith('extensions')).toBe(true) + }) + + it('should get extension API', () => { + let res = extensions.getExtensionApi('test') as any + expect(typeof res.echo).toBe('function') + }) + + it('should load single file extension', async () => { + let filepath = path.join(__dirname, '../extensions/root.js') + await extensions.loadExtensionFile(filepath) + expect(extensions.has('single-root')).toBe(true) + }) +}) + +describe('extensions active events', () => { + + function createExtension(event: string): Extension { + let id = uuidv1() + let isActive = false + let packageJSON = { + name: id, + activationEvents: [event] + } + let ext = { + id, + packageJSON, + exports: void 0, + extensionPath: '', + activate: async () => { + isActive = true + } + } as any + Object.defineProperty(ext, 'isActive', { + get: () => isActive + }) + extensions.registerExtension(ext, () => { + isActive = false + }) + return ext + } + + it('should activate on language', async () => { + let ext = createExtension('onLanguage:javascript') + expect(ext.isActive).toBe(false) + await nvim.command('edit /tmp/a.js') + await helper.wait(300) + expect(ext.isActive).toBe(true) + ext = createExtension('onLanguage:javascript') + expect(ext.isActive).toBe(true) + }) + + it('should activate on command', async () => { + let ext = createExtension('onCommand:test.echo') + await events.fire('Command', ['test.echo']) + await helper.wait(30) + expect(ext.isActive).toBe(true) + }) + + it('should activate on workspace contains', async () => { + let ext = createExtension('workspaceContains:package.json') + let root = path.resolve(__dirname, '../../..') + await nvim.command(`edit ${path.join(root, 'file.js')}`) + await helper.wait(100) + expect(ext.isActive).toBe(true) + }) + + it('should activate on file system', async () => { + let ext = createExtension('onFileSystem:zip') + await nvim.command('edit zip:///a') + await helper.wait(30) + expect(ext.isActive).toBe(true) + ext = createExtension('onFileSystem:zip') + expect(ext.isActive).toBe(true) + }) +}) + +describe('extension properties', () => { + it('should get extensionPath', () => { + let ext = extensions.getExtension('test') + let p = ext.extension.extensionPath + expect(p.endsWith('test')).toBe(true) + }) + + it('should deactivate', async () => { + let ext = extensions.getExtension('test') + await ext.deactivate() + expect(ext.extension.isActive).toBe(false) + await extensions.activate('test') + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/fetch.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/fetch.test.ts new file mode 100644 index 00000000..7a66a9f9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/fetch.test.ts @@ -0,0 +1,87 @@ +import fs from 'fs-extra' +import os from 'os' +import path from 'path' +import { parse } from 'url' +import download from '../../model/download' +import fetch, { getAgent } from '../../model/fetch' +import helper from '../helper' + +beforeAll(async () => { + await helper.setup() +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + helper.updateConfiguration('http.proxy', '') + await helper.reset() +}) + +describe('fetch', () => { + + it('should fetch json', async () => { + let res = await fetch('https://nodejs.org/dist/index.json') + expect(Array.isArray(res)).toBe(true) + }, 10000) + + it('should fetch buffer', async () => { + let res = await fetch('https://www.npmjs.com/', { buffer: true }) + expect(Buffer.isBuffer(res)).toBe(true) + }) + + it('should throw on request error', async () => { + let err + try { + await fetch('http://not_exists_org') + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should report valid proxy', async () => { + let agent = getAgent(parse('http://google.com'), { proxyUrl: 'domain.com:1234' }) + expect(agent).toBe(null) + + agent = getAgent(parse('http://google.com'), { proxyUrl: 'https://domain.com:1234' }) + let proxy = (agent as any).proxy + expect(proxy.host).toBe('domain.com') + expect(proxy.port).toBe(1234) + + agent = getAgent(parse('http://google.com'), { proxyUrl: 'http://user:pass@domain.com:1234' }) + proxy = (agent as any).proxy + expect(proxy.host).toBe('domain.com') + expect(proxy.port).toBe(1234) + expect(proxy.auth).toBe('user:pass') + }) +}) + +describe('download', () => { + it('should download binary file', async () => { + let url = 'https://registry.npmjs.org/coc-pairs/-/coc-pairs-1.2.13.tgz' + let tmpFolder = await fs.mkdtemp(path.join(os.tmpdir(), 'coc-test')) + let res = await download(url, { dest: tmpFolder }) + expect(fs.existsSync(res)).toBe(true) + await fs.remove(tmpFolder) + }, 10000) + + it('should download tgz', async () => { + let url = 'https://registry.npmjs.org/coc-pairs/-/coc-pairs-1.2.13.tgz' + let tmpFolder = await fs.mkdtemp(path.join(os.tmpdir(), 'coc-test')) + await download(url, { dest: tmpFolder, extract: 'untar' }) + let file = path.join(tmpFolder, 'package.json') + expect(fs.existsSync(file)).toBe(true) + await fs.remove(tmpFolder) + }, 10000) + + it('should extract zip file', async () => { + let url = 'https://codeload.github.com/chemzqm/vimrc/zip/master' + let tmpFolder = await fs.mkdtemp(path.join(os.tmpdir(), 'coc-test')) + await download(url, { dest: tmpFolder, extract: 'unzip' }) + let folder = path.join(tmpFolder, 'vimrc-master') + expect(fs.existsSync(folder)).toBe(true) + await fs.remove(tmpFolder) + }, 30000) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/floatFactory.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/floatFactory.test.ts new file mode 100644 index 00000000..c978c135 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/floatFactory.test.ts @@ -0,0 +1,276 @@ +import { Neovim } from '@chemzqm/neovim' +import FloatFactory from '../../model/floatFactory' +import snippetManager from '../../snippets/manager' +import { Documentation } from '../../markdown/index' +import helper from '../helper' + +let nvim: Neovim +let floatFactory: FloatFactory +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + floatFactory = new FloatFactory(nvim) +}) + +afterAll(async () => { + await helper.shutdown() + floatFactory.dispose() +}) + +afterEach(async () => { + floatFactory.close() + await helper.reset() +}) + +describe('FloatFactory', () => { + describe('show()', () => { + it('should show window', async () => { + expect(floatFactory.window).toBe(null) + expect(floatFactory.buffer).toBe(null) + expect(floatFactory.bufnr).toBe(0) + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'f'.repeat(81) + }] + await floatFactory.show(docs) + expect(floatFactory.window).toBeDefined() + expect(floatFactory.buffer).toBeDefined() + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(1) + await floatFactory.show([{ filetype: 'txt', content: '' }]) + expect(floatFactory.window).toBe(null) + }) + + it('should create window', async () => { + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'f'.repeat(81) + }] + await floatFactory.create(docs) + expect(floatFactory.window).toBeDefined() + }) + + it('should catch error on create', async () => { + let fn = floatFactory.unbind + floatFactory.unbind = () => { + throw new Error('bad') + } + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'f'.repeat(81) + }] + await floatFactory.show(docs) + floatFactory.unbind = fn + let msg = await helper.getCmdline() + expect(msg).toMatch('bad') + }) + + it('should show only one window', async () => { + await helper.edit() + await nvim.setLine('foo') + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'foo' + }] + await Promise.all([ + floatFactory.show(docs), + floatFactory.show(docs) + ]) + let count = 0 + let wins = await nvim.windows + for (let win of wins) { + let isFloat = await win.getVar('float') + if (isFloat) count++ + } + expect(count).toBe(1) + }) + + it('should close window when close called after create', async () => { + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'f' + }] + let p = floatFactory.show(docs) + await helper.wait(1) + floatFactory.close() + await p + let activated = await floatFactory.activated() + expect(activated).toBe(false) + }) + + it('should not create on visual mode', async () => { + await helper.createDocument() + await nvim.call('cursor', [1, 1]) + await nvim.setLine('foo') + await nvim.command('normal! v$') + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'f' + }] + await floatFactory.show(docs) + expect(floatFactory.window).toBe(null) + }) + }) + + describe('checkRetrigger', () => { + it('should check retrigger', async () => { + expect(floatFactory.checkRetrigger(99)).toBe(false) + let bufnr = await nvim.call('bufnr', ['%']) + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'f' + }] + await floatFactory.show(docs) + expect(floatFactory.checkRetrigger(99)).toBe(false) + expect(floatFactory.checkRetrigger(bufnr)).toBe(true) + }) + }) + + describe('options', () => { + it('should config maxHeight and maxWidth', async () => { + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'f'.repeat(80) + '\nbar', + }] + await floatFactory.show(docs, { + maxWidth: 20, + maxHeight: 1 + }) + let win = floatFactory.window + expect(win).toBeDefined() + let width = await win.width + let height = await win.height + expect(width).toBe(19) + expect(height).toBe(1) + }) + + it('should set border, title, highlight, borderhighlight, cursorline', async () => { + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'foo\nbar' + }] + await floatFactory.show(docs, { + border: [1, 1, 1, 1], + title: 'title', + highlight: 'Pmenu', + borderhighlight: 'MoreMsg', + cursorline: true + }) + let activated = await floatFactory.activated() + expect(activated).toBe(true) + }) + + it('should respect prefer top', async () => { + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'foo\nbar' + }] + await nvim.call('append', [1, ['', '', '']]) + await nvim.command('exe 4') + await floatFactory.show(docs, { preferTop: true }) + let win = await helper.getFloat() + expect(win).toBeDefined() + let pos = await nvim.call('nvim_win_get_position', [win.id]) + expect(pos).toEqual([1, 0]) + }) + }) + + describe('events', () => { + it('should hide on BufEnter', async () => { + await helper.edit() + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'foo' + }] + await floatFactory.show(docs) + await nvim.command(`edit foo`) + await helper.wait(50) + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(0) + }) + + it('should hide on CursorMoved', async () => { + await helper.createDocument() + await nvim.setLine('foo') + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'foo' + }] + await floatFactory.show(docs) + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(1) + await helper.wait(30) + await nvim.input('$') + await helper.wait(200) + hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(0) + }) + + it('should not hide when cursor position not changed', async () => { + await helper.edit() + await nvim.setLine('foo') + let cursor = await nvim.eval("[line('.'), col('.')]") + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'foo' + }] + await floatFactory.show(docs) + await nvim.call('cursor', [1, 2]) + await helper.wait(10) + await nvim.call('cursor', cursor) + await helper.wait(200) + let hasFloat = await nvim.call('coc#float#has_float') + expect(hasFloat).toBe(1) + }) + + it('should preserve float when autohide disable and not overlap with pum', async () => { + await helper.createDocument() + let buf = await nvim.buffer + await buf.setLines(['foo', '', '', '', 'f'], { start: 0, end: -1, strictIndexing: false }) + await nvim.call('cursor', [5, 2]) + await nvim.input('A') + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'foo' + }] + await floatFactory.show(docs, { + preferTop: true, + autoHide: false + }) + let activated = await floatFactory.activated() + expect(activated).toBe(true) + await nvim.input('') + await helper.wait(100) + let pumvisible = await helper.pumvisible() + expect(pumvisible).toBe(true) + activated = await floatFactory.activated() + expect(activated).toBe(true) + }) + }) + + it('should allow select mode', async () => { + await helper.createDocument() + await snippetManager.insertSnippet('${1:foo}') + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'foo' + }] + await floatFactory.show(docs) + let { mode } = await nvim.mode + expect(mode).toBe('s') + }) + + it('should get active state of window', async () => { + let docs: Documentation[] = [{ + filetype: 'markdown', + content: 'f'.repeat(81) + }] + await floatFactory.show(docs) + let res = await floatFactory.activated() + expect(res).toBe(true) + await nvim.call('coc#float#close_all') + res = await floatFactory.activated() + expect(res).toBe(false) + }) + +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/memos.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/memos.test.ts new file mode 100644 index 00000000..76af1232 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/memos.test.ts @@ -0,0 +1,45 @@ +import Memos from '../../model/memos' +import os from 'os' +import path from 'path' +import fs from 'fs' + +let filepath = path.join(os.tmpdir(), 'test') +let memos: Memos +beforeEach(() => { + memos = new Memos(filepath) +}) + +afterEach(() => { + if (fs.existsSync(filepath)) { + fs.unlinkSync(filepath) + } +}) + +describe('Memos', () => { + it('should udpate and get', async () => { + let memo = memos.createMemento('x') + await memo.update('foo.bar', 'memo') + let res = memo.get('foo.bar') + expect(res).toBe('memo') + }) + + it('should get value for key not exists', async () => { + let memo = memos.createMemento('y') + let res = memo.get('xyz') + expect(res).toBeUndefined() + }) + + it('should use defaultValue when not exists', async () => { + let memo = memos.createMemento('y') + let res = memo.get('f.o.o', 'default') + expect(res).toBe('default') + }) + + it('should update multiple values', async () => { + let memo = memos.createMemento('x') + await memo.update('foo', 'x') + await memo.update('bar', 'y') + expect(memo.get('foo')).toBe('x') + expect(memo.get('bar')).toBe('y') + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/menu.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/menu.test.ts new file mode 100644 index 00000000..015a3bce --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/menu.test.ts @@ -0,0 +1,119 @@ +import { Neovim } from '@chemzqm/neovim' +import helper from '../helper' +import Menu from '../../model/menu' + +let nvim: Neovim +let menu: Menu + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + menu.dispose() + await helper.reset() +}) + +describe('Menu', () => { + it('should cancel by ', async () => { + menu = new Menu(nvim, { items: ['foo', 'bar'] }) + let p = new Promise(resolve => { + menu.onDidClose(v => { + resolve(v) + }) + }) + await menu.show() + await helper.wait(30) + await nvim.input('') + let res = await p + expect(res).toBe(-1) + }) + + it('should select by CR', async () => { + menu = new Menu(nvim, { items: ['foo', 'bar'] }) + let p = new Promise(resolve => { + menu.onDidClose(v => { + resolve(v) + }) + }) + await menu.show() + await helper.wait(30) + await nvim.input('j') + await helper.wait(30) + await nvim.input('') + let res = await p + expect(res).toBe(1) + }) + + it('should ignore invalid index', async () => { + menu = new Menu(nvim, { items: ['foo', 'bar'] }) + await menu.show() + await helper.wait(30) + await nvim.input('0') + await helper.wait(30) + let exists = await nvim.call('coc#float#has_float', []) + expect(exists).toBe(1) + }) + + it('should select by index number', async () => { + menu = new Menu(nvim, { items: ['foo', 'bar'] }) + let p = new Promise(resolve => { + menu.onDidClose(v => { + resolve(v) + }) + }) + await menu.show() + await helper.wait(30) + await nvim.input('1') + let res = await p + expect(res).toBe(0) + }) + + it('should navigate by j, k, g & G', async () => { + menu = new Menu(nvim, { items: ['one', 'two', 'three'] }) + await menu.show() + await helper.wait(50) + let id = await nvim.call('coc#float#get_float_win') + expect(id).toBeGreaterThan(0) + let win = nvim.createWindow(id) + await nvim.input('j') + await helper.wait(50) + let cursor = await win.cursor + expect(cursor[0]).toBe(2) + await nvim.input('k') + await helper.wait(50) + cursor = await win.cursor + expect(cursor[0]).toBe(1) + await nvim.input('G') + await helper.wait(50) + cursor = await win.cursor + expect(cursor[0]).toBe(3) + await nvim.input('g') + await helper.wait(50) + cursor = await win.cursor + expect(cursor[0]).toBe(1) + }) + + it('should select by numbers', async () => { + let selected: number + menu = new Menu(nvim, { items: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] }) + await menu.show() + let promise = new Promise(resolve => { + menu.onDidClose(n => { + selected = n + resolve(undefined) + }) + }) + await helper.wait(50) + await nvim.input('1') + await helper.wait(50) + await nvim.input('0') + await promise + expect(selected).toBe(9) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/mru.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/mru.test.ts new file mode 100644 index 00000000..4447c79b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/mru.test.ts @@ -0,0 +1,33 @@ +import Mru from '../../model/mru' +import os from 'os' +import fs from 'fs' +import path from 'path' +const root = fs.mkdtempSync(path.join(os.tmpdir(), 'coc-mru-')) + +describe('Mru', () => { + + it('should load items', async () => { + let mru = new Mru('test', root) + await mru.clean() + let res = await mru.load() + expect(res.length).toBe(0) + }) + + it('should add items', async () => { + let mru = new Mru('test', root) + await mru.add('a') + await mru.add('b') + let res = await mru.load() + expect(res.length).toBe(2) + await mru.clean() + }) + + it('should remove item', async () => { + let mru = new Mru('test', root) + await mru.add('a') + await mru.remove('a') + let res = await mru.load() + expect(res.length).toBe(0) + await mru.clean() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/outputChannel.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/outputChannel.test.ts new file mode 100644 index 00000000..f41ae1c0 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/outputChannel.test.ts @@ -0,0 +1,77 @@ +import { Neovim } from '@chemzqm/neovim' +import OutputChannel from '../../model/outputChannel' +import { wait } from '../../util' +import helper from '../helper' + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterEach(async () => { + await helper.reset() +}) + +afterAll(async () => { + await helper.shutdown() +}) + +describe('OutputChannel', () => { + test('outputChannel.show(true)', async () => { + await nvim.setLine('foo') + let c = new OutputChannel('0', nvim) + let bufnr = (await nvim.buffer).id + c.show(true) + await wait(100) + let nr = (await nvim.buffer).id + expect(bufnr).toBe(nr) + }) + + test('outputChannel.show(false)', async () => { + let c = new OutputChannel('1', nvim) + let bufnr = (await nvim.buffer).id + c.show() + await wait(100) + let nr = (await nvim.buffer).id + expect(bufnr).toBeLessThan(nr) + }) + + test('outputChannel.appendLine()', async () => { + let c = new OutputChannel('2', nvim) + c.show() + await wait(100) + let buf = await nvim.buffer + c.appendLine('foo') + await wait(500) + let lines = await buf.lines + expect(lines).toContain('foo') + }) + + test('outputChannel.append()', async () => { + let c = new OutputChannel('3', nvim) + c.show(false) + await wait(60) + c.append('foo') + c.append('bar') + await wait(500) + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines.join('\n')).toMatch('foo') + }) + + test('outputChannel.clear()', async () => { + let c = new OutputChannel('4', nvim) + c.show(false) + await wait(30) + let buf = await nvim.buffer + c.appendLine('foo') + c.appendLine('bar') + await wait(30) + c.clear() + await wait(30) + let lines = await buf.lines + let content = lines.join('') + expect(content).toBe('') + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/picker.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/picker.test.ts new file mode 100644 index 00000000..469f75df --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/picker.test.ts @@ -0,0 +1,157 @@ +import { CancellationTokenSource } from 'vscode-languageserver-protocol' +import { Neovim } from '@chemzqm/neovim' +import Picker, { QuickPickItem } from '../../model/picker' +import helper from '../helper' + +let nvim: Neovim +let picker: Picker + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + if (picker) picker.dispose() + picker = undefined + await helper.reset() +}) + +const items: QuickPickItem[] = [{ label: 'foo' }, { label: 'bar' }] + +describe('Picker create', () => { + it('should show dialog with buttons', async () => { + picker = new Picker(nvim, { title: 'title', items }) + let winid = await picker.show({ pickerButtons: true }) + expect(winid).toBeDefined() + let id = await nvim.call('coc#float#get_related', [winid, 'buttons']) + expect(id).toBeGreaterThan(0) + let res = await nvim.call('sign_getplaced', [picker.buffer.id, { lnum: 1 }]) + expect(res[0].signs).toBeDefined() + expect(res[0].signs[0].name).toBe('CocCurrentLine') + }) + + it('should cancel dialog when cancellation token requested', async () => { + let tokenSource = new CancellationTokenSource() + picker = new Picker(nvim, { title: 'title', items }, tokenSource.token) + let winid = await picker.show({ pickerButtons: true }) + expect(winid).toBeDefined() + tokenSource.cancel() + await helper.wait(50) + let res = await nvim.call('coc#float#valid', [winid]) + expect(res).toBe(0) + }) +}) + +describe('Picker key mappings', () => { + it('should toggle selection mouse click bracket', async () => { + picker = new Picker(nvim, { title: 'title', items }) + let winid = await picker.show() + await nvim.setVar('mouse_position', [winid, 1, 1]) + await nvim.input('') + await helper.wait(50) + let buf = picker.buffer + let lines = await buf.getLines({ start: 0, end: 1, strictIndexing: false }) + expect(lines[0]).toMatch(/^\[x\]/) + }) + + it('should change current line on mouse click label', async () => { + picker = new Picker(nvim, { title: 'title', items }) + let winid = await picker.show() + await nvim.setVar('mouse_position', [winid, 2, 4]) + await nvim.input('') + await helper.wait(50) + let buf = picker.buffer + let res = await nvim.call('sign_getplaced', [buf.id, { lnum: 2 }]) + expect(res[0].signs).toBeDefined() + expect(res[0].signs[0].name).toBe('CocCurrentLine') + }) + + it('should cancel by ', async () => { + await helper.createDocument() + picker = new Picker(nvim, { title: 'title', items }) + let winid = await picker.show({ pickerButtons: true }) + expect(winid).toBeDefined() + let fn = jest.fn() + picker.onDidClose(fn) + await nvim.eval(`feedkeys("\\", 'in')`) + await helper.wait(200) + expect(fn).toBeCalledTimes(1) + }) + + it('should confirm by ', async () => { + await helper.createDocument() + picker = new Picker(nvim, { title: 'title', items }) + let winid = await picker.show({ pickerButtons: true }) + expect(winid).toBeDefined() + let fn = jest.fn() + picker.onDidClose(fn) + await nvim.input('') + await helper.wait(100) + await nvim.input('') + await nvim.command('redraw') + await helper.wait(100) + expect(fn).toBeCalledWith([0]) + }) + + it('should move cursor by j, k, g & G', async () => { + await helper.createDocument() + picker = new Picker(nvim, { title: 'title', items }) + let winid = await picker.show({ pickerButtons: true }) + expect(winid).toBeDefined() + await nvim.input('j') + await helper.wait(100) + let res = await nvim.call('sign_getplaced', [picker.buffer.id]) + expect(res[0].signs[0].lnum).toBe(2) + await nvim.input('k') + await helper.wait(100) + res = await nvim.call('sign_getplaced', [picker.buffer.id]) + expect(res[0].signs[0].lnum).toBe(1) + await nvim.input('G') + await helper.wait(100) + res = await nvim.call('sign_getplaced', [picker.buffer.id]) + expect(res[0].signs[0].lnum).toBe(2) + await nvim.input('g') + await helper.wait(100) + res = await nvim.call('sign_getplaced', [picker.buffer.id]) + expect(res[0].signs[0].lnum).toBe(1) + }) + + it('should toggle selection by ', async () => { + await helper.createDocument() + picker = new Picker(nvim, { title: 'title', items }) + let winid = await picker.show({ pickerButtons: true }) + expect(winid).toBeDefined() + let fn = jest.fn() + picker.onDidClose(fn) + await nvim.input('') + await helper.wait(100) + await nvim.command('redraw') + let lines = await nvim.call('getbufline', [picker.buffer.id, 1]) + expect(lines[0]).toMatch('[x]') + }) + + it('should scroll forward & backward', async () => { + await helper.createDocument() + let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'].map(s => { + return { label: s } + }) + picker = new Picker(nvim, { title: 'title', items }) + let winid = await picker.show({ maxHeight: 3 }) + expect(winid).toBeDefined() + await nvim.input('') + await helper.wait(100) + let info = await nvim.call('getwininfo', [winid]) + expect(info[0]).toBeDefined() + expect(info[0].topline).toBeGreaterThan(1) + await nvim.input('') + await helper.wait(100) + info = await nvim.call('getwininfo', [winid]) + expect(info[0]).toBeDefined() + expect(info[0].topline).toBe(1) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/plugin.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/plugin.test.ts new file mode 100644 index 00000000..30fec85e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/plugin.test.ts @@ -0,0 +1,49 @@ +import helper from '../helper' +import path from 'path' +import workspace from '../../workspace' +import { Neovim } from '@chemzqm/neovim' + +let nvim: Neovim + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('help tags', () => { + it('should generate help tags', async () => { + let root = workspace.pluginRoot + let dir = await nvim.call('fnameescape', path.join(root, 'doc')) + let res = await nvim.call('execute', `helptags ${dir}`) as string + expect(res.length).toBe(0) + }) + + it('should return jumpable', async () => { + let jumpable = await helper.plugin.cocAction('snippetCheck', false, true) + expect(jumpable).toBe(false) + }) + + it('should show CocInfo', async () => { + await nvim.call('CocActionAsync', ['showInfo']) + await helper.wait(300) + let line = await nvim.line + expect(line).toMatch('versions') + }) + + it('should ensure current document created', async () => { + await nvim.command('tabe tmp.js') + let res = await helper.plugin.cocAction('ensureDocument') + expect(res).toBe(true) + let bufnr = await nvim.call('bufnr', ['%']) + let doc = workspace.getDocument(bufnr) + expect(doc).toBeDefined() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/position.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/position.test.ts new file mode 100644 index 00000000..38d041e4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/position.test.ts @@ -0,0 +1,63 @@ +import { rangeInRange, positionInRange, comparePosition, isSingleLine, getChangedPosition, rangeOverlap } from '../../util/position' +import { Position, Range, TextEdit } from 'vscode-languageserver-types' + +function addPosition(position: Position, line: number, character: number): Position { + return Position.create(position.line + line, position.character + character) +} + +describe('Position', () => { + test('rangeInRange', () => { + let pos = Position.create(0, 0) + let r = Range.create(pos, pos) + expect(rangeInRange(r, r)).toBe(true) + expect(rangeInRange(r, Range.create(addPosition(pos, 1, 0), pos))).toBe(false) + }) + + test('rangeOverlap', () => { + let r = Range.create(0, 0, 0, 0) + expect(rangeOverlap(r, Range.create(0, 0, 0, 0))).toBe(false) + expect(rangeOverlap(Range.create(0, 0, 0, 10), Range.create(0, 1, 0, 2))).toBe(true) + expect(rangeOverlap(Range.create(0, 0, 0, 1), Range.create(0, 1, 0, 2))).toBe(false) + expect(rangeOverlap(Range.create(0, 1, 0, 2), Range.create(0, 0, 0, 1))).toBe(false) + expect(rangeOverlap(Range.create(0, 0, 0, 1), Range.create(0, 2, 0, 3))).toBe(false) + }) + + test('positionInRange', () => { + let pos = Position.create(0, 0) + let r = Range.create(pos, pos) + expect(positionInRange(pos, r)).toBe(0) + }) + + test('comparePosition', () => { + let pos = Position.create(0, 0) + expect(comparePosition(pos, pos)).toBe(0) + }) + + test('isSingleLine', () => { + let pos = Position.create(0, 0) + let r = Range.create(pos, pos) + expect(isSingleLine(r)).toBe(true) + }) + + test('getChangedPosition #1', () => { + let pos = Position.create(0, 0) + let edit = TextEdit.insert(pos, 'abc') + let res = getChangedPosition(pos, edit) + expect(res).toEqual({ line: 0, character: 3 }) + }) + + test('getChangedPosition #2', () => { + let pos = Position.create(0, 0) + let edit = TextEdit.insert(pos, 'a\nb\nc') + let res = getChangedPosition(pos, edit) + expect(res).toEqual({ line: 2, character: 1 }) + }) + + test('getChangedPosition #3', () => { + let pos = Position.create(0, 1) + let r = Range.create(addPosition(pos, 0, -1), pos) + let edit = TextEdit.replace(r, 'a\nb\n') + let res = getChangedPosition(pos, edit) + expect(res).toEqual({ line: 2, character: -1 }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/score.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/score.test.ts new file mode 100644 index 00000000..e49c8b28 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/score.test.ts @@ -0,0 +1,34 @@ +import { getMatchResult } from '../../util/score' + +describe('match result', () => { + + it('should respect filename #1', () => { + let res = getMatchResult('/coc.nvim/coc.txt', 'coc', 'coc.txt') + expect(res).toEqual({ score: 4, matches: [10, 11, 12] }) + }) + + it('should respect filename #2', () => { + let res = getMatchResult('/coc.nvim/Coc.txt', 'coc', 'Coc.txt') + expect(res).toEqual({ score: 3.5, matches: [10, 11, 12] }) + }) + + it('should respect filename #3', () => { + let res = getMatchResult('/coc.nvim/cdoxc.txt', 'coc', 'cdoxc.txt') + expect(res).toEqual({ score: 3, matches: [10, 12, 14] }) + }) + + it('should respect path start', () => { + let res = getMatchResult('/foob/baxr/xyz', 'fbx') + expect(res).toEqual({ score: 3, matches: [1, 6, 11] }) + }) + + it('should find fuzzy result', () => { + let res = getMatchResult('foobarzyx', 'fbx') + expect(res).toEqual({ score: 2, matches: [0, 3, 8] }) + }) + + it('should find fuzzy result #1', () => { + let res = getMatchResult('LICENSES/preferred/MIT', 'lsit') + expect(res).toEqual({ score: 1.4, matches: [0, 5, 20, 21] }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/settings.json b/vim-config/plugins/coc.nvim/src/__tests__/modules/settings.json new file mode 100644 index 00000000..55bb35f8 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/settings.json @@ -0,0 +1,12 @@ +{ + "foo.bar": 1, + "bar.foo": 2, + "schema": { + "https://example.com": "*.yaml" + }, + "servers": { + "c": { + "trace.server": "verbose" + } + } +} \ No newline at end of file diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/sources.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/sources.test.ts new file mode 100644 index 00000000..ccb6dfe6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/sources.test.ts @@ -0,0 +1,192 @@ +import { Neovim } from '@chemzqm/neovim' +import path from 'path' +import events from '../../events' +import workspace from '../../workspace' +import sources from '../../sources' +import { ISource, SourceType } from '../../types' +import helper from '../helper' + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('sources', () => { + + it('should do document enter', async () => { + let fn = jest.fn() + let source: ISource = { + name: 'enter', + enable: true, + priority: 0, + sourceType: SourceType.Service, + triggerCharacters: [], + doComplete: () => Promise.resolve({ items: [] }), + onEnter: fn + } + sources.addSource(source) + let buffer = await nvim.buffer + await events.fire('BufEnter', [buffer.id]) + expect(fn).toBeCalled() + sources.removeSource(source) + }) + + it('should return source states', () => { + let stats = sources.sourceStats() + expect(stats.length > 1).toBe(true) + }) + + it('should toggle source state', () => { + sources.toggleSource('around') + let s = sources.getSource('around') + expect(s.enable).toBe(false) + sources.toggleSource('around') + }) + + it('should disable source by coc_sources_disable_map', async () => { + await nvim.command('let g:coc_sources_disable_map = {"python": ["around", "buffer"]}') + let res = sources.getNormalSources('python', 'file:///t.py') + await nvim.command('let g:coc_sources_disable_map = {}') + expect(res.find(o => o.name == 'around')).toBeUndefined() + expect(res.find(o => o.name == 'buffer')).toBeUndefined() + }) +}) + +describe('sources#has', () => { + + it('should has source', () => { + expect(sources.has('around')).toBe(true) + }) + + it('should not has source', () => { + expect(sources.has('NotExists')).toBe(false) + }) +}) + +describe('sources#refresh', () => { + it('should refresh if possible', async () => { + let fn = jest.fn() + let source: ISource = { + name: 'refresh', + enable: true, + priority: 0, + sourceType: SourceType.Service, + triggerCharacters: [], + doComplete: () => Promise.resolve({ items: [] }), + refresh: fn + } + sources.addSource(source) + await sources.refresh('refresh') + expect(fn).toBeCalled() + sources.removeSource(source) + }) + + it('should work if refresh not defined', async () => { + let source: ISource = { + name: 'refresh', + enable: true, + priority: 0, + sourceType: SourceType.Service, + triggerCharacters: [], + doComplete: () => Promise.resolve({ items: [] }) + } + sources.addSource(source) + await sources.refresh('refresh') + sources.removeSource(source) + }) +}) + +describe('sources#createSource', () => { + it('should create source', async () => { + let disposable = sources.createSource({ + name: 'custom', + doComplete: () => Promise.resolve({ + items: [{ + word: 'custom' + }] + }) + }) + await helper.createDocument() + await nvim.input('i') + await helper.wait(30) + await nvim.input('c') + let visible = await helper.visible('custom', 'custom') + expect(visible).toBe(true) + disposable.dispose() + }) + + it('should create vim source', async () => { + let folder = path.resolve(__dirname, '..') + await nvim.command(`set runtimepath+=${folder}`) + await helper.wait(100) + let exists = sources.has('email') + expect(exists).toBe(true) + await helper.createDocument() + await nvim.input('i') + await helper.wait(10) + await nvim.input('@') + await helper.visible('foo@gmail.com') + }) +}) + +describe('sources#getTriggerSources()', () => { + it('should filter by filetypes', async () => { + let source: ISource = { + name: 'test', + enable: true, + priority: 0, + filetypes: ['javascript'], + sourceType: SourceType.Service, + triggerCharacters: ['#'], + doComplete: () => Promise.resolve({ items: [] }) + } + let disposable = sources.addSource(source) + let res = sources.getTriggerSources('#', 'javascript', 'file:///tmp.js') + expect(res.find(o => o.name == 'test')).toBeDefined() + disposable.dispose() + }) + + it('should filter by documentSelector', async () => { + let source: ISource = { + name: 'test', + enable: true, + priority: 0, + documentSelector: [{ language: 'javascript' }], + sourceType: SourceType.Service, + triggerCharacters: ['#'], + doComplete: () => Promise.resolve({ items: [] }) + } + let disposable = sources.addSource(source) + let res = sources.getTriggerSources('#', 'javascript', 'file:///tmp.js') + expect(res.find(o => o.name == 'test')).toBeDefined() + disposable.dispose() + }) + + it('should filter by disabledSources', async () => { + workspace.env.disabledSources = { + javascript: ['test'] + } + let source: ISource = { + name: 'test', + enable: true, + priority: 0, + documentSelector: [{ language: 'javascript' }], + sourceType: SourceType.Service, + triggerCharacters: ['#'], + doComplete: () => Promise.resolve({ items: [] }) + } + let disposable = sources.addSource(source) + let res = sources.getTriggerSources('#', 'javascript', 'file:///tmp.js') + expect(res.find(o => o.name == 'test')).toBeUndefined() + disposable.dispose() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/task.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/task.test.ts new file mode 100644 index 00000000..bd90ebed --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/task.test.ts @@ -0,0 +1,113 @@ +import { Neovim } from '@chemzqm/neovim' +import helper, { createTmpFile } from '../helper' +import workspace from '../../workspace' + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +describe('task test', () => { + it('should start task', async () => { + let task = workspace.createTask('sleep') + let started = await task.start({ cmd: 'sleep', args: ['50'] }) + expect(started).toBe(true) + task.dispose() + }) + + it('should stop task', async () => { + let task = workspace.createTask('sleep') + await task.start({ cmd: 'sleep', args: ['50'] }) + await helper.wait(10) + await task.stop() + let running = await task.running + expect(running).toBe(false) + task.dispose() + }) + + it('should emit exit event', async () => { + let fn = jest.fn() + let task = workspace.createTask('sleep') + task.onExit(fn) + await task.start({ cmd: 'sleep', args: ['50'] }) + await helper.wait(10) + await task.stop() + task.dispose() + expect(fn).toBeCalled() + }) + + it('should emit stdout event', async () => { + let file = await createTmpFile('echo foo') + let fn = jest.fn() + let task = workspace.createTask('echo') + let called = false + task.onStdout(lines => { + if (!called) expect(lines).toEqual(['foo']) + called = true + fn() + }) + await task.start({ cmd: '/bin/sh', args: [file] }) + await helper.wait(300) + task.dispose() + expect(fn).toBeCalled() + }) + + it('should change environment variables', async () => { + let file = await createTmpFile('echo $NODE_ENV\necho $COC_NVIM_TEST\nsleep 1') + let task = workspace.createTask('ENV') + let lines: string[] = [] + task.onStdout(arr => { + lines.push(...arr) + }) + await task.start({ + cmd: '/bin/sh', + args: [file], + env: { + NODE_ENV: 'production', + COC_NVIM_TEST: 'yes' + } + }) + await helper.wait(300) + expect(lines).toEqual(['production', 'yes']) + let res = await nvim.call('getenv', 'COC_NVIM_TEST') + expect(res).toBeNull() + task.dispose() + }) + + it('should receive stdout lines as expected', async () => { + let file = await createTmpFile('echo 3\necho ""\necho 4') + let task = workspace.createTask('ENV') + let lines: string[] = [] + task.onStdout(arr => { + lines.push(...arr) + }) + await task.start({ + cmd: '/bin/sh', + args: [file] + }) + await helper.wait(300) + expect(lines).toEqual(['3', '', '4']) + task.dispose() + }) + + it('should emit stderr event', async () => { + let file = await createTmpFile('console.error("start\\n\\nend");') + let fn = jest.fn() + let task = workspace.createTask('error') + let lines: string[] = [] + task.onStderr(arr => { + lines.push(...arr) + fn() + }) + await task.start({ cmd: 'node', args: [file] }) + await helper.wait(300) + expect(lines).toEqual(['start', '', 'end']) + task.dispose() + expect(fn).toBeCalled() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/terminal.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/terminal.test.ts new file mode 100644 index 00000000..9597c8b9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/terminal.test.ts @@ -0,0 +1,53 @@ +import { Neovim } from '@chemzqm/neovim' +import helper from '../helper' +import TerminalModel from '../../model/terminal' + +let nvim: Neovim +let terminal: TerminalModel +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + terminal = new TerminalModel('sh', [], nvim) + await terminal.start(__dirname, { COC_TERMINAL: `option '-term'` }) +}) + +afterAll(async () => { + terminal.dispose() + await helper.shutdown() +}) + +describe('terminal properties', () => { + it('should get name', () => { + let name = terminal.name + expect(name).toBe('sh') + }) + + it('should have correct cwd and env', async () => { + let bufnr = terminal.bufnr + terminal.sendText('echo $PWD') + await helper.wait(300) + let lines = await nvim.call('getbufline', [bufnr, 1, '$']) as string[] + expect(lines[0].trim().length).toBeGreaterThan(0) + terminal.sendText('echo $COC_TERMINAL') + await helper.wait(300) + lines = await nvim.call('getbufline', [bufnr, 1, '$']) as string[] + expect(lines.includes(`option '-term'`)).toBe(true) + }) + + it('should get pid', async () => { + let pid = await terminal.processId + expect(typeof pid).toBe('number') + }) + + it('should hide terminal window', async () => { + await terminal.hide() + let winnr = await nvim.call('bufwinnr', terminal.bufnr) + expect(winnr).toBe(-1) + }) + + it('should show terminal window', async () => { + await terminal.show() + let winnr = await nvim.call('bufwinnr', terminal.bufnr) + expect(winnr != -1).toBe(true) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/textdocument.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/textdocument.test.ts new file mode 100644 index 00000000..1d0a5e42 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/textdocument.test.ts @@ -0,0 +1,35 @@ +import { Position, Range } from 'vscode-languageserver-protocol' +import { LinesTextDocument } from '../../model/textdocument' + +function createTextDocument(lines: string[]): LinesTextDocument { + return new LinesTextDocument('file://a', 'txt', 1, lines, true) +} + +describe('LinesTextDocument', () => { + it('should get line count and content', async () => { + let doc = createTextDocument(['a', 'b']) + expect(doc.lineCount).toBe(3) + let content = doc.getText() + expect(content).toBe('a\nb\n') + }) + + it('should get position', async () => { + let doc = createTextDocument(['foo', 'bar']) + let pos = doc.positionAt(4) + expect(pos).toEqual({ line: 1, character: 0 }) + }) + + it('should get content by range', async () => { + let doc = createTextDocument(['foo', 'bar']) + let content = doc.getText(Range.create(0, 0, 0, 3)) + expect(content).toBe('foo') + }) + + it('should get offset', async () => { + let doc = createTextDocument(['foo', 'bar']) + let offset = doc.offsetAt(Position.create(0, 4)) + expect(offset).toBe(4) + offset = doc.offsetAt(Position.create(2, 1)) + expect(offset).toBe(8) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/util.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/util.test.ts new file mode 100644 index 00000000..24416f90 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/util.test.ts @@ -0,0 +1,295 @@ +import path from 'path' +import { URI } from 'vscode-uri' +import { Range } from 'vscode-languageserver-protocol' +import os from 'os' +import fs from 'fs' +import { wait, watchFile } from '../../util' +import { isGitIgnored, findUp, resolveRoot, statAsync, parentDirs, isParentFolder } from '../../util/fs' +import { fuzzyChar, fuzzyMatch, getCharCodes } from '../../util/fuzzy' +import { score, positions, groupPositions } from '../../util/fzy' +import { score as matchScore } from '../../util/match' +import { mixin } from '../../util/object' +import { Mutex } from '../../util/mutex' +import { indexOf, rangeParts } from '../../util/string' +import helper, { createTmpFile } from '../helper' +import { ansiparse } from '../../util/ansiparse' +import { concurrent } from '../../util' +import { spawn } from 'child_process' +import { terminate } from '../../util/processes' + +describe('rangeParts', () => { + it('should get parts', async () => { + let res = rangeParts('foo bar', Range.create(0, 0, 0, 4)) + expect(res).toEqual(['', 'bar']) + res = rangeParts('foo\nbar', Range.create(0, 1, 1, 1)) + expect(res).toEqual(['f', 'ar']) + res = rangeParts('x\nfoo\nbar\ny', Range.create(0, 1, 2, 3)) + expect(res).toEqual(['x', '\ny']) + }) +}) + +describe('watchFile', () => { + it('should watch file', async () => { + let filepath = await createTmpFile('my file') + let fn = jest.fn() + let disposable = watchFile(filepath, () => { + fn() + }) + await wait(30) + fs.writeFileSync(filepath, 'new file', 'utf8') + await wait(200) + expect(fn).toBeCalled() + disposable.dispose() + }) +}) + +describe('score test', () => { + it('should match schema', () => { + let uri = URI.file('/foo').toString() + let s = matchScore([{ language: '*', scheme: 'file' }], uri, 'typescript') + expect(s).toBe(5) + }) + + it('fzy#score', async () => { + let a = score("amuser", "app/models/user.rb") + let b = score("amuser", "app/models/customer.rb") + expect(a).toBeGreaterThan(b) + }) + + it('fzy#positions', async () => { + let arr = positions("amuser", "app/models/user.rb") + expect(arr).toEqual([0, 4, 11, 12, 13, 14]) + }) + + it('fzy#groupPositions', async () => { + let arr = groupPositions([1, 2, 3, 6, 7, 10]) + expect(arr).toEqual([[1, 4], [6, 8], [10, 11]]) + }) +}) + +describe('parentDirs', () => { + it('get parentDirs', () => { + let dirs = parentDirs('/a/b/c') + expect(dirs).toEqual(['/', '/a', '/a/b']) + }) +}) + +describe('isParentFolder', () => { + it('check parent folder', () => { + expect(isParentFolder('/a', '/a/b')).toBe(true) + expect(isParentFolder('/a/b', '/a/b/')).toBe(false) + expect(isParentFolder('/a/b', '/a/b')).toBe(false) + expect(isParentFolder('/a/b', '/a/b', true)).toBe(true) + }) +}) + +describe('string test', () => { + it('should find index', () => { + expect(indexOf('a,b,c', ',', 2)).toBe(3) + expect(indexOf('a,b,c', ',', 1)).toBe(1) + }) +}) + +describe('concurrent', () => { + it('should run concurrent', async () => { + let res: number[] = [] + let fn = (n: number): Promise => { + return new Promise(resolve => { + setTimeout(() => { + res.push(n) + resolve() + }, n * 100) + }) + } + let arr = [5, 4, 3, 6, 8] + let ts = Date.now() + await concurrent(arr, fn, 3) + let dt = Date.now() - ts + expect(dt).toBeLessThanOrEqual(1300) + expect(dt).toBeGreaterThanOrEqual(1200) + expect(res).toEqual([3, 4, 5, 6, 8]) + }) +}) + +describe('fuzzy match test', () => { + it('should be fuzzy match', () => { + let needle = 'aBc' + let codes = getCharCodes(needle) + expect(fuzzyMatch(codes, 'abc')).toBeFalsy + expect(fuzzyMatch(codes, 'ab')).toBeFalsy + expect(fuzzyMatch(codes, 'addbdd')).toBeFalsy + expect(fuzzyMatch(codes, 'abbbBc')).toBeTruthy + expect(fuzzyMatch(codes, 'daBc')).toBeTruthy + expect(fuzzyMatch(codes, 'ABCz')).toBeTruthy + }) + + it('should be fuzzy for character', () => { + expect(fuzzyChar('a', 'a')).toBeTruthy + expect(fuzzyChar('a', 'A')).toBeTruthy + expect(fuzzyChar('z', 'z')).toBeTruthy + expect(fuzzyChar('z', 'Z')).toBeTruthy + expect(fuzzyChar('A', 'a')).toBeFalsy + expect(fuzzyChar('A', 'A')).toBeTruthy + expect(fuzzyChar('Z', 'z')).toBeFalsy + expect(fuzzyChar('Z', 'Z')).toBeTruthy + }) +}) + +describe('fs test', () => { + it('fs statAsync', async () => { + let res = await statAsync(__filename) + expect(res).toBeDefined + expect(res.isFile()).toBe(true) + }) + + it('fs statAsync #1', async () => { + let res = await statAsync(path.join(__dirname, 'file_not_exist')) + expect(res).toBeNull + }) + + it('should be not ignored', async () => { + let res = await isGitIgnored(__filename) + expect(res).toBeFalsy + }) + + it('should be ignored', async () => { + let res = await isGitIgnored(path.resolve(__dirname, '../lib/index.js.map')) + expect(res).toBeTruthy + }) +}) + +describe('object test', () => { + it('mixin should recursive', () => { + let res = mixin({ a: { b: 1 } }, { a: { c: 2 }, d: 3 }) + expect(res.a.b).toBe(1) + expect(res.a.c).toBe(2) + expect(res.d).toBe(3) + }) +}) + +describe('resolveRoot', () => { + it('resolve root consider root path', () => { + let res = resolveRoot(__dirname, ['.git']) + expect(res).toMatch('coc.nvim') + }) + + it('should resolve from parent folders', () => { + let root = path.resolve(__dirname, '../extensions/snippet-sample') + let res = resolveRoot(root, ['package.json']) + expect(res.endsWith('coc.nvim')).toBe(true) + }) + + it('should resolve from parent folders with bottom-up method', () => { + let root = path.resolve(__dirname, '../extensions/snippet-sample') + let res = resolveRoot(root, ['package.json'], null, true) + expect(res.endsWith('extensions')).toBe(true) + }) + + it('should resolve to cwd', () => { + let root = path.resolve(__dirname, '../extensions/test/') + let res = resolveRoot(root, ['package.json'], root, false, true) + expect(res).toBe(root) + }) + + it('should resolve to root', () => { + let root = path.resolve(__dirname, '../extensions/test/') + let res = resolveRoot(root, ['package.json'], root, false, false) + expect(res).toBe(path.resolve(__dirname, '../../../')) + }) + + it('should not resolve to home', () => { + let res = resolveRoot(__dirname, ['.config']) + expect(res != os.homedir()).toBeTruthy() + }) +}) + +describe('findUp', () => { + it('findUp by filename', () => { + let filepath = findUp('package.json', __dirname) + expect(filepath).toMatch('coc.nvim') + filepath = findUp('not_exists', __dirname) + expect(filepath).toBeNull() + }) + + it('findUp by filenames', async () => { + let filepath = findUp(['src'], __dirname) + expect(filepath).toMatch('coc.nvim') + }) +}) + +describe('ansiparse', () => { + it('ansiparse #1', () => { + let str = '\u001b[33mText\u001b[mnormal' + let res = ansiparse(str) + expect(res).toEqual([{ + foreground: 'yellow', text: 'Text' + }, { + text: 'normal' + }]) + }) + + it('ansiparse #2', () => { + let str = '\u001b[33m\u001b[mText' + let res = ansiparse(str) + expect(res).toEqual([ + { foreground: 'yellow', text: '' }, + { text: 'Text' }]) + }) + + it('ansiparse #3', () => { + let str = 'this.\u001b[0m\u001b[31m\u001b[1mhistory\u001b[0m.add()' + let res = ansiparse(str) + expect(res[1]).toEqual({ + foreground: 'red', + bold: true, text: 'history' + }) + }) +}) + +describe('Mutex', () => { + it('mutex run in serial', async () => { + let lastTs: number + let fn = () => new Promise(resolve => { + if (lastTs) { + let dt = Date.now() - lastTs + expect(dt).toBeGreaterThanOrEqual(298) + } + lastTs = Date.now() + setTimeout(() => { + resolve() + }, 300) + }) + let mutex = new Mutex() + await Promise.all([ + mutex.use(fn), + mutex.use(fn), + mutex.use(fn) + ]) + }) + + it('mutex run after job finish', async () => { + let count = 0 + let fn = () => new Promise(resolve => { + count = count + 1 + setTimeout(() => { + resolve() + }, 100) + }) + let mutex = new Mutex() + await mutex.use(fn) + await helper.wait(10) + await mutex.use(fn) + expect(count).toBe(2) + }) +}) + +describe('terminate', () => { + it('should terminate process', async () => { + let cwd = process.cwd() + let child = spawn('sleep', ['10'], { cwd, detached: true }) + let res = terminate(child, cwd) + await helper.wait(60) + expect(res).toBe(true) + expect(child.connected).toBe(false) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/watchman.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/watchman.test.ts new file mode 100644 index 00000000..d08a0122 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/watchman.test.ts @@ -0,0 +1,161 @@ +// import watchman from 'fb-watchman' +import { Neovim } from '@chemzqm/neovim' +import net from 'net' +import fs from 'fs' +import bser from 'bser' +import Watchman, { FileChangeItem } from '../../watchman' +import helper from '../helper' +import BufferChannel from '../../model/outputChannel' + +let server: net.Server +let client: net.Socket +const sockPath = '/tmp/watchman-fake' +process.env.WATCHMAN_SOCK = sockPath + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +function wait(ms: number): Promise { + return new Promise(resolve => { + setTimeout(() => { + resolve(undefined) + }, ms) + }) +} + +function sendResponse(data: any): void { + client.write(bser.dumpToBuffer(data)) +} + +function createFileChange(file: string, exists = true): FileChangeItem { + return { + size: 1, + name: file, + exists, + new: false, + type: 'f', + mtime_ms: Date.now() + } +} + +function sendSubscription(uid: string, root: string, files: FileChangeItem[]): void { + client.write(bser.dumpToBuffer({ + subscription: uid, + root, + files + })) +} + +beforeAll(done => { + // create a mock sever for watchman + server = net.createServer(c => { + client = c + c.on('data', data => { + let obj = bser.loadFromBuffer(data) + if (obj[0] == 'watch-project') { + sendResponse({ watch: obj[1] }) + } else if (obj[0] == 'unsubscribe') { + sendResponse({ path: obj[1] }) + } else if (obj[0] == 'clock') { + sendResponse({ clock: 'clock' }) + } else if (obj[0] == 'version') { + let { optional, required } = obj[1] + let res = {} + for (let key of Object.keys(optional)) { + res[key] = true + } + for (let key of Object.keys(required)) { + res[key] = true + } + sendResponse({ capabilities: res }) + } else if (obj[0] == 'subscribe') { + sendResponse({ subscribe: obj[2] }) + } else { + sendResponse({}) + } + }) + }) + server.on('error', err => { + throw err + }) + server.listen(sockPath, () => { + done() + }) +}) + +afterAll(() => { + client.unref() + server.close() + if (fs.existsSync(sockPath)) { + fs.unlinkSync(sockPath) + } +}) + +describe('watchman', () => { + it('should checkCapability', async () => { + let client = new Watchman(null) + let res = await client.checkCapability() + expect(res).toBe(true) + client.dispose() + }) + + it('should watchProject', async () => { + let client = new Watchman(null) + let res = await client.watchProject(__dirname) + expect(res).toBe(true) + client.dispose() + }) + + it('should subscribe', async () => { + let client = new Watchman(null, new BufferChannel('watchman', nvim)) + let cwd = process.cwd() + await client.watchProject(cwd) + let fn = jest.fn() + let disposable = await client.subscribe(`${cwd}/*`, fn) + let changes: FileChangeItem[] = [createFileChange(`${cwd}/a`)] + sendSubscription((global as any).subscribe, cwd, changes) + await wait(100) + expect(fn).toBeCalled() + let call = fn.mock.calls[0][0] + disposable.dispose() + expect(call.root).toBe(cwd) + client.dispose() + }) + + it('should unsubscribe', async () => { + let client = new Watchman(null) + await client.watchProject(process.cwd()) + let fn = jest.fn() + let disposable = await client.subscribe(`${process.cwd()}/*`, fn) + disposable.dispose() + client.dispose() + }) +}) + +describe('Watchman#createClient', () => { + it('should create client', async () => { + let client = await Watchman.createClient(null, process.cwd()) + expect(client).toBeDefined() + client.dispose() + }) + + it('should resue client for same root', async () => { + let client = await Watchman.createClient(null, process.cwd()) + expect(client).toBeDefined() + let other = await Watchman.createClient(null, process.cwd()) + expect(client).toBe(other) + client.dispose() + }) + + it('should not create client for root', async () => { + let client = await Watchman.createClient(null, '/') + expect(client).toBeNull() + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/window.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/window.test.ts new file mode 100644 index 00000000..727b2b1a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/window.test.ts @@ -0,0 +1,365 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, Emitter, Range } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import { TreeItem, TreeItemCollapsibleState } from '../../tree' +import { disposeAll } from '../../util' +import window from '../../window' +import workspace from '../../workspace' +import events from '../../events' +import helper from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] + +interface FileNode { + filepath: string + isFolder?: boolean +} + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim + let config = workspace.getConfiguration('coc.preferences') + config.update('enableMessageDialog', true) +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('window functions', () => { + it('should get offset', async () => { + let doc = await helper.createDocument() + await doc.applyEdits([{ range: Range.create(0, 0, 0, 0), newText: 'foo\nbar' }]) + let buf = await nvim.buffer + await buf.setLines(['foo', 'bar'], { start: 0, end: -1 }) + await helper.wait(100) + await nvim.call('cursor', [2, 2]) + let n = await window.getOffset() + expect(n).toBe(5) + }) + + it('should echo lines', async () => { + await window.echoLines(['a', 'b']) + let ch = await nvim.call('screenchar', [79, 1]) + let s = String.fromCharCode(ch) + expect(s).toBe('a') + }) + + it('should echo multiple lines with truncate', async () => { + await window.echoLines(['a', 'b', 'd', 'e'], true) + let ch = await nvim.call('screenchar', [79, 1]) + let s = String.fromCharCode(ch) + expect(s).toBe('a') + }) + + it('should run terminal command', async () => { + let res = await window.runTerminalCommand('ls', __dirname) + expect(res.success).toBe(true) + }) + + it('should open temimal buffer', async () => { + let bufnr = await window.openTerminal('ls', { autoclose: false, keepfocus: false }) + let curr = await nvim.eval('bufnr("%")') + expect(curr).toBe(bufnr) + let buftype = await nvim.eval('&buftype') + expect(buftype).toBe('terminal') + }) + + it('should show mesages', async () => { + await helper.edit() + window.showMessage('error', 'error') + await helper.wait(100) + let str = await helper.getCmdline() + expect(str).toMatch('error') + window.showMessage('warning', 'warning') + await helper.wait(100) + str = await helper.getCmdline() + expect(str).toMatch('warning') + window.showMessage('moremsg') + await helper.wait(100) + str = await helper.getCmdline() + expect(str).toMatch('moremsg') + }) + + it('should create outputChannel', () => { + let channel = window.createOutputChannel('channel') + expect(channel.name).toBe('channel') + }) + + it('should create TreeView instance', async () => { + let emitter = new Emitter() + let removed = false + let treeView = window.createTreeView('files', { + treeDataProvider: { + onDidChangeTreeData: emitter.event, + getChildren: root => { + if (root) return undefined + if (removed) return [{ filepath: '/foo/a', isFolder: true }] + return [{ filepath: '/foo/a', isFolder: true }, { filepath: '/foo/b.js' }] + }, + getTreeItem: (node: FileNode) => { + let { filepath, isFolder } = node + return new TreeItem(URI.file(filepath), isFolder ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None) + }, + } + }) + disposables.push(emitter) + disposables.push(treeView) + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['files', '- a', ' b.js']) + removed = true + emitter.fire(undefined) + await helper.wait(50) + lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['files', '- a']) + }) + + it('should show outputChannel', async () => { + window.createOutputChannel('channel') + window.showOutputChannel('channel') + await helper.wait(50) + let buf = await nvim.buffer + let name = await buf.name + expect(name).toMatch('channel') + }) + + it('should not show none exists channel', async () => { + let buf = await nvim.buffer + let bufnr = buf.id + window.showOutputChannel('NONE') + await helper.wait(10) + buf = await nvim.buffer + expect(buf.id).toBe(bufnr) + }) + + it('should get cursor position', async () => { + await helper.createDocument() + await nvim.setLine(' ') + await nvim.call('cursor', [1, 3]) + let pos = await window.getCursorPosition() + expect(pos).toEqual({ + line: 0, + character: 2 + }) + }) + + it('should moveTo position in insert mode', async () => { + await helper.edit() + await nvim.setLine('foo') + await nvim.input('i') + await window.moveTo({ line: 0, character: 3 }) + let col = await nvim.call('col', '.') + expect(col).toBe(4) + let virtualedit = await nvim.getOption('virtualedit') + expect(virtualedit).toBe('') + }) + + it('should choose quickpick', async () => { + let p = window.showQuickpick(['a', 'b']) + await helper.wait(100) + await nvim.input('1') + await nvim.input('') + let res = await p + expect(res).toBe(0) + }) + + it('should cancel quickpick', async () => { + let p = window.showQuickpick(['a', 'b']) + await helper.wait(100) + await nvim.input('') + let res = await p + expect(res).toBe(-1) + }) + + it('should show prompt', async () => { + let p = window.showPrompt('prompt') + await helper.wait(100) + await nvim.input('y') + let res = await p + expect(res).toBe(true) + }) + + it('should show dialog', async () => { + let dialog = await window.showDialog({ content: 'foo' }) + let winid = await dialog.winid + expect(winid).toBeDefined() + expect(winid).toBeGreaterThan(1000) + }) + + it('should show menu', async () => { + let p = window.showMenuPicker(['a', 'b', 'c'], 'choose item') + await helper.wait(100) + let exists = await nvim.call('coc#float#has_float', []) + expect(exists).toBe(1) + await nvim.input('2') + let res = await p + expect(res).toBe(1) + }) + + it('should request input', async () => { + let winid = await nvim.call('win_getid') + let p = window.requestInput('Name') + await helper.wait(100) + await nvim.input('bar') + let res = await p + let curr = await nvim.call('win_getid') + expect(curr).toBe(winid) + expect(res).toBe('bar') + }) + + it('should return null when input empty', async () => { + let p = window.requestInput('Name') + await helper.wait(30) + await nvim.input('') + let res = await p + expect(res).toBeNull() + }) + + it('should return select items for picker', async () => { + let curr = await nvim.call('win_getid') + let p = window.showPickerDialog(['foo', 'bar'], 'select') + await helper.wait(100) + await nvim.input(' ') + await helper.wait(30) + await nvim.input('') + let res = await p + let winid = await nvim.call('win_getid') + expect(winid).toBe(curr) + expect(res).toEqual(['foo']) + }) + + async function ensureNotification(idx: number): Promise { + let ids = await nvim.call('coc#float#get_float_win_list') + expect(ids.length).toBe(1) + let win = nvim.createWindow(ids[0]) + let kind = await win.getVar('kind') + expect(kind).toBe('notification') + let bufnr = await nvim.call('winbufnr', [win.id]) + await events.fire('FloatBtnClick', [bufnr, idx]) + } + + it('should show information message', async () => { + let p = window.showInformationMessage('information message', 'first', 'second') + await helper.wait(50) + await ensureNotification(0) + let res = await p + expect(res).toBe('first') + }) + + it('should show warning message', async () => { + let p = window.showWarningMessage('warning message', 'first', 'second') + await helper.wait(50) + await ensureNotification(1) + let res = await p + expect(res).toBe('second') + }) + + it('should show error message', async () => { + let p = window.showErrorMessage('error message', 'first', 'second') + await helper.wait(50) + await ensureNotification(0) + let res = await p + expect(res).toBe('first') + }) +}) + +describe('window notifications', () => { + it('should show notification with options', async () => { + let res = await window.showNotification({ + content: 'my notification', + close: true, + title: 'title', + timeout: 500 + }) + expect(res).toBe(true) + let ids = await nvim.call('coc#float#get_float_win_list') + expect(ids.length).toBe(1) + let win = nvim.createWindow(ids[0]) + let kind = await win.getVar('kind') + expect(kind).toBe('notification') + let winid = await nvim.call('coc#float#get_related', [win.id, 'border']) + let bufnr = await nvim.call('winbufnr', [winid]) + let buf = nvim.createBuffer(bufnr) + let lines = await buf.lines + expect(lines[0].includes('title')).toBe(true) + await helper.wait(600) + let valid = await nvim.call('coc#float#valid', [win.id]) + expect(valid).toBeFalsy() + }) + + it('should show progress notification', async () => { + let called = 0 + let res = await window.withProgress({ title: 'Downloading', cancellable: true }, (progress, token) => { + let n = 0 + return new Promise(resolve => { + let interval = setInterval(() => { + progress.report({ message: 'progress', increment: 1 }) + n = n + 10 + called = called + 1 + if (n == 100) { + clearInterval(interval) + resolve('done') + } + }, 100) + token.onCancellationRequested(() => { + clearInterval(interval) + resolve(undefined) + }) + }) + }) + expect(called).toBe(10) + expect(res).toBe('done') + }) + + it('should cancel progress notification on window close', async () => { + let called = 0 + let p = window.withProgress({ title: 'Downloading', cancellable: true }, (progress, token) => { + let n = 0 + return new Promise(resolve => { + let interval = setInterval(() => { + progress.report({ message: 'progress', increment: 1 }) + n = n + 10 + called = called + 1 + if (n == 100) { + clearInterval(interval) + resolve('done') + } + }, 100) + token.onCancellationRequested(() => { + clearInterval(interval) + resolve(undefined) + }) + }) + }) + await helper.wait(300) + await nvim.call('coc#float#close_all', []) + let res = await p + expect(called).toBeLessThan(10) + expect(res).toBe(undefined) + }) + + it('should cancel progress when window not shown', async () => { + let called = 0 + let p = window.withProgress({ title: 'Process' }, () => { + called = called + 1 + return Promise.resolve() + }) + await p + await helper.wait(120) + let floats = await helper.getFloats() + expect(called).toBe(1) + expect(floats.length).toBe(0) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/modules/workspace.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/modules/workspace.test.ts new file mode 100644 index 00000000..fb670b4d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/modules/workspace.test.ts @@ -0,0 +1,1043 @@ +import { Neovim } from '@chemzqm/neovim' +import fs from 'fs' +import os from 'os' +import path from 'path' +import { v4 as uuid } from 'uuid' +import { Disposable, Emitter } from 'vscode-languageserver-protocol' +import { CreateFile, DeleteFile, Location, Position, Range, RenameFile, TextDocumentEdit, TextEdit, VersionedTextDocumentIdentifier, WorkspaceEdit } from 'vscode-languageserver-types' +import { URI } from 'vscode-uri' +import events from '../../events' +import { TextDocumentContentProvider } from '../../provider' +import { ConfigurationTarget } from '../../types' +import { disposeAll } from '../../util' +import { readFile } from '../../util/fs' +import window from '../../window' +import workspace from '../../workspace' +import helper, { createTmpFile } from '../helper' + +let nvim: Neovim +let disposables: Disposable[] = [] + +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() + disposeAll(disposables) + disposables = [] +}) + +describe('workspace properties', () => { + + it('should have initialized', () => { + let { nvim, rootPath, cwd, documents, initialized, textDocuments } = workspace + expect(nvim).toBeTruthy() + expect(initialized).toBe(true) + expect(documents.length).toBe(1) + expect(textDocuments.length).toBe(1) + expect(rootPath).toBe(process.cwd()) + expect(cwd).toBe(process.cwd()) + }) + + it('should add workspaceFolder', async () => { + await helper.edit() + let { workspaceFolders, workspaceFolder } = workspace + expect(workspaceFolders.length).toBe(1) + expect(workspaceFolders[0].name).toBe('coc.nvim') + expect(workspaceFolder.name).toBe('coc.nvim') + }) + + it('should check isVim and isNvim', async () => { + let { isVim, isNvim } = workspace + expect(isVim).toBe(false) + expect(isNvim).toBe(true) + }) + + it('should return plugin root', () => { + let { pluginRoot } = workspace + expect(typeof pluginRoot).toBe('string') + }) + + it('should ready', async () => { + (workspace as any)._initialized = false + let p = workspace.ready + ; (workspace as any)._initialized = true + ; (workspace as any)._onDidWorkspaceInitialized.fire(void 0) + await p + }) + + it('should get filetyps', async () => { + await helper.edit('f.js') + let filetypes = workspace.filetypes + expect(filetypes.has('javascript')).toBe(true) + }) +}) + +describe('workspace applyEdits', () => { + it('should apply TextEdit of documentChanges', async () => { + let doc = await helper.createDocument() + let versioned = VersionedTextDocumentIdentifier.create(doc.uri, doc.version) + let edit = TextEdit.insert(Position.create(0, 0), 'bar') + let change = TextDocumentEdit.create(versioned, [edit]) + let workspaceEdit: WorkspaceEdit = { + documentChanges: [change] + } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(true) + let line = await nvim.getLine() + expect(line).toBe('bar') + }) + + it('should not apply TextEdit if version miss match', async () => { + let doc = await helper.createDocument() + let versioned = VersionedTextDocumentIdentifier.create(doc.uri, 10) + let edit = TextEdit.insert(Position.create(0, 0), 'bar') + let change = TextDocumentEdit.create(versioned, [edit]) + let workspaceEdit: WorkspaceEdit = { + documentChanges: [change] + } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(false) + }) + + it('should apply edits with changes to buffer', async () => { + let doc = await helper.createDocument() + let changes = { + [doc.uri]: [TextEdit.insert(Position.create(0, 0), 'bar')] + } + let workspaceEdit: WorkspaceEdit = { changes } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(true) + let line = await nvim.getLine() + expect(line).toBe('bar') + }) + + it('should apply edits with changes to file not in buffer list', async () => { + let filepath = await createTmpFile('bar') + let uri = URI.file(filepath).toString() + let changes = { + [uri]: [TextEdit.insert(Position.create(0, 0), 'foo')] + } + let res = await workspace.applyEdit({ changes }) + expect(res).toBe(true) + let doc = workspace.getDocument(uri) + let content = doc.getDocumentContent() + expect(content).toMatch(/^foobar/) + await nvim.command('silent! %bwipeout!') + }) + + it('should apply edits when file not exists', async () => { + let filepath = path.join(__dirname, 'not_exists') + let uri = URI.file(filepath).toString() + let changes = { + [uri]: [TextEdit.insert(Position.create(0, 0), 'foo')] + } + let res = await workspace.applyEdit({ changes }) + expect(res).toBe(true) + }) + + it('should adjust cursor position after applyEdits', async () => { + let doc = await helper.createDocument() + let pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 0, character: 0 }) + let edit = TextEdit.insert(Position.create(0, 0), 'foo\n') + let versioned = VersionedTextDocumentIdentifier.create(doc.uri, null) + let documentChanges = [TextDocumentEdit.create(versioned, [edit])] + let res = await workspace.applyEdit({ documentChanges }) + expect(res).toBe(true) + pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 1, character: 0 }) + }) + + it('should support null version of documentChanges', async () => { + let file = path.join(__dirname, 'foo') + await workspace.createFile(file, { ignoreIfExists: true, overwrite: true }) + let uri = URI.file(file).toString() + let versioned = VersionedTextDocumentIdentifier.create(uri, null) + let edit = TextEdit.insert(Position.create(0, 0), 'bar') + let change = TextDocumentEdit.create(versioned, [edit]) + let workspaceEdit: WorkspaceEdit = { + documentChanges: [change] + } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(true) + await nvim.command('wa') + let content = await readFile(file, 'utf8') + expect(content).toMatch(/^bar/) + await workspace.deleteFile(file, { ignoreIfNotExists: true }) + }) + + it('should support CreateFile edit', async () => { + let file = path.join(__dirname, 'foo') + let uri = URI.file(file).toString() + let workspaceEdit: WorkspaceEdit = { + documentChanges: [CreateFile.create(uri, { overwrite: true })] + } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(true) + await workspace.deleteFile(file, { ignoreIfNotExists: true }) + }) + + it('should support DeleteFile edit', async () => { + let file = path.join(__dirname, 'foo') + await workspace.createFile(file, { ignoreIfExists: true, overwrite: true }) + let uri = URI.file(file).toString() + let workspaceEdit: WorkspaceEdit = { + documentChanges: [DeleteFile.create(uri)] + } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(true) + }) + + it('should check uri for CreateFile edit', async () => { + let workspaceEdit: WorkspaceEdit = { + documentChanges: [CreateFile.create('term://.', { overwrite: true })] + } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(false) + }) + + it('should support RenameFile edit', async () => { + let file = path.join(__dirname, 'foo') + await workspace.createFile(file, { ignoreIfExists: true, overwrite: true }) + let newFile = path.join(__dirname, 'bar') + let uri = URI.file(file).toString() + let workspaceEdit: WorkspaceEdit = { + documentChanges: [RenameFile.create(uri, URI.file(newFile).toString())] + } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(true) + await workspace.deleteFile(newFile, { ignoreIfNotExists: true }) + }) + + it('should support changes with edit and rename', async () => { + let file = await createTmpFile('test') + let doc = await helper.createDocument(file) + let newFile = path.join(os.tmpdir(), `coc-${process.pid}/new-${uuid()}`) + let newUri = URI.file(newFile).toString() + let edit: WorkspaceEdit = { + documentChanges: [ + { + textDocument: { + version: null, + uri: doc.uri, + }, + edits: [ + { + range: { + start: { + line: 0, + character: 0 + }, + end: { + line: 0, + character: 4 + } + }, + newText: 'bar' + } + ] + }, + { + oldUri: doc.uri, + newUri, + kind: 'rename' + } + ] + } + let res = await workspace.applyEdit(edit) + expect(res).toBe(true) + let curr = await workspace.document + expect(curr.uri).toBe(newUri) + expect(curr.getline(0)).toBe('bar') + let line = await nvim.line + expect(line).toBe('bar') + }) + + it('should support edit new file with CreateFile', async () => { + let file = path.join(os.tmpdir(), 'foo') + let uri = URI.file(file).toString() + let workspaceEdit: WorkspaceEdit = { + documentChanges: [ + CreateFile.create(uri, { overwrite: true }), + TextDocumentEdit.create({ uri, version: 0 }, [ + TextEdit.insert(Position.create(0, 0), 'foo bar') + ]) + ] + } + let res = await workspace.applyEdit(workspaceEdit) + expect(res).toBe(true) + let doc = workspace.getDocument(uri) + expect(doc).toBeDefined() + let line = doc.getline(0) + expect(line).toBe('foo bar') + await workspace.deleteFile(file, { ignoreIfNotExists: true }) + }) +}) + +describe('workspace methods', () => { + it('should selected range', async () => { + let buf = await helper.edit() + await nvim.setLine('foobar') + await nvim.command('normal! viw') + await nvim.eval(`feedkeys("\\", 'in')`) + let doc = workspace.getDocument(buf.id) + let range = await workspace.getSelectedRange('v', doc) + expect(range).toEqual({ start: { line: 0, character: 0 }, end: { line: 0, character: 6 } }) + }) + + it('should get the document', async () => { + let buf = await helper.edit() + let doc = workspace.getDocument(buf.id) + expect(doc.buffer.equals(buf)).toBeTruthy() + doc = workspace.getDocument(doc.uri) + expect(doc.buffer.equals(buf)).toBeTruthy() + }) + + it('should get format options', async () => { + let opts = await workspace.getFormatOptions() + expect(opts.insertSpaces).toBe(true) + expect(opts.tabSize).toBe(2) + }) + + it('should get format options of current buffer', async () => { + let buf = await helper.edit() + await buf.setOption('shiftwidth', 8) + await buf.setOption('expandtab', false) + let doc = workspace.getDocument(buf.id) + let opts = await workspace.getFormatOptions(doc.uri) + expect(opts.insertSpaces).toBe(false) + expect(opts.tabSize).toBe(8) + }) + + it('should get format options when uri not exists', async () => { + let uri = URI.file('/tmp/foo').toString() + let opts = await workspace.getFormatOptions(uri) + expect(opts.insertSpaces).toBe(true) + expect(opts.tabSize).toBe(2) + }) + + it('should get config files', async () => { + let file = workspace.getConfigFile(ConfigurationTarget.Global) + expect(file).toBeFalsy() + file = workspace.getConfigFile(ConfigurationTarget.User) + expect(file).toBeTruthy() + }) + + it('should create file watcher', async () => { + let watcher = workspace.createFileSystemWatcher('**/*.ts') + expect(watcher).toBeTruthy() + }) + + it('should get quickfix item from Location', async () => { + let filepath = await createTmpFile('quickfix') + let uri = URI.file(filepath).toString() + let p = Position.create(0, 0) + let loc = Location.create(uri, Range.create(p, p)) + let item = await workspace.getQuickfixItem(loc) + expect(item.filename).toBe(filepath) + expect(item.text).toBe('quickfix') + }) + + it('should get line of document', async () => { + let doc = await helper.createDocument() + await nvim.setLine('abc') + let line = await workspace.getLine(doc.uri, 0) + expect(line).toBe('abc') + }) + + it('should get line of file', async () => { + let filepath = await createTmpFile('quickfix') + let uri = URI.file(filepath).toString() + let line = await workspace.getLine(uri, 0) + expect(line).toBe('quickfix') + }) + + it('should read content from buffer', async () => { + let doc = await helper.createDocument() + await doc.applyEdits([{ range: Range.create(0, 0, 0, 0), newText: 'foo' }]) + let line = await workspace.readFile(doc.uri) + expect(line).toBe('foo\n') + }) + + it('should read content from file', async () => { + let filepath = await createTmpFile('content') + let content = await workspace.readFile(URI.file(filepath).toString()) + expect(content).toBe(content) + }) + + it('should get current document', async () => { + let buf = await helper.edit('foo') + let doc = await workspace.document + expect(doc.bufnr).toBe(buf.id) + buf = await helper.edit('tmp') + doc = await workspace.document + expect(doc.bufnr).toBe(buf.id) + }) + + it('should expand filepath', async () => { + let home = os.homedir() + let res = workspace.expand('~/$NODE_ENV/') + expect(res.startsWith(home)).toBeTruthy() + expect(res).toContain(process.env.NODE_ENV) + + res = workspace.expand('$HOME/$NODE_ENV/') + expect(res.startsWith(home)).toBeTruthy() + expect(res).toContain(process.env.NODE_ENV) + }) + + it('should expand variables', async () => { + expect(workspace.expand('${workspace}/foo')).toBe(`${workspace.root}/foo`) + expect(workspace.expand('${env:NODE_ENV}')).toBe(process.env.NODE_ENV) + expect(workspace.expand('${cwd}')).toBe(workspace.cwd) + let folder = path.dirname(workspace.root) + expect(workspace.expand('${workspaceFolderBasename}')).toBe(folder) + await helper.edit('bar.ts') + expect(workspace.expand('${file}')).toContain('bar') + expect(workspace.expand('${fileDirname}')).toBe(path.dirname(__dirname)) + expect(workspace.expand('${fileExtname}')).toBe('.ts') + expect(workspace.expand('${fileBasename}')).toBe('bar.ts') + expect(workspace.expand('${fileBasenameNoExtension}')).toBe('bar') + }) + + it('should run command', async () => { + let res = await workspace.runCommand('ls', __dirname, 1) + expect(res).toMatch('workspace') + }) + + it('should resolve module path if exists', async () => { + let res = await workspace.resolveModule('typescript') + expect(res).toBeTruthy() + }) + + it('should not resolve module if not exists', async () => { + let res = await workspace.resolveModule('foo') + expect(res).toBeFalsy() + }) + + it('should return match score for document', async () => { + let doc = await helper.createDocument('tmp.xml') + expect(workspace.match(['xml'], doc.textDocument)).toBe(10) + expect(workspace.match(['wxml'], doc.textDocument)).toBe(0) + expect(workspace.match([{ language: 'xml' }], doc.textDocument)).toBe(10) + expect(workspace.match([{ language: 'wxml' }], doc.textDocument)).toBe(0) + expect(workspace.match([{ pattern: '**/*.xml' }], doc.textDocument)).toBe(5) + expect(workspace.match([{ pattern: '**/*.html' }], doc.textDocument)).toBe(0) + expect(workspace.match([{ scheme: 'file' }], doc.textDocument)).toBe(5) + expect(workspace.match([{ scheme: 'term' }], doc.textDocument)).toBe(0) + expect(workspace.match([{ language: 'xml' }, { scheme: 'file' }], doc.textDocument)).toBe(10) + }) + + it('should create terminal', async () => { + let terminal = await workspace.createTerminal({ name: 'test' }) + let pid = await terminal.processId + expect(typeof pid == 'number').toBe(true) + terminal.dispose() + }) + + it('should rename buffer', async () => { + await helper.createDocument('a') + let p = workspace.renameCurrent() + await helper.wait(30) + await nvim.input('b') + await p + let name = await nvim.eval('bufname("%")') as string + expect(name.endsWith('b')).toBe(true) + }) + + it('should rename file', async () => { + let cwd = await nvim.call('getcwd') + let file = path.join(cwd, 'a') + fs.writeFileSync(file, 'foo', 'utf8') + await helper.createDocument('a') + let p = workspace.renameCurrent() + await helper.wait(30) + await nvim.input('b') + await p + let name = await nvim.eval('bufname("%")') as string + expect(name.endsWith('b')).toBe(true) + expect(fs.existsSync(path.join(cwd, 'b'))).toBe(true) + fs.unlinkSync(path.join(cwd, 'b')) + }) +}) + +describe('workspace utility', () => { + + it('should support float', async () => { + let floatSupported = workspace.floatSupported + expect(floatSupported).toBe(true) + }) + + it('should loadFile', async () => { + let doc = await helper.createDocument() + let newFile = URI.file(path.join(__dirname, 'abc')).toString() + let document = await workspace.loadFile(newFile) + let bufnr = await nvim.call('bufnr', '%') + expect(document.uri.endsWith('abc')).toBe(true) + expect(bufnr).toBe(doc.bufnr) + }) + + it('should loadFiles', async () => { + let files = ['a', 'b', 'c'].map(key => URI.file(path.join(__dirname, key)).toString()) + await workspace.loadFiles(files) + for (let file of files) { + let uri = URI.file(file).toString() + let doc = workspace.getDocument(uri) + expect(doc).toBeDefined() + } + }) + + it('should not create file if document exists', async () => { + let doc = await helper.createDocument() + let filepath = URI.parse(doc.uri).fsPath + await workspace.createFile(filepath, { ignoreIfExists: false }) + let exists = fs.existsSync(filepath) + expect(exists).toBe(false) + }) + + it('should create file if parent folder not exists', async () => { + const folder = path.join(__dirname, 'foo') + const filepath = path.join(folder, 'bar') + await workspace.createFile(filepath) + const exists = fs.existsSync(filepath) + expect(exists).toBe(true) + fs.unlinkSync(filepath) + fs.rmdirSync(folder) + }) + + it('should not create file if file exists with ignoreIfExists', async () => { + let file = await createTmpFile('foo') + await workspace.createFile(file, { ignoreIfExists: true }) + let content = fs.readFileSync(file, 'utf8') + expect(content).toBe('foo') + }) + + it('should create file if not exists', async () => { + await helper.edit() + let filepath = path.join(__dirname, 'foo') + await workspace.createFile(filepath, { ignoreIfExists: true }) + let exists = fs.existsSync(filepath) + expect(exists).toBe(true) + fs.unlinkSync(filepath) + }) + + it('should create folder if not exists', async () => { + let filepath = path.join(__dirname, 'bar/') + await workspace.createFile(filepath) + expect(fs.existsSync(filepath)).toBe(true) + fs.rmdirSync(filepath) + }) + + it('should not throw on folder create if overwrite is true', async () => { + let filepath = path.join(__dirname, 'bar/') + await workspace.createFile(filepath) + await workspace.createFile(filepath, { overwrite: true }) + expect(fs.existsSync(filepath)).toBe(true) + fs.rmdirSync(filepath) + }) + + it('should rename if file not exists', async () => { + let filepath = path.join(__dirname, 'foo') + let newPath = path.join(__dirname, 'bar') + await workspace.createFile(filepath) + await workspace.renameFile(filepath, newPath) + expect(fs.existsSync(newPath)).toBe(true) + expect(fs.existsSync(filepath)).toBe(false) + fs.unlinkSync(newPath) + }) + + it('should rename current buffer with another buffer', async () => { + let file = await createTmpFile('test') + let doc = await helper.createDocument(file) + await nvim.setLine('bar') + await helper.wait(50) + let newFile = path.join(os.tmpdir(), `coc-${process.pid}/new-${uuid()}`) + await workspace.renameFile(file, newFile) + let bufnr = await nvim.call('bufnr', ['%']) + expect(bufnr).toBeGreaterThan(doc.bufnr) + let line = await nvim.line + expect(line).toBe('bar') + let exists = fs.existsSync(newFile) + expect(exists).toBe(true) + }) + + it('should overwrite if file exists', async () => { + let filepath = path.join(os.tmpdir(), uuid()) + let newPath = path.join(os.tmpdir(), uuid()) + await workspace.createFile(filepath) + await workspace.createFile(newPath) + await workspace.renameFile(filepath, newPath, { overwrite: true }) + expect(fs.existsSync(newPath)).toBe(true) + expect(fs.existsSync(filepath)).toBe(false) + fs.unlinkSync(newPath) + }) + + it('should delete file if exists', async () => { + let filepath = path.join(__dirname, 'foo') + await workspace.createFile(filepath) + expect(fs.existsSync(filepath)).toBe(true) + await workspace.deleteFile(filepath) + expect(fs.existsSync(filepath)).toBe(false) + }) + + it('should delete folder if exists', async () => { + let filepath = path.join(__dirname, 'foo/') + await workspace.createFile(filepath) + expect(fs.existsSync(filepath)).toBe(true) + await workspace.deleteFile(filepath, { recursive: true }) + expect(fs.existsSync(filepath)).toBe(false) + }) + + it('should open resource', async () => { + let uri = URI.file(path.join(os.tmpdir(), 'bar')).toString() + await workspace.openResource(uri) + let buf = await nvim.buffer + let name = await buf.name + expect(name).toMatch('bar') + }) + + it('should open none file uri', async () => { + let uri = 'jdi://abc' + await workspace.openResource(uri) + let buf = await nvim.buffer + let name = await buf.name + expect(name).toBe('jdi://abc') + }) + + it('should open opened buffer', async () => { + let buf = await helper.edit() + let doc = workspace.getDocument(buf.id) + await workspace.openResource(doc.uri) + await helper.wait(30) + let bufnr = await nvim.call('bufnr', '%') + expect(bufnr).toBe(buf.id) + }) + + it('should open url', async () => { + await helper.mockFunction('coc#util#open_url', 0) + let buf = await helper.edit() + let uri = 'http://example.com' + await workspace.openResource(uri) + await helper.wait(30) + let bufnr = await nvim.call('bufnr', '%') + expect(bufnr).toBe(buf.id) + }) + + it('should create database', async () => { + let db = workspace.createDatabase('test') + let res = db.exists('xyz') + expect(res).toBe(false) + db.destroy() + }) + + it('should get current state', async () => { + let buf = await helper.edit() + await buf.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + await nvim.call('cursor', [2, 2]) + let doc = workspace.getDocument(buf.id) + let state = await workspace.getCurrentState() + expect(doc.uri).toBe(state.document.uri) + expect(state.position).toEqual({ line: 1, character: 1 }) + }) + + it('should jumpTo position', async () => { + let uri = URI.file('/tmp/foo').toString() + await workspace.jumpTo(uri, { line: 1, character: 1 }) + await nvim.command('setl buftype=nofile') + let buf = await nvim.buffer + let name = await buf.name + expect(name).toMatch('/foo') + await buf.setLines(['foo', 'bar'], { start: 0, end: -1, strictIndexing: false }) + await workspace.jumpTo(uri, { line: 1, character: 1 }) + let pos = await nvim.call('getcurpos') + expect(pos.slice(1, 3)).toEqual([2, 2]) + }) + + it('should jumpTo uri without normalize', async () => { + let uri = 'zipfile:///tmp/clojure-1.9.0.jar::clojure/core.clj' + await workspace.jumpTo(uri) + let buf = await nvim.buffer + let name = await buf.name + expect(name).toBe(uri) + }) + + it('should jump without position', async () => { + let uri = URI.file('/tmp/foo').toString() + await workspace.jumpTo(uri) + let buf = await nvim.buffer + let name = await buf.name + expect(name).toMatch('/foo') + }) + + it('should jumpTo custom uri scheme', async () => { + let uri = 'jdt://foo' + await workspace.jumpTo(uri, { line: 1, character: 1 }) + let buf = await nvim.buffer + let name = await buf.name + expect(name).toBe(uri) + }) + + it('should findUp to tsconfig.json from current file', async () => { + await helper.edit(path.join(__dirname, 'edit')) + let filepath = await workspace.findUp('tsconfig.json') + expect(filepath).toMatch('tsconfig.json') + }) + + it('should findUp from current file ', async () => { + await helper.edit('foo') + let filepath = await workspace.findUp('tsconfig.json') + expect(filepath).toMatch('tsconfig.json') + }) + + it('should not findUp from file in other directory', async () => { + await nvim.command(`edit ${path.join(os.tmpdir(), 'foo')}`) + let filepath = await workspace.findUp('tsconfig.json') + expect(filepath).toBeNull() + }) + + it('should resolveRootPath', async () => { + let file = path.join(__dirname, 'foo') + let uri = URI.file(file) + let res = await workspace.resolveRootFolder(uri, ['.git']) + expect(res).toMatch('coc.nvim') + }) + + it('should register autocmd', async () => { + let event: any + let eventCount = 0 + let disposables = [] + disposables.push(workspace.registerAutocmd({ + event: 'TextYankPost', + arglist: ['v:event'], + callback: ev => { + eventCount += 1 + event = ev + } + })) + disposables.push(workspace.registerAutocmd({ + event: ['InsertEnter', 'CursorMoved'], + callback: () => { + eventCount += 1 + } + })) + await nvim.setLine('foo') + await helper.wait(30) + await nvim.command('normal! yy') + await helper.wait(30) + await nvim.command('normal! Abar') + await helper.wait(30) + expect(event.regtype).toBe('V') + expect(event.operator).toBe('y') + expect(event.regcontents).toEqual(['foo']) + expect(eventCount).toBeGreaterThan(2) + disposables.forEach(d => d.dispose()) + }) + + it('should regist keymap', async () => { + let fn = jest.fn() + await nvim.command('nmap go (coc-echo)') + let disposable = workspace.registerKeymap(['n', 'v'], 'echo', fn, { sync: true }) + await helper.wait(30) + let { mode } = await nvim.mode + expect(mode).toBe('n') + await nvim.call('feedkeys', ['go', 'i']) + await helper.wait(10) + expect(fn).toBeCalledTimes(1) + disposable.dispose() + await nvim.call('feedkeys', ['go', 'i']) + await helper.wait(10) + expect(fn).toBeCalledTimes(1) + }) + + it('should regist expr keymap', async () => { + let called = false + let fn = () => { + called = true + return '""' + } + await nvim.input('i') + let { mode } = await nvim.mode + expect(mode).toBe('i') + let disposable = workspace.registerExprKeymap('i', '"', fn) + await helper.wait(30) + await nvim.call('feedkeys', ['"', 't']) + await helper.wait(30) + expect(called).toBe(true) + let line = await nvim.line + expect(line).toBe('""') + disposable.dispose() + }) + + it('should regist buffer expr keymap', async () => { + let fn = () => '""' + await nvim.input('i') + let disposable = workspace.registerExprKeymap('i', '"', fn, true) + await helper.wait(30) + await nvim.call('feedkeys', ['"', 't']) + await helper.wait(30) + let line = await nvim.line + expect(line).toBe('""') + disposable.dispose() + }) + + it('should watch options', async () => { + let fn = jest.fn() + workspace.watchOption('showmode', fn, disposables) + await helper.wait(30) + await nvim.command('set showmode') + await helper.wait(30) + expect(fn).toBeCalled() + await nvim.command('noa set noshowmode') + }) + + it('should watch global', async () => { + let fn = jest.fn() + workspace.watchGlobal('x', fn, disposables) + await nvim.command('let g:x = 1') + await helper.wait(30) + }) +}) + +describe('workspace events', () => { + + it('should listen to fileType change', async () => { + let buf = await helper.edit() + await nvim.command('setf xml') + await helper.wait(40) + let doc = workspace.getDocument(buf.id) + expect(doc.filetype).toBe('xml') + }) + + it('should listen optionSet', async () => { + let opt = workspace.completeOpt + expect(opt).toMatch('menuone') + await nvim.command('set completeopt=menu,preview') + await helper.wait(50) + opt = workspace.completeOpt + expect(opt).toBe('menu,preview') + }) + + it('should fire onDidOpenTextDocument', async () => { + let fn = jest.fn() + workspace.onDidOpenTextDocument(fn, null, disposables) + await helper.edit() + await helper.wait(30) + expect(fn).toHaveBeenCalledTimes(1) + }) + + it('should fire onDidChangeTextDocument', async () => { + let fn = jest.fn() + await helper.edit() + workspace.onDidChangeTextDocument(fn, null, disposables) + await nvim.setLine('foo') + let doc = await workspace.document + doc.forceSync() + await helper.wait(20) + expect(fn).toHaveBeenCalledTimes(1) + }) + + it('should fire onDidChangeConfiguration', async () => { + await helper.createDocument() + let fn = jest.fn() + let disposable = workspace.onDidChangeConfiguration(e => { + disposable.dispose() + expect(e.affectsConfiguration('tsserver')).toBe(true) + expect(e.affectsConfiguration('tslint')).toBe(false) + fn() + }) + let config = workspace.getConfiguration('tsserver') + config.update('enable', false) + await helper.wait(100) + expect(fn).toHaveBeenCalledTimes(1) + config.update('enable', undefined) + }) + + it('should get empty configuration for none exists section', () => { + let config = workspace.getConfiguration('notexists') + let keys = Object.keys(config) + expect(keys.length).toBe(0) + }) + + it('should fire onWillSaveUntil', async () => { + let doc = await helper.createDocument() + let filepath = URI.parse(doc.uri).fsPath + let fn = jest.fn() + let disposable = workspace.onWillSaveTextDocument(event => { + let promise = new Promise(resolve => { + fn() + let edit: TextEdit = { + newText: 'foo', + range: Range.create(0, 0, 0, 0) + } + resolve([edit]) + }) + event.waitUntil(promise) + }) + await helper.wait(100) + await nvim.setLine('bar') + await helper.wait(30) + await events.fire('BufWritePre', [doc.bufnr]) + await helper.wait(30) + let content = doc.getDocumentContent() + expect(content.startsWith('foobar')).toBe(true) + disposable.dispose() + expect(fn).toBeCalledTimes(1) + if (fs.existsSync(filepath)) { + fs.unlinkSync(filepath) + } + }) + + it('should not work for async waitUntil', async () => { + let doc = await helper.createDocument() + let filepath = URI.parse(doc.uri).fsPath + let disposable = workspace.onWillSaveTextDocument(event => { + setTimeout(() => { + let edit: TextEdit = { + newText: 'foo', + range: Range.create(0, 0, 0, 0) + } + event.waitUntil(Promise.resolve([edit])) + }, 30) + }) + await nvim.setLine('bar') + await helper.wait(30) + await nvim.command('wa') + let content = doc.getDocumentContent() + expect(content).toMatch('bar') + disposable.dispose() + if (fs.existsSync(filepath)) { + fs.unlinkSync(filepath) + } + }) + + it('should only use first returned textEdits', async () => { + let doc = await helper.createDocument() + let filepath = URI.parse(doc.uri).fsPath + let disposables: Disposable[] = [] + workspace.onWillSaveTextDocument(event => { + event.waitUntil(Promise.resolve(undefined)) + }, null, disposables) + workspace.onWillSaveTextDocument(event => { + let promise = new Promise(resolve => { + setTimeout(() => { + let edit: TextEdit = { + newText: 'foo', + range: Range.create(0, 0, 0, 0) + } + resolve([edit]) + }, 10) + }) + event.waitUntil(promise) + }, null, disposables) + workspace.onWillSaveTextDocument(event => { + let promise = new Promise(resolve => { + setTimeout(() => { + let edit: TextEdit = { + newText: 'bar', + range: Range.create(0, 0, 0, 0) + } + resolve([edit]) + }, 30) + }) + event.waitUntil(promise) + }, null, disposables) + await nvim.setLine('bar') + await helper.wait(30) + await nvim.command('wa') + let content = doc.getDocumentContent() + expect(content).toMatch('foo') + disposeAll(disposables) + if (fs.existsSync(filepath)) { + fs.unlinkSync(filepath) + } + }) + + it('should attach & detach', async () => { + let buf = await helper.edit() + await nvim.command('CocDisable') + await helper.wait(100) + let doc = workspace.getDocument(buf.id) + expect(doc).toBeUndefined() + await nvim.command('CocEnable') + await helper.wait(100) + doc = workspace.getDocument(buf.id) + expect(doc.bufnr).toBe(buf.id) + }) + + it('should create document with same bufnr', async () => { + await nvim.command('tabe') + let buf = await helper.edit() + await helper.wait(100) + let doc = workspace.getDocument(buf.id) + expect(doc).toBeDefined() + }) +}) + +describe('workspace textDocument content provider', () => { + + it('should regist document content provider', async () => { + let provider: TextDocumentContentProvider = { + provideTextDocumentContent: (_uri, _token): string => 'sample text' + } + workspace.registerTextDocumentContentProvider('test', provider) + await helper.wait(100) + await nvim.command('edit test://1') + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual(['sample text']) + }) + + it('should react onChagne event of document content provider', async () => { + let text = 'foo' + let emitter = new Emitter() + let event = emitter.event + let provider: TextDocumentContentProvider = { + onDidChange: event, + provideTextDocumentContent: (_uri, _token): string => text + } + workspace.registerTextDocumentContentProvider('jdk', provider) + await helper.wait(80) + await nvim.command('edit jdk://1') + await helper.wait(100) + text = 'bar' + emitter.fire(URI.parse('jdk://1')) + await helper.wait(200) + let buf = await nvim.buffer + let lines = await buf.lines + expect(lines).toEqual(['bar']) + }) +}) + +describe('workspace registerBufferSync', () => { + it('should regist', async () => { + await helper.createDocument() + let created = 0 + let deleted = 0 + let changed = 0 + let disposable = workspace.registerBufferSync(() => { + created = created + 1 + return { + dispose: () => { + deleted += 1 + }, + onChange: () => { + changed += 1 + } + } + }) + disposables.push(disposable) + let doc = await helper.createDocument() + expect(created).toBe(2) + await doc.applyEdits([TextEdit.insert(Position.create(0, 0), 'foo')]) + expect(changed).toBe(1) + await nvim.command('bd!') + await helper.wait(50) + expect(deleted).toBe(1) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/rg b/vim-config/plugins/coc.nvim/src/__tests__/rg new file mode 100755 index 00000000..056d698a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/rg @@ -0,0 +1,38 @@ +#!/usr/bin/env node +// black:30 red:31 green:32 + +let content = `\x1b[30mmodules/cursors.test.ts\x1b[m +\x1b[32m218\x1b[m- let doc = await setup() +\x1b[32m219\x1b[m- await nvim.call('cursor', [1, 4]) +\x1b[32m220\x1b[m: await nvim.input('\x1b[31mabc\x1b[m') +\x1b[32m221\x1b[m- await helper.wait(30) +\x1b[32m222\x1b[m- doc.forceSync() +\x1b[32m223\x1b[m- await helper.wait(100) +\x1b[32m224\x1b[m- let lines = await nvim.call('getline', [1, '$']) +\x1b[32m225\x1b[m: expect(lines).toEqual(['\x1b[31mabc\x1b[m fooabc fooabc', 'barabc barabc']) +\x1b[32m226\x1b[m- }) +\x1b[32m227\x1b[m- +-- +\x1b[32m32\x1b[m- expect(rangeCount()).toBe(5) +\x1b[32m33\x1b[m- let lines = await nvim.call('getline', [1, '$']) +\x1b[32m34\x1b[m: expect(lines).toEqual(['\x1b[31mabc\x1b[m fooabc fooabc', 'barabc barabc']) +\x1b[32m35\x1b[m- }) +\x1b[32m36\x1b[m- + +\x1b[30mmodules/position.test.ts\x1b[m +\x1b[32m42\x1b[m- test('getChangedPosition #1', () => { +\x1b[32m43\x1b[m- let pos = Position.create(0, 0) +\x1b[32m44\x1b[m: let edit = TextEdit.insert(pos, '\x1b[31mabc\x1b[m') +\x1b[32m45\x1b[m- let res = getChangedPosition(pos, edit) +\x1b[32m46\x1b[m- expect(res).toEqual({ line: 0, character: 3 }) +` + +let idx = process.argv.findIndex(s => s == '--sleep') +if (idx !== -1) { + let ms = process.argv[idx + 1] + setTimeout(() => { + process.stdout.write(content) + }, ms) +} else { + process.stdout.write(content) +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/sample/.vim/coc-settings.json b/vim-config/plugins/coc.nvim/src/__tests__/sample/.vim/coc-settings.json new file mode 100644 index 00000000..745333b2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/sample/.vim/coc-settings.json @@ -0,0 +1,3 @@ +{ + "coc.preferences.rootPath": "./src" +} diff --git a/vim-config/plugins/coc.nvim/src/__tests__/snippets/manager.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/snippets/manager.test.ts new file mode 100644 index 00000000..a90db5a9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/snippets/manager.test.ts @@ -0,0 +1,306 @@ +import { Neovim } from '@chemzqm/neovim' +import path from 'path' +import { Range } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import Document from '../../model/document' +import snippetManager from '../../snippets/manager' +import { SnippetString } from '../../snippets/string' +import workspace from '../../workspace' +import helper from '../helper' + +let nvim: Neovim +let doc: Document +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +beforeEach(async () => { + doc = await helper.createDocument() +}) + +describe('snippet provider', () => { + describe('insertSnippet()', () => { + it('should not active when insert plain snippet', async () => { + await snippetManager.insertSnippet('foo') + let line = await nvim.line + expect(line).toBe('foo') + expect(snippetManager.session).toBe(null) + expect(snippetManager.getSession(doc.bufnr)).toBeUndefined() + expect(snippetManager.isActived(doc.bufnr)).toBe(false) + }) + + it('should resolve variables', async () => { + await snippetManager.insertSnippet('${foo:abcdef} ${bar}') + let line = await nvim.line + expect(line).toBe('abcdef bar') + }) + + it('should start new session if session exists', async () => { + await nvim.setLine('bar') + await snippetManager.insertSnippet('${1:foo} ') + await helper.wait(100) + await nvim.input('') + await nvim.command('stopinsert') + await nvim.input('A') + await helper.wait(100) + let active = await snippetManager.insertSnippet('${2:bar}') + expect(active).toBe(true) + let line = await nvim.getLine() + expect(line).toBe('foo barbar') + }) + + it('should start nest session', async () => { + await snippetManager.insertSnippet('${1:foo} ${2:bar}') + await nvim.input('') + await helper.wait(100) + let active = await snippetManager.insertSnippet('${1:x} $1') + expect(active).toBe(true) + }) + + it('should not consider plaintext as placeholder', async () => { + await snippetManager.insertSnippet('${1} ${2:bar}') + await nvim.input('$foo;') + await helper.wait(100) + await snippetManager.insertSnippet('${1:x}', false, Range.create(0, 5, 0, 6)) + await helper.wait(100) + let line = await nvim.line + expect(line).toBe('$foo;xbar') + }) + + it('should insert nest plain snippet', async () => { + await snippetManager.insertSnippet('${1:foo} ${2:bar}') + await nvim.input('') + await helper.wait(100) + let active = await snippetManager.insertSnippet('bar') + expect(active).toBe(true) + let cursor = await nvim.call('coc#cursor#position') + expect(cursor).toEqual([0, 3]) + }) + + it('should work with nest snippet', async () => { + let buf = await helper.edit() + let snip = '
    \n$0\n' + await snippetManager.insertSnippet(snip) + await helper.wait(30) + await nvim.input('abcde') + await helper.wait(100) + let lines = await buf.lines + expect(lines).toEqual(['', '', '']) + }) + + it('should insert snippetString', async () => { + let snippetString = new SnippetString() + .appendTabstop(1) + .appendText(' ') + .appendPlaceholder('bar', 2) + await snippetManager.insertSnippet(snippetString) + await nvim.input('$foo;') + await helper.wait(100) + snippetString = new SnippetString() + .appendVariable('foo', 'x') + await snippetManager.insertSnippet(snippetString, false, Range.create(0, 5, 0, 6)) + await helper.wait(100) + let line = await nvim.line + expect(line).toBe('$foo;xbar') + }) + }) + + describe('nextPlaceholder()', () => { + it('should goto next placeholder', async () => { + await snippetManager.insertSnippet('${1:a} ${2:b}') + await snippetManager.nextPlaceholder() + await helper.wait(30) + let col = await nvim.call('col', '.') + expect(col).toBe(3) + }) + + it('should remove keymap on nextPlaceholder when session not exits', async () => { + await nvim.call('coc#snippet#enable') + await snippetManager.nextPlaceholder() + await helper.wait(60) + let val = await doc.buffer.getVar('coc_snippet_active') + expect(val).toBe(0) + }) + }) + + describe('previousPlaceholder()', () => { + it('should goto previous placeholder', async () => { + await snippetManager.insertSnippet('${1:a} ${2:b}') + await snippetManager.nextPlaceholder() + await snippetManager.previousPlaceholder() + let col = await nvim.call('col', '.') + expect(col).toBe(1) + }) + + it('should remove keymap on previousPlaceholder when session not exits', async () => { + await nvim.call('coc#snippet#enable') + await snippetManager.previousPlaceholder() + await helper.wait(60) + let val = await doc.buffer.getVar('coc_snippet_active') + expect(val).toBe(0) + }) + }) + + describe('Events', () => { + it('should check position on InsertEnter', async () => { + await nvim.input('ibar') + await snippetManager.insertSnippet('${1:foo} $1 ') + await helper.wait(60) + await nvim.input('A') + await helper.wait(60) + expect(snippetManager.session).toBeNull() + }) + + }) + + describe('cancel()', () => { + it('should cancel snippet session', async () => { + let buffer = doc.buffer + await nvim.call('coc#snippet#enable') + snippetManager.cancel() + await helper.wait(60) + let val = await buffer.getVar('coc_snippet_active') + expect(val).toBe(0) + let active = await snippetManager.insertSnippet('${1:foo}') + expect(active).toBe(true) + snippetManager.cancel() + expect(snippetManager.session).toBeNull() + }) + }) + + describe('configuration', () => { + it('should respect preferCompleteThanJumpPlaceholder', async () => { + let config = workspace.getConfiguration('suggest') + config.update('preferCompleteThanJumpPlaceholder', true) + await nvim.setLine('foo') + await nvim.input('o') + await snippetManager.insertSnippet('${1:foo} ${2:bar}') + await helper.wait(10) + await nvim.input('f') + await helper.waitPopup() + await nvim.input('') + await helper.wait(200) + let line = await nvim.getLine() + expect(line).toBe('foo bar') + config.update('preferCompleteThanJumpPlaceholder', false) + }) + }) + + describe('jumpable()', () => { + it('should check jumpable', async () => { + await nvim.input('i') + await snippetManager.insertSnippet('${1:foo} ${2:bar}') + let jumpable = snippetManager.jumpable() + expect(jumpable).toBe(true) + await snippetManager.nextPlaceholder() + await helper.wait(30) + await snippetManager.nextPlaceholder() + await helper.wait(30) + jumpable = snippetManager.jumpable() + expect(jumpable).toBe(false) + }) + }) + + describe('synchronize text', () => { + it('should update placeholder on placeholder update', async () => { + await snippetManager.insertSnippet('$1\n${1/,/,\\n/g}') + await nvim.input('a,b') + await helper.wait(50) + doc.forceSync() + await helper.wait(200) + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(['a,b', 'a,', 'b']) + }) + + it('should adjust cursor position on update', async () => { + await nvim.input('i') + await snippetManager.insertSnippet('${1/..*/ -> /}$1') + let line = await nvim.line + expect(line).toBe('') + await helper.wait(60) + await nvim.input('x') + await helper.wait(400) + line = await nvim.line + expect(line).toBe(' -> x') + let col = await nvim.call('col', '.') + expect(col).toBe(6) + }) + + it('should synchronize text on change final placeholder', async () => { + await nvim.command('startinsert') + let res = await snippetManager.insertSnippet('$0empty$0') + expect(res).toBe(true) + await nvim.input('abc') + await nvim.input('') + await helper.wait(50) + await doc.patchChange() + let line = await nvim.line + expect(line).toBe('abcemptyabc') + }) + + it('should fix edit to current placeholder', async () => { + await nvim.command('startinsert') + let res = await snippetManager.insertSnippet('()$1$0', true) + expect(res).toBe(true) + await nvim.input('(') + await nvim.input(')') + await nvim.input('') + await helper.wait(50) + await doc.patchChange() + await helper.wait(200) + expect(snippetManager.session).toBeDefined() + }) + }) + + describe('resolveSnippet', () => { + it('should resolve snippet', async () => { + let fsPath = URI.parse(doc.uri).fsPath + let res = await snippetManager.resolveSnippet(`$TM_FILENAME`) + expect(res.toString()).toBe(path.basename(fsPath)) + res = await snippetManager.resolveSnippet(`$TM_FILENAME_BASE`) + expect(res.toString()).toBe(path.basename(fsPath, path.extname(fsPath))) + res = await snippetManager.resolveSnippet(`$TM_DIRECTORY`) + expect(res.toString()).toBe(path.dirname(fsPath)) + res = await snippetManager.resolveSnippet(`$TM_FILEPATH`) + expect(res.toString()).toBe(fsPath) + await nvim.call('setreg', ['""', 'foo']) + res = await snippetManager.resolveSnippet(`$YANK`) + expect(res.toString()).toBe('foo') + res = await snippetManager.resolveSnippet(`$TM_LINE_INDEX`) + expect(res.toString()).toBe('0') + res = await snippetManager.resolveSnippet(`$TM_LINE_NUMBER`) + expect(res.toString()).toBe('1') + await nvim.setLine('foo') + res = await snippetManager.resolveSnippet(`$TM_CURRENT_LINE`) + expect(res.toString()).toBe('foo') + res = await snippetManager.resolveSnippet(`$TM_CURRENT_WORD`) + expect(res.toString()).toBe('foo') + await nvim.call('setreg', ['*', 'foo']) + res = await snippetManager.resolveSnippet(`$CLIPBOARD`) + expect(res.toString()).toBe('foo') + let d = new Date() + res = await snippetManager.resolveSnippet(`$CURRENT_YEAR`) + expect(res.toString()).toBe(d.getFullYear().toString()) + res = await snippetManager.resolveSnippet(`$NOT_EXISTS`) + expect(res.toString()).toBe('NOT_EXISTS') + }) + }) + + describe('dispose()', () => { + it('should dispose', async () => { + let active = await snippetManager.insertSnippet('${1:foo}') + expect(active).toBe(true) + snippetManager.dispose() + expect(snippetManager.session).toBe(null) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/snippets/parser.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/snippets/parser.test.ts new file mode 100644 index 00000000..307a17f9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/snippets/parser.test.ts @@ -0,0 +1,780 @@ +/* eslint-disable */ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as assert from 'assert' +import { Scanner, TokenType, SnippetParser, Text, Placeholder, Variable, Marker, TextmateSnippet, Choice, FormatString, Transform } from '../../snippets/parser' +import { Range } from 'vscode-languageserver-types' + +describe('SnippetParser', () => { + + test('Scanner', () => { + + const scanner = new Scanner() + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('abc') + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('{{abc}}') + assert.equal(scanner.next().type, TokenType.CurlyOpen) + assert.equal(scanner.next().type, TokenType.CurlyOpen) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.CurlyClose) + assert.equal(scanner.next().type, TokenType.CurlyClose) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('abc() ') + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.Format) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('abc 123') + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.Format) + assert.equal(scanner.next().type, TokenType.Int) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('$foo') + assert.equal(scanner.next().type, TokenType.Dollar) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('$foo_bar') + assert.equal(scanner.next().type, TokenType.Dollar) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('$foo-bar') + assert.equal(scanner.next().type, TokenType.Dollar) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.Dash) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('${foo}') + assert.equal(scanner.next().type, TokenType.Dollar) + assert.equal(scanner.next().type, TokenType.CurlyOpen) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.CurlyClose) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('${1223:foo}') + assert.equal(scanner.next().type, TokenType.Dollar) + assert.equal(scanner.next().type, TokenType.CurlyOpen) + assert.equal(scanner.next().type, TokenType.Int) + assert.equal(scanner.next().type, TokenType.Colon) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.CurlyClose) + assert.equal(scanner.next().type, TokenType.EOF) + + scanner.text('\\${}') + assert.equal(scanner.next().type, TokenType.Backslash) + assert.equal(scanner.next().type, TokenType.Dollar) + assert.equal(scanner.next().type, TokenType.CurlyOpen) + assert.equal(scanner.next().type, TokenType.CurlyClose) + + scanner.text('${foo/regex/format/option}') + assert.equal(scanner.next().type, TokenType.Dollar) + assert.equal(scanner.next().type, TokenType.CurlyOpen) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.Forwardslash) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.Forwardslash) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.Forwardslash) + assert.equal(scanner.next().type, TokenType.VariableName) + assert.equal(scanner.next().type, TokenType.CurlyClose) + assert.equal(scanner.next().type, TokenType.EOF) + }) + + function assertText(value: string, expected: string) { + const p = new SnippetParser() + const actual = p.text(value) + assert.equal(actual, expected) + } + + function assertMarker(input: TextmateSnippet | Marker[] | string, ...ctors: Function[]) { + let marker: Marker[] + if (input instanceof TextmateSnippet) { + marker = input.children + } else if (typeof input === 'string') { + const p = new SnippetParser() + marker = p.parse(input).children + } else { + marker = input + } + while (marker.length > 0) { + let m = marker.pop() + let ctor = ctors.pop() + assert.ok(m instanceof ctor) + } + assert.equal(marker.length, ctors.length) + assert.equal(marker.length, 0) + } + + function assertTextAndMarker(value: string, escaped: string, ...ctors: Function[]) { + assertText(value, escaped) + assertMarker(value, ...ctors) + } + + function assertEscaped(value: string, expected: string) { + const actual = SnippetParser.escape(value) + assert.equal(actual, expected) + } + + test('Parser, escaped', function() { + assertEscaped('foo$0', 'foo\\$0') + assertEscaped('foo\\$0', 'foo\\\\\\$0') + assertEscaped('f$1oo$0', 'f\\$1oo\\$0') + assertEscaped('${1:foo}$0', '\\${1:foo\\}\\$0') + assertEscaped('$', '\\$') + }) + + test('Parser, text', () => { + assertText('$', '$') + assertText('\\\\$', '\\$') + assertText('{', '{') + assertText('\\}', '}') + assertText('\\abc', '\\abc') + assertText('foo${f:\\}}bar', 'foo}bar') + assertText('\\{', '\\{') + assertText('I need \\\\\\$', 'I need \\$') + assertText('\\', '\\') + assertText('\\{{', '\\{{') + assertText('{{', '{{') + assertText('{{dd', '{{dd') + assertText('}}', '}}') + assertText('ff}}', 'ff}}') + + assertText('farboo', 'farboo') + assertText('far{{}}boo', 'far{{}}boo') + assertText('far{{123}}boo', 'far{{123}}boo') + assertText('far\\{{123}}boo', 'far\\{{123}}boo') + assertText('far{{id:bern}}boo', 'far{{id:bern}}boo') + assertText('far{{id:bern {{basel}}}}boo', 'far{{id:bern {{basel}}}}boo') + assertText('far{{id:bern {{id:basel}}}}boo', 'far{{id:bern {{id:basel}}}}boo') + assertText('far{{id:bern {{id2:basel}}}}boo', 'far{{id:bern {{id2:basel}}}}boo') + }) + + + test('Parser, TM text', () => { + assertTextAndMarker('foo${1:bar}}', 'foobar}', Text, Placeholder, Text) + assertTextAndMarker('foo${1:bar}${2:foo}}', 'foobarfoo}', Text, Placeholder, Placeholder, Text) + + assertTextAndMarker('foo${1:bar\\}${2:foo}}', 'foobar}foo', Text, Placeholder) + + let [, placeholder] = new SnippetParser().parse('foo${1:bar\\}${2:foo}}').children + let { children } = (placeholder) + + assert.equal((placeholder).index, '1') + assert.ok(children[0] instanceof Text) + assert.equal(children[0].toString(), 'bar}') + assert.ok(children[1] instanceof Placeholder) + assert.equal(children[1].toString(), 'foo') + }) + + test('Parser, placeholder', () => { + assertTextAndMarker('farboo', 'farboo', Text) + assertTextAndMarker('far{{}}boo', 'far{{}}boo', Text) + assertTextAndMarker('far{{123}}boo', 'far{{123}}boo', Text) + assertTextAndMarker('far\\{{123}}boo', 'far\\{{123}}boo', Text) + }) + + test('Parser, literal code', () => { + assertTextAndMarker('far`123`boo', 'far`123`boo', Text) + assertTextAndMarker('far\\`123\\`boo', 'far\\`123\\`boo', Text) + }) + + test('Parser, variables/tabstop', () => { + assertTextAndMarker('$far-boo', '-boo', Variable, Text) + assertTextAndMarker('\\$far-boo', '$far-boo', Text) + assertTextAndMarker('far$farboo', 'far', Text, Variable) + assertTextAndMarker('far${farboo}', 'far', Text, Variable) + assertTextAndMarker('$123', '', Placeholder) + assertTextAndMarker('$farboo', '', Variable) + assertTextAndMarker('$far12boo', '', Variable) + assertTextAndMarker('000_${far}_000', '000__000', Text, Variable, Text) + assertTextAndMarker('FFF_${TM_SELECTED_TEXT}_FFF$0', 'FFF__FFF', Text, Variable, Text, Placeholder) + }) + + test('Parser, variables/placeholder with defaults', () => { + assertTextAndMarker('${name:value}', 'value', Variable) + assertTextAndMarker('${1:value}', 'value', Placeholder) + assertTextAndMarker('${1:bar${2:foo}bar}', 'barfoobar', Placeholder) + + assertTextAndMarker('${name:value', '${name:value', Text) + assertTextAndMarker('${1:bar${2:foobar}', '${1:barfoobar', Text, Placeholder) + }) + + test('Parser, variable transforms', function() { + assertTextAndMarker('${foo///}', '', Variable) + assertTextAndMarker('${foo/regex/format/gmi}', '', Variable) + assertTextAndMarker('${foo/([A-Z][a-z])/format/}', '', Variable) + + // invalid regex + assertTextAndMarker('${foo/([A-Z][a-z])/format/GMI}', '${foo/([A-Z][a-z])/format/GMI}', Text) + assertTextAndMarker('${foo/([A-Z][a-z])/format/funky}', '${foo/([A-Z][a-z])/format/funky}', Text) + assertTextAndMarker('${foo/([A-Z][a-z]/format/}', '${foo/([A-Z][a-z]/format/}', Text) + + // tricky regex + assertTextAndMarker('${foo/m\\/atch/$1/i}', '', Variable) + assertMarker('${foo/regex\/format/options}', Text) + + // incomplete + assertTextAndMarker('${foo///', '${foo///', Text) + assertTextAndMarker('${foo/regex/format/options', '${foo/regex/format/options', Text) + + // format string + assertMarker('${foo/.*/${0:fooo}/i}', Variable) + assertMarker('${foo/.*/${1}/i}', Variable) + assertMarker('${foo/.*/$1/i}', Variable) + assertMarker('${foo/.*/This-$1-encloses/i}', Variable) + assertMarker('${foo/.*/complex${1:else}/i}', Variable) + assertMarker('${foo/.*/complex${1:-else}/i}', Variable) + assertMarker('${foo/.*/complex${1:+if}/i}', Variable) + assertMarker('${foo/.*/complex${1:?if:else}/i}', Variable) + assertMarker('${foo/.*/complex${1:/upcase}/i}', Variable) + + }) + + test('Parser, placeholder with transform', () => { + const p = new SnippetParser() + const snippet = p.parse('${1:type}${1/(.+)/ /}') + let s = snippet.toString() + assert.equal(s.length, 5) + }) + + test('Parser, placeholder transforms', function() { + assertTextAndMarker('${1///}', '', Placeholder) + assertTextAndMarker('${1/regex/format/gmi}', '', Placeholder) + assertTextAndMarker('${1/([A-Z][a-z])/format/}', '', Placeholder) + assertTextAndMarker('${1///}', '', Placeholder) + + // tricky regex + assertTextAndMarker('${1/m\\/atch/$1/i}', '', Placeholder) + assertMarker('${1/regex\/format/options}', Text) + + // incomplete + assertTextAndMarker('${1///', '${1///', Text) + assertTextAndMarker('${1/regex/format/options', '${1/regex/format/options', Text) + }) + + test('No way to escape forward slash in snippet regex #36715', function() { + assertMarker('${TM_DIRECTORY/src\\//$1/}', Variable) + }) + + test('No way to escape forward slash in snippet format section #37562', function() { + assertMarker('${TM_SELECTED_TEXT/a/\\/$1/g}', Variable) + assertMarker('${TM_SELECTED_TEXT/a/in\\/$1ner/g}', Variable) + assertMarker('${TM_SELECTED_TEXT/a/end\\//g}', Variable) + }) + + test('Parser, placeholder with choice', () => { + + assertTextAndMarker('${1|one,two,three|}', 'one', Placeholder) + assertTextAndMarker('${1|one|}', 'one', Placeholder) + assertTextAndMarker('${1|one1,two2|}', 'one1', Placeholder) + assertTextAndMarker('${1|one1\\,two2|}', 'one1,two2', Placeholder) + assertTextAndMarker('${1|one1\\|two2|}', 'one1|two2', Placeholder) + assertTextAndMarker('${1|one1\\atwo2|}', 'one1\\atwo2', Placeholder) + assertTextAndMarker('${1|one,two,three,|}', '${1|one,two,three,|}', Text) + assertTextAndMarker('${1|one,', '${1|one,', Text) + + const p = new SnippetParser() + const snippet = p.parse('${1|one,two,three|}') + assertMarker(snippet, Placeholder) + const expected = [Placeholder, Text, Text, Text] + snippet.walk(marker => { + assert.equal(marker, expected.shift()) + return true + }) + }) + + test('Snippet choices: unable to escape comma and pipe, #31521', function() { + assertTextAndMarker('console.log(${1|not\\, not, five, 5, 1 23|});', 'console.log(not, not);', Text, Placeholder, Text) + }) + + test('Marker, toTextmateString()', function() { + + function assertTextsnippetString(input: string, expected: string): void { + const snippet = new SnippetParser().parse(input) + const actual = snippet.toTextmateString() + assert.equal(actual, expected) + } + + assertTextsnippetString('$1', '$1') + assertTextsnippetString('\\$1', '\\$1') + assertTextsnippetString('console.log(${1|not\\, not, five, 5, 1 23|});', 'console.log(${1|not\\, not, five, 5, 1 23|});') + assertTextsnippetString('console.log(${1|not\\, not, \\| five, 5, 1 23|});', 'console.log(${1|not\\, not, \\| five, 5, 1 23|});') + assertTextsnippetString('this is text', 'this is text') + assertTextsnippetString('this ${1:is ${2:nested with $var}}', 'this ${1:is ${2:nested with ${var}}}') + assertTextsnippetString('this ${1:is ${2:nested with $var}}}', 'this ${1:is ${2:nested with ${var}}}\\}') + }) + + test('Marker, toTextmateString() <-> identity', function() { + + function assertIdent(input: string): void { + // full loop: (1) parse input, (2) generate textmate string, (3) parse, (4) ensure both trees are equal + const snippet = new SnippetParser().parse(input) + const input2 = snippet.toTextmateString() + const snippet2 = new SnippetParser().parse(input2) + + function checkCheckChildren(marker1: Marker, marker2: Marker) { + assert.ok(marker1 instanceof Object.getPrototypeOf(marker2).constructor) + assert.ok(marker2 instanceof Object.getPrototypeOf(marker1).constructor) + + assert.equal(marker1.children.length, marker2.children.length) + assert.equal(marker1.toString(), marker2.toString()) + + for (let i = 0; i < marker1.children.length; i++) { + checkCheckChildren(marker1.children[i], marker2.children[i]) + } + } + + checkCheckChildren(snippet, snippet2) + } + + assertIdent('$1') + assertIdent('\\$1') + assertIdent('console.log(${1|not\\, not, five, 5, 1 23|});') + assertIdent('console.log(${1|not\\, not, \\| five, 5, 1 23|});') + assertIdent('this is text') + assertIdent('this ${1:is ${2:nested with $var}}') + assertIdent('this ${1:is ${2:nested with $var}}}') + assertIdent('this ${1:is ${2:nested with $var}} and repeating $1') + }) + + test('Parser, choise marker', () => { + const { placeholders } = new SnippetParser().parse('${1|one,two,three|}') + + assert.equal(placeholders.length, 1) + assert.ok(placeholders[0].choice instanceof Choice) + assert.ok(placeholders[0].children[0] instanceof Choice) + assert.equal((placeholders[0].children[0]).options.length, 3) + + assertText('${1|one,two,three|}', 'one') + assertText('\\${1|one,two,three|}', '${1|one,two,three|}') + assertText('${1\\|one,two,three|}', '${1\\|one,two,three|}') + assertText('${1||}', '${1||}') + }) + + test('Backslash character escape in choice tabstop doesn\'t work #58494', function() { + + const { placeholders } = new SnippetParser().parse('${1|\\,,},$,\\|,\\\\|}') + assert.equal(placeholders.length, 1) + assert.ok(placeholders[0].choice instanceof Choice) + }) + + test('Parser, only textmate', () => { + const p = new SnippetParser() + assertMarker(p.parse('far{{}}boo'), Text) + assertMarker(p.parse('far{{123}}boo'), Text) + assertMarker(p.parse('far\\{{123}}boo'), Text) + + assertMarker(p.parse('far$0boo'), Text, Placeholder, Text) + assertMarker(p.parse('far${123}boo'), Text, Placeholder, Text) + assertMarker(p.parse('far\\${123}boo'), Text) + }) + + test('Parser, real world', () => { + let marker = new SnippetParser().parse('console.warn(${1: $TM_SELECTED_TEXT })').children + + assert.equal(marker[0].toString(), 'console.warn(') + assert.ok(marker[1] instanceof Placeholder) + assert.equal(marker[2].toString(), ')') + + const placeholder = marker[1] + assert.equal(placeholder, false) + assert.equal(placeholder.index, '1') + assert.equal(placeholder.children.length, 3) + assert.ok(placeholder.children[0] instanceof Text) + assert.ok(placeholder.children[1] instanceof Variable) + assert.ok(placeholder.children[2] instanceof Text) + assert.equal(placeholder.children[0].toString(), ' ') + assert.equal(placeholder.children[1].toString(), '') + assert.equal(placeholder.children[2].toString(), ' ') + + const nestedVariable = placeholder.children[1] + assert.equal(nestedVariable.name, 'TM_SELECTED_TEXT') + assert.equal(nestedVariable.children.length, 0) + + marker = new SnippetParser().parse('$TM_SELECTED_TEXT').children + assert.equal(marker.length, 1) + assert.ok(marker[0] instanceof Variable) + }) + + test('Parser, transform example', () => { + let { children } = new SnippetParser().parse('${1:name} : ${2:type}${3/\\s:=(.*)/${1:+ :=}${1}/};\n$0') + + //${1:name} + assert.ok(children[0] instanceof Placeholder) + assert.equal(children[0].children.length, 1) + assert.equal(children[0].children[0].toString(), 'name') + assert.equal((children[0]).transform, undefined) + + // : + assert.ok(children[1] instanceof Text) + assert.equal(children[1].toString(), ' : ') + + //${2:type} + assert.ok(children[2] instanceof Placeholder) + assert.equal(children[2].children.length, 1) + assert.equal(children[2].children[0].toString(), 'type') + + //${3/\\s:=(.*)/${1:+ :=}${1}/} + assert.ok(children[3] instanceof Placeholder) + assert.equal(children[3].children.length, 0) + assert.notEqual((children[3]).transform, undefined) + let transform = (children[3]).transform + assert.equal(transform.regexp, '/\\s:=(.*)/') + assert.equal(transform.children.length, 2) + assert.ok(transform.children[0] instanceof FormatString) + assert.equal((transform.children[0]).index, 1) + assert.equal((transform.children[0]).ifValue, ' :=') + assert.ok(transform.children[1] instanceof FormatString) + assert.equal((transform.children[1]).index, 1) + assert.ok(children[4] instanceof Text) + assert.equal(children[4].toString(), ';\n') + + }) + + test('Parser, default placeholder values', () => { + + assertMarker('errorContext: `${1:err}`, error: $1', Text, Placeholder, Text, Placeholder) + + const [, p1, , p2] = new SnippetParser().parse('errorContext: `${1:err}`, error:$1').children + + assert.equal((p1).index, '1') + assert.equal((p1).children.length, '1') + assert.equal(((p1).children[0]), 'err') + + assert.equal((p2).index, '1') + assert.equal((p2).children.length, '1') + assert.equal(((p2).children[0]), 'err') + }) + + test('Parser, default placeholder values and one transform', () => { + + assertMarker('errorContext: `${1:err}`, error: ${1/err/ok/}', Text, Placeholder, Text, Placeholder) + + const [, p3, , p4] = new SnippetParser().parse('errorContext: `${1:err}`, error:${1/err/ok/}').children + + assert.equal((p3).index, '1') + assert.equal((p3).children.length, '1') + assert.equal(((p3).children[0]), 'err') + assert.equal((p3).transform, undefined) + + assert.equal((p4).index, '1') + assert.equal((p4).children.length, '1') + assert.equal(((p4).children[0]), 'ok') + assert.notEqual((p4).transform, undefined) + }) + + test('Repeated snippet placeholder should always inherit, #31040', function() { + assertText('${1:foo}-abc-$1', 'foo-abc-foo') + assertText('${1:foo}-abc-${1}', 'foo-abc-foo') + assertText('${1:foo}-abc-${1:bar}', 'foo-abc-foo') + assertText('${1}-abc-${1:foo}', 'foo-abc-foo') + }) + + test('backspace esapce in TM only, #16212', () => { + const actual = new SnippetParser().text('Foo \\\\${abc}bar') + assert.equal(actual, 'Foo \\bar') + }) + + test('colon as variable/placeholder value, #16717', () => { + let actual = new SnippetParser().text('${TM_SELECTED_TEXT:foo:bar}') + assert.equal(actual, 'foo:bar') + + actual = new SnippetParser().text('${1:foo:bar}') + assert.equal(actual, 'foo:bar') + }) + + test('incomplete placeholder', () => { + assertTextAndMarker('${1:}', '', Placeholder) + }) + + test('marker#len', () => { + + function assertLen(template: string, ...lengths: number[]): void { + const snippet = new SnippetParser().parse(template, true) + snippet.walk(m => { + const expected = lengths.shift() + assert.equal(m.len(), expected) + return true + }) + assert.equal(lengths.length, 0) + } + + assertLen('text$0', 4, 0) + assertLen('$1text$0', 0, 4, 0) + assertLen('te$1xt$0', 2, 0, 2, 0) + assertLen('errorContext: `${1:err}`, error: $0', 15, 0, 3, 10, 0) + assertLen('errorContext: `${1:err}`, error: $1$0', 15, 0, 3, 10, 0, 3, 0) + assertLen('$TM_SELECTED_TEXT$0', 0, 0) + assertLen('${TM_SELECTED_TEXT:def}$0', 0, 3, 0) + }) + + test('parser, parent node', function() { + let snippet = new SnippetParser().parse('This ${1:is ${2:nested}}$0', true) + + assert.equal(snippet.placeholders.length, 3) + let [first, second] = snippet.placeholders + assert.equal(first.index, '1') + assert.equal(second.index, '2') + assert.ok(second.parent === first) + assert.ok(first.parent === snippet) + + snippet = new SnippetParser().parse('${VAR:default${1:value}}$0', true) + assert.equal(snippet.placeholders.length, 2) + ;[first] = snippet.placeholders + assert.equal(first.index, '1') + + assert.ok(snippet.children[0] instanceof Variable) + assert.ok(first.parent === snippet.children[0]) + }) + + test('TextmateSnippet#enclosingPlaceholders', () => { + let snippet = new SnippetParser().parse('This ${1:is ${2:nested}}$0', true) + let [first, second] = snippet.placeholders + + assert.deepEqual(snippet.enclosingPlaceholders(first), []) + assert.deepEqual(snippet.enclosingPlaceholders(second), [first]) + }) + + test('TextmateSnippet#offset', () => { + let snippet = new SnippetParser().parse('te$1xt', true) + assert.equal(snippet.offset(snippet.children[0]), 0) + assert.equal(snippet.offset(snippet.children[1]), 2) + assert.equal(snippet.offset(snippet.children[2]), 2) + + snippet = new SnippetParser().parse('${TM_SELECTED_TEXT:def}', true) + assert.equal(snippet.offset(snippet.children[0]), 0) + assert.equal(snippet.offset((snippet.children[0]).children[0]), 0) + + // forgein marker + assert.equal(snippet.offset(new Text('foo')), -1) + }) + + test('TextmateSnippet#placeholder', () => { + let snippet = new SnippetParser().parse('te$1xt$0', true) + let placeholders = snippet.placeholders + assert.equal(placeholders.length, 2) + + snippet = new SnippetParser().parse('te$1xt$1$0', true) + placeholders = snippet.placeholders + assert.equal(placeholders.length, 3) + + + snippet = new SnippetParser().parse('te$1xt$2$0', true) + placeholders = snippet.placeholders + assert.equal(placeholders.length, 3) + + snippet = new SnippetParser().parse('${1:bar${2:foo}bar}$0', true) + placeholders = snippet.placeholders + assert.equal(placeholders.length, 3) + }) + + test('TextmateSnippet#replace 1/2', function() { + let snippet = new SnippetParser().parse('aaa${1:bbb${2:ccc}}$0', true) + + assert.equal(snippet.placeholders.length, 3) + const [, second] = snippet.placeholders + assert.equal(second.index, '2') + + const enclosing = snippet.enclosingPlaceholders(second) + assert.equal(enclosing.length, 1) + assert.equal(enclosing[0].index, '1') + + let nested = new SnippetParser().parse('ddd$1eee$0', true) + snippet.replace(second, nested.children) + + assert.equal(snippet.toString(), 'aaabbbdddeee') + assert.equal(snippet.placeholders.length, 4) + assert.equal(snippet.placeholders[0].index, '1') + assert.equal(snippet.placeholders[1].index, '1') + assert.equal(snippet.placeholders[2].index, '0') + assert.equal(snippet.placeholders[3].index, '0') + + const newEnclosing = snippet.enclosingPlaceholders(snippet.placeholders[1]) + assert.ok(newEnclosing[0] === snippet.placeholders[0]) + assert.equal(newEnclosing.length, 1) + assert.equal(newEnclosing[0].index, '1') + }) + + test('TextmateSnippet#replace 2/2', function() { + let snippet = new SnippetParser().parse('aaa${1:bbb${2:ccc}}$0', true) + + assert.equal(snippet.placeholders.length, 3) + const [, second] = snippet.placeholders + assert.equal(second.index, '2') + + let nested = new SnippetParser().parse('dddeee$0', true) + snippet.replace(second, nested.children) + + assert.equal(snippet.toString(), 'aaabbbdddeee') + assert.equal(snippet.placeholders.length, 3) + }) + + test('TextmateSnippet#insertSnippet', function() { + let snippet = new SnippetParser().parse('${1:aaa} ${1:aaa} bbb ${2:ccc}}$0', true) + snippet.insertSnippet('|${1:dd} ${2:ff}|', 1, Range.create(0, 0, 0, 0)) + const [one, two, three] = snippet.placeholders + assert.equal(one.index, 1) + assert.equal(one.toString(), 'aaa') + assert.equal(two.index, 2) + assert.equal(two.toString(), 'dd') + assert.equal(three.index, 3) + assert.equal(three.toString(), 'ff') + }) + + test('TextmateSnippet#updatePlaceholder', function() { + let snippet = new SnippetParser().parse('aaa${1:bbb} ${1:bbb}', true) + snippet.updatePlaceholder(0, 'ccc') + let p = snippet.placeholders[0] + assert.equal(p.toString(), 'ccc') + }) + + test('Snippet order for placeholders, #28185', function() { + + const _10 = new Placeholder(10) + const _2 = new Placeholder(2) + + assert.equal(Placeholder.compareByIndex(_10, _2), 1) + }) + + test('Maximum call stack size exceeded, #28983', function() { + new SnippetParser().parse('${1:${foo:${1}}}') + }) + + test('Snippet can freeze the editor, #30407', function() { + + const seen = new Set() + + seen.clear() + new SnippetParser().parse('class ${1:${TM_FILENAME/(?:\\A|_)([A-Za-z0-9]+)(?:\\.rb)?/(?2::\\u$1)/g}} < ${2:Application}Controller\n $3\nend').walk(marker => { + assert.ok(!seen.has(marker)) + seen.add(marker) + return true + }) + + seen.clear() + new SnippetParser().parse('${1:${FOO:abc$1def}}').walk(marker => { + assert.ok(!seen.has(marker)) + seen.add(marker) + return true + }) + }) + + test('Snippets: make parser ignore `${0|choice|}`, #31599', function() { + assertTextAndMarker('${0|foo,bar|}', '${0|foo,bar|}', Text) + assertTextAndMarker('${1|foo,bar|}', 'foo', Placeholder) + }) + + + test('Transform -> FormatString#resolve', function() { + + // shorthand functions + assert.equal(new FormatString(1, 'upcase').resolve('foo'), 'FOO') + assert.equal(new FormatString(1, 'downcase').resolve('FOO'), 'foo') + assert.equal(new FormatString(1, 'capitalize').resolve('bar'), 'Bar') + assert.equal(new FormatString(1, 'capitalize').resolve('bar no repeat'), 'Bar no repeat') + assert.equal(new FormatString(1, 'pascalcase').resolve('bar-foo'), 'BarFoo') + assert.equal(new FormatString(1, 'notKnown').resolve('input'), 'input') + + // if + assert.equal(new FormatString(1, undefined, 'foo', undefined).resolve(undefined), '') + assert.equal(new FormatString(1, undefined, 'foo', undefined).resolve(''), '') + assert.equal(new FormatString(1, undefined, 'foo', undefined).resolve('bar'), 'foo') + + // else + assert.equal(new FormatString(1, undefined, undefined, 'foo').resolve(undefined), 'foo') + assert.equal(new FormatString(1, undefined, undefined, 'foo').resolve(''), 'foo') + assert.equal(new FormatString(1, undefined, undefined, 'foo').resolve('bar'), 'bar') + + // if-else + assert.equal(new FormatString(1, undefined, 'bar', 'foo').resolve(undefined), 'foo') + assert.equal(new FormatString(1, undefined, 'bar', 'foo').resolve(''), 'foo') + assert.equal(new FormatString(1, undefined, 'bar', 'foo').resolve('baz'), 'bar') + }) + + test('Snippet variable transformation doesn\'t work if regex is complicated and snippet body contains \'$$\' #55627', function() { + const snippet = new SnippetParser().parse('const fileName = "${TM_FILENAME/(.*)\\..+$/$1/}"') + assert.equal(snippet.toTextmateString(), 'const fileName = "${TM_FILENAME/(.*)\\..+$/${1}/}"') + }) + + test('[BUG] HTML attribute suggestions: Snippet session does not have end-position set, #33147', function() { + + const { placeholders } = new SnippetParser().parse('src="$1"', true) + const [first, second] = placeholders + + assert.equal(placeholders.length, 2) + assert.equal(first.index, 1) + assert.equal(second.index, 0) + + }) + + test('Snippet optional transforms are not applied correctly when reusing the same variable, #37702', function() { + + const transform = new Transform() + transform.appendChild(new FormatString(1, 'upcase')) + transform.appendChild(new FormatString(2, 'upcase')) + transform.regexp = /^(.)|-(.)/g + + assert.equal(transform.resolve('my-file-name'), 'MyFileName') + + const clone = transform.clone() + assert.equal(clone.resolve('my-file-name'), 'MyFileName') + }) + + test('problem with snippets regex #40570', function() { + + const snippet = new SnippetParser().parse('${TM_DIRECTORY/.*src[\\/](.*)/$1/}') + assertMarker(snippet, Variable) + }) + + test('Variable transformation doesn\'t work if undefined variables are used in the same snippet #51769', function() { + let transform = new Transform() + transform.appendChild(new Text('bar')) + transform.regexp = new RegExp('foo', 'gi') + assert.equal(transform.toTextmateString(), '/foo/bar/ig') + }) + + test('Snippet parser freeze #53144', function() { + let snippet = new SnippetParser().parse('${1/(void$)|(.+)/${1:?-\treturn nil;}/}') + assertMarker(snippet, Placeholder) + }) + + test('snippets variable not resolved in JSON proposal #52931', function() { + assertTextAndMarker('FOO${1:/bin/bash}', 'FOO/bin/bash', Text, Placeholder) + }) + + test('Mirroring sequence of nested placeholders not selected properly on backjumping #58736', function() { + let snippet = new SnippetParser().parse('${3:nest1 ${1:nest2 ${2:nest3}}} $3') + assert.equal(snippet.children.length, 3) + assert.ok(snippet.children[0] instanceof Placeholder) + assert.ok(snippet.children[1] instanceof Text) + assert.ok(snippet.children[2] instanceof Placeholder) + + function assertParent(marker: Marker) { + marker.children.forEach(assertParent) + if (!(marker instanceof Placeholder)) { + return + } + let found = false + let m: Marker = marker + while (m && !found) { + if (m.parent === snippet) { + found = true + } + m = m.parent + } + assert.ok(found) + } + let [, , clone] = snippet.children + assertParent(clone) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/snippets/session.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/snippets/session.test.ts new file mode 100644 index 00000000..d787dc23 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/snippets/session.test.ts @@ -0,0 +1,537 @@ +import { Range } from 'vscode-languageserver-protocol' +import { Neovim } from '@chemzqm/neovim' +import workspace from '../../workspace' +import window from '../../window' +import { SnippetSession } from '../../snippets/session' +import helper from '../helper' + +let nvim: Neovim +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +afterEach(async () => { + await helper.reset() +}) + +describe('SnippetSession#start', () => { + + it('should start with plain snippet', async () => { + let buf = await helper.edit() + await helper.wait(30) + await nvim.input('i') + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('bar$0') + expect(res).toBe(false) + let pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 0, character: 3 }) + }) + + it('should start with range replaced', async () => { + let buf = await helper.edit() + await helper.wait(30) + await nvim.setLine('foo') + await nvim.input('i') + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('bar$0', true, Range.create(0, 0, 0, 3)) + expect(res).toBe(false) + let line = await nvim.line + expect(line).toBe('bar') + }) + + it('should insert placeholder with default value', async () => { + let buf = await helper.edit() + await helper.wait(30) + await nvim.input('i') + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('a${TM_SELECTED_TEXT:return}b') + expect(res).toBe(false) + let line = await nvim.line + expect(line).toBe('areturnb') + }) + + it('should fix indent of next line when necessary', async () => { + let buf = await helper.edit() + await nvim.setLine(' ab') + await nvim.input('i') + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('x\n') + expect(res).toBe(false) + let lines = await buf.lines + expect(lines).toEqual([' ax', ' b']) + }) + + it('should start with final position for plain snippet', async () => { + let buf = await helper.edit() + await nvim.command('startinsert') + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('bar$0') + expect(res).toBe(false) + let pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 0, character: 3 }) + }) + + it('should insert indent for snippet endsWith line break', async () => { + let buf = await helper.edit() + await nvim.setLine(' bar') + await helper.wait(10) + await nvim.command('startinsert') + await nvim.call('cursor', [1, 3]) + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('foo\n') + expect(res).toBe(false) + let lines = await buf.lines + expect(lines).toEqual([' foo', ' bar']) + }) + + it('should insert resolved variable', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${TM_LINE_NUMBER}') + expect(res).toBe(false) + let line = await nvim.line + expect(line).toBe('1') + }) + + it('should use default value of unresolved variable', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${TM_SELECTION:abc}') + expect(res).toBe(false) + let line = await nvim.line + expect(line).toBe('abc') + }) + + it('should start with snippet insert', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start(' ${1:aa} bb $1') + expect(res).toBe(true) + let line = await nvim.getLine() + expect(line).toBe(' aa bb aa') + let { mode } = await nvim.mode + expect(mode).toBe('s') + let pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 0, character: 2 }) + }) + + it('should start without select placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start(' ${1:aa} ', false) + expect(res).toBe(true) + let line = await nvim.getLine() + expect(line).toBe(' aa ') + let { mode } = await nvim.mode + expect(mode).toBe('n') + await session.selectCurrentPlaceholder() + await helper.wait(100) + let m = await nvim.mode + expect(m.mode).toBe('s') + }) + + it('should start with variable selected', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${foo:bar}', false) + expect(res).toBe(true) + let line = await nvim.getLine() + expect(line).toBe('bar') + await session.selectCurrentPlaceholder() + await helper.wait(100) + let m = await nvim.mode + expect(m.mode).toBe('s') + }) + + it('should start with nest snippet', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1:a} ${2:b}', false) + let line = await nvim.getLine() + expect(line).toBe('a b') + expect(res).toBe(true) + let { placeholder } = session + expect(placeholder.index).toBe(1) + res = await session.start('${1:foo} ${2:bar}') + expect(res).toBe(true) + placeholder = session.placeholder + let { snippet } = session + expect(placeholder.index).toBe(2) + line = await nvim.getLine() + expect(line).toBe('foo bara b') + expect(snippet.toString()).toBe('foo bara b') + }) + + it('should jump to nested snippet placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('${1} ${2:b}', false) + await session.start('${1:foo} ${2:bar}') + await session.nextPlaceholder() + await session.nextPlaceholder() + await session.nextPlaceholder() + let pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 0, character: 8 }) + }) + + it('should jump to variable placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('${foo} ${bar}', false) + await session.selectCurrentPlaceholder() + await helper.wait(100) + await session.nextPlaceholder() + let pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 0, character: 6 }) + }) + + it('should jump to variable placeholder after number placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('${foo} ${1:bar}', false) + await session.selectCurrentPlaceholder() + await session.nextPlaceholder() + let pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 0, character: 2 }) + }) + + it('should jump to variable placeholder with same name only once', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('${foo} ${foo} ${2:bar}', false) + await session.selectCurrentPlaceholder() + await session.nextPlaceholder() + await session.nextPlaceholder() + let pos = await window.getCursorPosition() + expect(pos).toEqual({ line: 0, character: 11 }) + }) + + it('should start nest snippet without select', async () => { + let buf = await helper.edit() + await nvim.command('startinsert') + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1:a} ${2:b}') + await helper.wait(30) + await nvim.input('') + res = await session.start('${1:foo} ${2:bar}', false) + await helper.wait(30) + expect(res).toBe(true) + let line = await nvim.line + expect(line).toBe('foo bar b') + }) + + it('should select none transform placeholder', async () => { + let buf = await helper.edit() + await nvim.command('startinsert') + let session = new SnippetSession(nvim, buf.id) + await session.start('${1/..*/ -> /}xy$1') + await helper.wait(30) + let col = await nvim.call('col', '.') + expect(col).toBe(3) + }) + + it('should indent multiple lines variable text', async () => { + let text = 'abc\n def' + await nvim.setVar('coc_selected_text', text) + let buf = await helper.edit() + await nvim.input('i') + let session = new SnippetSession(nvim, buf.id) + await session.start('fun\n ${0:${TM_SELECTED_TEXT:return}}\nend') + await helper.wait(30) + let lines = await buf.lines + expect(lines.length).toBe(4) + expect(lines).toEqual([ + 'fun', ' abc', ' def', 'end' + ]) + }) +}) + +describe('SnippetSession#deactivate', () => { + + it('should deactivate on invalid change', async () => { + let doc = await helper.createDocument() + await nvim.input('i') + let session = new SnippetSession(nvim, doc.bufnr) + let res = await session.start('${1:a}bc') + expect(res).toBe(true) + let edit = { + range: Range.create(0, 0, 0, 2), + newText: '' + } + await doc.applyEdits([edit]) + await session.synchronizeUpdatedPlaceholders({ range: edit.range, text: edit.newText }) + expect(session.isActive).toBe(false) + }) + + it('should deactivate on cursor outside', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('a${1:a}b') + expect(res).toBe(true) + await buf.append(['foo', 'bar']) + await nvim.call('cursor', [2, 1]) + await session.checkPosition() + expect(session.isActive).toBe(false) + }) + + it('should cancel keymap on jump final placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await nvim.input('i') + await session.start('$0x${1:a}b$0') + let line = await nvim.line + expect(line).toBe('xab') + let map = await nvim.call('maparg', ['', 'i']) as string + expect(map).toMatch('snippetNext') + await session.nextPlaceholder() + map = await nvim.call('maparg', ['', 'i']) as string + expect(map).toBe('') + }) +}) + +describe('SnippetSession#nextPlaceholder', () => { + + it('should goto next placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1:a} ${2:b} c') + expect(res).toBe(true) + await session.nextPlaceholder() + let { placeholder } = session + expect(placeholder.index).toBe(2) + }) + + it('should jump to none transform placeholder', async () => { + let buf = await helper.edit() + await helper.wait(60) + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1} ${2/^_(.*)/$2/}bar$2') + expect(res).toBe(true) + let line = await nvim.line + expect(line).toBe(' bar') + await session.nextPlaceholder() + await helper.wait(60) + let col = await nvim.call('col', '.') + expect(col).toBe(5) + }) +}) + +describe('SnippetSession#previousPlaceholder', () => { + + it('should goto previous placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1:foo} ${2:bar}') + expect(res).toBe(true) + await session.nextPlaceholder() + await helper.wait(60) + expect(session.placeholder.index).toBe(2) + await session.previousPlaceholder() + await helper.wait(60) + expect(session.placeholder.index).toBe(1) + }) +}) + +describe('SnippetSession#synchronizeUpdatedPlaceholders', () => { + + it('should adjust with line changed before start position', async () => { + let buf = await helper.edit() + await nvim.setLine('abd') + await nvim.input('o') + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1:foo}') + await helper.wait(30) + expect(res).toBe(true) + await session.synchronizeUpdatedPlaceholders({ + range: Range.create(0, 0, 0, 3), + text: 'def' + }) + expect(session.isActive).toBe(true) + }) + + it('should adjust for variable placeholders', async () => { + let buf = await helper.edit() + await nvim.input('i') + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${foo} ${foo}') + expect(res).toBe(true) + await session.selectCurrentPlaceholder() + await helper.wait(100) + await nvim.input('bar') + await helper.wait(100) + await session.synchronizeUpdatedPlaceholders({ + range: Range.create(0, 0, 0, 3), + text: 'bar' + }) + let line = await nvim.getLine() + expect(line).toBe('bar bar') + }) + + it('should adjust with previous line change', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1:foo}') + await nvim.input('Obar') + await helper.wait(30) + expect(res).toBe(true) + await session.synchronizeUpdatedPlaceholders({ + range: Range.create(0, 0, 0, 0), + text: 'bar\n' + }) + expect(session.isActive).toBe(true) + let { start } = session.snippet.range + expect(start).toEqual({ line: 1, character: 0 }) + }) + + it('should adjust with previous character change', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('foo ${1:foo}') + await nvim.input('Ibar') + await helper.wait(30) + expect(res).toBe(true) + await session.synchronizeUpdatedPlaceholders({ + range: Range.create(0, 0, 0, 0), + text: 'bar' + }) + expect(session.isActive).toBe(true) + let { start } = session.snippet.range + expect(start).toEqual({ line: 0, character: 3 }) + }) + + it('should deactivate when content add after snippet', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1:foo} $0 ') + await nvim.input('Abar') + await helper.wait(100) + expect(res).toBe(true) + await session.synchronizeUpdatedPlaceholders({ + range: Range.create(0, 5, 0, 5), + text: 'bar' + }) + expect(session.isActive).toBe(false) + }) + + it('should not deactivate when content remove after snippet', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + let res = await session.start('${1:foo}') + expect(res).toBe(true) + await nvim.input('Abar') + await helper.wait(30) + await session.synchronizeUpdatedPlaceholders({ + range: Range.create(0, 5, 0, 6), + text: '' + }) + await helper.wait(30) + expect(session.isActive).toBe(true) + }) + + it('should deactivate when change outside placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('a${1:b}c') + let doc = await workspace.document + await doc.applyEdits([{ + range: Range.create(0, 0, 0, 1), + newText: '' + }]) + await session.synchronizeUpdatedPlaceholders({ + range: Range.create(0, 0, 0, 1), + text: '' + }) + expect(session.isActive).toBe(false) + }) + + it('should deactivate when jump to single final placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start(' $0 ${1:a}') + await session.nextPlaceholder() + expect(session.isActive).toBe(false) + }) +}) + +describe('SnippetSession#checkPosition', () => { + + it('should cancel snippet if position out of range', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await nvim.setLine('bar') + await session.start('${1:foo}') + await nvim.call('cursor', [1, 5]) + await session.checkPosition() + expect(session.isActive).toBe(false) + }) + + it('should not cancel snippet if position in range', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('${1:foo}') + await nvim.call('cursor', [1, 3]) + await session.checkPosition() + expect(session.isActive).toBe(true) + }) +}) + +describe('SnippetSession#findPlaceholder', () => { + + it('should find current placeholder if possible', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('${1:abc}${2:def}') + let placeholder = session.findPlaceholder(Range.create(0, 3, 0, 3)) + expect(placeholder.index).toBe(1) + }) + + it('should return null if placeholder not found', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('${1:abc}xyz${2:def}') + let placeholder = session.findPlaceholder(Range.create(0, 4, 0, 4)) + expect(placeholder).toBeNull() + }) +}) + +describe('SnippetSession#selectPlaceholder', () => { + + it('should select range placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('${1:abc}') + let mode = await nvim.mode + expect(mode.mode).toBe('s') + await nvim.input('') + let line = await nvim.line + expect(line).toBe('') + }) + + it('should select empty placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await session.start('a ${1} ${2}') + let mode = await nvim.mode + expect(mode.mode).toBe('i') + let col = await nvim.call('col', '.') + expect(col).toBe(3) + }) + + it('should select choice placeholder', async () => { + let buf = await helper.edit() + let session = new SnippetSession(nvim, buf.id) + await nvim.input('i') + await session.start('${1|one,two,three|}') + await helper.wait(60) + let line = await nvim.line + expect(line).toBe('one') + let val = await nvim.eval('g:coc#_context') as any + expect(val.start).toBe(0) + expect(val.candidates).toEqual(['one', 'two', 'three']) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/snippets/string.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/snippets/string.test.ts new file mode 100644 index 00000000..cfbadda9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/snippets/string.test.ts @@ -0,0 +1,78 @@ +import { SnippetString } from '../../snippets/string' + +describe('SnippetString', () => { + describe('Append', () => { + it('should append plain snippets', () => { + let snippetString = new SnippetString('foo') + expect(snippetString.value).toBe('foo') + + snippetString = new SnippetString().appendText('foo') + expect(snippetString.value).toBe('foo') + }) + + it('should append tabstop', () => { + let snippetString = new SnippetString() + .appendTabstop() + .appendText(' ') + .appendTabstop() + .appendText(' ') + .appendTabstop(4) + .appendText(' ') + .appendTabstop(3) + + expect(snippetString.value).toBe('$1 $2 $4 $3') + }) + + it('should append placeholder', () => { + let snippetString = new SnippetString() + .appendPlaceholder('abcdef') + .appendText(' ') + .appendPlaceholder('foo') + .appendText(' ') + .appendPlaceholder('bar', 4) + .appendText(' ') + .appendPlaceholder('a', 3) + .appendText(' ') + .appendPlaceholder(s => { + s.appendText('plain') + }, 5) + + expect(snippetString.value).toBe('${1:abcdef} ${2:foo} ${4:bar} ${3:a} ${5:plain}') + }) + + it('should append choice', () => { + let snippetString = new SnippetString() + .appendChoice(['foo', 'bar']) + .appendText(' ') + .appendChoice(['foo3', 'bar3'], 3) + .appendText(' ') + .appendChoice(['foo2', 'bar2'], 2) + + expect(snippetString.value).toBe('${1|foo,bar|} ${3|foo3,bar3|} ${2|foo2,bar2|}') + }) + + it('should append variables', () => { + let snippetString = new SnippetString() + .appendVariable('foo', 'abcdef') + .appendText(' ') + .appendVariable('bar') + + expect(snippetString.value).toBe('${foo:abcdef} ${bar}') + + snippetString = new SnippetString() + .appendVariable('foo', s => s.appendText('abcdef')) + .appendText(' ') + .appendVariable('bar') + + expect(snippetString.value).toBe('${foo:abcdef} ${bar}') + }) + }) + + describe('isSnippetString()', () => { + let snippetString = new SnippetString() + expect(SnippetString.isSnippetString(snippetString)).toBe(true) + + let snippetStr = '' + expect(SnippetString.isSnippetString(snippetStr)).toBe(false) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/tree/basicProvider.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/tree/basicProvider.test.ts new file mode 100644 index 00000000..92dc104b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/tree/basicProvider.test.ts @@ -0,0 +1,541 @@ +import { CancellationTokenSource, Disposable } from 'vscode-languageserver-protocol' +import { TreeItemCollapsibleState } from '../../tree' +import commandsManager from '../../commands' +import BasicDataProvider, { TreeNode } from '../../tree/BasicDataProvider' +import { disposeAll } from '../../util' + +let disposables: Disposable[] = [] + +type NodeDef = [string, NodeDef[]?] + +interface CustomNode extends TreeNode { + kind?: string + x?: number + y?: number +} + +afterEach(async () => { + disposeAll(disposables) + disposables = [] +}) + +function createNode(label: string, children?: TreeNode[], key?: string, tooltip?: string): CustomNode { + let res: TreeNode = { label } + if (children) res.children = children + if (tooltip) res.tooltip = tooltip + if (key) res.key = key + return res +} + +let defaultDef: NodeDef[] = [ + ['a', [['c'], ['d']]], + ['b', [['e'], ['f']]], + ['g'] +] + +function createLabels(data: ReadonlyArray): string[] { + let res: string[] = [] + const addLabels = (n: TreeNode, level: number) => { + res.push(' '.repeat(level) + n.label) + if (n.children) { + for (let node of n.children) { + addLabels(node, level + 1) + } + } + } + for (let item of data || []) { + addLabels(item, 0) + } + return res +} + +function findNode(label: string, nodes: ReadonlyArray): TreeNode | undefined { + for (let n of nodes) { + if (n.label == label) { + return n + } + let children = n.children + if (Array.isArray(children)) { + let find = findNode(label, children) + if (find) return find + } + } +} + +function createNodes(defs: NodeDef[]): TreeNode[] { + return defs.map(o => { + let children + if (Array.isArray(o[1])) { + children = createNodes(o[1]) + } + return createNode(o[0], children) + }) +} + +describe('BasicDataProvider', () => { + describe('getChildren()', () => { + it('should get children from root', async () => { + let nodes = createNodes(defaultDef) + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + let res = await provider.getChildren() + expect(res.length).toBe(3) + expect(res.map(o => o.label)).toEqual(['a', 'b', 'g']) + }) + + it('should get children from child node', async () => { + let provider = new BasicDataProvider({ + provideData: () => { + return createNodes(defaultDef) + } + }) + disposables.push(provider) + let res = await provider.getChildren() + let nodes = await provider.getChildren(res[0]) + expect(nodes.length).toBe(2) + expect(nodes.map(o => o.label)).toEqual(['c', 'd']) + }) + + it('should throw when provideData throws', async () => { + let provider = new BasicDataProvider({ + provideData: () => { + throw new Error('my error') + } + }) + disposables.push(provider) + let err + try { + await provider.getChildren() + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + }) + + describe('getTreeItem()', () => { + it('should get tree item from node', async () => { + let provider = new BasicDataProvider({ + provideData: () => { + return createNodes(defaultDef) + } + }) + disposables.push(provider) + let res = await provider.getChildren() + let item = provider.getTreeItem(res[0]) + expect(item).toBeDefined() + expect(item.collapsibleState).toBe(TreeItemCollapsibleState.Collapsed) + item = provider.getTreeItem(res[2]) + expect(item.collapsibleState).toBe(TreeItemCollapsibleState.None) + }) + + it('should respect expandLevel option', async () => { + let provider = new BasicDataProvider({ + expandLevel: 1, + provideData: () => { + return createNodes(defaultDef) + } + }) + disposables.push(provider) + let res = await provider.getChildren() + let item = provider.getTreeItem(res[0]) + expect(item).toBeDefined() + expect(item.collapsibleState).toBe(TreeItemCollapsibleState.Expanded) + }) + + it('should include highlights', async () => { + let provider = new BasicDataProvider({ + provideData: () => { + return [createNode('a', [], undefined, 'tip')] + } + }) + disposables.push(provider) + let res = await provider.getChildren() + let item = provider.getTreeItem(res[0]) + expect(item).toBeDefined() + expect(item.tooltip).toBe('tip') + }) + + it('should use icon from node', async () => { + let node = createNode('a', [], undefined, 'tip') + node.icon = { + text: 'i', + hlGroup: 'Function' + } + let provider = new BasicDataProvider({ + provideData: () => { + return [node] + } + }) + disposables.push(provider) + let res = await provider.getChildren() + let item = provider.getTreeItem(res[0]) + expect(item).toBeDefined() + expect(item.icon).toBeDefined() + expect(item.icon).toEqual({ + text: 'i', + hlGroup: 'Function' + }) + }) + + it('should resolve icon', async () => { + let provider = new BasicDataProvider({ + provideData: () => { + let node = createNode('a', [], undefined, 'tip') + node.kind = 'function' + return [node] + }, + resolveIcon: item => { + if (item.kind === 'function') { + return { + text: 'f', + hlGroup: 'Function' + } + } + } + }) + disposables.push(provider) + let res = await provider.getChildren() + let item = provider.getTreeItem(res[0]) + expect(item).toBeDefined() + expect(item.icon).toEqual({ + text: 'f', + hlGroup: 'Function' + }) + }) + }) + + describe('getParent()', () => { + it('should get undefined when data not exists', async () => { + let node = createNode('a') + let provider = new BasicDataProvider({ + provideData: () => { + return [node] + } + }) + disposables.push(provider) + let res = provider.getParent(node) + expect(res).toBeUndefined() + }) + + it('should get parent node', async () => { + let node = createNode('g') + let provider = new BasicDataProvider({ + provideData: () => { + return [ + createNode('a', [createNode('c', [node]), createNode('d')]), + createNode('b', [createNode('e'), createNode('f')]), + createNode('g') + ] + } + }) + disposables.push(provider) + await provider.getChildren() + let res = provider.getParent(node) + expect(res).toBeDefined() + expect(res.label).toBe('c') + // console.log(provider.labels.join('\n')) + }) + }) + + describe('resolveTreeItem()', () => { + it('should resolve tooltip and command', async () => { + let node = createNode('a') + let provider = new BasicDataProvider({ + provideData: () => { + return [node] + }, + resolveItem: item => { + item.tooltip = 'tip' + item.command = { + command: 'test command', + title: 'test' + } + return item + } + }) + disposables.push(provider) + await provider.getChildren() + let source = new CancellationTokenSource() + let item = provider.getTreeItem(node) + let resolved = await provider.resolveTreeItem(item, node, source.token) + expect(resolved.tooltip).toBe('tip') + expect(resolved.command.command).toBe('test command') + }) + + it('should register command invoke click', async () => { + let node = createNode('a') + let called: TreeNode + let provider = new BasicDataProvider({ + provideData: () => { + return [node] + }, + handleClick: item => { + called = item + } + }) + disposables.push(provider) + await provider.getChildren() + let source = new CancellationTokenSource() + let item = provider.getTreeItem(node) + let resolved = await provider.resolveTreeItem(item, node, source.token) + expect(resolved.command).toBeDefined() + expect(resolved.command.command).toMatch('invoke') + await commandsManager.execute(resolved.command) + expect(called).toBeDefined() + expect(called).toBe(node) + }) + }) + + describe('update()', () => { + it('should add children with event', async () => { + let defs: NodeDef[] = [ + ['a', [['b']]], + ['b', [['f']]] + ] + let nodes = createNodes(defs) + let b = nodes[0].children[0] + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + await provider.getChildren() + let called = false + provider.onDidChangeTreeData(node => { + expect(node).toBe(b) + called = true + }) + let newDefs: NodeDef[] = [ + ['a', [['b', [['c'], ['d']]]]], + ['b', [['f']]] + ] + let curr = provider.update(createNodes(newDefs)) + let labels = createLabels(curr) + expect(labels).toEqual([ + 'a', ' b', ' c', ' d', 'b', ' f' + ]) + expect(called).toBe(true) + expect(b.children).toBeDefined() + expect(b.children.length).toBe(2) + }) + + it('should remove children with event', async () => { + let defs: NodeDef[] = [ + ['a', [['b', [['c'], ['d']]]]], + ['e', [['f']]] + ] + let nodes = createNodes(defs) + let b = nodes[0].children[0] + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + await provider.getChildren() + let called = false + provider.onDidChangeTreeData(node => { + expect(node).toBe(b) + called = true + }) + let newDefs: NodeDef[] = [ + ['a', [['b']]], + ['e', [['f']]] + ] + let curr = provider.update(createNodes(newDefs)) + let labels = createLabels(curr) + expect(labels).toEqual([ + 'a', ' b', 'e', ' f' + ]) + expect(called).toBe(true) + expect(b.children).toBeUndefined() + }) + + it('should not fire event for children when parent have changed', async () => { + let defs: NodeDef[] = [ + ['a', [['b', [['c'], ['d']]]]] + ] + let nodes = createNodes(defs) + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + await provider.getChildren() + let called = 0 + provider.onDidChangeTreeData(node => { + expect(node).toBeUndefined() + called += 1 + }) + let newDefs: NodeDef[] = [ + ['a', [['b', [['c'], ['d'], ['g']]]]], + ['e', [['f']]] + ] + let curr = provider.update(createNodes(newDefs)) + expect(called).toBe(1) + let labels = createLabels(curr) + expect(labels).toEqual([ + 'a', ' b', ' c', ' d', ' g', 'e', ' f' + ]) + }) + + it('should fire events for independent node change', async () => { + let defs: NodeDef[] = [ + ['a', [['b', [['c']]]]], + ['e', [['f']]] + ] + let nodes = createNodes(defs) + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + await provider.getChildren() + let called = [] + provider.onDidChangeTreeData(node => { + called.push(node) + }) + let newDefs: NodeDef[] = [ + ['a', [['b', [['c'], ['d']]]]], + ['e', [['f', [['g']]]]] + ] + let curr = provider.update(createNodes(newDefs)) + expect(called.length).toBe(2) + expect(called[0].label).toBe('b') + expect(called[1].label).toBe('f') + let labels = createLabels(curr) + expect(labels).toEqual([ + 'a', ' b', ' c', ' d', 'e', ' f', ' g' + ]) + }) + + it('should apply new properties', async () => { + let defs: NodeDef[] = [ + ['a', [['b']]], + ['e', [['f']]] + ] + let nodes = createNodes(defs) + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + await provider.getChildren() + let newNodes = createNodes([ + ['a', [['b', [['c']]]]], + ['e', [['f', [['g']]]]] + ]) + let b = newNodes[0].children[0] + Object.assign(b, { x: 1, y: 2 }) + let curr = provider.update(newNodes) + let node = curr[0].children[0] + expect(node).toBeDefined() + expect(node.x).toBe(1) + expect(node.y).toBe(2) + }) + + it('should keep references and have new data sequence', async () => { + let defs: NodeDef[] = [ + ['a', [['b'], ['c']]], + ['e', [['f']]], + ['g'] + ] + let nodes = createNodes(defs) + let keeps = [ + findNode('a', nodes), + findNode('b', nodes), + findNode('c', nodes), + findNode('e', nodes), + findNode('f', nodes), + ] + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + await provider.getChildren() + let newNodes = createNodes([ + ['a', [['c', [['d'], ['h']]], ['b']]], + ['e', [['f', [['j']]], ['i']]] + ]) + let curr = provider.update(newNodes) + expect(curr).toBe(nodes) + expect(keeps[0]).toBe(findNode('a', curr)) + expect(keeps[1]).toBe(findNode('b', curr)) + expect(keeps[2]).toBe(findNode('c', curr)) + expect(keeps[3]).toBe(findNode('e', curr)) + expect(keeps[4]).toBe(findNode('f', curr)) + let labels = createLabels(curr) + expect(labels).toEqual([ + 'a', ' c', ' d', ' h', ' b', 'e', ' f', ' j', ' i' + ]) + }) + + it('should use key for nodes', async () => { + let nodes = [ + createNode('a', [], 'x'), + createNode('a', [], 'y'), + createNode('a', [], 'z'), + ] + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + await provider.getChildren() + let newNodes = [ + createNode('a', [], 'x'), + createNode('a', [], 'z'), + ] + let curr = provider.update(newNodes) + expect(curr.length).toBe(2) + expect(curr[0].key).toBe('x') + expect(curr[1].key).toBe('z') + }) + + it('should reset data', async () => { + let nodes = [ + createNode('a', [], 'x'), + ] + let provider = new BasicDataProvider({ + provideData: () => { + return nodes + } + }) + disposables.push(provider) + await provider.getChildren() + let newNodes = [ + createNode('a', [], 'x'), + ] + let curr = provider.update(newNodes, true) + expect(curr === nodes).toBe(false) + }) + }) + + describe('dispose', () => { + it('should invoke onDispose from opts', async () => { + let called = false + let provider = new BasicDataProvider({ + provideData: () => { + return [] + }, + onDispose: () => { + called = true + } + }) + provider.dispose() + expect(called).toBe(true) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/tree/treeView.test.ts b/vim-config/plugins/coc.nvim/src/__tests__/tree/treeView.test.ts new file mode 100644 index 00000000..6b0aa605 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/tree/treeView.test.ts @@ -0,0 +1,1146 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import TreeView from '../../tree/TreeView' +import { TreeItem } from '../../tree/TreeItem' +import BasicDataProvider, { ProviderOptions, TreeNode } from '../../tree/BasicDataProvider' +import { disposeAll } from '../../util' +import events from '../../events' +import workspace from '../../workspace' +import helper from '../helper' +import { TreeViewOptions } from '../../tree' + +type NodeDef = [string, NodeDef[]?] + +let nvim: Neovim +let disposables: Disposable[] = [] +let treeView: TreeView +let provider: BasicDataProvider +let nodes: TreeNode[] +beforeAll(async () => { + await helper.setup() + nvim = helper.nvim +}) + +afterAll(async () => { + await helper.shutdown() +}) + +beforeEach(async () => { + await helper.createDocument() +}) + +afterEach(async () => { + if (provider) provider.dispose() + if (treeView) treeView.dispose() + disposeAll(disposables) + await helper.reset() +}) + +function createNode(label: string, children?: TreeNode[], key?: string, tooltip?: string): TreeNode { + let res: TreeNode = { label } + if (children) res.children = children + if (tooltip) res.tooltip = tooltip + if (key) res.key = key + return res +} + +function createNodes(defs: NodeDef[]): TreeNode[] { + return defs.map(o => { + let children + if (Array.isArray(o[1])) { + children = createNodes(o[1]) + } + return createNode(o[0], children) + }) +} + +function createTreeView(defs: NodeDef[], opts: Partial> = {}, providerOpts: Partial> = {}) { + nodes = createNodes(defs) + provider = new BasicDataProvider(Object.assign(providerOpts, { + provideData: () => { + return nodes + } + })) + treeView = new TreeView('test', Object.assign(opts, { + treeDataProvider: provider + })) +} + +function updateData(defs: NodeDef[], reset = false) { + nodes = createNodes(defs) + provider.update(nodes, reset) +} + +function makeUpdateUIThrowError() { + (treeView as any).updateUI = () => { + throw new Error('Error on updateUI') + } +} + +let defaultDef: NodeDef[] = [ + ['a', [['c'], ['d']]], + ['b', [['e'], ['f']]], + ['g'] +] + +async function checkLines(arr: string[]): Promise { + let lines = await nvim.call('getline', [1, '$']) + expect(lines).toEqual(arr) +} + +describe('TreeView', () => { + describe('TreeItem()', () => { + it('should create TreeItem from resourceUri', async () => { + let item = new TreeItem(URI.file('/foo/bar.ts')) + expect(item.resourceUri).toBeDefined() + expect(item.label).toBe('bar.ts') + expect(item.label).toBeDefined() + }) + }) + + describe('show()', () => { + it('should show with title', async () => { + createTreeView(defaultDef) + expect(treeView).toBeDefined() + await treeView.show() + let visible = treeView.visible + expect(visible).toBe(true) + await helper.wait(50) + await checkLines(['test', '+ a', '+ b', ' g']) + }) + + it('should not show when visible', async () => { + createTreeView(defaultDef) + await treeView.show() + let windowId = treeView.windowId + await treeView.show() + expect(treeView.windowId).toBe(windowId) + }) + + it('should reuse window', async () => { + createTreeView(defaultDef) + await treeView.show() + let windowId = treeView.windowId + await helper.wait(50) + provider.dispose() + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + expect(treeView.windowId).toBe(windowId) + }) + + it('should render item icon', async () => { + createTreeView(defaultDef) + nodes[0].icon = { text: 'i', hlGroup: 'Title' } + nodes[1].icon = { text: 'i', hlGroup: 'Title' } + nodes[2].icon = { text: 'i', hlGroup: 'Title' } + await treeView.show() + await helper.wait(50) + await checkLines(['test', '+ i a', '+ i b', ' i g']) + }) + }) + + describe('configuration', () => { + afterAll(() => { + let { configurations } = workspace + configurations.updateUserConfig({ + 'tree.openedIcon': '-', + 'tree.closedIcon': '+', + }) + }) + + it('should change open close icon', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + let { configurations } = workspace + configurations.updateUserConfig({ + 'tree.openedIcon': '', + 'tree.closedIcon': '', + }) + await helper.wait(50) + await checkLines(['test', ' a', ' b', ' g']) + }) + }) + + describe('public properties', () => { + it('should change title', async () => { + createTreeView(defaultDef) + treeView.title = 'foo' + await treeView.show() + await helper.wait(50) + await checkLines(['foo', '+ a', '+ b', ' g']) + treeView.title = 'bar' + await helper.wait(50) + await checkLines(['bar', '+ a', '+ b', ' g']) + treeView.title = undefined + await helper.wait(50) + await checkLines(['+ a', '+ b', ' g']) + makeUpdateUIThrowError() + treeView.title = 'xyz' + await helper.wait(50) + await checkLines(['+ a', '+ b', ' g']) + }) + + it('should change description', async () => { + createTreeView(defaultDef) + treeView.description = 'desc' + await treeView.show() + await helper.wait(50) + await checkLines(['test desc', '+ a', '+ b', ' g']) + treeView.description = 'foo bar' + await helper.wait(50) + await checkLines(['test foo bar', '+ a', '+ b', ' g']) + treeView.description = '' + await helper.wait(50) + await checkLines(['test', '+ a', '+ b', ' g']) + makeUpdateUIThrowError() + treeView.description = 'desc' + await helper.wait(50) + await checkLines(['test', '+ a', '+ b', ' g']) + }) + + it('should change message', async () => { + createTreeView(defaultDef) + treeView.message = 'hello' + await treeView.show() + await helper.wait(50) + await checkLines(['hello', '', 'test', '+ a', '+ b', ' g']) + treeView.message = 'foo' + await helper.wait(50) + await checkLines(['foo', '', 'test', '+ a', '+ b', ' g']) + treeView.message = undefined + await helper.wait(50) + await checkLines(['test', '+ a', '+ b', ' g']) + makeUpdateUIThrowError() + treeView.message = 'bar' + await helper.wait(50) + await checkLines(['test', '+ a', '+ b', ' g']) + }) + }) + + describe('options', () => { + it('should disable winfixwidth', async () => { + createTreeView(defaultDef, { winfixwidth: false }) + await treeView.show() + let res = await nvim.eval('&winfixwidth') + expect(res).toBe(0) + }) + + it('should disable leaf indent', async () => { + createTreeView(defaultDef, { disableLeafIndent: true }) + await treeView.show() + await helper.wait(50) + await checkLines(['test', '+ a', '+ b', 'g']) + }) + + it('should support many selection', async () => { + createTreeView(defaultDef, { canSelectMany: true }) + await treeView.show() + await helper.wait(50) + let selection: TreeNode[] + treeView.onDidChangeSelection(e => { + selection = e.selection + }) + await nvim.command('exe 1') + await nvim.input('') + await helper.wait(10) + await nvim.command('exe 2') + await nvim.input('') + await helper.wait(50) + expect(selection.length).toBe(1) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + expect(selection.length).toBe(2) + await nvim.input('') + await helper.wait(50) + expect(selection.length).toBe(1) + let buf = await nvim.buffer + let res = await nvim.call('sign_getplaced', [buf.id, { group: 'CocTree' }]) + let signs = res[0].signs + expect(treeView.selection.length).toBe(1) + expect(signs.length).toBe(1) + expect(signs[0]).toEqual({ + lnum: 2, + id: 3001, + name: 'CocTreeSelected', + priority: 10, + group: 'CocTree' + }) + }) + }) + + describe('key-mappings', () => { + it('should jump back by ', async () => { + let winid = await nvim.call('win_getid') + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + let win = await nvim.window + expect(win.id).toBe(winid) + }) + + it('should toggle selection by ', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + let selection: TreeNode[] + treeView.onDidChangeSelection(e => { + selection = e.selection + }) + await nvim.command('exe 1') + await nvim.input('') + await helper.wait(10) + await nvim.command('exe 2') + await nvim.input('') + await helper.wait(50) + expect(selection.length).toBe(1) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + let buf = await nvim.buffer + let res = await nvim.call('sign_getplaced', [buf.id, { group: 'CocTree' }]) + let signs = res[0].signs + expect(treeView.selection.length).toBe(1) + expect(signs.length).toBe(1) + expect(signs[0]).toEqual({ + lnum: 3, + id: 3002, + name: 'CocTreeSelected', + priority: 10, + group: 'CocTree' + }) + await nvim.input('') + await helper.wait(50) + res = await nvim.call('sign_getplaced', [buf.id, { group: 'CocTree' }]) + signs = res[0].signs + expect(signs.length).toBe(0) + }) + + it('should reset signs after expand & collapse', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + await checkLines([ + 'test', + '- a', + ' c', + ' d', + '+ b', + ' g', + ]) + await nvim.command('exe 3') + await nvim.input('') + await helper.wait(50) + let buf = await nvim.buffer + let res = await nvim.call('sign_getplaced', [buf.id, { group: 'CocTree' }]) + expect(res[0].signs.length).toBe(1) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + res = await nvim.call('sign_getplaced', [buf.id, { group: 'CocTree' }]) + expect(res[0].signs.length).toBe(0) + await nvim.input('t') + await helper.wait(100) + res = await nvim.call('sign_getplaced', [buf.id, { group: 'CocTree' }]) + expect(res[0].signs.length).toBe(1) + }) + + it('should close tree view by ', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + expect(treeView.visible).toBe(true) + await nvim.input('') + await helper.wait(50) + expect(treeView.visible).toBe(false) + }) + + it('should invoke command by ', async () => { + let node: TreeNode + createTreeView(defaultDef, {}, { + handleClick: n => { + node = n + } + }) + await treeView.show() + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + expect(node).toBeUndefined() + await nvim.command('exe 2') + await nvim.input('') + await helper.wait(50) + expect(node.label).toBe('a') + }) + + it('should not throw when resolve command cancelled', async () => { + let node: TreeNode + let cancelled = false + createTreeView(defaultDef, {}, { + handleClick: n => { + node = n + }, + resolveItem: (item, _node, token) => { + return new Promise(resolve => { + let timer = setTimeout(() => { + item.command = { + title: 'not exists', + command: 'test' + } + resolve(item) + }, 5000) + token.onCancellationRequested(() => { + cancelled = true + clearTimeout(timer) + resolve(item) + }) + }) + } + }) + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('') + await helper.wait(50) + await nvim.command('exe 1') + await helper.wait(50) + expect(cancelled).toBe(true) + expect(node).toBeUndefined() + }) + + it('should toggle expand by t', async () => { + createTreeView(defaultDef) + let c = nodes[0].children[0] + c.children = [createNode('h')] + await treeView.show() + await helper.wait(50) + await nvim.command('exe 1') + await nvim.input('t') + await helper.wait(50) + await nvim.command('exe 3') + await nvim.input('t') + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + await checkLines([ + 'test', '- a', ' + c', ' d', '- b', ' e', ' f', ' g' + ]) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + await checkLines([ + 'test', '+ a', '- b', ' e', ' f', ' g' + ]) + }) + + it('should should collapse parent node by t', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + await checkLines([ + 'test', + '- a', + ' c', + ' d', + '+ b', + ' g', + ]) + await nvim.command('exe 3') + await nvim.input('t') + await helper.wait(50) + await checkLines([ + 'test', + '+ a', + '+ b', + ' g', + ]) + }) + + it('should collapse all nodes by M', async () => { + createTreeView(defaultDef) + let c = nodes[0].children[0] + c.children = [createNode('h')] + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + await nvim.command('exe 3') + await nvim.input('t') + await helper.wait(50) + await nvim.command('exe 6') + await nvim.input('t') + await helper.wait(50) + await checkLines([ + 'test', + '- a', + ' - c', + ' h', + ' d', + '- b', + ' e', + ' f', + ' g', + ]) + await nvim.input('M') + await helper.wait(50) + await checkLines([ + 'test', + '+ a', + '+ b', + ' g', + ]) + let res = await treeView.checkLines() + expect(res).toBe(true) + }) + + it('should toggle expand on open/close icon click ', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await nvim.call('cursor', [1, 1]) + await nvim.input('') + await helper.wait(50) + await nvim.call('cursor', [2, 1]) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', + '- a', + ' c', + ' d', + '+ b', + ' g', + ]) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', + '+ a', + '+ b', + ' g', + ]) + let res = await treeView.checkLines() + expect(res).toBe(true) + }) + + it('should invoke command on node click', async () => { + let node: TreeNode + createTreeView(defaultDef, {}, { + handleClick: n => { + node = n + } + }) + await treeView.show() + await helper.wait(50) + await nvim.call('cursor', [2, 3]) + await nvim.input('') + await helper.wait(50) + expect(node).toBeDefined() + expect(node.label).toBe('a') + }) + }) + + describe('invokeActions', () => { + it('should show warning when resolveActions not exists', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await nvim.call('cursor', [2, 3]) + await nvim.input('') + await helper.wait(50) + let cmdline = await helper.getCmdline() + expect(cmdline).toMatch('No actions') + }) + + it('should show warning when resolveActions is empty', async () => { + createTreeView(defaultDef, {}, { + resolveActions: () => { + return [] + } + }) + await treeView.show() + await helper.wait(50) + await nvim.call('cursor', [2, 3]) + await nvim.input('') + await helper.wait(50) + let cmdline = await helper.getCmdline() + expect(cmdline).toMatch('No actions') + }) + + it('should invoke selected action', async () => { + let args: any[] + let called = false + createTreeView(defaultDef, {}, { + resolveActions: (item, element) => { + args = [item, element] + return [{ + title: 'one', + handler: () => { + called = true + } + }] + } + }) + await treeView.show() + await helper.wait(50) + await nvim.call('cursor', [2, 3]) + await nvim.input('') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + expect(called).toBe(true) + expect(args[0].label).toBe('a') + expect(args[1].label).toBe('a') + }) + }) + + describe('events', () => { + it('should emit visibility change on buffer unload', async () => { + createTreeView(defaultDef) + let visible + treeView.onDidChangeVisibility(e => { + visible = e.visible + }) + await treeView.show() + await helper.wait(50) + let buf = await nvim.buffer + nvim.command(`bd! ${buf.id}`, true) + await helper.wait(50) + expect(visible).toBe(false) + }) + + it('should show tooltip on CursorHold', async () => { + createTreeView(defaultDef, {}, { + resolveItem: (item, node) => { + if (node.label == 'a') { + item.tooltip = 'first' + } + if (node.label == 'b') { + item.tooltip = { kind: 'markdown', value: '#title' } + } + return item + } + }) + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + let bufnr = await nvim.eval(`bufnr('%')`) as number + await events.fire('CursorHold', [bufnr]) + let win = await helper.getFloat() + expect(win).toBeDefined() + let buf = await win.buffer + let lines = await buf.lines + expect(lines).toEqual(['first']) + await helper.wait(50) + await nvim.command('exe 3') + await events.fire('CursorHold', [bufnr]) + lines = await buf.lines + expect(lines).toEqual(['#title']) + }) + }) + + describe('data change', () => { + it('should ignore hidden node change', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + let tick = await nvim.eval('b:changedtick') + updateData([ + ['a', [['c', [['h']]], ['d']]], + ['b', [['e'], ['f']]], + ['g'] + ]) + await helper.wait(50) + let curr = await nvim.eval('b:changedtick') + expect(curr).toBe(tick) + }) + + it('should render all nodes on root change', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + updateData([ + ['g'], + ['h'], + ['b', [['e'], ['f']]], + ['a', [['c'], ['d']]] + ]) + await helper.wait(50) + await checkLines([ + 'test', + ' g', + ' h', + '+ b', + '+ a', + ]) + let res = await treeView.checkLines() + expect(res).toBe(true) + }) + + it('should keep node open state', async () => { + createTreeView(defaultDef) + let c = nodes[0].children[0] + c.children = [createNode('h')] + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + await nvim.command('exe 3') + await nvim.input('t') + await helper.wait(50) + await nvim.command('exe 6') + await nvim.input('t') + await helper.wait(50) + updateData([ + ['h'], + ['g', [['i']]], + ['b', [['f']]], + ['a', [['c'], ['j']]] + ]) + await helper.wait(50) + await checkLines([ + 'test', + ' h', + '+ g', + '- b', + ' f', + '- a', + ' c', + ' j', + ]) + let res = await treeView.checkLines() + expect(res).toBe(true) + }) + + it('should render changed nodes', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + updateData([ + ['a', [['h', [['i']]], ['d']]], + ['b', [['e'], ['f']]], + ['g'], + ]) + await helper.wait(50) + await checkLines([ + 'test', + '- a', + ' + h', + ' d', + '+ b', + ' g', + ]) + let res = await treeView.checkLines() + expect(res).toBe(true) + }) + + it('should error message on error', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await nvim.command('exe 2') + await nvim.input('t') + await helper.wait(50) + let msg = 'Unable to fetch children' + provider.getChildren = () => { + throw new Error(msg) + } + updateData([['a']]) + await helper.wait(50) + let line = await nvim.call('getline', [1]) + expect(line).toMatch(msg) + let res = await treeView.checkLines() + expect(res).toBe(true) + }) + + it('should show error message on refresh error', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + makeUpdateUIThrowError() + updateData([ + ['a', [['h'], ['d']]], + ['b', [['e'], ['f']]], + ['g'], + ]) + await helper.wait(50) + let line = await helper.getCmdline() + expect(line).toMatch('Error on updateUI') + }) + + it('should render deprecated node with deprecated highlight', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + let defs: NodeDef[] = [ + ['a'], + ['b'] + ] + let nodes = createNodes(defs) + nodes[0].deprecated = true + provider.update(nodes) + await helper.wait(50) + await checkLines([ + 'test', + ' a', + ' b', + ]) + let ns = await nvim.call('coc#highlight#create_namespace', ['tree']) + let bufnr = await nvim.call('bufnr', ['%']) + let markers = await nvim.call('nvim_buf_get_extmarks', [bufnr, ns, [1, 0], [1, -1], { details: true }]) as any[] + expect(markers.length > 0).toBe(true) + expect(markers[0][3]['hl_group']).toBe('CocDeprecatedHighlight') + }) + }) + + describe('focusItem()', () => { + it('should not throw when node not rendered', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + let c = nodes[0].children[0] + treeView.focusItem(c) + }) + + it('should focus rendered node', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + treeView.focusItem(nodes[1]) + await helper.wait(50) + let line = await nvim.call('getline', ['.']) + expect(line).toBe('+ b') + }) + }) + + describe('reveal()', () => { + it('should throw error when getParent not exists', async () => { + createTreeView(defaultDef) + provider.getParent = undefined + await treeView.show() + await helper.wait(50) + let err + try { + await treeView.reveal(nodes[0].children[0]) + } catch (e) { + err = e + } + expect(err).toBeDefined() + }) + + it('should select item', async () => { + createTreeView(defaultDef) + let c = nodes[0].children[0] + let h = createNode('h') + c.children = [h] + await treeView.show() + await helper.wait(50) + await treeView.reveal(h) + await checkLines([ + 'test', + '- a', + ' - c', + ' h', + ' d', + '+ b', + ' g', + ]) + let selection = treeView.selection + expect(selection.length).toBe(1) + expect(selection[0].label).toBe('h') + let line = await nvim.call('getline', ['.']) + expect(line).toMatch('h') + }) + + it('should not select item', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await treeView.reveal(nodes[1], { select: false }) + let lnum = await nvim.call('line', ['.']) + expect(lnum).toBe(1) + }) + + it('should focus item', async () => { + createTreeView(defaultDef) + await treeView.show() + await helper.wait(50) + await treeView.reveal(nodes[1], { focus: true }) + let line = await nvim.call('getline', ['.']) + expect(line).toMatch('b') + }) + + it('should expand item whih single level', async () => { + createTreeView(defaultDef) + let c = nodes[0].children[0] + c.children = [createNode('h')] + await treeView.show() + await helper.wait(50) + await treeView.reveal(nodes[0], { expand: true }) + await checkLines([ + 'test', + '- a', + ' + c', + ' d', + '+ b', + ' g', + ]) + }) + + it('should expand item whih 2 level', async () => { + createTreeView(defaultDef) + let c = nodes[0].children[0] + c.children = [createNode('h')] + await treeView.show() + await helper.wait(50) + await treeView.reveal(nodes[0], { expand: 2 }) + await checkLines([ + 'test', + '- a', + ' - c', + ' h', + ' d', + '+ b', + ' g', + ]) + }) + }) + + describe('filter', () => { + async function createFilterTreeView(opts: Partial> = {}): Promise { + createTreeView(defaultDef, { enableFilter: true }, opts) + await treeView.show() + await helper.wait(50) + await nvim.input('f') + await helper.wait(50) + } + + it('should start filter by input', async () => { + await createFilterTreeView() + await checkLines([ + 'test', ' ', ' a', ' c', ' d', ' b', ' e', ' f', ' g' + ]) + await nvim.input('a') + await helper.wait(50) + await checkLines([ + 'test', + 'a ', + ' a', + ]) + }) + + it('should not throw error on filter', async () => { + await createFilterTreeView() + ; (treeView as any).getRenderedLine = () => { + throw new Error('Error on updateUI') + } + await nvim.input('a') + await helper.wait(100) + }) + + it('should add & remove Cursor highlight on window change', async () => { + let winid = await nvim.call('win_getid') + let ns = await nvim.call('coc#highlight#create_namespace', ['tree']) + await createFilterTreeView() + let bufnr = await nvim.call('bufnr', ['%']) + let markers = await nvim.call('nvim_buf_get_extmarks', [bufnr, ns, [1, 0], [1, -1], {}]) as [number, number, number][] + expect(markers[0]).toBeDefined() + await nvim.call('win_gotoid', [winid]) + await helper.wait(50) + markers = await nvim.call('nvim_buf_get_extmarks', [bufnr, ns, [1, 0], [1, -1], {}]) as [number, number, number][] + expect(markers.length).toBe(0) + await nvim.command('wincmd p') + await helper.wait(50) + markers = await nvim.call('nvim_buf_get_extmarks', [bufnr, ns, [1, 0], [1, -1], {}]) as [number, number, number][] + expect(markers.length).toBe(1) + }) + + it('should filter new nodes on data change', async () => { + await createFilterTreeView() + await nvim.input('a') + await helper.wait(50) + updateData([ + ['ab'], + ['e'], + ['fa'] + ]) + await helper.wait(50) + await checkLines([ + 'test', + 'a ', + ' ab', + ' fa', + ]) + }) + + it('should change selected item by and ', async () => { + await createFilterTreeView() + await nvim.input('a') + await helper.wait(50) + updateData([ + ['ab'], + ['fa'] + ]) + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + let curr = treeView.selection[0] + expect(curr.label).toBe('fa') + await nvim.input('') + await helper.wait(50) + curr = treeView.selection[0] + expect(curr.label).toBe('ab') + await nvim.input('') + await helper.wait(50) + curr = treeView.selection[0] + expect(curr.label).toBe('fa') + await nvim.input('') + await helper.wait(50) + curr = treeView.selection[0] + expect(curr.label).toBe('ab') + }) + + it('should not throw with empty nodes', async () => { + await createFilterTreeView() + await nvim.input('ab') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + await checkLines(['test', 'ab ']) + let curr = treeView.selection[0] + expect(curr).toBeUndefined() + }) + + it('should invoke command by ', async () => { + let node + await createFilterTreeView({ + handleClick: n => { + node = n + } + }) + await nvim.input('') + await helper.wait(50) + expect(node).toBeDefined() + let curr = treeView.selection[0] + expect(curr).toBeDefined() + }) + + it('should keep state when press with empty selection ', async () => { + await createFilterTreeView() + await nvim.input('ab') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + await checkLines(['test', 'ab ']) + }) + + it('should delete last filter character by ', async () => { + await createFilterTreeView() + await nvim.input('a') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', ' ', ' a', ' c', ' d', ' b', ' e', ' f', ' g' + ]) + }) + + it('should clean filter character by ', async () => { + await createFilterTreeView() + await nvim.input('ab') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', ' ', ' a', ' c', ' d', ' b', ' e', ' f', ' g' + ]) + }) + + it('should cancel filter by and ', async () => { + await createFilterTreeView() + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', + '+ a', + '+ b', + ' g', + ]) + await nvim.input('f') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', + '+ a', + '+ b', + ' g', + ]) + }) + + it('should navigate input history by and ', async () => { + await createFilterTreeView() + await nvim.input('a') + await helper.wait(20) + await nvim.input('') + await helper.wait(50) + await nvim.input('f') + await helper.wait(50) + await nvim.input('b') + await helper.wait(20) + await nvim.input('') + await helper.wait(50) + await nvim.input('f') + await helper.wait(50) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', + 'a ', + ' a', + ]) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', + 'b ', + ' b', + ]) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', + 'a ', + ' a', + ]) + await nvim.input('') + await helper.wait(50) + await checkLines([ + 'test', + 'b ', + ' b', + ]) + }) + }) +}) diff --git a/vim-config/plugins/coc.nvim/src/__tests__/vimrc b/vim-config/plugins/coc.nvim/src/__tests__/vimrc new file mode 100644 index 00000000..60d51897 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/__tests__/vimrc @@ -0,0 +1,26 @@ +set nocompatible + +set hidden +set noswapfile +set nobackup +set completeopt=menuone,noinsert,noselect +set tabstop=2 +set cmdheight=2 +set shiftwidth=2 +set updatetime=300 +set expandtab +set noshowmode +set shortmess=at + +let s:dir = expand(':h') +let s:root = expand(':h:h:h') +let g:coc_node_env = 'test' + +let g:coc_vim_commands = [{ + \ "id": "config", + \ "cmd": "edit coc-settings.json" + \ }] + +autocmd BufNewFile,BufRead *.ts set filetype=typescript + +execute 'set runtimepath+='.s:root diff --git a/vim-config/plugins/coc.nvim/src/attach.ts b/vim-config/plugins/coc.nvim/src/attach.ts new file mode 100644 index 00000000..7650d0cd --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/attach.ts @@ -0,0 +1,133 @@ +import { attach, Attach, NeovimClient } from '@chemzqm/neovim' +import log4js from 'log4js' +import events from './events' +import Plugin from './plugin' +import semver from 'semver' +import { objectLiteral } from './util/is' +import { URI } from 'vscode-uri' +import { version as VERSION } from '../package.json' + +const logger = require('./util/logger')('attach') +const isTest = global.hasOwnProperty('__TEST__') +/** + * Request actions that not need plugin ready + */ +const ACTIONS_NO_WAIT = ['installExtensions', 'updateExtensions'] + +export default (opts: Attach, requestApi = true): Plugin => { + const nvim: NeovimClient = attach(opts, log4js.getLogger('node-client'), requestApi) + if (!global.hasOwnProperty('__TEST__')) { + nvim.call('coc#util#path_replace_patterns').then(prefixes => { + if (objectLiteral(prefixes)) { + const old_uri = URI.file + URI.file = (path): URI => { + path = path.replace(/\\/g, '/') + Object.keys(prefixes).forEach(k => path = path.replace(new RegExp('^' + k), prefixes[k])) + return old_uri(path) + } + } + }).logError() + } + nvim.setVar('coc_process_pid', process.pid, true) + const plugin = new Plugin(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 'Log': { + logger.debug(...args) + break + } + case 'TaskExit': + case 'TaskStderr': + case 'TaskStdout': + case 'GlobalChange': + case 'PromptInsert': + case 'InputChar': + case 'MenuInput': + case 'OptionSet': + case 'FloatBtnClick': + await events.fire(method, args) + break + case 'CocAutocmd': + logger.trace('Notification autocmd:', ...args) + await events.fire(args[0], args.slice(1)) + break + default: { + let exists = plugin.hasAction(method) + if (!exists) { + if (global.hasOwnProperty('__TEST__')) return + console.error(`action "${method}" not exists`) + return + } + try { + if (!plugin.isReady) { + logger.warn(`Plugin not ready when received "${method}"`, args) + } else { + logger.info('receive notification:', method, args) + } + await plugin.ready + await plugin.cocAction(method, ...args) + } catch (e) { + console.error(`Error on "${method}": ${e.message || e.toString()}`) + logger.error(`Notification error:`, method, args, e) + } + } + } + }) + + nvim.on('request', async (method: string, args, resp) => { + if (method == 'redraw') { + // ignore redraw from neovim + resp.send() + return + } + let timer = setTimeout(() => { + logger.error('Request cost more than 3s', method, args) + }, 3000) + try { + if (method == 'CocAutocmd') { + logger.trace('Request autocmd:', ...args) + await events.fire(args[0], args.slice(1)) + resp.send(undefined) + } else { + if (!plugin.isReady && !ACTIONS_NO_WAIT.includes(method)) { + logger.warn(`Plugin not ready on request "${method}"`, args) + resp.send('Plugin not ready', true) + return + } + logger.info('Request action:', method, args) + let res = await plugin.cocAction(method, ...args) + resp.send(res) + } + clearTimeout(timer) + } catch (e) { + clearTimeout(timer) + resp.send(e.message || e.toString(), true) + logger.error(`Request error:`, method, args, e) + } + }) + + nvim.channelId.then(async channelId => { + clientReady = true + // Used for test client on vim side + if (isTest) nvim.command(`let g:coc_node_channel_id = ${channelId}`, true) + let { major, minor, patch } = semver.parse(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}`) + }) + return plugin +} diff --git a/vim-config/plugins/coc.nvim/src/channels.ts b/vim-config/plugins/coc.nvim/src/channels.ts new file mode 100644 index 00000000..6d5b6864 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/channels.ts @@ -0,0 +1,82 @@ +import { Neovim } from '@chemzqm/neovim' +import { URI } from 'vscode-uri' +import BufferChannel from './model/outputChannel' +import { Disposable } from 'vscode-languageserver-protocol' +import { TextDocumentContentProvider } from './provider' +import events from './events' +import { OutputChannel } from './types' +const logger = require('./util/logger')('channels') + +export class Channels { + private outputChannels: Map = new Map() + private bufnrs: Map = new Map() + private disposable: Disposable + constructor() { + this.disposable = events.on('BufUnload', bufnr => { + let name = this.bufnrs.get(bufnr) + if (name) { + let channel = this.outputChannels.get(name) + if (channel) channel.created = false + } + }) + } + + /** + * Get text document provider + */ + public getProvider(nvim: Neovim): TextDocumentContentProvider { + let provider: TextDocumentContentProvider = { + onDidChange: null, + provideTextDocumentContent: async (uri: URI) => { + let channel = this.get(uri.path.slice(1)) + if (!channel) return '' + nvim.pauseNotification() + nvim.call('bufnr', ['%'], true) + nvim.command('setlocal nospell nofoldenable nowrap noswapfile', true) + nvim.command('setlocal buftype=nofile bufhidden=hide', true) + nvim.command('setfiletype log', true) + let res = await nvim.resumeNotification() + if (!res[1]) { + this.bufnrs.set(res[0][0], channel.name) + channel.created = true + } + return channel.content + } + } + return provider + } + + public get names(): string[] { + return Array.from(this.outputChannels.keys()) + } + + public get(channelName: string): BufferChannel | null { + return this.outputChannels.get(channelName) + } + + public create(name: string, nvim: Neovim): OutputChannel | null { + if (this.outputChannels.has(name)) return this.outputChannels.get(name) + if (!/^[\w\s-.]+$/.test(name)) throw new Error(`Invalid channel name "${name}", only word characters and white space allowed.`) + let channel = new BufferChannel(name, nvim, () => { + this.outputChannels.delete(name) + }) + this.outputChannels.set(name, channel) + return channel + } + + public show(name: string, preserveFocus?: boolean): void { + let channel = this.outputChannels.get(name) + if (!channel) return + channel.show(preserveFocus) + } + + public dispose(): void { + this.disposable.dispose() + for (let channel of this.outputChannels.values()) { + channel.dispose() + } + this.outputChannels.clear() + } +} + +export default new Channels() diff --git a/vim-config/plugins/coc.nvim/src/commands.ts b/vim-config/plugins/coc.nvim/src/commands.ts new file mode 100644 index 00000000..704a94bc --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/commands.ts @@ -0,0 +1,379 @@ +import { Neovim } from '@chemzqm/neovim' +import * as language from 'vscode-languageserver-protocol' +import { CodeAction, Disposable, Location, Position, Range, TextDocumentEdit, TextEdit, WorkspaceEdit } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import diagnosticManager from './diagnostic/manager' +import Mru from './model/mru' +import Plugin from './plugin' +import snipetsManager from './snippets/manager' +import { wait } from './util' +import workspace from './workspace' +import window from './window' +const logger = require('./util/logger')('commands') + +// command center +export interface Command { + readonly id: string | string[] + execute(...args: any[]): void | Promise +} + +class CommandItem implements Disposable, Command { + constructor( + public id: string, + private impl: (...args: any[]) => void, + private thisArg: any, + public internal = false + ) { + } + + public execute(...args: any[]): void | Promise { + let { impl, thisArg } = this + return impl.apply(thisArg, args || []) + } + + public dispose(): void { + this.thisArg = null + this.impl = null + } +} + +export class CommandManager implements Disposable { + private readonly commands = new Map() + public titles = new Map() + public onCommandList: string[] = [] + private mru: Mru + + public init(nvim: Neovim, plugin: Plugin): void { + this.mru = workspace.createMru('commands') + this.register({ + id: 'vscode.open', + execute: async (url: string | URI) => { + nvim.call('coc#util#open_url', url.toString(), true) + } + }, true) + this.register({ + id: 'workbench.action.reloadWindow', + execute: async () => { + await nvim.command('edit') + } + }, true) + this.register({ + id: 'editor.action.insertSnippet', + execute: async (edit: TextEdit) => { + nvim.call('coc#_cancel', [], true) + return await snipetsManager.insertSnippet(edit.newText, true, edit.range) + } + }, true) + this.register({ + id: 'editor.action.doCodeAction', + execute: async (action: CodeAction) => { + await plugin.cocAction('doCodeAction', action) + } + }, true) + this.register({ + id: 'editor.action.triggerSuggest', + execute: async () => { + await wait(60) + nvim.call('coc#start', [], true) + } + }, true) + this.register({ + id: 'editor.action.triggerParameterHints', + execute: async () => { + await wait(60) + await plugin.cocAction('showSignatureHelp') + } + }, true) + this.register({ + id: 'editor.action.addRanges', + execute: async (ranges: Range[]) => { + await plugin.cocAction('addRanges', ranges) + } + }, true) + this.register({ + id: 'editor.action.restart', + execute: async () => { + await wait(30) + nvim.command('CocRestart', true) + } + }, true) + this.register({ + id: 'editor.action.showReferences', + execute: async (_filepath: string, _position: Position, references: Location[]) => { + await workspace.showLocations(references) + } + }, true) + this.register({ + id: 'editor.action.rename', + execute: async (uri: string, position: Position) => { + await workspace.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.clearWatchman', + execute: async () => { + let res = await window.runTerminalCommand('watchman watch-del-all') + if (res.success) window.showMessage('Cleared watchman watching directories.') + } + }, false, 'run watch-del-all for watchman to free up memory.') + this.register({ + id: 'workspace.workspaceFolders', + execute: async () => { + let folders = workspace.workspaceFolders + let lines = folders.map(folder => URI.parse(folder.uri).fsPath) + await window.echoLines(lines) + } + }, false, 'show opened workspaceFolders.') + this.register({ + id: 'workspace.renameCurrentFile', + execute: async () => { + await workspace.renameCurrent() + } + }, false, 'change current filename to a new name and reload it.') + this.register({ + id: 'extensions.toggleAutoUpdate', + execute: async () => { + let config = workspace.getConfiguration('coc.preferences') + let interval = config.get('extensionUpdateCheck', 'daily') + if (interval == 'never') { + config.update('extensionUpdateCheck', 'daily', true) + window.showMessage('Extension auto update enabled.', 'more') + } else { + config.update('extensionUpdateCheck', 'never', true) + window.showMessage('Extension auto update disabled.', 'more') + } + } + }, false, 'toggle auto update of extensions.') + this.register({ + id: 'workspace.diagnosticRelated', + execute: () => diagnosticManager.jumpRelated() + }, false, 'jump to related locations of current diagnostic.') + this.register({ + id: 'workspace.showOutput', + execute: async (name?: string) => { + if (name) { + window.showOutputChannel(name) + } else { + let names = workspace.channelNames + if (names.length == 0) return + if (names.length == 1) { + window.showOutputChannel(names[0]) + } else { + let idx = await window.showQuickpick(names) + if (idx == -1) return + let name = names[idx] + window.showOutputChannel(name) + } + } + } + }, false, 'open output buffer to show output from languageservers or extensions.') + this.register({ + id: 'document.showIncomingCalls', + execute: async () => { + await plugin.cocAction('showIncomingCalls') + } + }, false, 'show incoming calls in tree view.') + this.register({ + id: 'document.showOutgoingCalls', + execute: async () => { + await plugin.cocAction('showOutgoingCalls') + } + }, false, 'show outgoing calls in tree view.') + this.register({ + id: 'document.echoFiletype', + execute: async () => { + let bufnr = await nvim.call('bufnr', '%') + let doc = workspace.getDocument(bufnr) + if (!doc) return + await window.echoLines([doc.filetype]) + } + }, false, 'echo the mapped filetype of the current buffer') + this.register({ + id: 'document.renameCurrentWord', + execute: async () => { + let bufnr = await nvim.call('bufnr', '%') + let doc = workspace.getDocument(bufnr) + if (!doc) return + let edit = await plugin.cocAction('getWordEdit') as WorkspaceEdit + if (!edit) { + window.showMessage('Invalid position', 'warning') + return + } + let ranges: Range[] = [] + 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 (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.document + if (!doc) return + let ranges = await plugin.cocAction('symbolRanges') as Range[] + if (!ranges) return + let { textDocument } = doc + let offset = await window.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 window.moveTo(ranges[i].start) + return + } + } + await window.moveTo(ranges[0].start) + } + }, false, 'Jump to next symbol highlight position.') + this.register({ + id: 'workspace.openLocation', + execute: async (winid: number, loc: Location, openCommand?: string) => { + if (winid) await nvim.call('win_gotoid', [winid]) + await workspace.jumpTo(loc.uri, loc.range.start, openCommand) + } + }, true) + this.register({ + id: 'document.jumpToPrevSymbol', + execute: async () => { + let doc = await workspace.document + if (!doc) return + let ranges = await plugin.cocAction('symbolRanges') as Range[] + if (!ranges) return + let { textDocument } = doc + let offset = await window.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 = ranges.length - 1; i >= 0; i--) { + if (textDocument.offsetAt(ranges[i].end) < offset) { + await window.moveTo(ranges[i].start) + return + } + } + await window.moveTo(ranges[ranges.length - 1].start) + } + }, false, 'Jump to previous symbol highlight position.') + } + + public get commandList(): CommandItem[] { + let res: CommandItem[] = [] + for (let item of this.commands.values()) { + if (!item.internal) res.push(item) + } + return res + } + + public dispose(): void { + for (const registration of this.commands.values()) { + registration.dispose() + } + this.commands.clear() + } + + public execute(command: language.Command): Promise { + let args = [command.command] + let arr = command.arguments + if (arr) args.push(...arr) + return this.executeCommand.apply(this, args) + } + + public register(command: T, internal = false, description?: string): T { + 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 + } + + public has(id: string): boolean { + return this.commands.has(id) + } + + public unregister(id: string): void { + 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. + */ + public registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any, internal = false): Disposable { + if (id.startsWith("_")) internal = true + this.commands.set(id, new CommandItem(id, impl, thisArg, internal)) + return 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. + */ + public executeCommand(command: string, ...rest: any[]): Promise { + let cmd = this.commands.get(command) + if (!cmd) throw new Error(`Command: ${command} not found`) + return Promise.resolve(cmd.execute.apply(cmd, rest)) + } + + public async addRecent(cmd: string): Promise { + await this.mru.add(cmd) + await workspace.nvim.command(`silent! call repeat#set("\\(coc-command-repeat)", -1)`) + } + + public async repeatCommand(): Promise { + let mruList = await this.mru.load() + let first = mruList[0] + if (first) { + await this.executeCommand(first) + await workspace.nvim.command(`silent! call repeat#set("\\(coc-command-repeat)", -1)`) + } + } +} + +export default new CommandManager() diff --git a/vim-config/plugins/coc.nvim/src/completion/complete.ts b/vim-config/plugins/coc.nvim/src/completion/complete.ts new file mode 100644 index 00000000..5684165c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/completion/complete.ts @@ -0,0 +1,376 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Emitter, Event, Position } from 'vscode-languageserver-protocol' +import Document from '../model/document' +import { CompleteOption, FloatConfig, VimCompleteItem, CompleteResult, ExtendedCompleteItem, ISource } from '../types' +import { fuzzyMatch, getCharCodes } from '../util/fuzzy' +import { byteSlice, characterIndex } from '../util/string' +import { matchScore } from './match' +const logger = require('../util/logger')('completion-complete') + +export interface CompleteConfig { + disableKind: boolean + disableMenu: boolean + disableMenuShortcut: boolean + enablePreview: boolean + enablePreselect: boolean + labelMaxLength: number + floatEnable: boolean + autoTrigger: string + previewIsKeyword: string + triggerCompletionWait: number + minTriggerInputLength: number + triggerAfterInsertEnter: boolean + acceptSuggestionOnCommitCharacter: boolean + noselect: boolean + keepCompleteopt: boolean + numberSelect: boolean + maxItemCount: number + timeout: number + snippetIndicator: string + fixInsertedWord: boolean + localityBonus: boolean + highPrioritySourceLimit: number + lowPrioritySourceLimit: number + removeDuplicateItems: boolean + defaultSortMethod: string + asciiCharactersOnly: boolean + floatConfig: FloatConfig +} + +export type Callback = () => void + +// first time completion +const FIRST_TIMEOUT = 500 + +export default class Complete { + // identify this complete + public results: CompleteResult[] = [] + private completing: Set = new Set() + private _canceled = false + private localBonus: Map + private tokenSources: Map = new Map() + private readonly _onDidComplete = new Emitter() + public readonly onDidComplete: Event = this._onDidComplete.event + constructor(public option: CompleteOption, + private document: Document, + private config: CompleteConfig, + private sources: ISource[], + private nvim: Neovim) { + } + + public get isCompleting(): boolean { + return this.completing.size > 0 + } + + public get isCanceled(): boolean { + return this._canceled + } + + public get isEmpty(): boolean { + return this.results.length == 0 + } + + public get startcol(): number { + return this.option.col || 0 + } + + public get input(): string { + return this.option.input + } + + public get isIncomplete(): boolean { + return this.results.findIndex(o => o.isIncomplete) !== -1 + } + + private async completeSource(source: ISource): Promise { + 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, 15000), 500) + 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 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(undefined) + }, 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(undefined) + }) + 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(undefined) + } else { + let { results } = this + this.results = results.filter(res => res.source != name) + resolve(undefined) + } + }, 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) + } + } + + public async completeInComplete(resumeInput: string): Promise { + let { results, document } = this + let remains = results.filter(res => !res.isIncomplete) + remains.forEach(res => { + res.items.forEach(item => delete item.user_data) + }) + let arr = results.filter(res => res.isIncomplete) + 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.includes(s.name)) + await Promise.all(sources.map(s => this.completeSource(s))) + return this.filterResults(resumeInput, Math.floor(Date.now() / 1000)) + } + + public filterResults(input: string, cid = 0): ExtendedCompleteItem[] { + 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 { snippetIndicator, removeDuplicateItems, fixInsertedWord, asciiCharactersOnly } = this.config + let followPart = (!fixInsertedWord || cid == 0) ? '' : this.getFollowPart() + if (results.length == 0) return [] + let arr: ExtendedCompleteItem[] = [] + let codes = getCharCodes(input) + let words: Set = new Set() + for (let i = 0, l = results.length; i < l; i++) { + let res = results[i] + let { items, source, priority } = res + for (let idx = 0; idx < items.length; idx++) { + let item = items[idx] + if (!item || typeof item.word !== 'string') { + continue + } + let { word } = item + // eslint-disable-next-line no-control-regex + if (asciiCharactersOnly && !/^[\x00-\x7F]*$/.test(word)) { + continue + } + if (!item.dup && words.has(word)) continue + if (removeDuplicateItems && !item.isSnippet && words.has(word) && item.line == undefined) continue + let filterText = item.filterText || item.word + item.filterText = filterText + if (filterText.length < input.length) continue + let score = item.kind && filterText == input ? 64 : matchScore(filterText, codes) + if (input.length && score == 0) 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: any = { 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 + } + item.priority = priority + item.abbr = item.abbr || item.word + item.score = input.length ? score * (item.sourceScore || 1) : 0 + item.localBonus = this.localBonus ? this.localBonus.get(filterText) || 0 : 0 + words.add(word) + if (item.isSnippet && input.length && 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.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 'none': + return 0 + 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)) + } + + private limitCompleteItems(items: ExtendedCompleteItem[]): ExtendedCompleteItem[] { + let { highPrioritySourceLimit, lowPrioritySourceLimit } = this.config + if (!highPrioritySourceLimit && !lowPrioritySourceLimit) return items + let counts: Map = 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 + }) + } + + public hasMatch(input: string): boolean { + let { results } = this + if (!results) return false + let codes = getCharCodes(input) + for (let i = 0, l = results.length; i < l; i++) { + let items = results[i].items + let idx = items.findIndex(item => fuzzyMatch(codes, item.filterText || item.word)) + if (idx !== -1) return true + } + return false + } + + public async doComplete(): Promise { + let opts = this.option + let { line, colnr, linenr, col } = this.option + if (this.config.localityBonus) { + let line = linenr - 1 + this.localBonus = this.document.getLocalifyBonus(Position.create(line, opts.col - 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 = 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)) + } + + public resolveCompletionItem(item: VimCompleteItem): ExtendedCompleteItem | null { + 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 + } + } + + private getFollowPart(): string { + let { colnr, line } = this.option + let idx = characterIndex(line, colnr - 1) + if (idx == line.length) return '' + let part = line.slice(idx - line.length) + return part.match(/^\S?[\w-]*/)[0] + } + + public dispose(): void { + if (this._canceled) return + this._onDidComplete.dispose() + this._canceled = true + for (let tokenSource of this.tokenSources.values()) { + tokenSource.cancel() + } + this.tokenSources.clear() + this.sources = [] + this.results = [] + } +} diff --git a/vim-config/plugins/coc.nvim/src/completion/floating.ts b/vim-config/plugins/coc.nvim/src/completion/floating.ts new file mode 100644 index 00000000..a7a3fa38 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/completion/floating.ts @@ -0,0 +1,69 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationToken } from 'vscode-jsonrpc' +import { FloatConfig } from '../types' +import { parseDocuments, Documentation } from '../markdown' +const logger = require('../util/logger')('floating') + +export interface PumBounding { + readonly height: number + readonly width: number + readonly row: number + readonly col: number + readonly scrollbar: boolean +} + +export interface FloatingConfig extends FloatConfig { + excludeImages: boolean +} + +export default class Floating { + private winid = 0 + private bufnr = 0 + + constructor( + private nvim: Neovim, + private isVim: boolean) { + } + + public async show(docs: Documentation[], bounding: PumBounding, config: FloatingConfig, token: CancellationToken): Promise { + let { nvim } = this + docs = docs.filter(o => o.content.trim().length > 0) + let { lines, codes, highlights } = parseDocuments(docs, { excludeImages: config.excludeImages }) + if (lines.length == 0) { + this.close() + return + } + let opts: any = { + codes, + highlights, + maxWidth: config.maxWidth || 80, + pumbounding: bounding, + } + if (config.border) opts.border = [1, 1, 1, 1] + if (config.highlight) opts.highlight = config.highlight + if (config.borderhighlight) opts.borderhighlight = config.borderhighlight + if (!this.isVim) { + if (typeof config.winblend === 'number') opts.winblend = config.winblend + opts.focusable = config.focusable === true ? 1 : 0 + if (config.shadow) opts.shadow = 1 + } + let res = await nvim.call('coc#float#create_pum_float', [this.winid, this.bufnr, lines, opts]) + // can't use redrawVim which lost the cursor. + if (this.isVim) nvim.command('redraw', true) + if (!res || res.length == 0) return + this.winid = res[0] + this.bufnr = res[1] + if (token.isCancellationRequested) { + this.close() + return + } + } + + public close(): void { + let { winid, nvim } = this + this.winid = 0 + if (!winid) return + nvim.call('coc#float#close', [winid], true) + if (this.isVim) nvim.command('redraw', true) + } +} diff --git a/vim-config/plugins/coc.nvim/src/completion/index.ts b/vim-config/plugins/coc.nvim/src/completion/index.ts new file mode 100644 index 00000000..dbe871dd --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/completion/index.ts @@ -0,0 +1,623 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationToken, CancellationTokenSource, Disposable } from 'vscode-languageserver-protocol' +import events, { PopupChangeEvent, InsertChange } from '../events' +import Document from '../model/document' +import sources from '../sources' +import { CompleteOption, ISource, VimCompleteItem, ExtendedCompleteItem, FloatConfig } from '../types' +import { disposeAll, wait } from '../util' +import * as Is from '../util/is' +import workspace from '../workspace' +import Complete, { CompleteConfig } from './complete' +import Floating, { PumBounding } from './floating' +import debounce from 'debounce' +import { byteSlice } from '../util/string' +import { equals } from '../util/object' +const logger = require('../util/logger')('completion') +const completeItemKeys = ['abbr', 'menu', 'info', 'kind', 'icase', 'dup', 'empty', 'user_data'] + +export interface LastInsert { + character: string + timestamp: number +} + +export class Completion implements Disposable { + public config: CompleteConfig + private popupEvent: PopupChangeEvent + private triggerTimer: NodeJS.Timer + private floating: Floating + // current input string + private activated = false + private input: string + private lastInsert?: LastInsert + private disposables: Disposable[] = [] + private complete: Complete | null = null + private resolveTokenSource: CancellationTokenSource + private pretext: string + private changedTick = 0 + private insertCharTs = 0 + private insertLeaveTs = 0 + private excludeImages: boolean + + public init(): void { + this.config = this.getCompleteConfig() + workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('suggest')) { + this.config = this.getCompleteConfig() + } + }, null, this.disposables) + workspace.watchOption('completeopt', async (_, newValue) => { + workspace.env.completeOpt = newValue + if (!this.isActivated) return + if (this.config.autoTrigger === 'always') { + let content = await this.nvim.call('execute', ['verbose set completeopt']) as string + let lines = content.split(/\r?\n/) + console.error(`Some plugin change completeopt during completion: ${lines[lines.length - 1].trim()}!`) + } + }, this.disposables) + this.excludeImages = workspace.getConfiguration('coc.preferences').get('excludeImageLinksInMarkdownDocument') + this.floating = new Floating(workspace.nvim, workspace.env.isVim) + events.on(['InsertCharPre', 'MenuPopupChanged', 'TextChangedI', 'CursorMovedI', 'InsertLeave'], () => { + if (this.triggerTimer) { + clearTimeout(this.triggerTimer) + this.triggerTimer = null + } + }, this, this.disposables) + events.on('InsertCharPre', this.onInsertCharPre, this, this.disposables) + events.on('InsertLeave', this.onInsertLeave, this, this.disposables) + events.on('InsertEnter', this.onInsertEnter, this, this.disposables) + events.on('TextChangedP', this.onTextChangedP, this, this.disposables) + events.on('TextChangedI', this.onTextChangedI, this, this.disposables) + let fn = debounce(this.onPumChange.bind(this), 20) + this.disposables.push({ + dispose: () => { + fn.clear() + } + }) + events.on('CompleteDone', async item => { + this.popupEvent = null + if (!this.activated) return + fn.clear() + this.cancelResolve() + this.floating.close() + await this.onCompleteDone(item) + }, this, this.disposables) + this.cancelResolve() + events.on('MenuPopupChanged', ev => { + if (!this.activated || this.isCommandLine) return + if (equals(this.popupEvent, ev)) return + this.cancelResolve() + this.popupEvent = ev + fn() + }, this, this.disposables) + } + + private get nvim(): Neovim { + return workspace.nvim + } + + public get option(): CompleteOption { + if (!this.complete) return null + return this.complete.option + } + + private get selectedItem(): VimCompleteItem | null { + if (!this.popupEvent) return null + let { completed_item } = this.popupEvent + return Is.vimCompleteItem(completed_item) ? completed_item : null + } + + private get isCommandLine(): boolean { + return this.document?.uri.endsWith('%5BCommand%20Line%5D') + } + + public get isActivated(): boolean { + return this.activated + } + + private get document(): Document | null { + if (!this.option) return null + return workspace.getDocument(this.option.bufnr) + } + + private getCompleteConfig(): CompleteConfig { + let suggest = workspace.getConfiguration('suggest') + function getConfig(key, defaultValue: T): T { + return suggest.get(key, defaultValue) + } + let keepCompleteopt = getConfig('keepCompleteopt', false) + let autoTrigger = getConfig('autoTrigger', 'always') + if (keepCompleteopt && autoTrigger != 'none') { + let { completeOpt } = workspace + if (!completeOpt.includes('noinsert') && !completeOpt.includes('noselect')) { + autoTrigger = 'none' + } + } + let floatEnable = workspace.floatSupported && getConfig('floatEnable', true) + let acceptSuggestionOnCommitCharacter = workspace.env.pumevent && getConfig('acceptSuggestionOnCommitCharacter', false) + return { + autoTrigger, + floatEnable, + keepCompleteopt, + floatConfig: getConfig('floatConfig', {}), + 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), + triggerCompletionWait: getConfig('triggerCompletionWait', 100), + labelMaxLength: getConfig('labelMaxLength', 200), + triggerAfterInsertEnter: getConfig('triggerAfterInsertEnter', false), + noselect: getConfig('noselect', true), + numberSelect: getConfig('numberSelect', false), + maxItemCount: getConfig('maxCompleteItemCount', 50), + timeout: getConfig('timeout', 500), + minTriggerInputLength: getConfig('minTriggerInputLength', 1), + snippetIndicator: getConfig('snippetIndicator', '~'), + fixInsertedWord: getConfig('fixInsertedWord', true), + localityBonus: getConfig('localityBonus', true), + highPrioritySourceLimit: getConfig('highPrioritySourceLimit', null), + lowPrioritySourceLimit: getConfig('lowPrioritySourceLimit', null), + asciiCharactersOnly: getConfig('asciiCharactersOnly', false) + } + } + + public async startCompletion(option: CompleteOption): Promise { + this.pretext = byteSlice(option.line, 0, option.colnr - 1) + try { + await this._doComplete(option) + } catch (e) { + this.stop() + logger.error('Complete error:', e.stack) + } + } + + private async resumeCompletion(force = false): Promise { + let { document, complete } = this + if (!document + || complete.isCanceled + || !complete.results + || complete.results.length == 0) return + let search = this.getResumeInput() + if (search == this.input && !force) return + if (!search || search.endsWith(' ') || !search.startsWith(complete.input)) { + this.stop() + return + } + this.input = search + let items: VimCompleteItem[] = [] + if (complete.isIncomplete) { + await document.patchChange(true) + let { changedtick } = document + items = await complete.completeInComplete(search) + if (complete.isCanceled || document.changedtick != changedtick) return + } else { + items = complete.filterResults(search) + } + if (!complete.isCompleting && items.length === 0) { + this.stop() + return + } + await this.showCompletion(complete.option.col, items) + } + + public hasSelected(): boolean { + if (workspace.env.pumevent) return this.selectedItem != null + if (!this.config.noselect) return true + return false + } + + private async showCompletion(col: number, items: ExtendedCompleteItem[]): Promise { + let { nvim, document, option } = this + let { numberSelect, disableKind, labelMaxLength, disableMenuShortcut, disableMenu } = this.config + let preselect = this.config.enablePreselect ? items.findIndex(o => o.preselect) : -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(/\[.+\]$/, '') + } 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) + } + + private async _doComplete(option: CompleteOption): Promise { + let { source } = option + let { nvim, config } = this + let doc = workspace.getDocument(option.bufnr) + if (!doc || !doc.attached) return + // use fixed filetype + option.filetype = doc.filetype + // current input + this.input = option.input + let arr: ISource[] = [] + if (source == null) { + arr = sources.getCompleteSources(option) + } else { + let s = sources.getSource(source) + if (s) arr.push(s) + } + if (!arr.length) return + await doc.patchChange() + // document get changed, not complete + if (doc.changedtick != option.changedtick) return + let complete = new Complete(option, doc, 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 () => { + if (this.selectedItem != null) return + let search = this.getResumeInput() + if (complete.isCanceled || search == null) return + let { input } = this.option + if (search == input) { + let items = complete.filterResults(search, Math.floor(Date.now() / 1000)) + await this.showCompletion(option.col, items) + } else { + await this.resumeCompletion() + } + }) + if (items.length) { + let search = this.getResumeInput() + if (search == option.input) { + await this.showCompletion(option.col, items) + } else { + await this.resumeCompletion(true) + } + } + } + + private async onTextChangedP(bufnr: number, info: InsertChange): Promise { + let { option, document } = this + let pretext = this.pretext = info.pre + // avoid trigger filter on pumvisible + if (!option || option.bufnr != bufnr || info.changedtick == this.changedTick) return + let hasInsert = this.latestInsert != null + this.lastInsert = null + if (info.pre.match(/^\s*/)[0] !== option.line.match(/^\s*/)[0]) { + // Can't handle indent change + logger.warn('Complete stopped by indent change.') + this.stop(false) + return + } + // not handle when not triggered by character insert + if (!hasInsert || !pretext) return + if (sources.shouldTrigger(pretext, document.filetype, document.uri)) { + await this.triggerCompletion(document, pretext) + } else { + await this.resumeCompletion() + } + } + + private async onTextChangedI(bufnr: number, info: InsertChange): Promise { + let { nvim, latestInsertChar, option } = this + let noChange = this.pretext == info.pre + let pretext = this.pretext = info.pre + this.lastInsert = null + let doc = workspace.getDocument(bufnr) + if (!doc) return + // try trigger on character type + if (!this.activated) { + if (!latestInsertChar) return + let triggerSources = sources.getTriggerSources(pretext, doc.filetype, doc.uri) + if (triggerSources.length) { + await this.triggerCompletion(doc, this.pretext) + return + } + this.triggerTimer = setTimeout(async () => { + await this.triggerCompletion(doc, pretext) + }, this.config.triggerCompletionWait) + return + } + // Ignore change with other buffer + if (!option || bufnr != option.bufnr) return + if (option.linenr != info.lnum || option.col >= info.col - 1) { + this.stop() + return + } + // Completion is canceled by + if (noChange && !latestInsertChar) { + this.stop(false) + return + } + // Check commit character + if (pretext + && this.selectedItem + && this.config.acceptSuggestionOnCommitCharacter + && latestInsertChar) { + let resolvedItem = this.getCompleteItem(this.selectedItem) + let last = pretext[pretext.length - 1] + if (sources.shouldCommit(resolvedItem, last)) { + 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]) + await doc.patchChange() + return + } + } + // prefer trigger completion + if (sources.shouldTrigger(pretext, doc.filetype, doc.uri)) { + await this.triggerCompletion(doc, pretext) + } else { + await this.resumeCompletion() + } + } + + private async triggerCompletion(doc: Document, pre: string): Promise { + if (!doc || !doc.attached) { + logger.warn('Document not attached, suggest disabled.') + return + } + // check trigger + let shouldTrigger = this.shouldTrigger(doc, pre) + if (!shouldTrigger) return + if (doc.getVar('suggest_disable')) { + logger.warn(`Suggest disabled by b:coc_suggest_disable`) + return + } + await doc.patchChange() + let [disabled, option] = await this.nvim.eval('[get(b:,"coc_suggest_disable",0),coc#util#get_complete_option()]') as [number, CompleteOption] + if (disabled == 1) { + logger.warn(`Suggest disabled by b:coc_suggest_disable`) + return + } + if (option.blacklist && option.blacklist.includes(option.input)) { + logger.warn(`Suggest disabled by b:coc_suggest_blacklist`, option.blacklist) + return + } + if (pre.length) { + option.triggerCharacter = pre.slice(-1) + } + logger.debug('trigger completion with', option) + await this.startCompletion(option) + } + + private async onCompleteDone(item: VimCompleteItem): Promise { + let { document, isActivated } = this + if (!isActivated || !document || !Is.vimCompleteItem(item)) 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 + let source = new CancellationTokenSource() + await this.doCompleteResolve(resolvedItem, source.token) + source.dispose() + // Wait possible TextChangedI + await wait(50) + if (this.insertCharTs != timestamp || this.insertLeaveTs != insertLeaveTs) return + let [visible, lnum, pre] = await this.nvim.eval(`[pumvisible(),line('.'),strpart(getline('.'), 0, col('.') - 1)]`) as [number, number, string] + if (visible || lnum != opt.linenr || this.activated || !pre.endsWith(resolvedItem.word)) return + await document.patchChange(true) + await this.doCompleteDone(resolvedItem, opt) + } + + private async doCompleteResolve(item: ExtendedCompleteItem, token: CancellationToken): Promise { + let source = sources.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) + } + } + } + + public async doCompleteDone(item: ExtendedCompleteItem, opt: CompleteOption): Promise { + let data = JSON.parse(item.user_data) + let source = sources.getSource(data.source) + if (source && typeof source.onCompleteDone === 'function') { + await Promise.resolve(source.onCompleteDone(item, opt)) + } + } + + private async onInsertLeave(): Promise { + this.insertLeaveTs = Date.now() + this.stop(false) + } + + private async onInsertEnter(bufnr: number): Promise { + if (!this.config.triggerAfterInsertEnter || this.config.autoTrigger !== 'always') return + let doc = workspace.getDocument(bufnr) + if (!doc) return + let pre = await this.nvim.eval(`strpart(getline('.'), 0, col('.') - 1)`) as string + if (!pre) return + await this.triggerCompletion(doc, pre) + } + + private async onInsertCharPre(character: string): Promise { + this.lastInsert = { + character, + timestamp: Date.now(), + } + this.insertCharTs = this.lastInsert.timestamp + } + + private get latestInsert(): LastInsert | null { + let { lastInsert } = this + if (!lastInsert || Date.now() - lastInsert.timestamp > 500) { + return null + } + return lastInsert + } + + private get latestInsertChar(): string { + let { latestInsert } = this + if (!latestInsert) return '' + return latestInsert.character + } + + public shouldTrigger(doc: Document, pre: string): boolean { + let autoTrigger = this.config.autoTrigger + if (autoTrigger == 'none') return false + if (sources.shouldTrigger(pre, doc.filetype, doc.uri)) return true + if (autoTrigger !== 'always' || this.isActivated) return false + let last = pre.slice(-1) + if (last && (doc.isWord(pre.slice(-1)) || last.codePointAt(0) > 255)) { + let minLength = this.config.minTriggerInputLength + if (minLength == 1) return true + let input = this.getInput(doc, pre) + return input.length >= minLength + } + return false + } + + private async onPumChange(): Promise { + if (!this.popupEvent) return + let { col, row, height, width, scrollbar } = this.popupEvent + let bounding: PumBounding = { col, row, height, width, scrollbar } + let resolvedItem = this.getCompleteItem(this.selectedItem) + if (!resolvedItem) { + this.floating.close() + return + } + let source = this.resolveTokenSource = new CancellationTokenSource() + let { token } = source + await this.doCompleteResolve(resolvedItem, token) + if (this.resolveTokenSource == source) { + this.resolveTokenSource = null + } + source.dispose() + 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 (this.config.floatEnable) { + let source = new CancellationTokenSource() + await this.floating.show(docs, bounding, Object.assign({}, this.config.floatConfig, { + excludeImages: this.excludeImages + }), source.token) + } + if (!this.isActivated) { + this.floating.close() + } + } + } + + public start(complete: Complete): void { + let { activated } = this + this.activated = true + if (activated) { + this.complete.dispose() + } + this.complete = complete + if (!this.config.keepCompleteopt) { + this.nvim.command(`noa set completeopt=${this.completeOpt}`, true) + } + } + + private cancelResolve(): void { + if (this.resolveTokenSource) { + this.resolveTokenSource.cancel() + this.resolveTokenSource = null + } + } + + public stop(hide = true): void { + let { nvim } = this + if (!this.activated) return + this.cancelResolve() + this.floating.close() + this.activated = false + if (this.complete) { + this.complete.dispose() + this.complete = null + } + nvim.pauseNotification() + if (hide) { + nvim.call('coc#_hide', [], true) + } + if (this.config.numberSelect) { + nvim.call('coc#_unmap', [], true) + } + if (!this.config.keepCompleteopt) { + nvim.command(`noa set completeopt=${workspace.completeOpt}`, true) + } + nvim.command(`let g:coc#_context = {'start': 0, 'preselect': -1,'candidates': []}`, true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + + private getInput(document: Document, pre: string): string { + 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 + } + + public getResumeInput(): string { + let { option, pretext } = this + if (!option) return null + let buf = Buffer.from(pretext, 'utf8') + if (buf.length < option.col) return null + let input = buf.slice(option.col).toString('utf8') + if (option.blacklist && option.blacklist.includes(input)) return null + return input + } + + private get completeOpt(): string { + let { noselect, enablePreview } = this.config + let preview = enablePreview && !workspace.env.pumevent ? ',preview' : '' + if (noselect) return `noselect,menuone${preview}` + return `noinsert,menuone${preview}` + } + + private getCompleteItem(item: VimCompleteItem | {} | null): ExtendedCompleteItem | null { + if (!this.complete || !Is.vimCompleteItem(item)) return null + return this.complete.resolveCompletionItem(item) + } + + public dispose(): void { + this.resolveTokenSource = null + disposeAll(this.disposables) + } +} + +export default new Completion() diff --git a/vim-config/plugins/coc.nvim/src/completion/match.ts b/vim-config/plugins/coc.nvim/src/completion/match.ts new file mode 100644 index 00000000..b82d6087 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/completion/match.ts @@ -0,0 +1,133 @@ +import { getCharCodes, caseMatch, wordChar } from '../util/fuzzy' + +function nextWordIndex(start = 0, codes: number[]): number { + for (let i = start; i < codes.length; i++) { + if (isWordIndex(i, codes)) { + return i + } + } + return -1 +} + +function upperCase(code: number): boolean { + return code >= 65 && code <= 90 +} + +function isWordIndex(index: number, codes: number[]): boolean { + if (index == 0) return true + let curr = codes[index] + if (!wordChar(curr)) return false + let pre = codes[index - 1] + if (!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} + */ +export function matchScore(word: string, input: number[]): number { + if (input.length == 0 || word.length < input.length) return 0 + let codes = getCharCodes(word) + let curr = codes[0] + let score = 0 + let first = input[0] + let idx = 1 + let allowFuzzy = true + if (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 (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 (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 +} + +function nextScore(codes: number[], index: number, inputCodes: number[], allowFuzzy = true): number { + if (index >= codes.length) return 0 + let scores: number[] = [] + let input = inputCodes[0] + let len = codes.length + let isFinal = inputCodes.length == 1 + if (!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 = 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 (wordChar(input) && !isWordIndex(index, codes)) { + let idx = nextWordIndex(index + 1, codes) + if (idx !== -1) { + let next = codes[idx] + if (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 (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) +} diff --git a/vim-config/plugins/coc.nvim/src/configuration/configuration.ts b/vim-config/plugins/coc.nvim/src/configuration/configuration.ts new file mode 100644 index 00000000..dcd13aff --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/configuration/configuration.ts @@ -0,0 +1,71 @@ +import { ConfigurationModel } from './model' +import { IConfigurationData } from '../types' + +export class Configuration { + private _consolidateConfiguration: ConfigurationModel + + constructor( + private _defaultConfiguration: ConfigurationModel, + private _userConfiguration: ConfigurationModel, + private _workspaceConfiguration: ConfigurationModel, + private _memoryConfiguration: ConfigurationModel = new ConfigurationModel(), + ) { + } + + private getConsolidateConfiguration(): ConfigurationModel { + if (!this._consolidateConfiguration) { + this._consolidateConfiguration = this._defaultConfiguration.merge(this._userConfiguration, this._workspaceConfiguration, this._memoryConfiguration) + this._consolidateConfiguration = this._consolidateConfiguration.freeze() + } + return this._consolidateConfiguration + } + + public getValue(section?: string): any { + let configuration = this.getConsolidateConfiguration() + return configuration.getValue(section) + } + + public inspect(key: string): { + default: C + user: C + workspace: C + memory?: C + value: C + } { + 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) + } + } + + public get defaults(): ConfigurationModel { + return this._defaultConfiguration + } + + public get user(): ConfigurationModel { + return this._userConfiguration + } + + public get workspace(): ConfigurationModel { + return this._workspaceConfiguration + } + + public toData(): IConfigurationData { + return { + defaults: { + contents: this._defaultConfiguration.contents + }, + user: { + contents: this._userConfiguration.contents + }, + workspace: { + contents: this._workspaceConfiguration.contents + } + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/configuration/index.ts b/vim-config/plugins/coc.nvim/src/configuration/index.ts new file mode 100644 index 00000000..f0c151c4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/configuration/index.ts @@ -0,0 +1,338 @@ +import os from 'os' +import fs from 'fs' +import path from 'path' +import { Emitter, Event, Disposable } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import { ConfigurationChangeEvent, ConfigurationInspect, ConfigurationShape, ConfigurationTarget, ErrorItem, IConfigurationData, IConfigurationModel, WorkspaceConfiguration } from '../types' +import { deepClone, deepFreeze, mixin } from '../util/object' +import { watchFile, disposeAll, CONFIG_FILE_NAME } from '../util' +import { Configuration } from './configuration' +import { ConfigurationModel } from './model' +import { addToValueTree, loadDefaultConfigurations, parseContentFromFile, getChangedKeys } from './util' +import { objectLiteral } from '../util/is' +import { isParentFolder, findUp } from '../util/fs' +const logger = require('../util/logger')('configurations') + +function lookUp(tree: any, key: string): any { + 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 +} + +export default class Configurations { + private _configuration: Configuration + private _errorItems: ErrorItem[] = [] + private _folderConfigurations: Map = new Map() + private _onError = new Emitter() + private _onChange = new Emitter() + private disposables: Disposable[] = [] + private workspaceConfigFile: string + + public readonly onError: Event = this._onError.event + public readonly onDidChange: Event = this._onChange.event + + constructor( + private userConfigFile?: string | null, + private readonly _proxy?: ConfigurationShape + ) { + let user = this.parseContentFromFile(userConfigFile) + let data: IConfigurationData = { + defaults: loadDefaultConfigurations(), + user, + workspace: { contents: {} } + } + this._configuration = Configurations.parse(data) + this.watchFile(userConfigFile, ConfigurationTarget.User) + let folderConfigFile = path.join(process.cwd(), `.vim/${CONFIG_FILE_NAME}`) + if (folderConfigFile != userConfigFile && fs.existsSync(folderConfigFile)) { + this.addFolderFile(folderConfigFile) + } + } + + private parseContentFromFile(filepath: string): IConfigurationModel { + if (!filepath) return { contents: {} } + let uri = URI.file(filepath).toString() + this._errorItems = this._errorItems.filter(o => o.location.uri != uri) + let res = parseContentFromFile(filepath, errors => { + this._errorItems.push(...errors) + }) + this._onError.fire(this._errorItems) + return res + } + + public get errorItems(): ErrorItem[] { + return this._errorItems + } + + public get foldConfigurations(): Map { + return this._folderConfigurations + } + + // used for extensions, no change event fired + public extendsDefaults(props: { [key: string]: any }): void { + let { defaults } = this._configuration + let { contents } = defaults + contents = deepClone(contents) + Object.keys(props).forEach(key => { + addToValueTree(contents, key, props[key], msg => { + logger.error(msg) + }) + }) + let data: IConfigurationData = { + defaults: { contents }, + user: this._configuration.user, + workspace: this._configuration.workspace + } + this._configuration = Configurations.parse(data) + } + + // change user configuration, without change file + public updateUserConfig(props: { [key: string]: any }): void { + 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 (objectLiteral(val)) { + for (let k of Object.keys(val)) { + model.setValue(`${key}.${k}`, val[k]) + } + } else { + model.setValue(key, val) + } + }) + this.changeConfiguration(ConfigurationTarget.User, model) + } + + public get defaults(): ConfigurationModel { + return this._configuration.defaults + } + + public get user(): ConfigurationModel { + return this._configuration.user + } + + public get workspace(): ConfigurationModel { + return this._configuration.workspace + } + + public addFolderFile(filepath: string): void { + let { _folderConfigurations } = this + if (_folderConfigurations.has(filepath)) return + if (path.resolve(filepath, '../..') == os.homedir()) return + let model = this.parseContentFromFile(filepath) + this.watchFile(filepath, ConfigurationTarget.Workspace) + this.changeConfiguration(ConfigurationTarget.Workspace, model, filepath) + } + + private watchFile(filepath: string, target: ConfigurationTarget): void { + if (!fs.existsSync(filepath) || global.hasOwnProperty('__TEST__')) return + let disposable = watchFile(filepath, () => { + let model = this.parseContentFromFile(filepath) + this.changeConfiguration(target, model, filepath) + }) + this.disposables.push(disposable) + } + + // create new configuration and fire change event + public changeConfiguration(target: ConfigurationTarget, model: IConfigurationModel, configFile?: string): void { + let { defaults, user, workspace } = this._configuration + let { workspaceConfigFile } = this + let data: IConfigurationData = { + defaults: target == ConfigurationTarget.Global ? model : defaults, + user: target == ConfigurationTarget.User ? model : user, + workspace: target == ConfigurationTarget.Workspace ? model : workspace, + } + let configuration = Configurations.parse(data) + let changed = getChangedKeys(this._configuration.getValue(), configuration.getValue()) + if (target == ConfigurationTarget.Workspace && configFile) { + this._folderConfigurations.set(configFile, new ConfigurationModel(model.contents)) + this.workspaceConfigFile = configFile + } + if (changed.length == 0) return + this._configuration = configuration + this._onChange.fire({ + affectsConfiguration: (section, resource) => { + if (!resource || target != ConfigurationTarget.Workspace) return changed.includes(section) + let u = URI.parse(resource) + if (u.scheme !== 'file') return changed.includes(section) + let filepath = u.fsPath + let preRoot = workspaceConfigFile ? path.resolve(workspaceConfigFile, '../..') : '' + if (configFile && !isParentFolder(preRoot, filepath, true) && !isParentFolder(path.resolve(configFile, '../..'), filepath)) { + return false + } + return changed.includes(section) + } + }) + } + + public setFolderConfiguration(uri: string): void { + let u = URI.parse(uri) + if (u.scheme != 'file') return + let filepath = u.fsPath + for (let [configFile, model] of this.foldConfigurations) { + let root = path.resolve(configFile, '../..') + if (isParentFolder(root, filepath, true) && this.workspaceConfigFile != configFile) { + this.changeConfiguration(ConfigurationTarget.Workspace, model, configFile) + break + } + } + } + + public hasFolderConfiguration(filepath: string): boolean { + let { folders } = this + return folders.findIndex(f => isParentFolder(f, filepath, true)) !== -1 + } + + public getConfigFile(target: ConfigurationTarget): string { + if (target == ConfigurationTarget.Global) return null + if (target == ConfigurationTarget.User) return this.userConfigFile + return this.workspaceConfigFile + } + + private get folders(): string[] { + let res: string[] = [] + let { _folderConfigurations } = this + for (let folder of _folderConfigurations.keys()) { + res.push(path.resolve(folder, '../..')) + } + return res + } + + public get configuration(): Configuration { + return this._configuration + } + + /** + * getConfiguration + * + * @public + * @param {string} section + * @returns {WorkspaceConfiguration} + */ + public getConfiguration(section?: string, resource?: string): WorkspaceConfiguration { + let configuration: Configuration + if (resource) { + let { defaults, user } = this._configuration + configuration = new Configuration(defaults, user, this.getFolderConfiguration(resource)) + } else { + configuration = this._configuration + } + const config = Object.freeze(lookUp(configuration.getValue(null), section)) + + const result: WorkspaceConfiguration = { + has(key: string): boolean { + return typeof lookUp(config, key) !== 'undefined' + }, + get: (key: string, defaultValue?: T) => { + let result: T = lookUp(config, key) + if (result == null) return defaultValue + return result + }, + update: (key: string, value: any, isUser = false) => { + let s = section ? `${section}.${key}` : key + let target = isUser ? ConfigurationTarget.User : ConfigurationTarget.Workspace + let model = target == ConfigurationTarget.User ? this.user.clone() : this.workspace.clone() + if (value == undefined) { + model.removeValue(s) + } else { + model.setValue(s, value) + } + if (target == ConfigurationTarget.Workspace && !this.workspaceConfigFile && this._proxy) { + let file = this.workspaceConfigFile = this._proxy.workspaceConfigFile + if (!fs.existsSync(file)) { + let folder = path.dirname(file) + if (!fs.existsSync(folder)) fs.mkdirSync(folder) + fs.writeFileSync(file, '{}', { encoding: 'utf8' }) + } + } + this.changeConfiguration(target, model, target == 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: string): ConfigurationInspect => { + 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') { + mixin(result, config, false) + } + return deepFreeze(result) + } + + private getFolderConfiguration(uri: string): ConfigurationModel { + let u = URI.parse(uri) + if (u.scheme != 'file') return new ConfigurationModel() + let filepath = u.fsPath + for (let [configFile, model] of this.foldConfigurations) { + let root = path.resolve(configFile, '../..') + if (isParentFolder(root, filepath, true)) return model + } + return new ConfigurationModel() + } + + public checkFolderConfiguration(uri: string): void { + let u = URI.parse(uri) + if (u.scheme != 'file') return + let rootPath = path.dirname(u.fsPath) + if (!this.hasFolderConfiguration(rootPath)) { + let folder = findUp('.vim', rootPath) + if (folder && folder != os.homedir()) { + let file = path.join(folder, CONFIG_FILE_NAME) + if (fs.existsSync(file)) { + this.addFolderFile(file) + } + } + } else { + this.setFolderConfiguration(uri) + } + } + + private static parse(data: IConfigurationData): Configuration { + const defaultConfiguration = new ConfigurationModel(data.defaults.contents) + const userConfiguration = new ConfigurationModel(data.user.contents) + const workspaceConfiguration = new ConfigurationModel(data.workspace.contents) + return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, new ConfigurationModel()) + } + + public dispose(): void { + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/configuration/model.ts b/vim-config/plugins/coc.nvim/src/configuration/model.ts new file mode 100644 index 00000000..da5f17e6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/configuration/model.ts @@ -0,0 +1,64 @@ +import { IConfigurationModel } from '../types' +import { objectLiteral } from '../util/is' +import { deepClone } from '../util/object' +import { addToValueTree, getConfigurationValue, removeFromValueTree } from './util' + +export class ConfigurationModel implements IConfigurationModel { + + constructor(private _contents: any = {}) { } + + public get contents(): any { + return this._contents + } + + public clone(): ConfigurationModel { + return new ConfigurationModel(deepClone(this._contents)) + } + + public getValue(section: string): V { + let res = section + ? getConfigurationValue(this.contents, section) + : this.contents + return res + } + + public merge(...others: ConfigurationModel[]): ConfigurationModel { + const contents = deepClone(this.contents) + + for (const other of others) { + this.mergeContents(contents, other.contents) + } + return new ConfigurationModel(contents) + } + + public freeze(): ConfigurationModel { + if (!Object.isFrozen(this._contents)) { + Object.freeze(this._contents) + } + return this + } + + private mergeContents(source: any, target: any): void { + for (const key of Object.keys(target)) { + if (key in source) { + if (objectLiteral(source[key]) && objectLiteral(target[key])) { + this.mergeContents(source[key], target[key]) + continue + } + } + source[key] = deepClone(target[key]) + } + } + + // Update methods + + public setValue(key: string, value: any): void { + addToValueTree(this.contents, key, value, message => { + console.error(message) + }) + } + + public removeValue(key: string): void { + removeFromValueTree(this.contents, key) + } +} diff --git a/vim-config/plugins/coc.nvim/src/configuration/shape.ts b/vim-config/plugins/coc.nvim/src/configuration/shape.ts new file mode 100644 index 00000000..e8a408ce --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/configuration/shape.ts @@ -0,0 +1,47 @@ +import { Neovim } from '@chemzqm/neovim' +import fs from 'fs' +import { applyEdits, modify } from 'jsonc-parser' +import path from 'path' +import { FormattingOptions } from 'vscode-languageserver-types' +import { URI } from 'vscode-uri' +import { ConfigurationShape, ConfigurationTarget, IWorkspace } from '../types' +import { CONFIG_FILE_NAME } from '../util' +const logger = require('../util/logger')('configuration-shape') + +export default class ConfigurationProxy implements ConfigurationShape { + + constructor(private workspace: IWorkspace) { + } + + private get nvim(): Neovim { + return this.workspace.nvim + } + + private async modifyConfiguration(target: ConfigurationTarget, key: string, value?: any): Promise { + let { nvim, workspace } = this + let file = workspace.getConfigFile(target) + if (!file) return + let formattingOptions: FormattingOptions = { tabSize: 2, insertSpaces: true } + let content = fs.readFileSync(file, 'utf8') + value = value == null ? undefined : value + let edits = modify(content, [key], value, { formattingOptions }) + content = applyEdits(content, edits) + fs.writeFileSync(file, content, 'utf8') + let doc = workspace.getDocument(URI.file(file).toString()) + if (doc) nvim.command('checktime', true) + return + } + + public get workspaceConfigFile(): string { + let folder = path.join(this.workspace.root, '.vim') + return path.join(folder, CONFIG_FILE_NAME) + } + + public $updateConfigurationOption(target: ConfigurationTarget, key: string, value: any): void { + this.modifyConfiguration(target, key, value).logError() + } + + public $removeConfigurationOption(target: ConfigurationTarget, key: string): void { + this.modifyConfiguration(target, key).logError() + } +} diff --git a/vim-config/plugins/coc.nvim/src/configuration/util.ts b/vim-config/plugins/coc.nvim/src/configuration/util.ts new file mode 100644 index 00000000..463b1dd6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/configuration/util.ts @@ -0,0 +1,271 @@ +import { Location, Range } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { parse, ParseError } from 'jsonc-parser' +import { IConfigurationModel, ErrorItem } from '../types' +import { emptyObject, objectLiteral } from '../util/is' +import { equals } from '../util/object' +import fs from 'fs' +import { URI } from 'vscode-uri' +import path, { dirname, resolve } from 'path' +const logger = require('../util/logger')('configuration-util') +declare const ESBUILD + +const pluginRoot = typeof ESBUILD === 'undefined' ? resolve(__dirname, '../..') : dirname(__dirname) + +export type ShowError = (errors: ErrorItem[]) => void + +export function parseContentFromFile(filepath: string | null, onError?: ShowError): IConfigurationModel { + if (!filepath || !fs.existsSync(filepath)) return { contents: {} } + let content: string + let uri = URI.file(filepath).toString() + try { + content = fs.readFileSync(filepath, 'utf8') + } catch (_e) { + content = '' + } + let [errors, contents] = parseConfiguration(content) + if (errors && errors.length) { + onError(convertErrors(uri, content, errors)) + } + return { contents } +} + +export function parseConfiguration(content: string): [ParseError[], any] { + if (content.length == 0) return [[], {}] + let errors: ParseError[] = [] + let data = parse(content, errors, { allowTrailingComma: true }) + function addProperty(current: object, key: string, remains: string[], value: any): void { + 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: any, split = false): any { + if (!objectLiteral(obj)) return obj + if (emptyObject(obj)) return {} + let dest = {} + for (let key of Object.keys(obj)) { + if (split && key.includes('.')) { + 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)] +} + +export function convertErrors(uri: string, content: string, errors: ParseError[]): ErrorItem[] { + let items: ErrorItem[] = [] + let document = 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: Range = { + start: document.positionAt(err.offset), + end: document.positionAt(err.offset + err.length), + } + let loc = Location.create(uri, range) + items.push({ location: loc, message: msg }) + } + return items +} + +export function addToValueTree( + settingsTreeRoot: any, + key: string, + value: any, + conflictReporter: (message: string) => void +): void { + 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)}` + ) + } +} + +export function removeFromValueTree(valueTree: any, key: string): void { + const segments = key.split('.') + doRemoveFromValueTree(valueTree, segments) +} + +function doRemoveFromValueTree(valueTree: any, segments: string[]): void { + const first = segments.shift() + if (segments.length === 0) { + // Reached last segment + delete valueTree[first] + return + } + + if (Object.keys(valueTree).includes(first)) { + const value = valueTree[first] + if (typeof value === 'object' && !Array.isArray(value)) { + doRemoveFromValueTree(value, segments) + if (Object.keys(value).length === 0) { + delete valueTree[first] + } + } + } +} + +export function getConfigurationValue( + config: any, + settingPath: string, + defaultValue?: T +): T { + function accessSetting(config: any, path: string[]): any { + let current = config + for (let i = 0; i < path.length; i++) { + if (typeof current !== 'object' || current === null) { + return undefined + } + current = current[path[i]] + } + return current as T + } + + const path = settingPath.split('.') + const result = accessSetting(config, path) + + return typeof result === 'undefined' ? defaultValue : result +} + +export function loadDefaultConfigurations(): IConfigurationModel { + let file = path.join(pluginRoot, 'data/schema.json') + if (!fs.existsSync(file)) { + console.error('schema.json not found, reinstall coc.nvim to fix this!') + return { contents: {} } + } + let content = fs.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) + }) + } + }) + return { contents: config } +} + +export function getKeys(obj: { [key: string]: any }, curr?: string): string[] { + let keys: string[] = [] + for (let key of Object.keys(obj)) { + let val = obj[key] + let newKey = curr ? `${curr}.${key}` : key + keys.push(newKey) + if (objectLiteral(val)) { + keys.push(...getKeys(val, newKey)) + } + } + return keys +} + +export function getChangedKeys(from: { [key: string]: any }, to: { [key: string]: any }): string[] { + let keys: string[] = [] + let fromKeys = getKeys(from) + let toKeys = getKeys(to) + const added = toKeys.filter(key => !fromKeys.includes(key)) + const removed = fromKeys.filter(key => !toKeys.includes(key)) + keys.push(...added) + keys.push(...removed) + for (const key of fromKeys) { + if (!toKeys.includes(key)) continue + const value1 = getConfigurationValue(from, key) + const value2 = getConfigurationValue(to, key) + if (!equals(value1, value2)) { + keys.push(key) + } + } + return keys +} diff --git a/vim-config/plugins/coc.nvim/src/cursors/index.ts b/vim-config/plugins/coc.nvim/src/cursors/index.ts new file mode 100644 index 00000000..adbffbaa --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/cursors/index.ts @@ -0,0 +1,167 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-jsonrpc' +import { Range } from 'vscode-languageserver-types' +import events from '../events' +import Document from '../model/document' +import { comparePosition } from '../util/position' +import window from '../window' +import workspace from '../workspace' +import CursorSession from './session' +import { getVisualRanges, splitRange } from './util' +const logger = require('../util/logger')('cursors') + +interface Config { + cancelKey: string + previousKey: string + nextKey: string +} + +export default class Cursors { + private sessionsMap: Map = new Map() + private disposables: Disposable[] = [] + private config: Config + constructor(private nvim: Neovim) { + this.loadConfig() + workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('cursors')) { + this.loadConfig() + } + }, null, this.disposables) + events.on('BufUnload', bufnr => { + let session = this.getSession(bufnr) + if (!session) return + session.dispose() + this.sessionsMap.delete(bufnr) + }, null, this.disposables) + } + + private loadConfig(): void { + let config = workspace.getConfiguration('cursors') + this.config = { + nextKey: config.get('nextKey', ''), + previousKey: config.get('previousKey', ''), + cancelKey: config.get('cancelKey', '') + } + } + + public getSession(bufnr: number): CursorSession | undefined { + return this.sessionsMap.get(bufnr) + } + + public async isActivated(): Promise { + let bufnr = await this.nvim.call('bufnr', ['%']) as number + return this.sessionsMap.get(bufnr) != null + } + + public async select(bufnr: number, kind: string, mode: string): Promise { + let doc = workspace.getDocument(bufnr) + if (!doc || !doc.attached) { + window.showMessage(`buffer ${bufnr} not attached.`) + return + } + let { nvim } = this + let session = this.createSession(doc) + let pos = await window.getCursorPosition() + let range: Range + if (kind == 'operator') { + await nvim.command(`normal! ${mode == 'line' ? `'[` : '`['}`) + let start = await window.getCursorPosition() + await nvim.command(`normal! ${mode == 'line' ? `']` : '`]'}`) + let end = await window.getCursorPosition() + await window.moveTo(pos) + let relative = 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, Range.create(start, end)) + for (let r of ranges) { + let text = doc.textDocument.getText(r) + session.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 = Range.create(pos.line, Math.max(0, line.length - 1), pos.line, line.length) + } else { + range = 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) + session.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 = Range.create(pos.line, line.length - 1, pos.line, line.length) + } else { + range = Range.create(pos.line, pos.character, pos.line, pos.character + 1) + } + session.addRange(range, line.slice(range.start.character, range.end.character)) + } else if (kind == 'range') { + await nvim.call('eval', 'feedkeys("\\", "in")') + let range = await workspace.getSelectedRange(mode, doc) + if (!range || 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) + session.addRange(r, text) + } + } else { + window.showMessage(`${kind} not supported`, 'error') + return + } + if (kind == 'word' || kind == 'position') { + await nvim.command(`silent! call repeat#set("\\(coc-cursors-${kind})", -1)`) + } + } + + private createSession(doc: Document): CursorSession { + let session = this.getSession(doc.bufnr) + if (session) return session + session = new CursorSession(this.nvim, doc, this.config) + this.sessionsMap.set(doc.bufnr, session) + session.onDidCancel(() => { + session.dispose() + this.sessionsMap.delete(doc.bufnr) + }) + return session + } + + // Add ranges to current document + public async addRanges(ranges: Range[]): Promise { + let { nvim } = this + let bufnr = await nvim.call('bufnr', ['%']) as number + let doc = workspace.getDocument(bufnr) + if (!doc || !doc.attached) { + window.showMessage('Document not attached', 'error') + return false + } + let session = this.createSession(doc) + return session.addRanges(ranges) + } + + public reset(): void { + for (let session of this.sessionsMap.values()) { + session.cancel() + } + this.sessionsMap.clear() + } + + public dispose(): void { + for (let session of this.sessionsMap.values()) { + session.dispose() + } + this.sessionsMap.clear() + for (let disposable of this.disposables) { + disposable.dispose() + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/cursors/range.ts b/vim-config/plugins/coc.nvim/src/cursors/range.ts new file mode 100644 index 00000000..8e732007 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/cursors/range.ts @@ -0,0 +1,104 @@ +import { Position, Range, TextEdit } from 'vscode-languageserver-types' +import { comparePosition } from '../util/position' +const logger = require('../util/logger')('cursors-range') + +// edit range +export default class TextRange { + private currStart: number + private currEnd: number + + constructor(public line: number, + public start: number, + public end: number, + public text: string, + // range count at this line before, shuld be updated on range add + public preCount: number) { + this.currStart = start + this.currEnd = end + } + + public add(offset: number, add: string): void { + 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 + } + + public replace(begin: number, end: number, add = ''): void { + 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 + } + + public get range(): Range { + return Range.create(this.line, this.start, this.line, this.end) + } + + public get currRange(): Range { + return Range.create(this.line, this.currStart, this.line, this.currEnd) + } + + public applyEdit(edit: TextEdit): void { + 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) + } + } + + /** + * Adjust from textEdit that not overlap + */ + public adjustFromEdit(edit: TextEdit): void { + let { range, newText } = edit + // no change if edit after current range + if (comparePosition(range.start, Position.create(this.line, this.currEnd)) > 0) { + return + } + let newLines = newText.split('\n') + let changeCount = newLines.length - (range.end.line - range.start.line + 1) + this.line = this.line + changeCount + if (range.end.line == this.line) { + let remove = range.start.line == range.end.line ? range.end.character - range.start.character : range.end.character + if (newLines.length > 1 && range.start.line == range.end.line) { + remove = remove + range.start.character + } + let add = 0 + if (newLines.length > 1) { + add = newLines[newLines.length - 1].length + } else { + if (range.start.line == range.end.line) { + add = newText.length + } else { + add = range.start.character + newText.length + } + } + let delta = add - remove + for (let key of ['start', 'end', 'currStart', 'currEnd']) { + this[key] += delta + } + } + } + + public sync(): void { + this.start = this.currStart + this.end = this.currEnd + } + + public get textEdit(): TextEdit { + return { + range: this.range, + newText: this.text + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/cursors/session.ts b/vim-config/plugins/coc.nvim/src/cursors/session.ts new file mode 100644 index 00000000..00ca3e3f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/cursors/session.ts @@ -0,0 +1,444 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import fastDiff from 'fast-diff' +import { Disposable, Emitter, Event, Range, TextEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import events from '../events' +import Document from '../model/document' +import { DidChangeTextDocumentParams } from '../types' +import { comparePosition, emptyRange, positionInRange, rangeInRange, rangeIntersect, rangeOverlap } from '../util/position' +import window from '../window' +import workspace from '../workspace' +import TextRange from './range' +import { adjustPosition, equalEdit } from './util' +const logger = require('../util/logger')('cursors-session') + +export interface Config { + cancelKey: string + previousKey: string + nextKey: string +} + +/** + * Cursor session for single buffer + */ +export default class CursorSession { + private readonly _onDidCancel = new Emitter() + public readonly onDidCancel: Event = this._onDidCancel.event + private disposables: Disposable[] = [] + private ranges: TextRange[] = [] + private activated = true + private changing = false + private changed = false + private textDocument: TextDocument + constructor( + private nvim: Neovim, + private doc: Document, + private config: Config) { + this.textDocument = this.doc.textDocument + this.buffer.setVar('coc_cursors_activated', 1, true) + let { cancelKey, nextKey, previousKey } = this.config + this.disposables.push(workspace.registerLocalKeymap('n', cancelKey, () => { + this.cancel() + }, true)) + this.disposables.push(workspace.registerLocalKeymap('n', nextKey, async () => { + if (!this.activated) return + let ranges = this.ranges.map(o => o.currRange) + let curr = await window.getCursorPosition() + for (let r of ranges) { + if (comparePosition(r.start, curr) > 0) { + await window.moveTo(r.start) + return + } + } + if (ranges.length) await window.moveTo(ranges[0].start) + }, true)) + this.disposables.push(workspace.registerLocalKeymap('n', previousKey, async () => { + if (!this.activated) return + let ranges = this.ranges.map(o => o.currRange) + ranges.reverse() + let curr = await window.getCursorPosition() + for (let r of ranges) { + if (comparePosition(r.end, curr) < 0) { + await window.moveTo(r.start) + return + } + } + if (ranges.length) await window.moveTo(ranges[ranges.length - 1].start) + }, true)) + this.doc.onDocumentChange(this.onChange, this, this.disposables) + } + + private async onChange(e: DidChangeTextDocumentParams): Promise { + if (!this.activated || this.ranges.length == 0) return + if (this.changing) return + let change = e.contentChanges[0] + let { text, range } = change + let intersect = this.ranges.some(r => rangeIntersect(range, r.currRange)) + let begin = this.ranges[0].currRange.start + if (text.endsWith('\n') && comparePosition(begin, range.end) == 0) { + // prepend lines + intersect = false + } + if (!intersect) { + this.ranges.forEach(r => { + r.adjustFromEdit({ range, newText: text }) + }) + this.doHighlights() + this.textDocument = this.doc.textDocument + return + } + this.changed = true + // get range from edit + let textRange = this.getTextRange(range, text) + if (textRange) { + await this.applySingleEdit(textRange, { range, newText: text }) + } else { + this.applyComposedEdit(e.original, { range, newText: text }) + if (this.activated) { + this.ranges.forEach(r => { + r.sync() + }) + this.textDocument = this.doc.textDocument + } + } + } + + private doHighlights(): void { + let { nvim, buffer, ranges } = this + buffer.clearNamespace('cursors') + let arr = ranges.map(o => o.currRange) + buffer.highlightRanges('cursors', 'CocCursorRange', arr) + nvim.command('redraw', true) + } + + public addRanges(ranges: Range[]): boolean { + let { nvim, doc } = this + if (this.changed) { + window.showMessage(`Can't add ranges after range change.`) + return false + } + // filter overlap ranges + this.ranges = this.ranges.filter(r => { + let { currRange } = r + return !ranges.some(range => rangeOverlap(range, currRange)) + }) + let { textDocument } = doc + for (let range of ranges) { + let { line } = range.start + let textRange = new TextRange(line, range.start.character, range.end.character, textDocument.getText(range), 0) + this.ranges.push(textRange) + } + this.ranges.sort((a, b) => 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 + } + nvim.pauseNotification() + this.doHighlights() + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + return true + } + + /** + * Cancel session and highlights + */ + public cancel(): void { + if (!this.activated) return + let { nvim } = this + this.activated = false + let { cancelKey, nextKey, previousKey } = this.config + nvim.pauseNotification() + this.buffer.clearNamespace('cursors') + this.buffer.setVar('coc_cursors_activated', 0, true) + nvim.command('redraw', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + this._onDidCancel.fire() + } + + /** + * Called on buffer unload or cancel + */ + public dispose(): void { + if (!this.doc) return + this._onDidCancel.dispose() + for (let disposable of this.disposables) { + disposable.dispose() + } + this.ranges = [] + this.doc = null + this.textDocument = null + } + + private get buffer(): Buffer { + return this.nvim.createBuffer(this.doc.bufnr) + } + + /** + * Find changed range from edit + */ + private getTextRange(range: Range, text: string): TextRange | null { + let { ranges } = this + 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 (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 positionInRange(next.currRange.start, range) ? null : r + } + } + return null + } + + /** + * Adjust change for current ranges + */ + private adjustRanges(textRange: TextRange, range: Range, text: string): void { + 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.includes(textRange.text)) { + 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.includes(text)) { + // 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) + }) + } + } + } + + public addRange(range: Range, text: string): void { + if (this.changed) { + window.showMessage(`Can't add range after range change.`) + return + } + let { ranges } = this + let idx = ranges.findIndex(o => 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 TextRange(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 + } + } + } + if (this.ranges.length == 0) { + this.cancel() + } else { + this.doHighlights() + } + } + + private async applySingleEdit(textRange: TextRange, edit: TextEdit): Promise { + // single range change, calculate & apply changes for all ranges + let { range, newText } = edit + let { doc } = this + this.adjustRanges(textRange, range, newText) + if (this.ranges.length == 1) { + this.doHighlights() + return + } + let edits = this.ranges.map(o => o.textEdit) + let content = TextDocument.applyEdits(this.textDocument, edits) + let newLines = content.split('\n') + let changedLnum: Set = new Set() + let arr: [number, string][] = [] + 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.changing = true + await doc.changeLines(arr) + this.changing = false + if (this.activated) { + this.ranges.forEach(r => { + r.sync() + }) + this.textDocument = this.doc.textDocument + } + // apply changes + nvim.pauseNotification() + let { cursor } = events + if (textRange.preCount > 0 && cursor.bufnr == doc.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() + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + + private applyComposedEdit(original: string, edit: TextEdit): void { + // check complex edit + let { range, newText } = edit + let { ranges } = this + let doc = TextDocument.create('file:///1', '', 0, original) + let edits: TextEdit[] = [] + let diffs = fastDiff(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] == fastDiff.EQUAL) { + offset = offset + diff[1].length + } else if (diff[0] == fastDiff.DELETE) { + let end = adjustPosition(range.start, doc.positionAt(offset + diff[1].length)) + if (diffs[i + 1] && diffs[i + 1][0] == fastDiff.INSERT) { + // change + edits.push({ range: Range.create(pos, end), newText: diffs[i + 1][1] }) + i = i + 1 + } else { + // delete + edits.push({ range: Range.create(pos, end), newText: '' }) + } + offset = offset + diff[1].length + } else if (diff[0] == fastDiff.INSERT) { + edits.push({ range: Range.create(pos, pos), newText: diff[1] }) + } + } + if (edits.some(edit => edit.newText.includes('\n') || edit.range.start.line != edit.range.end.line)) { + this.cancel() + return + } + if (edits.length == ranges.length) { + let last: TextEdit + for (let i = 0; i < edits.length; i++) { + let edit = edits[i] + let textRange = this.ranges[i] + if (!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 (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 (emptyRange(edit.range) && emptyRange(next.range)) { + // add begin & end + let textRange = this.ranges[i / 2] + if (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() + return + } + } + } else { + this.cancel() + return + } + this.doHighlights() + } +} diff --git a/vim-config/plugins/coc.nvim/src/cursors/util.ts b/vim-config/plugins/coc.nvim/src/cursors/util.ts new file mode 100644 index 00000000..0ad3839b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/cursors/util.ts @@ -0,0 +1,49 @@ +import { Range, Position, TextEdit } from 'vscode-languageserver-protocol' +import Document from '../model/document' + +/** + * Split to single line ranges + */ +export function splitRange(doc: Document, range: Range): Range[] { + let splited: Range[] = [] + 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(Range.create(i, sc, i, ec)) + } + return splited +} + +/** + * Get ranges of visual block + */ +export function getVisualRanges(doc: Document, range: Range): 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: Range[] = [] + for (let i = start.line; i <= end.line; i++) { + let line = doc.getline(i) + ranges.push(Range.create(i, sc, i, Math.min(line.length, ec))) + } + return ranges +} + +export function adjustPosition(position: Position, delta: Position): Position { + let { line, character } = delta + return Position.create(position.line + line, line == 0 ? position.character + character : character) +} + +export function equalEdit(one: TextEdit, two: TextEdit): boolean { + 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 +} diff --git a/vim-config/plugins/coc.nvim/src/diagnostic/buffer.ts b/vim-config/plugins/coc.nvim/src/diagnostic/buffer.ts new file mode 100644 index 00000000..8290d0bc --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/diagnostic/buffer.ts @@ -0,0 +1,392 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import { Mutex } from '../util/mutex' +import { Diagnostic, DiagnosticSeverity, DiagnosticTag, Position } from 'vscode-languageserver-protocol' +import { BufferSyncItem, FloatConfig, HighlightItem, LocationListItem } from '../types' +import { equals } from '../util/object' +import { comparePosition, lineInRange, positionInRange } from '../util/position' +import workspace from '../workspace' +import events from '../events' +import { getLocationListItem, getNameFromSeverity, getSeverityType } from './util' +const isVim = process.env.VIM_NODE_RPC == '1' +const logger = require('../util/logger')('diagnostic-buffer') +const signGroup = 'CocDiagnostic' +const highlightNamespace = 'diagnostic' +// higher priority first +const hlGroups = ['CocErrorHighlight', 'CocWarningHighlight', 'CocInfoHighlight', 'CocHintHighlight', 'CocDeprecatedHighlight', 'CocUnusedHighlight'] + +export enum DiagnosticHighlight { + Error = 'CocErrorHighlight', + Warning = 'CocWarningHighlight', + Information = 'CocInfoHighlight', + Hint = 'CocHintHighlight', + Deprecated = 'CocDeprecatedHighlight', + Unused = 'CocUnusedHighlight' +} + +export interface DiagnosticConfig { + highlighLimit: number + autoRefresh: boolean + enableSign: boolean + locationlistUpdate: boolean + enableHighlightLineNumber: boolean + checkCurrentLine: boolean + enableMessage: string + displayByAle: boolean + signPriority: number + errorSign: string + warningSign: string + infoSign: string + hintSign: string + level: number + messageTarget: string + messageDelay: number + refreshOnInsertMode: boolean + virtualText: boolean + virtualTextCurrentLineOnly: boolean + virtualTextSrcId: number + virtualTextPrefix: string + virtualTextLines: number + virtualTextLineSeparator: string + filetypeMap: object + showUnused?: boolean + showDeprecated?: boolean + format?: string + floatConfig: FloatConfig +} + +interface DiagnosticInfo { + /** + * current bufnr + */ + bufnr: number + lnum: number + winid: number + locationlist: string +} + +/** + * Manage diagnostics of buffer, including: + * + * - highlights + * - variable + * - signs + * - location list + * - virtual text + */ +export class DiagnosticBuffer implements BufferSyncItem { + private diagnosticsMap: Map> = new Map() + private mutex = new Mutex() + private _disposed = false + constructor( + private readonly nvim: Neovim, + public readonly bufnr: number, + public readonly uri: string, + private config: DiagnosticConfig, + private onRefresh: (diagnostics: ReadonlyArray) => void + ) { + } + + private get displayByAle(): boolean { + return this.config.displayByAle + } + + private clearHighlight(collection: string): void { + this.buffer.clearNamespace(highlightNamespace + collection) + } + + private clearSigns(collection: string): void { + this.buffer.unplaceSign({ group: signGroup + collection }) + } + + private get diagnostics(): Diagnostic[] { + let res: Diagnostic[] = [] + for (let diags of this.diagnosticsMap.values()) { + res.push(...diags) + } + return res + } + + private get buffer(): Buffer { + return this.nvim.createBuffer(this.bufnr) + } + + private refreshAle(collection: string, diagnostics: ReadonlyArray): void { + let aleItems = diagnostics.map(o => { + let range = o.range + 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: getSeverityType(o.severity) + } + }) + let method = global.hasOwnProperty('__TEST__') ? 'MockAleResults' : 'ale#other_source#ShowResults' + this.nvim.call(method, [this.bufnr, 'coc' + collection, aleItems], true) + } + + /** + * Refresh buffer with new diagnostics. + * + * @param {Object} diagnosticsMap + * @param {boolean} force Force highlights update. + */ + public async refresh(diagnosticsMap: { [collection: string]: Diagnostic[] }, force?: boolean): Promise { + let release = await this.mutex.acquire() + try { + await this._refresh(diagnosticsMap, force === true) + release() + } catch (e) { + release() + this.nvim.echoError(e) + } + } + + /** + * Refresh UI with new diagnostics. + */ + private async _refresh(diagnosticsMap: { [collection: string]: Diagnostic[] }, force: boolean): Promise { + let { refreshOnInsertMode } = this.config + let { nvim } = this + let checkInsert = !this.displayByAle && !refreshOnInsertMode + if (events.insertMode && checkInsert) return + let info = await nvim.call('coc#util#diagnostic_info', [this.bufnr, checkInsert]) as DiagnosticInfo | undefined + if (!info || this._disposed) return + if (this.displayByAle) { + nvim.pauseNotification() + for (let [collection, diagnostics] of Object.entries(diagnosticsMap)) { + // no need to save diagnostics + this.diagnosticsMap.set(collection, []) + this.refreshAle(collection, diagnostics) + } + await nvim.resumeNotification() + } else { + let changed = false + let redraw = false + nvim.pauseNotification() + for (let [collection, diagnostics] of Object.entries(diagnosticsMap)) { + let prev = this.diagnosticsMap.get(collection) || [] + this.diagnosticsMap.set(collection, diagnostics) + if (!equals(prev, diagnostics)) { + changed = true + redraw = true + this.addSigns(collection, diagnostics) + this.updateHighlights(collection, diagnostics) + } else if (prev.length && force) { + redraw = true + this.updateHighlights(collection, diagnostics) + } + } + if (changed) { + this.showVirtualText(info.lnum, info.bufnr) + this.updateLocationList(info.winid, info.locationlist) + this.setDiagnosticInfo() + } + if (isVim && redraw) this.nvim.command('redraw', true) + await this.nvim.resumeNotification() + } + this.onRefresh(this.diagnostics) + } + + public updateLocationList(winid: number, title: string): void { + if (!this.config.locationlistUpdate || winid == -1 || title !== 'Diagnostics of coc') return + let items: LocationListItem[] = [] + let { diagnostics } = this + diagnostics.sort(sortDiagnostics) + for (let diagnostic of diagnostics) { + let item = getLocationListItem(this.bufnr, diagnostic) + items.push(item) + } + this.nvim.call('setloclist', [winid, [], 'r', { title: 'Diagnostics of coc', items }], true) + } + + public addSigns(collection: string, diagnostics: ReadonlyArray): void { + if (!this.config.enableSign) return + let group = signGroup + collection + this.buffer.unplaceSign({ group }) + let signsMap: Map = new Map() + for (let diagnostic of diagnostics) { + let { range, severity } = diagnostic + let line = range.start.line + let exists = signsMap.get(line) || [] + if (exists.includes(severity)) { + continue + } + exists.push(severity) + signsMap.set(line, exists) + let priority = this.config.signPriority + 4 - severity + let name = getNameFromSeverity(severity) + this.buffer.placeSign({ name, lnum: line + 1, group, priority }) + } + } + + public setDiagnosticInfo(): void { + let lnums = [0, 0, 0, 0] + let info = { error: 0, warning: 0, information: 0, hint: 0, lnums } + for (let diagnostics of this.diagnosticsMap.values()) { + for (let diagnostic of diagnostics) { + let lnum = diagnostic.range.start.line + 1 + switch (diagnostic.severity) { + case DiagnosticSeverity.Warning: + info.warning = info.warning + 1 + lnums[1] = lnums[1] ? Math.min(lnums[1], lnum) : lnum + break + case DiagnosticSeverity.Information: + info.information = info.information + 1 + lnums[2] = lnums[2] ? Math.min(lnums[2], lnum) : lnum + break + case DiagnosticSeverity.Hint: + info.hint = info.hint + 1 + lnums[3] = lnums[3] ? Math.min(lnums[3], lnum) : lnum + break + default: + lnums[0] = lnums[0] ? Math.min(lnums[0], lnum) : lnum + info.error = info.error + 1 + } + } + } + let buf = this.nvim.createBuffer(this.bufnr) + buf.setVar('coc_diagnostic_info', info, true) + this.nvim.call('coc#util#do_autocmd', ['CocDiagnosticChange'], true) + } + + public showVirtualText(lnum: number, bufnr?: number): void { + if (!this.config.virtualText) return + let { virtualTextSrcId, virtualTextPrefix, virtualTextCurrentLineOnly } = this.config + let { diagnostics, buffer } = this + if (virtualTextCurrentLineOnly) { + if (bufnr && this.bufnr != bufnr) return + diagnostics = diagnostics.filter(d => { + let { start, end } = d.range + return start.line <= lnum - 1 && end.line >= lnum - 1 + }) + } + diagnostics.sort(sortDiagnostics) + buffer.clearNamespace(virtualTextSrcId) + for (let i = diagnostics.length - 1; i >= 0; i--) { + let diagnostic = diagnostics[i] + let { line } = diagnostic.range.start + let highlight = getNameFromSeverity(diagnostic.severity) + 'VirtualText' + let msg = diagnostic.message.split(/\n/) + .map((l: string) => l.trim()) + .filter((l: string) => l.length > 0) + .slice(0, this.config.virtualTextLines) + .join(this.config.virtualTextLineSeparator) + void buffer.setVirtualText(virtualTextSrcId, line, [[virtualTextPrefix + msg, highlight]], {}) + } + } + + public updateHighlights(collection: string, diagnostics: Diagnostic[]): void { + if (!diagnostics.length) { + this.clearHighlight(collection) + } else { + let items = this.getHighlightItems(diagnostics) + this.buffer.updateHighlights(highlightNamespace + collection, items) + } + } + + private getHighlightItems(diagnostics: ReadonlyArray): HighlightItem[] { + let doc = workspace.getDocument(this.bufnr) + if (!doc) return [] + let res: HighlightItem[] = [] + for (let diagnostic of diagnostics.slice(0, this.config.highlighLimit)) { + let hlGroup = getHighlightGroup(diagnostic) + doc.addHighlights(res, hlGroup, diagnostic.range) + } + // needed for iteration performance and since diagnostic highlight may cross lines. + res.sort((a, b) => { + if (a.lnum != b.lnum) return a.lnum - b.lnum + if (a.colStart != b.colStart) return a.colStart - b.colStart + return hlGroups.indexOf(b.hlGroup) - hlGroups.indexOf(a.hlGroup) + }) + return res + } + + /** + * Clear all diagnostics from UI. + */ + public clear(): void { + let { nvim } = this + let collections = Array.from(this.diagnosticsMap.keys()) + this.diagnosticsMap.clear() + if (this.displayByAle) { + for (let collection of collections) { + let method = global.hasOwnProperty('__TEST__') ? 'MockAleResults' : 'ale#other_source#ShowResults' + this.nvim.call(method, [this.bufnr, collection, []], true) + } + } else { + nvim.pauseNotification() + for (let collection of collections) { + this.clearHighlight(collection) + this.clearSigns(collection) + } + if (this.config.virtualText) { + this.buffer.clearNamespace(this.config.virtualTextSrcId) + } + this.buffer.deleteVar('coc_diagnostic_info') + void nvim.resumeNotification(false, true) + } + } + + /** + * Get diagnostics at cursor position. + */ + public getDiagnosticsAt(pos: Position, checkCurrentLine: boolean): Diagnostic[] { + let diagnostics: Diagnostic[] = [] + for (let diags of this.diagnosticsMap.values()) { + if (checkCurrentLine) { + diagnostics.push(...diags.filter(o => lineInRange(pos.line, o.range))) + } else { + diagnostics.push(...diags.filter(o => positionInRange(pos, o.range) == 0)) + } + } + diagnostics.sort(sortDiagnostics) + return diagnostics + } + + public async isEnabled(): Promise { + if (this._disposed) return false + let buf = this.nvim.createBuffer(this.bufnr) + let res = await buf.getVar('coc_diagnostic_disable') + return res != 1 + } + + public dispose(): void { + this._disposed = true + this.clear() + } +} + +/** + * Sort by severity and position + */ +function sortDiagnostics(a: Diagnostic, b: Diagnostic): number { + if ((a.severity || 1) != (b.severity || 1)) { + return (a.severity || 1) - (b.severity || 1) + } + let d = comparePosition(a.range.start, b.range.start) + if (d != 0) return d + return a.source > b.source ? 1 : -1 +} + +function getHighlightGroup(diagnostic: Diagnostic): DiagnosticHighlight { + let tags = diagnostic.tags || [] + if (tags.includes(DiagnosticTag.Deprecated)) { + return DiagnosticHighlight.Deprecated + } + if (tags.includes(DiagnosticTag.Unnecessary)) { + return DiagnosticHighlight.Unused + } + switch (diagnostic.severity) { + case DiagnosticSeverity.Warning: + return DiagnosticHighlight.Warning + case DiagnosticSeverity.Information: + return DiagnosticHighlight.Information + case DiagnosticSeverity.Hint: + return DiagnosticHighlight.Hint + default: + return DiagnosticHighlight.Error + } +} diff --git a/vim-config/plugins/coc.nvim/src/diagnostic/collection.ts b/vim-config/plugins/coc.nvim/src/diagnostic/collection.ts new file mode 100644 index 00000000..d0e75c23 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/diagnostic/collection.ts @@ -0,0 +1,86 @@ +import { Diagnostic, Emitter, Event, Range } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import workspace from '../workspace' +const logger = require('../util/logger')('diagnostic-collection') + +export default class DiagnosticCollection { + private diagnosticsMap: Map = new Map() + private _onDidDiagnosticsChange = new Emitter() + public readonly onDidDiagnosticsChange: Event = this._onDidDiagnosticsChange.event + + constructor( + public readonly name: string, + private onDispose?: () => void) { + } + + public set(uri: string, diagnostics: Diagnostic[] | undefined): void + public set(entries: [string, Diagnostic[] | undefined][]): void + public set(entries: [string, Diagnostic[] | undefined][] | string, diagnostics?: Diagnostic[]): void { + let diagnosticsPerFile: Map = new Map() + if (!Array.isArray(entries)) { + let doc = workspace.getDocument(entries) + let uri = doc ? doc.uri : entries + diagnosticsPerFile.set(uri, diagnostics || []) + } else { + for (let item of entries) { + let [uri, diagnostics] = item + let doc = workspace.getDocument(uri) + uri = doc ? doc.uri : uri + if (diagnostics == null) { + // clear previous diagnostics if entry contains null + diagnostics = [] + } else { + diagnostics = (diagnosticsPerFile.get(uri) || []).concat(diagnostics) + } + diagnosticsPerFile.set(uri, diagnostics) + } + } + for (let item of diagnosticsPerFile) { + let [uri, diagnostics] = item + uri = URI.parse(uri).toString() + diagnostics.forEach(o => { + // should be message for the file, but we need range + o.range = o.range || Range.create(0, 0, 0, 0) + o.message = o.message || '' + o.source = o.source || this.name + }) + this.diagnosticsMap.set(uri, diagnostics) + this._onDidDiagnosticsChange.fire(uri) + } + } + + public delete(uri: string): void { + this.diagnosticsMap.delete(uri) + this._onDidDiagnosticsChange.fire(uri) + } + + public clear(): void { + let uris = this.diagnosticsMap.keys() + this.diagnosticsMap.clear() + for (let uri of uris) { + this._onDidDiagnosticsChange.fire(uri) + } + } + + public forEach(callback: (uri: string, diagnostics: Diagnostic[], collection: DiagnosticCollection) => any, thisArg?: any): void { + for (let uri of this.diagnosticsMap.keys()) { + let diagnostics = this.diagnosticsMap.get(uri) + callback.call(thisArg, uri, diagnostics, this) + } + } + + public get(uri: string): Diagnostic[] { + let arr = this.diagnosticsMap.get(uri) + return arr == null ? [] : arr + } + + public has(uri: string): boolean { + return this.diagnosticsMap.has(uri) + } + + public dispose(): void { + this.clear() + if (this.onDispose) this.onDispose() + this._onDidDiagnosticsChange.dispose() + } +} diff --git a/vim-config/plugins/coc.nvim/src/diagnostic/manager.ts b/vim-config/plugins/coc.nvim/src/diagnostic/manager.ts new file mode 100644 index 00000000..de4e34a0 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/diagnostic/manager.ts @@ -0,0 +1,635 @@ +import { Neovim } from '@chemzqm/neovim' +import debounce from 'debounce' +import { Diagnostic, DiagnosticSeverity, DiagnosticTag, Disposable, Emitter, Event, Location, Position, Range } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import events from '../events' +import BufferSync from '../model/bufferSync' +import FloatFactory from '../model/floatFactory' +import { ConfigurationChangeEvent, ErrorItem, LocationListItem } from '../types' +import { disposeAll } from '../util' +import { comparePosition, rangeIntersect } from '../util/position' +import window from '../window' +import workspace from '../workspace' +import { DiagnosticBuffer, DiagnosticConfig } from './buffer' +import DiagnosticCollection from './collection' +import { getLocationListItem, getSeverityName, severityLevel } from './util' +const logger = require('../util/logger')('diagnostic-manager') + +export interface DiagnosticEventParams { + bufnr: number + uri: string + diagnostics: ReadonlyArray +} + +export interface DiagnosticItem { + file: string + lnum: number + end_lnum: number + col: number + end_col: number + source: string + code: string | number + message: string + severity: string + level: number + location: Location +} + +export class DiagnosticManager implements Disposable { + public config: DiagnosticConfig + private enabled = true + private readonly _onDidRefresh = new Emitter() + public readonly onDidRefresh: Event = this._onDidRefresh.event + private buffers: BufferSync + private floatFactory: FloatFactory + private collections: DiagnosticCollection[] = [] + private disposables: Disposable[] = [] + private timer: NodeJS.Timer + + public init(): void { + this.setConfiguration() + workspace.onDidChangeConfiguration(e => { + this.setConfiguration(e) + }, null, this.disposables) + + this.floatFactory = new FloatFactory(this.nvim) + this.buffers = workspace.registerBufferSync(doc => { + if (doc.buftype !== '') return undefined + let buf = new DiagnosticBuffer( + this.nvim, doc.bufnr, doc.uri, this.config, + diagnostics => { + this._onDidRefresh.fire({ diagnostics, uri: buf.uri, bufnr: buf.bufnr }) + if (['never', 'jump'].includes(this.config.enableMessage)) return + if (events.insertMode) return + this.echoMessage(true).logError() + }) + let collections = this.getCollections(doc.uri) + if (this.enabled && collections.length) { + let diagnostics = this.getDiagnostics(doc.uri) + void buf.refresh(diagnostics) + } + return buf + }) + + workspace.onDidCloseTextDocument(e => { + for (let collection of this.collections) { + collection.delete(e.uri) + } + }, null, this.disposables) + + events.on('CursorMoved', bufnr => { + if (this.config.enableMessage != 'always') return + if (!this.buffers.getItem(bufnr)) return + if (this.timer) clearTimeout(this.timer) + this.timer = setTimeout(async () => { + await this.echoMessage(true) + }, this.config.messageDelay) + }, null, this.disposables) + + let fn = debounce((bufnr, cursor) => { + if (!this.config.virtualTextCurrentLineOnly) return + let buf = this.buffers.getItem(bufnr) + if (buf) buf.showVirtualText(cursor[0]) + }, 100) + events.on('CursorMoved', fn, null, this.disposables) + this.disposables.push(Disposable.create(() => { + fn.clear() + })) + let timer: NodeJS.Timer + events.on('InsertLeave', async bufnr => { + if (this.config.refreshOnInsertMode || !this.autoRefresh) return + let doc = workspace.getDocument(bufnr) + if (!doc?.attached) return + doc._forceSync() + timer = setTimeout(() => { + if (events.insertMode) return + for (let buf of this.buffers.items) { + void buf.refresh(this.getDiagnostics(buf.uri), false) + } + }, Math.max(0, 500 - Date.now() + events.lastChangeTs)) + }, null, this.disposables) + let clear = () => { + if (timer) clearTimeout(timer) + } + this.disposables.push({ dispose: clear }) + events.on('InsertEnter', clear, null, this.disposables) + events.on('BufEnter', async () => { + if (this.timer) clearTimeout(this.timer) + }, null, this.disposables) + let errorItems = workspace.configurations.errorItems + this.setConfigurationErrors(errorItems) + workspace.configurations.onError(items => { + this.setConfigurationErrors(items) + }, null, this.disposables) + } + + private defineSigns(): void { + let { nvim } = this + let { enableHighlightLineNumber, enableSign } = this.config + if (!enableSign) return + nvim.pauseNotification() + for (let kind of ['Error', 'Warning', 'Info', 'Hint']) { + let signText = this.config[kind.toLowerCase() + 'Sign'] + let cmd = `sign define Coc${kind} linehl=Coc${kind}Line` + if (signText) cmd += ` texthl=Coc${kind}Sign text=${signText}` + if (enableHighlightLineNumber) cmd += ` numhl=Coc${kind}Sign` + nvim.command(cmd, true) + } + void nvim.resumeNotification(false, true) + } + + /** + * Fill location list with diagnostics + */ + public async setLocationlist(bufnr: number): Promise { + let buf = this.buffers.getItem(bufnr) + let diagnosticsMap = buf ? this.getDiagnostics(buf.uri) : {} + let items: LocationListItem[] = [] + for (let diagnostics of Object.values(diagnosticsMap)) { + for (let diagnostic of diagnostics) { + let item = getLocationListItem(bufnr, diagnostic) + items.push(item) + } + } + let curr = await this.nvim.call('getloclist', [0, { title: 1 }]) as any + let action = curr.title && curr.title.indexOf('Diagnostics of coc') != -1 ? 'r' : ' ' + await this.nvim.call('setloclist', [0, [], action, { title: 'Diagnostics of coc', items }]) + } + + public setConfigurationErrors(errorItems?: ErrorItem[]): void { + let collection = this.create('config') + if (errorItems?.length) { + let entries: Map = new Map() + for (let item of errorItems) { + let { uri } = item.location + let diagnostics: Diagnostic[] = entries.get(uri) || [] + diagnostics.push(Diagnostic.create(item.location.range, item.message, DiagnosticSeverity.Error)) + entries.set(uri, diagnostics) + } + collection.set(Array.from(entries)) + } else { + collection.clear() + } + } + + /** + * Create collection by name + */ + public create(name: string): DiagnosticCollection { + let collection = this.getCollectionByName(name) + if (collection) return collection + collection = new DiagnosticCollection(name, () => { + let idx = this.collections.findIndex(o => o == collection) + if (idx !== -1) this.collections.splice(idx, 1) + }) + this.collections.push(collection) + collection.onDidDiagnosticsChange(uri => { + let buf = this.buffers.getItem(uri) + if (!this.autoRefresh || !buf) return + if (events.insertMode && !this.config.refreshOnInsertMode) return + void buf.refresh(this.getDiagnostics(uri, name), true) + }) + return collection + } + + /** + * Get diagnostics ranges from document + */ + public getSortedRanges(uri: string, severity?: string): Range[] { + let collections = this.getCollections(uri) + let res: Range[] = [] + let level = severity ? severityLevel(severity) : 0 + for (let collection of collections) { + let diagnostics = collection.get(uri) + if (level) { + diagnostics = diagnostics.filter(o => o.severity == level) + } else { + let minLevel = this.config.level + if (minLevel && minLevel < DiagnosticSeverity.Hint) { + diagnostics = diagnostics.filter(o => { + if (o.severity && o.severity > minLevel) { + return false + } + return true + }) + } + } + 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 + */ + public getDiagnostics(uri: string, collection?: string): { [collection: string]: Diagnostic[] } { + let res: { [collection: string]: Diagnostic[] } = {} + let collections = collection ? [this.getCollectionByName(collection)] : this.getCollections(uri) + let { level, showUnused, showDeprecated } = this.config + for (let collection of collections) { + if (!collection) continue + let items = collection.get(uri) || [] + if (items.length) { + items = items.filter(d => { + if (level && d.severity && d.severity > level) { + return false + } + if (!showUnused && d.tags?.includes(DiagnosticTag.Unnecessary)) { + return false + } + if (!showDeprecated && d.tags?.includes(DiagnosticTag.Deprecated)) { + return false + } + return true + }) + items.sort((a, b) => { + return comparePosition(a.range.start, b.range.start) + }) + } + res[collection.name] = items + } + return res + } + + public getDiagnosticsInRange(document: TextDocument, range: Range): Diagnostic[] { + let collections = this.getCollections(document.uri) + let res: Diagnostic[] = [] + for (let collection of collections) { + let items = collection.get(document.uri) + if (!items) continue + for (let item of items) { + if (rangeIntersect(item.range, range)) { + res.push(item) + } + } + } + return res + } + + /** + * Show diagnostics under curosr in preview window + */ + public async preview(): Promise { + let diagnostics = await this.getCurrentDiagnostics() + if (diagnostics.length == 0) { + this.nvim.command('pclose', true) + return + } + let lines: string[] = [] + for (let diagnostic of diagnostics) { + let { source, code, severity, message } = diagnostic + let s = getSeverityName(severity)[0] + lines.push(`[${source}${code ? ' ' + code : ''}] [${s}]`) + lines.push(...message.split(/\r?\n/)) + lines.push('') + } + this.nvim.call('coc#util#preview_info', [lines, 'txt'], true) + } + + /** + * Jump to previous diagnostic position + */ + public async jumpPrevious(severity?: string): Promise { + let buffer = await this.nvim.buffer + let document = workspace.getDocument(buffer.id) + if (!document) return + let curpos = await window.getCursorPosition() + let ranges = this.getSortedRanges(document.uri, severity) + let pos: Position + for (let i = ranges.length - 1; i >= 0; i--) { + let end = ranges[i].end + if (comparePosition(end, curpos) < 0) { + pos = ranges[i].start + break + } else if (i == 0) { + let wrapscan = await this.nvim.getOption('wrapscan') + if (wrapscan) pos = ranges[ranges.length - 1].start + } + } + if (pos) { + await window.moveTo(pos) + if (this.config.enableMessage == 'never') return + await this.echoMessage(false) + } + } + + /** + * Jump to next diagnostic position + */ + public async jumpNext(severity?: string): Promise { + let buffer = await this.nvim.buffer + let document = workspace.getDocument(buffer.id) + let curpos = await window.getCursorPosition() + let ranges = this.getSortedRanges(document.uri, severity) + let pos: Position + for (let i = 0; i <= ranges.length - 1; i++) { + let start = ranges[i].start + if (comparePosition(start, curpos) > 0) { + pos = ranges[i].start + break + } else if (i == ranges.length - 1) { + let wrapscan = await this.nvim.getOption('wrapscan') + if (wrapscan) pos = ranges[0].start + } + } + if (pos) { + await window.moveTo(pos) + if (this.config.enableMessage == 'never') return + await this.echoMessage(false) + } + } + + /** + * All diagnostics of current workspace + */ + public getDiagnosticList(): DiagnosticItem[] { + let res: DiagnosticItem[] = [] + const { level, showUnused, showDeprecated } = this.config + for (let collection of this.collections) { + collection.forEach((uri, diagnostics) => { + let file = URI.parse(uri).fsPath + for (let diagnostic of diagnostics) { + if (diagnostic.severity && diagnostic.severity > level) { + continue + } + if (!showUnused && diagnostic.tags?.includes(DiagnosticTag.Unnecessary)) { + continue + } + if (!showDeprecated && diagnostic.tags?.includes(DiagnosticTag.Deprecated)) { + continue + } + let { start, end } = diagnostic.range + let o: DiagnosticItem = { + file, + lnum: start.line + 1, + end_lnum: end.line + 1, + col: start.character + 1, + end_col: end.character + 1, + code: diagnostic.code, + source: diagnostic.source || collection.name, + message: diagnostic.message, + severity: getSeverityName(diagnostic.severity), + level: diagnostic.severity || 0, + location: 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 + } + + private getDiagnosticsAt(bufnr: number, cursor: [number, number], atEnd = false, lastline = false): Diagnostic[] { + let buffer = this.buffers.getItem(bufnr) + if (!buffer) return [] + let pos = Position.create(cursor[0], cursor[1]) + let res = buffer.getDiagnosticsAt(pos, this.config.checkCurrentLine) + if (this.config.checkCurrentLine || res.length) return res + // check next character when cursor at end of line. + if (atEnd) { + pos = Position.create(cursor[0], cursor[1] + 1) + res = buffer.getDiagnosticsAt(pos, false) + if (res.length) return res + } + // check next line when cursor at the beginning of last line. + if (lastline && cursor[1] == 0) { + pos = Position.create(cursor[0] + 1, 0) + res = buffer.getDiagnosticsAt(pos, false) + } + return res + } + + public async getCurrentDiagnostics(): Promise { + let [bufnr, cursor, eol, lastline] = await this.nvim.eval(`[bufnr("%"),coc#cursor#position(),col('.')==col('$')-1,line('.')==line('$')]`) as [number, [number, number], number, number] + return this.getDiagnosticsAt(bufnr, cursor, eol == 1, lastline == 1) + } + + /** + * Echo diagnostic message under cursor. + */ + public async echoMessage(truncate = false): Promise { + const config = this.config + if (!this.enabled || config.displayByAle) return + if (this.timer) clearTimeout(this.timer) + let useFloat = config.messageTarget == 'float' + // echo + let [filetype, mode] = await this.nvim.eval(`[&filetype,mode()]`) as [string, string] + if (mode != 'n') return + let diagnostics = await this.getCurrentDiagnostics() + if (diagnostics.length == 0) { + if (useFloat) this.floatFactory.close() + return + } + if (truncate && workspace.insertMode) return + let docs = [] + let ft = '' + if (Object.keys(config.filetypeMap).length > 0) { + const defaultFiletype = config.filetypeMap['default'] || '' + ft = config.filetypeMap[filetype] || (defaultFiletype == 'bufferType' ? filetype : defaultFiletype) + } + diagnostics.forEach(diagnostic => { + let { source, code, severity, message } = diagnostic + let s = getSeverityName(severity)[0] + const codeStr = code ? ' ' + code : '' + const str = config.format.replace('%source', source).replace('%code', codeStr).replace('%severity', s).replace('%message', message) + let filetype = 'Error' + if (ft === '') { + switch (severity) { + case DiagnosticSeverity.Hint: + filetype = 'Hint' + break + case DiagnosticSeverity.Warning: + filetype = 'Warning' + break + case DiagnosticSeverity.Information: + filetype = 'Info' + break + } + } else { + filetype = ft + } + docs.push({ filetype, content: str }) + }) + if (useFloat) { + let config = this.floatFactory.applyFloatConfig({ modes: ['n'], maxWidth: 80 }, this.config.floatConfig) + await this.floatFactory.show(docs, config) + } else { + let lines = docs.map(d => d.content).join('\n').split(/\r?\n/) + if (lines.length) { + await this.nvim.command('echo ""') + await window.echoLines(lines, truncate) + } + } + } + + public async jumpRelated(): Promise { + 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.jumpTo(locations[0].uri, locations[0].range.start) + } else if (locations.length > 1) { + await workspace.showLocations(locations) + } + } + + public reset(): void { + if (this.timer) { + clearTimeout(this.timer) + } + this.buffers.reset() + for (let collection of this.collections) { + collection.dispose() + } + this.collections = [] + } + + public dispose(): void { + this.buffers.dispose() + if (this.timer) { + clearTimeout(this.timer) + } + for (let collection of this.collections) { + collection.dispose() + } + this.floatFactory?.close() + this.collections = [] + disposeAll(this.disposables) + } + + private get nvim(): Neovim { + return workspace.nvim + } + + private setConfiguration(event?: ConfigurationChangeEvent): void { + if (event && !event.affectsConfiguration('diagnostic')) return + let config = workspace.getConfiguration('diagnostic') + let messageTarget = config.get('messageTarget', 'float') + if (messageTarget == 'float' && !workspace.env.floating && !workspace.env.textprop) { + messageTarget = 'echo' + } + let enableHighlightLineNumber = config.get('enableHighlightLineNumber', true) + if (!workspace.isNvim) enableHighlightLineNumber = false + this.config = { + floatConfig: config.get('floatConfig', {}), + messageTarget, + enableHighlightLineNumber, + highlighLimit: config.get('highlighLimit', 1000), + autoRefresh: config.get('autoRefresh', true), + virtualTextSrcId: workspace.createNameSpace('diagnostic-virtualText'), + checkCurrentLine: config.get('checkCurrentLine', false), + enableSign: workspace.env.sign && config.get('enableSign', true), + locationlistUpdate: config.get('locationlistUpdate', true), + enableMessage: config.get('enableMessage', 'always'), + messageDelay: config.get('messageDelay', 200), + virtualText: config.get('virtualText', false) && this.nvim.hasFunction('nvim_buf_set_virtual_text'), + virtualTextCurrentLineOnly: config.get('virtualTextCurrentLineOnly', true), + virtualTextPrefix: config.get('virtualTextPrefix', " "), + virtualTextLineSeparator: config.get('virtualTextLineSeparator', " \\ "), + virtualTextLines: config.get('virtualTextLines', 3), + displayByAle: config.get('displayByAle', false), + level: severityLevel(config.get('level', 'hint')), + signPriority: config.get('signPriority', 10), + errorSign: config.get('errorSign', '>>'), + warningSign: config.get('warningSign', '>>'), + infoSign: config.get('infoSign', '>>'), + hintSign: config.get('hintSign', '>>'), + refreshOnInsertMode: config.get('refreshOnInsertMode', false), + filetypeMap: config.get('filetypeMap', {}), + showUnused: config.get('showUnused', true), + showDeprecated: config.get('showDeprecated', true), + format: config.get('format', '[%source%code] [%severity] %message'), + } + this.enabled = config.get('enable', true) + this.defineSigns() + } + + public getCollectionByName(name: string): DiagnosticCollection { + return this.collections.find(o => o.name == name) + } + + private getCollections(uri: string): DiagnosticCollection[] { + return this.collections.filter(c => c.has(uri)) + } + + public toggleDiagnostic(): void { + let { enabled } = this + this.enabled = !enabled + for (let buf of this.buffers.items) { + if (this.enabled) { + void this.refreshBuffer(buf.uri, true) + } else { + buf.clear() + } + } + } + + public async toggleDiagnosticBuffer(bufnr: number): Promise { + if (!this.enabled) return + let buf = this.buffers.getItem(bufnr) + if (buf) { + let isEnabled = await buf.isEnabled() + await this.nvim.call('setbufvar', [bufnr, 'coc_diagnostic_disable', isEnabled ? 1 : 0]) + if (isEnabled) { + buf.clear() + } else { + void this.refreshBuffer(bufnr, true) + } + } + } + + private get autoRefresh(): boolean { + return this.enabled && this.config.autoRefresh + } + + /** + * Refresh diagnostics by uri or bufnr + */ + public async refreshBuffer(uri: string | number, force = false): Promise { + let buf = this.buffers.getItem(uri) + if (!buf) return false + await buf.refresh(this.getDiagnostics(buf.uri), force) + return true + } + + /** + * Force diagnostics refresh. + */ + public refresh(bufnr?: number): void { + if (!bufnr) { + for (let item of this.buffers.items) { + void this.refreshBuffer(item.uri, true) + } + } else { + let item = this.buffers.getItem(bufnr) + if (item) { + void this.refreshBuffer(item.uri, true) + } + } + } +} + +export default new DiagnosticManager() diff --git a/vim-config/plugins/coc.nvim/src/diagnostic/util.ts b/vim-config/plugins/coc.nvim/src/diagnostic/util.ts new file mode 100644 index 00000000..83d7335c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/diagnostic/util.ts @@ -0,0 +1,74 @@ +import { DiagnosticSeverity, Diagnostic } from 'vscode-languageserver-protocol' +import { LocationListItem } from '../types' + +export function getSeverityName(severity: DiagnosticSeverity): string { + switch (severity) { + case DiagnosticSeverity.Warning: + return 'Warning' + case DiagnosticSeverity.Information: + return 'Information' + case DiagnosticSeverity.Hint: + return 'Hint' + default: + return 'Error' + } +} + +export function getSeverityType(severity: DiagnosticSeverity): string { + switch (severity) { + case DiagnosticSeverity.Warning: + return 'W' + case DiagnosticSeverity.Information: + return 'I' + case DiagnosticSeverity.Hint: + return 'I' + default: + return 'E' + } +} + +export function severityLevel(level: string): number { + switch (level) { + case 'hint': + return DiagnosticSeverity.Hint + case 'information': + return DiagnosticSeverity.Information + case 'warning': + return DiagnosticSeverity.Warning + case 'error': + return DiagnosticSeverity.Error + default: + return DiagnosticSeverity.Hint + } +} + +export function getNameFromSeverity(severity: DiagnosticSeverity): string { + switch (severity) { + case DiagnosticSeverity.Error: + return 'CocError' + case DiagnosticSeverity.Warning: + return 'CocWarning' + case DiagnosticSeverity.Information: + return 'CocInfo' + case DiagnosticSeverity.Hint: + return 'CocHint' + default: + return 'CocError' + } +} + +export function getLocationListItem(bufnr: number, diagnostic: Diagnostic): LocationListItem { + let { start, end } = diagnostic.range + let owner = diagnostic.source || 'coc.nvim' + let msg = diagnostic.message.split('\n')[0] + let type = getSeverityName(diagnostic.severity).slice(0, 1).toUpperCase() + return { + bufnr, + lnum: start.line + 1, + end_lnum: end.line + 1, + col: start.character + 1, + end_col: end.character + 1, + text: `[${owner}${diagnostic.code ? ' ' + diagnostic.code : ''}] ${msg} [${type}]`, + type + } +} diff --git a/vim-config/plugins/coc.nvim/src/events.ts b/vim-config/plugins/coc.nvim/src/events.ts new file mode 100644 index 00000000..7dbbb7f9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/events.ts @@ -0,0 +1,209 @@ +import { Disposable } from 'vscode-languageserver-protocol' +import { disposeAll } from './util' +import { VimCompleteItem } from './types' +import { equals } from './util/object' +const logger = require('./util/logger')('events') + +export type Result = void | Promise + +export interface PopupChangeEvent { + completed_item: VimCompleteItem | {} + height: number + width: number + row: number + col: number + size: number + scrollbar: boolean +} + +export interface InsertChange { + lnum: number + col: number + pre: string + changedtick: number +} + +export type BufEvents = 'BufHidden' | 'BufEnter' | 'BufWritePost' + | 'CursorHold' | 'InsertLeave' | 'TermOpen' | 'TermClose' | 'InsertEnter' + | 'BufCreate' | 'BufUnload' | 'BufWritePre' | 'CursorHoldI' | 'Enter' + +export type EmptyEvents = 'FocusGained' | 'FocusLost' | 'InsertSnippet' | 'ready' + +export type InsertChangeEvents = 'TextChangedP' | 'TextChangedI' + +export type TaskEvents = 'TaskExit' | 'TaskStderr' | 'TaskStdout' + +export type WindowEvents = 'WinLeave' | 'WinEnter' | 'WinClosed' + +export type AllEvents = BufEvents | EmptyEvents | MoveEvents | TaskEvents | WindowEvents + | InsertChangeEvents | 'CompleteDone' | 'TextChanged' | 'MenuPopupChanged' + | 'InsertCharPre' | 'FileType' | 'BufWinEnter' | 'BufWinLeave' | 'VimResized' + | 'DirChanged' | 'OptionSet' | 'Command' | 'BufReadCmd' | 'GlobalChange' | 'InputChar' + | 'WinLeave' | 'MenuInput' | 'PromptInsert' | 'FloatBtnClick' | 'InsertSnippet' | 'TextInsert' + +export type MoveEvents = 'CursorMoved' | 'CursorMovedI' + +export type OptionValue = string | number | boolean + +export interface CursorPosition { + bufnr: number + lnum: number + col: number + insert: boolean +} + +export interface LatestInsert { + bufnr: number + character: string + timestamp: number +} + +class Events { + + private handlers: Map = new Map() + private _cursor: CursorPosition + private _latestInsert: LatestInsert + private _lastChange = 0 + private _insertMode = false + private _pumAlignTop = false + + public get cursor(): CursorPosition { + return this._cursor + } + + public get pumAlignTop(): boolean { + return this._pumAlignTop + } + + public get insertMode(): boolean { + return this._insertMode + } + + public get lastChangeTs(): number { + return this._lastChange + } + + public async fire(event: string, args: any[]): Promise { + let cbs = 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 + void this.fire('InsertEnter', [args[0]]) + } else if (this._insertMode && (event == 'CursorHold' || event == 'CursorMoved')) { + this._insertMode = false + this.fire('InsertLeave', [args[0]]).logError() + } + if (event == 'MenuPopupChanged') { + this._pumAlignTop = args[1] > args[0].row + } + if (event == 'InsertCharPre') { + this._latestInsert = { bufnr: args[1], character: args[0], timestamp: Date.now() } + } + if (event == 'TextChanged') { + this._lastChange = Date.now() + } + if (event == 'TextChangedI' || event == 'TextChangedP') { + this._lastChange = Date.now() + if (this._latestInsert) { + let insert = this._latestInsert + this._latestInsert = undefined + if (insert.bufnr == args[0] && Date.now() - insert.timestamp < 200 && args[1].pre.length) { + let character = args[1].pre.slice(-1) + // make it fires after TextChangedI & TextChangedP + process.nextTick(() => { + void this.fire('TextInsert', [...args, character]) + }) + } + } + } + if (event == 'CursorMoved' || event == 'CursorMovedI') { + let cursor = { + bufnr: args[0], + lnum: args[1][0], + col: args[1][1], + insert: event == 'CursorMovedI' + } + // Avoid CursorMoved event when it's not moved at all + if (this._cursor && equals(this._cursor, cursor)) return + this._cursor = cursor + } + if (cbs) { + try { + await Promise.all(cbs.map(fn => fn(args))) + } catch (e) { + if (e.message && e.message.indexOf('transport disconnected') == -1) return + logger.error(`Error on event: ${event}`, e.stack) + } + } + } + + public on(event: EmptyEvents | AllEvents[], handler: () => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: BufEvents, handler: (bufnr: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: MoveEvents, handler: (bufnr: number, cursor: [number, number]) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: InsertChangeEvents, handler: (bufnr: number, info: InsertChange) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: WindowEvents, handler: (winid: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'TextInsert', handler: (bufnr: number, info: InsertChange, character: string) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'FloatBtnClick', handler: (bufnr: number, index: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'TextChanged', handler: (bufnr: number, changedtick: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'TaskExit', handler: (id: string, code: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'TaskStderr' | 'TaskStdout', handler: (id: string, lines: string[]) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'BufReadCmd', handler: (scheme: string, fullpath: string) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'VimResized', handler: (columns: number, lines: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'Command', handler: (name: string) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'MenuPopupChanged', handler: (event: PopupChangeEvent, cursorline: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'CompleteDone', handler: (item: VimCompleteItem) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'InsertCharPre', handler: (character: string, bufnr: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'FileType', handler: (filetype: string, bufnr: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'BufWinEnter' | 'BufWinLeave', handler: (bufnr: number, winid: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'DirChanged', handler: (cwd: string) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'OptionSet' | 'GlobalChange', handler: (option: string, oldVal: OptionValue, newVal: OptionValue) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'InputChar', handler: (session: string, character: string, mode: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: 'PromptInsert', handler: (value: string, bufnr: number) => Result, thisArg?: any, disposables?: Disposable[]): Disposable + public on(event: AllEvents[] | AllEvents, handler: (...args: any[]) => Result, thisArg?: any, disposables?: Disposable[]): Disposable { + if (Array.isArray(event)) { + let arr = disposables || [] + for (let ev of event) { + this.on(ev as any, handler, thisArg, arr) + } + return Disposable.create(() => { + disposeAll(arr) + }) + } else { + let arr = this.handlers.get(event) || [] + let stack = Error().stack + let wrappedhandler = args => new Promise((resolve, reject) => { + let timer + try { + Promise.resolve(handler.apply(thisArg || null, args)).then(() => { + if (timer) clearTimeout(timer) + resolve(undefined) + }, e => { + if (timer) clearTimeout(timer) + reject(e) + }) + timer = setTimeout(() => { + logger.warn(`Handler of ${event} blocked more than 2s:`, stack) + }, 2000) + } catch (e) { + reject(e) + } + }) + arr.push(wrappedhandler) + this.handlers.set(event, arr) + let disposable = Disposable.create(() => { + let idx = arr.indexOf(wrappedhandler) + if (idx !== -1) { + arr.splice(idx, 1) + } + }) + if (disposables) { + disposables.push(disposable) + } + return disposable + } + } +} +export default new Events() diff --git a/vim-config/plugins/coc.nvim/src/extensions.ts b/vim-config/plugins/coc.nvim/src/extensions.ts new file mode 100644 index 00000000..1be986d2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/extensions.ts @@ -0,0 +1,1061 @@ +import { debounce } from 'debounce' +import { parse, ParseError } from 'jsonc-parser' +import fs from 'fs-extra' +import isuri from 'isuri' +import path from 'path' +import semver from 'semver' +import { Disposable, Emitter, Event } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import which from 'which' +import commandManager from './commands' +import events from './events' +import DB from './model/db' +import FloatFactory from './model/floatFactory' +import InstallBuffer from './model/installBuffer' +import { createInstallerFactory } from './model/installer' +import Memos from './model/memos' +import { disposeAll, wait, concurrent, watchFile } from './util' +import { distinct, splitArray } from './util/array' +import './util/extensions' +import { createExtension, ExtensionExport } from './util/factory' +import { inDirectory, readFile, statAsync } from './util/fs' +import { objectLiteral } from './util/is' +import Watchman from './watchman' +import workspace from './workspace' +import window from './window' +import { OutputChannel } from './types' + +const createLogger = require('./util/logger') +const logger = createLogger('extensions') + +export type API = { [index: string]: any } | void | null | undefined + +export type ExtensionState = 'disabled' | 'loaded' | 'activated' | 'unknown' + +export enum ExtensionType { + Global, + Local, + SingleFile, + Internal +} + +export interface PropertyScheme { + type: string + default: any + description: string + enum?: string[] + items?: any + [key: string]: any +} + +export interface Extension { + readonly id: string + readonly extensionPath: string + readonly isActive: boolean + readonly packageJSON: any + readonly exports: T + activate(): Promise +} + +export interface ExtensionItem { + id: Readonly + type: Readonly + extension: Extension + deactivate: () => void | Promise + filepath?: string + directory?: string + isLocal: Readonly +} + +export interface ExtensionJson { + name: string + main?: string + engines: { + [key: string]: string + } + version?: string + [key: string]: any +} + +export interface ExtensionInfo { + id: string + version: string + description: string + root: string + exotic: boolean + uri?: string + state: ExtensionState + isLocal: boolean + packageJSON: Readonly +} + +// global local file native +export class Extensions { + private extensions: Map = new Map() + private disabled: Set = new Set() + private db: DB + private memos: Memos + private root: string + private _onDidLoadExtension = new Emitter>() + private _onDidActiveExtension = new Emitter>() + private _onDidUnloadExtension = new Emitter() + private _additionalSchemes: { [key: string]: PropertyScheme } = {} + private activated = false + private installBuffer: InstallBuffer + private disposables: Disposable[] = [] + private _outputChannel: OutputChannel | undefined + public ready = true + public readonly onDidLoadExtension: Event> = this._onDidLoadExtension.event + public readonly onDidActiveExtension: Event> = this._onDidActiveExtension.event + public readonly onDidUnloadExtension: Event = this._onDidUnloadExtension.event + + constructor() { + let folder = global.hasOwnProperty('__TEST__') ? path.join(__dirname, '__tests__') : process.env.COC_DATA_HOME + let root = this.root = path.join(folder, 'extensions') + if (!fs.existsSync(root)) { + fs.mkdirpSync(root) + } + let jsonFile = path.join(root, 'package.json') + if (!fs.existsSync(jsonFile)) { + fs.writeFileSync(jsonFile, '{"dependencies":{}}', 'utf8') + } + let filepath = path.join(root, 'db.json') + this.db = new DB(filepath) + } + + private get outputChannel(): OutputChannel { + if (this._outputChannel) return this._outputChannel + this._outputChannel = window.createOutputChannel('extensions') + return this._outputChannel + } + + public async init(): Promise { + let extensionObj = this.db.fetch('extension') || {} + let keys = Object.keys(extensionObj) + for (let key of keys) { + if (extensionObj[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.map(o => o.id)) + stats = stats.concat(localStats) + this.memos = new Memos(path.resolve(this.root, '../memos.json')) + stats.map(stat => { + let extensionType = stat.isLocal ? ExtensionType.Local : ExtensionType.Global + try { + this.createExtension(stat.root, stat.packageJSON, extensionType) + } catch (e) { + logger.error(`Error on create ${stat.root}:`, e) + } + }) + await this.loadFileExtensions() + commandManager.register({ + id: 'extensions.forceUpdateAll', + execute: async () => { + let arr = await this.cleanExtensions() + logger.info(`Force update extensions: ${arr}`) + await this.installExtensions(arr) + } + }, false, 'remove all global extensions and install them') + workspace.onDidRuntimePathChange(async paths => { + for (let p of paths) { + if (p && this.checkDirectory(p) === true) { + await this.loadExtension(p) + } + } + }, null, this.disposables) + } + + public activateExtensions(): void { + this.activated = true + for (let item of this.extensions.values()) { + let { id, packageJSON } = item.extension + this.setupActiveEvents(id, packageJSON).logError() + } + // make sure workspace.env exists + let floatFactory = new FloatFactory(workspace.nvim) + events.on('CursorMoved', debounce(async bufnr => { + if (this.installBuffer && bufnr == this.installBuffer.bufnr) { + let lnum = await workspace.nvim.call('line', ['.']) + let msgs = this.installBuffer.getMessages(lnum - 1) + let docs = msgs && msgs.length ? [{ content: msgs.join('\n'), filetype: 'txt' }] : [] + await floatFactory.show(docs, { modes: ['n'] }) + } + }, 500)) + if (global.hasOwnProperty('__TEST__')) return + // check extensions need watch & install + this.checkExtensions().logError() + let config = workspace.getConfiguration('coc.preferences') + let interval = config.get('extensionUpdateCheck', 'never') + let silent = config.get('silentAutoupdate', true) + 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.outputChannel.appendLine('Start auto update...') + this.updateExtensions(false, silent).logError() + } + } + + public async updateExtensions(sync?: boolean, silent = false): Promise { + if (!this.npm) return + let lockedList = await this.getLockedList() + let stats = await this.globalExtensionStats() + stats = stats.filter(o => ![...lockedList, ...this.disabled].includes(o.id)) + this.db.push('lastUpdate', Date.now()) + if (silent) { + window.showMessage('Updating extensions, checkout output:///extensions for details.', 'more') + } + let installBuffer = this.installBuffer = new InstallBuffer(true, sync, silent ? this.outputChannel : undefined) + installBuffer.setExtensions(stats.map(o => o.id)) + await installBuffer.show(workspace.nvim) + let createInstaller = createInstallerFactory(this.npm, this.modulesFolder) + let fn = (stat: ExtensionInfo): Promise => { + let { id } = stat + installBuffer.startProgress([id]) + let url = stat.exotic ? stat.uri : null + // msg => installBuffer.addMessage(id, msg) + let installer = createInstaller(id) + installer.on('message', (msg, isProgress) => { + installBuffer.addMessage(id, msg, isProgress) + }) + return installer.update(url).then(directory => { + installBuffer.finishProgress(id, true) + if (directory) { + this.loadExtension(directory).logError() + } + }, err => { + installBuffer.addMessage(id, err.message) + installBuffer.finishProgress(id, false) + }) + } + await concurrent(stats, fn, silent ? 1 : 3) + } + + private async checkExtensions(): Promise { + let { globalExtensions } = workspace.env + if (globalExtensions && globalExtensions.length) { + let names = this.filterGlobalExtensions(globalExtensions) + this.installExtensions(names).logError() + } + } + + public get installer() { + return createInstallerFactory(this.npm, this.modulesFolder) + } + + /** + * Install extensions, can be called without initialize. + */ + public async installExtensions(list: string[] = []): Promise { + let { npm } = this + if (!npm || !list.length) return + list = distinct(list) + let installBuffer = this.installBuffer = new InstallBuffer() + installBuffer.setExtensions(list) + await installBuffer.show(workspace.nvim) + let createInstaller = createInstallerFactory(this.npm, this.modulesFolder) + let fn = (key: string): Promise => { + installBuffer.startProgress([key]) + let installer = createInstaller(key) + installer.on('message', (msg, isProgress) => { + installBuffer.addMessage(key, msg, isProgress) + }) + return installer.install().then(name => { + installBuffer.finishProgress(key, true) + let directory = path.join(this.modulesFolder, name) + this.loadExtension(directory).logError() + }, err => { + installBuffer.addMessage(key, err.message) + installBuffer.finishProgress(key, false) + logger.error(`Error on install ${key}`, err) + }) + } + await concurrent(list, fn) + } + + /** + * Get list of extensions in package.json that not installed + */ + public getMissingExtensions(): string[] { + let json = this.loadJson() || { dependencies: {} } + let ids: string[] = [] + for (let key of Object.keys(json.dependencies)) { + let folder = path.join(this.modulesFolder, key) + if (!fs.existsSync(folder)) { + let val = json.dependencies[key] + if (val.startsWith('http')) { + ids.push(val) + } else { + ids.push(key) + } + } + } + return ids + } + + public get npm(): string { + let npm = workspace.getConfiguration('npm').get('binPath', 'npm') + npm = workspace.expand(npm) + for (let exe of [npm, 'yarnpkg', 'yarn', 'npm']) { + try { + let res = which.sync(exe) + return res + } catch (e) { + continue + } + } + window.showMessage(`Can't find npm or yarn in your $PATH`, 'error') + return null + } + + /** + * Get all loaded extensions. + */ + public get all(): Extension[] { + return Array.from(this.extensions.values()).map(o => o.extension).filter(o => !this.isDisabled(o.id)) + } + + public getExtension(id: string): ExtensionItem { + return this.extensions.get(id) + } + + public getExtensionState(id: string): ExtensionState { + let disabled = this.isDisabled(id) + if (disabled) return 'disabled' + let item = this.extensions.get(id) + if (!item) return 'unknown' + let { extension } = item + return extension.isActive ? 'activated' : 'loaded' + } + + public async getExtensionStates(): Promise { + let localStats = await this.localExtensionStats([]) + let globalStats = await this.globalExtensionStats() + return localStats.concat(globalStats.filter(o => localStats.find(s => s.id == o.id) == null)) + } + + public async getLockedList(): Promise { + let obj = await this.db.fetch('extension') + obj = obj || {} + return Object.keys(obj).filter(id => obj[id].locked === true) + } + + public async toggleLock(id: string): Promise { + let key = `extension.${id}.locked` + let locked = await this.db.fetch(key) + if (locked) { + this.db.delete(key) + } else { + this.db.push(key, true) + } + } + + public async toggleExtension(id: string): Promise { + let state = this.getExtensionState(id) + if (state == null) return + if (state == 'activated') { + await this.deactivate(id) + } + let key = `extension.${id}.disabled` + this.db.push(key, state == 'disabled' ? false : true) + if (state != 'disabled') { + this.disabled.add(id) + await this.unloadExtension(id) + } else { + this.disabled.delete(id) + let folder = path.join(this.modulesFolder, id) + if (fs.existsSync(folder)) { + await this.loadExtension(folder) + } + } + await wait(200) + } + + public async reloadExtension(id: string): Promise { + let item = this.extensions.get(id) + if (!item) { + window.showMessage(`Extension ${id} not registered`, 'error') + return + } + if (item.type == ExtensionType.Internal) { + window.showMessage(`Can't reload internal extension "${item.id}"`, 'warning') + return + } + if (item.type == ExtensionType.SingleFile) { + await this.loadExtensionFile(item.filepath) + } else if (item.directory) { + await this.loadExtension(item.directory) + } else { + window.showMessage(`Can't reload extension ${item.id}`, 'warning') + } + } + + /** + * Unload & remove all global extensions, return removed extensions. + */ + public async cleanExtensions(): Promise { + let dir = this.modulesFolder + if (!fs.existsSync(dir)) return [] + let ids = this.globalExtensions + let res: string[] = [] + for (let id of ids) { + let directory = path.join(dir, id) + let stat = await fs.lstat(directory) + if (!stat || (stat && stat.isSymbolicLink())) continue + await this.unloadExtension(id) + await fs.remove(directory) + res.push(id) + } + return res + } + + public async uninstallExtension(ids: string[]): Promise { + try { + if (!ids.length) return + let [globals, filtered] = splitArray(ids, id => this.globalExtensions.includes(id)) + if (filtered.length) { + window.showMessage(`Extensions ${filtered} not global extensions, can't uninstall!`, 'warning') + } + let json = this.loadJson() || { dependencies: {} } + for (let id of globals) { + await this.unloadExtension(id) + delete json.dependencies[id] + // remove directory + let folder = path.join(this.modulesFolder, id) + if (fs.existsSync(folder)) { + await fs.remove(folder) + } + } + // update package.json + const sortedObj = { dependencies: {} } + Object.keys(json.dependencies).sort().forEach(k => { + sortedObj.dependencies[k] = json.dependencies[k] + }) + let jsonFile = path.join(this.root, 'package.json') + fs.writeFileSync(jsonFile, JSON.stringify(sortedObj, null, 2), { encoding: 'utf8' }) + window.showMessage(`Removed: ${globals.join(' ')}`) + } catch (e) { + window.showMessage(`Uninstall failed: ${e.message}`, 'error') + } + } + + public isDisabled(id: string): boolean { + return this.disabled.has(id) + } + + public has(id: string): boolean { + return this.extensions.has(id) + } + + public isActivated(id: string): boolean { + let item = this.extensions.get(id) + if (item && item.extension.isActive) { + return true + } + return false + } + + /** + * Load extension from folder, folder should contains coc extension. + */ + public async loadExtension(folder: string): Promise { + try { + let parentFolder = path.dirname(folder) + let isLocal = path.normalize(parentFolder) != path.normalize(this.modulesFolder) + let jsonFile = path.join(folder, 'package.json') + let packageJSON = JSON.parse(fs.readFileSync(jsonFile, 'utf8')) + let { name } = packageJSON + if (this.isDisabled(name)) return false + // unload if loaded + await this.unloadExtension(name) + this.createExtension(folder, Object.freeze(packageJSON), isLocal ? ExtensionType.Local : ExtensionType.Global) + return true + } catch (e) { + window.showMessage(`Error on load extension from "${folder}": ${e.message}`, 'error') + logger.error(`Error on load extension from ${folder}`, e) + return false + } + } + + private async loadFileExtensions(): Promise { + if (!process.env.COC_VIMCONFIG) return + let folder = path.join(process.env.COC_VIMCONFIG, 'coc-extensions') + if (!fs.existsSync(folder)) return + let files = await fs.readdir(folder) + files = files.filter(f => f.endsWith('.js')) + for (let file of files) { + await this.loadExtensionFile(path.join(folder, file)) + } + } + + public loadedExtensions(): string[] { + return Array.from(this.extensions.keys()) + } + + public async watchExtension(id: string): Promise { + let item = this.extensions.get(id) + if (!item) { + window.showMessage(`extension ${id} not found`, 'error') + return + } + if (id.startsWith('single-')) { + window.showMessage(`watching ${item.filepath}`) + this.disposables.push(watchFile(item.filepath, async () => { + await this.loadExtensionFile(item.filepath) + window.showMessage(`reloaded ${id}`) + })) + } else { + let watchmanPath = workspace.getWatchmanPath() + if (!watchmanPath) { + window.showMessage('watchman not found', 'error') + return + } + let client = await Watchman.createClient(watchmanPath, item.directory) + if (!client) { + window.showMessage(`Can't create watchman client, check output:///watchman`) + return + } + window.showMessage(`watching ${item.directory}`) + this.disposables.push(client) + client.subscribe('**/*.js', async () => { + await this.reloadExtension(id) + window.showMessage(`reloaded ${id}`) + }).then(disposable => { + this.disposables.push(disposable) + }, e => { + logger.error(e) + }) + } + } + + /** + * Load single javascript file as extension. + */ + public async loadExtensionFile(filepath: string): Promise { + let filename = path.basename(filepath) + let basename = path.basename(filepath, '.js') + let name = 'single-' + basename + if (this.isDisabled(name)) return + let root = path.dirname(filepath) + let packageJSON = { + name, main: filename, engines: { coc: '^0.0.79' } + } + let confpath = path.join(root, basename + '.json') + let stat = await statAsync(confpath) + if (stat && stat.isFile()) { + let content = await readFile(confpath, 'utf8') + let obj = JSON.parse(content) + if (obj) { + let attrs = ['activationEvents', 'contributes'] + for (const attr of attrs) { + if (obj[attr]) { + packageJSON[attr] = obj[attr] + } + } + } + } + await this.unloadExtension(name) + this.createExtension(root, packageJSON, ExtensionType.SingleFile) + } + + /** + * Activate extension, throw error if disabled or not exists + * Returns true if extension successfully activated. + */ + public async activate(id): Promise { + if (this.isDisabled(id)) { + throw new Error(`Extension ${id} is disabled!`) + } + let item = this.extensions.get(id) + if (!item) { + throw new Error(`Extension ${id} not registered!`) + } + let { extension } = item + if (extension.isActive) return true + await Promise.resolve(extension.activate()) + if (extension.isActive) { + this._onDidActiveExtension.fire(extension) + return true + } + return false + } + + public async deactivate(id): Promise { + let item = this.extensions.get(id) + if (!item) return false + await Promise.resolve(item.deactivate()) + return true + } + + public async call(id: string, method: string, args: any[]): Promise { + let item = this.extensions.get(id) + if (!item) throw new Error(`extension ${id} not registered`) + let { extension } = item + if (!extension.isActive) { + await this.activate(id) + } + let { exports } = extension + if (!exports || !exports.hasOwnProperty(method)) { + throw new Error(`method ${method} not found on extension ${id}`) + } + return await Promise.resolve(exports[method].apply(null, args)) + } + + public getExtensionApi(id: string): API | null { + let item = this.extensions.get(id) + if (!item) return null + let { extension } = item + return extension.isActive ? extension.exports : null + } + + public registerExtension(extension: Extension, deactivate?: () => void): void { + let { id, packageJSON } = extension + this.extensions.set(id, { id, type: ExtensionType.Internal, 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.configurations.extendsDefaults(props) + } + } + this._onDidLoadExtension.fire(extension) + this.setupActiveEvents(id, packageJSON).logError() + } + + public get globalExtensions(): string[] { + let json = this.loadJson() + if (!json || !json.dependencies) return [] + return Object.keys(json.dependencies) + } + + private async globalExtensionStats(): Promise { + let json = this.loadJson() + if (!json || !json.dependencies) return [] + let { modulesFolder } = this + let res: ExtensionInfo[] = await Promise.all(Object.keys(json.dependencies).map(key => new Promise(async resolve => { + try { + let val = json.dependencies[key] + let root = path.join(modulesFolder, key) + let res = this.checkDirectory(root) + if (res instanceof Error) { + window.showMessage(`Unable to load global extension at ${root}: ${res.message}`, 'error') + logger.error(`Error on load ${root}`, res) + return resolve(null) + } + let content = await readFile(path.join(root, 'package.json'), 'utf8') + root = await fs.realpath(root) + let obj = JSON.parse(content) + let version = obj ? obj.version || '' : '' + let description = obj ? obj.description || '' : '' + let uri = isuri.isValid(val) ? val : '' + resolve({ + id: key, + isLocal: false, + version, + description, + exotic: /^https?:/.test(val), + uri: uri.replace(/\.git(#master)?$/, ''), + root, + state: this.getExtensionState(key), + packageJSON: Object.freeze(obj) + }) + } catch (e) { + logger.error(e) + resolve(null) + } + }))) + return res.filter(info => info != null) + } + + private async localExtensionStats(excludes: string[]): Promise { + let runtimepath = await workspace.nvim.eval('&runtimepath') as string + let paths = runtimepath.split(',') + let res: ExtensionInfo[] = await Promise.all(paths.map(root => new Promise(async resolve => { + try { + let res = this.checkDirectory(root) + if (res !== true) return resolve(null) + let jsonFile = path.join(root, 'package.json') + let content = await readFile(jsonFile, 'utf8') + let obj = JSON.parse(content) + let exist = this.extensions.get(obj.name) + if (exist && !exist.isLocal) { + logger.info(`Extension "${obj.name}" in runtimepath already loaded.`) + return resolve(null) + } + if (excludes.includes(obj.name)) { + logger.info(`Skipped load vim plugin from "${root}", "${obj.name}" already global extension.`) + 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), + packageJSON: Object.freeze(obj) + }) + } catch (e) { + logger.error(e) + resolve(null) + } + }))) + return res.filter(info => info != null) + } + + private loadJson(): any { + let { root } = this + let jsonFile = path.join(root, 'package.json') + if (!fs.existsSync(jsonFile)) return null + let errors: ParseError[] = [] + let content = fs.readFileSync(jsonFile, 'utf8') + let data = parse(content, errors, { allowTrailingComma: true }) + if (errors && errors.length > 0) { + window.showMessage(`Error on parse ${jsonFile}`, 'error') + workspace.nvim.call('coc#util#open_file', ['edit', jsonFile], true) + } + return data + } + + public get schemes(): { [key: string]: PropertyScheme } { + return this._additionalSchemes + } + + public addSchemeProperty(key: string, def: PropertyScheme): void { + this._additionalSchemes[key] = def + workspace.configurations.extendsDefaults({ [key]: def.default }) + } + + private async setupActiveEvents(id: string, packageJSON: any): Promise { + let { activationEvents } = packageJSON + if (!this.canActivate(id)) return + if (!activationEvents || Array.isArray(activationEvents) && activationEvents.includes('*')) { + await this.activate(id).catch(e => { + window.showMessage(`Error on activate extension ${id}: ${e.message}`) + this.outputChannel.appendLine(`Error on activate extension ${id}.\n${e.message}\n ${e.stack}`) + }) + return + } + let disposables: Disposable[] = [] + let active = (): Promise => { + disposeAll(disposables) + return new Promise(resolve => { + if (!this.canActivate(id)) { + this.outputChannel.appendLine(`Extension ${id} is disabled or not loaded.`) + return resolve() + } + let timer = setTimeout(() => { + this.outputChannel.appendLine(`Extension ${id} activate cost more than 1s`) + resolve() + }, 1000) + this.activate(id).then(() => { + clearTimeout(timer) + resolve() + }, e => { + clearTimeout(timer) + window.showMessage(`Error on activate extension ${id}: ${e.message}`) + this.outputChannel.appendLine(`Error on activate extension ${id}:${e.message}\n ${e.stack}`) + resolve() + }) + }) + } + + for (let eventName of activationEvents as string[]) { + let parts = eventName.split(':') + let ev = parts[0] + if (ev == 'onLanguage') { + if (workspace.filetypes.has(parts[1])) { + await active() + return + } + workspace.onDidOpenTextDocument(document => { + if (document.languageId == parts[1]) { + void active() + } + }, null, disposables) + } else if (ev == 'onCommand') { + commandManager.onCommandList.push(parts[1]) + events.on('Command', async command => { + if (command == parts[1]) { + await active() + await wait(500) + } + }, null, disposables) + } else if (ev == 'workspaceContains') { + let check = async () => { + let folders = workspace.workspaceFolders.map(o => URI.parse(o.uri).fsPath) + for (let folder of folders) { + if (inDirectory(folder, parts[1].split(/\s+/))) { + await active() + return true + } + } + } + let res = await check() + if (res) return + workspace.onDidChangeWorkspaceFolders(check, null, disposables) + } else if (ev == 'onFileSystem') { + for (let doc of workspace.documents) { + let u = URI.parse(doc.uri) + if (u.scheme == parts[1]) { + await active() + return + } + } + workspace.onDidOpenTextDocument(document => { + let u = URI.parse(document.uri) + if (u.scheme == parts[1]) { + void active() + } + }, null, disposables) + } else { + window.showMessage(`Unsupported event ${eventName} of ${id}`, 'error') + } + } + } + + private createExtension(root: string, packageJSON: any, type: ExtensionType): void { + let id = packageJSON.name + let isActive = false + let result: Promise | undefined + let filename = path.join(root, packageJSON.main || 'index.js') + let ext: ExtensionExport + let subscriptions: Disposable[] = [] + let exports: any + let extension: any = { + activate: (): Promise => { + if (result) return result + let context = { + subscriptions, + extensionPath: root, + globalState: this.memos.createMemento(`${id}|global`), + workspaceState: this.memos.createMemento(`${id}|${workspace.rootPath}`), + asAbsolutePath: relativePath => path.join(root, relativePath), + storagePath: path.join(this.root, `${id}-data`), + logger: createLogger(id) + } + if (!ext) { + try { + let isEmpty = !(packageJSON.engines || {}).hasOwnProperty('coc') + ext = createExtension(id, filename, isEmpty) + } catch (e) { + logger.error(`Error on createExtension ${id} from ${filename}`, e) + return + } + } + result = new Promise((resolve, reject) => { + try { + Promise.resolve(ext.activate(context)).then(res => { + isActive = true + exports = res + resolve(res) + }, e => { + logger.error(`Error on active extension ${id}: ${e.message}`, e) + reject(e) + }) + } catch (e) { + logger.error(`Error on active extension ${id}: ${e.stack}`, e) + reject(e) + } + }) + return result + } + } + Object.defineProperties(extension, { + id: { + get: () => id, + enumerable: true + }, + packageJSON: { + get: () => packageJSON, + enumerable: true + }, + extensionPath: { + get: () => root, + enumerable: true + }, + isActive: { + get: () => isActive, + enumerable: true + }, + exports: { + get: () => { + if (!isActive) throw new Error(`Invalid access to exports, extension "${id}" not activated`) + return exports + }, + enumerable: true + } + }) + + this.extensions.set(id, { + id, + type, + isLocal: type == ExtensionType.Local, + extension, + directory: root, + filepath: filename, + deactivate: () => { + if (!isActive) return + result = undefined + exports = undefined + isActive = false + disposeAll(subscriptions) + subscriptions.splice(0, subscriptions.length) + subscriptions = [] + if (ext && ext.deactivate) { + try { + return Promise.resolve(ext.deactivate()).catch(e => { + logger.error(`Error on ${id} deactivate: `, e) + }) + } catch (e) { + logger.error(`Error on ${id} deactivate: `, e) + } + } + } + }) + 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.configurations.extendsDefaults(props) + } + if (rootPatterns && rootPatterns.length) { + for (let item of rootPatterns) { + workspace.addRootPattern(item.filetype, item.patterns) + } + } + if (commands && commands.length) { + for (let cmd of commands) { + commandManager.titles.set(cmd.command, cmd.title) + } + } + } + this._onDidLoadExtension.fire(extension) + if (this.activated) { + this.setupActiveEvents(id, packageJSON).logError() + } + } + + /** + * Filter out global extensions that needs install + */ + public filterGlobalExtensions(names: string[]): string[] { + let map: Map = new Map() + names.forEach(def => { + let name = this.getExtensionName(def) + if (name) map.set(name, def) + }) + let json = this.loadJson() + let urls: string[] = [] + let exists: string[] = [] + if (json && json.dependencies) { + for (let key of Object.keys(json.dependencies)) { + let val = json.dependencies[key] + if (typeof val !== 'string') continue + if (fs.existsSync(path.join(this.modulesFolder, key, 'package.json'))) { + exists.push(key) + if (/^https?:/.test(val)) { + urls.push(val) + } + } + } + } + for (let name of map.keys()) { + if (this.disabled.has(name) || this.extensions.has(name)) { + map.delete(name) + continue + } + if ((/^https?:/.test(name) && urls.some(url => url.startsWith(name))) + || exists.includes(name)) { + map.delete(name) + } + } + return Array.from(map.values()) + } + + /** + * Name of extension + */ + private getExtensionName(def: string): string { + if (/^https?:/.test(def)) return def + if (!def.includes('@')) return def + return def.replace(/@[\d.]+$/, '') + } + + private get modulesFolder(): string { + return path.join(this.root, global.hasOwnProperty('__TEST__') ? '' : 'node_modules') + } + + private canActivate(id: string): boolean { + return !this.disabled.has(id) && this.extensions.has(id) + } + + /** + * Deactive & unregist extension + */ + private async unloadExtension(id: string): Promise { + let item = this.extensions.get(id) + if (item) { + await this.deactivate(id) + this.extensions.delete(id) + this._onDidUnloadExtension.fire(id) + } + } + + /** + * Check if folder contains extension, return Error + */ + private checkDirectory(folder: string): boolean | Error { + try { + let jsonFile = path.join(folder, 'package.json') + if (!fs.existsSync(jsonFile)) throw new Error('package.json not found') + let packageJSON = JSON.parse(fs.readFileSync(jsonFile, 'utf8')) + let { name, engines, main } = packageJSON + if (!name || !engines) throw new Error(`can't find name & engines in package.json`) + if (!engines || !objectLiteral(engines)) { + throw new Error(`invalid engines in ${jsonFile}`) + } + if (main && !fs.existsSync(path.join(folder, main))) { + throw new Error(`main file ${main} not found, you may need to build the project.`) + } + let keys = Object.keys(engines) + if (!keys.includes('coc') && !keys.includes('vscode')) { + throw new Error(`Engines in package.json doesn't have coc or vscode`) + } + if (keys.includes('coc')) { + let required = engines['coc'].replace(/^\^/, '>=') + if (!semver.satisfies(workspace.version, required)) { + throw new Error(`Please update coc.nvim, ${packageJSON.name} requires coc.nvim ${engines['coc']}`) + } + } + return true + } catch (e) { + return e + } + } + + public dispose(): void { + disposeAll(this.disposables) + } +} + +export default new Extensions() diff --git a/vim-config/plugins/coc.nvim/src/handler/callHierarchy.ts b/vim-config/plugins/coc.nvim/src/handler/callHierarchy.ts new file mode 100644 index 00000000..80c4ba4c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/callHierarchy.ts @@ -0,0 +1,257 @@ +import { Neovim } from '@chemzqm/neovim' +import path from 'path' +import { CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, CancellationToken, CancellationTokenSource, Disposable, Emitter, Position, Range, SymbolTag } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import commands from '../commands' +import events from '../events' +import languages from '../languages' +import { TreeDataProvider, TreeItem, TreeItemCollapsibleState } from '../tree/index' +import BasicTreeView from '../tree/TreeView' +import { ConfigurationChangeEvent, HandlerDelegate } from '../types' +import { disposeAll } from '../util' +import { omit } from '../util/lodash' +import workspace from '../workspace' +const logger = require('../util/logger')('Handler-callHierarchy') + +interface CallHierarchyDataItem extends CallHierarchyItem { + ranges?: Range[] + sourceUri?: string + children?: CallHierarchyItem[] +} + +interface CallHierarchyConfig { + splitCommand: string + openCommand: string + enableTooltip: boolean +} + +interface CallHierarchyProvider extends TreeDataProvider { + kind: 'incoming' | 'outgoing' + dispose: () => void +} + +function isCallHierarchyItem(item: any): item is CallHierarchyItem { + if (item && item.name && item.kind && Range.is(item.range) && item.uri) return true + return false +} + +export default class CallHierarchyHandler { + private config: CallHierarchyConfig + private disposables: Disposable[] = [] + public static commandId = 'callHierarchy.reveal' + public static rangesHighlight = 'CocSelectedRange' + private highlightWinids: Set = new Set() + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + this.loadConfiguration() + workspace.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables) + this.disposables.push(commands.registerCommand(CallHierarchyHandler.commandId, async (winid: number, item: CallHierarchyDataItem, openCommand?: string) => { + let { nvim } = this + await nvim.call('win_gotoid', [winid]) + await workspace.jumpTo(item.uri, item.selectionRange.start, openCommand) + let win = await nvim.window + win.clearMatchGroup(CallHierarchyHandler.rangesHighlight) + win.highlightRanges(CallHierarchyHandler.rangesHighlight, [item.selectionRange], 10, true) + if (!item.ranges?.length) return + if (item.sourceUri) { + let doc = workspace.getDocument(item.sourceUri) + if (!doc) return + let winid = await nvim.call('coc#compat#buf_win_id', [doc.bufnr]) + if (winid == -1) return + if (winid != win.id) { + win = nvim.createWindow(winid) + win.clearMatchGroup(CallHierarchyHandler.rangesHighlight) + } + } + win.highlightRanges(CallHierarchyHandler.rangesHighlight, item.ranges, 100, true) + this.highlightWinids.add(win.id) + }, null, true)) + events.on('BufWinEnter', (_, winid) => { + if (this.highlightWinids.has(winid)) { + this.highlightWinids.delete(winid) + let win = nvim.createWindow(winid) + win.clearMatchGroup(CallHierarchyHandler.rangesHighlight) + } + }, null, this.disposables) + } + + private loadConfiguration(e?: ConfigurationChangeEvent): void { + if (!e || e.affectsConfiguration('callHierarchy')) { + let c = workspace.getConfiguration('callHierarchy') + this.config = { + splitCommand: c.get('splitCommand'), + openCommand: c.get('openCommand'), + enableTooltip: c.get('enableTooltip') + } + } + } + + private createProvider(doc: TextDocument, winid: number, position: Position, kind: 'incoming' | 'outgoing'): CallHierarchyProvider { + let _onDidChangeTreeData = new Emitter() + let source: CancellationTokenSource | undefined + let rootItems: CallHierarchyDataItem[] | undefined + const cancel = () => { + if (source) { + source.cancel() + source.dispose() + source = null + } + } + const findParent = (curr: CallHierarchyDataItem, element: CallHierarchyDataItem): CallHierarchyDataItem | undefined => { + let children = curr.children + if (!Array.isArray(children)) return undefined + let find = children.find(o => o == element) + if (find) return curr + for (let item of children) { + let res = findParent(item, element) + if (res) return res + } + } + let provider: CallHierarchyProvider = { + kind, + onDidChangeTreeData: _onDidChangeTreeData.event, + getTreeItem: element => { + let item = new TreeItem(element.name, element.children ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed) + if (this.config.enableTooltip) { + item.tooltip = path.relative(workspace.cwd, URI.parse(element.uri).fsPath) + } + item.description = element.detail + item.deprecated = element.tags?.includes(SymbolTag.Deprecated) + item.icon = this.handler.getIcon(element.kind) + item.command = { + command: CallHierarchyHandler.commandId, + title: 'open location', + arguments: [winid, element, this.config.openCommand] + } + return item + }, + getChildren: async element => { + cancel() + source = new CancellationTokenSource() + let { token } = source + if (!element) { + if (!rootItems) { + rootItems = await this.prepare(doc, position, token) as CallHierarchyDataItem[] + if (!rootItems?.length) return + } + for (let o of rootItems) { + let children = await this.getChildren(doc, o, provider.kind, token) + if (token.isCancellationRequested) break + if (Array.isArray(children)) o.children = children + } + return rootItems + } + if (element.children) return element.children + let items = await this.getChildren(doc, element, provider.kind, token) + source = null + if (token.isCancellationRequested) return [] + element.children = items + return items + }, + resolveActions: () => { + return [{ + title: 'Open in new tab', + handler: async element => { + await commands.executeCommand(CallHierarchyHandler.commandId, winid, element, 'tabe') + } + }, { + title: 'Show Incoming Calls', + handler: element => { + rootItems = [omit(element, ['children', 'ranges', 'sourceUri'])] + provider.kind = 'incoming' + _onDidChangeTreeData.fire(undefined) + } + }, { + title: 'Show Outgoing Calls', + handler: element => { + rootItems = [omit(element, ['children', 'ranges', 'sourceUri'])] + provider.kind = 'outgoing' + _onDidChangeTreeData.fire(undefined) + } + }, { + title: 'Dismiss', + handler: async element => { + let parentElement: CallHierarchyDataItem | undefined + for (let curr of rootItems) { + parentElement = findParent(curr, element) + if (parentElement) break + } + if (!parentElement) return + let idx = parentElement.children.findIndex(o => o === element) + parentElement.children.splice(idx, 1) + _onDidChangeTreeData.fire(parentElement) + } + }] + }, + dispose: () => { + cancel() + _onDidChangeTreeData.dispose() + rootItems = undefined + _onDidChangeTreeData = undefined + } + } + return provider + } + + private async getChildren(doc: TextDocument, item: CallHierarchyItem, kind: 'incoming' | 'outgoing', token: CancellationToken): Promise { + let items: CallHierarchyDataItem[] = [] + if (kind == 'incoming') { + let res = await languages.provideIncomingCalls(doc, item, token) + if (res) items = res.map(o => Object.assign(o.from, { ranges: o.fromRanges })) + } else { + let res = await languages.provideOutgoingCalls(doc, item, token) + if (res) items = res.map(o => Object.assign(o.to, { ranges: o.fromRanges, sourceUri: item.uri })) + } + return items + } + + private async prepare(doc: TextDocument, position: Position, token: CancellationToken): Promise { + this.handler.checkProvier('callHierarchy', doc) + const res = await languages.prepareCallHierarchy(doc, position, token) + return isCallHierarchyItem(res) ? [res] : res + } + + private async getCallHierarchyItems(item: CallHierarchyItem | undefined, kind: 'outgoing'): Promise + private async getCallHierarchyItems(item: CallHierarchyItem | undefined, kind: 'incoming'): Promise + private async getCallHierarchyItems(item: CallHierarchyItem | undefined, kind: 'incoming' | 'outgoing'): Promise { + const { doc, position } = await this.handler.getCurrentState() + const source = new CancellationTokenSource() + if (!item) { + await doc.synchronize() + let res = await this.prepare(doc.textDocument, position, source.token) + item = res ? res[0] : undefined + if (!res) return undefined + } + let method = kind == 'incoming' ? 'provideIncomingCalls' : 'provideOutgoingCalls' + return await languages[method](doc.textDocument, item, source.token) + } + + public async getIncoming(item?: CallHierarchyItem): Promise { + return await this.getCallHierarchyItems(item, 'incoming') + } + + public async getOutgoing(item?: CallHierarchyItem): Promise { + return await this.getCallHierarchyItems(item, 'outgoing') + } + + public async showCallHierarchyTree(kind: 'incoming' | 'outgoing'): Promise { + const { doc, position, winid } = await this.handler.getCurrentState() + await doc.synchronize() + let provider = this.createProvider(doc.textDocument, winid, position, kind) + let treeView = new BasicTreeView('calls', { treeDataProvider: provider }) + treeView.title = `${kind.toUpperCase()} CALLS` + provider.onDidChangeTreeData(e => { + if (!e) treeView.title = `${provider.kind.toUpperCase()} CALLS` + }) + treeView.onDidChangeVisibility(e => { + if (!e.visible) provider.dispose() + }) + this.disposables.push(treeView) + await treeView.show(this.config.splitCommand) + } + + public dispose(): void { + this.highlightWinids.clear() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/codeActions.ts b/vim-config/plugins/coc.nvim/src/handler/codeActions.ts new file mode 100644 index 00000000..9fd54cff --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/codeActions.ts @@ -0,0 +1,140 @@ +import { NeovimClient as Neovim } from '@chemzqm/neovim' +import diagnosticManager from '../diagnostic/manager' +import { CodeAction, CodeActionContext, Range, CodeActionKind } from 'vscode-languageserver-protocol' +import commandManager from '../commands' +import workspace from '../workspace' +import Document from '../model/document' +import window from '../window' +import { HandlerDelegate } from '../types' +import languages from '../languages' +const logger = require('../util/logger')('handler-codeActions') + +/** + * Handle codeActions related methods. + */ +export default class CodeActions { + constructor( + private nvim: Neovim, + private handler: HandlerDelegate + ) { + handler.addDisposable(commandManager.registerCommand('editor.action.organizeImport', async (bufnr?: number) => { + await this.organizeImport(bufnr) + })) + commandManager.titles.set('editor.action.organizeImport', 'run organize import code action.') + } + + public async codeActionRange(start: number, end: number, only?: string): Promise { + let { doc } = await this.handler.getCurrentState() + await doc.synchronize() + let line = doc.getline(end - 1) + let range = Range.create(start - 1, 0, end - 1, line.length) + let codeActions = await this.getCodeActions(doc, range, only ? [only] : null) + if (!codeActions || codeActions.length == 0) { + window.showMessage(`No${only ? ' ' + only : ''} code action available`, 'warning') + return + } + let idx = await window.showMenuPicker(codeActions.map(o => o.title), 'Choose action') + let action = codeActions[idx] + if (action) await this.applyCodeAction(action) + } + + public async organizeImport(bufnr?: number): Promise { + let { doc } = await this.handler.getCurrentState() + if (bufnr && doc.bufnr != bufnr) return + await doc.synchronize() + let actions = await this.getCodeActions(doc, undefined, [CodeActionKind.SourceOrganizeImports]) + if (actions && actions.length) { + await this.applyCodeAction(actions[0]) + return + } + throw new Error('Organize import action not found.') + } + + public async getCodeActions(doc: Document, range?: Range, only?: CodeActionKind[]): Promise { + range = range || Range.create(0, 0, doc.lineCount, 0) + let diagnostics = diagnosticManager.getDiagnosticsInRange(doc.textDocument, range) + let context: CodeActionContext = { diagnostics } + if (only && Array.isArray(only)) context.only = only + let codeActions = await this.handler.withRequestToken('code action', token => { + return languages.getCodeActions(doc.textDocument, range, context, token) + }) + if (!codeActions || codeActions.length == 0) return [] + // TODO support fadeout disabled actions in menu + codeActions = codeActions.filter(o => !o.disabled) + codeActions.sort((a, b) => { + if (a.isPreferred && !b.isPreferred) return -1 + if (b.isPreferred && !a.isPreferred) return 1 + return 0 + }) + return codeActions + } + + private get floatActions(): boolean { + if (!workspace.floatSupported) return false + let config = workspace.getConfiguration('coc.preferences') + return config.get('floatActions', true) + } + + public async doCodeAction(mode: string | null, only?: CodeActionKind[] | string): Promise { + let { doc } = await this.handler.getCurrentState() + let range: Range + if (mode) range = await workspace.getSelectedRange(mode, doc) + await doc.synchronize() + let codeActions = await this.getCodeActions(doc, range, Array.isArray(only) ? only : null) + if (typeof only == 'string') { + codeActions = codeActions.filter(o => o.title == only || (o.command && o.command.title == only)) + } else if (Array.isArray(only)) { + codeActions = codeActions.filter(o => only.some(k => o.kind && o.kind.startsWith(k))) + } + if (!codeActions || codeActions.length == 0) { + window.showMessage(`No${only ? ' ' + only : ''} code action available`, 'warning') + return + } + if (only && codeActions.length == 1) { + await this.applyCodeAction(codeActions[0]) + return + } + let idx = this.floatActions + ? await window.showMenuPicker( + codeActions.map(o => o.title), + "Choose action" + ) + : await window.showQuickpick(codeActions.map(o => o.title)) + let action = codeActions[idx] + if (action) await this.applyCodeAction(action) + } + + /** + * Get current codeActions + */ + public async getCurrentCodeActions(mode?: string, only?: CodeActionKind[]): Promise { + let { doc } = await this.handler.getCurrentState() + let range: Range + if (mode) range = await workspace.getSelectedRange(mode, doc) + return await this.getCodeActions(doc, range, only) + } + + /** + * Invoke preferred quickfix at current position + */ + public async doQuickfix(): Promise { + let actions = await this.getCurrentCodeActions('line', [CodeActionKind.QuickFix]) + if (!actions || actions.length == 0) { + throw new Error('No quickfix action available') + } + await this.applyCodeAction(actions[0]) + this.nvim.command(`silent! call repeat#set("\\(coc-fix-current)", -1)`, true) + } + + public async applyCodeAction(action: CodeAction): Promise { + if (action.disabled) { + throw new Error(`Action "${action.title}" is disabled: ${action.disabled.reason}`) + } + action = await this.handler.withRequestToken('resolve codeAction', token => { + return languages.resolveCodeAction(action, token) + }) + let { edit, command } = action + if (edit) await workspace.applyEdit(edit) + if (command) await commandManager.execute(command) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/codelens/buffer.ts b/vim-config/plugins/coc.nvim/src/handler/codelens/buffer.ts new file mode 100644 index 00000000..9caa16e1 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/codelens/buffer.ts @@ -0,0 +1,213 @@ +import { Neovim } from '@chemzqm/neovim' +import debounce from 'debounce' +import { CancellationTokenSource, CodeLens, Command } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import commandManager from '../../commands' +import languages from '../../languages' +import { BufferSyncItem } from '../../types' +import window from '../../window' +import workspace from '../../workspace' +const logger = require('../../util/logger')('codelens-buffer') + +export interface CodeLensInfo { + codeLenses: CodeLens[] + version: number + hasError: boolean +} + +export interface CodeLensConfig { + enabled: boolean + separator: string + subseparator: string +} + +/** + * CodeLens buffer + */ +export default class CodeLensBuffer implements BufferSyncItem { + private codeLenses: CodeLensInfo + private tokenSource: CancellationTokenSource + private resolveTokenSource: CancellationTokenSource + private srcId: number + public fetchCodelenses: (() => void) & { clear(): void } + public resolveCodeLens: (() => void) & { clear(): void } + constructor( + private nvim: Neovim, + public readonly bufnr: number, + private config: CodeLensConfig + ) { + this.fetchCodelenses = debounce(() => { + void this._fetchCodeLenses() + }, 200) + this.resolveCodeLens = debounce(() => { + void this._resolveCodeLenses() + }, 200) + this.fetchCodelenses() + } + + public currentCodeLens(): CodeLens[] { + return this.codeLenses?.codeLenses + } + + private get enabled(): boolean { + return this.textDocument && this.config.enabled && languages.hasProvider('codeLens', this.textDocument) + } + + public async forceFetch(): Promise { + this.fetchCodelenses.clear() + await this._fetchCodeLenses() + } + + private get textDocument(): TextDocument | undefined { + return workspace.getDocument(this.bufnr)?.textDocument + } + + private async _fetchCodeLenses(): Promise { + if (!this.enabled) return + this.cancel() + let noFetch = !this.isChanged && !this.codeLenses?.hasError + if (!noFetch) { + let { textDocument } = this + let version = textDocument.version + let tokenSource = this.tokenSource = new CancellationTokenSource() + let token = tokenSource.token + let codeLenses = await languages.getCodeLens(textDocument, token) + this.tokenSource = undefined + if (token.isCancellationRequested) return + if (!Array.isArray(codeLenses) || codeLenses.length == 0) return + let hasError = codeLenses.some(o => o == null) + this.codeLenses = { version, codeLenses: codeLenses.filter(o => o != null), hasError } + } + let codeLenses = this.codeLenses?.codeLenses + if (codeLenses?.length) { + await this._resolveCodeLenses() + } + } + + /** + * Resolve visible codeLens + */ + private async _resolveCodeLenses(): Promise { + if (!this.enabled || !this.codeLenses || this.isChanged) return + let { codeLenses } = this.codeLenses + let [bufnr, start, end] = await this.nvim.eval(`[bufnr('%'),line('w0'),line('w$')]`) as [number, number, number] + // only resolve current buffer + if (this.isChanged || bufnr != this.bufnr) return + if (this.resolveTokenSource) { + this.resolveTokenSource.cancel() + } + codeLenses = codeLenses.filter(o => { + let lnum = o.range.start.line + 1 + return lnum >= start && lnum <= end + }) + if (codeLenses.length) { + let tokenSource = this.resolveTokenSource = new CancellationTokenSource() + let token = tokenSource.token + await Promise.all(codeLenses.map(codeLens => languages.resolveCodeLens(codeLens, token))) + this.resolveTokenSource = undefined + if (token.isCancellationRequested || this.isChanged) return + } + if (!this.srcId) this.srcId = await this.nvim.createNamespace('coc-codelens') + this.nvim.pauseNotification() + this.clear(start - 1, end) + this.setVirtualText(codeLenses) + await this.nvim.resumeNotification() + } + + private get isChanged(): boolean { + if (!this.textDocument || !this.codeLenses) return true + let { version } = this.codeLenses + return this.textDocument.version !== version + } + + /** + * Attach resolved codeLens + */ + private setVirtualText(codeLenses: CodeLens[]): void { + if (codeLenses.length == 0) return + let list: Map = new Map() + for (let codeLens of codeLenses) { + 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 codeLenses = list.get(lnum) + let commands = codeLenses.map(codeLens => codeLens.command) + commands = commands.filter(c => c && c.title) + let chunks = [] + let n_commands = commands.length + for (let i = 0; i < n_commands; i++) { + let c = commands[i] + chunks.push([c.title.replace(/(\r\n|\r|\n|\s)+/g, " "), 'CocCodeLens'] as [string, string]) + if (i != n_commands - 1) { + chunks.push([this.config.subseparator, 'CocCodeLens'] as [string, string]) + } + } + chunks.unshift([`${this.config.separator} `, 'CocCodeLens']) + this.nvim.call('nvim_buf_set_virtual_text', [this.bufnr, this.srcId, lnum, chunks, {}], true) + } + } + + public clear(start = 0, end = -1): void { + if (!this.srcId) return + let buf = this.nvim.createBuffer(this.bufnr) + buf.clearNamespace(this.srcId, start, end) + } + + public cleanUp(): void { + this.clear() + this.codeLenses = undefined + } + + public getCodelenses(): CodeLens[] | undefined { + return this.codeLenses?.codeLenses + } + + public async doAction(line: number): Promise { + let { codeLenses } = this.codeLenses ?? {} + if (!codeLenses?.length) return + let commands: Command[] = [] + for (let codeLens of codeLenses) { + let { range, command } = codeLens + if (!command || !range) continue + if (line == range.start.line) { + commands.push(command) + } + } + if (!commands.length) return + if (commands.length == 1) { + await commandManager.execute(commands[0]) + } else { + let res = await window.showMenuPicker(commands.map(c => c.title)) + if (res == -1) return + await commandManager.execute(commands[res]) + } + } + + private cancel(): void { + this.resolveCodeLens.clear() + this.fetchCodelenses.clear() + if (this.tokenSource) { + this.tokenSource.cancel() + this.tokenSource.dispose() + this.tokenSource = null + } + } + + public onChange(): void { + this.cancel() + this.fetchCodelenses() + } + + public dispose(): void { + this.clear() + this.cancel() + this.codeLenses = undefined + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/codelens/index.ts b/vim-config/plugins/coc.nvim/src/handler/codelens/index.ts new file mode 100644 index 00000000..0cd6f5c5 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/codelens/index.ts @@ -0,0 +1,88 @@ +import { NeovimClient as Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import events from '../../events' +import BufferSync from '../../model/bufferSync' +import { ConfigurationChangeEvent } from '../../types' +import { disposeAll } from '../../util' +import workspace from '../../workspace' +import CodeLensBuffer, { CodeLensConfig } from './buffer' +const logger = require('../../util/logger')('codelens') + +/** + * Show codeLens of document, works on neovim only. + */ +export default class CodeLensManager { + private config: CodeLensConfig + private disposables: Disposable[] = [] + public buffers: BufferSync + constructor(private nvim: Neovim) { + this.setConfiguration() + // need neovim to work + if (!workspace.isNvim) return + workspace.onDidChangeConfiguration(e => { + this.setConfiguration(e) + }) + this.buffers = workspace.registerBufferSync(doc => { + if (doc.buftype != '') return undefined + return new CodeLensBuffer(nvim, doc.bufnr, this.config) + }) + this.listen() + } + + private listen(): void { + events.on('CursorMoved', bufnr => { + let buf = this.buffers.getItem(bufnr) + if (buf) buf.resolveCodeLens() + }, null, this.disposables) + // Refresh on CursorHold + events.on('CursorHold', async bufnr => { + let buf = this.buffers.getItem(bufnr) + if (buf) await buf.forceFetch() + }, this, this.disposables) + } + + /** + * Check provider for buf that not fetched + */ + public async checkProvider(): Promise { + for (let buf of this.buffers.items) { + await buf.forceFetch() + } + } + + private setConfiguration(e?: ConfigurationChangeEvent): void { + if (e && !e.affectsConfiguration('codeLens')) return + let config = workspace.getConfiguration('codeLens') + let enable: boolean = this.nvim.hasFunction('nvim_buf_set_virtual_text') && config.get('enable', false) + if (e && enable != this.config.enabled) { + if (enable) { + this.listen() + } else { + disposeAll(this.disposables) + } + for (let buf of this.buffers.items) { + if (enable) { + buf.fetchCodelenses() + } else { + buf.cleanUp() + } + } + } + this.config = Object.assign(this.config || {}, { + enabled: enable, + separator: config.get('separator', '‣'), + subseparator: config.get('subseparator', ' ') + }) + } + + public async doAction(): Promise { + let [bufnr, line] = await this.nvim.eval(`[bufnr("%"),line(".")-1]`) as [number, number] + let buf = this.buffers.getItem(bufnr) + await buf?.doAction(line) + } + + public dispose(): void { + this.buffers.dispose() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/colors/colorBuffer.ts b/vim-config/plugins/coc.nvim/src/handler/colors/colorBuffer.ts new file mode 100644 index 00000000..b6880103 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/colors/colorBuffer.ts @@ -0,0 +1,157 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import debounce from 'debounce' +import { CancellationToken, CancellationTokenSource, Color, ColorInformation, Position, Range } from 'vscode-languageserver-protocol' +import languages from '../../languages' +import { SyncItem } from '../../model/bufferSync' +import { group } from '../../util/array' +import { equals } from '../../util/object' +import { positionInRange } from '../../util/position' +import { isDark, toHexColor, toHexString } from '../../util/color' +import workspace from '../../workspace' +const logger = require('../../util/logger')('colors-buffer') + +export interface ColorRanges { + color: Color + ranges: Range[] +} + +export default class ColorBuffer implements SyncItem { + private _colors: ColorInformation[] = [] + private tokenSource: CancellationTokenSource + private version: number + public highlight: Function & { clear(): void } + // last highlight version + constructor( + private nvim: Neovim, + private bufnr: number, + private enabled: boolean, + private usedColors: Set) { + this.highlight = debounce(() => { + void this.doHighlight() + }, global.hasOwnProperty('__TEST__') ? 10 : 500) + } + + public onChange(): void { + this.cancel() + this.highlight() + } + + public get buffer(): Buffer { + return this.nvim.createBuffer(this.bufnr) + } + + public get colors(): ColorInformation[] { + return this._colors + } + + public hasColor(): boolean { + return this._colors.length > 0 + } + + public setState(enabled: boolean): void { + this.enabled = enabled + if (enabled) { + this.highlight() + } else { + this.clearHighlight() + } + } + + public async doHighlight(): Promise { + let doc = workspace.getDocument(this.bufnr) + if (!doc || !this.enabled) return + try { + this.tokenSource = new CancellationTokenSource() + let { token } = this.tokenSource + if (this.version && doc.version == this.version) return + let { version } = doc + let colors: ColorInformation[] + colors = await languages.provideDocumentColors(doc.textDocument, token) + colors = colors || [] + if (token.isCancellationRequested) return + this.version = version + await this.addHighlight(colors) + } catch (e) { + logger.error('Error on highlight:', e) + } + } + + private async addHighlight(colors: ColorInformation[]): Promise { + colors = colors || [] + if (equals(this._colors, colors)) return + let { nvim } = this + this._colors = colors + // improve performance + let groups = group(colors, 100) + nvim.pauseNotification() + this.buffer.clearNamespace('color') + this.defineColors(colors) + void nvim.resumeNotification(false, true) + for (let colors of groups) { + nvim.pauseNotification() + let colorRanges = this.getColorRanges(colors) + for (let o of colorRanges) { + this.highlightColor(o.ranges, o.color) + } + void nvim.resumeNotification(false, true) + } + if (workspace.isVim) this.nvim.command('redraw', true) + } + + private highlightColor(ranges: Range[], color: Color): void { + let hlGroup = `BG${toHexString(color)}` + this.buffer.highlightRanges('color', hlGroup, ranges) + } + + private defineColors(colors: ColorInformation[]): void { + for (let color of colors) { + let hex = toHexString(color.color) + if (!this.usedColors.has(hex)) { + this.nvim.command(`hi BG${hex} guibg=#${hex} guifg=#${isDark(color.color) ? 'ffffff' : '000000'}`, true) + this.usedColors.add(hex) + } + } + } + + private getColorRanges(infos: ColorInformation[]): ColorRanges[] { + let res: ColorRanges[] = [] + for (let info of infos) { + let { color, range } = info + let idx = res.findIndex(o => 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 + } + + public clearHighlight(): void { + this.highlight.clear() + this._colors = [] + this.version = null + this.buffer.clearNamespace('color') + } + + public hasColorAtPosition(position: Position): boolean { + let { colors } = this + return colors.some(o => positionInRange(position, o.range) == 0) + } + + public cancel(): void { + if (this.tokenSource) { + this.tokenSource.cancel() + this.tokenSource = null + } + } + + public dispose(): void { + this.highlight.clear() + this.cancel() + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/colors/index.ts b/vim-config/plugins/coc.nvim/src/handler/colors/index.ts new file mode 100644 index 00000000..997e77db --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/colors/index.ts @@ -0,0 +1,147 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, ColorInformation, Disposable, Position } from 'vscode-languageserver-protocol' +import commandManager from '../../commands' +import extensions from '../../extensions' +import languages from '../../languages' +import BufferSync from '../../model/bufferSync' +import { HandlerDelegate } from '../../types' +import { disposeAll } from '../../util' +import { toHexString } from '../../util/color' +import window from '../../window' +import workspace from '../../workspace' +import ColorBuffer from './colorBuffer' +const logger = require('../../util/logger')('colors-index') + +export default class Colors { + private _enabled = true + private disposables: Disposable[] = [] + private highlighters: BufferSync + + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + let config = workspace.getConfiguration('coc.preferences') + this._enabled = config.get('colorSupport', true) + let usedColors: Set = new Set() + this.highlighters = workspace.registerBufferSync(doc => { + let buf = new ColorBuffer(this.nvim, doc.bufnr, this._enabled, usedColors) + buf.highlight() + return buf + }) + extensions.onDidActiveExtension(() => { + this.highlightAll() + }, null, this.disposables) + workspace.onDidChangeConfiguration(async e => { + if (e.affectsConfiguration('coc.preferences.colorSupport')) { + let config = workspace.getConfiguration('coc.preferences') + let enabled = config.get('colorSupport', true) + this._enabled = enabled + for (let buf of this.highlighters.items) { + buf.setState(enabled) + } + } + }, null, this.disposables) + this.disposables.push(commandManager.registerCommand('editor.action.pickColor', () => { + return this.pickColor() + })) + commandManager.titles.set('editor.action.pickColor', 'pick color from system color picker when possible.') + this.disposables.push(commandManager.registerCommand('editor.action.colorPresentation', () => { + return this.pickPresentation() + })) + commandManager.titles.set('editor.action.colorPresentation', 'change color presentation.') + } + + public async pickPresentation(): Promise { + let { doc } = await this.handler.getCurrentState() + this.handler.checkProvier('documentColor', doc.textDocument) + let info = await this.getColorInformation(doc.bufnr) + if (!info) return window.showMessage('Color not found at current position', 'warning') + let document = await workspace.document + let tokenSource = new CancellationTokenSource() + let presentations = await languages.provideColorPresentations(info, document.textDocument, tokenSource.token) + if (!presentations?.length) return + let res = await window.showMenuPicker(presentations.map(o => o.label), 'choose color:') + if (res == -1) return + let presentation = presentations[res] + let { textEdit, additionalTextEdits, label } = presentation + if (!textEdit) textEdit = { range: info.range, newText: label } + await document.applyEdits([textEdit]) + if (additionalTextEdits) { + await document.applyEdits(additionalTextEdits) + } + } + + public async pickColor(): Promise { + let { doc } = await this.handler.getCurrentState() + this.handler.checkProvier('documentColor', doc.textDocument) + let info = await this.getColorInformation(doc.bufnr) + if (!info) return window.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) return + let hex = toHexString({ + red: (res[0] / 65535), + green: (res[1] / 65535), + blue: (res[2] / 65535), + alpha: 1 + }) + let document = await workspace.document + await document.applyEdits([{ + range: info.range, + newText: `#${hex}` + }]) + } + + public get enabled(): boolean { + return this._enabled + } + + public clearHighlight(bufnr: number): void { + let highlighter = this.highlighters.getItem(bufnr) + if (!highlighter) return + highlighter.clearHighlight() + } + + public hasColor(bufnr: number): boolean { + let highlighter = this.highlighters.getItem(bufnr) + if (!highlighter) return false + return highlighter.hasColor() + } + + public hasColorAtPosition(bufnr: number, position: Position): boolean { + let highlighter = this.highlighters.getItem(bufnr) + if (!highlighter) return false + return highlighter.hasColorAtPosition(position) + } + + public highlightAll(): void { + for (let buf of this.highlighters.items) { + buf.highlight() + } + } + + public async doHighlight(bufnr: number): Promise { + let highlighter = this.highlighters.getItem(bufnr) + if (highlighter) await highlighter.doHighlight() + } + + public async getColorInformation(bufnr: number): Promise { + let highlighter = this.highlighters.getItem(bufnr) + if (!highlighter) return null + let position = await window.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 + } + + public dispose(): void { + this.highlighters.dispose() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/commands.ts b/vim-config/plugins/coc.nvim/src/handler/commands.ts new file mode 100644 index 00000000..467957a1 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/commands.ts @@ -0,0 +1,64 @@ +import { Neovim } from '@chemzqm/neovim' +import commandManager from '../commands' +import events from '../events' +import { Env } from '../types' +import listManager from '../list/manager' +const logger = require('../util/logger')('handler-commands') +const isVim = process.env.VIM_NODE_RPC == '1' + +interface CommandItem { + id: string + title: string +} + +export default class Commands { + constructor(private nvim: Neovim, private env: Readonly) { + for (let item of env.vimCommands) { + this.addVimCommand(item) + } + } + + public addVimCommand(cmd: { id: string; cmd: string; title?: string }): void { + let id = `vim.${cmd.id}` + commandManager.registerCommand(id, () => { + this.nvim.command(cmd.cmd, true) + if (isVim) this.nvim.command('redraw', true) + }) + if (cmd.title) commandManager.titles.set(id, cmd.title) + } + + public getCommandList(): string[] { + return commandManager.commandList.map(o => o.id) + } + + public async repeat(): Promise { + await commandManager.repeatCommand() + } + + public async runCommand(id?: string, ...args: any[]): Promise { + if (id) { + // needed to load onCommand extensions + await events.fire('Command', [id]) + let res = await commandManager.executeCommand(id, ...args) + if (args.length == 0) { + await commandManager.addRecent(id) + } + return res + } else { + await listManager.start(['commands']) + } + } + + public getCommands(): CommandItem[] { + let list = commandManager.commandList + let res: CommandItem[] = [] + let { titles } = commandManager + for (let item of list) { + res.push({ + id: item.id, + title: titles.get(item.id) || '' + }) + } + return res + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/fold.ts b/vim-config/plugins/coc.nvim/src/handler/fold.ts new file mode 100644 index 00000000..3b955a6c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/fold.ts @@ -0,0 +1,37 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Range, WorkspaceEdit } from 'vscode-languageserver-protocol' +import languages from '../languages' +import { HandlerDelegate } from '../types' +import workspace from '../workspace' + +export default class FoldHandler { + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + } + + public async fold(kind?: string | 'comment' | 'region'): Promise { + let { doc, winid } = await this.handler.getCurrentState() + this.handler.checkProvier('foldingRange', doc.textDocument) + await doc.synchronize() + let win = this.nvim.createWindow(winid) + let foldlevel = await this.nvim.eval('&foldlevel') as number + let ranges = await this.handler.withRequestToken('foldingrange', token => { + return languages.provideFoldingRanges(doc.textDocument, {}, token) + }, true) + if (!ranges || !ranges.length) return false + if (kind) ranges = ranges.filter(o => o.kind == kind) + ranges.sort((a, b) => b.startLine - a.startLine) + this.nvim.pauseNotification() + win.setOption('foldmethod', 'manual', true) + this.nvim.command('normal! zE', true) + for (let range of ranges) { + let { startLine, endLine } = range + let cmd = `${startLine + 1}, ${endLine + 1}fold` + this.nvim.command(cmd, true) + } + win.setOption('foldenable', true, true) + win.setOption('foldlevel', foldlevel, true) + if (workspace.isVim) this.nvim.command('redraw', true) + await this.nvim.resumeNotification() + return true + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/format.ts b/vim-config/plugins/coc.nvim/src/handler/format.ts new file mode 100644 index 00000000..bad33af2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/format.ts @@ -0,0 +1,228 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Position, Range, TextEdit } from 'vscode-languageserver-protocol' +import events from '../events' +import languages from '../languages' +import Document from '../model/document' +import snippetManager from '../snippets/manager' +import { ConfigurationChangeEvent, HandlerDelegate } from '../types' +import { getChangedFromEdits } from '../util/position' +import { isWord } from '../util/string' +import window from '../window' +import workspace from '../workspace' +const logger = require('../util/logger')('handler-format') + +const pairs: Map = new Map([ + ['<', '>'], + ['>', '<'], + ['{', '}'], + ['[', ']'], + ['(', ')'], +]) + +interface FormatPreferences { + formatOnType: boolean + formatOnTypeFiletypes: string[] + formatOnSaveFiletypes: string[] + bracketEnterImprove: boolean +} + +export default class FormatHandler { + private preferences: FormatPreferences + constructor( + private nvim: Neovim, + private handler: HandlerDelegate + ) { + this.loadPreferences() + handler.addDisposable(workspace.onDidChangeConfiguration(this.loadPreferences, this)) + handler.addDisposable(workspace.onWillSaveTextDocument(event => { + let { languageId } = event.document + let filetypes = this.preferences.formatOnSaveFiletypes + if (filetypes.includes(languageId) || filetypes.includes('*')) { + let willSaveWaitUntil = async (): Promise => { + if (!languages.hasFormatProvider(event.document)) { + logger.warn(`Format provider not found for ${event.document.uri}`) + return undefined + } + let options = await workspace.getFormatOptions(event.document.uri) + let tokenSource = new CancellationTokenSource() + let timer = setTimeout(() => { + logger.warn(`Format on save ${event.document.uri} timeout after 0.5s`) + tokenSource.cancel() + }, 500) + let textEdits = await languages.provideDocumentFormattingEdits(event.document, options, tokenSource.token) + clearTimeout(timer) + if (!textEdits && !tokenSource.token.isCancellationRequested) { + logger.want(`Format on save ${event.document.uri} get undefined result.`) + } + return textEdits + } + event.waitUntil(willSaveWaitUntil()) + } + })) + let enterTs: number + let enterBufnr: number + handler.addDisposable(events.on('Enter', async bufnr => { + enterTs = Date.now() + enterBufnr = bufnr + })) + handler.addDisposable(events.on('CursorMovedI', async bufnr => { + if (bufnr == enterBufnr && Date.now() - enterTs < 100) { + await this.handleEnter(bufnr) + } + })) + let changedTs: number + let lastInsert: number + handler.addDisposable(events.on('InsertCharPre', async () => { + lastInsert = Date.now() + })) + handler.addDisposable(events.on('TextChangedI', async (bufnr, info) => { + changedTs = Date.now() + if (!lastInsert || changedTs - lastInsert > 300) return + lastInsert = null + let pre = info.pre[info.pre.length - 1] + if (pre) await this.tryFormatOnType(pre, bufnr) + })) + let lastEnterBufnr: number + let lastEnterTs: number + handler.addDisposable(events.on('InsertEnter', bufnr => { + lastEnterBufnr = bufnr + lastEnterTs = Date.now() + })) + handler.addDisposable(events.on('TextChangedI', async (bufnr, info) => { + if (!this.preferences.formatOnType && !/^\s*$/.test(info.pre)) return + if (lastEnterBufnr != bufnr || !lastEnterTs || Date.now() - lastEnterTs > 30) return + lastEnterBufnr = undefined + await this.tryFormatOnType('\n', bufnr, true) + })) + } + + private loadPreferences(e?: ConfigurationChangeEvent): void { + if (!e || e.affectsConfiguration('coc.preferences')) { + let config = workspace.getConfiguration('coc.preferences') + this.preferences = { + formatOnType: config.get('formatOnType', false), + formatOnSaveFiletypes: config.get('formatOnSaveFiletypes', []), + formatOnTypeFiletypes: config.get('formatOnTypeFiletypes', []), + bracketEnterImprove: config.get('bracketEnterImprove', true), + } + } + } + + private async tryFormatOnType(ch: string, bufnr: number, newLine = false): Promise { + if (!ch || isWord(ch) || !this.preferences.formatOnType) return + if (snippetManager.getSession(bufnr) != null) return + let doc = workspace.getDocument(bufnr) + if (!doc || !doc.attached || doc.isCommandLine) return + const filetypes = this.preferences.formatOnTypeFiletypes + if (filetypes.length && !filetypes.includes(doc.filetype) && !filetypes.includes('*')) { + // Only check formatOnTypeFiletypes when set, avoid breaking change + return + } + if (!languages.hasProvider('formatOnType', doc.textDocument)) { + logger.warn(`Format on type provider not found for buffer: ${doc.uri}`) + return + } + if (!languages.canFormatOnType(ch, doc.textDocument)) return + let position: Position + let edits = await this.handler.withRequestToken('Format on type', async token => { + position = await window.getCursorPosition() + let origLine = doc.getline(position.line - 1) + // not format for empty line. + if (newLine && /^\s*$/.test(origLine)) return + let pos: Position = newLine ? { line: position.line - 1, character: origLine.length } : position + await doc.synchronize() + return await languages.provideDocumentOnTypeEdits(ch, doc.textDocument, pos, token) + }) + if (!edits || !edits.length) return + let changed = getChangedFromEdits(position, edits) + await doc.applyEdits(edits) + let to = changed ? Position.create(position.line + changed.line, position.character + changed.character) : null + if (to && !newLine) await window.moveTo(to) + } + + public async formatCurrentBuffer(): Promise { + let { doc } = await this.handler.getCurrentState() + return await this.documentFormat(doc) + } + + public async formatCurrentRange(mode: string): Promise { + let { doc } = await this.handler.getCurrentState() + return await this.documentRangeFormat(doc, mode) + } + + public async documentFormat(doc: Document): Promise { + await doc.synchronize() + if (!languages.hasFormatProvider(doc.textDocument)) { + throw new Error(`Format provider not found for buffer: ${doc.bufnr}`) + } + let options = await workspace.getFormatOptions(doc.uri) + let textEdits = await this.handler.withRequestToken('format', token => { + return languages.provideDocumentFormattingEdits(doc.textDocument, options, token) + }) + if (textEdits && textEdits.length > 0) { + await doc.applyEdits(textEdits) + return true + } + return false + } + + private async handleEnter(bufnr: number): Promise { + let { nvim } = this + let { bracketEnterImprove } = this.preferences + await this.tryFormatOnType('\n', bufnr) + if (bracketEnterImprove) { + let line = (await nvim.call('line', '.') as number) - 1 + let doc = workspace.getDocument(bufnr) + if (!doc) return + await doc.patchChange() + 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: TextEdit[] = [] + let opts = await workspace.getFormatOptions(doc.uri) + let space = opts.insertSpaces ? ' '.repeat(opts.tabSize) : '\t' + let currIndent = curr.match(/^\s*/)[0] + let pos: Position = Position.create(line - 1, pre.length) + // make sure indent of current line + if (doc.filetype == 'vim') { + let newText = '\n' + currIndent + space + edits.push({ range: Range.create(line, currIndent.length, line, currIndent.length), newText: ' \\ ' }) + newText = newText + '\\ ' + edits.push({ range: Range.create(pos, pos), newText }) + await doc.applyEdits(edits) + await window.moveTo(Position.create(line, newText.length - 1)) + } else { + await nvim.eval(`feedkeys("\\O", 'in')`) + } + } + } + } + } + + public async documentRangeFormat(doc: Document, mode?: string): Promise { + this.handler.checkProvier('formatRange', doc.textDocument) + await doc.synchronize() + let range: Range + if (mode) { + range = await workspace.getSelectedRange(mode, doc) + if (!range) return -1 + } else { + let [lnum, count, mode] = await this.nvim.eval("[v:lnum,v:count,mode()]") as [number, number, string] + // we can't handle + if (count == 0 || mode == 'i' || mode == 'R') return -1 + range = Range.create(lnum - 1, 0, lnum - 1 + count, 0) + } + let options = await workspace.getFormatOptions(doc.uri) + let textEdits = await this.handler.withRequestToken('Format range', token => { + return languages.provideDocumentRangeFormattingEdits(doc.textDocument, range, options, token) + }) + if (textEdits && textEdits.length > 0) { + await doc.applyEdits(textEdits) + return 0 + } + return -1 + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/highlights.ts b/vim-config/plugins/coc.nvim/src/handler/highlights.ts new file mode 100644 index 00000000..10b7c6c5 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/highlights.ts @@ -0,0 +1,106 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Disposable, DocumentHighlight, DocumentHighlightKind, Position, Range } from 'vscode-languageserver-protocol' +import events from '../events' +import languages from '../languages' +import Document from '../model/document' +import { HandlerDelegate } from '../types' +import { disposeAll } from '../util' +import workspace from '../workspace' +const logger = require('../util/logger')('documentHighlight') + +/** + * Highlight same symbols. + * Highlights are added to window by matchaddpos. + */ +export default class Highlights { + private disposables: Disposable[] = [] + private tokenSource: CancellationTokenSource + private highlights: Map = new Map() + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + events.on(['CursorMoved', 'CursorMovedI'], () => { + this.cancel() + this.clearHighlights() + }, null, this.disposables) + } + + public clearHighlights(): void { + if (this.highlights.size == 0) return + for (let winid of this.highlights.keys()) { + let win = this.nvim.createWindow(winid) + win.clearMatchGroup('^CocHighlight') + } + this.highlights.clear() + } + + public async highlight(): Promise { + let { nvim } = this + this.cancel() + let [bufnr, winid, pos, cursors] = await nvim.eval(`[bufnr("%"),win_getid(),coc#cursor#position(),get(b:,'coc_cursors_activated',0)]`) as [number, number, [number, number], number] + let doc = workspace.getDocument(bufnr) + if (!doc || !doc.attached || cursors) return + if (!languages.hasProvider('documentHighlight', doc.textDocument)) return + let highlights = await this.getHighlights(doc, Position.create(pos[0], pos[1])) + if (!highlights) return + let groups: { [index: string]: Range[] } = {} + for (let hl of highlights) { + if (!hl.range) continue + let hlGroup = hl.kind == DocumentHighlightKind.Text + ? 'CocHighlightText' + : hl.kind == DocumentHighlightKind.Read ? 'CocHighlightRead' : 'CocHighlightWrite' + groups[hlGroup] = groups[hlGroup] || [] + groups[hlGroup].push(hl.range) + } + let win = nvim.createWindow(winid) + nvim.pauseNotification() + win.clearMatchGroup('^CocHighlight') + for (let hlGroup of Object.keys(groups)) { + win.highlightRanges(hlGroup, groups[hlGroup], -1, true) + } + if (workspace.isVim) nvim.command('redraw', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + this.highlights.set(winid, highlights) + } + + public async getSymbolsRanges(): Promise { + let { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('documentHighlight', doc.textDocument) + let highlights = await this.getHighlights(doc, position) + if (!highlights) return null + return highlights.map(o => o.range) + } + + public hasHighlights(winid: number): boolean { + return this.highlights.get(winid) != null + } + + public async getHighlights(doc: Document, position: Position): Promise { + let line = doc.getline(position.line) + let ch = line[position.character] + if (!ch || !doc.isWord(ch)) return null + await doc.synchronize() + this.tokenSource = new CancellationTokenSource() + let source = this.tokenSource + let highlights = await languages.getDocumentHighLight(doc.textDocument, position, source.token) + if (source == this.tokenSource) { + source.dispose() + this.tokenSource = null + } + if (source.token.isCancellationRequested) return null + return highlights + } + + private cancel(): void { + if (this.tokenSource) { + this.tokenSource.cancel() + this.tokenSource.dispose() + this.tokenSource = null + } + } + + public dispose(): void { + this.highlights.clear() + this.cancel() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/hover.ts b/vim-config/plugins/coc.nvim/src/handler/hover.ts new file mode 100644 index 00000000..167cfc68 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/hover.ts @@ -0,0 +1,235 @@ +import { Neovim } from '@chemzqm/neovim' +import fs from 'fs' +import { CancellationTokenSource, Disposable, Hover, MarkedString, MarkupContent, Range } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import languages from '../languages' +import { Documentation } from '../markdown' +import FloatFactory, { FloatWinConfig } from '../model/floatFactory' +import { TextDocumentContentProvider } from '../provider' +import { ConfigurationChangeEvent, FloatConfig, HandlerDelegate } from '../types' +import { disposeAll, isMarkdown } from '../util' +import { readFileLines } from '../util/fs' +import workspace from '../workspace' +const logger = require('../util/logger')('handler-hover') + +export type HoverTarget = 'float' | 'preview' | 'echo' + +interface HoverConfig { + target: HoverTarget + floatConfig: FloatConfig + previewMaxHeight: number + autoHide: boolean +} + +export default class HoverHandler { + private hoverFactory: FloatFactory + private disposables: Disposable[] = [] + private documentLines: string[] = [] + private config: HoverConfig + private timer: NodeJS.Timeout + private hasProvider = false + private excludeImages = true + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + this.loadConfiguration() + workspace.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables) + this.hoverFactory = new FloatFactory(nvim) + this.disposables.push(this.hoverFactory) + } + + private registerProvider(): void { + if (this.hasProvider) return + this.hasProvider = true + let { nvim } = this + let provider: TextDocumentContentProvider = { + 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(`if winnr('j') != winnr('k') | exe "normal! z${Math.min(this.documentLines.length, this.config.previewMaxHeight)}\\ | endif"`, true) + await nvim.resumeNotification() + return this.documentLines.join('\n') + } + } + this.disposables.push(workspace.registerTextDocumentContentProvider('coc', provider)) + } + + private loadConfiguration(e?: ConfigurationChangeEvent): void { + if (!e || e.affectsConfiguration('hover')) { + let config = workspace.getConfiguration('hover') + let target = config.get('target', 'float') + this.config = { + floatConfig: config.get('floatConfig', {}), + autoHide: config.get('autoHide', true), + target: target == 'float' && !workspace.floatSupported ? 'preview' : target, + previewMaxHeight: config.get('previewMaxHeight', 12) + } + if (this.config.target == 'preview') { + this.registerProvider() + } + let preferences = workspace.getConfiguration('coc.preferences') + this.excludeImages = preferences.get('excludeImageLinksInMarkdownDocument', true) + } + } + + public async onHover(hoverTarget?: HoverTarget): Promise { + let { doc, position, winid } = await this.handler.getCurrentState() + if (hoverTarget == 'preview') this.registerProvider() + this.handler.checkProvier('hover', doc.textDocument) + await doc.synchronize() + let hovers = await this.handler.withRequestToken('hover', token => { + return languages.getHover(doc.textDocument, position, token) + }, true) + if (hovers == null || !hovers.length) return false + let hover = hovers.find(o => Range.is(o.range)) + if (hover?.range) { + let win = this.nvim.createWindow(winid) + win.highlightRanges('CocHoverRange', [hover.range], 99, true) + this.timer = setTimeout(() => { + win.clearMatchGroup('CocHoverRange') + if (workspace.isVim) this.nvim.command('redraw', true) + }, 500) + } + await this.previewHover(hovers, hoverTarget) + return true + } + + public async definitionHover(hoverTarget: HoverTarget): Promise { + const { doc, position } = await this.handler.getCurrentState() + if (hoverTarget == 'preview') this.registerProvider() + this.handler.checkProvier('hover', doc.textDocument) + await doc.synchronize() + const hovers: (Hover | Documentation)[] = await this.handler.withRequestToken('hover', token => { + return languages.getHover(doc.textDocument, position, token) + }, true) + if (!hovers?.length) return false + const defs = await this.handler.withRequestToken('definitionHover', token => { + return languages.getDefinitionLinks(doc.textDocument, position, token) + }, false) + if (defs?.length) { + for (const def of defs) { + if (!def.targetRange) continue + const { start, end } = def.targetRange + const endLine = end.line - start.line >= 100 ? start.line + 100 : (end.character == 0 ? end.line - 1 : end.line) + let lines = await readLines(def.targetUri, start.line, endLine) + if (lines.length) { + let indent = lines[0].match(/^\s*/)[0] + if (indent) lines = lines.map(l => l.startsWith(indent) ? l.substring(indent.length) : l) + hovers.push({ content: lines.join('\n'), filetype: doc.filetype }) + } + } + } + await this.previewHover(hovers, hoverTarget) + return true + } + + private async previewHover(hovers: (Hover | Documentation)[], target?: string): Promise { + let docs: Documentation[] = [] + target = target || this.config.target + let isPreview = target === 'preview' + for (let hover of hovers) { + if (isDocumentation(hover)) { + docs.push(hover) + continue + } + let { contents } = hover + if (Array.isArray(contents)) { + for (let item of contents) { + if (typeof item === 'string') { + addDocument(docs, item, 'markdown', isPreview) + } else { + addDocument(docs, item.value, item.language, isPreview) + } + } + } else if (MarkedString.is(contents)) { + if (typeof contents == 'string') { + addDocument(docs, contents, 'markdown', isPreview) + } else { + addDocument(docs, contents.value, contents.language, isPreview) + } + } else if (MarkupContent.is(contents)) { + addDocument(docs, contents.value, isMarkdown(contents) ? 'markdown' : 'txt', isPreview) + } + } + if (target == 'float') { + let config = this.hoverFactory.applyFloatConfig({ + modes: ['n'], + autoHide: this.config.autoHide, + excludeImages: this.excludeImages, + maxWidth: 80, + }, this.config.floatConfig) + await this.hoverFactory.show(docs, config) + return + } + let lines = docs.reduce((p, c) => { + let arr = c.content.split(/\r?\n/) + if (p.length > 0) p.push('') + p.push(...arr) + return p + }, []) + if (target == 'echo') { + const msg = lines.join('\n').trim() + await this.nvim.call('coc#util#echo_hover', [msg]) + } else { + this.documentLines = lines + await this.nvim.command(`noswapfile pedit coc://document`) + } + } + + /** + * Get hover text array + */ + public async getHover(): Promise { + let result: string[] = [] + let { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('hover', doc.textDocument) + await doc.synchronize() + let tokenSource = new CancellationTokenSource() + let hovers = await languages.getHover(doc.textDocument, position, tokenSource.token) + if (Array.isArray(hovers)) { + for (let h of hovers) { + let { contents } = h + if (Array.isArray(contents)) { + contents.forEach(c => { + result.push(typeof c === 'string' ? c : c.value) + }) + } else if (MarkupContent.is(contents)) { + result.push(contents.value) + } else { + result.push(typeof contents === 'string' ? contents : contents.value) + } + } + } + result = result.filter(s => s != null && s.length > 0) + return result + } + + public dispose(): void { + if (this.timer) clearTimeout(this.timer) + disposeAll(this.disposables) + } +} + +function addDocument(docs: Documentation[], text: string, filetype: string, isPreview = false): void { + let content = text.trim() + if (!content.length) + return + if (isPreview && filetype !== 'markdown') { + content = '``` ' + filetype + '\n' + content + '\n```' + } + docs.push({ content, filetype }) +} + +function isDocumentation(obj: any): obj is Documentation { + if (!obj) return false + return typeof obj.filetype === 'string' && typeof obj.content === 'string' +} + +async function readLines(uri: string, start: number, end: number): Promise { + let doc = workspace.getDocument(uri) + if (doc) return doc.getLines(start, end + 1) + let fsPath = URI.parse(uri).fsPath + if (!fs.existsSync(fsPath)) return [] + return await readFileLines(fsPath, start, end) +} diff --git a/vim-config/plugins/coc.nvim/src/handler/index.ts b/vim-config/plugins/coc.nvim/src/handler/index.ts new file mode 100644 index 00000000..59265892 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/index.ts @@ -0,0 +1,207 @@ +import { NeovimClient as Neovim } from '@chemzqm/neovim' +import { CancellationToken, CancellationTokenSource, CodeAction, CodeActionKind, Disposable, Position, Range, SymbolKind } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import events from '../events' +import languages from '../languages' +import Document from '../model/document' +import { StatusBarItem } from '../model/status' +import { ProviderName } from '../types' +import { disposeAll } from '../util' +import window from '../window' +import workspace from '../workspace' +import CodeActions from './codeActions' +import CodeLens from './codelens/index' +import Colors from './colors/index' +import Commands from './commands' +import Fold from './fold' +import Format from './format' +import Highlights from './highlights' +import HoverHandler from './hover' +import Links from './links' +import Locations from './locations' +import Refactor from './refactor/index' +import Rename from './rename' +import SelectionRange from './selectionRange' +import CallHierarchy from './callHierarchy' +import SemanticTokensHighlights from './semanticTokensHighlights/index' +import Signature from './signature' +import Symbols from './symbols/index' +import { HandlerDelegate } from '../types' +import { getSymbolKind } from '../util/convert' +const logger = require('../util/logger')('Handler') + +export interface CurrentState { + doc: Document + winid: number + position: Position + // :h mode() + mode: string +} + +export default class Handler implements HandlerDelegate { + public readonly documentHighlighter: Highlights + public readonly colors: Colors + public readonly signature: Signature + public readonly locations: Locations + public readonly symbols: Symbols + public readonly refactor: Refactor + public readonly codeActions: CodeActions + public readonly format: Format + public readonly hover: HoverHandler + public readonly codeLens: CodeLens + public readonly commands: Commands + public readonly links: Links + public readonly rename: Rename + public readonly fold: Fold + public readonly selectionRange: SelectionRange + public readonly callHierarchy: CallHierarchy + public readonly semanticHighlighter: SemanticTokensHighlights + private labels: { [key: string]: string } + private requestStatusItem: StatusBarItem + private requestTokenSource: CancellationTokenSource | undefined + private requestTimer: NodeJS.Timer + private disposables: Disposable[] = [] + + constructor(private nvim: Neovim) { + this.requestStatusItem = window.createStatusBarItem(0, { progress: true }) + events.on(['CursorMoved', 'CursorMovedI', 'InsertEnter', 'InsertSnippet', 'InsertLeave'], () => { + if (this.requestTokenSource) { + this.requestTokenSource.cancel() + this.requestTokenSource = null + } + }, null, this.disposables) + this.labels = workspace.getConfiguration('suggest').get('completionItemKindLabels', {}) + this.fold = new Fold(nvim, this) + this.links = new Links(nvim, this) + this.codeLens = new CodeLens(nvim) + this.colors = new Colors(nvim, this) + this.format = new Format(nvim, this) + this.symbols = new Symbols(nvim, this) + this.refactor = new Refactor(nvim, this) + this.hover = new HoverHandler(nvim, this) + this.locations = new Locations(nvim, this) + this.signature = new Signature(nvim, this) + this.rename = new Rename(nvim, this) + this.codeActions = new CodeActions(nvim, this) + this.commands = new Commands(nvim, workspace.env) + this.callHierarchy = new CallHierarchy(nvim, this) + this.documentHighlighter = new Highlights(nvim, this) + this.semanticHighlighter = new SemanticTokensHighlights(nvim, this) + this.selectionRange = new SelectionRange(nvim, this) + this.disposables.push({ + dispose: () => { + this.callHierarchy.dispose() + this.codeLens.dispose() + this.refactor.dispose() + this.signature.dispose() + this.symbols.dispose() + this.hover.dispose() + this.locations.dispose() + this.colors.dispose() + this.documentHighlighter.dispose() + this.semanticHighlighter.dispose() + } + }) + } + + public async getCurrentState(): Promise { + let { nvim } = this + let [bufnr, [line, character], winid, mode] = await nvim.eval("[bufnr('%'),coc#cursor#position(),win_getid(),mode()]") as [number, [number, number], number, string] + let doc = workspace.getDocument(bufnr) + if (!doc || !doc.attached) throw new Error(`current buffer ${bufnr} not attached`) + return { + doc, + mode, + position: Position.create(line, character), + winid + } + } + + public addDisposable(disposable: Disposable): void { + this.disposables.push(disposable) + } + + /** + * Throw error when provider not exists. + */ + public checkProvier(id: ProviderName, document: TextDocument): void { + if (!languages.hasProvider(id, document)) { + throw new Error(`${id} provider not found for current buffer, your language server doesn't support it.`) + } + } + + public async withRequestToken(name: string, fn: (token: CancellationToken) => Thenable, checkEmpty?: boolean): Promise { + if (this.requestTokenSource) { + this.requestTokenSource.cancel() + this.requestTokenSource.dispose() + } + if (this.requestTimer) { + clearTimeout(this.requestTimer) + } + let statusItem = this.requestStatusItem + this.requestTokenSource = new CancellationTokenSource() + let { token } = this.requestTokenSource + token.onCancellationRequested(() => { + statusItem.text = `${name} request canceled` + statusItem.isProgress = false + this.requestTimer = setTimeout(() => { + statusItem.hide() + }, 500) + }) + statusItem.isProgress = true + statusItem.text = `requesting ${name}` + statusItem.show() + let res: T + try { + res = await Promise.resolve(fn(token)) + } catch (e) { + window.showMessage(e.message, 'error') + logger.error(`Error on ${name}`, e) + } + if (this.requestTokenSource) { + this.requestTokenSource.dispose() + this.requestTokenSource = undefined + } + if (token.isCancellationRequested) return null + statusItem.hide() + if (checkEmpty && (!res || (Array.isArray(res) && res.length == 0))) { + window.showMessage(`${name} not found`, 'warning') + return null + } + return res + } + + public getIcon(kind: SymbolKind): { text: string, hlGroup: string } { + let { labels } = this + let kindText = getSymbolKind(kind) + let defaultIcon = typeof labels['default'] === 'string' ? labels['default'] : kindText[0].toLowerCase() + let text = kindText == 'Unknown' ? '' : labels[kindText[0].toLowerCase() + kindText.slice(1)] + if (!text || typeof text !== 'string') text = defaultIcon + return { + text, + hlGroup: kindText == 'Unknown' ? 'CocSymbolDefault' : `CocSymbol${kindText}` + } + } + + public async getCodeActions(doc: Document, range?: Range, only?: CodeActionKind[]): Promise { + return await this.codeActions.getCodeActions(doc, range, only) + } + + public async applyCodeAction(action: CodeAction): Promise { + await this.codeActions.applyCodeAction(action) + } + + public async hasProvider(id: string): Promise { + let bufnr = await this.nvim.call('bufnr', '%') + let doc = workspace.getDocument(bufnr) + if (!doc) return false + return languages.hasProvider(id as ProviderName, doc.textDocument) + } + + public dispose(): void { + if (this.requestTimer) { + clearTimeout(this.requestTimer) + } + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/links.ts b/vim-config/plugins/coc.nvim/src/handler/links.ts new file mode 100644 index 00000000..7f02b94d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/links.ts @@ -0,0 +1,42 @@ +import { Neovim } from '@chemzqm/neovim' +import { DocumentLink, Position } from 'vscode-languageserver-protocol' +import languages from '../languages' +import { HandlerDelegate } from '../types' +import { positionInRange } from '../util/position' +import workspace from '../workspace' + +export default class Links { + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + } + + public async getLinks(): Promise { + let { doc } = await this.handler.getCurrentState() + this.handler.checkProvier('documentLink', doc.textDocument) + let links = await this.handler.withRequestToken('links', token => { + return languages.getDocumentLinks(doc.textDocument, token) + }) + return links || [] + } + + public async openLink(link: DocumentLink): Promise { + if (!link.target) { + link = await languages.resolveDocumentLink(link) + if (!link.target) throw new Error(`Failed to resolve link target`) + } + await workspace.openResource(link.target) + } + + public async openCurrentLink(): Promise { + let [line, character] = await this.nvim.call('coc#cursor#position') as [number, number] + let links = await this.getLinks() + if (!links || links.length == 0) return false + let position = Position.create(line, character) + for (let link of links) { + if (positionInRange(position, link.range) == 0) { + await this.openLink(link) + return true + } + } + return false + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/locations.ts b/vim-config/plugins/coc.nvim/src/handler/locations.ts new file mode 100644 index 00000000..29208b34 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/locations.ts @@ -0,0 +1,175 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationToken, CancellationTokenSource, Definition, Location, LocationLink, Position, TextDocument } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import languages from '../languages' +import services from '../services' +import { HandlerDelegate, ProviderName } from '../types' +import workspace from '../workspace' +const logger = require('../util/logger')('handler-hover') + +export interface TagDefinition { + name: string + cmd: string + filename: string +} + +export type RequestFunc = (doc: TextDocument, position: Position, token: CancellationToken) => Thenable + +export default class LocationsHandler { + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + } + + private async request(method: ProviderName, fn: RequestFunc): Promise { + let { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier(method, doc.textDocument) + await doc.synchronize() + return await this.handler.withRequestToken(method, token => { + return fn(doc.textDocument, position, token) + }, true) + } + + public async definitions(): Promise { + const { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('definition', doc.textDocument) + await doc.synchronize() + const tokenSource = new CancellationTokenSource() + return languages.getDefinition(doc.textDocument, position, tokenSource.token) + } + + public async declarations(): Promise { + const { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('declaration', doc.textDocument) + await doc.synchronize() + const tokenSource = new CancellationTokenSource() + return languages.getDeclaration(doc.textDocument, position, tokenSource.token) + } + + public async typeDefinitions(): Promise { + const { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('typeDefinition', doc.textDocument) + await doc.synchronize() + const tokenSource = new CancellationTokenSource() + return languages.getTypeDefinition(doc.textDocument, position, tokenSource.token) + } + + public async implementations(): Promise { + const { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('implementation', doc.textDocument) + await doc.synchronize() + const tokenSource = new CancellationTokenSource() + return languages.getImplementation(doc.textDocument, position, tokenSource.token) + } + + public async references(): Promise { + const { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('reference', doc.textDocument) + await doc.synchronize() + const tokenSource = new CancellationTokenSource() + return languages.getReferences(doc.textDocument, { includeDeclaration: true }, position, tokenSource.token) + } + + public async gotoDefinition(openCommand?: string): Promise { + let definition = await this.request('definition', (doc, position, token) => { + return languages.getDefinition(doc, position, token) + }) + await this.handleLocations(definition, openCommand) + return definition ? definition.length > 0 : false + } + + public async gotoDeclaration(openCommand?: string): Promise { + let definition = await this.request('declaration', (doc, position, token) => { + return languages.getDeclaration(doc, position, token) + }) + await this.handleLocations(definition, openCommand) + return definition ? (Array.isArray(definition) ? definition.length > 0 : true) : false + } + + public async gotoTypeDefinition(openCommand?: string): Promise { + let definition = await this.request('typeDefinition', (doc, position, token) => { + return languages.getTypeDefinition(doc, position, token) + }) + await this.handleLocations(definition, openCommand) + return definition ? definition.length > 0 : false + } + + public async gotoImplementation(openCommand?: string): Promise { + let definition = await this.request('implementation', (doc, position, token) => { + return languages.getImplementation(doc, position, token) + }) + await this.handleLocations(definition, openCommand) + return definition ? definition.length > 0 : false + } + + public async gotoReferences(openCommand?: string, includeDeclaration = true): Promise { + let definition = await this.request('reference', (doc, position, token) => { + return languages.getReferences(doc, { includeDeclaration }, position, token) + }) + await this.handleLocations(definition, openCommand) + return definition ? definition.length > 0 : false + } + + public async getTagList(): Promise { + let { doc, position } = await this.handler.getCurrentState() + let word = await this.nvim.call('expand', '') + if (!word) return null + if (!languages.hasProvider('definition', doc.textDocument)) return null + let tokenSource = new CancellationTokenSource() + let definitions = await languages.getDefinition(doc.textDocument, position, tokenSource.token) + if (!definitions || !definitions.length) return null + return definitions.map(location => { + let parsedURI = URI.parse(location.uri) + const filename = parsedURI.scheme == 'file' ? parsedURI.fsPath : parsedURI.toString() + return { + name: word, + cmd: `keepjumps ${location.range.start.line + 1} | normal ${location.range.start.character + 1}|`, + filename, + } + }) + } + + /** + * Send custom request for locations to services. + */ + public async findLocations(id: string, method: string, params: any, openCommand?: string | false): Promise { + let { doc, position } = await this.handler.getCurrentState() + params = params || {} + Object.assign(params, { + textDocument: { uri: doc.uri }, + position + }) + let res: any = await services.sendRequest(id, method, params) + res = res || [] + let locations: Location[] = [] + if (Array.isArray(res)) { + locations = res as Location[] + } else if (res.hasOwnProperty('location') && res.hasOwnProperty('children')) { + let getLocation = (item: any): void => { + locations.push(item.location as Location) + if (item.children && item.children.length) { + for (let loc of item.children) { + getLocation(loc) + } + } + } + getLocation(res) + } + await this.handleLocations(locations, openCommand) + } + + public async handleLocations(definition: Definition | LocationLink[], openCommand?: string | false): Promise { + if (!definition) return + let locations: Location[] = Array.isArray(definition) ? definition as Location[] : [definition] + locations = locations.map(o => LocationLink.is(o) ? Location.create(o.targetUri, o.targetRange) : o) + let len = locations.length + if (len == 0) return + if (len == 1 && openCommand !== false) { + let { uri, range } = locations[0] + await workspace.jumpTo(uri, range.start, openCommand) + } else { + await workspace.showLocations(locations) + } + } + + public dispose(): void { + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/refactor/buffer.ts b/vim-config/plugins/coc.nvim/src/handler/refactor/buffer.ts new file mode 100644 index 00000000..64ba241b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/refactor/buffer.ts @@ -0,0 +1,545 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import fastDiff from 'fast-diff' +import path from 'path' +import { Disposable, Range, TextEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import commands from '../../commands' +import Document from '../../model/document' +import Highlighter from '../../model/highligher' +import { BufferSyncItem, DidChangeTextDocumentParams } from '../../types' +import { disposeAll } from '../../util' +import { isParentFolder, readFileLines } from '../../util/fs' +import { Mutex } from '../../util/mutex' +import { equals } from '../../util/object' +import { byteLength } from '../../util/string' +import window from '../../window' +import workspace from '../../workspace' +const logger = require('../../util/logger')('handler-refactorBuffer') + +export const SEPARATOR = '\u3000' + +export interface LineChange { + // zero indexed + lnum: number + delta: number +} + +export interface FileChange { + // line number of filepath + lnum: number + // start line 0 indexed + start?: number + // end line 0 indexed, excluded + end?: number + filepath: string + lines: string[] +} + +export interface FileRange { + // start lnum in refactor buffer, 1 indexed + lnum?: number + // start line 0 indexed + start: number + // end line 0 indexed, excluded + end: number + // range relatived to new range + highlights?: Range[] + lines?: string[] +} + +export interface FileItem { + filepath: string + ranges: FileRange[] +} + +export interface RefactorConfig { + openCommand: string + beforeContext: number + afterContext: number + saveToFile: boolean +} + +export interface RefactorBufferOpts { + cwd: string + winid: number + fromWinid: number +} + +export default class RefactorBuffer implements BufferSyncItem { + private mutex = new Mutex() + private _disposed = false + private disposables: Disposable[] = [] + private _fileItems: FileItem[] = [] + private matchIds: Set = new Set() + private changing = false + constructor( + private bufnr: number, + private srcId: number, + private nvim: Neovim, + public readonly config: RefactorConfig, + private opts: RefactorBufferOpts + ) { + this.disposables.push(workspace.registerLocalKeymap('n', '', this.splitOpen.bind(this), true)) + workspace.onDidChangeTextDocument(this.onDocumentChange, this, this.disposables) + } + + public get fileItems(): FileItem[] { + return this._fileItems + } + + public onChange(e: DidChangeTextDocumentParams): void { + if (this.changing) return + let doc = this.document + let { nvim, _fileItems: fileItems } = this + if (!fileItems.length) return + let change = e.contentChanges[0] + if (!('range' in change)) return + 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: LineChange[] = [] + if (text.includes('\u3000')) { + let startLine = range.start.line + let diffs = fastDiff(original, text) + let offset = 0 + let orig = 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] == fastDiff.EQUAL) { + offset = offset + diff[1].length + } else if (diff[0] == fastDiff.DELETE) { + let end = orig.positionAt(offset + diff[1].length) + if (diffs[i + 1] && diffs[i + 1][0] == fastDiff.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] == fastDiff.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) return + nvim.pauseNotification() + this.highlightLineNr() + nvim.resumeNotification().then(res => { + if (Array.isArray(res) && res[1] != null) { + logger.error(`Error on highlightLineNr:`, res[1]) + } + }).logError() + } + + /** + * Handle changes of other buffers. + */ + private async onDocumentChange(e: DidChangeTextDocumentParams): Promise { + if (e.bufnr == this.bufnr || this.changing) return + let { uri } = e.textDocument + let { range, text } = e.contentChanges[0] + let filepath = URI.parse(uri).fsPath + let fileItem = this._fileItems.find(o => o.filepath == filepath) + // not affected + if (!fileItem) return + let lineChange = text.split('\n').length - (range.end.line - range.start.line) - 1 + let edits: TextEdit[] = [] + // 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.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' + }) + } + } + } + // clean fileItem with empty ranges + this._fileItems = this._fileItems.filter(o => o.ranges && o.ranges.length > 0) + if (edits.length) { + this.changing = true + await this.document.applyEdits(edits) + this.changing = false + } + this.nvim.pauseNotification() + this.highlightLineNr() + this.buffer.setOption('modified', false, true) + await this.nvim.resumeNotification() + } + + /** + * Current changed file ranges + */ + public async getFileChanges(): Promise { + if (this._disposed) return [] + let changes: FileChange[] = [] + let lines = await this.buffer.lines + lines.push(SEPARATOR) + // current lines + let arr: string[] = [] + let fsPath: string + let lnum: number + for (let i = 0; i < lines.length; i++) { + let line = lines[i] + if (line.startsWith(SEPARATOR)) { + if (fsPath) { + changes.push({ + filepath: fsPath, + lines: arr.slice(), + lnum + }) + fsPath = undefined + arr = [] + } + if (line.length > 1) { + let ms = line.match(/^\u3000(.*)/) + if (ms) { + fsPath = this.getAbsolutePath(ms[1].replace(/\s+$/, '')) + lnum = i + 1 + arr = [] + } + } + } else { + arr.push(line) + } + } + return changes + } + + /** + * Open line under cursor in split window + */ + public async splitOpen(): Promise { + let { nvim } = this + let win = nvim.createWindow(this.opts.fromWinid) + let valid = await win.valid + let lines = await nvim.eval('getline(1,line("."))') as string[] + 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 - 1 + let bufname = this.getAbsolutePath(filepath) + nvim.pauseNotification() + if (valid) { + nvim.call('win_gotoid', [this.opts.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) window.showMessage(`Error on open ${filepath}: ${err}`, 'error') + if (!valid) { + this.opts.fromWinid = await nvim.call('win_getid') + } + break + } + } + } + + /** + * Add FileItem to refactor buffer. + */ + public async addFileItems(items: FileItem[]): Promise { + if (this._disposed) return + let { cwd } = this.opts + let { document } = this + const release = await this.mutex.acquire() + try { + await document.synchronize() + 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 Highlighter() + let hlRanges: Range[] = [] + for (let item of items) { + for (let range of item.ranges) { + highligher.addLine(SEPARATOR) + highligher.addLine(SEPARATOR) + range.lnum = count + highligher.length + highligher.addText(`${isParentFolder(cwd, item.filepath) ? path.relative(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.changing = true + 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#cursor#move_to', [pos.line, pos.character], true) + } + if (workspace.isVim) { + nvim.command('redraw', true) + } + let [, err] = await nvim.resumeNotification() + if (err) throw new Error(err[2]) + await document.patchChange() + this.changing = false + await commands.executeCommand('editor.action.addRanges', hlRanges) + } catch (e) { + this.changing = false + logger.error(`Error on add file item:`, e) + } + release() + } + + /** + * Save changes to buffers/files, return false when no change made. + */ + public async save(): Promise { + let { nvim } = this + let doc = this.document + let { buffer } = doc + await doc.patchChange() + let changes = await this.getFileChanges() + if (!changes) return + changes.sort((a, b) => a.lnum - b.lnum) + // filter changes that not change + let removeList: number[] = [] + let deltaMap: Map = 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 || equals(range.lines, change.lines)) { + removeList.push(i) + if (curr && range) { + 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) { + window.showMessage('No change.', 'more') + await buffer.setOption('modified', false) + return false + } + let changeMap: { [uri: string]: TextEdit[] } = {} + for (let change of changes) { + let uri = URI.file(change.filepath).toString() + let edits = changeMap[uri] || [] + edits.push({ + range: Range.create(change.start, 0, change.end, 0), + newText: change.lines.join('\n') + '\n' + }) + changeMap[uri] = edits + } + this.changing = true + await workspace.applyEdit({ changes: changeMap }) + this.changing = false + nvim.pauseNotification() + buffer.setOption('modified', false, true) + if (this.config.saveToFile) { + nvim.command('silent noa wa', true) + } + this.highlightLineNr() + await nvim.resumeNotification() + return true + } + + public getFileRange(lnum: number): FileRange { + for (let item of this._fileItems) { + for (let r of item.ranges) { + if (r.lnum == lnum) { + return r + } + } + } + } + + private getLinesRange(lnum: number): [number, number] | null { + for (let item of this._fileItems) { + for (let range of item.ranges) { + if (range.lnum == lnum) { + return [range.start, range.end] + } + } + } + } + + private async getLines(fsPath: string, start: number, end: number): Promise { + let uri = URI.file(fsPath).toString() + let doc = workspace.getDocument(uri) + if (doc) return doc.getLines(start, end) + return await readFileLines(fsPath, start, end - 1) + } + + private getAbsolutePath(filepath: string): string { + if (path.isAbsolute(filepath)) return filepath + return path.join(this.opts.cwd, filepath) + } + + /** + * Edit range of FileRange + */ + private getFileRangeRange(range: FileRange, lineOnly = true): Range { + 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 Range.create(start, 0, end, 0) + } + + /** + * Use conceal to add lineNr + */ + private highlightLineNr(): void { + let { _fileItems: fileItems, nvim, srcId, bufnr } = this + let { winid, cwd } = this.opts + 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#highlight#clear_matches', [winid, Array.from(this.matchIds)], true) + this.matchIds.clear() + } + let id = 2000 + for (let item of fileItems) { + let filename = `${cwd ? path.relative(cwd, item.filepath) : item.filepath}` + let col = 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) + } + + public get valid(): Promise { + return this.buffer.valid + } + + public get buffer(): Buffer { + return this.nvim.createBuffer(this.bufnr) + } + + public get document(): Document | null { + if (this._disposed) return null + return workspace.getDocument(this.bufnr) + } + + public dispose(): void { + this._disposed = true + disposeAll(this.disposables) + } +} + +function adjustRange(range: Range, offset: number): Range { + let { start, end } = range + return Range.create(start.line - offset, start.character, end.line - offset, end.character) +} + diff --git a/vim-config/plugins/coc.nvim/src/handler/refactor/index.ts b/vim-config/plugins/coc.nvim/src/handler/refactor/index.ts new file mode 100644 index 00000000..d96e0503 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/refactor/index.ts @@ -0,0 +1,247 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable, Emitter, Event, Location, Range, TextDocumentEdit, TextEdit, WorkspaceEdit } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import languages from '../../languages' +import { ConfigurationChangeEvent, HandlerDelegate } from '../../types' +import { disposeAll } from '../../util' +import { getFileLineCount } from '../../util/fs' +import window from '../../window' +import workspace from '../../workspace' +import Search from '../search' +import RefactorBuffer, { FileItem, FileRange, RefactorConfig, SEPARATOR } from './buffer' +const logger = require('../../util/logger')('handler-refactor') + +const name = '__coc_refactor__' +let refactorId = 0 + +export { FileItem } + +export default class Refactor { + private srcId: number + private timer: NodeJS.Timer + private buffers: Map = new Map() + public config: RefactorConfig + private disposables: Disposable[] = [] + private readonly _onCreate = new Emitter() + public readonly onCreate: Event = this._onCreate.event + constructor( + private nvim: Neovim, + private handler: HandlerDelegate + ) { + if (workspace.isNvim && this.nvim.hasFunction('nvim_buf_set_virtual_text')) { + this.srcId = workspace.createNameSpace('coc-refactor') + } + this.setConfiguration() + workspace.onDidChangeConfiguration(this.setConfiguration, this, this.disposables) + workspace.onDidCloseTextDocument(e => { + let buf = this.buffers.get(e.bufnr) + if (buf) { + buf.dispose() + this.buffers.delete(e.bufnr) + } + }, null, this.disposables) + workspace.onDidChangeTextDocument(e => { + let buf = this.buffers.get(e.bufnr) + if (buf) buf.onChange(e) + }, null, this.disposables) + } + + private setConfiguration(e?: ConfigurationChangeEvent): void { + if (e && !e.affectsConfiguration('refactor')) return + let config = workspace.getConfiguration('refactor') + this.config = Object.assign(this.config || {}, { + afterContext: config.get('afterContext', 3), + beforeContext: config.get('beforeContext', 3), + openCommand: config.get('openCommand', 'edit'), + saveToFile: config.get('saveToFile', true) + }) + } + + /** + * Refactor of current symbol + */ + public async doRefactor(): Promise { + let { doc, position } = await this.handler.getCurrentState() + if (!languages.hasProvider('rename', doc.textDocument)) { + throw new Error(`Rename provider not found for current buffer`) + } + await doc.synchronize() + let edit = await this.handler.withRequestToken('refactor', async token => { + let res = await languages.prepareRename(doc.textDocument, position, token) + if (token.isCancellationRequested) return null + if (res === false) throw new Error(`Provider returns null on prepare, unable to rename at current position`) + let edit = await languages.provideRenameEdits(doc.textDocument, position, 'NewName', token) + if (token.isCancellationRequested) return null + if (!edit) throw new Error('Provider returns null for rename edits.') + return edit + }) + if (edit) { + await this.fromWorkspaceEdit(edit, doc.filetype) + } + } + + /** + * Search by rg + */ + public async search(args: string[]): Promise { + let buf = await this.createRefactorBuffer() + if (!buf) return + let cwd = await this.nvim.call('getcwd', []) + let search = new Search(this.nvim) + await search.run(args, cwd, buf) + } + + public async save(bufnr: number): Promise { + let buf = this.buffers.get(bufnr) + if (buf) return await buf.save() + } + + public getBuffer(bufnr: number): RefactorBuffer { + return this.buffers.get(bufnr) + } + + /** + * Create initialized refactor buffer + */ + public async createRefactorBuffer(filetype?: string): Promise { + let { nvim } = this + let [fromWinid, cwd] = await nvim.eval('[win_getid(),getcwd()]') as [number, string] + 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) + let [, err] = await nvim.resumeNotification() + if (err) return + let [bufnr, win] = await nvim.eval('[bufnr("%"),win_getid()]') as [number, number] + let opts = { fromWinid, winid: win, cwd } + await workspace.document + let buf = new RefactorBuffer(bufnr, this.srcId, this.nvim, this.config, opts) + this.buffers.set(bufnr, buf) + return buf + } + + /** + * Create refactor buffer from lines + */ + public async fromLines(lines: string[]): Promise { + let buf = await this.createRefactorBuffer() + if (buf) await buf.buffer.setLines(lines, { start: 0, end: -1, strictIndexing: false }) + return buf + } + + /** + * Create refactor buffer from locations + */ + public async fromLocations(locations: Location[], filetype?: string): Promise { + if (!locations || locations.length == 0) return null + let changes: { [uri: string]: TextEdit[] } = {} + let edit: WorkspaceEdit = { changes } + for (let location of locations) { + let edits: TextEdit[] = changes[location.uri] || [] + edits.push({ range: location.range, newText: '' }) + changes[location.uri] = edits + } + return await this.fromWorkspaceEdit(edit, filetype) + } + + /** + * Start refactor from workspaceEdit + */ + public async fromWorkspaceEdit(edit: WorkspaceEdit, filetype?: string): Promise { + if (!edit || emptyWorkspaceEdit(edit)) return undefined + let items: FileItem[] = [] + let { beforeContext, afterContext } = this.config + let { changes, documentChanges } = edit + if (!changes) { + changes = {} + for (let change of documentChanges || []) { + if (TextDocumentEdit.is(change)) { + let { textDocument, edits } = change + if (textDocument.uri.startsWith('file:')) { + changes[textDocument.uri] = edits + } + } + } + } + for (let key of Object.keys(changes)) { + let max = await this.getLineCount(key) + let edits = changes[key] + let ranges: FileRange[] = [] + // start end highlights + let start = null + let end = null + let highlights: Range[] = [] + 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 }) + items.push({ + ranges, + filepath: URI.parse(key).fsPath + }) + } + let buf = await this.createRefactorBuffer(filetype) + await buf.addFileItems(items) + return buf + } + + private async getLineCount(uri: string): Promise { + let doc = workspace.getDocument(uri) + if (doc) return doc.lineCount + return await getFileLineCount(URI.parse(uri).fsPath) + } + + public reset(): void { + if (this.timer) { + clearTimeout(this.timer) + } + for (let buf of this.buffers.values()) { + buf.dispose() + } + this.buffers.clear() + } + + public dispose(): void { + if (this.timer) { + clearTimeout(this.timer) + } + this._onCreate.dispose() + for (let buf of this.buffers.values()) { + buf.dispose() + } + this.buffers.clear() + disposeAll(this.disposables) + } +} + +function adjustRange(range: Range, offset: number): Range { + let { start, end } = range + return Range.create(start.line - offset, start.character, end.line - offset, end.character) +} + +function emptyWorkspaceEdit(edit: WorkspaceEdit): boolean { + let { changes, documentChanges } = edit + if (documentChanges && documentChanges.length) return false + if (changes && Object.keys(changes).length) return false + return true +} diff --git a/vim-config/plugins/coc.nvim/src/handler/rename.ts b/vim-config/plugins/coc.nvim/src/handler/rename.ts new file mode 100644 index 00000000..3279f0ae --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/rename.ts @@ -0,0 +1,67 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Range, WorkspaceEdit } from 'vscode-languageserver-protocol' +import languages from '../languages' +import { HandlerDelegate } from '../types' +import { emptyRange } from '../util/position' +import window from '../window' +import workspace from '../workspace' +const logger = require('../util/logger')('handler-rename') + +export default class Rename { + constructor( + private nvim: Neovim, + private handler: HandlerDelegate) { + } + + public async getWordEdit(): Promise { + let { doc, position } = await this.handler.getCurrentState() + let range = doc.getWordRangeAtPosition(position) + if (!range || emptyRange(range)) return null + let curname = doc.textDocument.getText(range) + if (languages.hasProvider('rename', doc.textDocument)) { + await doc.synchronize() + let requestTokenSource = new CancellationTokenSource() + let res = await languages.prepareRename(doc.textDocument, position, requestTokenSource.token) + if (res === false) return null + let edit = await languages.provideRenameEdits(doc.textDocument, position, curname, requestTokenSource.token) + if (edit) return edit + } + window.showMessage('Rename provider not found, extract word ranges from current buffer', 'more') + let ranges = doc.getSymbolRanges(curname) + return { + changes: { + [doc.uri]: ranges.map(r => ({ range: r, newText: curname })) + } + } + } + + public async rename(newName?: string): Promise { + let { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('rename', doc.textDocument) + await doc.synchronize() + let token = (new CancellationTokenSource()).token + let res = await languages.prepareRename(doc.textDocument, position, token) + if (res === false) { + window.showMessage('Invalid position for rename', 'warning') + return false + } + let curname: string + if (!newName) { + if (Range.is(res)) { + curname = doc.textDocument.getText(res) + await window.moveTo(res.start) + } else if (res && typeof res.placeholder === 'string') { + curname = res.placeholder + } else { + curname = await this.nvim.eval('expand("")') as string + } + newName = await window.requestInput('New name', curname) + } + if (!newName) return false + let edit = await languages.provideRenameEdits(doc.textDocument, position, newName, token) + if (token.isCancellationRequested || !edit) return false + await workspace.applyEdit(edit) + if (workspace.isVim) this.nvim.command('redraw', true) + return true + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/search.ts b/vim-config/plugins/coc.nvim/src/handler/search.ts new file mode 100644 index 00000000..cf95850d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/search.ts @@ -0,0 +1,201 @@ +import { Neovim } from '@chemzqm/neovim' +import { Mutex } from '../util/mutex' +import { ChildProcess, spawn } from 'child_process' +import { EventEmitter } from 'events' +import path from 'path' +import readline from 'readline' +import { Range } from 'vscode-languageserver-types' +import Highlighter from '../model/highligher' +import { ansiparse } from '../util/ansiparse' +import window from '../window' +import RefactorBuffer, { FileItem, FileRange } from './refactor/buffer' +const logger = require('../util/logger')('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 EventEmitter { + private process: ChildProcess + public start(cmd: string, args: string[], cwd: string): void { + this.process = spawn(cmd, args, { cwd }) + this.process.on('error', e => { + this.emit('error', e.message) + }) + const rl = readline.createInterface(this.process.stdout) + let start: number + let fileItem: FileItem + let lines: string[] = [] + let highlights: Range[] = [] + let create = true + rl.on('line', content => { + if (content.includes(controlCode)) { + let items = ansiparse(content) + if (items[0].foreground == 'black') { + fileItem = { filepath: path.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(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: 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: FileRange = { + lines, + highlights, + start, + end: start + lines.length + } + fileItem.ranges.push(fileRange) + } + this.emit('item', fileItem) + } + lines = highlights = fileItem = null + this.emit('end') + }) + } + + public dispose(): void { + if (this.process) { + this.process.kill() + } + } +} + +export default class Search { + private task: Task + constructor(private nvim: Neovim, private cmd = 'rg') { + } + + public run(args: string[], cwd: string, refactorBuf: RefactorBuffer): Promise { + let { nvim, cmd } = this + let { afterContext, beforeContext } = refactorBuf.config + let argList = ['-A', afterContext.toString(), '-B', beforeContext.toString()].concat(defaultArgs, args) + let p = getPathFromArgs(args) + if (p) argList.pop() + argList.push('--', p ? path.isAbsolute(p) ? p : `./${p.replace(/^\.\//, '')}` : './') + this.task = new Task() + this.task.start(cmd, argList, cwd) + let mutex: Mutex = new Mutex() + let files = 0 + let matches = 0 + let start = Date.now() + // remaining items + let fileItems: FileItem[] = [] + const addFileItems = async () => { + if (fileItems.length == 0) return + let items = fileItems.slice() + fileItems = [] + const release = await mutex.acquire() + try { + await refactorBuf.addFileItems(items) + } catch (e) { + logger.error(e) + } + release() + } + return new Promise((resolve, reject) => { + let interval = setInterval(addFileItems, 300) + this.task.on('item', async (fileItem: FileItem) => { + files++ + matches = matches + fileItem.ranges.reduce((p, r) => p + r.highlights.length, 0) + fileItems.push(fileItem) + }) + this.task.on('error', message => { + clearInterval(interval) + window.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 buf = refactorBuf.buffer + if (buf) { + nvim.pauseNotification() + if (files == 0) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + buf.setLines(['No match found'], { start: 1, end: 2, strictIndexing: false }, true) + buf.addHighlight({ line: 1, srcId: -1, colEnd: -1, colStart: 0, hlGroup: 'Error' }).logError() + buf.setOption('modified', false, true) + } else { + let highligher = new Highlighter() + 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() + }) + }) + } + + public abort(): void { + this.task?.dispose() + } +} + +// rg requires `-- [path]` at the end +export function getPathFromArgs(args: string[]): string | undefined { + if (args.length < 2) return undefined + let len = args.length + if (args[len - 1].startsWith('-')) return undefined + if (args[len - 2].startsWith('-')) return undefined + return args[len - 1] +} diff --git a/vim-config/plugins/coc.nvim/src/handler/selectionRange.ts b/vim-config/plugins/coc.nvim/src/handler/selectionRange.ts new file mode 100644 index 00000000..3b014aeb --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/selectionRange.ts @@ -0,0 +1,83 @@ +import { Neovim } from '@chemzqm/neovim' +import { Position, Range, SelectionRange } from 'vscode-languageserver-protocol' +import languages from '../languages' +import { HandlerDelegate } from '../types' +import { equals } from '../util/object' +import { positionInRange } from '../util/position' +import window from '../window' +import workspace from '../workspace' + +export default class SelectionRangeHandler { + private selectionRange: SelectionRange = null + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + } + + public async getSelectionRanges(): Promise { + let { doc, position } = await this.handler.getCurrentState() + this.handler.checkProvier('selectionRange', doc.textDocument) + await doc.synchronize() + let selectionRanges: SelectionRange[] = await this.handler.withRequestToken('selection ranges', token => { + return languages.getSelectionRanges(doc.textDocument, [position], token) + }) + return selectionRanges + } + + public async selectRange(visualmode: string, forward: boolean): Promise { + let { nvim } = this + let { doc } = await this.handler.getCurrentState() + this.handler.checkProvier('selectionRange', doc.textDocument) + let positions: Position[] = [] + if (!forward && (!this.selectionRange || !visualmode)) return + if (visualmode) { + let range = await workspace.getSelectedRange(visualmode, doc) + positions.push(range.start, range.end) + } else { + let position = await window.getCursorPosition() + positions.push(position) + } + if (!forward) { + let curr = Range.create(positions[0], positions[1]) + let { selectionRange } = this + while (selectionRange && selectionRange.parent) { + if (equals(selectionRange.parent.range, curr)) { + break + } + selectionRange = selectionRange.parent + } + if (selectionRange && selectionRange.parent) { + await workspace.selectRange(selectionRange.range) + } + return + } + await doc.synchronize() + let selectionRanges: SelectionRange[] = await this.handler.withRequestToken('selection ranges', token => { + return languages.getSelectionRanges(doc.textDocument, positions, token) + }) + if (!selectionRanges || selectionRanges.length == 0) return + let mode = await nvim.eval('mode()') + if (mode != 'n') await nvim.eval(`feedkeys("\\", 'in')`) + let selectionRange: SelectionRange + if (selectionRanges.length == 1) { + selectionRange = selectionRanges[0] + } else { + let end = positions[1] || positions[0] + let r = Range.create(positions[0], end) + selectionRange = selectionRanges[0] + while (selectionRange) { + if (equals(r, selectionRange.range)) { + selectionRange = selectionRange.parent + continue + } + if ( + positionInRange(positions[0], selectionRange.range) == 0 && + positionInRange(end, selectionRange.range) == 0) { + break + } + selectionRange = selectionRange.parent + } + } + if (!selectionRange) return + this.selectionRange = selectionRanges[0] + await workspace.selectRange(selectionRange.range) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/semanticTokensHighlights/buffer.ts b/vim-config/plugins/coc.nvim/src/handler/semanticTokensHighlights/buffer.ts new file mode 100644 index 00000000..e0da0c29 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/semanticTokensHighlights/buffer.ts @@ -0,0 +1,301 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import debounce from 'debounce' +import { CancellationTokenSource, Range, SemanticTokens, SemanticTokensDelta, uinteger } from 'vscode-languageserver-protocol' +import languages from '../../languages' +import { SyncItem } from '../../model/bufferSync' +import Document from '../../model/document' +import { HighlightItem } from '../../types' +import workspace from '../../workspace' +const logger = require('../../util/logger')('semanticTokens-buffer') + +const SEMANTIC_HLGROUP_PREFIX = 'CocSem_' +/** + * Relative highlight + */ +interface RelativeHighlight { + group: string + deltaLine: number + deltaStartCharacter: number + length: number +} + +export interface SemanticTokensConfig { + enabled: boolean +} + +interface SemanticTokensPreviousResult { + readonly version: number + readonly resultId: string | undefined, + readonly tokens?: uinteger[], +} + +export const NAMESPACE = 'semanticTokens' + +export default class SemanticTokensBuffer implements SyncItem { + private tokenSource: CancellationTokenSource + private _highlights: HighlightItem[] + private previousResults: SemanticTokensPreviousResult + public highlight: Function & { clear(): void } + constructor( + private nvim: Neovim, + public readonly bufnr: number, + private readonly config: SemanticTokensConfig) { + this.highlight = debounce(() => { + this.doHighlight().catch(e => { + logger.error('Error on semanticTokens highlight:', e.stack) + }) + }, global.hasOwnProperty('__TEST__') ? 10 : 2000) + this.highlight() + } + + public onChange(): void { + this.cancel() + this.highlight() + } + + public async forceHighlight(): Promise { + this.cancel() + this.highlight.clear() + await this.doHighlight() + } + + /** + * Get current highlight items + */ + public get highlights(): ReadonlyArray { + return this._highlights + } + + public get enabled(): boolean { + if (!this.config.enabled) return false + let doc = workspace.getDocument(this.bufnr) + if (!doc || !doc.attached) return false + return languages.hasProvider('semanticTokens', doc.textDocument) + } + + public get previousVersion(): number | undefined { + if (!this.previousResults) return undefined + return this.previousResults.version + } + + private get buffer(): Buffer { + return this.nvim.createBuffer(this.bufnr) + } + + public checkState(): void { + if (!this.config.enabled) throw new Error('SemanticTokens highlights disabled by configuration') + let doc = workspace.getDocument(this.bufnr) + if (!doc || !doc.attached) throw new Error('Document not attached') + if (!languages.hasProvider('semanticTokens', doc.textDocument)) throw new Error('SemanticTokens provider not found, your languageserver may not support it') + } + + public setState(enabled: boolean): void { + if (enabled) { + this.highlight() + } else { + this.highlight.clear() + this.clearHighlight() + } + } + + private async doHighlight(): Promise { + if (!this.enabled) return + let doc = workspace.getDocument(this.bufnr) + const { nvim } = this + let winid = await nvim.call('bufwinid', [this.bufnr]) + // not visible on current tab + if (winid == -1) return + const curr = await this.requestHighlights(doc) + // request cancelled or can't work + if (!curr) return + if (!curr.length) { + this.clearHighlight() + return + } + let prev: HighlightItem[] = [] + if (workspace.env.updateHighlight) { + prev = (await nvim.call('coc#highlight#get_highlights', [this.bufnr, NAMESPACE])) as HighlightItem[] + } + const { highlights, lines } = this.calculateHighlightUpdates(prev, curr) + nvim.pauseNotification() + if (!workspace.env.updateHighlight) { + this.buffer.clearNamespace(NAMESPACE, 0, -1) + } else { + for (const ln of lines) { + this.buffer.clearNamespace(NAMESPACE, ln, ln + 1) + } + } + const groups: { [index: string]: Range[] } = {} + if (highlights.length) { + for (const h of highlights) { + const range = Range.create(h.lnum, h.colStart, h.lnum, h.colEnd) + groups[h.hlGroup] = groups[h.hlGroup] || [] + groups[h.hlGroup].push(range) + } + } + for (const hlGroup of Object.keys(groups)) { + this.buffer.highlightRanges(NAMESPACE, hlGroup, groups[hlGroup]) + } + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + if (workspace.isVim) nvim.command('redraw', true) + } + + private calculateHighlightUpdates(prev: HighlightItem[], curr: HighlightItem[]): { highlights: HighlightItem[], lines: Set } { + const stringCompare = Intl.Collator("en").compare + function compare(a: HighlightItem, b: HighlightItem): number { + return ( + a.lnum - b.lnum || + a.colStart - b.colStart || + a.colEnd - b.colEnd || + stringCompare(a.hlGroup, b.hlGroup) + ) + } + + prev = prev.slice().sort(compare) + curr = curr.slice().sort(compare) + + const prevByLine: Map = new Map() + for (const hl of prev) { + if (!prevByLine.has(hl.lnum)) prevByLine.set(hl.lnum, []) + prevByLine.get(hl.lnum).push(hl) + } + + const currByLine: Map = new Map() + for (const hl of curr) { + if (!currByLine.has(hl.lnum)) currByLine.set(hl.lnum, []) + currByLine.get(hl.lnum).push(hl) + } + + const lastLine = Math.max( + (prev[prev.length - 1] || { lnum: 0 }).lnum, + (curr[curr.length - 1] || { lnum: 0 }).lnum + ) + const lineNumbersToUpdate: Set = new Set() + for (let i = 0; i <= lastLine; i++) { + const ph = prevByLine.has(i) + const ch = currByLine.has(i) + if (ph !== ch) { + lineNumbersToUpdate.add(i) + continue + } else if (!ph && !ch) { + continue + } + + const pp = prevByLine.get(i) + const cc = currByLine.get(i) + + if (pp.length !== cc.length) { + lineNumbersToUpdate.add(i) + continue + } + + for (let j = 0; j < pp.length; j++) { + if (compare(pp[j], cc[j]) !== 0) { + lineNumbersToUpdate.add(i) + continue + } + } + } + + let highlights: HighlightItem[] = [] + for (const line of lineNumbersToUpdate) { + highlights = highlights.concat(currByLine.get(line) || []) + } + return { highlights, lines: lineNumbersToUpdate } + } + + /** + * Request highlights from provider, return undefined when can't request or request cancelled + * TODO use range provider as well + */ + private async requestHighlights(doc: Document, forceFull?: boolean): Promise { + const legend = languages.getLegend(doc.textDocument) + if (!legend) return undefined + this.cancel() + this.tokenSource = new CancellationTokenSource() + const { token } = this.tokenSource + const hasEditProvider = languages.hasSemanticTokensEdits(doc.textDocument) + const previousResult = forceFull ? null : this.previousResults + let result: SemanticTokens | SemanticTokensDelta + let version = doc.textDocument.version + if (hasEditProvider && previousResult?.resultId) { + result = await languages.provideDocumentSemanticTokensEdits(doc.textDocument, previousResult.resultId, token) + } else { + result = await languages.provideDocumentSemanticTokens(doc.textDocument, token) + } + this.tokenSource = null + if (token.isCancellationRequested || !result) return undefined + + let tokens: uinteger[] = [] + if (SemanticTokens.is(result)) { + tokens = result.data + } else { + tokens = previousResult.tokens + result.edits.forEach(e => { + if (e.deleteCount > 0) { + tokens.splice(e.start, e.deleteCount, ...e.data) + } else { + tokens.splice(e.start, 0, ...e.data) + } + }) + } + this.previousResults = { resultId: result.resultId, tokens, version } + const relatives: RelativeHighlight[] = [] + for (let i = 0; i < tokens.length; i += 5) { + const deltaLine = tokens[i] + const deltaStartCharacter = tokens[i + 1] + const length = tokens[i + 2] + const tokenType = tokens[i + 3] + // const tokenModifiers = legend.tokenModifiers.filter((_, m) => tokens[i + 4] & (1 << m)) + const group = SEMANTIC_HLGROUP_PREFIX + legend.tokenTypes[tokenType] + relatives.push({ + group, + deltaLine, + deltaStartCharacter, + length + }) + } + + const res: HighlightItem[] = [] + let currentLine = 0 + let currentCharacter = 0 + for (const { + group, + deltaLine, + deltaStartCharacter, + length + } of relatives) { + const lnum = currentLine + deltaLine + const colStart = deltaLine === 0 ? currentCharacter + deltaStartCharacter : deltaStartCharacter + const colEnd = colStart + length + currentLine = lnum + currentCharacter = colStart + res.push({ + hlGroup: group, + lnum, + colStart, + colEnd + }) + } + this._highlights = res + return res + } + + public clearHighlight(): void { + this.buffer.clearNamespace(NAMESPACE) + } + + public cancel(): void { + if (this.tokenSource) { + this.tokenSource.cancel() + this.tokenSource = null + } + } + + public dispose(): void { + this.highlight.clear() + this.previousResults = undefined + this.cancel() + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/semanticTokensHighlights/index.ts b/vim-config/plugins/coc.nvim/src/handler/semanticTokensHighlights/index.ts new file mode 100644 index 00000000..f20d642a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/semanticTokensHighlights/index.ts @@ -0,0 +1,182 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import commands from '../../commands' +import events from '../../events' +import languages from '../../languages' +import BufferSync from '../../model/bufferSync' +import Highlighter from '../../model/highligher' +import { ConfigurationChangeEvent, HandlerDelegate } from '../../types' +import { disposeAll } from '../../util' +import window from '../../window' +import workspace from '../../workspace' +import SemanticTokensBuffer, { NAMESPACE, SemanticTokensConfig } from './buffer' +const logger = require('../../util/logger')('semanticTokens') +const headGroup = 'Statement' + +export default class SemanticTokensHighlights { + // shared with buffers + private config: SemanticTokensConfig + private disposables: Disposable[] = [] + private highlighters: BufferSync + + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + this.loadConfiguration() + workspace.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables) + commands.register({ + id: 'semanticTokens.checkCurrent', + execute: async () => { + try { + let item = await this.getCurrentItem() + item.checkState() + } catch (e) { + window.showMessage(e.message, 'error') + return + } + window.showMessage('Semantic tokens provider found for current buffer', 'more') + } + }, false, 'check semantic tokens provider for current buffer') + commands.register({ + id: 'semanticTokens.clearCurrent', + execute: async () => { + let buf = await nvim.buffer + buf.clearNamespace(NAMESPACE, 0, -1) + } + }, false, 'clear semantic tokens highlights of current buffer') + commands.register({ + id: 'semanticTokens.clearAll', + execute: async () => { + let bufs = await nvim.buffers + for (let buf of bufs) { + buf.clearNamespace(NAMESPACE, 0, -1) + } + } + }, false, 'clear semantic tokens highlights of all buffers') + this.disposables.push({ + dispose: () => { + commands.unregister('semanticTokens.checkCurrentBuffer') + } + }) + // may need update highlights for buffer that becomes visible + events.on('BufEnter', bufnr => { + let item = this.highlighters.getItem(bufnr) + if (!item) return + let doc = workspace.getDocument(bufnr) + if (!doc || doc.textDocument.version == item.previousVersion) return + item.forceHighlight().catch(e => { + logger.error(`Error on semantic highlighters:`, e) + }) + }, null, this.disposables) + this.highlighters = workspace.registerBufferSync(doc => { + return new SemanticTokensBuffer(this.nvim, doc.bufnr, this.config) + }) + languages.onDidSemanticTokensRefresh(selector => { + for (let item of this.highlighters.items) { + let doc = workspace.getDocument(item.bufnr) + if (doc && workspace.match(selector, doc.textDocument)) { + item.highlight() + } + } + }, null, this.disposables) + } + + private loadConfiguration(e?: ConfigurationChangeEvent): void { + if (!e || e.affectsConfiguration('coc.preferences')) { + // let con = this.config || {} + let config = workspace.getConfiguration('coc.preferences') + let enabled = config.get('semanticTokensHighlights', true) + if (workspace.isVim && !workspace.env.textprop) { + enabled = false + } + if (this.config && enabled != this.config.enabled) { + if (this.highlighters) { + for (let buf of this.highlighters.items) { + buf.setState(enabled) + } + } + } + if (!this.config) { + this.config = { enabled } + } else { + this.config.enabled = enabled + } + } + } + + public async getCurrentItem(): Promise { + let buf = await this.nvim.buffer + let highlighter = this.highlighters.getItem(buf.id) + if (!highlighter) throw new Error('current buffer not attached') + return highlighter + } + + /** + * Force highlight of current buffer + */ + public async highlightCurrent(): Promise { + let highlighter = await this.getCurrentItem() + highlighter.checkState() + await highlighter.forceHighlight() + } + + /** + * Show semantic highlight info in temporarily buffer + */ + public async showHiglightInfo(): Promise { + if (!this.config.enabled) throw new Error('Semantic highlights is disabled by configuration.') + let item = await this.getCurrentItem() + item.checkState() + let highlights = item.highlights || [] + let highlighter = new Highlighter() + let { nvim } = this + nvim.pauseNotification() + nvim.command(`vs +setl\\ buftype=nofile __coc_semantic_highlights_${item.bufnr}__`, true) + nvim.command(`setl bufhidden=wipe noswapfile nobuflisted wrap undolevels=-1`, true) + nvim.call('bufnr', ['%'], true) + let res = await nvim.resumeNotification() + if (res[1]) throw new Error(`Error on buffer create: ${res[1]}`) + let bufnr = res[0][2] as number + highlighter.addLine('Semantic highlights info', headGroup) + highlighter.addLine('') + highlighter.addLine('The number of semantic tokens: ') + highlighter.addText(String(highlights.length), 'Number') + highlighter.addLine('') + highlighter.addLine('Semantic highlight groups used by current buffer', headGroup) + highlighter.addLine('') + const groups = [...new Set(highlights.map(({ hlGroup }) => hlGroup))] + for (const hlGroup of groups) { + highlighter.addTexts([{ text: '-', hlGroup: 'Comment' }, { text: ' ' }, { text: hlGroup, hlGroup }]) + highlighter.addLine('') + } + highlighter.addLine('Tokens types that current Language Server supported:', headGroup) + highlighter.addLine('') + let doc = workspace.getDocument(item.bufnr) + const legend = languages.getLegend(doc.textDocument) + if (legend?.tokenTypes.length) { + for (const t of [...new Set(legend.tokenTypes)]) { + highlighter.addTexts([{ text: '-', hlGroup: 'Comment' }, { text: ' ' }, { text: `CocSem_${t}`, hlGroup: `CocSem_${t}` }]) + highlighter.addLine('') + } + } else { + highlighter.addLine('No token types supported', 'Comment') + } + highlighter.addLine('Tokens modifiers that current Language Server supported:', headGroup) + highlighter.addLine('') + if (legend?.tokenModifiers.length) { + for (const t of [...new Set(legend.tokenModifiers)]) { + highlighter.addTexts([{ text: '-', hlGroup: 'Comment' }, { text: ' ' }, { text: `CocSem_${t}`, hlGroup: `CocSem_${t}` }]) + highlighter.addLine('') + } + } else { + highlighter.addLine('No token modifiers supported', 'Comment') + } + nvim.pauseNotification() + highlighter.render(nvim.createBuffer(bufnr)) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + + public dispose(): void { + this.highlighters.dispose() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/signature.ts b/vim-config/plugins/coc.nvim/src/handler/signature.ts new file mode 100644 index 00000000..b1dfc795 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/signature.ts @@ -0,0 +1,284 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Disposable, MarkupContent, Position, SignatureHelp, SignatureHelpTriggerKind } from 'vscode-languageserver-protocol' +import events from '../events' +import languages from '../languages' +import Document from '../model/document' +import FloatFactory from '../model/floatFactory' +import { ConfigurationChangeEvent, FloatConfig, HandlerDelegate } from '../types' +import { disposeAll, isMarkdown } from '../util' +import { byteLength } from '../util/string' +import workspace from '../workspace' +const logger = require('../util/logger')('handler-signature') + +interface SignatureConfig { + wait: number + trigger: boolean + target: string + preferAbove: boolean + hideOnChange: boolean + floatConfig: FloatConfig +} + +interface SignaturePosition { + bufnr: number + lnum: number + col: number +} + +interface SignaturePart { + text: string + type: 'Label' | 'MoreMsg' | 'Normal' +} + +export default class Signature { + private timer: NodeJS.Timer + private config: SignatureConfig + private signatureFactory: FloatFactory + private lastPosition: SignaturePosition | undefined + private disposables: Disposable[] = [] + private tokenSource: CancellationTokenSource | undefined + constructor(private nvim: Neovim, private handler: HandlerDelegate) { + this.signatureFactory = new FloatFactory(nvim) + this.loadConfiguration() + this.disposables.push(this.signatureFactory) + workspace.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables) + events.on('CursorMovedI', async (bufnr, cursor) => { + let pos = this.lastPosition + if (!pos) return + // avoid close signature for valid position. + if (pos.bufnr == bufnr && pos.lnum == cursor[0] && pos.col <= cursor[1]) return + this.signatureFactory.close() + }, null, this.disposables) + events.on(['InsertLeave', 'BufEnter'], () => { + this.tokenSource?.cancel() + }, null, this.disposables) + events.on('TextChangedI', () => { + if (this.config.hideOnChange) { + this.signatureFactory.close() + } + }, null, this.disposables) + events.on('TextInsert', async (bufnr, info, character) => { + if (!this.config.trigger) return + let doc = this.getTextDocument(bufnr) + if (!doc || !languages.shouldTriggerSignatureHelp(doc.textDocument, character)) return + await this._triggerSignatureHelp(doc, { line: info.lnum - 1, character: info.pre.length }, false) + }, null, this.disposables) + } + + private getTextDocument(bufnr: number): Document | undefined { + let doc = workspace.getDocument(bufnr) + if (!doc || doc.isCommandLine || !doc.attached) return + return doc + } + + private loadConfiguration(e?: ConfigurationChangeEvent): void { + if (!e || e.affectsConfiguration('signature')) { + let config = workspace.getConfiguration('signature') + let target = config.get('target', 'float') + if (target == 'float' && !workspace.floatSupported) { + target = 'echo' + } + this.config = { + target, + floatConfig: config.get('floatConfig', {}), + trigger: config.get('enable', true), + wait: Math.max(config.get('triggerSignatureWait', 500), 200), + preferAbove: config.get('preferShownAbove', true), + hideOnChange: config.get('hideOnTextChange', false), + } + } + } + + public async triggerSignatureHelp(): Promise { + let { doc, position, mode } = await this.handler.getCurrentState() + if (!languages.hasProvider('signature', doc.textDocument)) return false + let offset = 0 + let character = position.character + if (mode == 's') { + let placeholder = await this.nvim.getVar('coc_last_placeholder') as any + if (placeholder) { + let { start, end, bufnr } = placeholder + if (bufnr == doc.bufnr && start.line == end.line && start.line == position.line) { + position = Position.create(start.line, start.character) + offset = character - position.character + } + } + } + return await this._triggerSignatureHelp(doc, position, true, offset) + } + + private async _triggerSignatureHelp(doc: Document, position: Position, invoke = true, offset = 0): Promise { + this.tokenSource?.cancel() + let tokenSource = this.tokenSource = new CancellationTokenSource() + let token = tokenSource.token + token.onCancellationRequested(() => { + tokenSource.dispose() + this.tokenSource = undefined + }) + let { target } = this.config + let timer = this.timer = setTimeout(() => { + tokenSource.cancel() + }, this.config.wait) + await doc.patchChange(true) + let signatureHelp = await languages.getSignatureHelp(doc.textDocument, position, token, { + isRetrigger: this.signatureFactory.checkRetrigger(doc.bufnr), + triggerKind: invoke ? SignatureHelpTriggerKind.Invoked : SignatureHelpTriggerKind.TriggerCharacter + }) + clearTimeout(timer) + if (token.isCancellationRequested) return false + if (!signatureHelp || signatureHelp.signatures.length == 0) { + this.signatureFactory.close() + return false + } + let { activeSignature, signatures } = signatureHelp + if (activeSignature) { + // make active first + let [active] = signatures.splice(activeSignature, 1) + if (active) signatures.unshift(active) + } + if (target == 'echo') { + this.echoSignature(signatureHelp) + } else { + await this.showSignatureHelp(doc, position, signatureHelp, offset) + } + return true + } + + private async showSignatureHelp(doc: Document, position: Position, signatureHelp: SignatureHelp, offset: number): Promise { + let { signatures, activeParameter } = signatureHelp + let paramDoc: string | MarkupContent = null + let startOffset = offset + let docs = signatures.reduce((p, c, idx) => { + let activeIndexes: [number, number] = 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] + } + if (offset == startOffset) { + offset = offset + activeIndexes[0] + 1 + } + p.push({ + content: c.label, + filetype: doc.filetype, + active: activeIndexes + }) + if (paramDoc) { + let content = typeof paramDoc === 'string' ? paramDoc : paramDoc.value + if (content.trim().length) { + p.push({ + content, + filetype: isMarkdown(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: isMarkdown(c.documentation) ? 'markdown' : 'txt' + }) + } + } + return p + }, []) + let content = doc.getline(position.line, false).slice(0, position.character) + this.lastPosition = { bufnr: doc.bufnr, lnum: position.line + 1, col: byteLength(content) + 1 } + const excludeImages = workspace.getConfiguration('coc.preferences').get('excludeImageLinksInMarkdownDocument') + let config = this.signatureFactory.applyFloatConfig({ + preferTop: this.config.preferAbove, + autoHide: false, + offsetX: offset, + modes: ['i', 'ic', 's'], + excludeImages + }, this.config.floatConfig) + await this.signatureFactory.show(docs, config) + } + + private echoSignature(signatureHelp: SignatureHelp): void { + let { signatures, activeParameter } = signatureHelp + let columns = workspace.env.columns + signatures = signatures.slice(0, workspace.env.cmdheight) + let signatureList: SignaturePart[][] = [] + for (let signature of signatures) { + let parts: SignaturePart[] = [] + 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: number + let end: number + 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) + } + + public dispose(): void { + disposeAll(this.disposables) + if (this.timer) { + clearTimeout(this.timer) + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/symbols/buffer.ts b/vim-config/plugins/coc.nvim/src/handler/symbols/buffer.ts new file mode 100644 index 00000000..6f66474c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/symbols/buffer.ts @@ -0,0 +1,89 @@ +import debounce from 'debounce' +import { CancellationTokenSource, Disposable, DocumentSymbol, Emitter, Event, SymbolTag, TextDocument } from 'vscode-languageserver-protocol' +import languages from '../../languages' +import { SyncItem } from '../../model/bufferSync' +import { disposeAll } from '../../util' +import workspace from '../../workspace' +import { isDocumentSymbols } from './util' + +export default class SymbolsBuffer implements SyncItem { + private disposables: Disposable[] = [] + public fetchSymbols: (() => void) & { clear(): void } + private autoUpdate = false + private version: number + private symbols: DocumentSymbol[] + private tokenSource: CancellationTokenSource + private readonly _onDidUpdate = new Emitter() + public readonly onDidUpdate: Event = this._onDidUpdate.event + constructor(public readonly bufnr: number) { + this.fetchSymbols = debounce(() => { + this._fetchSymbols().logError() + }, global.hasOwnProperty('__TEST__') ? 10 : 500) + } + + /** + * Enable autoUpdate when invoked. + */ + public async getSymbols(): Promise { + let doc = workspace.getDocument(this.bufnr) + if (!doc) return [] + await doc.patchChange() + this.autoUpdate = true + // refresh for empty symbols since some languages server could be buggy first time. + if (doc.version == this.version && this.symbols?.length) return this.symbols + this.cancel() + await this._fetchSymbols() + return this.symbols + } + + public onChange(): void { + this.cancel() + if (this.autoUpdate) { + this.fetchSymbols() + } + } + + private get textDocument(): TextDocument | undefined { + return workspace.getDocument(this.bufnr)?.textDocument + } + + private async _fetchSymbols(): Promise { + let { textDocument } = this + if (!textDocument) return + let { version } = textDocument + let tokenSource = this.tokenSource = new CancellationTokenSource() + let { token } = tokenSource + let symbols = await languages.getDocumentSymbol(textDocument, token) + this.tokenSource = undefined + if (symbols == null || token.isCancellationRequested) return + let res: DocumentSymbol[] + if (isDocumentSymbols(symbols)) { + res = symbols + } else { + res = symbols.map(o => { + let sym = DocumentSymbol.create(o.name, '', o.kind, o.location.range, o.location.range) + if (o.deprecated) sym.tags = [SymbolTag.Deprecated] + return sym + }) + } + this.version = version + this.symbols = res + this._onDidUpdate.fire(res) + } + + public cancel(): void { + this.fetchSymbols.clear() + if (this.tokenSource) { + this.tokenSource.cancel() + this.tokenSource.dispose() + this.tokenSource = null + } + } + + public dispose(): void { + this.cancel() + this.symbols = undefined + this._onDidUpdate.dispose() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/symbols/index.ts b/vim-config/plugins/coc.nvim/src/handler/symbols/index.ts new file mode 100644 index 00000000..d4fba17c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/symbols/index.ts @@ -0,0 +1,161 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Disposable, Range, SymbolInformation } from 'vscode-languageserver-protocol' +import events from '../../events' +import languages from '../../languages' +import BufferSync from '../../model/bufferSync' +import { HandlerDelegate } from '../../types' +import { disposeAll } from '../../util/index' +import { equals } from '../../util/object' +import { positionInRange, rangeInRange } from '../../util/position' +import window from '../../window' +import workspace from '../../workspace' +import SymbolsBuffer from './buffer' +import Outline from './outline' +import { convertSymbols, SymbolInfo } from './util' + +export default class Symbols { + private buffers: BufferSync + private disposables: Disposable[] = [] + private outline: Outline + + constructor( + private nvim: Neovim, + private handler: HandlerDelegate + ) { + this.buffers = workspace.registerBufferSync(doc => { + if (doc.buftype != '') return undefined + return new SymbolsBuffer(doc.bufnr) + }) + this.outline = new Outline(nvim, this.buffers, handler) + events.on('CursorHold', async (bufnr: number) => { + if (!this.functionUpdate || !this.buffers.getItem(bufnr)) return + await this.getCurrentFunctionSymbol(bufnr) + }, null, this.disposables) + events.on('InsertEnter', (bufnr: number) => { + let buf = this.buffers.getItem(bufnr) + if (buf) buf.cancel() + }, null, this.disposables) + } + + public get functionUpdate(): boolean { + let config = workspace.getConfiguration('coc.preferences') + return config.get('currentFunctionSymbolAutoUpdate', false) + } + + public get labels(): { [key: string]: string } { + return workspace.getConfiguration('suggest').get('completionItemKindLabels', {}) + } + + public async getWorkspaceSymbols(input: string): Promise { + this.handler.checkProvier('workspaceSymbols', null) + let tokenSource = new CancellationTokenSource() + return await languages.getWorkspaceSymbols(input, tokenSource.token) + } + + public async resolveWorkspaceSymbol(symbolInfo: SymbolInformation): Promise { + if (symbolInfo.location?.uri) return symbolInfo + let tokenSource = new CancellationTokenSource() + return await languages.resolveWorkspaceSymbol(symbolInfo, tokenSource.token) + } + + public async getDocumentSymbols(bufnr: number): Promise { + let buf = this.buffers.getItem(bufnr) + if (!buf) return + let res = await buf.getSymbols() + return res ? convertSymbols(res) : undefined + } + + public async getCurrentFunctionSymbol(bufnr?: number): Promise { + if (!bufnr) bufnr = await this.nvim.call('bufnr', ['%']) + let doc = workspace.getDocument(bufnr) + if (!doc || !doc.attached) return + if (!languages.hasProvider('documentSymbol', doc.textDocument)) return + let position = await window.getCursorPosition() + let symbols = await this.getDocumentSymbols(bufnr) + let buffer = this.nvim.createBuffer(bufnr) + 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', + 'Struct', + ].includes(s.kind)) + let functionName = '' + for (let sym of symbols.reverse()) { + if (sym.range + && 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 + } + } + if (this.functionUpdate) { + buffer.setVar('coc_current_function', functionName, true) + this.nvim.call('coc#util#do_autocmd', ['CocStatusChange'], true) + } + return functionName + } + + /* + * supportedSymbols must be string values of symbolKind + */ + public async selectSymbolRange(inner: boolean, visualmode: string, supportedSymbols: string[]): Promise { + let { doc } = await this.handler.getCurrentState() + this.handler.checkProvier('documentSymbol', doc.textDocument) + let range: Range + if (visualmode) { + range = await workspace.getSelectedRange(visualmode, doc) + } else { + let pos = await window.getCursorPosition() + range = Range.create(pos, pos) + } + let symbols = await this.getDocumentSymbols(doc.bufnr) + if (!symbols || symbols.length === 0) { + window.showMessage('No symbols found', 'warning') + return + } + symbols = symbols.filter(s => supportedSymbols.includes(s.kind)) + let selectRange: Range + for (let sym of symbols.reverse()) { + if (sym.range && !equals(sym.range, range) && 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 = Range.create(start.line + 1, line.match(/^\s*/)[0].length, end.line - 1, endLine.length) + } + if (selectRange) { + await workspace.selectRange(selectRange) + } else if (['v', 'V', '\x16'].includes(visualmode)) { + await this.nvim.command('normal! gv') + } + } + + public async showOutline(keep?: number): Promise { + await this.outline.show(keep) + } + + public async hideOutline(): Promise { + await this.outline.hide() + } + + public hasOutline(bufnr: number): boolean { + return this.outline.has(bufnr) + } + + public dispose(): void { + this.outline.dispose() + this.buffers.dispose() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/symbols/outline.ts b/vim-config/plugins/coc.nvim/src/handler/symbols/outline.ts new file mode 100644 index 00000000..3f8b8aee --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/symbols/outline.ts @@ -0,0 +1,319 @@ +import { Neovim } from '@chemzqm/neovim' +import debounce from 'debounce' +import { CodeActionKind, Disposable, DocumentSymbol, Range, SymbolKind, SymbolTag } from 'vscode-languageserver-protocol' +import events from '../../events' +import languages from '../../languages' +import BufferSync from '../../model/bufferSync' +import BasicDataProvider, { TreeNode } from '../../tree/BasicDataProvider' +import BasicTreeView from '../../tree/TreeView' +import { ConfigurationChangeEvent, HandlerDelegate } from '../../types' +import { disposeAll } from '../../util' +import { comparePosition, positionInRange } from '../../util/position' +import window from '../../window' +import workspace from '../../workspace' +import SymbolsBuffer from './buffer' +const logger = require('../../util/logger')('symbols-outline') + +// Support expand level. +interface OutlineNode extends TreeNode { + kind: SymbolKind + range: Range + selectRange: Range +} + +interface OutlineConfig { + splitCommand: string + followCursor: boolean + keepWindow: boolean + expandLevel: number + checkBufferSwitch: boolean + showLineNumber: boolean + codeActionKinds: CodeActionKind[] + sortBy: 'position' | 'name' | 'category' +} + +/** + * Manage TreeViews and Providers of outline. + */ +export default class SymbolsOutline { + private providersMap: Map> = new Map() + private treeViews: WeakMap, BasicTreeView[]> = new WeakMap() + private originalWins: WeakMap, number> = new WeakMap() + private config: OutlineConfig + private disposables: Disposable[] = [] + constructor( + private nvim: Neovim, + private buffers: BufferSync, + private handler: HandlerDelegate + ) { + this.loadConfiguration() + workspace.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables) + events.on('BufUnload', async bufnr => { + let provider = this.providersMap.get(bufnr) + if (!provider) return + this.providersMap.delete(bufnr) + provider.dispose() + let views = this.treeViews.get(provider) + this.treeViews.delete(provider) + for (let view of views) { + if (!view.visible) continue + let winid = this.originalWins.get(view) + if (winid && this.config.checkBufferSwitch) { + // check if original window exists + let nr = await nvim.call('win_id2win', [winid]) + if (nr) { + let win = nvim.createWindow(view.windowId) + // buffer could be recreated. + win.setVar('target_bufnr', -1, true) + let timer = setTimeout(() => { + if (view.visible) view.dispose() + }, 200) + this.disposables.push({ + dispose: () => { + clearTimeout(timer) + } + }) + continue + } + } + view.dispose() + } + }, null, this.disposables) + events.on('BufEnter', debounce(() => { + void this._onBufEnter() + }, global.hasOwnProperty('__TEST__') ? 100 : 300), null, this.disposables) + events.on('CursorHold', async bufnr => { + if (!this.config.followCursor) return + let provider = this.providersMap.get(bufnr) + if (!provider) return + let views = this.treeViews.get(provider) + if (!views || !views.length) return + let winid = await this.nvim.call('coc#window#find', ['cocViewId', 'OUTLINE']) + if (winid == -1) return + let view = views.find(o => o.windowId == winid) + if (!view) return + let pos = await window.getCursorPosition() + let curr: OutlineNode + let checkNode = (node: OutlineNode): boolean => { + if (positionInRange(pos, node.range) != 0) return false + curr = node + if (Array.isArray(node.children)) { + for (let n of node.children) { + if (checkNode(n)) break + } + } + return true + } + let nodes = await Promise.resolve(provider.getChildren()) + for (let n of nodes) { + if (checkNode(n)) break + } + if (curr) await view.reveal(curr) + }, null, this.disposables) + } + + private async _onBufEnter(): Promise { + if (!this.config.checkBufferSwitch) return + let [curr, bufnr, winid] = await this.nvim.eval(`[win_getid(),bufnr('%'),coc#window#find('cocViewId', 'OUTLINE')]`) as [number, number, number] + if (curr == winid || winid == -1) return + if (!this.buffers.getItem(bufnr)) return + let win = this.nvim.createWindow(winid) + let target = await win.getVar('target_bufnr') + if (target == bufnr) return + await this.show(1) + } + + private loadConfiguration(e?: ConfigurationChangeEvent): void { + if (!e || e.affectsConfiguration('outline')) { + let c = workspace.getConfiguration('outline') + this.config = { + splitCommand: c.get('splitCommand'), + followCursor: c.get('followCursor'), + keepWindow: c.get('keepWindow'), + expandLevel: c.get('expandLevel'), + checkBufferSwitch: c.get('checkBufferSwitch'), + sortBy: c.get<'position' | 'name' | 'category'>('sortBy'), + showLineNumber: c.get('showLineNumber'), + codeActionKinds: c.get('codeActionKinds') + } + } + } + + private convertSymbolToNode(documentSymbol: DocumentSymbol, sortFn: (a: OutlineNode, b: OutlineNode) => number): OutlineNode { + return { + label: documentSymbol.name, + tooltip: documentSymbol.detail, + description: this.config.showLineNumber ? `${documentSymbol.selectionRange.start.line + 1}` : undefined, + icon: this.handler.getIcon(documentSymbol.kind), + deprecated: documentSymbol.tags?.includes(SymbolTag.Deprecated), + kind: documentSymbol.kind, + range: documentSymbol.range, + selectRange: documentSymbol.selectionRange, + children: Array.isArray(documentSymbol.children) ? documentSymbol.children.map(o => { + return this.convertSymbolToNode(o, sortFn) + }).sort(sortFn) : undefined + } + } + + private setMessage(provider: BasicDataProvider, msg: string | undefined): void { + let views = this.treeViews.get(provider) + if (views) { + views.forEach(view => { + view.message = msg + }) + } + } + + private createProvider(buf: SymbolsBuffer): BasicDataProvider { + let { bufnr } = buf + let { sortBy } = this.config + let { nvim } = this + let sortFn = (a: OutlineNode, b: OutlineNode): number => { + if (sortBy === 'name') { + return a.label < b.label ? -1 : 1 + } + if (sortBy === 'category') { + if (a.kind == b.kind) return a.label < b.label ? -1 : 1 + return a.kind - b.kind + } + return comparePosition(a.selectRange.start, b.selectRange.start) + } + let convertSymbols = (symbols: DocumentSymbol[]): OutlineNode[] => { + return symbols.map(s => this.convertSymbolToNode(s, sortFn)).sort(sortFn) + } + let disposable: Disposable + let provider = new BasicDataProvider({ + expandLevel: this.config.expandLevel, + provideData: async () => { + let doc = workspace.getDocument(bufnr) + if (!languages.hasProvider('documentSymbol', doc.textDocument)) { + throw new Error('Document symbol provider not found') + } + this.setMessage(provider, 'Loading document symbols') + let arr = await buf.getSymbols() + if (!arr || arr.length == 0) { + // server may return empty symbols on buffer initialize, throw error to force reload. + throw new Error('Empty symbols returned from language server. ') + } + disposable = buf.onDidUpdate(symbols => { + provider.update(convertSymbols(symbols)) + }) + this.setMessage(provider, undefined) + return convertSymbols(arr) + }, + handleClick: async item => { + let winnr = await nvim.call('bufwinnr', [bufnr]) + if (winnr == -1) return + nvim.pauseNotification() + nvim.command(`${winnr}wincmd w`, true) + let pos = item.selectRange.start + nvim.call('coc#cursor#move_to', [pos.line, pos.character], true) + nvim.command(`normal! zz`, true) + let buf = nvim.createBuffer(bufnr) + buf.highlightRanges('outline-hover', 'CocHoverRange', [item.selectRange]) + nvim.command('redraw', true) + await nvim.resumeNotification() + setTimeout(() => { + buf.clearNamespace('outline-hover') + nvim.command('redraw', true) + }, global.hasOwnProperty('__TEST__') ? 10 : 300) + }, + resolveActions: async (_, element) => { + let winnr = await nvim.call('bufwinnr', [bufnr]) + if (winnr == -1) return + let doc = workspace.getDocument(bufnr) + let actions = await this.handler.getCodeActions(doc, element.range, this.config.codeActionKinds) + let arr = actions.map(o => { + return { + title: o.title, + handler: async () => { + let position = element.range.start + await nvim.command(`${winnr}wincmd w`) + await this.nvim.call('coc#cursor#move_to', [position.line, position.character]) + await this.handler.applyCodeAction(o) + } + } + }) + return [...arr, { + title: 'Visual Select', + handler: async item => { + await nvim.command(`${winnr}wincmd w`) + await workspace.selectRange(item.range) + } + }] + }, + onDispose: () => { + this.providersMap.delete(buf.bufnr) + if (disposable) disposable.dispose() + } + }) + return provider + } + + /** + * Create outline view. + */ + public async show(keep?: number): Promise { + await workspace.document + let [bufnr, winid] = await this.nvim.eval('[bufnr("%"),win_getid()]') as [number, number] + let buf = this.buffers.getItem(bufnr) + if (!buf) throw new Error('Document not attached') + let provider = this.providersMap.get(bufnr) + if (!provider) { + provider = this.createProvider(buf) + this.providersMap.set(bufnr, provider) + } + let treeView = new BasicTreeView('OUTLINE', { + enableFilter: true, + treeDataProvider: provider, + }) + this.originalWins.set(treeView, winid) + let arr = this.treeViews.get(provider) || [] + arr.push(treeView) + this.treeViews.set(provider, arr) + treeView.onDidChangeVisibility(({ visible }) => { + if (visible || !this.treeViews.has(provider)) return + let arr = this.treeViews.get(provider) || [] + arr = arr.filter(s => s !== treeView) + this.originalWins.delete(treeView) + if (arr.length) { + this.treeViews.set(provider, arr) + return + } + provider.dispose() + this.treeViews.delete(provider) + }) + await treeView.show(this.config.splitCommand) + if (treeView.windowId) { + let win = this.nvim.createWindow(treeView.windowId) + win.setVar('target_bufnr', bufnr, true) + } + if (keep == 1 || (keep === undefined && this.config.keepWindow)) { + await this.nvim.command('wincmd p') + } + } + + public has(bufnr: number): boolean { + return this.providersMap.has(bufnr) + } + + /** + * Hide outline of current tab. + */ + public async hide(): Promise { + let winid = await this.nvim.call('coc#window#find', ['cocViewId', 'OUTLINE']) as number + if (winid == -1) return + await this.nvim.call('coc#window#close', [winid]) + } + + public dispose(): void { + for (let provider of this.providersMap.values()) { + provider.dispose() + for (let view of this.treeViews.get(provider)) { + view.dispose() + } + } + this.providersMap.clear() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/handler/symbols/util.ts b/vim-config/plugins/coc.nvim/src/handler/symbols/util.ts new file mode 100644 index 00000000..d5f03bec --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/handler/symbols/util.ts @@ -0,0 +1,57 @@ +import { DocumentSymbol, Range, SymbolInformation } from 'vscode-languageserver-protocol' +import { getSymbolKind } from '../../util/convert' +import { comparePosition } from '../../util/position' + +export interface SymbolInfo { + filepath?: string + lnum: number + col: number + text: string + kind: string + level?: number + containerName?: string + range: Range + selectionRange?: Range +} + +export function convertSymbols(symbols: DocumentSymbol[]): SymbolInfo[] { + let res: SymbolInfo[] = [] + let arr = symbols.slice() + arr.sort(sortDocumentSymbols) + arr.forEach(s => addDocumentSymbol(res, s, 0)) + return res +} + +export function sortDocumentSymbols(a: DocumentSymbol, b: DocumentSymbol): number { + let ra = a.selectionRange + let rb = b.selectionRange + return comparePosition(ra.start, rb.start) +} + +export function addDocumentSymbol(res: SymbolInfo[], sym: DocumentSymbol, level: number): void { + let { name, selectionRange, kind, children, range } = sym + let { start } = selectionRange || range + res.push({ + col: start.character + 1, + lnum: start.line + 1, + text: name, + level, + kind: getSymbolKind(kind), + range, + selectionRange + }) + if (children && children.length) { + children.sort(sortDocumentSymbols) + for (let sym of children) { + addDocumentSymbol(res, sym, level + 1) + } + } +} + +function isDocumentSymbol(a: DocumentSymbol | SymbolInformation): a is DocumentSymbol { + return a && !a.hasOwnProperty('location') +} + +export function isDocumentSymbols(a: DocumentSymbol[] | SymbolInformation[]): a is DocumentSymbol[] { + return isDocumentSymbol(a[0]) +} diff --git a/vim-config/plugins/coc.nvim/src/index.ts b/vim-config/plugins/coc.nvim/src/index.ts new file mode 100644 index 00000000..96525e19 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/index.ts @@ -0,0 +1,72 @@ +import commands from './commands' +import events from './events' +import languages from './languages' +import Mru from './model/mru' +import FloatFactory from './model/floatFactory' +import fetch from './model/fetch' +import download from './model/download' +import Highligher from './model/highligher' +import services from './services' +import sources from './sources/index' +import workspace from './workspace' +import window from './window' +import extensions from './extensions' +import listManager from './list/manager' +import snippetManager from './snippets/manager' +import { SnippetString } from './snippets/string' +import diagnosticManager from './diagnostic/manager' +import { ansiparse } from './util/ansiparse' +import Watchman from './watchman' +import BasicList from './list/basic' +import { Mutex } from './util/mutex' +import { URI } from 'vscode-uri' +import { Neovim, Buffer, Window } from '@chemzqm/neovim' +import { + CodeActionKind, + Disposable, + Position, + Range, + TextEdit, + RequestType, + RequestType0, + NotificationType, + NotificationType0, + Event, + CancellationToken, + CancellationTokenSource, + Emitter, + Diagnostic, + DiagnosticSeverity, + CompletionItemKind, + InsertTextFormat, + Location, + LocationLink, + MarkupKind, + FileChangeType, + SignatureHelpTriggerKind, + SymbolKind, + DocumentHighlightKind, + CompletionTriggerKind, + DiagnosticTag, + ProgressType, +} from 'vscode-languageserver-protocol' + +export { PatternType, SourceType, MessageLevel, ConfigurationTarget, ServiceStat, FileType } from './types' +export { + State, + NullLogger, + ClientState, + CloseAction, + ErrorAction, + TransportKind, + SettingMonitor, + LanguageClient, + MessageTransports, + TextDocumentFeature, + RevealOutputChannelOn, +} from './language-client' + +export { Neovim, MarkupKind, DiagnosticTag, DocumentHighlightKind, SymbolKind, SignatureHelpTriggerKind, FileChangeType, CodeActionKind, Diagnostic, DiagnosticSeverity, CompletionItemKind, InsertTextFormat, Location, LocationLink, CancellationTokenSource, CancellationToken, ProgressType, Position, Range, TextEdit, RequestType, RequestType0, NotificationType, NotificationType0, Buffer, Window, Highligher, Mru, Watchman, URI as Uri, Disposable, Event, Emitter, FloatFactory, fetch, download, ansiparse } +export { workspace, window, CompletionTriggerKind, snippetManager, SnippetString, events, services, commands, sources, languages, diagnosticManager, extensions, listManager, BasicList, Mutex } +export { disposeAll, concurrent, watchFile, wait, runCommand, isRunning, executable } from './util' +export { TreeItem, TreeItemCollapsibleState } from './tree/index' diff --git a/vim-config/plugins/coc.nvim/src/language-client/LICENSE.txt b/vim-config/plugins/coc.nvim/src/language-client/LICENSE.txt new file mode 100644 index 00000000..9afc63d4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/LICENSE.txt @@ -0,0 +1,23 @@ +MIT License + +Copyright (c) 2015 - present Microsoft Corporation + +All rights reserved. + +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. diff --git a/vim-config/plugins/coc.nvim/src/language-client/callHierarchy.ts b/vim-config/plugins/coc.nvim/src/language-client/callHierarchy.ts new file mode 100644 index 00000000..92199de8 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/callHierarchy.ts @@ -0,0 +1,122 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { + CallHierarchyClientCapabilities, CallHierarchyIncomingCall, CallHierarchyIncomingCallsRequest, CallHierarchyItem, CallHierarchyOptions, CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsRequest, CallHierarchyPrepareRequest, CallHierarchyRegistrationOptions, CancellationToken, ClientCapabilities, Disposable, DocumentSelector, Position, ServerCapabilities +} from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { CallHierarchyProvider, ProviderResult } from '../provider' +import { BaseLanguageClient, TextDocumentFeature } from './client' +import { asTextDocumentPositionParams } from './utils/converter' + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export interface PrepareCallHierarchySignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult +} + +export interface CallHierarchyIncomingCallsSignature { + (this: void, item: CallHierarchyItem, token: CancellationToken): ProviderResult +} + +export interface CallHierarchyOutgoingCallsSignature { + (this: void, item: CallHierarchyItem, token: CancellationToken): ProviderResult +} + +/** + * Call hierarchy middleware + * + * @since 3.16.0 + */ +export interface CallHierarchyMiddleware { + prepareCallHierarchy?: (this: void, document: TextDocument, positions: Position, token: CancellationToken, next: PrepareCallHierarchySignature) => ProviderResult + provideCallHierarchyIncomingCalls?: (this: void, item: CallHierarchyItem, token: CancellationToken, next: CallHierarchyIncomingCallsSignature) => ProviderResult + provideCallHierarchyOutgoingCalls?: (this: void, item: CallHierarchyItem, token: CancellationToken, next: CallHierarchyOutgoingCallsSignature) => ProviderResult +} + +export class CallHierarchyFeature extends TextDocumentFeature { + constructor(client: BaseLanguageClient) { + super(client, CallHierarchyPrepareRequest.type) + } + + public fillClientCapabilities(cap: ClientCapabilities): void { + const capabilities: ClientCapabilities & CallHierarchyClientCapabilities = cap as ClientCapabilities & CallHierarchyClientCapabilities + const capability = ensure(ensure(capabilities, 'textDocument')!, 'callHierarchy')! + capability.dynamicRegistration = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + const [id, options] = this.getRegistration(documentSelector, capabilities.callHierarchyProvider) + if (!id || !options) { + return + } + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider(options: CallHierarchyRegistrationOptions): [Disposable, CallHierarchyProvider] { + const provider: CallHierarchyProvider = { + prepareCallHierarchy: (document: TextDocument, position: Position, token: CancellationToken) => { + const client = this._client + const prepareCallHierarchy: PrepareCallHierarchySignature = (document, position, token) => { + const params = asTextDocumentPositionParams(document, position) + return client.sendRequest(CallHierarchyPrepareRequest.type, params, token).then( + res => res, + error => { + return client.handleFailedRequest(CallHierarchyPrepareRequest.type, token, error, null) + } + ) + } + + const middleware = client.clientOptions.middleware + return middleware.prepareCallHierarchy + ? middleware.prepareCallHierarchy(document, position, token, prepareCallHierarchy) + : prepareCallHierarchy(document, position, token) + }, + + provideCallHierarchyIncomingCalls: (item: CallHierarchyItem, token: CancellationToken) => { + const client = this._client + const provideCallHierarchyIncomingCalls: CallHierarchyIncomingCallsSignature = (item, token) => { + return client.sendRequest(CallHierarchyIncomingCallsRequest.type, { item }, token).then( + res => res, + error => { + return client.handleFailedRequest(CallHierarchyIncomingCallsRequest.type, token, error, null) + } + ) + } + + const middleware = client.clientOptions.middleware + return middleware.provideCallHierarchyIncomingCalls + ? middleware.provideCallHierarchyIncomingCalls(item, token, provideCallHierarchyIncomingCalls) + : provideCallHierarchyIncomingCalls(item, token) + }, + + provideCallHierarchyOutgoingCalls: (item: CallHierarchyItem, token: CancellationToken) => { + const client = this._client + const provideCallHierarchyOutgoingCalls: CallHierarchyOutgoingCallsSignature = (item, token) => { + return client.sendRequest(CallHierarchyOutgoingCallsRequest.type, { item }, token).then( + res => res, + error => { + return client.handleFailedRequest(CallHierarchyOutgoingCallsRequest.type, token, error, null) + } + ) + } + + const middleware = client.clientOptions.middleware + return middleware.provideCallHierarchyOutgoingCalls + ? middleware.provideCallHierarchyOutgoingCalls(item, token, provideCallHierarchyOutgoingCalls) + : provideCallHierarchyOutgoingCalls(item, token) + } + } + + return [languages.registerCallHierarchyProvider(options.documentSelector, provider), provider] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/client.ts b/vim-config/plugins/coc.nvim/src/language-client/client.ts new file mode 100644 index 00000000..1b7d0d21 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/client.ts @@ -0,0 +1,4352 @@ +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +/* eslint-disable */ +import path from 'path' +import { ApplyWorkspaceEditParams, CompletionItemTag, ApplyWorkspaceEditRequest, ApplyWorkspaceEditResponse, CancellationToken, ClientCapabilities, CodeAction, CodeActionContext, CodeActionKind, CodeActionOptions, CodeActionParams, CodeActionRegistrationOptions, CodeActionRequest, CodeLens, CodeLensOptions, CodeLensRegistrationOptions, CodeLensRequest, CodeLensResolveRequest, Command, CompletionContext, CompletionItem, CompletionItemKind, CompletionList, CompletionOptions, CompletionRegistrationOptions, CompletionRequest, CompletionResolveRequest, createProtocolConnection, DeclarationRequest, Definition, DefinitionOptions, DefinitionRegistrationOptions, DefinitionRequest, Diagnostic, DiagnosticSeverity, DiagnosticTag, DidChangeConfigurationNotification, DidChangeConfigurationParams, DidChangeConfigurationRegistrationOptions, DidChangeTextDocumentNotification, DidChangeTextDocumentParams, DidChangeWatchedFilesNotification, DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, DidCloseTextDocumentNotification, DidCloseTextDocumentParams, DidOpenTextDocumentNotification, DidOpenTextDocumentParams, DidSaveTextDocumentNotification, DidSaveTextDocumentParams, Disposable, DocumentColorRequest, DocumentFormattingOptions, DocumentFormattingParams, DocumentFormattingRequest, DocumentHighlight, DocumentHighlightOptions, DocumentHighlightRegistrationOptions, DocumentHighlightRequest, DocumentLink, DocumentLinkOptions, DocumentLinkRegistrationOptions, DocumentLinkRequest, DocumentLinkResolveRequest, DocumentOnTypeFormattingOptions, DocumentOnTypeFormattingParams, DocumentOnTypeFormattingRegistrationOptions, DocumentOnTypeFormattingRequest, DocumentRangeFormattingOptions, DocumentRangeFormattingParams, DocumentRangeFormattingRegistrationOptions, DocumentRangeFormattingRequest, DocumentSelector, DocumentSymbol, DocumentSymbolOptions, DocumentSymbolRegistrationOptions, DocumentSymbolRequest, Emitter, Event, ExecuteCommandParams, ExecuteCommandRegistrationOptions, ExecuteCommandRequest, ExitNotification, FailureHandlingKind, FileChangeType, FileEvent, FoldingRangeRequest, FormattingOptions, GenericNotificationHandler, GenericRequestHandler, Hover, HoverOptions, HoverRegistrationOptions, HoverRequest, ImplementationRequest, InitializedNotification, InitializeError, InitializeParams, InitializeRequest, InitializeResult, Location, Logger, LogMessageNotification, LogMessageParams, MarkupKind, Message, MessageReader, MessageType, MessageWriter, NotificationHandler, NotificationHandler0, NotificationType, NotificationType0, Position, PrepareRenameRequest, ProgressToken, ProgressType, PublishDiagnosticsNotification, PublishDiagnosticsParams, Range, ReferenceOptions, ReferenceRegistrationOptions, ReferencesRequest, RegistrationParams, RegistrationRequest, RenameOptions, RenameParams, RenameRegistrationOptions, RenameRequest, RequestHandler, RequestHandler0, RequestType, RequestType0, ResourceOperationKind, ResponseError, SelectionRangeRequest, ServerCapabilities, ShowMessageNotification, ShowMessageParams, ShowMessageRequest, ShutdownRequest, SignatureHelp, SignatureHelpOptions, SignatureHelpRegistrationOptions, SignatureHelpRequest, StaticRegistrationOptions, SymbolInformation, SymbolKind, SymbolTag, TelemetryEventNotification, TextDocumentChangeRegistrationOptions, TextDocumentEdit, TextDocumentPositionParams, TextDocumentRegistrationOptions, TextDocumentSaveRegistrationOptions, TextDocumentSyncKind, TextDocumentSyncOptions, TextEdit, Trace, TraceFormat, TraceOptions, Tracer, TypeDefinitionRequest, UnregistrationParams, UnregistrationRequest, WatchKind, WillSaveTextDocumentNotification, WillSaveTextDocumentParams, WillSaveTextDocumentWaitUntilRequest, WorkDoneProgressOptions, WorkspaceEdit, WorkspaceFolder, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolRequest, SignatureHelpContext, WorkDoneProgressBegin, WorkDoneProgressEnd, WorkDoneProgressReport, WorkDoneProgress, DefinitionLink, ProtocolRequestType0, ProtocolRequestType, MessageSignature, ProtocolNotificationType0, ProtocolNotificationType, RegistrationType, LSPErrorCodes, SaveOptions, CancellationStrategy, CallHierarchyPrepareRequest, SemanticTokensRegistrationType, CodeActionResolveRequest, CodeLensRefreshRequest, ShowDocumentParams, ShowDocumentRequest, ShowDocumentResult, InsertTextMode, LinkedEditingRangeRequest, DidCreateFilesNotification, FileOperationRegistrationOptions, DidRenameFilesNotification, DidDeleteFilesNotification, WillCreateFilesRequest, WillRenameFilesRequest, WillDeleteFilesRequest } from 'vscode-languageserver-protocol' +import { TextDocument } from "vscode-languageserver-textdocument" +import { URI } from 'vscode-uri' +import commands from '../commands' +import languages from '../languages' +import FileWatcher from '../model/fileSystemWatcher' +import { CallHierarchyProvider, CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentLinkProvider, DocumentRangeFormattingEditProvider, DocumentSymbolProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, LinkedEditingRangeProvider, OnTypeFormattingEditProvider, ProviderResult, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, WorkspaceSymbolProvider } from '../provider' +import { FileCreateEvent, FileDeleteEvent, FileRenameEvent, FileWillCreateEvent, FileWillDeleteEvent, FileWillRenameEvent, OutputChannel, TextDocumentWillSaveEvent, Thenable } from '../types' +import { resolveRoot } from '../util/fs' +import * as Is from '../util/is' +import { omit } from '../util/lodash' +import DiagnosticCollection from '../diagnostic/collection' +import window, { MessageItem } from '../window' +import workspace from '../workspace' +import sources from '../sources' +import { CallHierarchyMiddleware } from './callHierarchy' +import { ColorProviderMiddleware } from './colorProvider' +import { ConfigurationWorkspaceMiddleware } from './configuration' +import { DeclarationMiddleware } from './declaration' +import { FoldingRangeProviderMiddleware } from './foldingRange' +import { ImplementationMiddleware } from './implementation' +import { ProgressPart } from './progressPart' +import { SelectionRangeProviderMiddleware } from './selectionRange' +import { SemanticTokensMiddleware, SemanticTokensProviders } from './semanticTokens' +import { TypeDefinitionMiddleware } from './typeDefinition' +import { FileOperationsMiddleware } from './fileOperations' +import { Delayer } from './utils/async' +import os from 'os' +import * as cv from './utils/converter' +import * as UUID from './utils/uuid' +import { WorkspaceFolderWorkspaceMiddleware } from './workspaceFolders' +import { LinkedEditingRangeMiddleware } from './linkedEditingRange' + +const logger = require('../util/logger')('language-client-client') + +interface IConnection { + listen(): void + + sendRequest(type: ProtocolRequestType0, token?: CancellationToken): Promise + sendRequest(type: ProtocolRequestType, params: P, token?: CancellationToken): Promise + sendRequest(type: RequestType0, token?: CancellationToken): Promise + sendRequest(type: RequestType, params: P, token?: CancellationToken): Promise + sendRequest(method: string, token?: CancellationToken): Promise + sendRequest(method: string, param: any, token?: CancellationToken): Promise + sendRequest(type: string | MessageSignature, ...params: any[]): Promise + + onRequest(type: ProtocolRequestType0, handler: RequestHandler0): Disposable + onRequest(type: ProtocolRequestType, handler: RequestHandler): Disposable + onRequest(type: RequestType0, handler: RequestHandler0): Disposable + onRequest(type: RequestType, handler: RequestHandler): Disposable + onRequest(method: string, handler: GenericRequestHandler): Disposable + onRequest(method: string | MessageSignature, handler: GenericRequestHandler): Disposable + + sendNotification(type: ProtocolNotificationType0): void + sendNotification(type: ProtocolNotificationType, params?: P): void + sendNotification(type: NotificationType0): void + sendNotification

    (type: NotificationType

    , params?: P): void + sendNotification(method: string): void + sendNotification(method: string, params: any): void + sendNotification(method: string | MessageSignature, params?: any): void + + onNotification(type: ProtocolNotificationType0, handler: NotificationHandler0): Disposable + onNotification(type: ProtocolNotificationType, handler: NotificationHandler

    ): Disposable + onNotification(type: NotificationType0, handler: NotificationHandler0): Disposable + onNotification

    (type: NotificationType

    , handler: NotificationHandler

    ): Disposable + onNotification(method: string, handler: GenericNotificationHandler): Disposable + onNotification(method: string | MessageSignature, handler: GenericNotificationHandler): Disposable + + onProgress

    (type: ProgressType

    , token: string | number, handler: NotificationHandler

    ): Disposable + sendProgress

    (type: ProgressType

    , token: string | number, value: P): void + + trace(value: Trace, tracer: Tracer, sendNotification?: boolean): void + trace(value: Trace, tracer: Tracer, traceOptions?: TraceOptions): void + + initialize(params: InitializeParams): Promise + shutdown(): Promise + exit(): void + + onLogMessage(handle: NotificationHandler): void + onShowMessage(handler: NotificationHandler): void + onTelemetry(handler: NotificationHandler): void + + didChangeConfiguration(params: DidChangeConfigurationParams): void + didChangeWatchedFiles(params: DidChangeWatchedFilesParams): void + + didOpenTextDocument(params: DidOpenTextDocumentParams): void + didChangeTextDocument(params: DidChangeTextDocumentParams): void + didCloseTextDocument(params: DidCloseTextDocumentParams): void + didSaveTextDocument(params: DidSaveTextDocumentParams): void + onDiagnostics(handler: NotificationHandler): void + + dispose(): void +} + +class ConsoleLogger implements Logger { + public error(message: string): void { + logger.error(message) + } + public warn(message: string): void { + logger.warn(message) + } + public info(message: string): void { + logger.info(message) + } + public log(message: string): void { + logger.log(message) + } +} + +export class NullLogger implements Logger { + error(_message: string): void { + } + warn(_message: string): void { + } + info(_message: string): void { + } + log(_message: string): void { + } +} + +interface ConnectionErrorHandler { + (error: Error, message: Message | undefined, count: number | undefined): void +} + +interface ConnectionCloseHandler { + (): void +} + +interface ConnectionOptions { + cancellationStrategy: CancellationStrategy + maxRestartCount?: number +} + +function createConnection( + inputStream: NodeJS.ReadableStream, + outputStream: NodeJS.WritableStream, + errorHandler: ConnectionErrorHandler, + closeHandler: ConnectionCloseHandler, + options?: ConnectionOptions +): IConnection +function createConnection( + reader: MessageReader, + writer: MessageWriter, + errorHandler: ConnectionErrorHandler, + closeHandler: ConnectionCloseHandler, + options?: ConnectionOptions +): IConnection +function createConnection( + input: any, + output: any, + errorHandler: ConnectionErrorHandler, + closeHandler: ConnectionCloseHandler, + options?: ConnectionOptions +): IConnection { + let logger = new ConsoleLogger() + let connection = createProtocolConnection(input, output, logger, options) + connection.onError(data => { + errorHandler(data[0], data[1], data[2]) + }) + connection.onClose(closeHandler) + let result: IConnection = { + listen: (): void => connection.listen(), + + sendRequest: (type: string | MessageSignature, ...params: any[]): Promise => connection.sendRequest(Is.string(type) ? type : type.method, ...params), + onRequest: (type: string | MessageSignature, handler: GenericRequestHandler): Disposable => connection.onRequest(Is.string(type) ? type : type.method, handler), + + sendNotification: (type: string | MessageSignature, params?: any): void => connection.sendNotification(Is.string(type) ? type : type.method, params), + onNotification: (type: string | MessageSignature, handler: GenericNotificationHandler): Disposable => connection.onNotification(Is.string(type) ? type : type.method, handler), + + onProgress: connection.onProgress, + sendProgress: connection.sendProgress, + + trace: ( + value: Trace, + tracer: Tracer, + sendNotificationOrTraceOptions?: boolean | TraceOptions + ): void => { + const defaultTraceOptions: TraceOptions = { + sendNotification: false, + traceFormat: TraceFormat.Text + } + + if (sendNotificationOrTraceOptions === undefined) { + connection.trace(value, tracer, defaultTraceOptions) + } else if (Is.boolean(sendNotificationOrTraceOptions)) { + connection.trace(value, tracer, sendNotificationOrTraceOptions) + } else { + connection.trace(value, tracer, sendNotificationOrTraceOptions) + } + }, + + initialize: (params: InitializeParams) => + connection.sendRequest(InitializeRequest.type, params), + shutdown: () => connection.sendRequest(ShutdownRequest.type, undefined), + exit: () => connection.sendNotification(ExitNotification.type), + + onLogMessage: (handler: NotificationHandler) => + connection.onNotification(LogMessageNotification.type, handler), + onShowMessage: (handler: NotificationHandler) => + connection.onNotification(ShowMessageNotification.type, handler), + onTelemetry: (handler: NotificationHandler) => + connection.onNotification(TelemetryEventNotification.type, handler), + + didChangeConfiguration: (params: DidChangeConfigurationParams) => + connection.sendNotification( + DidChangeConfigurationNotification.type, + params + ), + didChangeWatchedFiles: (params: DidChangeWatchedFilesParams) => + connection.sendNotification( + DidChangeWatchedFilesNotification.type, + params + ), + + didOpenTextDocument: (params: DidOpenTextDocumentParams) => + connection.sendNotification(DidOpenTextDocumentNotification.type, params), + didChangeTextDocument: (params: DidChangeTextDocumentParams) => + connection.sendNotification( + DidChangeTextDocumentNotification.type, + params + ), + didCloseTextDocument: (params: DidCloseTextDocumentParams) => + connection.sendNotification( + DidCloseTextDocumentNotification.type, + params + ), + didSaveTextDocument: (params: DidSaveTextDocumentParams) => + connection.sendNotification(DidSaveTextDocumentNotification.type, params), + + onDiagnostics: (handler: NotificationHandler) => + connection.onNotification(PublishDiagnosticsNotification.type, handler), + + dispose: () => connection.dispose() + } + + return result +} + +/** + * An action to be performed when the connection is producing errors. + */ +export enum ErrorAction { + /** + * Continue running the server. + */ + Continue = 1, + /** + * Shutdown the server. + */ + Shutdown = 2 +} + +/** + * An action to be performed when the connection to a server got closed. + */ +export enum CloseAction { + /** + * Don't restart the server. The connection stays closed. + */ + DoNotRestart = 1, + /** + * Restart the server. + */ + Restart = 2 +} + +/** + * A plugable error handler that is invoked when the connection is either + * producing errors or got closed. + */ +export interface ErrorHandler { + /** + * An error has occurred while writing or reading from the connection. + * + * @param error - the error received + * @param message - the message to be delivered to the server if know. + * @param count - a count indicating how often an error is received. Will + * be reset if a message got successfully send or received. + */ + error(error: Error, message: Message | undefined, count: number | undefined): ErrorAction + + /** + * The connection to the server got closed. + */ + closed(): CloseAction +} + +class DefaultErrorHandler implements ErrorHandler { + private readonly restarts: number[] + + constructor(private name: string, private maxRestartCount: number) { + this.restarts = [] + } + + public error(_error: Error, _message: Message, count: number): ErrorAction { + if (count && count <= 3) { + return ErrorAction.Continue + } + return ErrorAction.Shutdown + } + public closed(): CloseAction { + this.restarts.push(Date.now()) + if (this.restarts.length < this.maxRestartCount) { + return CloseAction.Restart + } else { + let diff = this.restarts[this.restarts.length - 1] - this.restarts[0] + if (diff <= 3 * 60 * 1000) { + window.showMessage(`The "${this.name}" server crashed ${this.maxRestartCount} times in the last 3 minutes. The server will not be restarted.`, 'error') + return CloseAction.DoNotRestart + } else { + this.restarts.shift() + return CloseAction.Restart + } + } + } +} + +export interface InitializationFailedHandler { + (error: ResponseError | Error | any): boolean +} + +export interface SynchronizeOptions { + configurationSection?: string | string[] + fileEvents?: FileWatcher | FileWatcher[] +} + +export enum RevealOutputChannelOn { + Info = 1, + Warn = 2, + Error = 3, + Never = 4 +} + +export interface HandleWorkDoneProgressSignature { + (this: void, token: ProgressToken, params: WorkDoneProgressBegin | WorkDoneProgressReport | WorkDoneProgressEnd): void +} + +export interface HandleDiagnosticsSignature { + (this: void, uri: string, diagnostics: Diagnostic[]): void +} + +export interface ProvideCompletionItemsSignature { + ( + this: void, + document: TextDocument, + position: Position, + context: CompletionContext, + token: CancellationToken, + ): ProviderResult +} + +export interface ResolveCompletionItemSignature { + (this: void, item: CompletionItem, token: CancellationToken): ProviderResult +} + +export interface ProvideHoverSignature { + ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +export interface ProvideSignatureHelpSignature { + ( + this: void, + document: TextDocument, + position: Position, + context: SignatureHelpContext, + token: CancellationToken + ): ProviderResult +} + +export interface ProvideDefinitionSignature { + ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +export interface ProvideReferencesSignature { + ( + this: void, + document: TextDocument, + position: Position, + options: { includeDeclaration: boolean }, + token: CancellationToken + ): ProviderResult +} + +export interface ProvideDocumentHighlightsSignature { + ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +export interface ProvideDocumentSymbolsSignature { + (this: void, document: TextDocument, token: CancellationToken): ProviderResult +} + +export interface ProvideWorkspaceSymbolsSignature { + (this: void, query: string, token: CancellationToken): ProviderResult +} + +export interface ProvideCodeActionsSignature { + ( + this: void, + document: TextDocument, + range: Range, + context: CodeActionContext, + token: CancellationToken + ): ProviderResult<(Command | CodeAction)[]> +} + +export interface ResolveCodeActionSignature { + (this: void, item: CodeAction, token: CancellationToken): ProviderResult +} + +export interface ProvideCodeLensesSignature { + (this: void, document: TextDocument, token: CancellationToken): ProviderResult +} + +export interface ResolveCodeLensSignature { + (this: void, codeLens: CodeLens, token: CancellationToken): ProviderResult +} + +export interface ProvideDocumentFormattingEditsSignature { + ( + this: void, + document: TextDocument, + options: FormattingOptions, + token: CancellationToken + ): ProviderResult +} + +export interface ProvideDocumentRangeFormattingEditsSignature { + ( + this: void, + document: TextDocument, + range: Range, + options: FormattingOptions, + token: CancellationToken + ): ProviderResult +} + +export interface ProvideOnTypeFormattingEditsSignature { + ( + this: void, + document: TextDocument, + position: Position, + ch: string, + options: FormattingOptions, + token: CancellationToken + ): ProviderResult +} + +export interface PrepareRenameSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult +} + +export interface ProvideRenameEditsSignature { + ( + this: void, + document: TextDocument, + position: Position, + newName: string, + token: CancellationToken + ): ProviderResult +} + +export interface ProvideDocumentLinksSignature { + (this: void, document: TextDocument, token: CancellationToken): ProviderResult +} + +export interface ResolveDocumentLinkSignature { + (this: void, link: DocumentLink, token: CancellationToken): ProviderResult +} + +export interface ExecuteCommandSignature { + (this: void, command: string, args: any[]): ProviderResult +} + +export interface NextSignature { + (this: void, data: P, next: (data: P) => R): R +} + +export interface DidChangeConfigurationSignature { + (this: void, sections: string[] | undefined): void +} + +export interface DidChangeWatchedFileSignature { + (this: void, event: FileEvent): void +} + +export interface _WorkspaceMiddleware { + didChangeConfiguration?: ( + this: void, + sections: string[] | undefined, + next: DidChangeConfigurationSignature + ) => void + didChangeWatchedFile?: (this: void, event: FileEvent, next: DidChangeWatchedFileSignature) => void +} + +export type WorkspaceMiddleware = _WorkspaceMiddleware & ConfigurationWorkspaceMiddleware & WorkspaceFolderWorkspaceMiddleware & FileOperationsMiddleware + +export interface _WindowMiddleware { + showDocument?: (this: void, params: ShowDocumentParams, next: ShowDocumentRequest.HandlerSignature) => Promise +} + +export type WindowMiddleware = _WindowMiddleware + +/** + * The Middleware lets extensions intercept the request and notifications send and received + * from the server + */ +export interface _Middleware { + didOpen?: NextSignature + didChange?: NextSignature + willSave?: NextSignature + willSaveWaitUntil?: NextSignature< + TextDocumentWillSaveEvent, + Thenable + > + didSave?: NextSignature + didClose?: NextSignature + + handleDiagnostics?: ( + this: void, + uri: string, + diagnostics: Diagnostic[], + next: HandleDiagnosticsSignature + ) => void + provideCompletionItem?: ( + this: void, + document: TextDocument, + position: Position, + context: CompletionContext, + token: CancellationToken, + next: ProvideCompletionItemsSignature + ) => ProviderResult + resolveCompletionItem?: ( + this: void, + item: CompletionItem, + token: CancellationToken, + next: ResolveCompletionItemSignature + ) => ProviderResult + provideHover?: ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken, + next: ProvideHoverSignature + ) => ProviderResult + provideSignatureHelp?: ( + this: void, + document: TextDocument, + position: Position, + context: SignatureHelpContext, + token: CancellationToken, + next: ProvideSignatureHelpSignature + ) => ProviderResult + provideDefinition?: ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken, + next: ProvideDefinitionSignature + ) => ProviderResult + provideReferences?: ( + this: void, + document: TextDocument, + position: Position, + options: { includeDeclaration: boolean }, + token: CancellationToken, + next: ProvideReferencesSignature + ) => ProviderResult + provideDocumentHighlights?: ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken, + next: ProvideDocumentHighlightsSignature + ) => ProviderResult + provideDocumentSymbols?: ( + this: void, + document: TextDocument, + token: CancellationToken, + next: ProvideDocumentSymbolsSignature + ) => ProviderResult + provideWorkspaceSymbols?: ( + this: void, + query: string, + token: CancellationToken, + next: ProvideWorkspaceSymbolsSignature + ) => ProviderResult + provideCodeActions?: ( + this: void, + document: TextDocument, + range: Range, + context: CodeActionContext, + token: CancellationToken, + next: ProvideCodeActionsSignature + ) => ProviderResult<(Command | CodeAction)[]> + handleWorkDoneProgress?: ( + this: void, + token: ProgressToken, + params: WorkDoneProgressBegin | WorkDoneProgressReport | WorkDoneProgressEnd, next: HandleWorkDoneProgressSignature + ) => void + resolveCodeAction?: ( + this: void, + item: CodeAction, + token: CancellationToken, + next: ResolveCodeActionSignature + ) => ProviderResult + provideCodeLenses?: ( + this: void, + document: TextDocument, + token: CancellationToken, + next: ProvideCodeLensesSignature + ) => ProviderResult + resolveCodeLens?: ( + this: void, + codeLens: CodeLens, + token: CancellationToken, + next: ResolveCodeLensSignature + ) => ProviderResult + provideDocumentFormattingEdits?: ( + this: void, + document: TextDocument, + options: FormattingOptions, + token: CancellationToken, + next: ProvideDocumentFormattingEditsSignature + ) => ProviderResult + provideDocumentRangeFormattingEdits?: ( + this: void, + document: TextDocument, + range: Range, + options: FormattingOptions, + token: CancellationToken, + next: ProvideDocumentRangeFormattingEditsSignature + ) => ProviderResult + provideOnTypeFormattingEdits?: ( + this: void, + document: TextDocument, + position: Position, + ch: string, + options: FormattingOptions, + token: CancellationToken, + next: ProvideOnTypeFormattingEditsSignature + ) => ProviderResult + prepareRename?: ( + this: void, document: TextDocument, + position: Position, + token: CancellationToken, + next: PrepareRenameSignature + ) => ProviderResult + provideRenameEdits?: ( + this: void, + document: TextDocument, + position: Position, + newName: string, + token: CancellationToken, + next: ProvideRenameEditsSignature + ) => ProviderResult + provideDocumentLinks?: ( + this: void, + document: TextDocument, + token: CancellationToken, + next: ProvideDocumentLinksSignature + ) => ProviderResult + resolveDocumentLink?: ( + this: void, + link: DocumentLink, + token: CancellationToken, + next: ResolveDocumentLinkSignature + ) => ProviderResult + executeCommand?: ( + this: void, + command: string, + args: any[], + next: ExecuteCommandSignature + ) => ProviderResult + workspace?: WorkspaceMiddleware + window?: WindowMiddleware +} + +export type Middleware = _Middleware & + TypeDefinitionMiddleware & + ImplementationMiddleware & + ColorProviderMiddleware & + DeclarationMiddleware & + FoldingRangeProviderMiddleware & + CallHierarchyMiddleware & + SemanticTokensMiddleware & + LinkedEditingRangeMiddleware & + SelectionRangeProviderMiddleware + +export interface LanguageClientOptions { + ignoredRootPaths?: string[] + documentSelector?: DocumentSelector | string[] + synchronize?: SynchronizeOptions + diagnosticCollectionName?: string + disableDynamicRegister?: boolean + disableWorkspaceFolders?: boolean + disableSnippetCompletion?: boolean + disableDiagnostics?: boolean + disableCompletion?: boolean + formatterPriority?: number + outputChannelName?: string + outputChannel?: OutputChannel + revealOutputChannelOn?: RevealOutputChannelOn + /** + * The encoding use to read stdout and stderr. Defaults + * to 'utf8' if omitted. + */ + stdioEncoding?: string + initializationOptions?: any | (() => any) + initializationFailedHandler?: InitializationFailedHandler + progressOnInitialization?: boolean + errorHandler?: ErrorHandler + middleware?: Middleware + workspaceFolder?: WorkspaceFolder + connectionOptions?: ConnectionOptions + markdown?: { + isTrusted?: boolean + } +} + +interface ResolvedClientOptions { + ignoredRootPaths?: string[] + disableWorkspaceFolders: boolean + disableSnippetCompletion: boolean + disableDynamicRegister: boolean + disableDiagnostics: boolean + disableCompletion: boolean + formatterPriority: number + documentSelector?: DocumentSelector + synchronize: SynchronizeOptions + diagnosticCollectionName?: string + outputChannelName: string + revealOutputChannelOn: RevealOutputChannelOn + stdioEncoding: string + initializationOptions?: any | (() => any) + initializationFailedHandler?: InitializationFailedHandler + progressOnInitialization: boolean + errorHandler: ErrorHandler + middleware: Middleware + workspaceFolder?: WorkspaceFolder + connectionOptions?: ConnectionOptions + markdown: { + isTrusted: boolean + } +} + +export enum State { + Stopped = 1, + Running = 2, + Starting = 3, +} + +export interface StateChangeEvent { + oldState: State + newState: State +} + +export enum ClientState { + Initial, + Starting, + StartFailed, + Running, + Stopping, + Stopped +} + +const SupportedSymbolKinds: SymbolKind[] = [ + SymbolKind.File, + SymbolKind.Module, + SymbolKind.Namespace, + SymbolKind.Package, + SymbolKind.Class, + SymbolKind.Method, + SymbolKind.Property, + SymbolKind.Field, + SymbolKind.Constructor, + SymbolKind.Enum, + SymbolKind.Interface, + SymbolKind.Function, + SymbolKind.Variable, + SymbolKind.Constant, + SymbolKind.String, + SymbolKind.Number, + SymbolKind.Boolean, + SymbolKind.Array, + SymbolKind.Object, + SymbolKind.Key, + SymbolKind.Null, + SymbolKind.EnumMember, + SymbolKind.Struct, + SymbolKind.Event, + SymbolKind.Operator, + SymbolKind.TypeParameter +] + +const SupportedCompletionItemKinds: CompletionItemKind[] = [ + CompletionItemKind.Text, + CompletionItemKind.Method, + CompletionItemKind.Function, + CompletionItemKind.Constructor, + CompletionItemKind.Field, + CompletionItemKind.Variable, + CompletionItemKind.Class, + CompletionItemKind.Interface, + CompletionItemKind.Module, + CompletionItemKind.Property, + CompletionItemKind.Unit, + CompletionItemKind.Value, + CompletionItemKind.Enum, + CompletionItemKind.Keyword, + CompletionItemKind.Snippet, + CompletionItemKind.Color, + CompletionItemKind.File, + CompletionItemKind.Reference, + CompletionItemKind.Folder, + CompletionItemKind.EnumMember, + CompletionItemKind.Constant, + CompletionItemKind.Struct, + CompletionItemKind.Event, + CompletionItemKind.Operator, + CompletionItemKind.TypeParameter +] + +const SupportedSymbolTags: SymbolTag[] = [ + SymbolTag.Deprecated +] + +function ensure(target: T, key: K): T[K] { + if (target[key] === undefined) { + target[key] = {} as any + } + return target[key] +} + +interface ResolvedTextDocumentSyncCapabilities { + resolvedTextDocumentSync?: TextDocumentSyncOptions +} + +export interface RegistrationData { + id: string + registerOptions: T +} + +/** + * A static feature. A static feature can't be dynamically activate via the + * server. It is wired during the initialize sequence. + */ +export interface StaticFeature { + /** + * Called to fill the initialize params. + * + * @params the initialize params. + */ + fillInitializeParams?: (params: InitializeParams) => void + + /** + * Called to fill in the client capabilities this feature implements. + * + * @param capabilities The client capabilities to fill. + */ + fillClientCapabilities(capabilities: ClientCapabilities): void + + /** + * Initialize the feature. This method is called on a feature instance + * when the client has successfully received the initialize request from + * the server and before the client sends the initialized notification + * to the server. + * + * @param capabilities the server capabilities + * @param documentSelector the document selector pass to the client's constuctor. + * May be `undefined` if the client was created without a selector. + */ + initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector | undefined + ): void + + /** + * Called when the client is stopped to dispose this feature. Usually a feature + * unregisters listeners registered hooked up with the VS Code extension host. + */ + dispose(): void +} + +export interface DynamicFeature { + + /** + * Called to fill the initialize params. + * + * @params the initialize params. + */ + fillInitializeParams?: (params: InitializeParams) => void + + /** + * Called to fill in the client capabilities this feature implements. + * + * @param capabilities The client capabilities to fill. + */ + fillClientCapabilities(capabilities: ClientCapabilities): void + + /** + * Initialize the feature. This method is called on a feature instance + * when the client has successfully received the initialize request from + * the server and before the client sends the initialized notification + * to the server. + * + * @param capabilities the server capabilities. + * @param documentSelector the document selector pass to the client's constructor. + * May be `undefined` if the client was created without a selector. + */ + initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector | undefined + ): void + + /** + * The signature (e.g. method) for which this features support dynamic activation / registration. + */ + registrationType: RegistrationType + + /** + * Is called when the server send a register request for the given message. + * + * @param data additional registration data as defined in the protocol. + */ + register(data: RegistrationData): void + + /** + * Is called when the server wants to unregister a feature. + * + * @param id the id used when registering the feature. + */ + unregister(id: string): void + + /** + * Called when the client is stopped to dispose this feature. Usually a feature + * unregisters listeners registered hooked up with the VS Code extension host. + */ + dispose(): void +} + +export interface NotificationFeature { + /** + * Triggers the corresponding RPC method. + */ + getProvider(document: TextDocument): { send: T } | undefined +} + +namespace DynamicFeature { + export function is(value: any): value is DynamicFeature { + let candidate: DynamicFeature = value + return ( + candidate && + Is.func(candidate.register) && + Is.func(candidate.unregister) && + Is.func(candidate.dispose) && + candidate.registrationType !== undefined + ) + } +} + +interface CreateParamsSignature { + (data: E): P +} + +abstract class DocumentNotifications + implements DynamicFeature, NotificationFeature<(data: E) => void> { + private _listener: Disposable | undefined + protected _selectors: Map = new Map() + + public static textDocumentFilter( + selectors: IterableIterator, + textDocument: TextDocument + ): boolean { + for (const selector of selectors) { + if (workspace.match(selector, textDocument) > 0) { + return true + } + } + return false + } + + constructor( + protected _client: BaseLanguageClient, + private _event: Event, + protected _type: ProtocolNotificationType, + protected _middleware: NextSignature | undefined, + protected _createParams: CreateParamsSignature, + protected _selectorFilter?: ( + selectors: IterableIterator, + data: E + ) => boolean + ) {} + + public abstract registrationType: RegistrationType + + public abstract fillClientCapabilities(capabilities: ClientCapabilities): void + + public abstract initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector | undefined + ): void + + public register( + data: RegistrationData + ): void { + if (!data.registerOptions.documentSelector) { + return + } + if (!this._listener) { + this._listener = this._event(this.callback, this) + } + this._selectors.set(data.id, data.registerOptions.documentSelector) + } + + private callback(data: E): void { + 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) + } + } + + protected notificationSent(_data: E): void {} + + public unregister(id: string): void { + this._selectors.delete(id) + if (this._selectors.size === 0 && this._listener) { + this._listener.dispose() + this._listener = undefined + } + } + + public dispose(): void { + this._selectors.clear() + if (this._listener) { + this._listener.dispose() + this._listener = undefined + } + } + + public getProvider(document: TextDocument): { send: (data: E) => void } | undefined { + for (const selector of this._selectors.values()) { + if (workspace.match(selector, document)) { + return { + send: (data: E) => { + this.callback(data) + } + } + } + } + return undefined + } +} + +class DidOpenTextDocumentFeature extends DocumentNotifications { + constructor(client: BaseLanguageClient, private _syncedDocuments: Map) { + super( + client, + workspace.onDidOpenTextDocument, + DidOpenTextDocumentNotification.type, + client.clientOptions.middleware!.didOpen, + (textDocument) => { + return { textDocument: cv.convertToTextDocumentItem(textDocument) } + }, + DocumentNotifications.textDocumentFilter + ) + } + + public get registrationType(): RegistrationType { + return DidOpenTextDocumentNotification.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure(ensure(capabilities, 'textDocument')!, 'synchronization')!.dynamicRegistration = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + let textDocumentSyncOptions = (capabilities as ResolvedTextDocumentSyncCapabilities).resolvedTextDocumentSync + if ( + documentSelector && + textDocumentSyncOptions && + textDocumentSyncOptions.openClose + ) { + this.register({ + id: UUID.generateUuid(), + registerOptions: { documentSelector: documentSelector } + }) + } + } + + public register( + data: RegistrationData + ): void { + super.register(data) + if (!data.registerOptions.documentSelector) { + return + } + let documentSelector = data.registerOptions.documentSelector + workspace.textDocuments.forEach(textDocument => { + let uri: string = textDocument.uri.toString() + if (this._syncedDocuments.has(uri)) { + return + } + if (workspace.match(documentSelector, textDocument) > 0) { + let middleware = this._client.clientOptions.middleware! + let didOpen = (textDocument: TextDocument) => { + this._client.sendNotification( + this._type, + this._createParams(textDocument) + ) + } + if (middleware.didOpen) { + middleware.didOpen(textDocument, didOpen) + } else { + didOpen(textDocument) + } + this._syncedDocuments.set(uri, textDocument) + } + }) + } + + protected notificationSent(textDocument: TextDocument): void { + super.notificationSent(textDocument) + this._syncedDocuments.set(textDocument.uri.toString(), textDocument) + } +} + +class DidCloseTextDocumentFeature extends DocumentNotifications< + DidCloseTextDocumentParams, + TextDocument + > { + constructor( + client: BaseLanguageClient, + private _syncedDocuments: Map + ) { + super( + client, + workspace.onDidCloseTextDocument, + DidCloseTextDocumentNotification.type, + client.clientOptions.middleware!.didClose, + (textDocument) => cv.asCloseTextDocumentParams(textDocument), + DocumentNotifications.textDocumentFilter + ) + } + + public get registrationType(): RegistrationType { + return DidCloseTextDocumentNotification.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'textDocument')!, + 'synchronization' + )!.dynamicRegistration = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + let textDocumentSyncOptions = (capabilities as ResolvedTextDocumentSyncCapabilities).resolvedTextDocumentSync + if ( + documentSelector && + textDocumentSyncOptions && + textDocumentSyncOptions.openClose + ) { + this.register({ + id: UUID.generateUuid(), + registerOptions: { documentSelector: documentSelector } + }) + } + } + + protected notificationSent(textDocument: TextDocument): void { + super.notificationSent(textDocument) + this._syncedDocuments.delete(textDocument.uri.toString()) + } + + public unregister(id: string): void { + 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.match(selector, textDocument) > 0 && + !this._selectorFilter!(selectors, textDocument) + ) { + let middleware = this._client.clientOptions.middleware! + let didClose = (textDocument: 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) + } + } + }) + } +} + +interface DidChangeTextDocumentData { + documentSelector: DocumentSelector + syncKind: 0 | 1 | 2 +} + +class DidChangeTextDocumentFeature + implements DynamicFeature, NotificationFeature<(event: DidChangeTextDocumentParams) => void> { + private _listener: Disposable | undefined + private _changeData: Map = new Map() + + constructor(private _client: BaseLanguageClient) {} + + public get registrationType(): RegistrationType { + return DidChangeTextDocumentNotification.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure(ensure(capabilities, 'textDocument')!, 'synchronization')!.dynamicRegistration = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + let textDocumentSyncOptions = (capabilities as ResolvedTextDocumentSyncCapabilities).resolvedTextDocumentSync + if ( + documentSelector && + textDocumentSyncOptions && + textDocumentSyncOptions.change !== undefined && + textDocumentSyncOptions.change !== TextDocumentSyncKind.None + ) { + this.register({ + id: UUID.generateUuid(), + registerOptions: Object.assign( + {}, + { documentSelector: documentSelector }, + { syncKind: textDocumentSyncOptions.change } + ) + }) + } + } + + public register( + data: RegistrationData + ): void { + if (!data.registerOptions.documentSelector) { + return + } + if (!this._listener) { + this._listener = workspace.onDidChangeTextDocument(this.callback, this) + } + this._changeData.set(data.id, { + documentSelector: data.registerOptions.documentSelector, + syncKind: data.registerOptions.syncKind + }) + } + + private callback(event: DidChangeTextDocumentParams): void { + // 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.getDocument(event.textDocument.uri) + if (!doc) return + let { textDocument } = doc + for (const changeData of this._changeData.values()) { + if (workspace.match(changeData.documentSelector, textDocument) > 0) { + let middleware = this._client.clientOptions.middleware! + if (changeData.syncKind === TextDocumentSyncKind.Incremental) { + if (middleware.didChange) { + middleware.didChange(event, () => + this._client.sendNotification( + DidChangeTextDocumentNotification.type, + omit(event, ['bufnr', 'original']) + ) + ) + } else { + this._client.sendNotification( + DidChangeTextDocumentNotification.type, + omit(event, ['bufnr', 'original']) + ) + } + } else if (changeData.syncKind === TextDocumentSyncKind.Full) { + let didChange: (event: DidChangeTextDocumentParams) => void = event => { + let { textDocument } = workspace.getDocument(event.textDocument.uri) + this._client.sendNotification( + DidChangeTextDocumentNotification.type, + cv.asChangeTextDocumentParams(textDocument) + ) + } + if (middleware.didChange) { + middleware.didChange(event, didChange) + } else { + didChange(event) + } + } + } + } + } + + public unregister(id: string): void { + this._changeData.delete(id) + if (this._changeData.size === 0 && this._listener) { + this._listener.dispose() + this._listener = undefined + } + } + + public dispose(): void { + this._changeData.clear() + if (this._listener) { + this._listener.dispose() + this._listener = undefined + } + } + + public getProvider(document: TextDocument): { send: (event: DidChangeTextDocumentParams) => void } | undefined { + for (const changeData of this._changeData.values()) { + if (workspace.match(changeData.documentSelector, document)) { + return { + send: (event: DidChangeTextDocumentParams): void => { + this.callback(event) + } + } + } + } + return undefined + } +} + +class WillSaveFeature extends DocumentNotifications { + constructor(client: BaseLanguageClient) { + super( + client, + workspace.onWillSaveTextDocument, + WillSaveTextDocumentNotification.type, + client.clientOptions.middleware!.willSave, + willSaveEvent => cv.asWillSaveTextDocumentParams(willSaveEvent), + (selectors, willSaveEvent) => DocumentNotifications.textDocumentFilter(selectors, willSaveEvent.document) + ) + } + + public get registrationType(): RegistrationType { + return WillSaveTextDocumentNotification.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let value = ensure(ensure(capabilities, 'textDocument')!, 'synchronization')! + value.willSave = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + let textDocumentSyncOptions = (capabilities as ResolvedTextDocumentSyncCapabilities).resolvedTextDocumentSync + if ( + documentSelector && + textDocumentSyncOptions && + textDocumentSyncOptions.willSave + ) { + this.register({ + id: UUID.generateUuid(), + registerOptions: { documentSelector: documentSelector } + }) + } + } +} + +class WillSaveWaitUntilFeature implements DynamicFeature { + private _listener: Disposable | undefined + private _selectors: Map = new Map() + + constructor(private _client: BaseLanguageClient) {} + + public get registrationType(): RegistrationType { + return WillSaveTextDocumentWaitUntilRequest.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let value = ensure(ensure(capabilities, 'textDocument')!, 'synchronization')! + value.willSaveWaitUntil = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + let textDocumentSyncOptions = (capabilities as ResolvedTextDocumentSyncCapabilities).resolvedTextDocumentSync + if ( + documentSelector && + textDocumentSyncOptions && + textDocumentSyncOptions.willSaveWaitUntil + ) { + this.register({ + id: UUID.generateUuid(), + registerOptions: { documentSelector: documentSelector } + }) + } + } + + public register( + data: RegistrationData + ): void { + if (!data.registerOptions.documentSelector) { + return + } + if (!this._listener) { + this._listener = workspace.onWillSaveTextDocument(this.callback, this) + } + this._selectors.set(data.id, data.registerOptions.documentSelector) + } + + private callback(event: TextDocumentWillSaveEvent): void { + if (DocumentNotifications.textDocumentFilter( + this._selectors.values(), + event.document)) { + let middleware = this._client.clientOptions.middleware! + let willSaveWaitUntil = (event: TextDocumentWillSaveEvent): Thenable => { + return this._client + .sendRequest( + WillSaveTextDocumentWaitUntilRequest.type, + cv.asWillSaveTextDocumentParams(event) + ) + .then(edits => { + return edits ? edits : [] + }, e => { + window.showMessage(`Error on willSaveWaitUntil: ${e}`, 'error') + logger.error(e) + return [] + }) + } + event.waitUntil( + middleware.willSaveWaitUntil + ? middleware.willSaveWaitUntil(event, willSaveWaitUntil) + : willSaveWaitUntil(event) + ) + } + } + + public unregister(id: string): void { + this._selectors.delete(id) + if (this._selectors.size === 0 && this._listener) { + this._listener.dispose() + this._listener = undefined + } + } + + public dispose(): void { + this._selectors.clear() + if (this._listener) { + this._listener.dispose() + this._listener = undefined + } + } +} + +class DidSaveTextDocumentFeature extends DocumentNotifications< + DidSaveTextDocumentParams, + TextDocument + > { + private _includeText: boolean + + constructor(client: BaseLanguageClient) { + super( + client, + workspace.onDidSaveTextDocument, + DidSaveTextDocumentNotification.type, + client.clientOptions.middleware!.didSave, + textDocument => + cv.asSaveTextDocumentParams( + textDocument, + this._includeText + ), + DocumentNotifications.textDocumentFilter + ) + this._includeText = false + } + + public get registrationType(): RegistrationType { + return DidSaveTextDocumentNotification.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'textDocument')!, + 'synchronization' + )!.didSave = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const textDocumentSyncOptions = (capabilities as ResolvedTextDocumentSyncCapabilities).resolvedTextDocumentSync + if ( + documentSelector && + textDocumentSyncOptions && + textDocumentSyncOptions.save + ) { + const saveOptions: SaveOptions = typeof textDocumentSyncOptions.save === 'boolean' + ? { includeText: false } + : { includeText: !!textDocumentSyncOptions.save.includeText } + this.register({ + id: UUID.generateUuid(), + registerOptions: Object.assign( + {}, + { documentSelector: documentSelector }, + saveOptions + ) + }) + } + } + + public register( + data: RegistrationData + ): void { + this._includeText = !!data.registerOptions.includeText + super.register(data) + } +} + +class FileSystemWatcherFeature + implements DynamicFeature { + private _watchers: Map = new Map() + + constructor( + _client: BaseLanguageClient, + private _notifyFileEvent: (event: FileEvent) => void + ) {} + + public get registrationType(): RegistrationType { + return DidChangeWatchedFilesNotification.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'workspace')!, + 'didChangeWatchedFiles' + )!.dynamicRegistration = true + } + + public initialize( + _capabilities: ServerCapabilities, + _documentSelector: DocumentSelector + ): void {} + + public register( + data: RegistrationData + ): void { + if (!Array.isArray(data.registerOptions.watchers)) { + return + } + let disposables: Disposable[] = [] + for (let watcher of data.registerOptions.watchers) { + if (!Is.string(watcher.globPattern)) { + continue + } + let watchCreate: boolean = true, + watchChange: boolean = true, + watchDelete: boolean = true + if (watcher.kind != null) { + watchCreate = (watcher.kind & WatchKind.Create) !== 0 + watchChange = (watcher.kind & WatchKind.Change) != 0 + watchDelete = (watcher.kind & WatchKind.Delete) != 0 + } + let fileSystemWatcher = workspace.createFileSystemWatcher( + watcher.globPattern, + !watchCreate, + !watchChange, + !watchDelete + ) + this.hookListeners( + fileSystemWatcher, + watchCreate, + watchChange, + watchDelete, + disposables + ) + disposables.push(fileSystemWatcher) + } + this._watchers.set(data.id, disposables) + } + + public registerRaw(id: string, fileSystemWatchers: FileWatcher[]) { + let disposables: Disposable[] = [] + for (let fileSystemWatcher of fileSystemWatchers) { + disposables.push(fileSystemWatcher) + this.hookListeners(fileSystemWatcher, true, true, true, disposables) + } + this._watchers.set(id, disposables) + } + + private hookListeners( + fileSystemWatcher: FileWatcher, + watchCreate: boolean, + watchChange: boolean, + watchDelete: boolean, + listeners: Disposable[] + ): void { + if (watchCreate) { + fileSystemWatcher.onDidCreate( + resource => + this._notifyFileEvent({ + uri: cv.asUri(resource), + type: FileChangeType.Created + }), + null, + listeners + ) + } + if (watchChange) { + fileSystemWatcher.onDidChange( + resource => + this._notifyFileEvent({ + uri: cv.asUri(resource), + type: FileChangeType.Changed + }), + null, + listeners + ) + } + if (watchDelete) { + fileSystemWatcher.onDidDelete( + resource => + this._notifyFileEvent({ + uri: cv.asUri(resource), + type: FileChangeType.Deleted + }), + null, + listeners + ) + } + } + + public unregister(id: string): void { + let disposables = this._watchers.get(id) + if (disposables) { + for (let disposable of disposables) { + disposable.dispose() + } + } + } + + public dispose(): void { + this._watchers.forEach(disposables => { + for (let disposable of disposables) { + disposable.dispose() + } + }) + this._watchers.clear() + } +} + +interface TextDocumentFeatureRegistration { + disposable: Disposable + data: RegistrationData + provider: PR +} + +export interface TextDocumentProviderFeature { + /** + * Triggers the corresponding RPC method. + */ + getProvider(textDocument: TextDocument): T | undefined +} + +export abstract class TextDocumentFeature< + PO, RO extends TextDocumentRegistrationOptions & PO, PR + > implements DynamicFeature { + private _registrations: Map> = new Map() + + constructor( + protected _client: BaseLanguageClient, + private _registrationType: RegistrationType + ) {} + + public get registrationType(): RegistrationType { + return this._registrationType + } + + public abstract fillClientCapabilities(capabilities: ClientCapabilities): void + + public abstract initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void + + public register(data: RegistrationData): void { + if (!data.registerOptions.documentSelector) { + return + } + let registration = this.registerLanguageProvider(data.registerOptions) + this._registrations.set(data.id, { disposable: registration[0], data, provider: registration[1] }) + } + + protected abstract registerLanguageProvider(options: RO): [Disposable, PR] + + public unregister(id: string): void { + let registration = this._registrations.get(id) + if (registration) { + registration.disposable.dispose() + } + } + + public dispose(): void { + this._registrations.forEach(value => { + value.disposable.dispose() + }) + this._registrations.clear() + } + + protected getRegistration(documentSelector: DocumentSelector | undefined, capability: undefined | PO | (RO & StaticRegistrationOptions)): [string | undefined, (RO & { documentSelector: DocumentSelector }) | undefined] { + if (!capability) { + return [undefined, undefined] + } else if (TextDocumentRegistrationOptions.is(capability)) { + const id = StaticRegistrationOptions.hasId(capability) ? capability.id : UUID.generateUuid() + const selector = capability.documentSelector || documentSelector + if (selector) { + return [id, Object.assign({}, capability, { documentSelector: selector })] + } + } else if (Is.boolean(capability) && capability === true || WorkDoneProgressOptions.is(capability)) { + if (!documentSelector) { + return [undefined, undefined] + } + let options: RO & { documentSelector: DocumentSelector } = (Is.boolean(capability) && capability === true ? { documentSelector } : Object.assign({}, capability, { documentSelector })) as any + return [UUID.generateUuid(), options] + } + return [undefined, undefined] + } + + protected getRegistrationOptions(documentSelector: DocumentSelector | undefined, capability: undefined | PO): (RO & { documentSelector: DocumentSelector }) | undefined { + if (!documentSelector || !capability) { + return undefined + } + return (Is.boolean(capability) && capability === true ? { documentSelector } : Object.assign({}, capability, { documentSelector })) as RO & { documentSelector: DocumentSelector } + } + + public getProvider(textDocument: TextDocument): PR | undefined { + for (const registration of this._registrations.values()) { + let selector = registration.data.registerOptions.documentSelector + if (selector !== null && workspace.match(selector, textDocument) > 0) { + return registration.provider + } + } + return undefined + } + + protected getAllProviders(): Iterable { + const result: PR[] = [] + for (const item of this._registrations.values()) { + result.push(item.provider) + } + return result + } +} + +export interface WorkspaceProviderFeature { + getProviders(): PR[] | undefined +} + +interface WorkspaceFeatureRegistration { + disposable: Disposable + provider: PR +} + +abstract class WorkspaceFeature implements DynamicFeature { + protected _registrations: Map> = new Map() + + constructor( + protected _client: BaseLanguageClient, + private _registrationType: RegistrationType + ) {} + + public get registrationType(): RegistrationType { + return this._registrationType + } + + public abstract fillClientCapabilities(capabilities: ClientCapabilities): void + + public abstract initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector | undefined + ): void + + public register(data: RegistrationData): void { + const registration = this.registerLanguageProvider(data.registerOptions) + this._registrations.set(data.id, { disposable: registration[0], provider: registration[1] }) + } + + protected abstract registerLanguageProvider(options: RO): [Disposable, PR] + + public unregister(id: string): void { + const registration = this._registrations.get(id) + if (registration) registration.disposable.dispose() + } + + public dispose(): void { + this._registrations.forEach(value => { + value.disposable.dispose() + }) + this._registrations.clear() + } + + public getProviders(): PR[] { + const result: PR[] = [] + for (const registration of this._registrations.values()) { + result.push(registration.provider) + } + return result + } +} + +export interface ProvideResolveFeature { + provide: T1 + resolve: T2 +} + +class CompletionItemFeature extends TextDocumentFeature { + private index: number + constructor(client: BaseLanguageClient) { + super(client, CompletionRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let snippetSupport = this._client.clientOptions.disableSnippetCompletion !== true + let completion = ensure(ensure(capabilities, 'textDocument')!, 'completion')! + completion.dynamicRegistration = true + completion.contextSupport = true + completion.completionItem = { + snippetSupport, + commitCharactersSupport: true, + documentationFormat: this._client.supporedMarkupKind, + deprecatedSupport: true, + preselectSupport: true, + insertReplaceSupport: true, + tagSupport: { valueSet: [CompletionItemTag.Deprecated] }, + resolveSupport: { properties: ['documentation', 'detail', 'additionalTextEdits'] }, + insertTextModeSupport: { valueSet: [InsertTextMode.asIs, InsertTextMode.adjustIndentation] } + } + completion.completionItemKind = { valueSet: SupportedCompletionItemKinds } + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + this.index = 0 + const options = this.getRegistrationOptions(documentSelector, capabilities.completionProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider(options: CompletionRegistrationOptions): [Disposable, CompletionItemProvider] { + let triggerCharacters = options.triggerCharacters || [] + let allCommitCharacters = options.allCommitCharacters || [] + let priority = (options as any).priority as number + const provider: CompletionItemProvider = { + provideCompletionItems: (document: TextDocument, position: Position, token: CancellationToken, context: CompletionContext): ProviderResult => { + const client = this._client + const middleware = this._client.clientOptions.middleware! + const provideCompletionItems: ProvideCompletionItemsSignature = (document, position, context, token) => { + return client.sendRequest( + CompletionRequest.type, + cv.asCompletionParams(document, position, context), + token + ).then(result => result, error => { + return client.handleFailedRequest(CompletionRequest.type, token, error, null) + }) + } + + return middleware.provideCompletionItem + ? middleware.provideCompletionItem(document, position, context, token, provideCompletionItems) + : provideCompletionItems(document, position, context, token) + }, + resolveCompletionItem: options.resolveProvider + ? (item: CompletionItem, token: CancellationToken): ProviderResult => { + const client = this._client + const middleware = this._client.clientOptions.middleware! + const resolveCompletionItem: ResolveCompletionItemSignature = (item, token) => { + return client.sendRequest( + CompletionResolveRequest.type, + item, + token + ).then(res => res, error => { + return client.handleFailedRequest(CompletionResolveRequest.type, token, error, item) + }) + } + + return middleware.resolveCompletionItem + ? middleware.resolveCompletionItem(item, token, resolveCompletionItem) + : resolveCompletionItem(item, token) + } + : undefined + } + // index is needed since one language server could create many sources. + let name = this._client.id + (this.index ? '-' + this.index : '') + sources.removeSource(name) + const disposable = languages.registerCompletionItemProvider( + name, + 'LS', + options.documentSelector || this._client.clientOptions.documentSelector, + provider, + triggerCharacters, + priority, + allCommitCharacters) + this.index = this.index + 1 + return [disposable, provider] + } +} + +class HoverFeature extends TextDocumentFeature< + boolean | HoverOptions, HoverRegistrationOptions, HoverProvider + > { + constructor(client: BaseLanguageClient) { + super(client, HoverRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + const hoverCapability = ensure( + ensure(capabilities, 'textDocument')!, + 'hover' + )! + hoverCapability.dynamicRegistration = true + hoverCapability.contentFormat = this._client.supporedMarkupKind + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.hoverProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: HoverRegistrationOptions + ): [Disposable, HoverProvider] { + const provider: HoverProvider = { + provideHover: (document, position, token) => { + const client = this._client + const provideHover: ProvideHoverSignature = (document, position, token) => { + return client.sendRequest( + HoverRequest.type, + cv.asTextDocumentPositionParams(document, position), + token + ).then(res => res, error => { + return client.handleFailedRequest(HoverRequest.type, token, error, null) + }) + } + + const middleware = client.clientOptions.middleware! + return middleware.provideHover + ? middleware.provideHover(document, position, token, provideHover) + : provideHover(document, position, token) + } + } + + return [languages.registerHoverProvider(options.documentSelector!, provider), provider] + } +} + +class SignatureHelpFeature extends TextDocumentFeature< + SignatureHelpOptions, SignatureHelpRegistrationOptions, SignatureHelpProvider + > { + constructor(client: BaseLanguageClient) { + super(client, SignatureHelpRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let config = ensure(ensure(capabilities, 'textDocument')!, 'signatureHelp')! + config.dynamicRegistration = true + config.contextSupport = true + config.signatureInformation = { + documentationFormat: this._client.supporedMarkupKind, + activeParameterSupport: true, + parameterInformation: { + labelOffsetSupport: true + } + } as any + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.signatureHelpProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: SignatureHelpRegistrationOptions + ): [Disposable, SignatureHelpProvider] { + const provider: SignatureHelpProvider = { + provideSignatureHelp: (document, position, token, context) => { + const client = this._client + const providerSignatureHelp: ProvideSignatureHelpSignature = (document, position, context, token) => { + return client.sendRequest( + SignatureHelpRequest.type, + cv.asSignatureHelpParams(document, position, context), + token + ).then(res => res, error => { + return client.handleFailedRequest(SignatureHelpRequest.type, token, error, null) + } + ) + } + + const middleware = client.clientOptions.middleware! + return middleware.provideSignatureHelp + ? middleware.provideSignatureHelp(document, position, context, token, providerSignatureHelp) + : providerSignatureHelp(document, position, context, token) + } + } + + const triggerCharacters = options.triggerCharacters || [] + const disposable = languages.registerSignatureHelpProvider(options.documentSelector!, provider, triggerCharacters) + return [disposable, provider] + } +} + +class DefinitionFeature extends TextDocumentFeature< + boolean | DefinitionOptions, DefinitionRegistrationOptions, DefinitionProvider + > { + constructor(client: BaseLanguageClient) { + super(client, DefinitionRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let definitionSupport = ensure(ensure(capabilities, 'textDocument')!, 'definition')! + definitionSupport.dynamicRegistration = true + // definitionSupport.linkSupport = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.definitionProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: DefinitionRegistrationOptions + ): [Disposable, DefinitionProvider] { + const provider: DefinitionProvider = { + provideDefinition: (document, position, token) => { + const client = this._client + const provideDefinition: ProvideDefinitionSignature = (document, position, token) => { + return client.sendRequest( + DefinitionRequest.type, + cv.asTextDocumentPositionParams(document, position), + token + ).then(res => res, error => { + return client.handleFailedRequest(DefinitionRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideDefinition + ? middleware.provideDefinition(document, position, token, provideDefinition) + : provideDefinition(document, position, token) + } + } + + return [languages.registerDefinitionProvider(options.documentSelector!, provider), provider] + } +} + +class ReferencesFeature extends TextDocumentFeature< + boolean | ReferenceOptions, ReferenceRegistrationOptions, ReferenceProvider + > { + constructor(client: BaseLanguageClient) { + super(client, ReferencesRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'textDocument')!, + 'references' + )!.dynamicRegistration = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.referencesProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: TextDocumentRegistrationOptions + ): [Disposable, ReferenceProvider] { + const provider: ReferenceProvider = { + provideReferences: (document, position, options, token) => { + const client = this._client + const _providerReferences: ProvideReferencesSignature = (document, position, options, token) => { + return client.sendRequest( + ReferencesRequest.type, + cv.asReferenceParams(document, position, options), + token + ).then(res => res, error => { + return client.handleFailedRequest(ReferencesRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideReferences + ? middleware.provideReferences(document, position, options, token, _providerReferences) + : _providerReferences(document, position, options, token) + } + } + return [languages.registerReferencesProvider(options.documentSelector!, provider), provider] + } +} + +class DocumentHighlightFeature extends TextDocumentFeature< + boolean | DocumentHighlightOptions, DocumentHighlightRegistrationOptions, DocumentHighlightProvider + > { + constructor(client: BaseLanguageClient) { + super(client, DocumentHighlightRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'textDocument')!, + 'documentHighlight' + )!.dynamicRegistration = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentHighlightProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: TextDocumentRegistrationOptions + ): [Disposable, DocumentHighlightProvider] { + const provider: DocumentHighlightProvider = { + provideDocumentHighlights: (document, position, token) => { + const client = this._client + const _provideDocumentHighlights: ProvideDocumentHighlightsSignature = (document, position, token) => { + return client.sendRequest( + DocumentHighlightRequest.type, + cv.asTextDocumentPositionParams(document, position), + token + ).then(res => res, error => { + return client.handleFailedRequest(DocumentHighlightRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideDocumentHighlights + ? middleware.provideDocumentHighlights(document, position, token, _provideDocumentHighlights) + : _provideDocumentHighlights(document, position, token) + } + } + return [languages.registerDocumentHighlightProvider(options.documentSelector!, provider), provider] + } +} + +class DocumentSymbolFeature extends TextDocumentFeature< + boolean | DocumentSymbolOptions, DocumentSymbolRegistrationOptions, DocumentSymbolProvider + > { + constructor(client: BaseLanguageClient) { + super(client, DocumentSymbolRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let symbolCapabilities = ensure(ensure(capabilities, 'textDocument')!, 'documentSymbol')! as any + symbolCapabilities.dynamicRegistration = true + symbolCapabilities.symbolKind = { + valueSet: SupportedSymbolKinds + } + symbolCapabilities.hierarchicalDocumentSymbolSupport = true + symbolCapabilities.tagSupport = { + valueSet: SupportedSymbolTags + } + // TODO: capabilities + // symbolCapabilities.labelSupport = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentSymbolProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: DocumentSymbolRegistrationOptions + ): [Disposable, DocumentSymbolProvider] { + const provider: DocumentSymbolProvider = { + provideDocumentSymbols: (document, token) => { + const client = this._client + const _provideDocumentSymbols: ProvideDocumentSymbolsSignature = (document, token) => { + return client.sendRequest( + DocumentSymbolRequest.type, + cv.asDocumentSymbolParams(document), + token + ).then( + (data) => { + if (data === null) { + return undefined + } + if (data.length === 0) { + return [] + } else { + let element = data[0] + if (DocumentSymbol.is(element)) { + return data as DocumentSymbol[] + } else { + return data as SymbolInformation[] + } + } + }, + (error) => { + return client.handleFailedRequest(DocumentSymbolRequest.type, token, error, null) + } + ) + } + const middleware = client.clientOptions.middleware! + return middleware.provideDocumentSymbols + ? middleware.provideDocumentSymbols(document, token, _provideDocumentSymbols) + : _provideDocumentSymbols(document, token) + } + } + const metadata = options.label ? { label: options.label } : undefined + return [languages.registerDocumentSymbolProvider(options.documentSelector!, provider, metadata), provider] + } +} + +class WorkspaceSymbolFeature extends WorkspaceFeature { + constructor(client: BaseLanguageClient) { + super(client, WorkspaceSymbolRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let symbolCapabilities = ensure( + ensure(capabilities, 'workspace')!, + 'symbol' + )! as any + symbolCapabilities.dynamicRegistration = true + symbolCapabilities.symbolKind = { + valueSet: SupportedSymbolKinds + } + symbolCapabilities.tagSupport = { + valueSet: SupportedSymbolTags + } + } + + public initialize( + capabilities: ServerCapabilities, + ): void { + if (!capabilities.workspaceSymbolProvider) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: capabilities.workspaceSymbolProvider === true ? { workDoneProgress: false } : capabilities.workspaceSymbolProvider + }) + } + + protected registerLanguageProvider(_options: WorkspaceSymbolRegistrationOptions): [Disposable, WorkspaceSymbolProvider] { + const provider: WorkspaceSymbolProvider = { + provideWorkspaceSymbols: (query, token) => { + const client = this._client + const provideWorkspaceSymbols: ProvideWorkspaceSymbolsSignature = (query, token) => { + return client.sendRequest(WorkspaceSymbolRequest.type, { query }, token).then( + res => res, + error => { + return client.handleFailedRequest(WorkspaceSymbolRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideWorkspaceSymbols + ? middleware.provideWorkspaceSymbols(query, token, provideWorkspaceSymbols) + : provideWorkspaceSymbols(query, token) + } + } + return [languages.registerWorkspaceSymbolProvider(provider), provider] + } +} + +class CodeActionFeature extends TextDocumentFeature { + private disposables: Disposable[] = [] + constructor(client: BaseLanguageClient) { + super(client, CodeActionRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + const cap = ensure(ensure(capabilities, 'textDocument')!, 'codeAction')! + cap.dynamicRegistration = true + cap.isPreferredSupport = true + cap.disabledSupport = true + cap.dataSupport = true + cap.honorsChangeAnnotations = false + cap.resolveSupport = { + properties: ['edit'] + } + cap.codeActionLiteralSupport = { + codeActionKind: { + valueSet: [ + CodeActionKind.Empty, + CodeActionKind.QuickFix, + CodeActionKind.Refactor, + CodeActionKind.RefactorExtract, + CodeActionKind.RefactorInline, + CodeActionKind.RefactorRewrite, + CodeActionKind.Source, + CodeActionKind.SourceOrganizeImports + ] + } + } + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.codeActionProvider) + if (!options) { + return + } + + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: CodeActionRegistrationOptions + ): [Disposable, CodeActionProvider] { + const registCommand = (id: string) => { + if (commands.has(id)) return + const client = this._client + const executeCommand: ExecuteCommandSignature = (command: string, args: any[]): any => { + const params: ExecuteCommandParams = { + command, + arguments: args + } + return client.sendRequest(ExecuteCommandRequest.type, params).then(undefined, (error) => { + client.handleFailedRequest(ExecuteCommandRequest.type, undefined, error, undefined) + throw error + }) + } + const middleware = client.clientOptions.middleware! + this.disposables.push(commands.registerCommand(id, (...args: any[]) => { + return middleware.executeCommand + ? middleware.executeCommand(id, args, executeCommand) + : executeCommand(id, args) + }, null, true)) + } + const provider: CodeActionProvider = { + provideCodeActions: (document, range, context, token) => { + const client = this._client + const _provideCodeActions: ProvideCodeActionsSignature = (document, range, context, token) => { + const params: CodeActionParams = { + textDocument: { + uri: document.uri + }, + range, + context, + } + return client.sendRequest(CodeActionRequest.type, params, token).then( + (values) => { + if (values === null) { + return undefined + } + // some server may not registered commands to client. + values.forEach(val => { + let cmd = Command.is(val) ? val.command : val.command?.command + if (cmd && !commands.has(cmd)) registCommand(cmd) + }) + return values + }, + (error) => { + return client.handleFailedRequest(CodeActionRequest.type, token, error, null) + } + ) + } + const middleware = client.clientOptions.middleware! + return middleware.provideCodeActions + ? middleware.provideCodeActions(document, range, context, token, _provideCodeActions) + : _provideCodeActions(document, range, context, token) + }, + resolveCodeAction: options.resolveProvider + ? (item: CodeAction, token: CancellationToken) => { + const client = this._client + const middleware = this._client.clientOptions.middleware! + const resolveCodeAction: ResolveCodeActionSignature = (item, token) => { + return client.sendRequest(CodeActionResolveRequest.type, item, token).then( + (values) => values, + (error) => { + return client.handleFailedRequest(CodeActionResolveRequest.type, token, error, item) + } + ) + } + return middleware.resolveCodeAction + ? middleware.resolveCodeAction(item, token, resolveCodeAction) + : resolveCodeAction(item, token) + } + : undefined + } + return [languages.registerCodeActionProvider(options.documentSelector, provider, this._client.id, options.codeActionKinds), provider] + } + + public dispose(): void { + this.disposables.forEach(o => { + o.dispose() + }) + this.disposables = [] + super.dispose() + } +} + +interface CodeLensProviderData { + provider?: CodeLensProvider + onDidChangeCodeLensEmitter?: Emitter +} + +class CodeLensFeature extends TextDocumentFeature { + constructor(client: BaseLanguageClient) { + super(client, CodeLensRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'textDocument')!, + 'codeLens' + )!.dynamicRegistration = true + ensure(ensure(capabilities, 'workspace')!, + 'codeLens' + )!.refreshSupport = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const client = this._client + client.onRequest(CodeLensRefreshRequest.type, async () => { + for (const provider of this.getAllProviders()) { + provider.onDidChangeCodeLensEmitter.fire() + } + }) + const options = this.getRegistrationOptions(documentSelector, capabilities.codeLensProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: CodeLensRegistrationOptions + ): [Disposable, CodeLensProviderData] { + const emitter: Emitter = new Emitter() + const provider: CodeLensProvider = { + onDidChangeCodeLenses: emitter.event, + provideCodeLenses: (document, token) => { + const client = this._client + const provideCodeLenses: ProvideCodeLensesSignature = (document, token) => { + return client.sendRequest( + CodeLensRequest.type, + cv.asCodeLensParams(document), + token + ).then(res => res, error => { + return client.handleFailedRequest(CodeLensRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideCodeLenses + ? middleware.provideCodeLenses(document, token, provideCodeLenses) + : provideCodeLenses(document, token) + }, + resolveCodeLens: (options.resolveProvider) + ? (codeLens: CodeLens, token: CancellationToken): ProviderResult => { + const client = this._client + const resolveCodeLens: ResolveCodeLensSignature = (codeLens, token) => { + return client.sendRequest( + CodeLensResolveRequest.type, + codeLens, + token + ).then(res => res, error => { + return client.handleFailedRequest(CodeLensResolveRequest.type, token, error, codeLens) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.resolveCodeLens + ? middleware.resolveCodeLens(codeLens, token, resolveCodeLens) + : resolveCodeLens(codeLens, token) + } + : undefined + } + + return [languages.registerCodeLensProvider(options.documentSelector, provider), { provider, onDidChangeCodeLensEmitter: emitter }] + } +} + +class DocumentFormattingFeature extends TextDocumentFeature< + boolean | DocumentFormattingOptions, DocumentHighlightRegistrationOptions, DocumentFormattingEditProvider + > { + + constructor(client: BaseLanguageClient) { + super(client, DocumentFormattingRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'textDocument')!, + 'formatting' + )!.dynamicRegistration = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentFormattingProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: TextDocumentRegistrationOptions + ): [Disposable, DocumentFormattingEditProvider] { + const provider: DocumentFormattingEditProvider = { + provideDocumentFormattingEdits: (document, options, token) => { + const client = this._client + const provideDocumentFormattingEdits: ProvideDocumentFormattingEditsSignature = (document, options, token) => { + const params: DocumentFormattingParams = { + textDocument: { uri: document.uri }, + options + } + return client.sendRequest(DocumentFormattingRequest.type, params, token).then(res => res, (error) => { + return client.handleFailedRequest(DocumentFormattingRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideDocumentFormattingEdits + ? middleware.provideDocumentFormattingEdits(document, options, token, provideDocumentFormattingEdits) + : provideDocumentFormattingEdits(document, options, token) + } + } + + return [ + languages.registerDocumentFormatProvider(options.documentSelector!, provider, this._client.clientOptions.formatterPriority), + provider + ] + } +} + +class DocumentRangeFormattingFeature extends TextDocumentFeature< + boolean | DocumentRangeFormattingOptions, DocumentRangeFormattingRegistrationOptions, DocumentRangeFormattingEditProvider + > { + constructor(client: BaseLanguageClient) { + super(client, DocumentRangeFormattingRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'textDocument')!, + 'rangeFormatting' + )!.dynamicRegistration = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentRangeFormattingProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: TextDocumentRegistrationOptions + ): [Disposable, DocumentRangeFormattingEditProvider] { + const provider: DocumentRangeFormattingEditProvider = { + provideDocumentRangeFormattingEdits: (document, range, options, token) => { + const client = this._client + const provideDocumentRangeFormattingEdits: ProvideDocumentRangeFormattingEditsSignature = (document, range, options, token) => { + const params: DocumentRangeFormattingParams = { + textDocument: { uri: document.uri }, + range, + options, + } + return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then(res => res, error => { + return client.handleFailedRequest(DocumentRangeFormattingRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideDocumentRangeFormattingEdits + ? middleware.provideDocumentRangeFormattingEdits(document, range, options, token, provideDocumentRangeFormattingEdits) + : provideDocumentRangeFormattingEdits(document, range, options, token) + } + } + + return [languages.registerDocumentRangeFormatProvider(options.documentSelector, provider), provider] + } +} + +class DocumentOnTypeFormattingFeature extends TextDocumentFeature< + DocumentOnTypeFormattingOptions, DocumentOnTypeFormattingRegistrationOptions, OnTypeFormattingEditProvider + > { + + constructor(client: BaseLanguageClient) { + super(client, DocumentOnTypeFormattingRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure(ensure(capabilities, 'textDocument')!, 'onTypeFormatting')!.dynamicRegistration = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentOnTypeFormattingProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider(options: DocumentOnTypeFormattingRegistrationOptions): [Disposable, OnTypeFormattingEditProvider] { + const provider: OnTypeFormattingEditProvider = { + provideOnTypeFormattingEdits: (document, position, ch, options, token) => { + const client = this._client + const provideOnTypeFormattingEdits: ProvideOnTypeFormattingEditsSignature = (document, position, ch, options, token) => { + const params: DocumentOnTypeFormattingParams = { + textDocument: cv.asVersionedTextDocumentIdentifier(document), + position, + ch, + options + } + return client.sendRequest(DocumentOnTypeFormattingRequest.type, params, token).then(res => res, (error) => { + return client.handleFailedRequest(DocumentOnTypeFormattingRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideOnTypeFormattingEdits + ? middleware.provideOnTypeFormattingEdits(document, position, ch, options, token, provideOnTypeFormattingEdits) + : provideOnTypeFormattingEdits(document, position, ch, options, token) + } + } + + const moreTriggerCharacter = options.moreTriggerCharacter || [] + const characters = [options.firstTriggerCharacter, ...moreTriggerCharacter] + return [languages.registerOnTypeFormattingEditProvider(options.documentSelector!, provider, characters), provider] + } +} + +interface DefaultBehavior { + defaultBehavior: boolean +} + +class RenameFeature extends TextDocumentFeature { + constructor(client: BaseLanguageClient) { + super(client, RenameRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let rename = ensure(ensure(capabilities, 'textDocument')!, 'rename')! + rename.dynamicRegistration = true + rename.prepareSupport = true + // TODO: capabilities + // rename.honorsChangeAnnotations = true + // rename.prepareSupportDefaultBehavior = PrepareSupportDefaultBehavior.Identifier + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.renameProvider) + if (!options) { + return + } + if (Is.boolean(capabilities.renameProvider)) { + options.prepareProvider = false + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider(options: RenameRegistrationOptions): [Disposable, RenameProvider] { + const provider: RenameProvider = { + provideRenameEdits: (document, position, newName, token) => { + const client = this._client + const provideRenameEdits: ProvideRenameEditsSignature = (document, position, newName, token) => { + const params: RenameParams = { + textDocument: { uri: document.uri }, + position, + newName: newName + } + return client.sendRequest(RenameRequest.type, params, token).then(res => res, (error: ResponseError) => { + return client.handleFailedRequest(RenameRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideRenameEdits + ? middleware.provideRenameEdits(document, position, newName, token, provideRenameEdits) + : provideRenameEdits(document, position, newName, token) + }, + prepareRename: options.prepareProvider + ? (document, position, token) => { + const client = this._client + const prepareRename: PrepareRenameSignature = (document, position, token) => { + const params: TextDocumentPositionParams = { + textDocument: cv.asTextDocumentIdentifier(document), + position + } + return client.sendRequest(PrepareRenameRequest.type, params, token).then( + (result) => { + if (Range.is(result)) { + return result + } else if (this.isDefaultBehavior(result)) { + return result.defaultBehavior === true ? null : Promise.reject(new Error(`The element can't be renamed.`)) + } else if (result && Range.is(result.range)) { + return { + range: result.range, + placeholder: result.placeholder + } + } + // To cancel the rename vscode API expects a rejected promise. + return Promise.reject(new Error(`The element can't be renamed.`)) + }, + (error: ResponseError) => { + return client.handleFailedRequest(PrepareRenameRequest.type, token, error, undefined) + } + ) + } + const middleware = client.clientOptions.middleware! + return middleware.prepareRename + ? middleware.prepareRename(document, position, token, prepareRename) + : prepareRename(document, position, token) + } + : undefined + } + + return [languages.registerRenameProvider(options.documentSelector, provider), provider] + } + + private isDefaultBehavior(value: any): value is DefaultBehavior { + const candidate: DefaultBehavior = value + return candidate && Is.boolean(candidate.defaultBehavior) + } +} + +class DocumentLinkFeature extends TextDocumentFeature { + constructor(client: BaseLanguageClient) { + super(client, DocumentLinkRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + const documentLinkCapabilities = ensure(ensure(capabilities, 'textDocument')!, 'documentLink')! + documentLinkCapabilities.dynamicRegistration = true + // TODO support tooltip + documentLinkCapabilities.tooltipSupport = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const options = this.getRegistrationOptions(documentSelector, capabilities.documentLinkProvider) + if (!options) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: options + }) + } + + protected registerLanguageProvider( + options: DocumentLinkRegistrationOptions + ): [Disposable, DocumentLinkProvider] { + const provider: DocumentLinkProvider = { + provideDocumentLinks: (document: TextDocument, token: CancellationToken): ProviderResult => { + const client = this._client + const provideDocumentLinks: ProvideDocumentLinksSignature = (document, token) => { + return client.sendRequest( + DocumentLinkRequest.type, + { + textDocument: { uri: document.uri } + }, + token + ).then(res => res, (error: ResponseError) => { + return client.handleFailedRequest(DocumentLinkRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideDocumentLinks + ? middleware.provideDocumentLinks(document, token, provideDocumentLinks) + : provideDocumentLinks(document, token) + }, + resolveDocumentLink: options.resolveProvider + ? (link, token) => { + const client = this._client + let resolveDocumentLink: ResolveDocumentLinkSignature = (link, token) => { + return client.sendRequest(DocumentLinkResolveRequest.type, link, token).then(res => res, (error: ResponseError) => { + return client.handleFailedRequest(DocumentLinkResolveRequest.type, token, error, link) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.resolveDocumentLink + ? middleware.resolveDocumentLink(link, token, resolveDocumentLink) + : resolveDocumentLink(link, token) + } + : undefined + } + + return [languages.registerDocumentLinkProvider(options.documentSelector, provider), provider] + } +} + +class ConfigurationFeature implements DynamicFeature { + private _listeners: Map = new Map() + + constructor(private _client: BaseLanguageClient) {} + + public get registrationType(): RegistrationType { + return DidChangeConfigurationNotification.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure(ensure(capabilities, 'workspace')!, 'didChangeConfiguration')!.dynamicRegistration = true + } + + public initialize(): void { + let section = this._client.clientOptions.synchronize?.configurationSection + if (section !== undefined) { + this.register({ + id: UUID.generateUuid(), + registerOptions: { + section: section + } + }) + } + } + + public register( + data: RegistrationData + ): void { + let { section } = data.registerOptions + let disposable = workspace.onDidChangeConfiguration((event) => { + if (typeof section == 'string' && !event.affectsConfiguration(section)) { + return + } + if (Array.isArray(section) && !section.some(v => event.affectsConfiguration(v))) { + return + } + if (section != undefined) { + this.onDidChangeConfiguration(data.registerOptions.section) + } + }) + this._listeners.set(data.id, disposable) + if (Is.string(section) && section.endsWith('.settings')) { + let settings = this.getConfiguredSettings(section as string) + if (!settings || Is.emptyObject(settings)) return + } + if (section != undefined) { + // Avoid server bug + this.onDidChangeConfiguration(data.registerOptions.section) + } + } + + public unregister(id: string): void { + let disposable = this._listeners.get(id) + if (disposable) { + this._listeners.delete(id) + disposable.dispose() + } + } + + public dispose(): void { + for (let disposable of this._listeners.values()) { + disposable.dispose() + } + this._listeners.clear() + } + + private onDidChangeConfiguration(configurationSection: string | string[]): void { + let isConfigured = typeof configurationSection === 'string' && configurationSection.startsWith('languageserver.') + let sections: string[] | undefined + if (Is.string(configurationSection)) { + sections = [configurationSection] + } else { + sections = configurationSection + } + let didChangeConfiguration = (sections: string[] | undefined): void => { + if (sections === undefined) { + this._client.sendNotification(DidChangeConfigurationNotification.type, { settings: null }) + return + } + this._client.sendNotification(DidChangeConfigurationNotification.type, { + settings: isConfigured ? this.getConfiguredSettings(sections[0]) : this.extractSettingsInformation(sections) + }) + } + let middleware = this.getMiddleware() + middleware + ? middleware(sections, didChangeConfiguration) + : didChangeConfiguration(sections) + } + + // for configured languageserver + private getConfiguredSettings(key: string): any { + let len = '.settings'.length + let config = workspace.getConfiguration(key.slice(0, - len)) + return config.get('settings', {}) + } + + private extractSettingsInformation(keys: string[]): any { + function ensurePath(config: any, path: string[]): any { + 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: number = key.indexOf('.') + let config: any = null + if (index >= 0) { + config = workspace.getConfiguration(key.substr(0, index)).get(key.substr(index + 1)) + } else { + config = workspace.getConfiguration(key) + } + if (config) { + let path = keys[i].split('.') + ensurePath(result, path)[path[path.length - 1]] = config + } + } + return result + } + + private getMiddleware() { + let middleware = this._client.clientOptions.middleware! + if (middleware.workspace && middleware.workspace.didChangeConfiguration) { + return middleware.workspace.didChangeConfiguration + } else { + return undefined + } + } +} + +class ExecuteCommandFeature + implements DynamicFeature { + private _commands: Map = new Map() + constructor(private _client: BaseLanguageClient) {} + + public get registrationType(): RegistrationType { + return ExecuteCommandRequest.type + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'workspace')!, + 'executeCommand' + )!.dynamicRegistration = true + } + + public initialize(capabilities: ServerCapabilities): void { + if (!capabilities.executeCommandProvider) { + return + } + this.register({ + id: UUID.generateUuid(), + registerOptions: Object.assign({}, capabilities.executeCommandProvider) + }) + } + + public register( + data: RegistrationData + ): void { + const client = this._client + const middleware = client.clientOptions.middleware! + const executeCommand: ExecuteCommandSignature = (command: string, args: any[]): any => { + const params: ExecuteCommandParams = { + command, + arguments: args + } + return client.sendRequest(ExecuteCommandRequest.type, params).then(undefined, (error) => { + client.handleFailedRequest(ExecuteCommandRequest.type, undefined, error, undefined) + throw error + }) + } + if (data.registerOptions.commands) { + let disposables: Disposable[] = [] + for (const command of data.registerOptions.commands) { + disposables.push(commands.registerCommand(command, (...args: any[]) => { + return middleware.executeCommand + ? middleware.executeCommand(command, args, executeCommand) + : executeCommand(command, args) + }, null, true)) + } + this._commands.set(data.id, disposables) + } + } + + public unregister(id: string): void { + let disposables = this._commands.get(id) + if (disposables) { + disposables.forEach(disposable => disposable.dispose()) + } + } + + public dispose(): void { + this._commands.forEach(value => { + value.forEach(disposable => disposable.dispose()) + }) + this._commands.clear() + } +} + +export interface MessageTransports { + reader: MessageReader + writer: MessageWriter + detached?: boolean +} + +export namespace MessageTransports { + export function is(value: any): value is MessageTransports { + let candidate: MessageTransports = value + return ( + candidate && + MessageReader.is(value.reader) && + MessageWriter.is(value.writer) + ) + } +} + +class OnReady { + private _used: boolean + constructor(private _resolve: () => void, private _reject: (error: any) => void) { + this._used = false + } + + public get isUsed(): boolean { + return this._used + } + + public resolve(): void { + this._used = true + this._resolve() + } + + public reject(error: any): void { + this._used = true + this._reject(error) + } +} + +export abstract class BaseLanguageClient { + private _id: string + private _name: string + private _markdownSupport: boolean + private _clientOptions: ResolvedClientOptions + + protected _state: ClientState + private _onReady: Promise + private _onReadyCallbacks: OnReady + private _onStop: Promise | undefined + private _connectionPromise: Promise | undefined + private _resolvedConnection: IConnection | undefined + private _initializeResult: InitializeResult | undefined + private _outputChannel: OutputChannel | undefined + private _capabilities: ServerCapabilities & ResolvedTextDocumentSyncCapabilities + + private _listeners: Disposable[] | undefined + private _providers: Disposable[] | undefined + private _diagnostics: DiagnosticCollection | undefined + private _syncedDocuments: Map + + private _fileEvents: FileEvent[] + private _fileEventDelayer: Delayer + private _stateChangeEmitter: Emitter + + private _traceFormat: TraceFormat + private _trace: Trace + private _tracer: Tracer + + public constructor( + id: string, + name: string, + clientOptions: LanguageClientOptions + ) { + this._id = id + this._name = name + if (clientOptions.outputChannel) { + this._outputChannel = clientOptions.outputChannel + } else { + this._outputChannel = undefined + } + let disableSnippetCompletion = false + let suggest = workspace.getConfiguration('suggest') + if (suggest.get('snippetsSupport', true) === false || clientOptions.disableSnippetCompletion) { + disableSnippetCompletion = true + } + + const markdown = { isTrusted: false } + if (clientOptions.markdown !== undefined && clientOptions.markdown.isTrusted === true) { + markdown.isTrusted = true + } + + this._clientOptions = { + disableWorkspaceFolders: clientOptions.disableWorkspaceFolders, + disableSnippetCompletion, + disableDynamicRegister: clientOptions.disableDynamicRegister, + disableDiagnostics: clientOptions.disableDiagnostics, + disableCompletion: clientOptions.disableCompletion, + formatterPriority: clientOptions.formatterPriority, + 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, + progressOnInitialization: !!clientOptions.progressOnInitialization, + errorHandler: clientOptions.errorHandler || this.createDefaultErrorHandler(clientOptions.connectionOptions?.maxRestartCount), + middleware: clientOptions.middleware || {}, + workspaceFolder: clientOptions.workspaceFolder, + connectionOptions: clientOptions.connectionOptions, + markdown + } + this.state = ClientState.Initial + this._connectionPromise = undefined + this._resolvedConnection = undefined + this._initializeResult = undefined + this._listeners = undefined + this._providers = undefined + this._diagnostics = undefined + + this._fileEvents = [] + this._fileEventDelayer = new Delayer(250) + this._onReady = new Promise((resolve, reject) => { + this._onReadyCallbacks = new OnReady(resolve, reject) + }) + this._onStop = undefined + this._stateChangeEmitter = new Emitter() + this._trace = Trace.Off + this._tracer = { + log: (messageOrDataObject: string | any, data?: string) => { + if (Is.string(messageOrDataObject)) { + this.logTrace(messageOrDataObject, data) + } else { + this.logObjectTrace(messageOrDataObject) + } + } + } + this._syncedDocuments = new Map() + let preferences = workspace.getConfiguration('coc.preferences') + this._markdownSupport = preferences.get('enableMarkdown', true) + this.registerBuiltinFeatures() + } + + public get supporedMarkupKind(): MarkupKind[] { + if (this._markdownSupport) return [MarkupKind.Markdown, MarkupKind.PlainText] + return [MarkupKind.PlainText] + } + + private get state(): ClientState { + return this._state + } + + public get id(): string { + return this._id + } + + public get name(): string { + return this._name + } + + private set state(value: ClientState) { + let oldState = this.getPublicState() + this._state = value + let newState = this.getPublicState() + if (newState !== oldState) { + this._stateChangeEmitter.fire({ oldState, newState }) + } + } + + public getPublicState(): State { + if (this.state === ClientState.Running) { + return State.Running + } else if (this.state === ClientState.Starting) { + return State.Starting + } else { + return State.Stopped + } + } + + public get initializeResult(): InitializeResult | undefined { + return this._initializeResult + } + + public sendRequest(type: ProtocolRequestType0, token?: CancellationToken): Promise + public sendRequest(type: ProtocolRequestType, params: P, token?: CancellationToken): Promise + public sendRequest(type: RequestType0, token?: CancellationToken): Promise + public sendRequest(type: RequestType, params: P, token?: CancellationToken): Promise + public sendRequest(method: string, token?: CancellationToken): Promise + public sendRequest(method: string, param: any, token?: CancellationToken): Promise + public sendRequest(type: string | MessageSignature, ...params: any[]): Promise { + if (!this.isConnectionActive()) { + throw new Error('Language client is not ready yet') + } + try { + return this._resolvedConnection!.sendRequest(type, ...params) + } catch (error) { + this.error( + `Sending request ${Is.string(type) ? type : type.method} failed.`, + error + ) + throw error + } + } + + public onRequest(type: ProtocolRequestType0, handler: RequestHandler0): Disposable + public onRequest(type: ProtocolRequestType, handler: RequestHandler): Disposable + public onRequest(type: RequestType0, handler: RequestHandler0): Disposable + public onRequest(type: RequestType, handler: RequestHandler): Disposable + public onRequest(method: string, handler: GenericRequestHandler): Disposable + public onRequest(type: string | MessageSignature, handler: GenericRequestHandler): Disposable { + if (!this.isConnectionActive()) { + throw new Error('Language client is not ready yet') + } + try { + return this._resolvedConnection!.onRequest(type, handler) + } catch (error) { + this.error( + `Registering request handler ${Is.string(type) ? type : type.method + } failed.`, + error + ) + throw error + } + } + + public sendNotification(type: ProtocolNotificationType0): void + public sendNotification(type: ProtocolNotificationType, params?: P): void + public sendNotification(type: NotificationType0): void + public sendNotification

    (type: NotificationType

    , params?: P): void + public sendNotification(method: string): void + public sendNotification(method: string, params: any): void + public sendNotification

    (type: string | MessageSignature, params?: P): void { + if (!this.isConnectionActive()) { + throw new Error('Language client is not ready yet') + } + try { + this._resolvedConnection!.sendNotification(type, params) + } catch (error) { + this.error( + `Sending notification ${Is.string(type) ? type : type.method} failed.`, + error + ) + throw error + } + } + + public onNotification(type: ProtocolNotificationType0, handler: NotificationHandler0): Disposable + public onNotification(type: ProtocolNotificationType, handler: NotificationHandler

    ): Disposable + public onNotification(type: NotificationType0, handler: NotificationHandler0): Disposable + public onNotification

    (type: NotificationType

    , handler: NotificationHandler

    ): Disposable + public onNotification(method: string, handler: GenericNotificationHandler): Disposable + public onNotification(type: string | MessageSignature, handler: GenericNotificationHandler): Disposable { + if (!this.isConnectionActive()) { + throw new Error('Language client is not ready yet') + } + try { + return this._resolvedConnection!.onNotification(type, handler) + } catch (error) { + this.error( + `Registering notification handler ${Is.string(type) ? type : type.method + } failed.`, + error + ) + throw error + } + } + + public onProgress

    (type: ProgressType, token: string | number, handler: NotificationHandler

    ): Disposable { + if (!this.isConnectionActive()) { + throw new Error('Language client is not ready yet') + } + try { + if (type == WorkDoneProgress.type) { + const handleWorkDoneProgress = this._clientOptions.middleware!.handleWorkDoneProgress + if (handleWorkDoneProgress !== undefined) { + return this._resolvedConnection!.onProgress(type, token, (params) => { + handleWorkDoneProgress(token, params as any, () => handler(params as unknown as P)) + }) + } + } + return this._resolvedConnection!.onProgress(type, token, handler) + } catch (error) { + this.error(`Registering progress handler for token ${token} failed.`, error) + throw error + } + } + + public sendProgress

    (type: ProgressType

    , token: string | number, value: P): void { + if (!this.isConnectionActive()) { + throw new Error('Language client is not ready yet') + } + try { + this._resolvedConnection!.sendProgress(type, token, value) + } catch (error) { + this.error(`Sending progress for token ${token} failed.`, error) + throw error + } + } + + public get clientOptions(): LanguageClientOptions { + return this._clientOptions + } + + public get onDidChangeState(): Event { + return this._stateChangeEmitter.event + } + + public get outputChannel(): OutputChannel { + if (!this._outputChannel) { + let { outputChannelName } = this._clientOptions + this._outputChannel = window.createOutputChannel(outputChannelName ? outputChannelName : this._name) + } + return this._outputChannel + } + + public get diagnostics(): DiagnosticCollection | undefined { + return this._diagnostics + } + + public createDefaultErrorHandler(maxRestartCount?: number): ErrorHandler { + return new DefaultErrorHandler(this._id, maxRestartCount ?? 4) + } + + public set trace(value: Trace) { + this._trace = value + this.onReady().then( + () => { + this.resolveConnection().then(connection => { + connection.trace(this._trace, this._tracer, { + sendNotification: false, + traceFormat: this._traceFormat + }) + }) + }, + () => {} + ) + } + + private logObjectTrace(data: any): void { + 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)}`) + } + } + + private data2String(data: any): string { + if (data instanceof ResponseError) { + const responseError = data as ResponseError + 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 as Error).message + } + if (Is.string(data)) { + return data + } + return data.toString() + } + + private _appendOutput(type: string, message: string, data?: any): void { + 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: string + if (data) { + dataString = this.data2String(data) + this.outputChannel.appendLine(dataString) + } + if (this._clientOptions.revealOutputChannelOn <= level) { + this.outputChannel.show(true) + } + } + + public info(message: string, data?: any): void { + this._appendOutput('Info', message, data) + } + + public warn(message: string, data?: any): void { + this._appendOutput('Warn', message, data) + } + + public error(message: string, data?: any): void { + this._appendOutput('Error', message, data) + } + + private logTrace(message: string, data?: any): void { + this.outputChannel.appendLine(`[Trace - ${(new Date().toLocaleTimeString())}] ${message}`) + if (data) { + this.outputChannel.appendLine(this.data2String(data)) + } + } + + public needsStart(): boolean { + return ( + this.state === ClientState.Initial || + this.state === ClientState.Stopping || + this.state === ClientState.Stopped + ) + } + + public needsStop(): boolean { + return ( + this.state === ClientState.Starting || this.state === ClientState.Running + ) + } + + public onReady(): Promise { + return this._onReady + } + + public get started(): boolean { + return this.state != ClientState.Initial + } + + private isConnectionActive(): boolean { + return this.state === ClientState.Running && !!this._resolvedConnection + } + + public start(): Disposable { + 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) { + let opts = this._clientOptions + let name = opts.diagnosticCollectionName ? opts.diagnosticCollectionName : this._id + this._diagnostics = languages.createDiagnosticCollection(name) + } + + this.state = ClientState.Starting + this.resolveConnection() + .then(connection => { + connection.onLogMessage(message => { + let kind: string + switch (message.type) { + case MessageType.Error: + kind = 'error' + this.error(message.message) + break + case MessageType.Warning: + kind = 'warning' + this.warn(message.message) + break + case MessageType.Info: + kind = 'info' + this.info(message.message) + break + default: + kind = 'log' + this.outputChannel.appendLine(message.message) + } + if (global.hasOwnProperty('__TEST__')) { + console.log(`[${kind}] ${message.message}`) + return + } + }) + connection.onShowMessage(message => { + switch (message.type) { + case MessageType.Error: + window.showErrorMessage(message.message) + break + case MessageType.Warning: + window.showWarningMessage(message.message) + break + case MessageType.Info: + window.showInformationMessage(message.message) + break + default: + window.showInformationMessage(message.message) + } + }) + connection.onRequest(ShowMessageRequest.type, params => { + let messageFunc: (message: string, ...items: T[]) => Thenable + switch (params.type) { + case MessageType.Error: + messageFunc = window.showErrorMessage.bind(window) + break + case MessageType.Warning: + messageFunc = window.showWarningMessage.bind(window) + break + case MessageType.Info: + messageFunc = window.showInformationMessage.bind(window) + break + default: + messageFunc = window.showInformationMessage.bind(window) + } + let actions = params.actions || [] + return messageFunc(params.message, ...actions) + }) + connection.onRequest(ShowDocumentRequest.type, async (params): Promise => { + const showDocument = async (params: ShowDocumentParams): Promise => { + try { + if (params.external === true) { + await workspace.openResource(params.uri) + return { success: true } + } else { + if (params.selection) { + params.selection.start + } + await workspace.jumpTo(params.uri, params.selection?.start) + return { success: true } + } + } catch (error) { + return { success: true } + } + } + const middleware = this._clientOptions.middleware.window?.showDocument + if (middleware !== undefined) { + return middleware(params, showDocument) + } else { + return showDocument(params) + } + }) + 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 Disposable.create(() => { + if (this.needsStop()) { + this.stop() + } + }) + } + + private resolveConnection(): Promise { + if (!this._connectionPromise) { + this._connectionPromise = this.createConnection() + } + return this._connectionPromise + } + + private resolveRootPath(): string | null | false { + if (this._clientOptions.workspaceFolder) { + return URI.parse(this._clientOptions.workspaceFolder.uri).fsPath + } + let { ignoredRootPaths } = this._clientOptions + let config = workspace.getConfiguration(this.id) + let rootPatterns = config.get('rootPatterns', []) + let required = config.get('requireRootPattern', false) + let resolved: string + if (rootPatterns && rootPatterns.length) { + let doc = workspace.getDocument(workspace.bufnr) + if (doc && doc.schema == 'file') { + let dir = path.dirname(URI.parse(doc.uri).fsPath) + resolved = resolveRoot(dir, rootPatterns, workspace.cwd) + } + } + if (required && !resolved) return false + let rootPath = resolved || workspace.rootPath || workspace.cwd + if (rootPath === os.homedir() || (ignoredRootPaths && ignoredRootPaths.includes(rootPath))) { + this.warn(`Ignored rootPath ${rootPath} of client "${this._id}"`) + return null + } + return rootPath + } + + private initialize(connection: IConnection): Promise { + this.refreshTrace(connection, false) + let { initializationOptions, progressOnInitialization } = this._clientOptions + let rootPath = this.resolveRootPath() + if (rootPath === false) { + console.warn(`required root pattern not found, server not started.`) + return + } + let initParams: any = { + processId: process.pid, + rootPath: rootPath ? rootPath : null, + rootUri: rootPath ? cv.asUri(URI.file(rootPath)) : null, + capabilities: this.computeClientCapabilities(), + initializationOptions: Is.func(initializationOptions) ? initializationOptions() : initializationOptions, + trace: Trace.toString(this._trace), + workspaceFolders: null, + locale: this.getLocale(), + clientInfo: { + name: 'coc.nvim', + version: workspace.version + } + } + this.fillInitializeParams(initParams) + if (progressOnInitialization) { + const token: ProgressToken = UUID.generateUuid() + initParams.workDoneToken = token + const part = new ProgressPart(connection, token) + part.begin({ title: `initializing ${this.id}`, kind: 'begin' }) + return this.doInitialize(connection, initParams).then((result) => { + part.done() + return result + }, (error) => { + part.cancel() + throw error + }) + } else { + return this.doInitialize(connection, initParams) + } + } + + private doInitialize(connection: IConnection, initParams: InitializeParams): Promise { + return connection.initialize(initParams).then(result => { + this._resolvedConnection = connection + this._initializeResult = result + this.state = ClientState.Running + + let textDocumentSyncOptions: TextDocumentSyncOptions | undefined = undefined + if (Is.number(result.capabilities.textDocumentSync)) { + if (result.capabilities.textDocumentSync === TextDocumentSyncKind.None) { + textDocumentSyncOptions = { + openClose: false, + change: TextDocumentSyncKind.None, + save: undefined + } + } else { + textDocumentSyncOptions = { + openClose: true, + change: result.capabilities.textDocumentSync, + save: { + includeText: false + } + } + } + } else if (result.capabilities.textDocumentSync != null && result.capabilities.textDocumentSync !== undefined) { + textDocumentSyncOptions = result.capabilities.textDocumentSync as TextDocumentSyncOptions + } + this._capabilities = Object.assign({}, result.capabilities, { + resolvedTextDocumentSync: textDocumentSyncOptions + }) + if (!this._clientOptions.disableDiagnostics) { + connection.onDiagnostics(params => this.handleDiagnostics(params)) + } + connection.onRequest(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(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(ApplyWorkspaceEditRequest.type, params => + this.handleApplyWorkspaceEdit(params) + ) + + connection.sendNotification(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 ResponseError && + error.data && + error.data.retry + ) { + window.showPrompt(error.message + ' Retry?').then(confirmed => { + if (confirmed) { + this.initialize(connection) + } else { + this.stop() + this._onReadyCallbacks.reject(error) + } + }) + } else { + if (error && error.message) { + window.showMessage(error.message, 'error') + } + this.error('Server initialization failed.', error) + this.stop() + this._onReadyCallbacks.reject(error) + } + throw error + }) + } + + public stop(): Promise { + 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.cleanUpChannel() + this._onStop = undefined + this._connectionPromise = undefined + this._resolvedConnection = undefined + }) + }).catch(e => { + logger.error('Error on stop languageserver:', e) + this.state = ClientState.Stopped + this.cleanUpChannel() + this._onStop = undefined + this._connectionPromise = undefined + this._resolvedConnection = undefined + })) + } + + private cleanUp(channel: boolean = true, diagnostics: boolean = true): void { + if (this._listeners) { + this._listeners.forEach(listener => listener.dispose()) + this._listeners = undefined + } + if (this._providers) { + this._providers.forEach(provider => provider.dispose()) + this._providers = undefined + } + for (let feature of this._features.values()) { + if (typeof feature.dispose === 'function') { + feature.dispose() + } else { + logger.error(`Feature can't be disposed`, feature) + } + } + if (this._syncedDocuments) { + this._syncedDocuments.clear() + } + if (channel) { + this.cleanUpChannel() + } + if (this._diagnostics) { + if (diagnostics) { + this._diagnostics.dispose() + this._diagnostics = undefined + } else { + this._diagnostics.clear() + } + } + } + + private cleanUpChannel(): void { + if (this._outputChannel) { + this._outputChannel.dispose() + this._outputChannel = undefined + } + } + + private notifyFileEvent(event: FileEvent): void { + const client = this + function didChangeWatchedFile(this: void, event: FileEvent) { + client._fileEvents.push(event) + client._fileEventDelayer.trigger(() => { + client.onReady().then(() => { + client.resolveConnection().then(connection => { + if (client.isConnectionActive()) { + connection.didChangeWatchedFiles({ changes: client._fileEvents }) + } + client._fileEvents = [] + }) + }, (error) => { + client.error(`Notify file events failed.`, error) + }) + }) + } + const workSpaceMiddleware = this.clientOptions.middleware?.workspace + workSpaceMiddleware?.didChangeWatchedFile ? workSpaceMiddleware.didChangeWatchedFile(event, didChangeWatchedFile) : didChangeWatchedFile(event) + } + + private handleDiagnostics(params: PublishDiagnosticsParams) { + 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) + } + } + + private setDiagnostics(uri: string, diagnostics: Diagnostic[] | undefined) { + if (!this._diagnostics) { + return + } + + const separate = workspace.getConfiguration('diagnostic').get('separateRelatedInformationAsDiagnostics') as boolean + if (separate && diagnostics.length > 0) { + const entries: Map = new Map() + entries.set(uri, diagnostics) + + for (const diagnostic of diagnostics) { + if (diagnostic.relatedInformation?.length) { + let message = `${diagnostic.message}\n\nRelated diagnostics:\n` + for (const info of diagnostic.relatedInformation) { + const basename = path.basename(URI.parse(info.location.uri).fsPath) + const ln = info.location.range.start.line + message = `${message}\n${basename}(line ${ln + 1}): ${info.message}` + + const diags: Diagnostic[] = entries.get(info.location.uri) || [] + diags.push(Diagnostic.create(info.location.range, info.message, DiagnosticSeverity.Hint, diagnostic.code, diagnostic.source)) + entries.set(info.location.uri, diags) + } + diagnostic.message = message + } + this._diagnostics.set(Array.from(entries)) + } + } else { + this._diagnostics.set(uri, diagnostics) + } + } + + protected abstract createMessageTransports( + encoding: string + ): Promise + + private createConnection(): Promise { + let errorHandler = (error: Error, message: Message | undefined, count: number | undefined) => { + 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, + this._clientOptions.connectionOptions + ) + }) + } + + protected handleConnectionClosed() { + // Check whether this is a normal shutdown in progress or the client stopped normally. + if (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 + if (this.state !== ClientState.Stopping) { + 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.' + ) + if (this.state === ClientState.Starting) { + this._onReadyCallbacks.reject(new Error(`Connection to server got closed. Server will not be restarted.`)) + this.state = ClientState.StartFailed + } else { + 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, true) + this.state = ClientState.Initial + this.start() + } + } + + public restart(): void { + this.cleanUp(true, false) + this.start() + } + + private handleConnectionError(error: Error, message: Message, count: number) { + 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() + } + } + + private hookConfigurationChanged(connection: IConnection): void { + workspace.onDidChangeConfiguration(() => { + this.refreshTrace(connection, true) + }) + } + + private refreshTrace( + connection: IConnection, + sendNotification: boolean = false + ): void { + let config = workspace.getConfiguration(this._id) + let trace: Trace = Trace.Off + let traceFormat: TraceFormat = TraceFormat.Text + if (config) { + const traceConfig = config.get('trace.server', 'off') + + if (typeof traceConfig === 'string') { + trace = Trace.fromString(traceConfig) + } else { + trace = Trace.fromString(config.get('trace.server.verbosity', 'off')) + traceFormat = TraceFormat.fromString(config.get('trace.server.format', 'text')) + } + } + this._trace = trace + this._traceFormat = traceFormat + connection.trace(this._trace, this._tracer, { + sendNotification, + traceFormat: this._traceFormat + }) + } + + private hookFileEvents(_connection: IConnection): void { + let fileEvents = this._clientOptions.synchronize.fileEvents + if (!fileEvents) return + let watchers: FileWatcher[] + if (Array.isArray(fileEvents)) { + watchers = fileEvents + } else { + watchers = [fileEvents] + } + if (!watchers) { + return + } + (this._dynamicFeatures.get( + DidChangeWatchedFilesNotification.type.method + )! as FileSystemWatcherFeature).registerRaw(UUID.generateUuid(), watchers) + } + + private readonly _features: (StaticFeature | DynamicFeature)[] = [] + private readonly _dynamicFeatures: Map> = new Map< + string, + DynamicFeature + >() + + public registerFeatures( + features: (StaticFeature | DynamicFeature)[] + ): void { + for (let feature of features) { + this.registerFeature(feature) + } + } + + public registerFeature(feature: StaticFeature | DynamicFeature): void { + this._features.push(feature) + if (DynamicFeature.is(feature)) { + const registrationType = feature.registrationType + this._dynamicFeatures.set(registrationType.method, feature) + } + } + + public getFeature(request: typeof DidOpenTextDocumentNotification.method): DynamicFeature & NotificationFeature<(textDocument: TextDocument) => void> + public getFeature(request: typeof DidChangeTextDocumentNotification.method): DynamicFeature & NotificationFeature<(textDocument: TextDocument) => void> + public getFeature(request: typeof WillSaveTextDocumentNotification.method): DynamicFeature & NotificationFeature<(textDocument: TextDocument) => void> + public getFeature(request: typeof WillSaveTextDocumentWaitUntilRequest.method): DynamicFeature & NotificationFeature<(textDocument: TextDocument) => ProviderResult> + public getFeature(request: typeof DidSaveTextDocumentNotification.method): DynamicFeature & NotificationFeature<(textDocument: TextDocument) => void> + public getFeature(request: typeof DidCloseTextDocumentNotification.method): DynamicFeature & NotificationFeature<(textDocument: TextDocument) => void> + public getFeature(request: typeof DidCreateFilesNotification.method): DynamicFeature & { send: (event: FileCreateEvent) => Promise } + public getFeature(request: typeof DidRenameFilesNotification.method): DynamicFeature & { send: (event: FileRenameEvent) => Promise } + public getFeature(request: typeof DidDeleteFilesNotification.method): DynamicFeature & { send: (event: FileDeleteEvent) => Promise } + public getFeature(request: typeof WillCreateFilesRequest.method): DynamicFeature & { send: (event: FileWillCreateEvent) => Promise } + public getFeature(request: typeof WillRenameFilesRequest.method): DynamicFeature & { send: (event: FileWillRenameEvent) => Promise } + public getFeature(request: typeof WillDeleteFilesRequest.method): DynamicFeature & { send: (event: FileWillDeleteEvent) => Promise } + public getFeature(request: typeof CompletionRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof HoverRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof SignatureHelpRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DefinitionRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof ReferencesRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DocumentHighlightRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof CodeActionRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DocumentFormattingRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DocumentRangeFormattingRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DocumentOnTypeFormattingRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof RenameRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DocumentSymbolRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DocumentLinkRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DocumentColorRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof DeclarationRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof FoldingRangeRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof ImplementationRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof SelectionRangeRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof TypeDefinitionRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof CallHierarchyPrepareRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof SemanticTokensRegistrationType.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof LinkedEditingRangeRequest.method): DynamicFeature & TextDocumentProviderFeature + public getFeature(request: typeof WorkspaceSymbolRequest.method): DynamicFeature & WorkspaceProviderFeature + public getFeature(request: string): DynamicFeature | undefined { + return this._dynamicFeatures.get(request) + } + + protected 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)) + } + + private fillInitializeParams(params: InitializeParams): void { + for (let feature of this._features) { + if (Is.func(feature.fillInitializeParams)) { + feature.fillInitializeParams(params) + } + } + } + + private computeClientCapabilities(): ClientCapabilities { + const result: ClientCapabilities = {} + ensure(result, 'workspace')!.applyEdit = true + const workspaceEdit = ensure(ensure(result, 'workspace')!, 'workspaceEdit')! + workspaceEdit.documentChanges = true + workspaceEdit.resourceOperations = [ResourceOperationKind.Create, ResourceOperationKind.Rename, ResourceOperationKind.Delete] + workspaceEdit.failureHandling = FailureHandlingKind.TextOnlyTransactional + // TODO: capabilities + // workspaceEdit.normalizesLineEndings = true + // workspaceEdit.changeAnnotationSupport = { + // groupsOnLabel: true + // } + const diagnostics = ensure(ensure(result, 'textDocument')!, 'publishDiagnostics')! + diagnostics.relatedInformation = true + diagnostics.versionSupport = false + diagnostics.tagSupport = { valueSet: [DiagnosticTag.Unnecessary, DiagnosticTag.Deprecated] } + // TODO: capabilities + // diagnostics.dataSupport = true + // diagnostics.codeDescriptionSupport = true + + // TODO: capabilities, disabled by default + const windowCapabilities = ensure(result, 'window')! + const showMessage = ensure(windowCapabilities, 'showMessage')! + showMessage.messageActionItem = { additionalPropertiesSupport: false } + const showDocument = ensure(windowCapabilities, 'showDocument')! + showDocument.support = false + + const generalCapabilities = ensure(result, 'general')! + generalCapabilities.regularExpressions = { engine: 'ECMAScript', version: 'ES2020' } + generalCapabilities.markdown = { parser: 'marked', version: '1.1.0' } + + for (let feature of this._features) { + feature.fillClientCapabilities(result) + } + return result + } + + private initializeFeatures(_connection: IConnection): void { + let documentSelector = this._clientOptions.documentSelector + for (let feature of this._features) { + feature.initialize(this._capabilities, documentSelector) + } + } + + private handleRegistrationRequest( + params: RegistrationParams + ): Promise { + if (this.clientOptions.disableDynamicRegister) return Promise.resolve() + return new Promise((resolve, reject) => { + for (const 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: RegistrationData = { + id: registration.id, + registerOptions: options + } + try { + feature.register(data) + } catch (err) { + reject(err) + return + } + } + resolve() + }) + } + + private handleUnregistrationRequest( + params: UnregistrationParams + ): Promise { + 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() + }) + } + + private handleApplyWorkspaceEdit( + params: ApplyWorkspaceEditParams + ): Promise { + // This is some sort of workaround since the version check should be done by VS Code in the Workspace.applyEdit. + // However doing it here adds some safety since the server can lag more behind then an extension. + let workspaceEdit: WorkspaceEdit = params.edit + let openTextDocuments: Map = new Map() + workspace.textDocuments.forEach((document) => openTextDocuments.set(document.uri.toString(), document)) + let versionMismatch = false + if (workspaceEdit.documentChanges) { + for (const change of workspaceEdit.documentChanges) { + if (TextDocumentEdit.is(change) && change.textDocument.version && change.textDocument.version >= 0) { + let textDocument = openTextDocuments.get(change.textDocument.uri) + if (textDocument && textDocument.version !== change.textDocument.version) { + versionMismatch = true + break + } + } + } + } + if (versionMismatch) { + return Promise.resolve({ applied: false }) + } + return workspace.applyEdit(params.edit).then(value => { + return { applied: value } + }) + } + + private getLocale(): string { + const lang = process.env.LANG + if (!lang) return 'en' + + return lang.split('.')[0] + } + + public handleFailedRequest(type: MessageSignature, token: CancellationToken | undefined, error: any, defaultValue: T): T { + // If we get a request cancel or a content modified don't log anything. + if (error instanceof ResponseError) { + if (error.code === LSPErrorCodes.RequestCancelled) { + if (token !== undefined && token.isCancellationRequested) { + return defaultValue + } + // do not throw error + } else if (error.code === LSPErrorCodes.ContentModified) { + return defaultValue + } + } + this.error(`Request ${type.method} failed.`, error) + } + + public logFailedRequest(type: any, error: any): void { + // If we get a request cancel don't log anything. + if (error instanceof ResponseError && error.code === LSPErrorCodes.RequestCancelled) { + // TODO: handle LSPErrorCodes.ContentModified + return + } + this.error(`Request ${type.method} failed.`, error) + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/colorProvider.ts b/vim-config/plugins/coc.nvim/src/language-client/colorProvider.ts new file mode 100644 index 00000000..fcfd1a5a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/colorProvider.ts @@ -0,0 +1,116 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { CancellationToken, ClientCapabilities, Color, ColorInformation, ColorPresentation, ColorPresentationRequest, Disposable, DocumentColorOptions, DocumentColorRegistrationOptions, DocumentColorRequest, DocumentSelector, Range, ServerCapabilities } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { DocumentColorProvider, ProviderResult } from '../provider' +import { BaseLanguageClient, TextDocumentFeature } from './client' + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export type ProvideDocumentColorsSignature = (document: TextDocument, token: CancellationToken) => ProviderResult + +export type ProvideColorPresentationSignature = ( + color: Color, + context: { document: TextDocument; range: Range }, + token: CancellationToken +) => ProviderResult + +export interface ColorProviderMiddleware { + provideDocumentColors?: ( + this: void, + document: TextDocument, + token: CancellationToken, + next: ProvideDocumentColorsSignature + ) => ProviderResult + provideColorPresentations?: ( + this: void, + color: Color, + context: { document: TextDocument; range: Range }, + token: CancellationToken, + next: ProvideColorPresentationSignature + ) => ProviderResult +} + +export class ColorProviderFeature extends TextDocumentFeature< + boolean | DocumentColorOptions, DocumentColorRegistrationOptions, DocumentColorProvider + > { + constructor(client: BaseLanguageClient) { + super(client, DocumentColorRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure( + ensure(capabilities, 'textDocument')!, + 'colorProvider' + )!.dynamicRegistration = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + let [id, options] = this.getRegistration(documentSelector, capabilities.colorProvider) + if (!id || !options) { + return + } + + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider( + options: DocumentColorRegistrationOptions + ): [Disposable, DocumentColorProvider] { + const provider: DocumentColorProvider = { + provideColorPresentations: (color, context, token) => { + const client = this._client + const provideColorPresentations: ProvideColorPresentationSignature = (color, context, token) => { + const requestParams = { + color, + textDocument: { uri: context.document.uri }, + range: context.range + } + return client.sendRequest(ColorPresentationRequest.type, requestParams, token).then( + res => res, + (error: any) => { + return client.handleFailedRequest(ColorPresentationRequest.type, token, error, null) + } + ) + } + const middleware = client.clientOptions.middleware + return middleware.provideColorPresentations + ? middleware.provideColorPresentations(color, context, token, provideColorPresentations) + : provideColorPresentations(color, context, token) + }, + provideDocumentColors: (document, token) => { + const client = this._client + const provideDocumentColors: ProvideDocumentColorsSignature = (document, token) => { + const requestParams = { + textDocument: { uri: document.uri } + } + return client.sendRequest(DocumentColorRequest.type, requestParams, token).then( + res => res, + (error: any) => { + return client.handleFailedRequest(ColorPresentationRequest.type, token, error, null) + } + ) + } + const middleware = client.clientOptions.middleware + return middleware.provideDocumentColors + ? middleware.provideDocumentColors(document, token, provideDocumentColors) + : provideDocumentColors(document, token) + } + } + + return [languages.registerDocumentColorProvider(options.documentSelector, provider), provider] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/configuration.ts b/vim-config/plugins/coc.nvim/src/language-client/configuration.ts new file mode 100644 index 00000000..c2c9f646 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/configuration.ts @@ -0,0 +1,94 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +import { ClientCapabilities, ConfigurationRequest } from 'vscode-languageserver-protocol' +import workspace from '../workspace' +import { BaseLanguageClient, StaticFeature } from './client' +const logger = require('../util/logger')('languageclient-configuration') + +export interface ConfigurationWorkspaceMiddleware { + configuration?: ConfigurationRequest.MiddlewareSignature +} + +export class ConfigurationFeature implements StaticFeature { + private languageserverSection: string | undefined + constructor(private _client: BaseLanguageClient) { + let section = this._client.clientOptions.synchronize?.configurationSection + if (typeof section === 'string' && section.startsWith('languageserver.')) { + this.languageserverSection = section + } + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + capabilities.workspace = capabilities.workspace || {} + capabilities.workspace.configuration = true + } + + public initialize(): void { + let client = this._client + client.onRequest(ConfigurationRequest.type, (params, token) => { + let configuration: ConfigurationRequest.HandlerSignature = params => { + let result: any[] = [] + 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) + }) + } + + private getConfiguration( + resource: string | undefined, + section: string | undefined + ): any { + let result: any = null + if (section) { + if (this.languageserverSection) { + section = `${this.languageserverSection}.${section}` + } + let index = section.lastIndexOf('.') + if (index === -1) { + result = toJSONObject(workspace.getConfiguration(undefined, resource).get(section)) + } else { + let config = workspace.getConfiguration(section.substr(0, index), resource) + if (config) { + result = toJSONObject(config.get(section.substr(index + 1))) + } + } + } else { + let config = workspace.getConfiguration(this.languageserverSection, resource) + result = {} + for (let key of Object.keys(config)) { + if (config.has(key)) { + result[key] = toJSONObject(config.get(key)) + } + } + } + return result + } + + public dispose(): void { + } +} + +export function toJSONObject(obj: any): any { + if (obj) { + if (Array.isArray(obj)) { + return obj.map(toJSONObject) + } else if (typeof obj === 'object') { + const res = Object.create(null) + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + res[key] = toJSONObject(obj[key]) + } + } + return res + } + } + return obj +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/declaration.ts b/vim-config/plugins/coc.nvim/src/language-client/declaration.ts new file mode 100644 index 00000000..2e1a195e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/declaration.ts @@ -0,0 +1,67 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { CancellationToken, ClientCapabilities, Declaration, DeclarationLink, DeclarationOptions, DeclarationRegistrationOptions, DeclarationRequest, Disposable, DocumentSelector, Position, ServerCapabilities } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { DeclarationProvider, ProviderResult } from '../provider' +import { BaseLanguageClient, TextDocumentFeature } from './client' +import { asTextDocumentPositionParams } from './utils/converter' + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export interface ProvideDeclarationSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult +} + +export interface DeclarationMiddleware { + provideDeclaration?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: ProvideDeclarationSignature) => ProviderResult +} + +export class DeclarationFeature extends TextDocumentFeature { + + constructor(client: BaseLanguageClient) { + super(client, DeclarationRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let declarationSupport = ensure(ensure(capabilities, 'textDocument')!, 'declaration')! + declarationSupport.dynamicRegistration = true + // declarationSupport.linkSupport = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + const [id, options] = this.getRegistration(documentSelector, capabilities.declarationProvider) + if (!id || !options) { + return + } + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider(options: DeclarationRegistrationOptions): [Disposable, DeclarationProvider] { + const provider: DeclarationProvider = { + provideDeclaration: (document: TextDocument, position: Position, token: CancellationToken) => { + const client = this._client + const provideDeclaration: ProvideDeclarationSignature = (document, position, token) => client.sendRequest(DeclarationRequest.type, asTextDocumentPositionParams(document, position), token).then( + res => res, error => { + return client.handleFailedRequest(DeclarationRequest.type, token, error, null) + } + ) + const middleware = client.clientOptions.middleware + return middleware.provideDeclaration + ? middleware.provideDeclaration(document, position, token, provideDeclaration) + : provideDeclaration(document, position, token) + } + } + + return [languages.registerDeclarationProvider(options.documentSelector, provider), provider] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/fileOperations.ts b/vim-config/plugins/coc.nvim/src/language-client/fileOperations.ts new file mode 100644 index 00000000..3d3397c1 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/fileOperations.ts @@ -0,0 +1,436 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as minimatch from 'minimatch' +import { ClientCapabilities, CreateFilesParams, DeleteFilesParams, DidCreateFilesNotification, DidDeleteFilesNotification, DidRenameFilesNotification, Disposable, Event, FileOperationClientCapabilities, FileOperationOptions, FileOperationPatternKind, FileOperationPatternOptions, FileOperationRegistrationOptions, ProtocolNotificationType, ProtocolRequestType, RegistrationType, RenameFilesParams, ServerCapabilities, WillCreateFilesRequest, WillDeleteFilesRequest, WillRenameFilesRequest, WorkspaceEdit } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import { FileCreateEvent, FileDeleteEvent, FileRenameEvent, FileType, FileWillCreateEvent, FileWillDeleteEvent, FileWillRenameEvent } from '../types' +import { statAsync } from '../util/fs' +import workspace from '../workspace' +import { BaseLanguageClient, DynamicFeature, NextSignature, RegistrationData } from './client' +import * as UUID from './utils/uuid' +const logger = require('../util/logger')('language-client-fileOperations') + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +function access(target: T, key: K): T[K] { + return target[key] +} + +function assign(target: T, key: K, value: T[K]): void { + target[key] = value +} + +function asCreateDeleteFilesParams(e: FileCreateEvent | FileDeleteEvent): CreateFilesParams | DeleteFilesParams { + return { + files: e.files.map(f => ({uri: f.toString()})) + } +} + +function asRenameFilesParams(e: FileRenameEvent | FileWillRenameEvent): RenameFilesParams { + return { + files: e.files.map(f => ({oldUri: f.oldUri.toString(), newUri: f.newUri.toString()})) + } +} + +/** + * File operation middleware + * + * @since 3.16.0 + */ +export interface FileOperationsMiddleware { + didCreateFiles?: NextSignature; + willCreateFiles?: NextSignature>; + didRenameFiles?: NextSignature; + willRenameFiles?: NextSignature>; + didDeleteFiles?: NextSignature; + willDeleteFiles?: NextSignature>; +} + +interface EventWithFiles { + readonly files: ReadonlyArray; +} + +abstract class FileOperationFeature> + implements DynamicFeature { + protected _client: BaseLanguageClient + private _event: Event + private _registrationType: RegistrationType + private _clientCapability: keyof FileOperationClientCapabilities + private _serverCapability: keyof FileOperationOptions + private _listener: Disposable | undefined + private _filters = new Map< + string, + Array<{ + scheme?: string; + matcher: minimatch.IMinimatch; + kind?: FileOperationPatternKind; + }> + >() + + constructor( + client: BaseLanguageClient, + event: Event, + registrationType: RegistrationType, + clientCapability: keyof FileOperationClientCapabilities, + serverCapability: keyof FileOperationOptions + ) { + this._client = client + this._event = event + this._registrationType = registrationType + this._clientCapability = clientCapability + this._serverCapability = serverCapability + } + + public get registrationType(): RegistrationType { + return this._registrationType + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + const value = ensure(ensure(capabilities, 'workspace')!, 'fileOperations')! + // this happens n times but it is the same value so we tolerate this. + assign(value, 'dynamicRegistration', true) + assign(value, this._clientCapability, true) + } + + public initialize(capabilities: ServerCapabilities): void { + const options = capabilities.workspace?.fileOperations + const capability = options !== undefined ? access(options, this._serverCapability) : undefined + if (capability?.filters !== undefined) { + try { + this.register({ + id: UUID.generateUuid(), + registerOptions: { filters: capability.filters }, + }) + } catch (e) { + this._client.warn( + `Ignoring invalid glob pattern for ${this._serverCapability} registration: ${e}` + ) + } + } + } + + public register(data: RegistrationData): void { + if (!this._listener) { + this._listener = this._event(this.send, this) + } + const minimatchFilter = data.registerOptions.filters.map(filter => { + const matcher = new minimatch.Minimatch( + filter.pattern.glob, + FileOperationFeature.asMinimatchOptions(filter.pattern.options) + ) + if (!matcher.makeRe()) { + throw new Error(`Invalid pattern ${filter.pattern.glob}!`) + } + return { scheme: filter.scheme, matcher, kind: filter.pattern.matches } + }) + this._filters.set(data.id, minimatchFilter) + } + + public abstract send(data: E): Promise + + public unregister(id: string): void { + this._filters.delete(id) + if (this._filters.size === 0 && this._listener) { + this._listener.dispose() + this._listener = undefined + } + } + + public dispose(): void { + this._filters.clear() + if (this._listener) { + this._listener.dispose() + this._listener = undefined + } + } + + protected async filter(event: E, prop: (i: I) => URI): Promise { + // (Asynchronously) map each file onto a boolean of whether it matches + // any of the globs. + const fileMatches = await Promise.all( + event.files.map(async item => { + const uri = prop(item) + // Use fsPath to make this consistent with file system watchers but help + // minimatch to use '/' instead of `\\` if present. + const path = uri.fsPath.replace(/\\/g, '/') + for (const filters of this._filters.values()) { + for (const filter of filters) { + if (filter.scheme !== undefined && filter.scheme !== uri.scheme) { + continue + } + if (filter.matcher.match(path)) { + // The pattern matches. If kind is undefined then everything is ok + if (filter.kind === undefined) { + return true + } + const fileType = await FileOperationFeature.getFileType(uri) + // If we can't determine the file type than we treat it as a match. + // Dropping it would be another alternative. + if (fileType === undefined) { + this._client.error( + `Failed to determine file type for ${uri.toString()}.` + ) + return true + } + if ( + (fileType === FileType.File && filter.kind === FileOperationPatternKind.file) || + (fileType === FileType.Directory && filter.kind === FileOperationPatternKind.folder) + ) { + return true + } + } else if (filter.kind === FileOperationPatternKind.folder) { + const fileType = await FileOperationFeature.getFileType(uri) + if (fileType === FileType.Directory && filter.matcher.match(`${path}/`)) { + return true + } + } + } + } + return false + }) + ) + + // Filter the files to those that matched. + const files = event.files.filter((_, index) => fileMatches[index]) + + return { ...event, files } + } + + private static async getFileType(uri: URI): Promise { + try { + const stat = await statAsync(uri.fsPath) + if (stat.isFile()) { + return FileType.File + } + if (stat.isDirectory()) { + return FileType.Directory + } + if (stat.isSymbolicLink()) { + return FileType.SymbolicLink + } + return FileType.Unknown + } catch (e) { + return undefined + } + } + + private static asMinimatchOptions(options: FileOperationPatternOptions | undefined): minimatch.IOptions | undefined { + if (options === undefined) { + return undefined + } + if (options.ignoreCase === true) { + return { nocase: true } + } + return undefined + } +} + +abstract class NotificationFileOperationFeature; }, P> extends FileOperationFeature { + + private _notificationType: ProtocolNotificationType + private _accessUri: (i: I) => URI + private _createParams: (e: E) => P + + constructor( + client: BaseLanguageClient, + event: Event, + notificationType: ProtocolNotificationType, + clientCapability: keyof FileOperationClientCapabilities, + serverCapability: keyof FileOperationOptions, + accessUri: (i: I) => URI, + createParams: (e: E) => P + ) { + super(client, event, notificationType, clientCapability, serverCapability) + this._notificationType = notificationType + this._accessUri = accessUri + this._createParams = createParams + } + + public async send(originalEvent: E): Promise { + // Create a copy of the event that has the files filtered to match what the + // server wants. + const filteredEvent = await this.filter(originalEvent, this._accessUri) + if (filteredEvent.files.length) { + const next = async (event: E): Promise => { + this._client.sendNotification( + this._notificationType, + this._createParams(event) + ) + } + this.doSend(filteredEvent, next) + } + } + + protected abstract doSend(event: E, next: (event: E) => void): void +} + +export class DidCreateFilesFeature extends NotificationFileOperationFeature { + constructor(client: BaseLanguageClient) { + super( + client, + workspace.onDidCreateFiles, + DidCreateFilesNotification.type, + 'didCreate', + 'didCreate', + (i: URI) => i, + e => asCreateDeleteFilesParams(e), + ) + } + + protected doSend(event: FileCreateEvent, next: (event: FileCreateEvent) => void): void { + const middleware = this._client.clientOptions.middleware?.workspace + return middleware?.didCreateFiles ? middleware.didCreateFiles(event, next) : next(event) + } +} + +export class DidRenameFilesFeature extends NotificationFileOperationFeature<{ oldUri: URI; newUri: URI }, FileRenameEvent, RenameFilesParams> { + constructor(client: BaseLanguageClient) { + super( + client, + workspace.onDidRenameFiles, + DidRenameFilesNotification.type, + 'didRename', + 'didRename', + (i: { oldUri: URI; newUri: URI }) => i.oldUri, + e => asRenameFilesParams(e) + ) + } + + protected doSend(event: FileRenameEvent, next: (event: FileRenameEvent) => void): void { + const middleware = this._client.clientOptions.middleware?.workspace + return middleware?.didRenameFiles ? middleware.didRenameFiles(event, next) : next(event) + } +} + +export class DidDeleteFilesFeature extends NotificationFileOperationFeature { + constructor(client: BaseLanguageClient) { + super( + client, + workspace.onDidDeleteFiles, + DidDeleteFilesNotification.type, + 'didDelete', + 'didDelete', + (i: URI) => i, + e => asCreateDeleteFilesParams(e) + ) + } + + protected doSend(event: FileCreateEvent, next: (event: FileCreateEvent) => void): void { + const middleware = this._client.clientOptions.middleware?.workspace + return middleware?.didDeleteFiles ? middleware.didDeleteFiles(event, next) : next(event) + } +} + +interface RequestEvent { + readonly files: ReadonlyArray; + waitUntil(thenable: Thenable): void; +} + +abstract class RequestFileOperationFeature, P> extends FileOperationFeature { + private _requestType: ProtocolRequestType + private _accessUri: (i: I) => URI + private _createParams: (e: EventWithFiles) => P + + constructor( + client: BaseLanguageClient, + event: Event, + requestType: ProtocolRequestType, + clientCapability: keyof FileOperationClientCapabilities, + serverCapability: keyof FileOperationOptions, + accessUri: (i: I) => URI, + createParams: (e: EventWithFiles) => P + ) { + super(client, event, requestType, clientCapability, serverCapability) + this._requestType = requestType + this._accessUri = accessUri + this._createParams = createParams + } + + public async send(originalEvent: E & RequestEvent): Promise { + const waitUntil = this.waitUntil(originalEvent) + originalEvent.waitUntil(waitUntil) + } + + private async waitUntil(originalEvent: E): Promise { + // Create a copy of the event that has the files filtered to match what the + // server wants. + const filteredEvent = await this.filter(originalEvent, this._accessUri) + + if (filteredEvent.files.length) { + const next = (event: EventWithFiles): Promise => { + return this._client.sendRequest(this._requestType, this._createParams(event)) + } + return this.doSend(filteredEvent, next) + } else { + return undefined + } + } + + protected abstract doSend(event: E, next: (event: EventWithFiles) => Thenable | Thenable): Thenable | Thenable +} + +export class WillCreateFilesFeature extends RequestFileOperationFeature { + constructor(client: BaseLanguageClient) { + super( + client, + workspace.onWillCreateFiles, + WillCreateFilesRequest.type, + 'willCreate', + 'willCreate', + (i: URI) => i, + e => asCreateDeleteFilesParams(e) + ) + } + + protected doSend(event: FileWillCreateEvent, next: (event: FileCreateEvent) => Thenable | Thenable): Thenable | Thenable { + const middleware = this._client.clientOptions.middleware?.workspace + return middleware?.willCreateFiles ? middleware.willCreateFiles(event, next) : next(event) + } +} + +export class WillRenameFilesFeature extends RequestFileOperationFeature<{ oldUri: URI; newUri: URI }, FileWillRenameEvent, RenameFilesParams> { + constructor(client: BaseLanguageClient) { + super( + client, + workspace.onWillRenameFiles, + WillRenameFilesRequest.type, + 'willRename', + 'willRename', + (i: { oldUri: URI; newUri: URI }) => i.oldUri, + e => asRenameFilesParams(e) + ) + } + + protected doSend(event: FileWillRenameEvent, next: (event: FileRenameEvent) => Thenable | Thenable): Thenable | Thenable { + const middleware = this._client.clientOptions.middleware?.workspace + return middleware?.willRenameFiles ? middleware.willRenameFiles(event, next) : next(event) + } +} + +export class WillDeleteFilesFeature extends RequestFileOperationFeature { + constructor(client: BaseLanguageClient) { + super( + client, + workspace.onWillDeleteFiles, + WillDeleteFilesRequest.type, + 'willDelete', + 'willDelete', + (i: URI) => i, + e => asCreateDeleteFilesParams(e) + ) + } + + protected doSend(event: FileWillDeleteEvent, next: (event: FileDeleteEvent) => Thenable | Thenable): Thenable | Thenable { + const middleware = this._client.clientOptions.middleware?.workspace + return middleware?.willDeleteFiles ? middleware.willDeleteFiles(event, next) : next(event) + } +} + diff --git a/vim-config/plugins/coc.nvim/src/language-client/foldingRange.ts b/vim-config/plugins/coc.nvim/src/language-client/foldingRange.ts new file mode 100644 index 00000000..07ce1b4d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/foldingRange.ts @@ -0,0 +1,90 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { CancellationToken, ClientCapabilities, Disposable, DocumentSelector, FoldingRange, FoldingRangeOptions, FoldingRangeParams, FoldingRangeRegistrationOptions, FoldingRangeRequest, ServerCapabilities } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { FoldingContext, FoldingRangeProvider, ProviderResult } from '../provider' +import { BaseLanguageClient, TextDocumentFeature } from './client' + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export type ProvideFoldingRangeSignature = ( + this: void, + document: TextDocument, + context: FoldingContext, + token: CancellationToken +) => ProviderResult + +export interface FoldingRangeProviderMiddleware { + provideFoldingRanges?: ( + this: void, + document: TextDocument, + context: FoldingContext, + token: CancellationToken, + next: ProvideFoldingRangeSignature + ) => ProviderResult +} + +export class FoldingRangeFeature extends TextDocumentFeature< + boolean | FoldingRangeOptions, FoldingRangeRegistrationOptions, FoldingRangeProvider + > { + constructor(client: BaseLanguageClient) { + super(client, FoldingRangeRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + let capability = ensure( + ensure(capabilities, 'textDocument')!, + 'foldingRange' + )! + capability.dynamicRegistration = true + capability.rangeLimit = 5000 + capability.lineFoldingOnly = true + } + + public initialize( + capabilities: ServerCapabilities, + documentSelector: DocumentSelector + ): void { + const [id, options] = this.getRegistration(documentSelector, capabilities.foldingRangeProvider) + if (!id || !options) { + return + } + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider( + options: FoldingRangeRegistrationOptions + ): [Disposable, FoldingRangeProvider] { + const provider: FoldingRangeProvider = { + provideFoldingRanges: (document, context, token) => { + const client = this._client + const provideFoldingRanges: ProvideFoldingRangeSignature = (document, _, token) => { + const requestParams: FoldingRangeParams = { + textDocument: { uri: document.uri } + } + return client.sendRequest(FoldingRangeRequest.type, requestParams, token).then( + res => res, (error: any) => { + return client.handleFailedRequest(FoldingRangeRequest.type, token, error, null) + } + ) + } + const middleware = client.clientOptions.middleware + return middleware.provideFoldingRanges + ? middleware.provideFoldingRanges(document, context, token, provideFoldingRanges) + : provideFoldingRanges(document, context, token) + } + } + + return [languages.registerFoldingRangeProvider(options.documentSelector, provider), provider] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/implementation.ts b/vim-config/plugins/coc.nvim/src/language-client/implementation.ts new file mode 100644 index 00000000..1874beec --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/implementation.ts @@ -0,0 +1,65 @@ +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { CancellationToken, ClientCapabilities, Definition, DefinitionLink, Disposable, DocumentSelector, ImplementationOptions, ImplementationRegistrationOptions, ImplementationRequest, Position, ServerCapabilities } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { ImplementationProvider, ProviderResult } from '../provider' +import { BaseLanguageClient, TextDocumentFeature } from './client' +import * as cv from './utils/converter' + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export interface ProvideImplementationSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult +} + +export interface ImplementationMiddleware { + provideImplementation?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: ProvideImplementationSignature) => ProviderResult +} + +export class ImplementationFeature extends TextDocumentFeature { + + constructor(client: BaseLanguageClient) { + super(client, ImplementationRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + const implementationSupport = ensure(ensure(capabilities, 'textDocument')!, 'implementation')! + implementationSupport.dynamicRegistration = true + // implementationSupport.linkSupport = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + const [id, options] = this.getRegistration(documentSelector, capabilities.implementationProvider) + if (!id || !options) { + return + } + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider(options: ImplementationRegistrationOptions): [Disposable, ImplementationProvider] { + const provider: ImplementationProvider = { + provideImplementation: (document, position, token) => { + const client = this._client + const provideImplementation: ProvideImplementationSignature = (document, position, token) => client.sendRequest(ImplementationRequest.type, cv.asTextDocumentPositionParams(document, position), token).then( + res => res, error => { + return client.handleFailedRequest(ImplementationRequest.type, token, error, null) + } + ) + const middleware = client.clientOptions.middleware + return middleware.provideImplementation + ? middleware.provideImplementation(document, position, token, provideImplementation) + : provideImplementation(document, position, token) + } + } + + return [languages.registerImplementationProvider(options.documentSelector, provider), provider] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/index.ts b/vim-config/plugins/coc.nvim/src/language-client/index.ts new file mode 100644 index 00000000..e7fdfc85 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/index.ts @@ -0,0 +1,637 @@ +/* eslint-disable no-redeclare */ +import cp from 'child_process' +import fs from 'fs' +import path from 'path' +import { createClientPipeTransport, createClientSocketTransport, Disposable, generateRandomPipeName, IPCMessageReader, IPCMessageWriter, StreamMessageReader, StreamMessageWriter } from 'vscode-languageserver-protocol/node' +import { ServiceStat } from '../types' +import { disposeAll } from '../util' +import * as Is from '../util/is' +import { terminate } from '../util/processes' +import workspace from '../workspace' +import { BaseLanguageClient, ClientState, DynamicFeature, LanguageClientOptions, MessageTransports, StaticFeature } from './client' +import { ColorProviderFeature } from './colorProvider' +import { ConfigurationFeature as PullConfigurationFeature } from './configuration' +import { DeclarationFeature } from './declaration' +import { FoldingRangeFeature } from './foldingRange' +import { ImplementationFeature } from './implementation' +import { ProgressFeature } from './progress' +import { TypeDefinitionFeature } from './typeDefinition' +import { WorkspaceFoldersFeature } from './workspaceFolders' +import { SelectionRangeFeature } from './selectionRange' +import ChildProcess = cp.ChildProcess +import { CallHierarchyFeature } from './callHierarchy' +import { SemanticTokensFeature } from './semanticTokens' +import { LinkedEditingFeature } from './linkedEditingRange' +import { DidCreateFilesFeature, DidDeleteFilesFeature, DidRenameFilesFeature, WillCreateFilesFeature, WillDeleteFilesFeature, WillRenameFilesFeature } from './fileOperations' + +const logger = require('../util/logger')('language-client-index') + +export * from './client' + +declare let v8debug: any + +export interface ExecutableOptions { + cwd?: string + env?: any + detached?: boolean + shell?: boolean +} + +export interface Executable { + command: string + args?: string[] + options?: ExecutableOptions +} + +namespace Executable { + export function is(value: any): value is Executable { + return Is.string(value.command) + } +} + +export interface ForkOptions { + cwd?: string + env?: any + execPath?: string + encoding?: string + execArgv?: string[] +} + +export enum TransportKind { + stdio, + ipc, + pipe, + socket +} + +export interface SocketTransport { + kind: TransportKind.socket + port: number +} + +namespace Transport { + export function isSocket(value: Transport): value is SocketTransport { + let candidate = value as SocketTransport + return ( + candidate && + candidate.kind === TransportKind.socket && + Is.number(candidate.port) + ) + } +} + +/** + * To avoid any timing, pipe name or port number issues the pipe (TransportKind.pipe) + * and the sockets (TransportKind.socket and SocketTransport) are owned by the + * VS Code processes. The server process simply connects to the pipe / socket. + * In node term the VS Code process calls `createServer`, then starts the server + * process, waits until the server process has connected to the pipe / socket + * and then signals that the connection has been established and messages can + * be send back and forth. If the language server is implemented in a different + * programm language the server simply needs to create a connection to the + * passed pipe name or port number. + */ +export type Transport = TransportKind | SocketTransport + +export interface NodeModule { + module: string + transport?: Transport + args?: string[] + runtime?: string + options?: ForkOptions +} + +namespace NodeModule { + export function is(value: any): value is NodeModule { + return Is.string(value.module) + } +} + +export interface StreamInfo { + writer: NodeJS.WritableStream + reader: NodeJS.ReadableStream + detached?: boolean +} + +namespace StreamInfo { + export function is(value: any): value is StreamInfo { + let candidate = value as StreamInfo + return ( + candidate && candidate.writer !== void 0 && candidate.reader !== void 0 + ) + } +} + +export interface ChildProcessInfo { + process: ChildProcess + detached: boolean +} + +namespace ChildProcessInfo { + export function is(value: any): value is ChildProcessInfo { + let candidate = value as ChildProcessInfo + return ( + candidate && + candidate.process !== void 0 && + typeof candidate.detached === 'boolean' + ) + } +} + +export type ServerOptions = + | Executable + | { run: Executable; debug: Executable } + | { run: NodeModule; debug: NodeModule } + | NodeModule + | (() => Promise) + +export class LanguageClient extends BaseLanguageClient { + private _forceDebug: boolean + private _serverProcess: ChildProcess | undefined + private _isDetached: boolean | undefined + private _serverOptions: ServerOptions + + public constructor( + name: string, + serverOptions: ServerOptions, + clientOptions: LanguageClientOptions, + forceDebug?: boolean + ) + public constructor( + id: string, + name: string, + serverOptions: ServerOptions, + clientOptions: LanguageClientOptions, + forceDebug?: boolean + ) + public constructor( + arg1: string, + arg2: string | ServerOptions, + arg3: LanguageClientOptions | ServerOptions, + arg4?: boolean | LanguageClientOptions, + arg5?: boolean + ) { + let id: string + let name: string + let serverOptions: ServerOptions + let clientOptions: LanguageClientOptions + let forceDebug: boolean + if (Is.string(arg2)) { + id = arg1 + name = arg2 + serverOptions = arg3 as ServerOptions + clientOptions = arg4 as LanguageClientOptions + forceDebug = !!arg5 + } else { + // first signature + id = arg1.toLowerCase() + name = arg1 + serverOptions = arg2 + clientOptions = arg3 as LanguageClientOptions + forceDebug = arg4 as boolean + } + if (forceDebug === void 0) { + forceDebug = false + } + super(id, name, clientOptions) + this._serverOptions = serverOptions + this._forceDebug = forceDebug + this.registerProposedFeatures() + } + + public stop(): Promise { + 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 + } + }) + } + + public get serviceState(): ServiceStat { + let state = this._state + switch (state) { + case ClientState.Initial: + return ServiceStat.Initial + case ClientState.Running: + return ServiceStat.Running + case ClientState.StartFailed: + return ServiceStat.StartFailed + case ClientState.Starting: + return ServiceStat.Starting + case ClientState.Stopped: + return ServiceStat.Stopped + case ClientState.Stopping: + return ServiceStat.Stopping + default: + logger.error(`Unknown state: ${state}`) + return ServiceStat.Stopped + } + } + + public static stateName(state: ClientState): string { + switch (state) { + case ClientState.Initial: + return 'Initial' + case ClientState.Running: + return 'Running' + case ClientState.StartFailed: + return 'StartFailed' + case ClientState.Starting: + return 'Starting' + case ClientState.Stopped: + return 'Stopped' + case ClientState.Stopping: + return 'Stopping' + default: + return 'Unknonw' + } + } + + private checkProcessDied(childProcess: ChildProcess | undefined): void { + if (!childProcess || global.hasOwnProperty('__TEST__')) return + if (global.hasOwnProperty('__TEST__')) { + process.kill(childProcess.pid, 0) + return + } + setTimeout(() => { + // Test if the process is still alive. Throws an exception if not + try { + process.kill(childProcess.pid, 0) + terminate(childProcess) + } catch (error) { + // All is fine. + } + }, 2000) + } + + protected handleConnectionClosed(): void { + this._serverProcess = undefined + super.handleConnectionClosed() + } + + protected createMessageTransports(encoding: string): Promise { + + function getEnvironment(env: any, fork: boolean): any { + if (!env && !fork) { + return undefined + } + let result: any = Object.create(null) + Object.keys(process.env).forEach(key => result[key] = process.env[key]) + if (env) { + Object.keys(env).forEach(key => result[key] = env[key]) + } + return result + } + + const debugStartWith: string[] = ['--debug=', '--debug-brk=', '--inspect=', '--inspect-brk='] + const debugEquals: string[] = ['--debug', '--debug-brk', '--inspect', '--inspect-brk'] + function startedInDebugMode(): boolean { + let args: string[] = (process as any).execArgv + if (args) { + return args.some(arg => { + return debugStartWith.some(value => arg.startsWith(value)) || + debugEquals.some(value => arg === value) + }) + } + return false + } + + function assertStdio(process: cp.ChildProcess): asserts process is cp.ChildProcessWithoutNullStreams { + if (process.stdin === null || process.stdout === null || process.stderr === null) { + throw new Error('Process created without stdio streams') + } + } + + let server = this._serverOptions + // We got a function. + if (Is.func(server)) { + return server().then(result => { + if (MessageTransports.is(result)) { + this._isDetached = !!result.detached + return result + } else if (StreamInfo.is(result)) { + this._isDetached = !!result.detached + return { + reader: new StreamMessageReader(result.reader), + writer: new StreamMessageWriter(result.writer) + } + } else { + let cp: ChildProcess + if (ChildProcessInfo.is(result)) { + cp = result.process + this._isDetached = result.detached + } else { + cp = result + this._isDetached = false + } + cp.stderr!.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + return { + reader: new StreamMessageReader(cp.stdout!), + writer: new StreamMessageWriter(cp.stdin!) + } + } + }) + } + let json: NodeModule | Executable + let runDebug = server as { run: any; debug: any } + if (runDebug.run || runDebug.debug) { + if (typeof v8debug === 'object' || this._forceDebug || startedInDebugMode()) { + json = runDebug.debug + } else { + json = runDebug.run + } + } else { + json = server as NodeModule | Executable + } + return this._getServerWorkingDir(json.options).then(serverWorkingDir => { + if (NodeModule.is(json) && json.module) { + let node = json + let transport = node.transport || TransportKind.stdio + if (node.runtime) { + let args: string[] = [] + let options: ForkOptions = node.options || Object.create(null) + if (options.execArgv) { + options.execArgv.forEach(element => args.push(element)) + } + args.push(node.module) + if (node.args) { + node.args.forEach(element => args.push(element)) + } + const execOptions: cp.SpawnOptionsWithoutStdio = Object.create(null) + execOptions.cwd = serverWorkingDir + execOptions.env = getEnvironment(options.env, false) + const runtime = this._getRuntimePath(node.runtime, serverWorkingDir) + let pipeName: string | undefined + if (transport === TransportKind.ipc) { + // exec options not correctly typed in lib + execOptions.stdio = [null, null, null, 'ipc'] as any + args.push('--node-ipc') + } else if (transport === TransportKind.stdio) { + args.push('--stdio') + } else if (transport === TransportKind.pipe) { + pipeName = 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 || transport === TransportKind.stdio) { + let serverProcess = cp.spawn(runtime, args, execOptions) + if (!serverProcess || !serverProcess.pid) { + return Promise.reject(`Launching server using runtime ${runtime} failed.`) + } + this._serverProcess = serverProcess + serverProcess.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + if (transport === TransportKind.ipc) { + serverProcess.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + return Promise.resolve({ reader: new IPCMessageReader(serverProcess), writer: new IPCMessageWriter(serverProcess) }) + } else { + return Promise.resolve({ reader: new StreamMessageReader(serverProcess.stdout), writer: new StreamMessageWriter(serverProcess.stdin) }) + } + } else if (transport === TransportKind.pipe) { + return createClientPipeTransport(pipeName!).then(transport => { + let process = cp.spawn(runtime, args, execOptions) + if (!process || !process.pid) { + return Promise.reject(`Launching server using runtime ${runtime} failed.`) + } + this._serverProcess = process + process.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + process.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + return transport.onConnected().then(protocol => { + return { reader: protocol[0], writer: protocol[1] } + }) + }) + } else if (Transport.isSocket(transport)) { + return createClientSocketTransport(transport.port).then(transport => { + let process = cp.spawn(runtime, args, execOptions) + if (!process || !process.pid) { + return Promise.reject(`Launching server using runtime ${runtime} failed.`) + } + this._serverProcess = process + process.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + process.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + return transport.onConnected().then(protocol => { + return { reader: protocol[0], writer: protocol[1] } + }) + }) + } + } else { + let pipeName: string | undefined + return new Promise((resolve, _reject) => { + let args = node.args && node.args.slice() || [] + if (transport === TransportKind.ipc) { + args.push('--node-ipc') + } else if (transport === TransportKind.stdio) { + args.push('--stdio') + } else if (transport === TransportKind.pipe) { + pipeName = generateRandomPipeName() + args.push(`--pipe=${pipeName}`) + } else if (Transport.isSocket(transport)) { + args.push(`--socket=${transport.port}`) + } + args.push(`--clientProcessId=${process.pid.toString()}`) + let options: cp.ForkOptions = node.options || Object.create(null) + options.env = getEnvironment(options.env, true) + options.execArgv = options.execArgv || [] + options.cwd = serverWorkingDir + options.silent = true + if (transport === TransportKind.ipc || transport === TransportKind.stdio) { + let sp = cp.fork(node.module, args || [], options) + assertStdio(sp) + this._serverProcess = sp + sp.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + if (transport === TransportKind.ipc) { + sp.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + resolve({ reader: new IPCMessageReader(this._serverProcess), writer: new IPCMessageWriter(this._serverProcess) }) + } else { + resolve({ reader: new StreamMessageReader(sp.stdout), writer: new StreamMessageWriter(sp.stdin) }) + } + } else if (transport === TransportKind.pipe) { + void createClientPipeTransport(pipeName!).then(transport => { + let sp = cp.fork(node.module, args || [], options) + assertStdio(sp) + this._serverProcess = sp + sp.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + sp.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + void transport.onConnected().then(protocol => { + resolve({ reader: protocol[0], writer: protocol[1] }) + }) + }) + } else if (Transport.isSocket(transport)) { + void createClientSocketTransport(transport.port).then(transport => { + let sp = cp.fork(node.module, args || [], options) + assertStdio(sp) + this._serverProcess = sp + sp.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + sp.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + void transport.onConnected().then(protocol => { + resolve({ reader: protocol[0], writer: protocol[1] }) + }) + }) + } + }) + } + } else if (Executable.is(json) && json.command) { + let command: Executable = json + let args = command.args || [] + let options = Object.assign({}, command.options) + options.env = options.env ? Object.assign({}, process.env, options.env) : process.env + options.cwd = options.cwd || serverWorkingDir + let cmd = workspace.expand(json.command) + let serverProcess = cp.spawn(cmd, args, options) + serverProcess.on('error', e => { + this.error(e.message) + logger.error(e) + }) + if (!serverProcess || !serverProcess.pid) { + return Promise.reject(`Launching server "${this.id}" using command ${command.command} failed.`) + } + logger.info(`Language server "${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.outputChannel.append(Is.string(data) ? data : data.toString(encoding))) + this._serverProcess = serverProcess + this._isDetached = !!options.detached + return Promise.resolve({ reader: new StreamMessageReader(serverProcess.stdout), writer: new StreamMessageWriter(serverProcess.stdin) }) + } + return Promise.reject(`Unsupported server configuration ${JSON.stringify(server, null, 2)}`) + }) + + } + + private _getRuntimePath(runtime: string, serverWorkingDirectory: string | undefined): string { + if (path.isAbsolute(runtime)) { + return runtime + } + const mainRootPath = this._mainGetRootPath() + if (mainRootPath !== undefined) { + const result = path.join(mainRootPath, runtime) + if (fs.existsSync(result)) { + return result + } + } + if (serverWorkingDirectory !== undefined) { + const result = path.join(serverWorkingDirectory, runtime) + if (fs.existsSync(result)) { + return result + } + } + return runtime + } + + private _mainGetRootPath(): string | undefined { + let folders = workspace.workspaceFolders + if (!folders || folders.length === 0) { + return undefined + } + let folder = folders[0] + return folder.uri + } + + public registerProposedFeatures(): void { + this.registerFeatures(ProposedFeatures.createAll(this)) + } + + protected registerBuiltinFeatures(): void { + super.registerBuiltinFeatures() + this.registerFeature(new PullConfigurationFeature(this)) + this.registerFeature(new TypeDefinitionFeature(this)) + this.registerFeature(new ImplementationFeature(this)) + this.registerFeature(new DeclarationFeature(this)) + this.registerFeature(new ColorProviderFeature(this)) + this.registerFeature(new FoldingRangeFeature(this)) + this.registerFeature(new SelectionRangeFeature(this)) + this.registerFeature(new ProgressFeature(this)) + this.registerFeature(new CallHierarchyFeature(this)) + if (workspace.isNvim || (workspace.isVim && workspace.env.textprop)) { + const config = workspace.getConfiguration('coc.preferences') + const enabled = config.get('semanticTokensHighlights', true) + if (enabled) this.registerFeature(new SemanticTokensFeature(this)) + } + this.registerFeature(new LinkedEditingFeature(this)) + this.registerFeature(new DidCreateFilesFeature(this)) + this.registerFeature(new DidRenameFilesFeature(this)) + this.registerFeature(new DidDeleteFilesFeature(this)) + this.registerFeature(new WillCreateFilesFeature(this)) + this.registerFeature(new WillRenameFilesFeature(this)) + this.registerFeature(new WillDeleteFilesFeature(this)) + if (!this.clientOptions.disableWorkspaceFolders) { + this.registerFeature(new WorkspaceFoldersFeature(this)) + } + } + + private _getServerWorkingDir(options?: { cwd?: string }): Promise { + let cwd = options && options.cwd + if (cwd && !path.isAbsolute(cwd)) cwd = path.join(workspace.cwd, cwd) + if (!cwd) cwd = workspace.cwd + if (cwd) { + // make sure the folder exists otherwise creating the process will fail + return new Promise(s => { + fs.lstat(cwd, (err, stats) => { + s(!err && stats.isDirectory() ? cwd : undefined) + }) + }) + } + return Promise.resolve(undefined) + } + + private appendOutput(data: any, encoding: string): void { + let msg: string = Is.string(data) ? data : data.toString(encoding) + this.outputChannel.append(msg.endsWith('\n') ? msg : msg + '\n') + } +} + +export class SettingMonitor { + private _listeners: Disposable[] + + constructor(private _client: LanguageClient, private _setting: string) { + this._listeners = [] + } + + public start(): Disposable { + workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(this._setting)) { + this.onDidChangeConfiguration() + } + }, null, this._listeners) + this.onDidChangeConfiguration() + return { + dispose: () => { + disposeAll(this._listeners) + if (this._client.needsStop()) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this._client.stop() + } + } + } + } + + private onDidChangeConfiguration(): void { + 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.getConfiguration(primary).get(rest, true) + : workspace.getConfiguration(primary) + if (enabled && this._client.needsStart()) { + this._client.start() + } else if (!enabled && this._client.needsStop()) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this._client.stop() + } + } +} + +// Exporting proposed protocol. +export namespace ProposedFeatures { + export function createAll(_client: BaseLanguageClient): (StaticFeature | DynamicFeature)[] { + let result: (StaticFeature | DynamicFeature)[] = [] + return result + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/linkedEditingRange.ts b/vim-config/plugins/coc.nvim/src/language-client/linkedEditingRange.ts new file mode 100644 index 00000000..4a4346b5 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/linkedEditingRange.ts @@ -0,0 +1,71 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. +* ------------------------------------------------------------------------------------------ */ + +import { CancellationToken, ClientCapabilities, Disposable, DocumentSelector, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions, LinkedEditingRangeRequest, LinkedEditingRanges, Position, ServerCapabilities } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { LinkedEditingRangeProvider, ProviderResult } from '../provider' +import { BaseLanguageClient, TextDocumentFeature } from './client' +import * as cv from './utils/converter' +const logger = require('../util/logger')('languageclient-linkedEditingRange') + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export interface ProvideLinkedEditingRangeSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult +} + +/** + * Linked editing middleware + * + * @since 3.16.0 + */ +export interface LinkedEditingRangeMiddleware { + provideLinkedEditingRange?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: ProvideLinkedEditingRangeSignature) => ProviderResult +} + +export class LinkedEditingFeature extends TextDocumentFeature { + + constructor(client: BaseLanguageClient) { + super(client, LinkedEditingRangeRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + const linkedEditingSupport = ensure(ensure(capabilities, 'textDocument')!, 'linkedEditingRange')! + linkedEditingSupport.dynamicRegistration = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + let [id, options] = this.getRegistration(documentSelector, capabilities.linkedEditingRangeProvider) + if (!id || !options) { + return + } + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider(options: LinkedEditingRangeRegistrationOptions): [Disposable, LinkedEditingRangeProvider] { + const provider: LinkedEditingRangeProvider = { + provideLinkedEditingRanges: (document, position, token) => { + const client = this._client + const provideLinkedEditing: ProvideLinkedEditingRangeSignature = (document, position, token) => { + const params = cv.asTextDocumentPositionParams(document, position) + return client.sendRequest(LinkedEditingRangeRequest.type, params, token).then(result => result, error => { + return client.handleFailedRequest(LinkedEditingRangeRequest.type, token, error, null) + }) + } + const middleware = client.clientOptions.middleware! + return middleware.provideLinkedEditingRange + ? middleware.provideLinkedEditingRange(document, position, token, provideLinkedEditing) + : provideLinkedEditing(document, position, token) + } + } + return [languages.registerLinkedEditingRangeProvider(options.documentSelector!, provider), provider] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/progress.ts b/vim-config/plugins/coc.nvim/src/language-client/progress.ts new file mode 100644 index 00000000..db74e53b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/progress.ts @@ -0,0 +1,45 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { ClientCapabilities, WorkDoneProgressCreateParams, WorkDoneProgressCreateRequest } from 'vscode-languageserver-protocol' +import { BaseLanguageClient, StaticFeature } from './client' +import { ProgressPart } from './progressPart' +// const logger = require('../util/logger')('language-client-progress') + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = Object.create(null) + } + return target[key] +} + +export class ProgressFeature implements StaticFeature { + private activeParts: Set = new Set() + constructor(private _client: BaseLanguageClient) { + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + ensure(capabilities, 'window')!.workDoneProgress = true + } + + public initialize(): void { + let client = this._client + const deleteHandler = (part: ProgressPart) => { + this.activeParts.delete(part) + } + const createHandler = (params: WorkDoneProgressCreateParams) => { + this.activeParts.add(new ProgressPart(this._client, params.token, deleteHandler)) + } + client.onRequest(WorkDoneProgressCreateRequest.type, createHandler) + } + + public dispose(): void { + for (const part of this.activeParts) { + part.done() + } + this.activeParts.clear() + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/progressPart.ts b/vim-config/plugins/coc.nvim/src/language-client/progressPart.ts new file mode 100644 index 00000000..6d6be04c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/progressPart.ts @@ -0,0 +1,74 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { Disposable, NotificationHandler, ProgressToken, ProgressType, ProtocolNotificationType, WorkDoneProgress, WorkDoneProgressBegin, WorkDoneProgressReport } from 'vscode-languageserver-protocol' +import { StatusBarItem } from '../model/status' +import { disposeAll } from '../util' +import window from '../window' +const logger = require('../util/logger')('language-client-progressPart') + +export interface ProgressContext { + onProgress

    (type: ProgressType

    , token: string | number, handler: NotificationHandler

    ): Disposable + sendNotification(type: ProtocolNotificationType, params?: P): void +} + +export class ProgressPart { + private disposables: Disposable[] = [] + private statusBarItem: StatusBarItem | undefined + private _cancelled = false + private title: string + + public constructor(private client: ProgressContext, private token: ProgressToken, done?: (part: ProgressPart) => void) { + this.statusBarItem = window.createStatusBarItem(99, { progress: true }) + this.disposables.push(client.onProgress(WorkDoneProgress.type, this.token, value => { + switch (value.kind) { + case 'begin': + this.begin(value) + break + case 'report': + this.report(value) + break + case 'end': + this.done(value.message) + done && done(this) + break + } + })) + } + + public begin(params: WorkDoneProgressBegin): void { + if (typeof this.title === 'string') return + // TODO support params.cancellable + this.title = params.title + this.report(params) + } + + private report(params: WorkDoneProgressReport | WorkDoneProgressBegin): void { + let statusBarItem = this.statusBarItem + let parts: string[] = [] + if (this.title) parts.push(this.title) + if (typeof params.percentage == 'number') parts.push(params.percentage.toFixed(0) + '%') + if (params.message) parts.push(params.message) + statusBarItem.text = parts.join(' ') + statusBarItem.show() + } + + public cancel(): void { + if (this._cancelled) return + this._cancelled = true + disposeAll(this.disposables) + } + + public done(message?: string): void { + if (this._cancelled) return + const statusBarItem = this.statusBarItem + statusBarItem.text = `${this.title} ${message || 'finished'}` + setTimeout(() => { + statusBarItem.dispose() + }, 300) + this.cancel() + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/selectionRange.ts b/vim-config/plugins/coc.nvim/src/language-client/selectionRange.ts new file mode 100644 index 00000000..65e9143d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/selectionRange.ts @@ -0,0 +1,70 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { CancellationToken, ClientCapabilities, Disposable, DocumentSelector, Position, SelectionRange, SelectionRangeClientCapabilities, SelectionRangeOptions, SelectionRangeParams, SelectionRangeRegistrationOptions, SelectionRangeRequest, ServerCapabilities } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { ProviderResult, SelectionRangeProvider } from '../provider' +import { BaseLanguageClient, TextDocumentFeature } from './client' + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export interface ProvideSelectionRangeSignature { + (this: void, document: TextDocument, positions: Position[], token: CancellationToken): ProviderResult +} + +export interface SelectionRangeProviderMiddleware { + provideSelectionRanges?: (this: void, document: TextDocument, positions: Position[], token: CancellationToken, next: ProvideSelectionRangeSignature) => ProviderResult +} + +export class SelectionRangeFeature extends TextDocumentFeature { + constructor(client: BaseLanguageClient) { + super(client, SelectionRangeRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities & SelectionRangeClientCapabilities): void { + let capability = ensure(ensure(capabilities, 'textDocument')!, 'selectionRange')! + capability.dynamicRegistration = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + let [id, options] = this.getRegistration(documentSelector, capabilities.selectionRangeProvider) + if (!id || !options) { + return + } + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider(options: SelectionRangeRegistrationOptions): [Disposable, SelectionRangeProvider] { + const provider: SelectionRangeProvider = { + provideSelectionRanges: (document, positions, token) => { + const client = this._client + const provideSelectionRanges: ProvideSelectionRangeSignature = (document, positions, token) => { + const requestParams: SelectionRangeParams = { + textDocument: { uri: document.uri }, + positions + } + return client.sendRequest(SelectionRangeRequest.type, requestParams, token).then( + ranges => ranges, + (error: any) => { + return client.handleFailedRequest(SelectionRangeRequest.type, token, error, null) + } + ) + } + const middleware = client.clientOptions.middleware + return middleware.provideSelectionRanges + ? middleware.provideSelectionRanges(document, positions, token, provideSelectionRanges) + : provideSelectionRanges(document, positions, token) + } + } + return [languages.registerSelectionRangeProvider(options.documentSelector, provider), provider] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/semanticTokens.ts b/vim-config/plugins/coc.nvim/src/language-client/semanticTokens.ts new file mode 100644 index 00000000..23923f1f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/semanticTokens.ts @@ -0,0 +1,202 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { + CancellationToken, SemanticTokensClientCapabilities, ClientCapabilities, Disposable, DocumentSelector, Emitter, Range, SemanticTokenModifiers, SemanticTokens, SemanticTokensDelta, SemanticTokensDeltaParams, SemanticTokensDeltaRequest, SemanticTokensOptions, SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeRequest, SemanticTokensRefreshRequest, SemanticTokensRegistrationOptions, SemanticTokensRegistrationType, SemanticTokensRequest, SemanticTokenTypes, ServerCapabilities, TokenFormat +} from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, ProviderResult } from '../provider' +import * as cv from './utils/converter' +import * as Is from '../util/is' +import { BaseLanguageClient, Middleware, TextDocumentFeature } from './client' +const logger = require('../util/logger')('languageclient-semanticTokens') + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export interface DocumentSemanticsTokensSignature { + (this: void, document: TextDocument, token: CancellationToken): ProviderResult +} + +export interface DocumentSemanticsTokensEditsSignature { + (this: void, document: TextDocument, previousResultId: string, token: CancellationToken): ProviderResult +} + +export interface DocumentRangeSemanticTokensSignature { + (this: void, document: TextDocument, range: Range, token: CancellationToken): ProviderResult +} + +/** + * The semantic token middleware + * + * @since 3.16.0 + */ +export interface SemanticTokensMiddleware { + provideDocumentSemanticTokens?: (this: void, document: TextDocument, token: CancellationToken, next: DocumentSemanticsTokensSignature) => ProviderResult + provideDocumentSemanticTokensEdits?: (this: void, document: TextDocument, previousResultId: string, token: CancellationToken, next: DocumentSemanticsTokensEditsSignature) => ProviderResult + provideDocumentRangeSemanticTokens?: (this: void, document: TextDocument, range: Range, token: CancellationToken, next: DocumentRangeSemanticTokensSignature) => ProviderResult +} + +export interface SemanticTokensProviders { + range?: DocumentRangeSemanticTokensProvider + full?: DocumentSemanticTokensProvider + onDidChangeSemanticTokensEmitter: Emitter +} + +export class SemanticTokensFeature extends TextDocumentFeature { + + constructor(client: BaseLanguageClient) { + super(client, SemanticTokensRegistrationType.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + const capability = ensure(ensure(capabilities, 'textDocument')!, 'semanticTokens')! + capability.dynamicRegistration = true + capability.tokenTypes = [ + SemanticTokenTypes.namespace, + SemanticTokenTypes.type, + SemanticTokenTypes.class, + SemanticTokenTypes.enum, + SemanticTokenTypes.interface, + SemanticTokenTypes.struct, + SemanticTokenTypes.typeParameter, + SemanticTokenTypes.parameter, + SemanticTokenTypes.variable, + SemanticTokenTypes.property, + SemanticTokenTypes.enumMember, + SemanticTokenTypes.event, + SemanticTokenTypes.function, + SemanticTokenTypes.method, + SemanticTokenTypes.macro, + SemanticTokenTypes.keyword, + SemanticTokenTypes.modifier, + SemanticTokenTypes.comment, + SemanticTokenTypes.string, + SemanticTokenTypes.number, + SemanticTokenTypes.regexp, + SemanticTokenTypes.operator + ] + capability.tokenModifiers = [ + SemanticTokenModifiers.declaration, + SemanticTokenModifiers.definition, + SemanticTokenModifiers.readonly, + SemanticTokenModifiers.static, + SemanticTokenModifiers.deprecated, + SemanticTokenModifiers.abstract, + SemanticTokenModifiers.async, + SemanticTokenModifiers.modification, + SemanticTokenModifiers.documentation, + SemanticTokenModifiers.defaultLibrary + ] + capability.formats = [TokenFormat.Relative] + capability.requests = { + range: true, + full: { + delta: true + } + } + capability.multilineTokenSupport = false + capability.overlappingTokenSupport = false + ensure(ensure(capabilities, 'workspace')!, 'semanticTokens')!.refreshSupport = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + const client = this._client + client.onRequest(SemanticTokensRefreshRequest.type, async () => { + for (const provider of this.getAllProviders()) { + provider.onDidChangeSemanticTokensEmitter.fire() + } + }) + const [id, options] = this.getRegistration(documentSelector, capabilities.semanticTokensProvider) + if (!id || !options) { + return + } + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider(options: SemanticTokensRegistrationOptions): [Disposable, SemanticTokensProviders] { + const fullProvider = Is.boolean(options.full) ? options.full : options.full !== undefined + const hasEditProvider = options.full !== undefined && typeof options.full !== 'boolean' && options.full.delta === true + const eventEmitter: Emitter = new Emitter() + const documentProvider: DocumentSemanticTokensProvider | undefined = fullProvider + ? { + onDidChangeSemanticTokens: eventEmitter.event, + provideDocumentSemanticTokens: (document, token) => { + const client = this._client + const middleware = client.clientOptions.middleware! as Middleware & SemanticTokensMiddleware + const provideDocumentSemanticTokens: DocumentSemanticsTokensSignature = (document, token) => { + const params: SemanticTokensParams = { + textDocument: cv.asTextDocumentIdentifier(document) + } + return client.sendRequest(SemanticTokensRequest.type, params, token).then(result => result, (error: any) => { + return client.handleFailedRequest(SemanticTokensRequest.type, token, error, null) + }) + } + return middleware.provideDocumentSemanticTokens + ? middleware.provideDocumentSemanticTokens(document, token, provideDocumentSemanticTokens) + : provideDocumentSemanticTokens(document, token) + }, + provideDocumentSemanticTokensEdits: hasEditProvider + ? (document, previousResultId, token) => { + const client = this._client + const middleware = client.clientOptions.middleware! as Middleware & SemanticTokensMiddleware + const provideDocumentSemanticTokensEdits: DocumentSemanticsTokensEditsSignature = (document, previousResultId, token) => { + const params: SemanticTokensDeltaParams = { + textDocument: cv.asTextDocumentIdentifier(document), + previousResultId + } + return client.sendRequest(SemanticTokensDeltaRequest.type, params, token).then(result => result, (error: any) => { + return client.handleFailedRequest(SemanticTokensDeltaRequest.type, token, error, null) + }) + } + return middleware.provideDocumentSemanticTokensEdits + ? middleware.provideDocumentSemanticTokensEdits(document, previousResultId, token, provideDocumentSemanticTokensEdits) + : provideDocumentSemanticTokensEdits(document, previousResultId, token) + } + : undefined + } + : undefined + + const hasRangeProvider: boolean = options.range === true + const rangeProvider: DocumentRangeSemanticTokensProvider | undefined = hasRangeProvider + ? { + provideDocumentRangeSemanticTokens: (document: TextDocument, range: Range, token: CancellationToken) => { + const client = this._client + const middleware = client.clientOptions.middleware! as Middleware & SemanticTokensMiddleware + const provideDocumentRangeSemanticTokens: DocumentRangeSemanticTokensSignature = (document, range, token) => { + const params: SemanticTokensRangeParams = { + textDocument: cv.asTextDocumentIdentifier(document), + range + } + return client.sendRequest(SemanticTokensRangeRequest.type, params, token).then( + result => result, + (error: any) => { + return client.handleFailedRequest(SemanticTokensRangeRequest.type, token, error, null) + }) + } + return middleware.provideDocumentRangeSemanticTokens + ? middleware.provideDocumentRangeSemanticTokens(document, range, token, provideDocumentRangeSemanticTokens) + : provideDocumentRangeSemanticTokens(document, range, token) + } + } + : undefined + + const disposables: Disposable[] = [] + if (documentProvider !== undefined) { + disposables.push(languages.registerDocumentSemanticTokensProvider(options.documentSelector!, documentProvider, options.legend)) + } + if (rangeProvider !== undefined) { + disposables.push(languages.registerDocumentRangeSemanticTokensProvider(options.documentSelector!, rangeProvider, options.legend)) + } + + return [Disposable.create(() => disposables.forEach(item => item.dispose())), { range: rangeProvider, full: documentProvider, onDidChangeSemanticTokensEmitter: eventEmitter }] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/typeDefinition.ts b/vim-config/plugins/coc.nvim/src/language-client/typeDefinition.ts new file mode 100644 index 00000000..75f3acf7 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/typeDefinition.ts @@ -0,0 +1,74 @@ +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { CancellationToken, ClientCapabilities, Definition, DefinitionLink, Disposable, DocumentSelector, Position, ServerCapabilities, TypeDefinitionOptions, TypeDefinitionRegistrationOptions, TypeDefinitionRequest } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import languages from '../languages' +import { ProviderResult, TypeDefinitionProvider } from '../provider' +import { BaseLanguageClient, TextDocumentFeature } from './client' +import * as cv from './utils/converter' + +function ensure(target: T, key: K): T[K] { + if (target[key] === void 0) { + target[key] = {} as any + } + return target[key] +} + +export interface ProvideTypeDefinitionSignature { + ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +export interface TypeDefinitionMiddleware { + provideTypeDefinition?: ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken, + next: ProvideTypeDefinitionSignature + ) => ProviderResult +} + +export class TypeDefinitionFeature extends TextDocumentFeature { + constructor(client: BaseLanguageClient) { + super(client, TypeDefinitionRequest.type) + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + const typeDefinitionSupport = ensure(ensure(capabilities, 'textDocument')!, 'typeDefinition')! + typeDefinitionSupport.dynamicRegistration = true + // typeDefinitionSupport.linkSupport = true + } + + public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void { + const [id, options] = this.getRegistration(documentSelector, capabilities.typeDefinitionProvider) + if (!id || !options) { + return + } + this.register({ id, registerOptions: options }) + } + + protected registerLanguageProvider(options: TypeDefinitionRegistrationOptions): [Disposable, TypeDefinitionProvider] { + const provider: TypeDefinitionProvider = { + provideTypeDefinition: (document, position, token) => { + const client = this._client + const provideTypeDefinition: ProvideTypeDefinitionSignature = (document, position, token) => client.sendRequest(TypeDefinitionRequest.type, cv.asTextDocumentPositionParams(document, position), token).then( + res => res, error => { + return client.handleFailedRequest(TypeDefinitionRequest.type, token, error, null) + } + ) + const middleware = client.clientOptions.middleware + return middleware.provideTypeDefinition + ? middleware.provideTypeDefinition(document, position, token, provideTypeDefinition) + : provideTypeDefinition(document, position, token) + } + } + return [languages.registerTypeDefinitionProvider(options.documentSelector, provider), provider] + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/utils/async.ts b/vim-config/plugins/coc.nvim/src/language-client/utils/async.ts new file mode 100644 index 00000000..1e772bcb --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/utils/async.ts @@ -0,0 +1,87 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import { RAL } from 'vscode-languageserver-protocol' + +export interface ITask { + (): T +} + +export class Delayer { + + public defaultDelay: number + private timeout: RAL.TimeoutHandle | undefined + private completionPromise: Promise | undefined + private onSuccess: ((value: T | Promise | undefined) => void) | undefined + private task: ITask | undefined + + constructor(defaultDelay: number) { + this.defaultDelay = defaultDelay + this.timeout = undefined + this.completionPromise = undefined + this.onSuccess = undefined + this.task = undefined + } + + public trigger(task: ITask, delay: number = this.defaultDelay): Promise { + this.task = task + if (delay >= 0) { + this.cancelTimeout() + } + + if (!this.completionPromise) { + this.completionPromise = new Promise(resolve => { + this.onSuccess = resolve + }).then(() => { + this.completionPromise = undefined + this.onSuccess = undefined + let result = this.task!() + this.task = undefined + return result + }) + } + + if (delay >= 0 || this.timeout === void 0) { + this.timeout = RAL().timer.setTimeout(() => { + this.timeout = undefined + this.onSuccess!(undefined) + }, delay >= 0 ? delay : this.defaultDelay) + } + + return this.completionPromise + } + + public forceDelivery(): T | undefined { + if (!this.completionPromise) { + return undefined + } + this.cancelTimeout() + let result: T = this.task!() + this.completionPromise = undefined + this.onSuccess = undefined + this.task = undefined + return result + } + + public isTriggered(): boolean { + return this.timeout !== void 0 + } + + public cancel(): void { + this.cancelTimeout() + this.completionPromise = undefined + } + + public dispose(): void { + this.cancelTimeout() + } + + private cancelTimeout(): void { + if (this.timeout !== void 0) { + RAL().timer.clearTimeout(this.timeout) + this.timeout = undefined + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/utils/converter.ts b/vim-config/plugins/coc.nvim/src/language-client/utils/converter.ts new file mode 100644 index 00000000..b05248a5 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/utils/converter.ts @@ -0,0 +1,135 @@ +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { CodeLensParams, CompletionContext, CompletionParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidSaveTextDocumentParams, DocumentSelector, DocumentSymbolParams, Position, ReferenceParams, SignatureHelpContext, SignatureHelpParams, TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams, VersionedTextDocumentIdentifier, WillSaveTextDocumentParams } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import { TextDocumentWillSaveEvent } from '../../types' +import { omit } from '../../util/lodash' + +export function asLanguageIds(documentSelector: DocumentSelector): string[] { + 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 +} + +export function convertToTextDocumentItem(document: TextDocument): TextDocumentItem { + return { + uri: document.uri, + languageId: document.languageId, + version: document.version, + text: document.getText() + } +} + +export function asCloseTextDocumentParams(document: TextDocument): DidCloseTextDocumentParams { + return { + textDocument: { + uri: document.uri + } + } +} + +export function asChangeTextDocumentParams(document: TextDocument): DidChangeTextDocumentParams { + let result: DidChangeTextDocumentParams = { + textDocument: { + uri: document.uri, + version: document.version + }, + contentChanges: [{ text: document.getText() }] + } + return result +} + +export function asWillSaveTextDocumentParams(event: TextDocumentWillSaveEvent): WillSaveTextDocumentParams { + return { + textDocument: asVersionedTextDocumentIdentifier(event.document), + reason: event.reason + } +} + +export function asVersionedTextDocumentIdentifier(textDocument: TextDocument): VersionedTextDocumentIdentifier { + return { + uri: textDocument.uri, + version: textDocument.version + } +} + +export function asSaveTextDocumentParams(document: TextDocument, includeText: boolean): DidSaveTextDocumentParams { + let result: DidSaveTextDocumentParams = { + textDocument: asVersionedTextDocumentIdentifier(document) + } + if (includeText) { + result.text = document.getText() + } + return result +} + +export function asUri(resource: URI): string { + return resource.toString() +} + +export function asCompletionParams(textDocument: TextDocument, position: Position, context: CompletionContext): CompletionParams { + return { + textDocument: { + uri: textDocument.uri, + }, + position, + context: omit(context, ['option']), + } +} + +export function asTextDocumentPositionParams(textDocument: TextDocument, position: Position): TextDocumentPositionParams { + return { + textDocument: { + uri: textDocument.uri, + }, + position + } +} + +export function asSignatureHelpParams(textDocument: TextDocument, position: Position, context: SignatureHelpContext): SignatureHelpParams { + return { + textDocument: asTextDocumentIdentifier(textDocument), + position, + context + } +} + +export function asTextDocumentIdentifier(textDocument: TextDocument): TextDocumentIdentifier { + return { + uri: textDocument.uri + } +} + +export function asReferenceParams(textDocument: TextDocument, position: Position, options: { includeDeclaration: boolean }): ReferenceParams { + return { + textDocument: { + uri: textDocument.uri, + }, + position, + context: { includeDeclaration: options.includeDeclaration } + } +} + +export function asDocumentSymbolParams(textDocument: TextDocument): DocumentSymbolParams { + return { + textDocument: { + uri: textDocument.uri + } + } +} + +export function asCodeLensParams(textDocument: TextDocument): CodeLensParams { + return { + textDocument: { + uri: textDocument.uri + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/utils/uuid.ts b/vim-config/plugins/coc.nvim/src/language-client/utils/uuid.ts new file mode 100644 index 00000000..0adb8eee --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/utils/uuid.ts @@ -0,0 +1,5 @@ +import { v4 as uuidv4 } from 'uuid' + +export function generateUuid(): string { + return uuidv4() +} diff --git a/vim-config/plugins/coc.nvim/src/language-client/workspaceFolders.ts b/vim-config/plugins/coc.nvim/src/language-client/workspaceFolders.ts new file mode 100644 index 00000000..30cd6409 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/language-client/workspaceFolders.ts @@ -0,0 +1,170 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict' + +import { CancellationToken, ClientCapabilities, DidChangeWorkspaceFoldersNotification, DidChangeWorkspaceFoldersParams, Disposable, InitializeParams, RegistrationType, ServerCapabilities, WorkspaceFolder, WorkspaceFoldersChangeEvent, WorkspaceFoldersRequest } from 'vscode-languageserver-protocol' +import workspace from '../workspace' +import os from 'os' +import { BaseLanguageClient, DynamicFeature, NextSignature, RegistrationData } from './client' +import * as UUID from './utils/uuid' +import { URI } from 'vscode-uri' +const logger = require('../util/logger')('language-client-workspaceFolder') + +function access(target: T | undefined, key: K): T[K] | undefined { + if (target === void 0) { + return undefined + } + return target[key] +} + +function arrayDiff(left: ReadonlyArray, right: ReadonlyArray): T[] { + return left.filter(element => !right.includes(element)) +} + +export interface WorkspaceFolderWorkspaceMiddleware { + workspaceFolders?: WorkspaceFoldersRequest.MiddlewareSignature + didChangeWorkspaceFolders?: NextSignature +} + +export class WorkspaceFoldersFeature implements DynamicFeature { + + private _listeners: Map = new Map() + private _initialFolders: ReadonlyArray | undefined + + constructor(private _client: BaseLanguageClient) { + } + + public get registrationType(): RegistrationType { + return DidChangeWorkspaceFoldersNotification.type + } + + private getValidWorkspaceFolders(): WorkspaceFolder[] | undefined { + let { workspaceFolders } = workspace + if (!workspaceFolders || workspaceFolders.length == 0) return undefined + let home = os.homedir() + let { ignoredRootPaths } = this._client.clientOptions + if (!Array.isArray(ignoredRootPaths)) { + ignoredRootPaths = [] + } + let arr = workspaceFolders.filter(o => { + let fsPath = URI.parse(o.uri).fsPath + return fsPath != home && !ignoredRootPaths.includes(fsPath) + }) + return arr.length ? arr : undefined + } + + private asProtocol(workspaceFolder: WorkspaceFolder): WorkspaceFolder + private asProtocol(workspaceFolder: undefined): null + private asProtocol(workspaceFolder: WorkspaceFolder | undefined): WorkspaceFolder | null { + if (workspaceFolder === void 0) { + return null + } + return { uri: workspaceFolder.uri, name: workspaceFolder.name } + } + + public fillInitializeParams(params: InitializeParams): void { + const folders = this.getValidWorkspaceFolders() + this._initialFolders = folders + if (folders == null) { + params.workspaceFolders = null + } else { + params.workspaceFolders = folders.map(folder => this.asProtocol(folder)) + } + // params.workspaceFolders = workspace.workspaceFolders + } + + public fillClientCapabilities(capabilities: ClientCapabilities): void { + capabilities.workspace = capabilities.workspace || {} + capabilities.workspace.workspaceFolders = true + } + + public initialize(capabilities: ServerCapabilities): void { + let client = this._client + client.onRequest(WorkspaceFoldersRequest.type, (token: CancellationToken) => { + let workspaceFolders: WorkspaceFoldersRequest.HandlerSignature = () => { + let folders = this.getValidWorkspaceFolders() + if (folders === void 0) { + return null + } + let result: WorkspaceFolder[] = folders.map(folder => this.asProtocol(folder)) + return result + } + const middleware = client.clientOptions.middleware.workspace + return middleware && middleware.workspaceFolders + ? middleware.workspaceFolders(token, workspaceFolders) + : workspaceFolders(token) + }) + const value = access(access(access(capabilities, 'workspace'), 'workspaceFolders'), 'changeNotifications') + let id: string | undefined + if (typeof value === 'string') { + id = value + } else if (value === true) { + id = UUID.generateUuid() + } + if (id) { + this.register({ + id, + registerOptions: undefined + }) + } + } + + private doSendEvent(addedFolders: ReadonlyArray, removedFolders: ReadonlyArray): void { + let params: DidChangeWorkspaceFoldersParams = { + event: { + added: addedFolders.map(folder => this.asProtocol(folder)), + removed: removedFolders.map(folder => this.asProtocol(folder)) + } + } + this._client.sendNotification(DidChangeWorkspaceFoldersNotification.type, params) + } + + protected sendInitialEvent(currentWorkspaceFolders: ReadonlyArray | undefined): void { + if (this._initialFolders && currentWorkspaceFolders) { + const removed: WorkspaceFolder[] = arrayDiff(this._initialFolders, currentWorkspaceFolders) + const added: WorkspaceFolder[] = arrayDiff(currentWorkspaceFolders, this._initialFolders) + if (added.length > 0 || removed.length > 0) { + this.doSendEvent(added, removed) + } + } else if (this._initialFolders) { + this.doSendEvent([], this._initialFolders) + } else if (currentWorkspaceFolders) { + this.doSendEvent(currentWorkspaceFolders, []) + } + } + + public register(data: RegistrationData): void { + let id = data.id + let client = this._client + let disposable = workspace.onDidChangeWorkspaceFolders(event => { + let didChangeWorkspaceFolders = (event: WorkspaceFoldersChangeEvent) => { + this.doSendEvent(event.added, event.removed) + } + let middleware = client.clientOptions.middleware.workspace + middleware && middleware.didChangeWorkspaceFolders + ? middleware.didChangeWorkspaceFolders(event, didChangeWorkspaceFolders) + : didChangeWorkspaceFolders(event) + }) + this._listeners.set(id, disposable) + let workspaceFolders = this.getValidWorkspaceFolders() + this.sendInitialEvent(workspaceFolders) + } + + public unregister(id: string): void { + let disposable = this._listeners.get(id) + if (disposable === void 0) { + return + } + this._listeners.delete(id) + disposable.dispose() + } + + public dispose(): void { + for (let disposable of this._listeners.values()) { + disposable.dispose() + } + this._listeners.clear() + } +} diff --git a/vim-config/plugins/coc.nvim/src/languages.ts b/vim-config/plugins/coc.nvim/src/languages.ts new file mode 100644 index 00000000..2c23c637 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/languages.ts @@ -0,0 +1,450 @@ +import { CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, CancellationToken, CancellationTokenSource, CodeAction, CodeActionContext, CodeActionKind, CodeLens, ColorInformation, ColorPresentation, DefinitionLink, Disposable, DocumentHighlight, DocumentLink, DocumentSelector, DocumentSymbol, Emitter, Event, FoldingRange, FormattingOptions, Hover, LinkedEditingRanges, Location, LocationLink, Position, Range, SelectionRange, SemanticTokens, SemanticTokensDelta, SemanticTokensLegend, SignatureHelp, SignatureHelpContext, SymbolInformation, TextEdit, WorkspaceEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import DiagnosticCollection from './diagnostic/collection' +import diagnosticManager from './diagnostic/manager' +import { CallHierarchyProvider, CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentLinkProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, FoldingContext, FoldingRangeProvider, HoverProvider, ImplementationProvider, LinkedEditingRangeProvider, OnTypeFormattingEditProvider, ReferenceContext, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, WorkspaceSymbolProvider } from './provider' +import CallHierarchyManager from './provider/callHierarchyManager' +import CodeActionManager from './provider/codeActionManager' +import CodeLensManager from './provider/codeLensManager' +import DeclarationManager from './provider/declarationManager' +import DefinitionManager from './provider/definitionManager' +import DocumentColorManager from './provider/documentColorManager' +import DocumentHighlightManager from './provider/documentHighlightManager' +import DocumentLinkManager from './provider/documentLinkManager' +import DocumentSymbolManager from './provider/documentSymbolManager' +import FoldingRangeManager from './provider/foldingRangeManager' +import FormatManager from './provider/formatManager' +import FormatRangeManager from './provider/formatRangeManager' +import HoverManager from './provider/hoverManager' +import ImplementationManager from './provider/implementationManager' +import LinkedEditingRangeManager from './provider/linkedEditingRangeManager' +import OnTypeFormatManager from './provider/onTypeFormatManager' +import ReferenceManager from './provider/referenceManager' +import RenameManager from './provider/renameManager' +import SelectionRangeManager from './provider/selectionRangeManager' +import SemanticTokensManager from './provider/semanticTokensManager' +import SemanticTokensRangeManager from './provider/semanticTokensRangeManager' +import SignatureManager from './provider/signatureManager' +import TypeDefinitionManager from './provider/typeDefinitionManager' +import WorkspaceSymbolManager from './provider/workspaceSymbolsManager' +const logger = require('./util/logger')('languages') + +export interface DocumentSymbolProviderMetadata { + /** + * A human-readable string that is shown when multiple outlines trees show for one document. + */ + label?: string +} + +class Languages { + private _onDidSemanticTokensRefresh = new Emitter() + public readonly onDidSemanticTokensRefresh: Event = this._onDidSemanticTokensRefresh.event + private onTypeFormatManager = new OnTypeFormatManager() + private documentLinkManager = new DocumentLinkManager() + private documentColorManager = new DocumentColorManager() + private foldingRangeManager = new FoldingRangeManager() + private renameManager = new RenameManager() + private formatManager = new FormatManager() + private codeActionManager = new CodeActionManager() + private workspaceSymbolsManager = new WorkspaceSymbolManager() + private formatRangeManager = new FormatRangeManager() + private hoverManager = new HoverManager() + private signatureManager = new SignatureManager() + private documentSymbolManager = new DocumentSymbolManager() + private documentHighlightManager = new DocumentHighlightManager() + private definitionManager = new DefinitionManager() + private declarationManager = new DeclarationManager() + private typeDefinitionManager = new TypeDefinitionManager() + private referenceManager = new ReferenceManager() + private implementationManager = new ImplementationManager() + private codeLensManager = new CodeLensManager() + private selectionRangeManager = new SelectionRangeManager() + private callHierarchyManager = new CallHierarchyManager() + private semanticTokensManager = new SemanticTokensManager() + private semanticTokensRangeManager = new SemanticTokensRangeManager() + private linkedEditingManager = new LinkedEditingRangeManager() + private cancelTokenSource: CancellationTokenSource = new CancellationTokenSource() + + public hasFormatProvider(doc: TextDocument): boolean { + if (this.formatManager.hasProvider(doc)) { + return true + } + if (this.formatRangeManager.hasProvider(doc)) { + return true + } + return false + } + + public registerOnTypeFormattingEditProvider( + selector: DocumentSelector, + provider: OnTypeFormattingEditProvider, + triggerCharacters: string[] + ): Disposable { + return this.onTypeFormatManager.register(selector, provider, triggerCharacters) + } + + public registerCompletionItemProvider( + name: string, + shortcut: string, + selector: DocumentSelector | null, + provider: CompletionItemProvider, + triggerCharacters: string[] = [], + priority?: number, + allCommitCharacters?: string[] + ): Disposable { + selector = typeof selector == 'string' ? [{ language: selector }] : selector + let sources = require('./sources/index').default + return sources.createLanguageSource(name, shortcut, selector, provider, triggerCharacters, priority, allCommitCharacters) + } + + public registerCodeActionProvider(selector: DocumentSelector, provider: CodeActionProvider, clientId: string | undefined, codeActionKinds?: CodeActionKind[]): Disposable { + return this.codeActionManager.register(selector, provider, clientId, codeActionKinds) + } + + public registerHoverProvider(selector: DocumentSelector, provider: HoverProvider): Disposable { + return this.hoverManager.register(selector, provider) + } + + public registerSelectionRangeProvider(selector: DocumentSelector, provider: SelectionRangeProvider): Disposable { + return this.selectionRangeManager.register(selector, provider) + } + + public registerSignatureHelpProvider( + selector: DocumentSelector, + provider: SignatureHelpProvider, + triggerCharacters?: string[]): Disposable { + return this.signatureManager.register(selector, provider, triggerCharacters) + } + + public registerDocumentSymbolProvider(selector: DocumentSelector, provider: DocumentSymbolProvider, metadata?: DocumentSymbolProviderMetadata): Disposable { + return this.documentSymbolManager.register(selector, provider, metadata?.label) + } + + public registerFoldingRangeProvider(selector: DocumentSelector, provider: FoldingRangeProvider): Disposable { + return this.foldingRangeManager.register(selector, provider) + } + + public registerDocumentHighlightProvider(selector: DocumentSelector, provider: DocumentHighlightProvider): Disposable { + return this.documentHighlightManager.register(selector, provider) + } + + public registerCodeLensProvider(selector: DocumentSelector, provider: CodeLensProvider): Disposable { + return this.codeLensManager.register(selector, provider) + } + + public registerDocumentLinkProvider(selector: DocumentSelector, provider: DocumentLinkProvider): Disposable { + return this.documentLinkManager.register(selector, provider) + } + + public registerDocumentColorProvider(selector: DocumentSelector, provider: DocumentColorProvider): Disposable { + return this.documentColorManager.register(selector, provider) + } + + public registerDefinitionProvider(selector: DocumentSelector, provider: DefinitionProvider): Disposable { + return this.definitionManager.register(selector, provider) + } + + public registerDeclarationProvider(selector: DocumentSelector, provider: DeclarationProvider): Disposable { + return this.declarationManager.register(selector, provider) + } + + public registerTypeDefinitionProvider(selector: DocumentSelector, provider: TypeDefinitionProvider): Disposable { + return this.typeDefinitionManager.register(selector, provider) + } + + public registerImplementationProvider(selector: DocumentSelector, provider: ImplementationProvider): Disposable { + return this.implementationManager.register(selector, provider) + } + + public registerReferencesProvider(selector: DocumentSelector, provider: ReferenceProvider): Disposable { + return this.referenceManager.register(selector, provider) + } + + public registerRenameProvider(selector: DocumentSelector, provider: RenameProvider): Disposable { + return this.renameManager.register(selector, provider) + } + + public registerWorkspaceSymbolProvider(provider: WorkspaceSymbolProvider): Disposable { + if (arguments.length > 1 && typeof arguments[1].provideWorkspaceSymbols === 'function') { + provider = arguments[1] + } + return this.workspaceSymbolsManager.register(provider) + } + + public registerDocumentFormatProvider(selector: DocumentSelector, provider: DocumentFormattingEditProvider, priority = 0): Disposable { + return this.formatManager.register(selector, provider, priority) + } + + public registerDocumentRangeFormatProvider(selector: DocumentSelector, provider: DocumentRangeFormattingEditProvider, priority = 0): Disposable { + return this.formatRangeManager.register(selector, provider, priority) + } + + public registerCallHierarchyProvider(selector: DocumentSelector, provider: CallHierarchyProvider): Disposable { + return this.callHierarchyManager.register(selector, provider) + } + + public registerDocumentSemanticTokensProvider(selector: DocumentSelector, provider: DocumentSemanticTokensProvider, legend: SemanticTokensLegend): Disposable { + this._onDidSemanticTokensRefresh.fire(selector) + return this.semanticTokensManager.register(selector, provider, legend, () => { + this._onDidSemanticTokensRefresh.fire(selector) + }) + } + + public registerDocumentRangeSemanticTokensProvider(selector: DocumentSelector, provider: DocumentRangeSemanticTokensProvider, legend: SemanticTokensLegend): Disposable { + this._onDidSemanticTokensRefresh.fire(selector) + return this.semanticTokensRangeManager.register(selector, provider, legend) + } + + public registerLinkedEditingRangeProvider(selector: DocumentSelector, provider: LinkedEditingRangeProvider): Disposable { + return this.linkedEditingManager.register(selector, provider) + } + + public shouldTriggerSignatureHelp(document: TextDocument, triggerCharacter: string): boolean { + return this.signatureManager.shouldTrigger(document, triggerCharacter) + } + + public async getHover(document: TextDocument, position: Position, token: CancellationToken): Promise { + return await this.hoverManager.provideHover(document, position, token) + } + + public async getSignatureHelp(document: TextDocument, position: Position, token: CancellationToken, context: SignatureHelpContext): Promise { + return await this.signatureManager.provideSignatureHelp(document, position, token, context) + } + + public async getDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise { + if (!this.definitionManager.hasProvider(document)) return null + return await this.definitionManager.provideDefinition(document, position, token) + } + + public async getDefinitionLinks(document: TextDocument, position: Position, token: CancellationToken): Promise { + if (!this.definitionManager.hasProvider(document)) return null + return await this.definitionManager.provideDefinitionLinks(document, position, token) + } + + public async getDeclaration(document: TextDocument, position: Position, token: CancellationToken): Promise { + if (!this.declarationManager.hasProvider(document)) return null + return await this.declarationManager.provideDeclaration(document, position, token) + } + + public async getTypeDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise { + if (!this.typeDefinitionManager.hasProvider(document)) return null + return await this.typeDefinitionManager.provideTypeDefinition(document, position, token) + } + + public async getImplementation(document: TextDocument, position: Position, token: CancellationToken): Promise { + if (!this.implementationManager.hasProvider(document)) return null + return await this.implementationManager.provideReferences(document, position, token) + } + + public async getReferences(document: TextDocument, context: ReferenceContext, position: Position, token: CancellationToken): Promise { + if (!this.referenceManager.hasProvider(document)) return null + return await this.referenceManager.provideReferences(document, position, context, token) + } + + public async getDocumentSymbol(document: TextDocument, token: CancellationToken): Promise { + return await this.documentSymbolManager.provideDocumentSymbols(document, token) + } + + public async getSelectionRanges(document: TextDocument, positions: Position[], token): Promise { + return await this.selectionRangeManager.provideSelectionRanges(document, positions, token) + } + + public async getWorkspaceSymbols(query: string, token: CancellationToken): Promise { + query = query || '' + return await this.workspaceSymbolsManager.provideWorkspaceSymbols(query, token) + } + + public async resolveWorkspaceSymbol(symbol: SymbolInformation, token: CancellationToken): Promise { + return await this.workspaceSymbolsManager.resolveWorkspaceSymbol(symbol, token) + } + + public async prepareRename(document: TextDocument, position: Position, token: CancellationToken): Promise { + return await this.renameManager.prepareRename(document, position, token) + } + + public async provideRenameEdits(document: TextDocument, position: Position, newName: string, token: CancellationToken): Promise { + return await this.renameManager.provideRenameEdits(document, position, newName, token) + } + + public async provideDocumentFormattingEdits(document: TextDocument, options: FormattingOptions, token: CancellationToken): Promise { + if (!this.formatManager.hasProvider(document)) { + let hasRangeFormater = this.formatRangeManager.hasProvider(document) + if (!hasRangeFormater) return null + let end = document.positionAt(document.getText().length) + let range = Range.create(Position.create(0, 0), end) + return await this.provideDocumentRangeFormattingEdits(document, range, options, token) + } + return await this.formatManager.provideDocumentFormattingEdits(document, options, token) + } + + public async provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): Promise { + if (!this.formatRangeManager.hasProvider(document)) return null + return await this.formatRangeManager.provideDocumentRangeFormattingEdits(document, range, options, token) + } + + public async getCodeActions(document: TextDocument, range: Range, context: CodeActionContext, token: CancellationToken): Promise { + return await this.codeActionManager.provideCodeActions(document, range, context, token) + } + + public async getDocumentHighLight(document: TextDocument, position: Position, token: CancellationToken): Promise { + return await this.documentHighlightManager.provideDocumentHighlights(document, position, token) + } + + public async getDocumentLinks(document: TextDocument, token: CancellationToken): Promise { + if (!this.documentLinkManager.hasProvider(document)) { + return null + } + return (await this.documentLinkManager.provideDocumentLinks(document, token)) || [] + } + + public async resolveDocumentLink(link: DocumentLink): Promise { + return await this.documentLinkManager.resolveDocumentLink(link, this.token) + } + + public async provideDocumentColors(document: TextDocument, token: CancellationToken): Promise { + return await this.documentColorManager.provideDocumentColors(document, token) + } + + public async provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken): Promise { + if (!this.foldingRangeManager.hasProvider(document)) { + return null + } + return await this.foldingRangeManager.provideFoldingRanges(document, context, token) + } + + public async provideColorPresentations(color: ColorInformation, document: TextDocument, token: CancellationToken): Promise { + return await this.documentColorManager.provideColorPresentations(color, document, token) + } + + public async getCodeLens(document: TextDocument, token: CancellationToken): Promise<(CodeLens | null)[]> { + return await this.codeLensManager.provideCodeLenses(document, token) + } + + public async resolveCodeLens(codeLens: CodeLens, token: CancellationToken): Promise { + if (codeLens.command != null) return codeLens + return await this.codeLensManager.resolveCodeLens(codeLens, token) + } + + public async resolveCodeAction(codeAction: CodeAction, token: CancellationToken): Promise { + return await this.codeActionManager.resolveCodeAction(codeAction, token) + } + + public async provideDocumentOnTypeEdits( + character: string, + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + return this.onTypeFormatManager.onCharacterType(character, document, position, token) + } + + public canFormatOnType(character: string, document: TextDocument): boolean { + return this.onTypeFormatManager.getProvider(document, character) != null + } + + public async prepareCallHierarchy(document: TextDocument, position: Position, token: CancellationToken): Promise { + return this.callHierarchyManager.prepareCallHierarchy(document, position, token) + } + + public async provideIncomingCalls(document: TextDocument, item: CallHierarchyItem, token: CancellationToken): Promise { + return this.callHierarchyManager.provideCallHierarchyIncomingCalls(document, item, token) + } + + public async provideOutgoingCalls(document: TextDocument, item: CallHierarchyItem, token: CancellationToken): Promise { + return this.callHierarchyManager.provideCallHierarchyOutgoingCalls(document, item, token) + } + + public getLegend(document: TextDocument, range?: boolean): SemanticTokensLegend | undefined { + if (range) return this.semanticTokensRangeManager.getLegend(document) + return this.semanticTokensManager.getLegend(document) + } + + public hasSemanticTokensEdits(document: TextDocument): boolean { + return this.semanticTokensManager.hasSemanticTokensEdits(document) + } + + public async provideDocumentSemanticTokens(document: TextDocument, token: CancellationToken): Promise { + return this.semanticTokensManager.provideDocumentSemanticTokens(document, token) + } + + public async provideDocumentSemanticTokensEdits(document: TextDocument, previousResultId: string, token: CancellationToken): Promise { + return this.semanticTokensManager.provideDocumentSemanticTokensEdits(document, previousResultId, token) + } + + public async provideDocumentRangeSemanticTokens(document: TextDocument, range: Range, token: CancellationToken): Promise { + return this.semanticTokensRangeManager.provideDocumentRangeSemanticTokens(document, range, token) + } + + public hasLinkedEditing(document: TextDocument): boolean { + return this.linkedEditingManager.hasProvider(document) + } + + public async provideLinkedEdits(document: TextDocument, position: Position, token: CancellationToken): Promise { + return this.linkedEditingManager.provideLinkedEditingRanges(document, position, token) + } + + public hasProvider(id: string, document: TextDocument): boolean { + switch (id) { + case 'formatOnType': + return this.onTypeFormatManager.hasProvider(document) + 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) || this.formatRangeManager.hasProvider(document) + case 'codeAction': + return this.codeActionManager.hasProvider(document) + case 'workspaceSymbols': + return this.workspaceSymbolsManager.hasProvider() + 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) + case 'callHierarchy': + return this.callHierarchyManager.hasProvider(document) + case 'semanticTokens': + return this.semanticTokensManager.hasProvider(document) + case 'linkedEditing': + return this.linkedEditingManager.hasProvider(document) + default: + throw new Error(`Invalid provider name: ${id}`) + } + } + public createDiagnosticCollection(owner: string): DiagnosticCollection { + return diagnosticManager.create(owner) + } + + private get token(): CancellationToken { + this.cancelTokenSource = new CancellationTokenSource() + return this.cancelTokenSource.token + } +} + +export default new Languages() diff --git a/vim-config/plugins/coc.nvim/src/list/basic.ts b/vim-config/plugins/coc.nvim/src/list/basic.ts new file mode 100644 index 00000000..19c83d7e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/basic.ts @@ -0,0 +1,323 @@ +import { Neovim } from '@chemzqm/neovim' +import fs from 'fs' +import path from 'path' +import readline from 'readline' +import { CancellationToken, Disposable, Location, Position, Range } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import { ProviderResult } from '../provider' +import { IList, ListAction, ListArgument, ListContext, ListItem, ListTask, LocationWithLine, WorkspaceConfiguration } from '../types' +import { disposeAll } from '../util' +import { readFile } from '../util/fs' +import { comparePosition, emptyRange } from '../util/position' +import workspace from '../workspace' +import CommandTask, { CommandTaskOption } from './commandTask' +import ListConfiguration from './configuration' +const logger = require('../util/logger')('list-basic') + +interface ActionOptions { + persist?: boolean + reload?: boolean + parallel?: boolean +} + +interface ArgumentItem { + hasValue: boolean + name: string +} + +interface PreviewConfig { + winid: number + position: string + hlGroup: string + maxHeight: number + name?: string + splitRight: boolean + lnum: number + filetype?: string + range?: Range + scheme?: string + toplineStyle: string + toplineOffset: number +} + +export interface PreviewOptions { + bufname?: string + filetype: string + lines: string[] + lnum?: number + range?: Range + sketch?: boolean +} + +export default abstract class BasicList implements IList, Disposable { + public name: string + public defaultAction = 'open' + public readonly actions: ListAction[] = [] + public options: ListArgument[] = [] + protected disposables: Disposable[] = [] + private optionMap: Map + public config: ListConfiguration + + constructor(protected nvim: Neovim) { + this.config = new ListConfiguration() + } + + public get alignColumns(): boolean { + return this.config.get('alignColumns', false) + } + + protected get hlGroup(): string { + return this.config.get('previewHighlightGroup', 'Search') + } + + protected get previewHeight(): number { + return this.config.get('maxPreviewHeight', 12) + } + + protected get splitRight(): boolean { + return this.config.get('previewSplitRight', false) + } + + protected get toplineStyle(): string { + return this.config.get('previewToplineStyle', 'offset') + } + + protected get toplineOffset(): number { + return this.config.get('previewToplineOffset', 3) + } + + public parseArguments(args: string[]): { [key: string]: string | boolean } { + 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: { [key: string]: string | boolean } = {} + for (let i = 0; i < args.length; i++) { + let arg = args[i] + let def = this.optionMap.get(arg) + if (!def) continue + let value: string | boolean = true + if (def.hasValue) { + value = args[i + 1] || '' + i = i + 1 + } + res[def.name] = value + } + return res + } + + /** + * Get configuration of current list + */ + protected getConfig(): WorkspaceConfiguration { + return workspace.getConfiguration(`list.source.${this.name}`) + } + + protected addAction(name: string, fn: (item: ListItem, context: ListContext) => ProviderResult, options?: ActionOptions): void { + this.createAction(Object.assign({ + name, + execute: fn + }, options || {})) + } + + protected addMultipleAction(name: string, fn: (item: ListItem[], context: ListContext) => ProviderResult, options?: ActionOptions): void { + this.createAction(Object.assign({ + name, + multiple: true, + execute: fn + }, options || {})) + } + + protected createCommandTask(opt: CommandTaskOption): CommandTask { + return new CommandTask(opt) + } + + public addLocationActions(): void { + this.createAction({ + name: 'preview', + execute: async (item: ListItem, context: ListContext) => { + let loc = await this.convertLocation(item.location) + await this.previewLocation(loc, context) + } + }) + let { nvim } = this + this.createAction({ + name: 'quickfix', + multiple: true, + execute: async (items: ListItem[]) => { + let quickfixItems = await Promise.all(items.map(item => this.convertLocation(item.location).then(loc => workspace.getQuickfixItem(loc)))) + await nvim.call('setqflist', [quickfixItems]) + let openCommand = await nvim.getVar('coc_quickfix_open_command') as string + nvim.command(typeof openCommand === 'string' ? openCommand : 'copen', true) + } + }) + for (let name of ['open', 'tabe', 'drop', 'vsplit', 'split']) { + this.createAction({ + name, + execute: async (item: ListItem) => { + await this.jumpTo(item.location, name == 'open' ? null : name) + } + }) + } + } + + public async convertLocation(location: Location | LocationWithLine | string): Promise { + if (typeof location == 'string') return Location.create(location, Range.create(0, 0, 0, 0)) + if (Location.is(location)) return location + let u = URI.parse(location.uri) + if (u.scheme != 'file') return Location.create(location.uri, Range.create(0, 0, 0, 0)) + const rl = readline.createInterface({ + input: fs.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.includes(match)) { + 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 = Position.create(n, character + (location.text ? location.text.length : 0)) + return Location.create(location.uri, Range.create(Position.create(n, character), end)) + } + return Location.create(location.uri, Range.create(0, 0, 0, 0)) + } + + public async jumpTo(location: Location | LocationWithLine | string, command?: string): Promise { + if (typeof location == 'string') { + await workspace.jumpTo(location, null, command) + return + } + let { range, uri } = await this.convertLocation(location) + let position = range.start + if (position.line == 0 && position.character == 0 && comparePosition(position, range.end) == 0) { + // allow plugin that remember position. + position = null + } + await workspace.jumpTo(uri, position, command) + } + + public createAction(action: ListAction): void { + 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) + } + + protected async previewLocation(location: Location, context: ListContext): Promise { + if (!context.listWindow) return + let { nvim } = this + let { uri, range } = location + let doc = workspace.getDocument(location.uri) + let u = URI.parse(uri) + let lines: string[] = [] + if (doc) { + lines = doc.getLines() + } else if (u.scheme == 'file') { + try { + let content = await readFile(u.fsPath, 'utf8') + lines = content.split(/\r?\n/) + } catch (e) { + [`Error on read file ${u.fsPath}`, e.message] + } + } + let config: PreviewConfig = { + winid: context.window.id, + range: emptyRange(range) ? null : range, + lnum: range.start.line + 1, + name: u.scheme == 'file' ? u.fsPath : uri, + filetype: doc ? doc.filetype : this.getFiletype(u.fsPath), + position: context.options.position, + maxHeight: this.previewHeight, + splitRight: this.splitRight, + hlGroup: this.hlGroup, + scheme: u.scheme, + toplineStyle: this.toplineStyle, + toplineOffset: this.toplineOffset, + } + await nvim.call('coc#list#preview', [lines, config]) + if (workspace.isVim) nvim.command('redraw', true) + } + + public async preview(options: PreviewOptions, context: ListContext): Promise { + let { nvim } = this + let { bufname, filetype, range, lines, lnum } = options + let config: PreviewConfig = { + winid: context.window.id, + lnum: range ? range.start.line + 1 : lnum || 1, + filetype: filetype || 'txt', + position: context.options.position, + maxHeight: this.previewHeight, + splitRight: this.splitRight, + hlGroup: this.hlGroup, + toplineStyle: this.toplineStyle, + toplineOffset: this.toplineOffset, + } + if (bufname) config.name = bufname + if (range) config.range = range + await nvim.call('coc#list#preview', [lines, config]) + if (workspace.isVim) nvim.command('redraw', true) + } + + public abstract loadItems(context: ListContext, token?: CancellationToken): Promise + + public doHighlight(): void { + // noop + } + + public dispose(): void { + disposeAll(this.disposables) + } + + /** + * Get filetype by check same extension name buffer. + */ + private getFiletype(filepath: string): string { + let extname = path.extname(filepath) + if (!extname) return '' + for (let doc of workspace.documents) { + let fsPath = URI.parse(doc.uri).fsPath + if (path.extname(fsPath) == extname) { + return getFiletype(doc.filetype) + } + } + return '' + } +} + +export function getFiletype(filetype: string): string { + switch (filetype) { + case 'javascriptreact': + return 'javascript' + case 'typescriptreact': + return 'typescript' + case 'latex': + // LaTeX (LSP language ID 'latex') has Vim filetype 'tex' + return 'tex' + default: + if (filetype.indexOf('.') !== -1) return filetype.split('.')[0] + return filetype + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/commandTask.ts b/vim-config/plugins/coc.nvim/src/list/commandTask.ts new file mode 100644 index 00000000..e67dc19c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/commandTask.ts @@ -0,0 +1,59 @@ +import { spawn } from 'child_process' +import { EventEmitter } from 'events' +import readline from 'readline' +import { Disposable } from 'vscode-languageserver-protocol' +import { ListItem, ListTask } from '../types' +import { disposeAll } from '../util' +const logger = require('../util/logger')('list-commandTask') + +export interface CommandTaskOption { + /** + * Command to run. + */ + cmd: string + /** + * Arguments of command. + */ + args: string[] + cwd: string + /** + * Runs for each line, return undefined for invalid item. + */ + onLine: (line: string) => ListItem | undefined +} + +export default class CommandTask extends EventEmitter implements ListTask { + private disposables: Disposable[] = [] + constructor(private opt: CommandTaskOption) { + super() + this.start() + } + + private start(): void { + let { cmd, args, cwd, onLine } = this.opt + let proc = spawn(cmd, args, { cwd, windowsHide: true }) + this.disposables.push({ + dispose: () => { + proc.kill() + } + }) + proc.on('error', e => { + this.emit('error', e.message) + }) + proc.stderr.on('data', chunk => { + logger.error(`[${cmd} Error]`, chunk.toString('utf8')) + }) + const rl = readline.createInterface(proc.stdout) + rl.on('line', line => { + let res = onLine(line) + if (res) this.emit('data', res) + }) + rl.on('close', () => { + this.emit('end') + }) + } + + public dispose(): void { + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/configuration.ts b/vim-config/plugins/coc.nvim/src/list/configuration.ts new file mode 100644 index 00000000..933ad9e3 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/configuration.ts @@ -0,0 +1,120 @@ +import workspace from '../workspace' +import window from '../window' +import { WorkspaceConfiguration } from '../types' +import { EventEmitter } from 'events' +import { Disposable } from 'vscode-languageserver-protocol' + +export const validKeys = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '<2-LeftMouse>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', +] + +export default class ListConfiguration extends EventEmitter { + private configuration: WorkspaceConfiguration + private disposable: Disposable + constructor() { + super() + this.configuration = workspace.getConfiguration('list') + this.disposable = workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('list')) { + this.configuration = workspace.getConfiguration('list') + this.emit('change') + } + }) + } + + public get(key: string, defaultValue?: T): T { + return this.configuration.get(key, defaultValue) + } + + public get previousKey(): string { + return this.fixKey(this.configuration.get('previousKeymap', '')) + } + + public get nextKey(): string { + return this.fixKey(this.configuration.get('nextKeymap', '')) + } + + public dispose(): void { + this.disposable.dispose() + this.removeAllListeners() + } + + public fixKey(key: string): string { + if (validKeys.includes(key)) return key + let find = validKeys.find(s => s.toLowerCase() == key.toLowerCase()) + if (find) return find + window.showMessage(`Configured key "${key}" not supported.`, 'error') + return null + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/formatting.ts b/vim-config/plugins/coc.nvim/src/list/formatting.ts new file mode 100644 index 00000000..fa8a4c62 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/formatting.ts @@ -0,0 +1,55 @@ +import { ListItem } from '../types' +import path from 'path' + +export type PathFormatting = "full" | "short" | "filename" | "hidden" + +export interface UnformattedListItem extends Omit { + label: string[] +} + +export function formatListItems(align: boolean, list: UnformattedListItem[]): ListItem[] { + if (list.length === 0) { + return [] + } + + let processedList: ListItem[] = [] + if (align) { + const maxWidths = Array(Math.min(...list.map(item => item.label.length))).fill(0) + for (let item of list) { + for (let i = 0; i < maxWidths.length; i++) { + maxWidths[i] = Math.max(maxWidths[i], item.label[i].length) + } + } + processedList = list + .map(item => ({ + ...item, + label: item.label + .map((element, idx) => element.padEnd(maxWidths[idx])) + .join("\t") + })) + } else { + processedList = list.map(item => ({ ...item, label: item.label.join("\t") })) + } + return processedList +} + +export function formatPath(format: PathFormatting, pathToFormat: string): string { + if (format === "hidden") { + return "" + } else if (format === "full") { + return pathToFormat + } else if (format === "short") { + const segments = pathToFormat.split(path.sep) + if (segments.length < 2) { + return pathToFormat + } + const shortenedInit = segments + .slice(0, segments.length - 2) + .filter(seg => seg.length > 0) + .map(seg => seg[0]) + return [...shortenedInit, segments[segments.length - 1]].join(path.sep) + } else { + const segments = pathToFormat.split(path.sep) + return segments[segments.length - 1] ?? "" + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/history.ts b/vim-config/plugins/coc.nvim/src/list/history.ts new file mode 100644 index 00000000..4a71721e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/history.ts @@ -0,0 +1,83 @@ +import DB from '../model/db' +import { fuzzyMatch, getCharCodes } from '../util/fuzzy' +import workspace from '../workspace' +import Prompt from './prompt' +const logger = require('../util/logger')('list-history') + +export default class InputHistory { + private db: DB + private index = -1 + private loaded: string[] = [] + private current: string[] = [] + private historyInput: string + private key: string + + constructor( + private prompt: Prompt, + private name: string + ) { + this.db = workspace.createDatabase(`list-${name}-history`) + this.key = Buffer.from(workspace.cwd).toString('base64') + } + + public filter(): void { + let { input } = this.prompt + if (input == this.curr) return + this.historyInput = '' + let codes = getCharCodes(input) + this.current = this.loaded.filter(s => fuzzyMatch(codes, s)) + this.index = -1 + } + + public get curr(): string | null { + return this.index == -1 ? null : this.current[this.index] + } + + public load(input: string): void { + let { db } = this + input = input || '' + let arr = db.fetch(this.key) + if (!arr || !Array.isArray(arr)) { + this.loaded = [] + } else { + this.loaded = arr + } + this.index = -1 + this.current = this.loaded.filter(s => s.startsWith(input)) + } + + public add(): void { + let { loaded, db, prompt } = this + let { input } = prompt + if (!input || input.length < 2 || input == this.historyInput) 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(this.key, loaded) + } + + public previous(): void { + let { current, index } = this + if (!current || !current.length) return + if (index <= 0) { + this.index = current.length - 1 + } else { + this.index = index - 1 + } + this.historyInput = this.prompt.input = current[this.index] || '' + } + + public next(): void { + let { current, index } = this + if (!current || !current.length) return + if (index == current.length - 1) { + this.index = 0 + } else { + this.index = index + 1 + } + this.historyInput = this.prompt.input = current[this.index] || '' + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/manager.ts b/vim-config/plugins/coc.nvim/src/list/manager.ts new file mode 100644 index 00000000..9ac20ecc --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/manager.ts @@ -0,0 +1,496 @@ +import { Neovim } from '@chemzqm/neovim' +import debounce from 'debounce' +import { CancellationTokenSource, Disposable } from 'vscode-languageserver-protocol' +import events from '../events' +import extensions from '../extensions' +import { IList, ListOptions, Matcher } from '../types' +import { disposeAll } from '../util' +import workspace from '../workspace' +import window from '../window' +import ListConfiguration from './configuration' +import Mappings from './mappings' +import Prompt from './prompt' +import ListSession from './session' +import CommandsList from './source/commands' +import DiagnosticsList from './source/diagnostics' +import ExtensionList from './source/extensions' +import FolderList from './source/folders' +import LinksList from './source/links' +import ListsList from './source/lists' +import LocationList from './source/location' +import OutlineList from './source/outline' +import ServicesList from './source/services' +import SourcesList from './source/sources' +import SymbolsList from './source/symbols' +const logger = require('../util/logger')('list-manager') + +const mouseKeys = ['', '', '', '<2-LeftMouse>'] + +export class ListManager implements Disposable { + public prompt: Prompt + public config: ListConfiguration + private nvim: Neovim + private plugTs = 0 + private mappings: Mappings + private sessionsMap: Map = new Map() + private lastSession: ListSession | undefined + private disposables: Disposable[] = [] + private listMap: Map = new Map() + + public init(nvim: Neovim): void { + this.nvim = nvim + this.config = new ListConfiguration() + this.prompt = new Prompt(nvim, this.config) + this.mappings = new Mappings(this, nvim, this.config) + let signText = this.config.get('selectedSignText', '*') + nvim.command(`sign define CocSelected text=${signText} texthl=CocSelectedText linehl=CocSelectedLine`, true) + events.on('InputChar', this.onInputChar, this, this.disposables) + let debounced = debounce(async () => { + let session = await this.getCurrentSession() + if (session) this.prompt.drawPrompt() + }, 100) + events.on('FocusGained', debounced, null, this.disposables) + events.on('WinEnter', winid => { + let session = this.getSessionByWinid(winid) + if (session) this.prompt.start(session.listOptions) + }, null, this.disposables) + events.on('WinLeave', winid => { + let session = this.getSessionByWinid(winid) + if (session) this.prompt.cancel() + }, null, this.disposables) + this.disposables.push({ + dispose: () => { + debounced.clear() + } + }) + // filter history on input + this.prompt.onDidChangeInput(() => { + let { session } = this + if (!session) return + session.onInputChange() + session.history.filter() + }) + this.registerList(new LinksList(nvim)) + this.registerList(new LocationList(nvim)) + this.registerList(new SymbolsList(nvim)) + this.registerList(new OutlineList(nvim)) + this.registerList(new CommandsList(nvim)) + this.registerList(new ExtensionList(nvim)) + this.registerList(new DiagnosticsList(nvim)) + this.registerList(new SourcesList(nvim)) + this.registerList(new ServicesList(nvim)) + this.registerList(new ListsList(nvim, this.listMap)) + this.registerList(new FolderList(nvim)) + } + + public async start(args: string[]): Promise { + let res = this.parseArgs(args) + if (!res) return + let { name } = res.list + let curr = this.sessionsMap.get(name) + if (curr) curr.dispose() + this.prompt.start(res.options) + let session = new ListSession(this.nvim, this.prompt, res.list, res.options, res.listArgs, this.config) + this.sessionsMap.set(name, session) + this.lastSession = session + try { + await session.start(args) + } catch (e) { + this.nvim.call('coc#prompt#stop_prompt', ['list'], true) + let msg = e instanceof Error ? e.message : e.toString() + window.showMessage(`Error on "CocList ${name}": ${msg}`, 'error') + logger.error(e) + } + } + + private getSessionByWinid(winid: number): ListSession | null { + for (let session of this.sessionsMap.values()) { + if (session && session.winid == winid) { + this.lastSession = session + return session + } + } + return null + } + + private async getCurrentSession(): Promise { + let { id } = await this.nvim.window + for (let session of this.sessionsMap.values()) { + if (session && session.winid == id) { + this.lastSession = session + return session + } + } + return null + } + + public async resume(name?: string): Promise { + if (!name) { + await this.session?.resume() + } else { + let session = this.sessionsMap.get(name) + if (!session) { + window.showMessage(`Can't find exists ${name} list`) + return + } + await session.resume() + } + } + + public async doAction(name?: string): Promise { + let lastSession = this.lastSession + if (!lastSession) return + await lastSession.doAction(name) + } + + public async first(name?: string): Promise { + let s = this.getSession(name) + if (s) await s.first() + } + + public async last(name?: string): Promise { + let s = this.getSession(name) + if (s) await s.last() + } + + public async previous(name?: string): Promise { + let s = this.getSession(name) + if (s) await s.previous() + } + + public async next(name?: string): Promise { + let s = this.getSession(name) + if (s) await s.next() + } + + private getSession(name?: string): ListSession { + if (!name) return this.session + return this.sessionsMap.get(name) + } + + public async cancel(close = true): Promise { + this.prompt.cancel() + if (!close) return + if (this.session) await this.session.hide() + } + + /** + * Clear all list sessions + */ + public reset(): void { + this.prompt.cancel() + this.lastSession = undefined + for (let session of this.sessionsMap.values()) { + session.dispose() + } + this.sessionsMap.clear() + this.nvim.call('coc#prompt#stop_prompt', ['list'], true) + } + + public switchMatcher(): void { + this.session?.switchMatcher() + } + + public async togglePreview(): Promise { + let { nvim } = this + let winid = await nvim.call('coc#list#get_preview', [0]) + if (winid != -1) { + await nvim.call('coc#window#close', [winid]) + await nvim.command('redraw') + } else { + await this.doAction('preview') + } + } + + public async chooseAction(): Promise { + let { lastSession } = this + if (lastSession) await lastSession.chooseAction() + } + + public parseArgs(args: string[]): { list: IList; options: ListOptions; listArgs: string[] } | null { + let options: string[] = [] + let interactive = false + let autoPreview = false + let numberSelect = false + let noQuit = false + let first = false + let name: string + let input = '' + let matcher: Matcher = 'fuzzy' + let position = 'bottom' + let listArgs: string[] = [] + let listOptions: string[] = [] + for (let arg of args) { + if (!name && arg.startsWith('-')) { + listOptions.push(arg) + } else if (!name) { + if (!/^\w+$/.test(arg)) { + window.showMessage(`Invalid list option: "${arg}"`, 'error') + return null + } + name = arg + } else { + listArgs.push(arg) + } + } + name = name || 'lists' + let config = workspace.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 if (opt == '--first') { + first = true + } else if (opt == '--no-quit') { + noQuit = true + } else { + window.showMessage(`Invalid option "${opt}" of list`, 'error') + return null + } + } + let list = this.listMap.get(name) + if (!list) { + window.showMessage(`List ${name} not found`, 'error') + return null + } + if (interactive && !list.interactive) { + window.showMessage(`Interactive mode of "${name}" list not supported`, 'error') + return null + } + return { + list, + listArgs, + options: { + numberSelect, + autoPreview, + noQuit, + first, + input, + interactive, + matcher, + position, + ignorecase: options.includes('ignore-case') ? true : false, + mode: !options.includes('normal') ? 'insert' : 'normal', + sort: !options.includes('no-sort') ? true : false + }, + } + } + + private async onInputChar(session: string, ch: string, charmod: number): Promise { + if (session != 'list') return + let { mode } = this.prompt + let now = Date.now() + if (ch == '' || (this.plugTs && now - this.plugTs < 20)) { + this.plugTs = now + return + } + if (!ch) return + if (ch == '') { + await this.cancel() + return + } + if (mode == 'insert') { + await this.onInsertInput(ch, charmod) + } else { + await this.onNormalInput(ch, charmod) + } + } + + public async onInsertInput(ch: string, charmod?: number): Promise { + let { session } = this + if (!session) return + if (mouseKeys.includes(ch)) { + await this.onMouseEvent(ch) + return + } + let n = await session.doNumberSelect(ch) + if (n) return + let done = await this.mappings.doInsertKeymap(ch) + if (done || charmod) return + if (ch.startsWith('<') && ch.endsWith('>')) return + for (let s of ch) { + let code = s.codePointAt(0) + if (code == 65533) return + // exclude control character + if (code < 32 || code >= 127 && code <= 159) return + await this.prompt.acceptCharacter(s) + } + } + + public async onNormalInput(ch: string, _charmod?: number): Promise { + if (mouseKeys.includes(ch)) { + await this.onMouseEvent(ch) + return + } + let used = await this.mappings.doNormalKeymap(ch) + if (!used) await this.feedkeys(ch) + } + + private onMouseEvent(key): Promise { + if (this.session) return this.session.onMouseEvent(key) + } + + public async feedkeys(key: string, remap = true): Promise { + let { nvim } = this + key = key.startsWith('<') && key.endsWith('>') ? `\\${key}` : key + await nvim.call('coc#prompt#stop_prompt', ['list']) + await nvim.call('eval', [`feedkeys("${key}", "${remap ? 'i' : 'in'}")`]) + this.prompt.start() + } + + public async command(command: string): Promise { + let { nvim } = this + await nvim.call('coc#prompt#stop_prompt', ['list']) + await nvim.command(command) + this.prompt.start() + } + + public async normal(command: string, bang = true): Promise { + let { nvim } = this + await nvim.call('coc#prompt#stop_prompt', ['list']) + await nvim.command(`normal${bang ? '!' : ''} ${command}`) + this.prompt.start() + } + + public async call(fname: string): Promise { + if (this.session) return await this.session.call(fname) + } + + public get session(): ListSession | undefined { + return this.lastSession + } + + public registerList(list: IList): Disposable { + 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) + } + window.showMessage(`list "${name}" recreated.`) + } + this.listMap.set(name, list) + let config = workspace.getConfiguration(`list.source.${name}`) + let defaultAction = config.get('defaultAction') + if (defaultAction && list.actions.find(o => o.name == defaultAction)) { + list.defaultAction = defaultAction + } + extensions.addSchemeProperty(`list.source.${name}.defaultAction`, { + type: 'string', + default: null, + description: `Default default action of "${name}" list.` + }) + extensions.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', '--first', '--no-quit'] + } + }) + extensions.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 Disposable.create(() => { + if (typeof list.dispose == 'function') { + list.dispose() + } + this.listMap.delete(name) + }) + } + + public get names(): string[] { + return Array.from(this.listMap.keys()) + } + + public get descriptions(): { [name: string]: string } { + let d = {} + for (let name of this.listMap.keys()) { + let list = this.listMap.get(name) + d[name] = list.description + } + return d + } + + /** + * Get items of {name} list, not work with interactive list and list return task. + * + * @param {string} name + * @returns {Promise} + */ + public async loadItems(name: string): Promise { + let args = [name] + let res = this.parseArgs(args) + if (!res) return + let { list, options, listArgs } = res + let source = new CancellationTokenSource() + let token = source.token + let arr = await this.nvim.eval('[win_getid(),bufnr("%")]') + let items = await list.loadItems({ + options, + args: listArgs, + input: '', + cwd: workspace.cwd, + window: this.nvim.createWindow(arr[0]), + buffer: this.nvim.createBuffer(arr[1]), + listWindow: null + }, token) + return items + } + + public toggleMode(): void { + let lastSession = this.lastSession + if (lastSession) lastSession.toggleMode() + } + + public get isActivated(): boolean { + return this.session?.winid != null + } + + public stop(): void { + let lastSession = this.lastSession + if (lastSession) lastSession.stop() + } + + public dispose(): void { + for (let session of this.sessionsMap.values()) { + session.dispose() + } + this.sessionsMap.clear() + if (this.config) { + this.config.dispose() + } + this.lastSession = undefined + disposeAll(this.disposables) + } +} + +export default new ListManager() diff --git a/vim-config/plugins/coc.nvim/src/list/mappings.ts b/vim-config/plugins/coc.nvim/src/list/mappings.ts new file mode 100644 index 00000000..2b816ef2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/mappings.ts @@ -0,0 +1,321 @@ +import { Neovim } from '@chemzqm/neovim' +import { ListMode } from '../types' +import '../util/extensions' +import window from '../window' +import ListConfiguration, { validKeys } from './configuration' +import { ListManager } from './manager' +const logger = require('../util/logger')('list-mappings') + +export default class Mappings { + private insertMappings: Map void | Promise> = new Map() + private normalMappings: Map void | Promise> = new Map() + private userInsertMappings: Map = new Map() + private userNormalMappings: Map = new Map() + + constructor(private manager: ListManager, + private nvim: Neovim, + private config: ListConfiguration) { + let { prompt } = manager + + this.add('insert', '', () => { + manager.session?.history.next() + }) + this.add('insert', '', () => { + manager.session?.history.previous() + }) + this.add('insert', '', async () => { + await prompt.paste() + }) + this.add('insert', '', () => manager.switchMatcher()) + this.add('insert', ['', ''], async () => { + await manager.doAction() + }) + this.add('insert', ['', '', '\t'], () => manager.chooseAction()) + this.add('insert', '', () => { + manager.toggleMode() + }) + this.add('insert', '', () => { + manager.stop() + return + }) + this.add('insert', '', async () => { + await manager.session?.reloadItems() + }) + this.add('insert', '', () => { + prompt.moveLeft() + }) + this.add('insert', '', () => { + prompt.moveRight() + }) + this.add('insert', ['', ''], () => { + prompt.moveToEnd() + }) + this.add('insert', ['', ''], () => { + prompt.moveToStart() + }) + this.add('insert', ['', '', ''], () => { + prompt.onBackspace() + }) + this.add('insert', '', () => { + prompt.removeWord() + }) + this.add('insert', '', () => { + prompt.removeAhead() + }) + this.add('insert', '', () => prompt.insertRegister()) + this.add('insert', '', () => manager.feedkeys('', false)) + this.add('insert', '', () => manager.feedkeys('', false)) + this.add('insert', '', () => manager.feedkeys('', false)) + this.add('insert', '', () => manager.normal('j')) + this.add('insert', '', () => manager.normal('k')) + this.add('insert', [''], this.doScroll.bind(this, '')) + this.add('insert', [''], this.doScroll.bind(this, '')) + this.add('insert', [''], this.doScroll.bind(this, '')) + this.add('insert', [''], this.doScroll.bind(this, '')) + this.add('normal', 't', () => manager.doAction('tabe')) + this.add('normal', 's', () => manager.doAction('split')) + this.add('normal', 'd', () => manager.doAction('drop')) + this.add('normal', ['', '', '\r'], () => manager.doAction()) + this.add('normal', '', () => manager.session?.ui.selectAll()) + this.add('normal', ' ', () => manager.session?.ui.toggleSelection()) + this.add('normal', 'p', () => manager.togglePreview()) + this.add('normal', ['', '\t', ''], () => manager.chooseAction()) + this.add('normal', '', () => { + manager.stop() + }) + this.add('normal', '', () => manager.session?.reloadItems()) + this.add('normal', '', () => manager.session?.jumpBack()) + this.add('normal', '', () => this.scrollPreview('down')) + this.add('normal', '', () => this.scrollPreview('up')) + this.add('normal', ['i', 'I', 'o', 'O', 'a', 'A'], () => manager.toggleMode()) + this.add('normal', '?', () => manager.session?.showHelp()) + this.add('normal', ':', async () => { + await manager.cancel(false) + await nvim.eval('feedkeys(":")') + }) + this.add('normal', [''], this.doScroll.bind(this, '')) + this.add('normal', [''], this.doScroll.bind(this, '')) + this.createMappings() + config.on('change', () => { + this.createMappings() + }) + } + + private createMappings(): void { + let insertMappings = this.config.get('insertMappings', {}) + this.userInsertMappings = this.fixUserMappings(insertMappings) + let normalMappings = this.config.get('normalMappings', {}) + this.userNormalMappings = this.fixUserMappings(normalMappings) + } + + private fixUserMappings(mappings: { [key: string]: string }): Map { + let res: Map = 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 (key.toLowerCase() == '') { + res.set(' ', value) + } else if (key.toLowerCase() == '') { + res.set('', value) + } else if (validKeys.includes(key)) { + res.set(key, value) + } else { + let find = false + for (let i = 0; i < validKeys.length; i++) { + if (validKeys[i].toLowerCase() == key.toLowerCase()) { + find = true + res.set(validKeys[i], value) + break + } + } + if (!find) window.showMessage(`Invalid list mappings key configuration: "${key}"`, 'warning') + } + } else { + window.showMessage(`Invalid list mappings key configuration: "${key}"`, 'warning') + } + } + return res + } + + public async doInsertKeymap(key: string): Promise { + let nextKey = this.config.nextKey + let previousKey = this.config.previousKey + let { session } = this.manager + if (!session) return + if (key == nextKey) { + session.ui.index = session.ui.index + 1 + return true + } + if (key == previousKey) { + session.ui.index = session.ui.index - 1 + 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 + } + + public async doNormalKeymap(key: string): Promise { + 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 + } + + private add(mode: ListMode, key: string | string[], fn: () => void | Promise): void { + 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) + } + } + + private async onError(msg: string): Promise { + let { nvim } = this + await nvim.call('coc#prompt#stop_prompt', ['list']) + window.showMessage(msg, 'error') + } + + private async evalExpression(expr: string, _mode: string): Promise { + if (typeof expr != 'string' || !expr.includes(':')) { + await this.onError(`Invalid list mapping expression: ${expr}`) + return + } + let { manager } = this + let { prompt } = manager + let [key, action] = expr.split(':', 2) + if (key == 'do') { + switch (action.toLowerCase()) { + case 'switch': + manager.switchMatcher() + return + case 'selectall': + await manager.session?.ui.selectAll() + return + case 'help': + await manager.session?.showHelp() + return + case 'refresh': + await manager.session?.reloadItems() + return + case 'exit': + await manager.cancel() + return + case 'stop': + manager.stop() + return + case 'cancel': + await manager.cancel(false) + return + case 'toggle': + await manager.session?.ui.toggleSelection() + return + case 'jumpback': + manager.session?.jumpBack() + return + case 'previous': + await manager.normal('k') + return + case 'next': + await manager.normal('j') + return + case 'defaultaction': + await manager.doAction() + return + case 'togglemode': + return manager.toggleMode() + case 'previewtoggle': + return manager.togglePreview() + case 'previewup': + return this.scrollPreview('up') + case 'previewdown': + return this.scrollPreview('down') + default: + await this.onError(`'${action}' not supported`) + } + } else if (key == 'prompt') { + switch (action) { + case 'previous': + manager.session?.history.previous() + return + case 'next': + manager.session?.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': + 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}`) + } + } + + private async doScroll(key: string): Promise { + await this.manager.feedkeys(key) + } + + private scrollPreview(dir: 'up' | 'down'): void { + let { nvim } = this + nvim.pauseNotification() + nvim.call('coc#list#scroll_preview', [dir], true) + nvim.command('redraw', true) + void nvim.resumeNotification(false, true) + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/prompt.ts b/vim-config/plugins/coc.nvim/src/list/prompt.ts new file mode 100644 index 00000000..ca31cd62 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/prompt.ts @@ -0,0 +1,214 @@ +import { Neovim } from '@chemzqm/neovim' +import { Emitter, Event } from 'vscode-languageserver-protocol' +import { ListMode, ListOptions, Matcher } from '../types' +import ListConfiguration from './configuration' +const logger = require('../util/logger')('list-prompt') + +export default class Prompt { + private cusorIndex = 0 + private _input = '' + private _matcher: Matcher | '' + private _mode: ListMode = 'insert' + private interactive = false + private requestInput = false + + private _onDidChangeInput = new Emitter() + public readonly onDidChangeInput: Event = this._onDidChangeInput.event + + constructor(private nvim: Neovim, private config: ListConfiguration) { + } + + public get input(): string { + return this._input + } + + public set input(str: string) { + if (this._input == str) return + this.cusorIndex = str.length + this._input = str + this.drawPrompt() + this._onDidChangeInput.fire(this._input) + } + + public get mode(): ListMode { + return this._mode + } + + public set mode(val: ListMode) { + if (val == this._mode) return + this._mode = val + this.drawPrompt() + } + + public set matcher(val: Matcher) { + this._matcher = val + this.drawPrompt() + } + + public start(opts?: ListOptions): void { + 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 + } + this.nvim.call('coc#prompt#start_prompt', ['list'], true) + this.drawPrompt() + } + + public cancel(): void { + let { nvim } = this + nvim.call('coc#prompt#stop_prompt', ['list'], true) + } + + public reset(): void { + this._input = '' + this.cusorIndex = 0 + } + + public drawPrompt(): void { + 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) + } + + public moveLeft(): void { + if (this.cusorIndex == 0) return + this.cusorIndex = this.cusorIndex - 1 + this.drawPrompt() + } + + public moveRight(): void { + if (this.cusorIndex == this._input.length) return + this.cusorIndex = this.cusorIndex + 1 + this.drawPrompt() + } + + public moveToEnd(): void { + if (this.cusorIndex == this._input.length) return + this.cusorIndex = this._input.length + this.drawPrompt() + } + + public moveToStart(): void { + if (this.cusorIndex == 0) return + this.cusorIndex = 0 + this.drawPrompt() + } + + public onBackspace(): void { + 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) + } + + public removeNext(): void { + 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) + } + + public removeWord(): void { + 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) + } + + public removeTail(): void { + 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) + } + + public removeAhead(): void { + 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) + } + + public async acceptCharacter(ch: string): Promise { + if (this.requestInput) { + this.requestInput = false + if (/^[0-9a-z"%#*+/:\-.]$/.test(ch)) { + let text = await this.nvim.call('getreg', ch) as string + text = text.replace(/\n/g, ' ') + this.addText(text) + } + } else { + this.addText(ch) + } + } + + public insertRegister(): void { + this.requestInput = true + } + + public async paste(): Promise { + let text = await this.nvim.eval('@*') as string + text = text.replace(/\n/g, '') + if (!text) return + this.addText(text) + } + + public async eval(expression: string): Promise { + let text = await this.nvim.call('eval', [expression]) as string + text = text.replace(/\n/g, '') + this.addText(text) + } + + private addText(text: string): void { + 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) + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/session.ts b/vim-config/plugins/coc.nvim/src/list/session.ts new file mode 100644 index 00000000..bcdd43d4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/session.ts @@ -0,0 +1,578 @@ +import { Buffer, Neovim, Window } from '@chemzqm/neovim' +import debounce from 'debounce' +import { Disposable } from 'vscode-languageserver-protocol' +import { Mutex } from '../util/mutex' +import extensions from '../extensions' +import Highlighter from '../model/highligher' +import { IList, ListAction, ListContext, ListItem, ListMode, ListOptions, Matcher } from '../types' +import { disposeAll, wait } from '../util' +import workspace from '../workspace' +import window from '../window' +import ListConfiguration from './configuration' +import InputHistory from './history' +import Prompt from './prompt' +import UI from './ui' +import Worker from './worker' +const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] +const logger = require('../util/logger')('list-session') + +/** + * Activated list session with UI and worker + */ +export default class ListSession { + public readonly history: InputHistory + public readonly ui: UI + public readonly worker: Worker + private cwd: string + private interval: NodeJS.Timer + private loadingFrame = '' + private timer: NodeJS.Timer + private hidden = false + private disposables: Disposable[] = [] + private savedHeight: number + private window: Window + private buffer: Buffer + private interactiveDebounceTime: number + private mutex: Mutex = new Mutex() + /** + * Original list arguments. + */ + private args: string[] = [] + constructor( + private nvim: Neovim, + private prompt: Prompt, + private list: IList, + public readonly listOptions: ListOptions, + private listArgs: string[] = [], + private config: ListConfiguration + ) { + this.ui = new UI(nvim, list.name, listOptions, config) + this.history = new InputHistory(prompt, list.name) + this.worker = new Worker(nvim, list, prompt, listOptions, { + interactiveDebounceTime: config.get('interactiveDebounceTime', 100), + extendedSearchMode: config.get('extendedSearchMode', true) + }) + this.interactiveDebounceTime = config.get('interactiveDebounceTime', 100) + let debouncedChangeLine = debounce(async () => { + let [previewing, currwin, lnum] = await nvim.eval('[coc#list#has_preview(),win_getid(),line(".")]') as [number, number, number] + if (previewing && currwin == this.winid) { + await this.doPreview(lnum - 1) + } + }, 50) + this.disposables.push({ + dispose: () => { + debouncedChangeLine.clear() + } + }) + this.ui.onDidChangeLine(debouncedChangeLine, null, this.disposables) + this.ui.onDidChangeLine(this.resolveItem, this, this.disposables) + this.ui.onDidLineChange(this.resolveItem, this, this.disposables) + let debounced = debounce(async () => { + let { autoPreview } = this.listOptions + if (!autoPreview) { + let [previewing, mode] = await nvim.eval('[coc#list#has_preview(),mode()]') as [number, string] + if (!previewing || mode != 'n') return + } + await this.doAction('preview') + }, 50) + this.disposables.push({ + dispose: () => { + debounced.clear() + } + }) + this.ui.onDidLineChange(debounced, null, this.disposables) + this.ui.onDidLineChange(() => { + this.updateStatus() + }, null, this.disposables) + this.ui.onDidOpen(async () => { + if (typeof this.list.doHighlight == 'function') { + this.list.doHighlight() + } + if (this.listOptions.first) { + await this.doAction() + } + }, null, this.disposables) + this.ui.onDidClose(async () => { + await this.hide() + }, null, this.disposables) + this.ui.onDidDoubleClick(async () => { + await this.doAction() + }, null, this.disposables) + this.worker.onDidChangeItems(async ({ items, reload, append, finished }) => { + let release = await this.mutex.acquire() + if (!this.hidden) { + try { + if (append) { + this.ui.appendItems(items) + } else { + let height = this.config.get('height', 10) + if (finished && !listOptions.interactive && listOptions.input.length == 0) { + height = Math.min(items.length, height) + } + await this.ui.drawItems(items, Math.max(1, height), reload) + } + } catch (e) { + nvim.echoError(e) + } + } + release() + }, null, this.disposables) + this.worker.onDidChangeLoading(loading => { + if (this.hidden) return + if (loading) { + this.interval = setInterval(() => { + let idx = Math.floor((new Date()).getMilliseconds() / 100) + this.loadingFrame = frames[idx] + this.updateStatus() + }, 100) + } else { + if (this.interval) { + this.loadingFrame = '' + clearInterval(this.interval) + this.interval = null + } + this.updateStatus() + } + }, null, this.disposables) + } + + public async start(args: string[]): Promise { + this.args = args + this.cwd = workspace.cwd + this.hidden = false + let { listOptions, listArgs } = this + let res = await this.nvim.eval('[win_getid(),bufnr("%"),winheight("%")]') + this.listArgs = listArgs + this.history.load(listOptions.input || '') + this.window = this.nvim.createWindow(res[0]) + this.buffer = this.nvim.createBuffer(res[1]) + this.savedHeight = res[2] + await this.worker.loadItems(this.context) + } + + public async reloadItems(): Promise { + if (!this.window) return + let bufnr = await this.nvim.call('winbufnr', [this.window.id]) + // can't reload since window not exists + if (bufnr == -1) return + this.buffer = this.nvim.createBuffer(bufnr) + await this.worker.loadItems(this.context, true) + } + + public async call(fname: string): Promise { + await this.nvim.call('coc#prompt#stop_prompt', ['list']) + let targets = await this.ui.getItems() + let context = { + name: this.name, + args: this.listArgs, + input: this.prompt.input, + winid: this.window?.id, + bufnr: this.buffer?.id, + targets + } + let res = await this.nvim.call(fname, [context]) + this.prompt.start() + return res + } + + public async chooseAction(): Promise { + let { nvim } = this + let { actions, defaultAction } = this.list + let names: string[] = actions.map(o => o.name) + let idx = names.indexOf(defaultAction) + if (idx != -1) { + names.splice(idx, 1) + names.unshift(defaultAction) + } + let shortcuts: Set = new Set() + let choices: string[] = [] + let invalids: string[] = [] + 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++ + } + if (i == name.length) { + invalids.push(name) + } + } + if (invalids.length) { + names = names.filter(s => !invalids.includes(s)) + } + await nvim.call('coc#prompt#stop_prompt', ['list']) + let n = await nvim.call('confirm', ['Choose action:', choices.join('\n')]) as number + await wait(10) + this.prompt.start() + if (n) await this.doAction(names[n - 1]) + if (invalids.length) { + nvim.echoError(`Can't create shortcut for actions: ${invalids.join(',')} of "${this.name}" list`) + } + } + + public async doAction(name?: string): Promise { + let { list } = this + name = name || list.defaultAction + let action = list.actions.find(o => o.name == name) + if (!action) { + window.showMessage(`Action ${name} not found`, 'error') + return + } + let items: ListItem[] + 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) + } + + private async doPreview(index: number): Promise { + let item = this.ui.getItem(index) + let action = this.list.actions.find(o => o.name == 'preview') + if (!item || !action) return + await this.doItemAction([item], action) + } + + public async first(): Promise { + await this.doDefaultAction(0) + } + + public async last(): Promise { + await this.doDefaultAction(this.ui.length - 1) + } + + public async previous(): Promise { + await this.doDefaultAction(this.ui.index - 1) + } + + public async next(): Promise { + await this.doDefaultAction(this.ui.index + 1) + } + + private async doDefaultAction(index: number): Promise { + let { ui } = this + let item = ui.getItem(index) + if (!item) return + ui.index = index + await this.doItemAction([item], this.defaultAction) + await ui.echoMessage(item) + } + + /** + * list name + */ + public get name(): string { + return this.list.name + } + + /** + * Window id used by list. + * + * @returns {number | undefined} + */ + public get winid(): number | undefined { + return this.ui.winid + } + + public get length(): number { + return this.ui.length + } + + private get defaultAction(): ListAction { + let { defaultAction, actions } = this.list + let action = actions.find(o => o.name == defaultAction) + if (!action) throw new Error(`default action "${defaultAction}" not found`) + return action + } + + public async hide(): Promise { + if (this.hidden) return + let { nvim, interval } = this + if (interval) clearInterval(interval) + this.hidden = true + this.worker.stop() + this.history.add() + let { winid } = this.ui + this.ui.reset() + if (this.window && winid) { + await nvim.call('coc#list#hide', [this.window.id, this.savedHeight, winid]) + if (workspace.isVim) { + nvim.command('redraw', true) + // Needed for tabe action, don't know why. + await wait(10) + } + } + nvim.call('coc#prompt#stop_prompt', ['list'], true) + } + + public toggleMode(): void { + let mode: ListMode = this.prompt.mode == 'normal' ? 'insert' : 'normal' + this.prompt.mode = mode + this.listOptions.mode = mode + this.updateStatus() + } + + public stop(): void { + this.worker.stop() + } + + private async resolveItem(): Promise { + let index = this.ui.index + let item = this.ui.getItem(index) + if (!item || item.resolved) return + let { list } = this + if (typeof list.resolveItem == 'function') { + let resolved = await Promise.resolve(list.resolveItem(item)) + if (resolved && index == this.ui.index) { + await this.ui.updateItem(resolved, index) + } + } + } + + public async showHelp(): Promise { + await this.hide() + let { list, nvim } = this + if (!list) return + nvim.pauseNotification() + nvim.command(`tabe +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 Highlighter() + 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.getConfiguration(`list.source.${list.name}`) + if (Object.keys(config).length) { + highligher.addLine('CONFIGURATIONS', 'Label') + highligher.addLine('') + let props = {} + extensions.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!', true) + await nvim.resumeNotification() + } + + public switchMatcher(): void { + let { matcher, interactive } = this.listOptions + if (interactive) return + const list: Matcher[] = ['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] + this.worker.drawItems() + } + + public updateStatus(): void { + let { ui, list, nvim } = this + if (!ui.winid) return + let buf = nvim.createBuffer(ui.bufnr) + let status = { + mode: this.prompt.mode.toUpperCase(), + args: this.args.join(' '), + name: list.name, + cwd: this.cwd, + loading: this.loadingFrame, + total: this.worker.length + } + nvim.pauseNotification() + buf.setVar('list_status', status, true) + nvim.command('redraws', true) + nvim.resumeNotification(false, true).logError() + } + + public get context(): ListContext { + let { winid } = this.ui + return { + options: this.listOptions, + args: this.listArgs, + input: this.prompt.input, + cwd: workspace.cwd, + window: this.window, + buffer: this.buffer, + listWindow: winid ? this.nvim.createWindow(winid) : undefined + } + } + + public onMouseEvent(key): Promise { + switch (key) { + case '': + return this.ui.onMouse('mouseDown') + case '': + return this.ui.onMouse('mouseDrag') + case '': + return this.ui.onMouse('mouseUp') + case '<2-LeftMouse>': + return this.ui.onMouse('doubleClick') + } + } + + public async doNumberSelect(ch: string): Promise { + if (!this.listOptions.numberSelect) return false + let code = ch.charCodeAt(0) + if (code >= 48 && code <= 57) { + let n = Number(ch) + if (n == 0) n = 10 + if (this.ui.length >= n) { + this.nvim.pauseNotification() + this.ui.setCursor(n, 0) + await this.nvim.resumeNotification() + await this.doAction() + return true + } + } + return false + } + + public jumpBack(): void { + let { window, nvim } = this + if (window) { + nvim.pauseNotification() + nvim.call('coc#prompt#stop_prompt', ['list'], true) + this.nvim.call('win_gotoid', [window.id], true) + nvim.resumeNotification(false, true).logError() + } + } + + public async resume(): Promise { + if (this.winid) await this.hide() + let res = await this.nvim.eval('[win_getid(),bufnr("%"),winheight("%")]') + this.hidden = false + this.window = this.nvim.createWindow(res[0]) + this.buffer = this.nvim.createBuffer(res[1]) + this.savedHeight = res[2] + this.prompt.start() + await this.ui.resume() + if (this.listOptions.autoPreview) { + await this.doAction('preview') + } + } + + private async doItemAction(items: ListItem[], action: ListAction): Promise { + let { noQuit } = this.listOptions + let { nvim } = this + let persistAction = action.persist === true || action.name == 'preview' + let persist = this.winid && (persistAction || noQuit) + try { + if (persist) { + if (!persistAction) { + nvim.pauseNotification() + nvim.call('coc#prompt#stop_prompt', ['list'], true) + nvim.call('win_gotoid', [this.context.window.id], true) + await nvim.resumeNotification() + } + } else { + await this.hide() + } + if (action.multiple) { + await Promise.resolve(action.execute(items, this.context)) + } else if (action.parallel) { + await Promise.all(items.map(item => Promise.resolve(action.execute(item, this.context)))) + } else { + for (let item of items) { + await Promise.resolve(action.execute(item, this.context)) + } + } + if (persist) { + this.ui.restoreWindow() + } + if (action.reload && persist) await this.worker.loadItems(this.context, true) + } catch (e) { + window.showMessage(e.message, 'error') + logger.error(`Error on action "${action.name}"`, e) + } + } + + public onInputChange(): void { + if (this.timer) clearTimeout(this.timer) + let len = this.worker.length + this.listOptions.input = this.prompt.input + // reload or filter items + if (this.listOptions.interactive) { + this.worker.stop() + this.timer = setTimeout(async () => { + await this.worker.loadItems(this.context) + }, this.interactiveDebounceTime) + } else if (len) { + let wait = Math.max(Math.min(Math.floor(len / 200), 300), 50) + this.timer = setTimeout(() => { + this.worker.drawItems() + }, wait) + } + } + + public dispose(): void { + if (!this.hidden) { + this.hidden = true + let { winid } = this.ui + this.ui.reset() + if (this.window && winid) { + this.nvim.call('coc#list#hide', [this.window.id, this.savedHeight, winid], true) + } + } + if (this.interval) { + clearInterval(this.interval) + } + if (this.timer) { + clearTimeout(this.timer) + } + disposeAll(this.disposables) + this.worker.dispose() + this.ui.dispose() + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/commands.ts b/vim-config/plugins/coc.nvim/src/list/source/commands.ts new file mode 100644 index 00000000..17247e2b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/commands.ts @@ -0,0 +1,59 @@ +import { Neovim } from '@chemzqm/neovim' +import commandManager from '../../commands' +import events from '../../events' +import Mru from '../../model/mru' +import { ListContext, ListItem } from '../../types' +import workspace from '../../workspace' +import BasicList from '../basic' +import { formatListItems, UnformattedListItem } from '../formatting' + +export default class CommandsList extends BasicList { + public defaultAction = 'run' + public description = 'registered commands of coc.nvim' + public readonly name = 'commands' + private mru: Mru + + constructor(nvim: Neovim) { + super(nvim) + this.mru = workspace.createMru('commands') + this.addAction('run', async item => { + let { cmd } = item.data + await events.fire('Command', [cmd]) + commandManager.executeCommand(cmd).logError() + await commandManager.addRecent(cmd) + }) + this.addAction('append', async item => { + let { cmd } = item.data + await nvim.feedKeys(`:CocCommand ${cmd} `, 'n', false) + }) + } + + public async loadItems(_context: ListContext): Promise { + let items: UnformattedListItem[] = [] + let mruList = await this.mru.load() + let { commandList, onCommandList, titles } = commandManager + let ids = commandList.map(c => c.id).concat(onCommandList) + for (const id of [...new Set(ids)]) { + items.push({ + label: [id, ...(titles.get(id) ? [titles.get(id)] : [])], + filterText: id, + data: { cmd: id, score: score(mruList, id) } + }) + } + items.sort((a, b) => b.data.score - a.data.score) + return formatListItems(this.alignColumns, items) + } + + public doHighlight(): void { + let { nvim } = this + nvim.pauseNotification() + nvim.command('syntax match CocCommandsTitle /\\t.*$/ contained containedin=CocCommandsLine', true) + nvim.command('highlight default link CocCommandsTitle Comment', true) + void nvim.resumeNotification(false, true) + } +} + +function score(list: string[], key: string): number { + let idx = list.indexOf(key) + return idx == -1 ? -1 : list.length - idx +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/diagnostics.ts b/vim-config/plugins/coc.nvim/src/list/source/diagnostics.ts new file mode 100644 index 00000000..ef66ba29 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/diagnostics.ts @@ -0,0 +1,49 @@ +import path from 'path' +import diagnosticManager from '../../diagnostic/manager' +import { ListContext, ListItem } from '../../types' +import LocationList from './location' +import { isParentFolder } from '../../util/fs' +import { formatListItems, formatPath, PathFormatting, UnformattedListItem } from '../formatting' +const logger = require('../../util/logger')('list-symbols') + +export default class DiagnosticsList extends LocationList { + public readonly defaultAction = 'open' + public readonly description = 'diagnostics of current workspace' + public name = 'diagnostics' + + public async loadItems(context: ListContext): Promise { + let list = diagnosticManager.getDiagnosticList() + let { cwd } = context + const config = this.getConfig() + const shouldIncludeCode = config.get('includeCode', true) + const pathFormat = config.get('pathFormat', "full") + const unformatted: UnformattedListItem[] = list.map(item => { + const file = isParentFolder(cwd, item.file) ? path.relative(cwd, item.file) : item.file + const formattedPath = formatPath(pathFormat, file) + const formattedPosition = pathFormat !== "hidden" ? [`${formattedPath}:${item.lnum}`] : [] + const code = shouldIncludeCode ? [`[${item.source}${item.code ? '' : ']'}`, item.code ? `${item.code}]` : ''] : [] + return { + label: [...formattedPosition, ...code, item.severity, item.message], + location: item.location, + } + }) + return formatListItems(this.alignColumns, unformatted) + } + + public doHighlight(): void { + let { nvim } = this + nvim.pauseNotification() + nvim.command('syntax match CocDiagnosticsFile /\\v^\\s*\\S+/ contained containedin=CocDiagnosticsLine', true) + nvim.command('syntax match CocDiagnosticsError /\\tError\\s*\\t/ contained containedin=CocDiagnosticsLine', true) + nvim.command('syntax match CocDiagnosticsWarning /\\tWarning\\s*\\t/ contained containedin=CocDiagnosticsLine', true) + nvim.command('syntax match CocDiagnosticsInfo /\\tInformation\\s*\\t/ contained containedin=CocDiagnosticsLine', true) + nvim.command('syntax match CocDiagnosticsHint /\\tHint\\s*\\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) + void nvim.resumeNotification(false, true) + } +} + diff --git a/vim-config/plugins/coc.nvim/src/list/source/extensions.ts b/vim-config/plugins/coc.nvim/src/list/source/extensions.ts new file mode 100644 index 00000000..94843c47 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/extensions.ts @@ -0,0 +1,180 @@ +import { Neovim } from '@chemzqm/neovim' +import fs from 'fs-extra' +import os from 'os' +import path from 'path' +import { URI } from 'vscode-uri' +import extensions from '../../extensions' +import { ListContext, ListItem } from '../../types' +import { wait } from '../../util' +import workspace from '../../workspace' +import window from '../../window' +import BasicList from '../basic' +import { formatListItems, UnformattedListItem } from '../formatting' +const logger = require('../../util/logger')('list-extensions') + +export default class ExtensionList extends BasicList { + public defaultAction = 'toggle' + public description = 'manage coc extensions' + public name = 'extensions' + + constructor(nvim: Neovim) { + super(nvim) + this.addAction('toggle', async item => { + let { id, state } = item.data + if (state == 'disabled') return + if (state == 'activated') { + await extensions.deactivate(id) + } else { + await extensions.activate(id) + } + await wait(100) + }, { persist: true, reload: true, parallel: true }) + + this.addAction('configuration', async item => { + let { root } = item.data + let jsonFile = path.join(root, 'package.json') + if (fs.existsSync(jsonFile)) { + let lines = fs.readFileSync(jsonFile, 'utf8').split(/\r?\n/) + let idx = lines.findIndex(s => s.includes('"contributes"')) + await workspace.jumpTo(URI.file(jsonFile).toString(), { line: idx == -1 ? 0 : idx, character: 0 }) + } + }) + + this.addAction('open', async item => { + let { root } = item.data + if (workspace.env.isiTerm) { + nvim.call('coc#util#iterm_open', [root], true) + } else { + nvim.call('coc#util#open_url', [root], true) + } + }) + + this.addAction('disable', async item => { + let { id, state } = item.data + if (state !== 'disabled') await extensions.toggleExtension(id) + }, { persist: true, reload: true, parallel: true }) + + this.addAction('enable', async item => { + let { id, state } = item.data + if (state == 'disabled') await extensions.toggleExtension(id) + }, { persist: true, reload: true, parallel: true }) + + this.addAction('lock', async item => { + let { id } = item.data + await extensions.toggleLock(id) + }, { persist: true, reload: true }) + + this.addAction('help', async item => { + let { root } = item.data + let files = await fs.readdir(root) + let file = files.find(f => /^readme/i.test(f)) + if (file) await workspace.callAsync('coc#util#jump', ['edit', path.join(root, file)]) + }) + + this.addAction('reload', async item => { + let { id } = item.data + await extensions.reloadExtension(id) + }, { persist: true, reload: true }) + + this.addAction('fix', async item => { + let { root, isLocal } = item.data + let { npm } = extensions + if (isLocal) { + window.showMessage(`Can't fix for local extension.`, 'warning') + return + } + if (!npm) return + let folder = path.join(root, 'node_modules') + if (fs.existsSync(folder)) { + fs.removeSync(folder) + } + let terminal = await workspace.createTerminal({ + cwd: root + }) + let shown = await terminal.show(false) + if (!shown) return + workspace.nvim.command(`startinsert`, true) + terminal.sendText(`${npm} install --production --ignore-scripts --no-lockfile`, true) + }) + + this.addMultipleAction('uninstall', async items => { + let ids = [] + for (let item of items) { + if (item.data.isLocal) continue + ids.push(item.data.id) + } + extensions.uninstallExtension(ids).catch(e => { + logger.error(e) + }) + }) + } + + public async loadItems(_context: ListContext): Promise { + let items: UnformattedListItem[] = [] + let list = await extensions.getExtensionStates() + let lockedList = await extensions.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.includes(stat.id) + items.push({ + label: [`${prefix} ${stat.id}${locked ? ' ' : ''}`, ...(stat.isLocal ? ['[RTP]'] : []), stat.version, root.replace(os.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 formatListItems(this.alignColumns, items) + } + + public doHighlight(): void { + 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 + }) + } +} + +function getPriority(stat: string): number { + switch (stat) { + case 'unknown': + return 2 + case 'activated': + return 1 + case 'disabled': + return -1 + default: + return 0 + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/folders.ts b/vim-config/plugins/coc.nvim/src/list/source/folders.ts new file mode 100644 index 00000000..b2ea073f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/folders.ts @@ -0,0 +1,48 @@ +import { Neovim } from '@chemzqm/neovim' +import path from 'path' +import { URI } from 'vscode-uri' +import fs from 'fs-extra' +import { ListContext, ListItem } from '../../types' +import { statAsync } from '../../util/fs' +import workspace from '../../workspace' +import window from '../../window' +import BasicList from '../basic' + +export default class FoldList extends BasicList { + public defaultAction = 'edit' + public description = 'list of current workspace folders' + public name = 'folders' + + constructor(nvim: Neovim) { + super(nvim) + + this.addAction('edit', async item => { + let newPath = await nvim.call('input', ['Folder: ', item.label, 'dir']) + let stat = await statAsync(newPath) + if (!stat || !stat.isDirectory()) { + window.showMessage(`invalid path: ${newPath}`, 'error') + return + } + workspace.renameWorkspaceFolder(item.label, newPath) + }) + + this.addAction('delete', async item => { + workspace.removeWorkspaceFolder(item.label) + }, { reload: true, persist: true }) + + this.addAction('newfile', async item => { + let file = await window.requestInput('File name', item.label + '/') + let dir = path.dirname(file) + let stat = await statAsync(dir) + if (!stat || !stat.isDirectory()) { + fs.mkdirpSync(dir) + } + await workspace.createFile(file, { overwrite: false, ignoreIfExists: true }) + await this.jumpTo(URI.file(file).toString()) + }) + } + + public async loadItems(_context: ListContext): Promise { + return workspace.folderPaths.map(p => ({ label: p })) + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/links.ts b/vim-config/plugins/coc.nvim/src/list/source/links.ts new file mode 100644 index 00000000..02eee7c8 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/links.ts @@ -0,0 +1,77 @@ +import { Neovim } from '@chemzqm/neovim' +import languages from '../../languages' +import workspace from '../../workspace' +import path from 'path' +import { ListContext, ListItem } from '../../types' +import BasicList from '../basic' +import { DocumentLink, Location } from 'vscode-languageserver-types' +import { URI } from 'vscode-uri' +import { isParentFolder } from '../../util/fs' +import { CancellationToken } from 'vscode-languageserver-protocol' + +export default class LinksList extends BasicList { + public defaultAction = 'open' + public description = 'links of current buffer' + public name = 'links' + + constructor(nvim: Neovim) { + super(nvim) + + this.addAction('open', async item => { + let { target } = item.data + let uri = URI.parse(target) + if (uri.scheme.startsWith('http')) { + await nvim.call('coc#util#open_url', target) + } else { + await workspace.jumpTo(target) + } + }) + + this.addAction('jump', async item => { + let { location } = item.data + await workspace.jumpTo(location.uri, location.range.start) + }) + } + + public async loadItems(context: ListContext, token: CancellationToken): Promise { + let buf = await context.window.buffer + let doc = workspace.getDocument(buf.id) + if (!doc) return null + let items: ListItem[] = [] + let links = await languages.getDocumentLinks(doc.textDocument, token) + if (links == null) { + throw new Error('Links provider not found.') + } + let res: DocumentLink[] = [] + for (let link of links) { + if (link.target) { + items.push({ + label: formatUri(link.target), + data: { + target: link.target, + location: Location.create(doc.uri, link.range) + } + }) + } else { + link = await languages.resolveDocumentLink(link) + if (link.target) { + items.push({ + label: formatUri(link.target), + data: { + target: link.target, + location: Location.create(doc.uri, link.range) + } + }) + } + res.push(link) + } + } + return items + } +} + +function formatUri(uri: string): string { + if (!uri.startsWith('file:')) return uri + let filepath = URI.parse(uri).fsPath + return isParentFolder(workspace.cwd, filepath) ? path.relative(workspace.cwd, filepath) : filepath +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/lists.ts b/vim-config/plugins/coc.nvim/src/list/source/lists.ts new file mode 100644 index 00000000..ad15fd48 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/lists.ts @@ -0,0 +1,55 @@ +import { Neovim } from '@chemzqm/neovim' +import { IList, ListContext, ListItem } from '../../types' +import BasicList from '../basic' +import Mru from '../../model/mru' +import { formatListItems, UnformattedListItem } from '../formatting' + +export default class LinksList extends BasicList { + public readonly name = 'lists' + public readonly defaultAction = 'open' + public readonly description = 'registered lists of coc.nvim' + private mru: Mru = new Mru('lists') + + constructor(nvim: Neovim, private readonly listMap: Map) { + super(nvim) + + this.addAction('open', async item => { + let { name } = item.data + await this.mru.add(name) + await nvim.command(`CocList ${name}`) + }) + } + + public async loadItems(_context: ListContext): Promise { + let items: UnformattedListItem[] = [] + let mruList = await this.mru.load() + for (let list of this.listMap.values()) { + if (list.name == 'lists') continue + items.push({ + label: [list.name, ...(list.description ? [list.description] : [])], + data: { + name: list.name, + interactive: list.interactive, + score: score(mruList, list.name) + } + }) + } + items.sort((a, b) => b.data.score - a.data.score) + return formatListItems(this.alignColumns, items) + } + + public doHighlight(): void { + 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 + }) + } +} + +function score(list: string[], key: string): number { + let idx = list.indexOf(key) + return idx == -1 ? -1 : list.length - idx +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/location.ts b/vim-config/plugins/coc.nvim/src/list/source/location.ts new file mode 100644 index 00000000..15f52e8a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/location.ts @@ -0,0 +1,85 @@ +import { Neovim } from '@chemzqm/neovim' +import { Location, Range } from 'vscode-languageserver-types' +import path from 'path' +import { ListContext, ListItem, QuickfixItem, AnsiHighlight } from '../../types' +import BasicList from '../basic' +import workspace from '../../workspace' +import { URI } from 'vscode-uri' +import { isParentFolder } from '../../util/fs' +import { CancellationToken } from 'vscode-languageserver-protocol' +import { byteLength } from '../../util/string' +const logger = require('../../util/logger')('list-location') + +export default class LocationList extends BasicList { + public defaultAction = 'open' + public description = 'show locations saved by g:coc_jump_locations variable' + public name = 'location' + + constructor(nvim: Neovim) { + super(nvim) + this.addLocationActions() + } + + public async loadItems(context: ListContext, token: CancellationToken): Promise { + // filename, lnum, col, text, type + let locs = await this.nvim.getVar('coc_jump_locations') as QuickfixItem[] + if (token.isCancellationRequested) return [] + locs = locs || [] + locs.forEach(loc => { + if (!loc.uri) { + let fullpath = path.isAbsolute(loc.filename) ? loc.filename : path.join(context.cwd, loc.filename) + loc.uri = URI.file(fullpath).toString() + } + if (!loc.bufnr && workspace.getDocument(loc.uri) != null) { + loc.bufnr = workspace.getDocument(loc.uri).bufnr + } + if (!loc.range) { + let { lnum, col } = loc + loc.range = 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 = context.buffer.id + let ignoreFilepath = locs.every(o => o.bufnr && bufnr && o.bufnr == bufnr) + let items: ListItem[] = locs.map(loc => { + let filename = ignoreFilepath ? '' : loc.filename + let filterText = `${filename}${loc.text.trim()}` + if (path.isAbsolute(filename)) { + filename = isParentFolder(context.cwd, filename) ? path.relative(context.cwd, filename) : filename + } + let pre = `${filename} |${loc.type ? loc.type + ' ' : ''}${loc.lnum} col ${loc.col}| ` + let highlight: AnsiHighlight + if (loc.range && loc.range.start.line == loc.range.end.line) { + let start = byteLength(pre) + byteLength(loc.text.slice(0, loc.range.start.character)) + let end = byteLength(pre) + byteLength(loc.text.slice(0, loc.range.end.character)) + highlight = { hlGroup: 'Search', span: [start, end] } + } + let label = pre + loc.text + return { + label, + location: Location.create(loc.uri, loc.range), + filterText, + ansiHighlights: highlight ? [highlight] : undefined + } as ListItem + }) + return items + } + + public doHighlight(): void { + 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 + }) + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/outline.ts b/vim-config/plugins/coc.nvim/src/list/source/outline.ts new file mode 100644 index 00000000..0e028088 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/outline.ts @@ -0,0 +1,160 @@ +import path from 'path' +import { DocumentSymbol, Location, Range, SymbolInformation } from 'vscode-languageserver-types' +import { URI } from 'vscode-uri' +import which from 'which' +import languages from '../../languages' +import Document from '../../model/document' +import { ListContext, ListItem, ListArgument } from '../../types' +import { runCommand } from '../../util' +import { writeFile } from '../../util/fs' +import workspace from '../../workspace' +import LocationList from './location' +import { getSymbolKind } from '../../util/convert' +import { CancellationToken } from 'vscode-languageserver-protocol' +import { formatListItems, UnformattedListItem } from '../formatting' +const logger = require('../../util/logger')('list-symbols') + +function getFilterText(s: DocumentSymbol | SymbolInformation, kind: string | null): string { + return `${s.name}${kind ? ` ${kind}` : ''}` +} + +export default class Outline extends LocationList { + public readonly description = 'symbols of current document' + public name = 'outline' + public options: ListArgument[] = [{ + name: '-k, -kind KIND', + hasValue: true, + description: 'filters also by kind', + }] + + public async loadItems(context: ListContext, token: CancellationToken): Promise { + let buf = await context.window.buffer + let document = workspace.getDocument(buf.id) + if (!document) return null + let config = this.getConfig() + let ctagsFilestypes = config.get('ctagsFilestypes', []) + let symbols: DocumentSymbol[] | SymbolInformation[] | null + let args = this.parseArguments(context.args) + if (!ctagsFilestypes.includes(document.filetype)) { + symbols = await languages.getDocumentSymbol(document.textDocument, token) + } + if (token.isCancellationRequested) return [] + if (!symbols) return await this.loadCtagsSymbols(document) + if (symbols.length == 0) return [] + let filterKind = args.kind ? (args.kind as string).toLowerCase() : null + let items: UnformattedListItem[] = [] + let isSymbols = !symbols[0].hasOwnProperty('location') + if (isSymbols) { + // eslint-disable-next-line no-inner-declarations + function addSymbols(symbols: DocumentSymbol[], level = 0): void { + symbols.sort(sortSymbols) + for (let s of symbols) { + let kind = getSymbolKind(s.kind) + let location = Location.create(document.uri, s.selectionRange) + items.push({ + label: [`${'| '.repeat(level)}${s.name}`, `[${kind}]`, `${s.range.start.line + 1}`], + filterText: getFilterText(s, args.kind == '' ? kind : null), + location, + data: { kind } + }) + if (s.children && s.children.length) { + addSymbols(s.children, level + 1) + } + } + } + addSymbols(symbols as DocumentSymbol[]) + if (filterKind) { + items = items.filter(o => o.data.kind.toLowerCase().indexOf(filterKind) == 0) + } + } else { + (symbols as SymbolInformation[]).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 as SymbolInformation[]) { + let kind = getSymbolKind(s.kind) + if (s.name.endsWith(') callback')) continue + if (filterKind && !kind.toLowerCase().startsWith(filterKind)) { + continue + } + if (s.location.uri === undefined) { + s.location.uri = document.uri + } + items.push({ + label: [s.name, `[${kind}]`, `${s.location.range.start.line + 1}`], + filterText: getFilterText(s, args.kind == '' ? kind : null), + location: s.location + }) + } + } + return formatListItems(this.alignColumns, items) + } + + public doHighlight(): void { + let { nvim } = this + nvim.pauseNotification() + nvim.command('syntax match CocOutlineName /\\v\\s?[^\\t]+\\s/ contained containedin=CocOutlineLine', true) + nvim.command('syntax match CocOutlineIndentLine /\\v\\|/ contained containedin=CocOutlineLine,CocOutlineName', 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 CocOutlineIndentLine Comment', true) + nvim.command('highlight default link CocOutlineKind Typedef', true) + nvim.command('highlight default link CocOutlineLine Comment', true) + nvim.resumeNotification(false, true).logError() + } + + public async loadCtagsSymbols(document: Document): Promise { + if (!which.sync('ctags', { nothrow: true })) { + return [] + } + let uri = URI.parse(document.uri) + let extname = path.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 writeFile(escaped, document.getDocumentContent()) + try { + content = await runCommand(`ctags -f - --excmd=number --language-force=${document.filetype} ${escaped}`) + } catch (e) { + // noop + } + if (!content.trim().length) { + content = await runCommand(`ctags -f - --excmd=number ${escaped}`) + } + content = content.trim() + if (!content) return [] + let lines = content.split(/\r?\n/) + let items: ListItem[] = [] + 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: Range = Range.create(lnum - 1, start, lnum - 1, start + parts[0].length) + items.push({ + label: `${parts[0]} [${parts[3]}] ${lnum}`, + filterText: parts[0], + location: Location.create(document.uri, range), + data: { line: lnum } + }) + } + items.sort((a, b) => a.data.line - b.data.line) + return items + } +} + +function sortSymbols(a: DocumentSymbol, b: DocumentSymbol): number { + 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 +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/services.ts b/vim-config/plugins/coc.nvim/src/list/source/services.ts new file mode 100644 index 00000000..49f8f0a5 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/services.ts @@ -0,0 +1,50 @@ +import { Neovim } from '@chemzqm/neovim' +import services from '../../services' +import { ListContext, ListItem } from '../../types' +import BasicList from '../basic' +import { wait } from '../../util' +import { formatListItems } from '../formatting' + +export default class ServicesList extends BasicList { + public defaultAction = 'toggle' + public description = 'registered services of coc.nvim' + public name = 'services' + + constructor(nvim: Neovim) { + super(nvim) + + this.addAction('toggle', async item => { + let { id } = item.data + await services.toggle(id) + await wait(100) + }, { persist: true, reload: true }) + } + + public async loadItems(_context: ListContext): Promise { + let stats = services.getServiceStats() + stats.sort((a, b) => a.id > b.id ? -1 : 1) + return formatListItems(this.alignColumns, stats.map(stat => { + let prefix = stat.state == 'running' ? '*' : ' ' + return { + label: [prefix, stat.id, `[${stat.state}]`, stat.languageIds.join(', ')], + data: { id: stat.id } + } + })) + } + + public doHighlight(): void { + 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 + }) + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/sources.ts b/vim-config/plugins/coc.nvim/src/list/source/sources.ts new file mode 100644 index 00000000..1448c3c5 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/sources.ts @@ -0,0 +1,84 @@ +import { Neovim } from '@chemzqm/neovim' +import { Location, Range } from 'vscode-languageserver-types' +import { URI } from 'vscode-uri' +import sources from '../../sources' +import workspace from '../../workspace' +import { ListContext, ListItem } from '../../types' +import BasicList from '../basic' +const logger = require('../../util/logger')('list-sources') + +export default class SourcesList extends BasicList { + public readonly defaultAction = 'toggle' + public readonly description = 'registered completion sources' + public readonly name = 'sources' + + constructor(nvim: Neovim) { + super(nvim) + + this.addAction('toggle', async item => { + let { name } = item.data + sources.toggleSource(name) + }, { persist: true, reload: true }) + + this.addAction('refresh', async item => { + let { name } = item.data + await sources.refresh(name) + }, { persist: true, reload: true }) + + this.addAction('open', async item => { + let { location } = item + if (location) await this.jumpTo(location) + }) + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async loadItems(context: ListContext): Promise { + let stats = sources.sourceStats() + let filetype = await context.buffer.getOption('filetype') as string + let map = workspace.env.disabledSources + let disables = map ? map[filetype] || [] : [] + 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 ? ' ' : '*' + if (disables && disables.includes(stat.name)) { + prefix = '-' + } + let location: Location + if (stat.filepath) { + location = Location.create(URI.file(stat.filepath).toString(), Range.create(0, 0, 0, 0)) + } + return { + label: `${prefix} ${fixWidth(stat.name, 22)} ${fixWidth('[' + stat.shortcut + ']', 10)} ${fixWidth(stat.triggerCharacters.join(''), 10)} ${fixWidth(stat.priority.toString(), 3)} ${stat.filetypes.join(',')}`, + location, + data: { name: stat.name } + } + }) + } + + public doHighlight(): void { + 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%25v.*%36v/ contained containedin=CocSourcesLine', true) + nvim.command('syntax match CocSourcesPriority /\\v%46v.*%50v/ 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 CocSourcesPriority Number', true) + nvim.command('highlight default link CocSourcesFileTypes Comment', true) + nvim.command('highlight default link CocSourcesType Statement', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } +} + +function fixWidth(str: string, width: number): string { + if (str.length > width) { + return str.slice(0, width - 1) + '.' + } + return str + ' '.repeat(width - str.length) +} diff --git a/vim-config/plugins/coc.nvim/src/list/source/symbols.ts b/vim-config/plugins/coc.nvim/src/list/source/symbols.ts new file mode 100644 index 00000000..6ab2a59c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/source/symbols.ts @@ -0,0 +1,105 @@ +import path from 'path' +import minimatch from 'minimatch' +import { SymbolInformation, SymbolKind } from 'vscode-languageserver-types' +import { URI } from 'vscode-uri' +import languages from '../../languages' +import { ListContext, ListItem } from '../../types' +import workspace from '../../workspace' +import LocationList from './location' +import { getSymbolKind } from '../../util/convert' +import { isParentFolder } from '../../util/fs' +import { score } from '../../util/fzy' +import { CancellationToken, CancellationTokenSource } from 'vscode-languageserver-protocol' +import { formatListItems, UnformattedListItem } from '../formatting' +const logger = require('../../util/logger')('list-symbols') + +export default class Symbols extends LocationList { + public readonly interactive = true + public readonly description = 'search workspace symbols' + public readonly detail = 'Symbols list is provided by server, it works on interactive mode only.' + private cwd: string + public name = 'symbols' + public options = [{ + name: '-k, -kind KIND', + description: 'Filter symbols by kind.', + hasValue: true + }] + + public async loadItems(context: ListContext, token: CancellationToken): Promise { + let { input } = context + this.cwd = context.cwd + let args = this.parseArguments(context.args) + let filterKind = args.kind ? (args.kind as string).toLowerCase() : '' + if (!context.options.interactive) { + throw new Error('Symbols only works on interactive mode') + } + let symbols = await languages.getWorkspaceSymbols(input, token) + if (!symbols) { + throw new Error('No workspace symbols provider registered') + } + let config = this.getConfig() + let excludes = config.get('excludes', []) + let items: UnformattedListItem[] = [] + for (let s of symbols) { + let kind = getSymbolKind(s.kind) + if (filterKind && kind.toLowerCase() != filterKind) { + continue + } + let file = URI.parse(s.location.uri).fsPath + if (isParentFolder(workspace.cwd, file)) { + file = path.relative(workspace.cwd, file) + } + if (excludes.some(p => minimatch(file, p))) { + continue + } + items.push({ + label: [s.name, `[${kind}]`, file], + filterText: `${s.name}`, + location: s.location, + data: { original: s, kind: s.kind, file, score: 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 formatListItems(this.alignColumns, items) + } + + public async resolveItem(item: ListItem): Promise { + let s = item.data.original + if (!s) return null + let tokenSource = new CancellationTokenSource() + let resolved = await languages.resolveWorkspaceSymbol(s, tokenSource.token) + if (!resolved) return null + let kind = getSymbolKind(resolved.kind) + let file = URI.parse(resolved.location.uri).fsPath + if (isParentFolder(this.cwd, file)) { + file = path.relative(this.cwd, file) + } + return { + label: `${s.name} [${kind}]\t${file}`, + filterText: `${s.name}`, + location: s.location + } + } + + public doHighlight(): void { + let { nvim } = this + nvim.pauseNotification() + nvim.command('syntax match CocSymbolsName /\\v^\\s*\\S+/ contained containedin=CocSymbolsLine', true) + nvim.command('syntax match CocSymbolsKind /\\[\\w\\+\\]\\s*\\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 + }) + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/ui.ts b/vim-config/plugins/coc.nvim/src/list/ui.ts new file mode 100644 index 00000000..c6b17b28 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/ui.ts @@ -0,0 +1,429 @@ +import { Buffer, Neovim, Window } from '@chemzqm/neovim' +import debounce from 'debounce' +import { Disposable, Emitter, Event } from 'vscode-languageserver-protocol' +import events from '../events' +import { ListItem, ListItemWithHighlights, ListOptions } from '../types' +import { disposeAll } from '../util' +import workspace from '../workspace' +import ListConfiguration from './configuration' +const logger = require('../util/logger')('list-ui') + +export type MouseEvent = 'mouseDown' | 'mouseDrag' | 'mouseUp' | 'doubleClick' + +export interface MousePosition { + winid: number + lnum: number + col: number + current: boolean +} + +export interface HighlightGroup { + hlGroup: string + priority: number + pos: [number, number, number] +} + +export default class ListUI { + private window: Window + private height: number + private newTab = false + private buffer: Buffer + private currIndex = 0 + private items: ListItemWithHighlights[] = [] + private disposables: Disposable[] = [] + private signOffset: number + private matchHighlightGroup: string + private selected: Set = new Set() + private mouseDown: MousePosition + private _onDidChangeLine = new Emitter() + private _onDidOpen = new Emitter() + private _onDidClose = new Emitter() + private _onDidLineChange = new Emitter() + private _onDoubleClick = new Emitter() + public readonly onDidChangeLine: Event = this._onDidChangeLine.event + public readonly onDidLineChange: Event = this._onDidLineChange.event + public readonly onDidOpen: Event = this._onDidOpen.event + public readonly onDidClose: Event = this._onDidClose.event + public readonly onDidDoubleClick: Event = this._onDoubleClick.event + + constructor( + private nvim: Neovim, + private name: string, + private listOptions: ListOptions, + private config: ListConfiguration + ) { + this.signOffset = config.get('signOffset') + this.matchHighlightGroup = config.get('matchHighlightGroup', 'Search') + this.newTab = listOptions.position == 'tab' + events.on('BufWinLeave', async bufnr => { + if (bufnr != this.bufnr || this.window == null) return + this.window = null + this._onDidClose.fire(bufnr) + }, null, this.disposables) + events.on('CursorMoved', async (bufnr, cursor) => { + if (bufnr != this.bufnr) return + this.onLineChange(cursor[0] - 1) + }, null, this.disposables) + let debounced = debounce(async bufnr => { + if (bufnr != this.bufnr) return + let [winid, start, end] = await nvim.eval('[win_getid(),line("w0"),line("w$")]') as number[] + if (end < 300 || winid != this.winid) return + // increment highlights + nvim.pauseNotification() + this.doHighlight(start - 1, end) + nvim.command('redraw', true) + void nvim.resumeNotification(false, true) + }, 100) + this.disposables.push({ + dispose: () => { + debounced.clear() + } + }) + events.on('CursorMoved', debounced, null, this.disposables) + } + + public get bufnr(): number | undefined { + return this.buffer?.id + } + + public get winid(): number | undefined { + return this.window?.id + } + private get limitLines(): number { + return this.config.get('limitLines', 30000) + } + + private onLineChange(index: number): void { + if (this.currIndex == index) return + this.currIndex = index + this._onDidChangeLine.fire(index) + } + + public set index(n: number) { + if (n < 0 || n >= this.items.length) return + let { nvim } = this + nvim.pauseNotification() + this.setCursor(n + 1, 0) + nvim.command('redraw', true) + void nvim.resumeNotification(false, true) + } + + public get index(): number { + return this.currIndex + } + + public getItem(index: number): ListItem { + return this.items[index] + } + + public get item(): Promise { + let { window } = this + if (!window) return Promise.resolve(null) + return window.cursor.then(cursor => { + this.currIndex = cursor[0] - 1 + return this.items[this.currIndex] + }) + } + + public async echoMessage(item: ListItem): Promise { + 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) + } + + public async updateItem(item: ListItem, index: number): Promise { + if (!this.bufnr) return + let obj: ListItem = Object.assign({ resolved: true }, item) + if (index < this.length) { + this.items[index] = obj + let { nvim } = this + nvim.pauseNotification() + this.buffer.setOption('modifiable', true, true) + nvim.call('setbufline', [this.bufnr, index + 1, obj.label], true) + this.buffer.setOption('modifiable', false, true) + await nvim.resumeNotification() + } + } + + public async getItems(): Promise { + if (this.length == 0 || !this.window) return [] + let mode = await this.nvim.call('mode') + if (mode == 'v' || mode == 'V') { + let [start, end] = await this.getSelectedRange() + let res: ListItem[] = [] + for (let i = start; i <= end; i++) { + let item = this.items[i - 1] + if (item) res.push(item) + } + return res + } + let { selectedItems } = this + if (selectedItems.length) return selectedItems + let item = await this.item + return item == null ? [] : [item] + } + + public async onMouse(event: MouseEvent): Promise { + let { nvim, window } = this + if (!window) return + let [winid, lnum, col] = await nvim.eval(`[v:mouse_winid,v:mouse_lnum,v:mouse_col]`) as [number, number, number] + 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 (current && event == 'mouseDrag') { + if (!this.mouseDown) return + await this.selectLines(this.mouseDown.lnum, lnum) + } else if (current && event == 'mouseUp') { + if (!this.mouseDown) return + if (this.mouseDown.lnum == lnum) { + this.setCursor(lnum, 0) + nvim.command('redraw', true) + } 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) + nvim.command('redraw', true) + void nvim.resumeNotification(false, true) + } + } + + public async resume(): Promise { + let { items, selected, nvim } = this + await this.drawItems(items, this.height, true) + if (!selected.size) return + nvim.pauseNotification() + for (let lnum of selected) { + this.buffer?.placeSign({ lnum, id: this.signOffset + lnum, name: 'CocSelected', group: 'coc-list' }) + } + nvim.command('redraw', true) + void nvim.resumeNotification(false, true) + } + + public async toggleSelection(): Promise { + let { nvim } = this + await nvim.call('win_gotoid', [this.winid]) + let lnum = await nvim.call('line', '.') + let mode = await nvim.call('mode') + if (mode == 'v' || mode == 'V') { + let [start, end] = await this.getSelectedRange() + let reverse = start > end + if (reverse) [start, end] = [end, start] + for (let i = start; i <= end; i++) { + this.toggleLine(i) + } + this.setCursor(end, 0) + nvim.command('redraw', true) + await nvim.resumeNotification() + return + } + nvim.pauseNotification() + this.toggleLine(lnum) + this.setCursor(lnum + 1, 0) + nvim.command('redraw', true) + await nvim.resumeNotification() + } + + private toggleLine(lnum: number): void { + let { selected, buffer, signOffset } = this + let exists = selected.has(lnum) + if (!exists) { + selected.add(lnum) + buffer.placeSign({ lnum, id: signOffset + lnum, name: 'CocSelected', group: 'coc-list' }) + } else { + selected.delete(lnum) + buffer.unplaceSign({ id: signOffset + lnum, group: 'coc-list' }) + } + } + + public async selectLines(start: number, end: number): Promise { + let { nvim, signOffset, buffer, 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) + buffer.placeSign({ lnum: i, id: signOffset + i, name: 'CocSelected', group: 'coc-list' }) + } + this.setCursor(end, 0) + nvim.command('redraw', true) + await nvim.resumeNotification() + } + + public async selectAll(): Promise { + let { length } = this + if (length == 0) return + await this.selectLines(1, length) + } + + public clearSelection(): void { + let { selected, signOffset, buffer } = this + if (selected.size > 0) { + let signIds: number[] = [] + for (let lnum of selected) { + signIds.push(signOffset + lnum) + } + buffer?.unplaceSign({ group: 'coc-list' }) + this.selected.clear() + } + } + + public get ready(): Promise { + if (this.window) return Promise.resolve() + return new Promise(resolve => { + let disposable = this.onDidLineChange(() => { + disposable.dispose() + resolve() + }) + }) + } + + public async drawItems(items: ListItem[], height: number, reload = false): Promise { + const { nvim, name, listOptions } = this + this.items = items.length > this.limitLines ? items.slice(0, this.limitLines) : items + if (!this.window) { + let { position, numberSelect } = listOptions + let [bufnr, winid] = await nvim.call('coc#list#create', [position, height, name, numberSelect]) + this.height = height + this.buffer = nvim.createBuffer(bufnr) + let win = this.window = nvim.createWindow(winid) + let statusSegments = this.config.get('statusLineSegments') + if (statusSegments) win.setOption('statusline', statusSegments.join(" "), true) + this._onDidOpen.fire(this.bufnr) + } + const lines = this.items.map(item => item.label) + let newIndex = reload ? this.currIndex : 0 + this.setLines(lines, false, newIndex) + this._onDidLineChange.fire(this.currIndex + 1) + } + + public appendItems(items: ListItem[]): void { + let curr = this.items.length + if (curr >= this.limitLines) return + let max = this.limitLines - curr + let append = items.slice(0, max) + this.items = this.items.concat(append) + this.setLines(append.map(item => item.label), curr > 0, this.currIndex) + } + + private setLines(lines: string[], append = false, index: number): void { + let { nvim, buffer, window } = this + if (!buffer || !window) return + nvim.pauseNotification() + if (!append) { + nvim.call('coc#compat#clear_matches', [window.id], true) + if (!lines.length) { + lines = ['No results, press ? on normal mode to get help.'] + nvim.call('coc#compat#matchaddpos', ['Comment', [[1]], 99, window.id], true) + } + } + buffer.setOption('modifiable', true, true) + void buffer.setLines(lines, { start: append ? -1 : 0, end: -1, strictIndexing: false }, true) + buffer.setOption('modifiable', false, true) + if (!append && index == 0) { + this.doHighlight(0, 299) + } else { + let height = this.newTab ? workspace.env.lines : this.height + this.doHighlight(Math.max(0, index - height), Math.min(index + height + 1, this.length - 1)) + } + if (!append) { + this.currIndex = index + window.setCursor([index + 1, 0], true) + } + nvim.command('redraws', true) + void nvim.resumeNotification(false, true) + } + + public restoreWindow(): void { + if (this.newTab) return + let { winid, height } = this + if (winid && height) { + this.nvim.call('coc#list#restore', [winid, height], true) + } + } + + public get length(): number { + return this.items.length + } + + public get selectedItems(): ListItem[] { + let { selected, items } = this + let res: ListItem[] = [] + for (let i of selected) { + if (items[i - 1]) res.push(items[i - 1]) + } + return res + } + + private doHighlight(start: number, end: number): void { + let { items } = this + let groups: HighlightGroup[] = [] + for (let i = start; i <= Math.min(end, items.length - 1); i++) { + let { ansiHighlights, highlights } = items[i] + if (ansiHighlights) { + for (let hi of ansiHighlights) { + let { span, hlGroup } = hi + groups.push({ hlGroup, priority: 9, pos: [i + 1, span[0] + 1, span[1] - span[0]] }) + } + } + if (highlights && Array.isArray(highlights.spans)) { + let { spans, hlGroup } = highlights + for (let span of spans) { + groups.push({ hlGroup: hlGroup || this.matchHighlightGroup, priority: 11, pos: [i + 1, span[0] + 1, span[1] - span[0]] }) + } + } + } + this.nvim.call('coc#compat#matchaddgroups', [this.window.id, groups], true) + } + + public setCursor(lnum: number, col: number): void { + let { items } = this + let max = items.length == 0 ? 1 : items.length + if (lnum > max) return + // change index since CursorMoved event not fired (seems bug of neovim)! + this.onLineChange(lnum - 1) + this.window?.setCursor([lnum, col], true) + } + + private async getSelectedRange(): Promise<[number, number]> { + let { nvim } = this + await nvim.call('coc#prompt#stop_prompt', ['list']) + await nvim.eval('feedkeys("\\", "in")') + let [, start] = await nvim.call('getpos', "'<") + let [, end] = await nvim.call('getpos', "'>") + this.nvim.call('coc#prompt#start_prompt', ['list'], true) + return [start, end] + } + + public reset(): void { + if (this.window) { + this.window = null + this.buffer = null + } + } + + public dispose(): void { + disposeAll(this.disposables) + this.nvim.call('coc#window#close', [this.winid || -1], true) + this.window = null + this.buffer = null + this.items = [] + this._onDidChangeLine.dispose() + this._onDidOpen.dispose() + this._onDidClose.dispose() + this._onDidLineChange.dispose() + this._onDoubleClick.dispose() + } +} diff --git a/vim-config/plugins/coc.nvim/src/list/worker.ts b/vim-config/plugins/coc.nvim/src/list/worker.ts new file mode 100644 index 00000000..c378944f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/list/worker.ts @@ -0,0 +1,367 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Emitter, Event } from 'vscode-languageserver-protocol' +import { IList, ListContext, ListHighlights, ListItem, ListItemsEvent, ListItemWithHighlights, ListOptions, ListTask } from '../types' +import { parseAnsiHighlights } from '../util/ansiparse' +import { patchLine } from '../util/diff' +import { hasMatch, positions, score } from '../util/fzy' +import { getMatchResult } from '../util/score' +import { byteIndex, byteLength } from '../util/string' +import window from '../window' +import workspace from '../workspace' +import Prompt from './prompt' +const logger = require('../util/logger')('list-worker') +const controlCode = '\x1b' + +export interface ExtendedItem extends ListItem { + score: number +} + +export interface WorkerConfiguration { + interactiveDebounceTime: number + extendedSearchMode: boolean +} + +// perform loading task +export default class Worker { + private _loading = false + private totalItems: ListItem[] = [] + private tokenSource: CancellationTokenSource + private _onDidChangeItems = new Emitter() + private _onDidChangeLoading = new Emitter() + public readonly onDidChangeItems: Event = this._onDidChangeItems.event + public readonly onDidChangeLoading: Event = this._onDidChangeLoading.event + + constructor( + private nvim: Neovim, + private list: IList, + private prompt: Prompt, + private listOptions: ListOptions, + private config: WorkerConfiguration + ) { + } + + private set loading(loading: boolean) { + if (this._loading == loading) return + this._loading = loading + this._onDidChangeLoading.fire(loading) + } + + public get isLoading(): boolean { + return this._loading + } + + public async loadItems(context: ListContext, reload = false): Promise { + let { list, listOptions } = this + this.loading = true + let { interactive } = listOptions + this.tokenSource = new CancellationTokenSource() + let token = this.tokenSource.token + let items = await list.loadItems(context, token) + if (token.isCancellationRequested) return + if (!items || Array.isArray(items)) { + this.tokenSource = null + items = (items || []) as ListItem[] + this.totalItems = items.map(item => { + item.label = this.fixLabel(item.label) + this.parseListItemAnsi(item) + return item + }) + this.loading = false + let filtered: ListItemWithHighlights[] + if (!interactive) { + filtered = this.filterItems(items) + } else { + filtered = this.convertToHighlightItems(items) + } + this._onDidChangeItems.fire({ + items: filtered, + reload, + finished: true + }) + } else { + let task = items as ListTask + let totalItems = this.totalItems = [] + let count = 0 + let currInput = context.input + let timer: NodeJS.Timer + let lastTs: number + let _onData = (finished?: boolean) => { + lastTs = Date.now() + 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: ListItem[] + if (interactive) { + items = this.convertToHighlightItems(totalItems) + } else { + items = this.filterItems(totalItems) + } + this._onDidChangeItems.fire({ items, reload, append: false, finished }) + } else { + let remain = totalItems.slice(count) + count = totalItems.length + let items: ListItem[] + if (!interactive) { + items = this.filterItems(remain) + } else { + items = this.convertToHighlightItems(remain) + } + this._onDidChangeItems.fire({ items, append: true, finished }) + } + } + task.on('data', 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 ((!lastTs && totalItems.length == 500) + || Date.now() - lastTs > 200) { + _onData() + } else { + timer = setTimeout(() => _onData(), 50) + } + }) + let onEnd = () => { + if (task == null) return + this.tokenSource = null + task = null + this.loading = false + disposable.dispose() + if (timer) clearTimeout(timer) + if (totalItems.length == 0) { + this._onDidChangeItems.fire({ items: [], finished: true }) + } else { + _onData(true) + } + } + let disposable = token.onCancellationRequested(() => { + if (task) { + task.dispose() + onEnd() + } + }) + task.on('error', async (error: Error | string) => { + if (task == null) return + task = null + this.tokenSource = null + this.loading = false + disposable.dispose() + if (timer) clearTimeout(timer) + this.nvim.call('coc#prompt#stop_prompt', ['list'], true) + window.showMessage(`Task error: ${error.toString()}`, 'error') + logger.error(error) + }) + task.on('end', onEnd) + } + } + + /* + * Draw all items with filter if necessary + */ + public drawItems(): void { + let { totalItems } = this + let items: ListItemWithHighlights[] + items = this.filterItems(totalItems) + this._onDidChangeItems.fire({ items, finished: true }) + } + + public stop(): void { + if (this.tokenSource) { + this.tokenSource.cancel() + this.tokenSource = null + } + this.loading = false + } + + public get length(): number { + return this.totalItems.length + } + + private get input(): string { + return this.prompt.input + } + + /** + * Add highlights for interactive list + */ + private convertToHighlightItems(items: ListItem[]): ListItemWithHighlights[] { + let { input } = this + if (!input) return [] + return items.map(item => { + let filterLabel = getFilterLabel(item) + let res = getMatchResult(filterLabel, input) + if (!res?.score) return item + let highlights = this.getHighlights(filterLabel, res.matches) + return Object.assign({}, item, { highlights }) + }) + } + + private filterItems(items: ListItem[]): ListItemWithHighlights[] { + let { input } = this + let { sort, matcher, ignorecase } = this.listOptions + let inputs = this.config.extendedSearchMode ? parseInput(input) : [input] + if (input.length == 0 || inputs.length == 0) return items + if (matcher == 'strict') { + let filtered: ListItemWithHighlights[] = [] + for (let item of items) { + let spans: [number, number][] = [] + let filterLabel = getFilterLabel(item) + let match = true + for (let input of inputs) { + let idx = ignorecase ? filterLabel.toLowerCase().indexOf(input.toLowerCase()) : filterLabel.indexOf(input) + if (idx == -1) { + match = false + break + } + spans.push([byteIndex(filterLabel, idx), byteIndex(filterLabel, idx + byteLength(input))]) + } + if (match) { + filtered.push(Object.assign({}, item, { + highlights: { spans } + })) + } + } + return filtered + } + if (matcher == 'regex') { + let filtered: ListItemWithHighlights[] = [] + let flags = ignorecase ? 'iu' : 'u' + let regexes = inputs.reduce((p, c) => { + try { + let regex = new RegExp(c, flags) + p.push(regex) + } catch (e) {} + return p + }, []) + for (let item of items) { + let spans: [number, number][] = [] + let filterLabel = getFilterLabel(item) + let match = true + for (let regex of regexes) { + let ms = filterLabel.match(regex) + if (ms == null) { + match = false + break + } + spans.push([byteIndex(filterLabel, ms.index), byteIndex(filterLabel, ms.index + byteLength(ms[0]))]) + } + if (match) { + filtered.push(Object.assign({}, item, { + highlights: { spans } + })) + } + } + return filtered + } + let filtered: ExtendedItem[] = [] + let idx = 0 + for (let item of items) { + let filterText = item.filterText || item.label + let matchScore = 0 + let matches: number[] = [] + let filterLabel = getFilterLabel(item) + let match = true + for (let input of inputs) { + if (!hasMatch(input, filterText)) { + match = false + break + } + matches.push(...positions(input, filterLabel)) + if (sort) matchScore += score(input, filterText) + } + if (!match) continue + let obj = Object.assign({}, item, { + sortText: typeof item.sortText === 'string' ? item.sortText : String.fromCharCode(idx), + score: matchScore, + highlights: this.getHighlights(filterLabel, matches) + }) + filtered.push(obj) + idx = idx + 1 + } + if (sort && filtered.length) { + filtered.sort((a, b) => { + if (a.score != b.score) return b.score - a.score + if (a.sortText > b.sortText) return 1 + return -1 + }) + } + return filtered + } + + private getHighlights(text: string, matches?: number[]): ListHighlights { + let spans: [number, number][] = [] + if (matches && 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([byteIndex(text, start), byteIndex(text, curr) + 1]) + start = next + curr = start + next = matches.shift() + } + spans.push([byteIndex(text, start), byteIndex(text, curr) + 1]) + } + return { spans } + } + + // set correct label, add ansi highlights + private parseListItemAnsi(item: ListItem): void { + let { label } = item + if (item.ansiHighlights || !label.includes(controlCode)) return + let { line, highlights } = parseAnsiHighlights(label) + item.label = line + item.ansiHighlights = highlights + } + + private fixLabel(label: string): string { + let { columns } = workspace.env + label = label.split('\n').join(' ') + return label.slice(0, columns * 2) + } + + public dispose(): void { + this.stop() + } +} + +function getFilterLabel(item: ListItem): string { + return item.filterText != null ? patchLine(item.filterText, item.label) : item.label +} + +/** + * `a\ b` => [`a b`] + * `a b` => ['a', 'b'] + */ +export function parseInput(input): string[] { + let res = [] + let startIdx = 0 + let currIdx = 0 + let prev = '' + for (; currIdx < input.length; currIdx++) { + let ch = input[currIdx] + if (ch.charCodeAt(0) === 32) { + // find space + if (prev && prev != '\\' && startIdx != currIdx) { + res.push(input.slice(startIdx, currIdx)) + startIdx = currIdx + 1 + } + } else { + } + prev = ch + } + if (startIdx != input.length) { + res.push(input.slice(startIdx, input.length)) + } + return res.map(s => s.replace(/\\\s/g, ' ').trim()).filter(s => s.length > 0) +} diff --git a/vim-config/plugins/coc.nvim/src/main.ts b/vim-config/plugins/coc.nvim/src/main.ts new file mode 100755 index 00000000..e934cac0 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/main.ts @@ -0,0 +1,26 @@ +require('./util/extensions') + +Object.defineProperty(console, 'log', { + value() { + logger.info(...arguments) + } +}) +const logger = require('./util/logger')('server') +const attach = require('./attach').default + +attach({ reader: process.stdin, writer: process.stdout }) + +process.on('uncaughtException', function(err) { + let msg = 'Uncaught exception: ' + err.message + 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) +}) diff --git a/vim-config/plugins/coc.nvim/src/markdown/index.ts b/vim-config/plugins/coc.nvim/src/markdown/index.ts new file mode 100644 index 00000000..f16602a9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/markdown/index.ts @@ -0,0 +1,199 @@ +import marked from 'marked' +import Renderer from './renderer' +import { parseAnsiHighlights } from '../util/ansiparse' +import { byteLength } from '../util/string' +import stripAnsi from 'strip-ansi' +import { HighlightItem } from '../types' +export const diagnosticFiletypes = ['Error', 'Warning', 'Info', 'Hint'] +const logger = require('../util/logger')('markdown-index') + +export interface Documentation { + filetype: string + content: string + active?: [number, number] +} + +export interface MarkdownParseOptions { + excludeImages?: boolean +} + +export interface CodeBlock { + /** + * Must have filetype or hlgroup + */ + filetype?: string + hlGroup?: string + startLine: number // 0 based + endLine: number +} + +export interface DocumentInfo { + lines: string[] + highlights: HighlightItem[] + codes: CodeBlock[] +} + +export function parseDocuments(docs: Documentation[], opts: MarkdownParseOptions = {}): DocumentInfo { + let lines: string[] = [] + let highlights: HighlightItem[] = [] + let codes: CodeBlock[] = [] + let idx = 0 + for (let doc of docs) { + let currline = lines.length + let { content, filetype } = doc + if (filetype == 'markdown') { + let info = parseMarkdown(content, opts) + codes.push(...info.codes.map(o => { + o.startLine = o.startLine + currline + o.endLine = o.endLine + currline + return o + })) + highlights.push(...info.highlights.map(o => { + o.lnum = o.lnum + currline + return o + })) + lines.push(...info.lines) + } else { + let parts = content.trim().split(/\r?\n/) + if (diagnosticFiletypes.includes(doc.filetype)) { + codes.push({ hlGroup: `Coc${filetype}Float`, startLine: currline, endLine: currline + parts.length }) + } else { + codes.push({ filetype: doc.filetype, startLine: currline, endLine: currline + parts.length }) + } + lines.push(...parts) + } + if (doc.active) { + let arr = getHighlightItems(content, currline, doc.active) + if (arr.length) highlights.push(...arr) + } + if (idx != docs.length - 1) { + lines.push('─') // separate line + } + idx = idx + 1 + } + return { lines, highlights, codes } +} + +/** + * Get 'CocUnderline' highlights from offset range + */ +export function getHighlightItems(content: string, currline: number, active: [number, number]): HighlightItem[] { + let res: HighlightItem[] = [] + let [start, end] = active + let lines = content.split(/\r?\n/) + let used = 0 + let inRange = false + for (let i = 0; i < lines.length; i++) { + let line = lines[i] + if (!inRange) { + if (used + line.length > start) { + inRange = true + let colStart = byteLength(line.slice(0, start - used)) + if (used + line.length > end) { + let colEnd = byteLength(line.slice(0, end - used)) + inRange = false + res.push({ colStart, colEnd, lnum: i + currline, hlGroup: 'CocUnderline' }) + break + } else { + let colEnd = byteLength(line) + res.push({ colStart, colEnd, lnum: i + currline, hlGroup: 'CocUnderline' }) + } + } + } else { + if (used + line.length > end) { + let colEnd = byteLength(line.slice(0, end - used)) + res.push({ colStart: 0, colEnd, lnum: i + currline, hlGroup: 'CocUnderline' }) + inRange = false + break + } else { + let colEnd = byteLength(line) + res.push({ colStart: 0, colEnd, lnum: i + currline, hlGroup: 'CocUnderline' }) + } + } + used = used + line.length + 1 + } + return res +} + +/** + * Parse markdown for lines, highlights & codes + */ +export function parseMarkdown(content: string, opts: MarkdownParseOptions): DocumentInfo { + marked.setOptions({ + renderer: new Renderer(), + gfm: true + }) + let lines: string[] = [] + let highlights: HighlightItem[] = [] + let codes: CodeBlock[] = [] + let currline = 0 + let inCodeBlock = false + let filetype: string + let startLnum = 0 + let parsed = marked(content) + let links = Renderer.getLinks() + if (links.length) { + parsed = parsed + '\n\n' + links.join('\n') + } + parsed = parsed.replace(/\s*$/, '') + let parsedLines = parsed.split(/\n/) + for (let i = 0; i < parsedLines.length; i++) { + let line = parsedLines[i] + if (!line.length) { + let pre = lines[lines.length - 1] + if (pre && pre.length) { + lines.push(line) + currline++ + } + continue + } + if (opts.excludeImages && line.indexOf('![') !== -1) { + line = line.replace(/\s*!\[.*?\]\(.*?\)/g, '') + if (!stripAnsi(line).trim().length) continue + } + if (/\s*```\s*([A-Za-z0-9_,]+)?$/.test(line)) { + if (!inCodeBlock) { + let pre = parsedLines[i - 1] + if (pre && /^\s*```\s*/.test(pre)) { + lines.push('') + currline++ + } + inCodeBlock = true + filetype = line.replace(/^\s*```\s*/, '') + if (filetype == 'js') filetype = 'javascript' + if (filetype == 'ts') filetype = 'typescript' + if (filetype == 'bash') filetype = 'sh' + startLnum = currline + } else { + inCodeBlock = false + codes.push({ + filetype, + startLine: startLnum, + endLine: currline + }) + } + continue + } + if (inCodeBlock) { + // no parse + lines.push(line) + currline++ + continue + } + let res = parseAnsiHighlights(line, true) + if (res.highlights) { + for (let hi of res.highlights) { + let { hlGroup, span } = hi + highlights.push({ + hlGroup, + lnum: currline, + colStart: span[0], + colEnd: span[1] + }) + } + } + lines.push(res.line) + currline++ + } + return { lines, highlights, codes } +} diff --git a/vim-config/plugins/coc.nvim/src/markdown/renderer.ts b/vim-config/plugins/coc.nvim/src/markdown/renderer.ts new file mode 100644 index 00000000..0018c0f3 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/markdown/renderer.ts @@ -0,0 +1,381 @@ +/** + * Renderer for convert markdown to terminal string + */ +import Table from 'cli-table' +import * as styles from './styles' +const logger = require('../util/logger')('markdown-renderer') +let TABLE_CELL_SPLIT = '^*||*^' +let TABLE_ROW_WRAP = '*|*|*|*' +let TABLE_ROW_WRAP_REGEXP = new RegExp(escapeRegExp(TABLE_ROW_WRAP), 'g') +let COLON_REPLACER = '*#COLON|*' +let COLON_REPLACER_REGEXP = new RegExp(escapeRegExp(COLON_REPLACER), 'g') + +let TAB_ALLOWED_CHARACTERS = ['\t'] + +// HARD_RETURN holds a character sequence used to indicate text has a +// hard (no-reflowing) line break. Previously \r and \r\n were turned +// into \n in marked's lexer- preprocessing step. So \r is safe to use +// to indicate a hard (non-reflowed) return. +let HARD_RETURN = '\r' + +let defaultOptions = { + code: identity, + blockquote: identity, + html: styles.gray, + heading: styles.magenta, + firstHeading: styles.magenta, + hr: identity, + listitem: identity, + list, + table: identity, + paragraph: identity, + strong: styles.bold, + em: styles.italic, + codespan: styles.yellow, + del: styles.strikethrough, + link: styles.underline, + href: styles.underline, + text: identity, + unescape: true, + emoji: false, + width: 80, + showSectionPrefix: true, + tab: 2, + tableOptions: {} +} + +function fixHardReturn(text, reflow) { + return reflow ? text.replace(HARD_RETURN, /\n/g) : text +} + +function sanitizeTab(tab, fallbackTab) { + if (typeof tab === 'number') { + return new Array(tab + 1).join(' ') + } else if (typeof tab === 'string' && isAllowedTabString(tab)) { + return tab + } else { + return new Array(fallbackTab + 1).join(' ') + } +} + +function isAllowedTabString(str) { + return TAB_ALLOWED_CHARACTERS.some(function(char) { + return str.match('^(' + char + ')+$') + }) +} + +function indentLines(indent, text) { + return text.replace(/(^|\n)(.+)/g, '$1' + indent + '$2') +} + +function indentify(indent, text) { + if (!text) return text + return indent + text.split('\n').join('\n' + indent) +} + +let BULLET_POINT_REGEX = '\\*' +let NUMBERED_POINT_REGEX = '\\d+\\.' +let POINT_REGEX = + '(?:' + [BULLET_POINT_REGEX, NUMBERED_POINT_REGEX].join('|') + ')' + +// Prevents nested lists from joining their parent list's last line +function fixNestedLists(body, indent) { + let regex = new RegExp( + '' + + '(\\S(?: | )?)' + // Last char of current point, plus one or two spaces + // to allow trailing spaces + '((?:' + + indent + + ')+)' + // Indentation of sub point + '(' + + POINT_REGEX + + '(?:.*)+)$', + 'gm' + ) // Body of subpoint + return body.replace(regex, '$1\n' + indent + '$2$3') +} + +let isPointedLine = function(line, indent) { + return line.match('^(?:' + indent + ')*' + POINT_REGEX) +} + +function toSpaces(str) { + return ' '.repeat(str.length) +} + +let BULLET_POINT = '* ' +function bulletPointLine(indent, line) { + return isPointedLine(line, indent) ? line : toSpaces(BULLET_POINT) + line +} + +function bulletPointLines(lines, indent) { + let transform = bulletPointLine.bind(null, indent) + return lines + .split('\n') + .filter(identity) + .map(transform) + .join('\n') +} + +let numberedPoint = function(n) { + return n + '. ' +} +function numberedLine(indent, line, num) { + return isPointedLine(line, indent) + ? { + num: num + 1, + line: line.replace(BULLET_POINT, numberedPoint(num + 1)) + } + : { + num, + line: toSpaces(numberedPoint(num)) + line + } +} + +function numberedLines(lines, indent) { + let transform = numberedLine.bind(null, indent) + let num = 0 + return lines + .split('\n') + .filter(identity) + .map(line => { + const numbered = transform(line, num) + num = numbered.num + + return numbered.line + }) + .join('\n') +} + +function list(body, ordered, indent) { + body = body.trim() + body = ordered ? numberedLines(body, indent) : bulletPointLines(body, indent) + return body +} + +function section(text) { + return text + '\n\n' +} + +function undoColon(str) { + return str.replace(COLON_REPLACER_REGEXP, ':') +} + +function generateTableRow(text, escape = null) { + if (!text) return [] + escape = escape || identity + let lines = escape(text).split('\n') + + let data = [] + lines.forEach(function(line) { + if (!line) return + let parsed = line + .replace(TABLE_ROW_WRAP_REGEXP, '') + .split(TABLE_CELL_SPLIT) + + data.push(parsed.splice(0, parsed.length - 1)) + }) + return data +} + +function escapeRegExp(str) { + // eslint-disable-next-line no-useless-escape + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&') +} + +function unescapeEntities(html) { + return html + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, "'") +} + +function identity(str) { + return str +} + +const links: Map = new Map() + +class Renderer { + private o: any + private tab: any + private tableSettings: any + // private emoji: any + private unescape: any + private transform: any + constructor(public options: any = {}, public highlightOptions: any = {}) { + this.o = Object.assign({}, defaultOptions, options) + this.tab = sanitizeTab(this.o.tab, defaultOptions.tab) + this.tableSettings = this.o.tableOptions + // this.emoji = identity + this.unescape = this.o.unescape ? unescapeEntities : identity + this.highlightOptions = highlightOptions || {} + this.transform = this.compose(undoColon, this.unescape) + } + + // Compute length of str not including ANSI escape codes. + // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + public textLength(str: string): number { + // eslint-disable-next-line no-control-regex + return str.replace(/\u001b\[(?:\d{1,3})(?:;\d{1,3})*m/g, '').length + } + + public text(t: string): string { + return this.o.text(t) + } + + public code(code: string, lang: string, _escaped: boolean): string { + return '``` ' + lang + '\n' + code + '\n```\n' + } + + public blockquote(quote: string): string { + return section(this.o.blockquote(indentify(this.tab, quote.trim()))) + } + + public html(html: string): string { + return this.o.html(html) + } + + public heading(text: string, level: number, _raw: any): string { + text = this.transform(text) + let prefix = this.o.showSectionPrefix + ? new Array(level + 1).join('#') + ' ' + : '' + text = prefix + text + return section( + level === 1 ? this.o.firstHeading(text) : this.o.heading(text) + ) + } + + public hr(): string { + // NOTE: the '─' character is conveniently translated into a window-wide + // horizontal rule by coc.nvim/autoload/coc/float.vim. Using this character + // causes the horizontal rule to appear like a proper hr separator. In case + // the user isn't benefiting from a floating window, we provide three + // characters so that the hr doesn't deviate too significantly from + // Markdown's normal '-'. + return `───\n` + } + + public list(body, ordered): string { + body = this.o.list(body, ordered, this.tab) + return section(fixNestedLists(indentLines(this.tab, body), this.tab)) + } + + public listitem(text: string): string { + let transform = this.compose(this.o.listitem, this.transform) + let isNested = text.indexOf('\n') !== -1 + if (isNested) text = text.trim() + // Use BULLET_POINT as a marker for ordered or unordered list item + return '\n' + BULLET_POINT + transform(text) + } + + public checkbox(checked): string { + return '[' + (checked ? 'X' : ' ') + '] ' + } + + public paragraph(text: string): string { + let transform = this.compose(this.o.paragraph, this.transform) + text = transform(text) + return section(text) + } + + public table(header, body): string { + let table = new Table( + Object.assign( + {}, + { + head: generateTableRow(header)[0] + }, + this.tableSettings + ) + ) + generateTableRow(body, this.transform).forEach(function(row) { + table.push(row) + }) + return section(this.o.table(table.toString())) + } + + public tablerow(content: string): string { + return TABLE_ROW_WRAP + content + TABLE_ROW_WRAP + '\n' + } + + public tablecell(content, _flags): string { + return content + TABLE_CELL_SPLIT + } + + public strong(text: string): string { + return this.o.strong(text) + } + + public em(text: string): string { + text = fixHardReturn(text, this.o.reflowText) + return this.o.em(text) + } + + public codespan(text: string): string { + text = fixHardReturn(text, this.o.reflowText) + return this.o.codespan(text.replace(/:/g, COLON_REPLACER)) + } + + public br(): string { + return '\n' + } + + public del(text: string): string { + return this.o.del(text) + } + + public link(href, title, text): string { + let prot: string + if (this.options.sanitize) { + try { + prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase() + } catch (e) { + return '' + } + if (prot.startsWith('javascript:')) { + return '' + } + } + if (text && href && text != href) { + links.set(text, href) + } + if (text && text != href) return styles.blue(text) + let out = this.o.href(href) + return this.o.link(out) + } + + public image(href, title, text): string { + if (typeof this.o.image === 'function') { + return this.o.image(href, title, text) + } + let out = '![' + text + if (title) out += ' – ' + title + return out + '](' + href + ')\n' + } + + public compose(...funcs: Function[]): any { + return (...args: any[]) => { + for (let i = funcs.length; i-- > 0;) { + args = [funcs[i].apply(this, args)] + } + return args[0] + } + } + + public static getLinks(): string[] { + let res = [] + for (let [text, href] of links.entries()) { + res.push(`${styles.blue(text)}: ${href}`) + } + links.clear() + return res + } +} + +export default Renderer diff --git a/vim-config/plugins/coc.nvim/src/markdown/styles.ts b/vim-config/plugins/coc.nvim/src/markdown/styles.ts new file mode 100644 index 00000000..2b047d17 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/markdown/styles.ts @@ -0,0 +1,37 @@ +import style from 'ansi-styles' + +export function gray(str: string): string { + return `${style.gray.open}${str}${style.gray.close}` +} + +export function magenta(str: string): string { + return `${style.magenta.open}${str}${style.magenta.close}` +} + +export function bold(str: string): string { + return `${style.bold.open}${str}${style.bold.close}` +} + +export function underline(str: string): string { + return `${style.underline.open}${str}${style.underline.close}` +} + +export function strikethrough(str: string): string { + return `${style.strikethrough.open}${str}${style.strikethrough.close}` +} + +export function italic(str: string): string { + return `${style.italic.open}${str}${style.italic.close}` +} + +export function yellow(str: string): string { + return `${style.yellow.open}${str}${style.yellow.close}` +} + +export function green(str: string): string { + return `${style.green.open}${str}${style.green.close}` +} + +export function blue(str: string): string { + return `${style.blue.open}${str}${style.blue.close}` +} diff --git a/vim-config/plugins/coc.nvim/src/model/bufferSync.ts b/vim-config/plugins/coc.nvim/src/model/bufferSync.ts new file mode 100644 index 00000000..8e2182b3 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/bufferSync.ts @@ -0,0 +1,84 @@ +import { Disposable } from 'vscode-languageserver-protocol' +import { DidChangeTextDocumentParams, IWorkspace } from '../types' +import { disposeAll } from '../util' +import Document from './document' + +export interface SyncItem extends Disposable { + onChange?(e: DidChangeTextDocumentParams): void +} + +/** + * Buffer sync support, document is always attached and not command line buffer. + */ +export default class BufferSync { + private disposables: Disposable[] = [] + private itemsMap: Map = new Map() + constructor(private _create: (doc: Document) => T | undefined, private workspace: IWorkspace) { + let { disposables } = this + for (let doc of workspace.documents) { + this.create(doc) + } + workspace.onDidOpenTextDocument(e => { + let doc = workspace.getDocument(e.bufnr) + if (doc) this.create(doc) + }, null, disposables) + workspace.onDidChangeTextDocument(e => { + this.onChange(e) + }, null, disposables) + workspace.onDidCloseTextDocument(e => { + this.delete(e.bufnr) + }, null, disposables) + } + + public get items(): Iterable { + return Array.from(this.itemsMap.values()).map(x => x.item) + } + + public getItem(bufnr: number | string): T | undefined { + if (typeof bufnr === 'number') { + return this.itemsMap.get(bufnr)?.item + } + let o = Array.from(this.itemsMap.values()).find(v => { + return v.uri == bufnr + }) + return o ? o.item : undefined + } + + private create(doc: Document): void { + if (!doc || doc.isCommandLine || !doc.attached) return + let o = this.itemsMap.get(doc.bufnr) + if (o) o.item.dispose() + let item = this._create(doc) + if (item) this.itemsMap.set(doc.bufnr, { uri: doc.uri, item }) + } + + private onChange(e: DidChangeTextDocumentParams): void { + let o = this.itemsMap.get(e.bufnr) + if (o && typeof o.item.onChange == 'function') { + o.item.onChange(e) + } + } + + private delete(bufnr: number): void { + let o = this.itemsMap.get(bufnr) + if (o) { + this.itemsMap.delete(bufnr) + o.item.dispose() + } + } + + public reset(): void { + for (let o of this.itemsMap.values()) { + o.item.dispose() + } + this.itemsMap.clear() + } + + public dispose(): void { + disposeAll(this.disposables) + for (let o of this.itemsMap.values()) { + o.item.dispose() + } + this.itemsMap.clear() + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/chars.ts b/vim-config/plugins/coc.nvim/src/model/chars.ts new file mode 100644 index 00000000..fe173f64 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/chars.ts @@ -0,0 +1,118 @@ +const logger = require('../util/logger')('model-chars') + +export class Range { + public start: number + public end: number + constructor(start: number, end?: number) { + this.start = start + this.end = end ? end : start + } + + public static fromKeywordOption(keywordOption: string): Range[] { + let parts = keywordOption.split(',') + let ranges: Range[] = [] + 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 + } + + public contains(c: number): boolean { + return c >= this.start && c <= this.end + } +} + +export class Chars { + public ranges: Range[] = [] + constructor(keywordOption?: string) { + if (keywordOption) this.ranges = Range.fromKeywordOption(keywordOption) + } + + public addKeyword(ch: string): void { + let c = ch.charCodeAt(0) + let { ranges } = this + if (!ranges.some(o => o.contains(c))) { + ranges.push(new Range(c)) + } + } + + public clone(): Chars { + let chars = new Chars() + chars.ranges = this.ranges.slice() + return chars + } + + public setKeywordOption(keywordOption: string): void { + this.ranges = Range.fromKeywordOption(keywordOption) + } + + public matchKeywords(content: string, min = 3): string[] { + let length = content.length + if (length == 0) return [] + let res: Set = 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) + } + + public isKeywordCode(code: number): boolean { + if (code > 255) return true + if (code < 33) return false + return this.ranges.some(r => r.contains(code)) + } + + public isKeywordChar(ch: string): boolean { + 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)) + } + + public isKeyword(word: string): boolean { + 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 + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/db.ts b/vim-config/plugins/coc.nvim/src/model/db.ts new file mode 100644 index 00000000..00a1488a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/db.ts @@ -0,0 +1,133 @@ +import fs from 'fs-extra' +import path from 'path' + +export default class DB { + constructor(public readonly filepath: string) { + } + + /** + * Get data by key. + * + * @param {string} key unique key allows dot notation. + * @returns {any} + */ + public fetch(key: string): any { + 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. + */ + public exists(key: string): boolean { + 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. + */ + public delete(key: string): void { + 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.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. + */ + public push(key: string, data: number | null | boolean | string | { [index: string]: any }): void { + let origin = this.load() || {} + let obj = origin + let parts = key.split('.') + let len = parts.length + if (obj == null) { + let dir = path.dirname(this.filepath) + fs.mkdirpSync(dir) + obj = origin + } + for (let i = 0; i < len; i++) { + let key = parts[i] + if (i == len - 1) { + obj[key] = data + fs.writeFileSync(this.filepath, JSON.stringify(origin, null, 2)) + break + } + if (typeof obj[key] == 'undefined') { + obj[key] = {} + obj = obj[key] + } else { + obj = obj[key] + } + } + } + + private load(): any { + let dir = path.dirname(this.filepath) + let stat = fs.statSync(dir) + if (!stat || !stat.isDirectory()) { + fs.mkdirpSync(dir) + fs.writeFileSync(this.filepath, '{}', 'utf8') + return {} + } + try { + let content = fs.readFileSync(this.filepath, 'utf8') + return JSON.parse(content.trim()) + } catch (e) { + fs.writeFileSync(this.filepath, '{}', 'utf8') + return {} + } + } + + /** + * Empty db file. + */ + public clear(): void { + let stat = fs.statSync(this.filepath) + if (!stat || !stat.isFile()) return + fs.writeFileSync(this.filepath, '{}', 'utf8') + } + + /** + * Remove db file. + */ + public destroy(): void { + if (fs.existsSync(this.filepath)) { + fs.unlinkSync(this.filepath) + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/dialog.ts b/vim-config/plugins/coc.nvim/src/model/dialog.ts new file mode 100644 index 00000000..71baa53f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/dialog.ts @@ -0,0 +1,109 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import events from '../events' +import { disposeAll } from '../util' +const logger = require('../util/logger')('model-dialog') + +export interface DialogButton { + /** + * Use by callback, should >= 0 + */ + index: number + text: string + /** + * Not shown when true + */ + disabled?: boolean +} + +export interface DialogPreferences { + maxWidth?: number + maxHeight?: number + floatHighlight?: string + floatBorderHighlight?: string + pickerButtons?: boolean + pickerButtonShortcut?: boolean + confirmKey?: string +} + +export interface DialogConfig { + content: string + /** + * Optional title text. + */ + title?: string + /** + * show close button, default to true when not specified. + */ + close?: boolean + /** + * highlight group for dialog window, default to `"dialog.floatHighlight"` or 'CocFlating' + */ + highlight?: string + /** + * highlight groups for border, default to `"dialog.borderhighlight"` or 'CocFlating' + */ + borderhighlight?: string + /** + * Buttons as bottom of dialog. + */ + buttons?: DialogButton[] + /** + * index is -1 for window close without button click + */ + callback?: (index: number) => void +} + +export default class Dialog { + private disposables: Disposable[] = [] + private bufnr: number + constructor(private nvim: Neovim, private config: DialogConfig) { + events.on('BufWinLeave', bufnr => { + if (bufnr == this.bufnr) { + this.dispose() + if (config.callback) config.callback(-1) + } + }, null, this.disposables) + events.on('FloatBtnClick', (bufnr, idx) => { + if (bufnr == this.bufnr) { + this.dispose() + let btns = config?.buttons.filter(o => o.disabled != true) + if (config.callback) config.callback(btns[idx].index) + } + }, null, this.disposables) + } + + private get lines(): string[] { + return [...this.config.content.split(/\r?\n/)] + } + + public async show(preferences: DialogPreferences): Promise { + let { nvim } = this + let { title, close, buttons } = this.config + let borderhighlight = this.config.borderhighlight || preferences.floatBorderHighlight + let highlight = this.config.highlight || preferences.floatHighlight + let opts: any = { maxwidth: preferences.maxWidth || 80, } + if (title) opts.title = title + if (close || typeof close === 'undefined') opts.close = 1 + if (preferences.maxHeight) opts.maxHeight = preferences.maxHeight + if (preferences.maxWidth) opts.maxWidth = preferences.maxWidth + if (highlight) opts.highlight = highlight + if (borderhighlight) opts.borderhighlight = [borderhighlight] + if (buttons) opts.buttons = buttons.filter(o => !o.disabled).map(o => o.text) + let res = await nvim.call('coc#float#create_dialog', [this.lines, opts]) + if (!res[1]) return + this.bufnr = res[1] + nvim.command('redraw', true) + } + + public get winid(): Promise { + if (!this.bufnr) return Promise.resolve(null) + return this.nvim.call('bufwinid', [this.bufnr]) + } + + public dispose(): void { + this.bufnr = undefined + disposeAll(this.disposables) + this.disposables = [] + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/document.ts b/vim-config/plugins/coc.nvim/src/model/document.ts new file mode 100644 index 00000000..4db78905 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/document.ts @@ -0,0 +1,723 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import debounce from 'debounce' +import { CancellationToken, Disposable, Emitter, Event, Position, Range, TextEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import events from '../events' +import { DidChangeTextDocumentParams, HighlightItem } from '../types' +import { diffLines, getChange } from '../util/diff' +import { disposeAll, getUri, wait, waitNextTick } from '../util/index' +import { equals } from '../util/object' +import { emptyRange } from '../util/position' +import { byteIndex, byteLength, byteSlice } from '../util/string' +import { Chars } from './chars' +import { LinesTextDocument } from './textdocument' +const logger = require('../util/logger')('model-document') + +export type LastChangeType = 'insert' | 'change' | 'delete' + +export interface Env { + readonly filetypeMap: { [index: string]: string } + readonly isVim: boolean + readonly isCygwin: boolean +} + +export interface ChangeInfo { + lnum: number + line: string + changedtick: number +} + +export interface BufferOption { + eol: number + size: number + winid: number + previewwindow: boolean + variables: { [key: string]: any } + bufname: string + fullpath: string + buftype: string + filetype: string + iskeyword: string + changedtick: number + lines: string[] +} + +// getText, positionAt, offsetAt +export default class Document { + public buftype: string + public isIgnored = false + public chars: Chars + public fireContentChanges: Function & { clear(): void } + public fetchContent: Function & { clear(): void } + private size = 0 + private nvim: Neovim + private eol = true + private variables: { [key: string]: any } + // real current lines + private lines: ReadonlyArray = [] + private _attached = false + private _previewwindow = false + private _winid = -1 + private _filetype: string + private _uri: string + private _changedtick: number + private _words: string[] = [] + private _onDocumentChange = new Emitter() + private _onDocumentDetach = new Emitter() + private disposables: Disposable[] = [] + private _textDocument: LinesTextDocument + public readonly onDocumentChange: Event = this._onDocumentChange.event + public readonly onDocumentDetach: Event = this._onDocumentDetach.event + constructor(public readonly buffer: Buffer, private env: Env, private maxFileSize: number | null) { + this.fireContentChanges = debounce(() => { + this._fireContentChanges() + }, 300) + this.fetchContent = debounce(() => { + void this._fetchContent() + }, 100) + } + + /** + * Synchronize content + */ + public get content(): string { + return this.syncLines.join('\n') + (this.eol ? '\n' : '') + } + + public get attached(): boolean { + return this._attached + } + + /** + * Buffer number + */ + public get bufnr(): number { + return this.buffer.id + } + + public get filetype(): string { + return this._filetype + } + + public get uri(): string { + return this._uri + } + /** + * Check if current document should be attached for changes. + * + * Currently only attach for empty and `acwrite` buftype. + */ + public get shouldAttach(): boolean { + let { buftype, maxFileSize } = this + if (!this.getVar('enabled', true)) return false + if (this.uri.endsWith('%5BCommand%20Line%5D')) return true + // too big + if (this.size == -2) return false + if (maxFileSize && this.size > maxFileSize) return false + return buftype == '' || buftype == 'acwrite' + } + + public get isCommandLine(): boolean { + return this.uri && this.uri.endsWith('%5BCommand%20Line%5D') + } + + public get enabled(): boolean { + return this.getVar('enabled', true) + } + + /** + * All words, extracted by `iskeyword` option. + */ + public get words(): string[] { + return this._words + } + + /** + * Map filetype for languageserver. + */ + public convertFiletype(filetype: string): string { + switch (filetype) { + case 'javascript.jsx': + return 'javascriptreact' + case 'typescript.jsx': + case 'typescript.tsx': + return 'typescriptreact' + case 'tex': + // Vim filetype 'tex' means LaTeX, which has LSP language ID 'latex' + return 'latex' + default: { + let map = this.env.filetypeMap + return map[filetype] || filetype + } + } + } + + /** + * Get current buffer changedtick. + */ + public get changedtick(): number { + return this._changedtick + } + + /** + * Scheme of document. + */ + public get schema(): string { + return URI.parse(this.uri).scheme + } + + /** + * Line count of current buffer. + */ + public get lineCount(): number { + return this.lines.length + } + + /** + * Window ID when buffer create, could be -1 when no window associated. + * + * @deprecated could be wrong. + */ + public get winid(): number { + return this._winid + } + + /** + * Returns if current document is opended with previewwindow + * + * @deprecated + */ + public get previewwindow(): boolean { + return this._previewwindow + } + + /** + * Initialize document model. + * + * @internal + */ + public async init(nvim: Neovim, token: CancellationToken): Promise { + this.nvim = nvim + let opts: BufferOption = await nvim.call('coc#util#get_bufoptions', [this.bufnr, this.maxFileSize]) + if (opts == null) return false + let buftype = this.buftype = opts.buftype + this._previewwindow = opts.previewwindow + this._winid = opts.winid + this.size = typeof opts.size == 'number' ? opts.size : 0 + this.variables = opts.variables || {} + this._changedtick = opts.changedtick + this.eol = opts.eol == 1 + this._uri = getUri(opts.fullpath, this.bufnr, buftype, this.env.isCygwin) + if (token.isCancellationRequested) return false + if (this.shouldAttach) { + this.lines = opts.lines + let res = await this.attach() + if (!res) return false + this._attached = true + } + this._filetype = this.convertFiletype(opts.filetype) + this.setIskeyword(opts.iskeyword) + this.createTextDocument(1, this.lines) + if (token.isCancellationRequested) { + this.detach() + return false + } + return true + } + + private async attach(): Promise { + let attached = await this.buffer.attach(true) + if (!attached) return false + let lines = this.lines + this.buffer.listen('lines', (buf: Buffer, tick: number, firstline: number, lastline: number, linedata: string[]) => { + if (buf.id !== this.bufnr || !this._attached || tick == null) return + if (tick > this._changedtick) { + this._changedtick = tick + lines = [...lines.slice(0, firstline), ...linedata, ...lines.slice(lastline)] + this.lines = lines + this.fireContentChanges() + } + }, this.disposables) + this.buffer.listen('detach', async buf => { + lines = [] + this._onDocumentDetach.fire(buf.id) + }, this.disposables) + return true + } + + /** + * Check if document changed after last synchronize + */ + public get dirty(): boolean { + if (this.lines === this.syncLines) return false + return !equals(this.lines, this.syncLines) + } + + private _fireContentChanges(): void { + let { cursor } = events + if (!this.dirty) return + let textDocument = this._textDocument + let endOffset = null + // consider cursor position. + if (cursor && cursor.bufnr == this.bufnr) { + endOffset = this.getEndOffset(cursor.lnum, cursor.col, cursor.insert) + } + let content = this.getDocumentContent() + let change = getChange(textDocument.getText(), content, endOffset) + if (change == null) return + let start = textDocument.positionAt(change.start) + let end = textDocument.positionAt(change.end) + let original = textDocument.getText(Range.create(start, end)) + this.createTextDocument(this.version + 1, this.lines) + let changes = [{ + range: { start, end }, + rangeLength: change.end - change.start, + text: change.newText + }] + this._onDocumentChange.fire({ + bufnr: this.bufnr, + original, + originalLines: textDocument.lines, + textDocument: { version: this.version, uri: this.uri }, + contentChanges: changes + }) + this._words = this.chars.matchKeywords(content) + } + + public async applyEdits(edits: TextEdit[]): Promise { + if (!Array.isArray(arguments[0]) && Array.isArray(arguments[1])) { + edits = arguments[1] + } + if (edits.length == 0) return + let textDocument = TextDocument.create(this.uri, this.filetype, 1, this.getDocumentContent()) + // apply edits to current textDocument + let applied = TextDocument.applyEdits(textDocument, edits) + let content: string + if (this.eol) { + if (applied.endsWith('\r\n')) { + content = applied.slice(0, -2) + } else { + content = applied.endsWith('\n') ? applied.slice(0, -1) : applied + } + } else { + content = applied + } + let lines = this.lines + let newLines = content.split(/\r?\n/) + // could be equal sometimes + if (!equals(lines, newLines)) { + let lnums = edits.map(o => o.range.start.line) + let d = diffLines(lines, newLines, Math.min.apply(null, lnums)) + let original = lines.slice(d.start, d.end) + this.nvim.call('coc#util#set_lines', [this.bufnr, this._changedtick, original, d.replacement, d.start, d.end], true) + if (this.env.isVim) this.nvim.command('redraw', true) + await waitNextTick(() => { + // can't wait vim sync buffer + this.lines = newLines + this._forceSync() + }) + } + } + + public async changeLines(lines: [number, string][]): Promise { + let filtered: [number, string][] = [] + let newLines = this.lines.slice() + for (let [lnum, text] of lines) { + if (newLines[lnum] != text) { + filtered.push([lnum, text]) + newLines[lnum] = text + } + } + if (!filtered.length) return + this.nvim.call('coc#util#change_lines', [this.bufnr, filtered], true) + if (this.env.isVim) this.nvim.command('redraw', true) + this.lines = newLines + this._forceSync() + } + + public _forceSync(): void { + this.fireContentChanges.clear() + this._fireContentChanges() + } + + public forceSync(): void { + // may cause bugs, prevent extensions use it. + if (global.hasOwnProperty('__TEST__')) { + this._forceSync() + } + } + + /** + * Get offset from lnum & col + */ + public getOffset(lnum: number, col: number): number { + return this.textDocument.offsetAt({ + line: lnum - 1, + character: col + }) + } + + /** + * Check string is word. + */ + public isWord(word: string): boolean { + return this.chars.isKeyword(word) + } + + /** + * Generate more words by split word with `-` + */ + public getMoreWords(): string[] { + let res = [] + let { words, chars } = this + if (!chars.isKeywordChar('-')) return res + for (let word of words) { + word = word.replace(/^-+/, '') + if (word.includes('-')) { + let parts = word.split('-') + for (let part of parts) { + if ( + part.length > 2 && + !res.includes(part) && + !words.includes(part) + ) { + res.push(part) + } + } + } + } + return res + } + + /** + * Current word for replacement + */ + public getWordRangeAtPosition(position: Position, extraChars?: string, current = true): Range | null { + 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 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 Range.create(position.line, start, position.line, end) + } + + /** + * Synchronized textDocument. + */ + public get textDocument(): TextDocument { + return this._textDocument + } + + private get syncLines(): ReadonlyArray { + return this._textDocument.lines + } + + public get version(): number { + return this._textDocument.version + } + + private createTextDocument(version: number, lines: ReadonlyArray): void { + let { uri, filetype, eol } = this + this._textDocument = new LinesTextDocument(uri, filetype, version, lines, eol) + } + + /** + * Used by vim for fetch new lines. + */ + private async _fetchContent(sync?: boolean): Promise { + if (!this.env.isVim || !this._attached) return + let { nvim, bufnr, changedtick } = this + let o = await nvim.call('coc#util#get_buf_lines', [bufnr, changedtick]) + if (o) { + this._changedtick = o.changedtick + this.lines = o.lines + if (sync) { + this._forceSync() + } else { + this.fireContentChanges() + } + } + } + + /** + * Get and synchronize change + */ + public async patchChange(currentLine?: boolean): Promise { + if (!this._attached) return + if (this.env.isVim) { + if (currentLine) { + let change = await this.nvim.call('coc#util#get_changeinfo', []) as ChangeInfo + if (change.changedtick < this._changedtick) return + let { lnum, line, changedtick } = change + let newLines = this.lines.slice() + this._changedtick = changedtick + if (newLines[lnum - 1] == line) return + newLines[lnum - 1] = line + this.lines = newLines + this._forceSync() + } else { + this.fetchContent.clear() + await this._fetchContent(true) + } + } else { + // changedtick from buffer events could be not latest. #3003 + this._changedtick = await this.buffer.getVar('changedtick') as number + // we have latest lines aftet TextChange on neovim + this._forceSync() + } + } + + /** + * Get ranges of word in textDocument. + */ + public getSymbolRanges(word: string): Range[] { + let { version, filetype, uri } = this + let textDocument = new LinesTextDocument(uri, filetype, version, this.lines, this.eol) + let res: Range[] = [] + 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(Range.create(textDocument.positionAt(i - str.length), textDocument.positionAt(i))) + } + if (!isKeyword) { + str = '' + } + } + return res + } + + /** + * Adjust col with new valid character before position. + */ + public fixStartcol(position: Position, valids: string[]): number { + let line = this.getline(position.line) + if (!line) return null + let { character } = position + let start = line.slice(0, character) + let col = 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.includes(c)) { + break + } + col = col - byteLength(c) + } + return col + } + + /** + * Add vim highlight items from highlight group and range. + * Synchronized lines are used for calculate cols. + */ + public addHighlights(items: HighlightItem[], hlGroup: string, range: Range): void { + let { start, end } = range + if (emptyRange(range)) return + for (let line = start.line; line <= end.line; line++) { + const text = this.getline(line, false) + let colStart = line == start.line ? byteIndex(text, start.character) : 0 + let colEnd = line == end.line ? byteIndex(text, end.character) : global.Buffer.byteLength(text) + if (colStart >= colEnd) continue + items.push({ hlGroup, lnum: line, colStart, colEnd }) + } + } + + /** + * Real current line + */ + public getline(line: number, current = true): string { + if (current) return this.lines[line] || '' + return this.syncLines[line] || '' + } + + /** + * Get lines, zero indexed, end exclude. + */ + public getLines(start?: number, end?: number): string[] { + return this.lines.slice(start, end) + } + + /** + * Get current content text. + */ + public getDocumentContent(): string { + let content = this.lines.join('\n') + return this.eol ? content + '\n' : content + } + + /** + * Get variable value by key, defined by `b:coc_{key}` + */ + public getVar(key: string, defaultValue?: T): T { + let val = this.variables[`coc_${key}`] + return val === undefined ? defaultValue : val + } + + /** + * Get position from lnum & col + */ + public getPosition(lnum: number, col: number): Position { + let line = this.getline(lnum - 1) + if (!line || col == 0) return { line: lnum - 1, character: 0 } + let pre = byteSlice(line, 0, col - 1) + return { line: lnum - 1, character: pre.length } + } + + /** + * Get end offset from cursor position. + * For normal mode, use offset - 1 when possible + */ + public getEndOffset(lnum: number, col: number, insert: boolean): number { + let total = 0 + let len = this.lines.length + for (let i = lnum - 1; i < len; i++) { + let line = this.lines[i] + let l = line.length + if (i == lnum - 1 && l != 0) { + // current + let buf = global.Buffer.from(line, 'utf8') + let isEnd = buf.byteLength <= col - 1 + if (!isEnd) { + total = total + buf.slice(col - 1, buf.length).toString('utf8').length + if (!insert) total = total - 1 + } + } else { + total = total + l + } + if (!this.eol && i == len - 1) break + total = total + 1 + } + return total + } + + /** + * Recreate document with new filetype. + */ + public setFiletype(filetype: string): void { + this._filetype = this.convertFiletype(filetype) + let lines = this._textDocument.lines + this._textDocument = new LinesTextDocument(this.uri, this.filetype, 1, lines, this.eol) + } + + /** + * Change iskeyword option of document + */ + public setIskeyword(iskeyword: string): void { + let chars = this.chars = new 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 + // TODO not parse words + this._words = this.chars.matchKeywords(lines.join('\n')) + } + + /** + * Detach document. + * + * @internal + */ + public detach(): void { + this._attached = false + disposeAll(this.disposables) + this.disposables = [] + this.fetchContent.clear() + this.fireContentChanges.clear() + this._onDocumentChange.dispose() + this._onDocumentDetach.dispose() + } + + /** + * Synchronize latest document content + */ + public async synchronize(): Promise { + let { changedtick } = this + await this.patchChange() + if (changedtick != this.changedtick) { + await wait(50) + } + } + + /** + * Get localify bonus map. + * + * @internal + */ + public getLocalifyBonus(sp: Position, ep: Position): Map { + let res: Map = 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 = Position.create(sp.line - startLine, sp.character) + ep = Position.create(ep.line - startLine, ep.character) + let doc = 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 + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/download.ts b/vim-config/plugins/coc.nvim/src/model/download.ts new file mode 100644 index 00000000..dba5a04d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/download.ts @@ -0,0 +1,127 @@ +import contentDisposition from 'content-disposition' +import { http, https } from 'follow-redirects' +import fs, { Stats } from 'fs-extra' +import { IncomingMessage } from 'http' +import path from 'path' +import tar from 'tar' +import unzip from 'unzip-stream' +import { v1 as uuidv1 } from 'uuid' +import { CancellationToken } from 'vscode-languageserver-protocol' +import { resolveRequestOptions, FetchOptions } from './fetch' +const logger = require('../util/logger')('model-download') + +export interface DownloadOptions extends Omit { + /** + * Folder that contains downloaded file or extracted files by untar or unzip + */ + dest: string + /** + * Remove the specified number of leading path elements for *untar* only, default to `1`. + */ + strip?: number + /** + * If true, use untar for `.tar.gz` filename + */ + extract?: boolean | 'untar' | 'unzip' + onProgress?: (percent: string) => void +} + +/** + * Download file from url, with optional untar/unzip support. + * + * @param {string} url + * @param {DownloadOptions} options contains dest folder and optional onProgress callback + */ +export default function download(url: string, options: DownloadOptions, token?: CancellationToken): Promise { + let { dest, onProgress, extract } = options + if (!dest || !path.isAbsolute(dest)) { + throw new Error(`Expect absolute file path for dest option.`) + } + let stat: Stats + try { + stat = fs.statSync(dest) + } catch (_e) { + fs.mkdirpSync(dest) + } + if (stat && !stat.isDirectory()) { + throw new Error(`${dest} exists, but not directory!`) + } + let mod = url.startsWith('https') ? https : http + let opts = resolveRequestOptions(url, options) + let extname = path.extname(url) + return new Promise((resolve, reject) => { + if (token) { + let disposable = token.onCancellationRequested(() => { + disposable.dispose() + req.destroy(new Error('request aborted')) + }) + } + const req = mod.request(opts, (res: IncomingMessage) => { + if ((res.statusCode >= 200 && res.statusCode < 300) || res.statusCode === 1223) { + let headers = res.headers || {} + let dispositionHeader = headers['content-disposition'] + if (!extname && dispositionHeader) { + let disposition = contentDisposition.parse(dispositionHeader) + if (disposition.parameters?.filename) { + extname = path.extname(disposition.parameters.filename) + } + } + if (extract === true) { + if (extname === '.zip' || headers['content-type'] == 'application/zip') { + extract = 'unzip' + } else if (extname == '.tgz') { + extract = 'untar' + } else { + reject(new Error(`Unable to extract for ${url}`)) + return + } + } + let total = Number(headers['content-length']) + let cur = 0 + if (!isNaN(total)) { + res.on('data', chunk => { + cur += chunk.length + let percent = (cur / total * 100).toFixed(1) + if (onProgress) { + onProgress(percent) + } else { + logger.info(`Download ${url} progress ${percent}%`) + } + }) + } + res.on('error', err => { + reject(new Error(`Unable to connect ${url}: ${err.message}`)) + }) + res.on('end', () => { + logger.info('Download completed:', url) + }) + let stream: any + if (extract === 'untar') { + stream = res.pipe(tar.x({ strip: options.strip ?? 1, C: dest })) + } else if (extract === 'unzip') { + stream = res.pipe(unzip.Extract({ path: dest })) + } else { + dest = path.join(dest, `${uuidv1()}${extname}`) + stream = res.pipe(fs.createWriteStream(dest)) + } + stream.on('finish', () => { + logger.info(`Downloaded ${url} => ${dest}`) + setTimeout(() => { + resolve(dest) + }, 100) + }) + stream.on('error', reject) + } else { + reject(new Error(`Invalid response from ${url}: ${res.statusCode}`)) + } + }) + req.on('error', reject) + req.on('timeout', () => { + req.destroy(new Error(`request timeout after ${options.timeout}ms`)) + }) + if (options.timeout) { + req.setTimeout(options.timeout) + } + req.end() + }) +} diff --git a/vim-config/plugins/coc.nvim/src/model/fetch.ts b/vim-config/plugins/coc.nvim/src/model/fetch.ts new file mode 100644 index 00000000..b817cbb2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/fetch.ts @@ -0,0 +1,257 @@ +import { http, https } from 'follow-redirects' +import { Readable } from 'stream' +import { parse, UrlWithStringQuery } from 'url' +import fs from 'fs' +import { objectLiteral } from '../util/is' +import workspace from '../workspace' +import { stringify } from 'querystring' +import createHttpProxyAgent, { HttpProxyAgent } from 'http-proxy-agent' +import createHttpsProxyAgent, { HttpsProxyAgent } from 'https-proxy-agent' +import { CancellationToken } from 'vscode-languageserver-protocol' +import decompressResponse from 'decompress-response' +const logger = require('../util/logger')('model-fetch') + +export type ResponseResult = string | Buffer | { [name: string]: any } + +export interface ProxyOptions { + proxyUrl: string + strictSSL?: boolean + proxyAuthorization?: string | null + proxyCA?: string | null +} + +export interface FetchOptions { + /** + * Default to 'GET' + */ + method?: string + /** + * Default no timeout + */ + timeout?: number + /** + * Always return buffer instead of parsed response. + */ + buffer?: boolean + /** + * - 'string' for text response content + * - 'object' for json response content + * - 'buffer' for response not text or json + */ + data?: string | { [key: string]: any } | Buffer + /** + * Plain object added as query of url + */ + query?: { [key: string]: unknown } + headers?: any + /** + * User for http basic auth, should use with password + */ + user?: string + /** + * Password for http basic auth, should use with user + */ + password?: string +} + +function getSystemProxyURI(endpoint: UrlWithStringQuery): string { + let env: string | null + if (endpoint.protocol === 'http:') { + env = process.env.HTTP_PROXY || process.env.http_proxy || null + } else if (endpoint.protocol === 'https:') { + env = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || null + } + let noProxy = process.env.NO_PROXY || process.env.no_proxy + if (noProxy === '*') { + env = null + } else if (noProxy) { + // canonicalize the hostname, so that 'oogle.com' won't match 'google.com' + const hostname = endpoint.hostname.replace(/^\.*/, '.').toLowerCase() + const port = endpoint.port || endpoint.protocol.startsWith('https') ? '443' : '80' + const noProxyList = noProxy.split(',') + for (let i = 0, len = noProxyList.length; i < len; i++) { + let noProxyItem = noProxyList[i].trim().toLowerCase() + // no_proxy can be granular at the port level, which complicates things a bit. + if (noProxyItem.includes(':')) { + let noProxyItemParts = noProxyItem.split(':', 2) + let noProxyHost = noProxyItemParts[0].replace(/^\.*/, '.') + let noProxyPort = noProxyItemParts[1] + if (port === noProxyPort && hostname.endsWith(noProxyHost)) { + env = null + break + } + } else { + noProxyItem = noProxyItem.replace(/^\.*/, '.') + if (hostname.endsWith(noProxyItem)) { + env = null + break + } + } + } + } + return env +} + +export function getAgent(endpoint: UrlWithStringQuery, options: ProxyOptions): HttpsProxyAgent | HttpProxyAgent { + let proxy = options.proxyUrl || getSystemProxyURI(endpoint) + if (proxy) { + const proxyEndpoint = parse(proxy) + if (!/^https?:$/.test(proxyEndpoint.protocol)) { + return null + } + let opts = { + host: proxyEndpoint.hostname, + port: proxyEndpoint.port ? Number(proxyEndpoint.port) : (proxyEndpoint.protocol === 'https' ? '443' : '80'), + auth: proxyEndpoint.auth, + rejectUnauthorized: typeof options.strictSSL === 'boolean' ? options.strictSSL : true + } + logger.info(`Using proxy ${proxy} from ${options.proxyUrl ? 'configuration' : 'system environment'} for ${endpoint.hostname}:`) + return endpoint.protocol === 'http:' ? createHttpProxyAgent(opts) : createHttpsProxyAgent(opts) + } + return null +} + +export function resolveRequestOptions(url: string, options: FetchOptions = {}): any { + let config = workspace.getConfiguration('http') + let { data } = options + let dataType = getDataType(data) + let proxyOptions: ProxyOptions = { + proxyUrl: config.get('proxy', ''), + strictSSL: config.get('proxyStrictSSL', true), + proxyAuthorization: config.get('proxyAuthorization', null), + proxyCA: config.get('proxyCA', null) + } + if (options.query && !url.includes('?')) { + url = `${url}?${stringify(options.query)}` + } + let headers = Object.assign(options.headers || {}, { 'Proxy-Authorization': proxyOptions.proxyAuthorization }) + let endpoint = parse(url) + let agent = getAgent(endpoint, proxyOptions) + let opts: any = { + method: options.method || 'GET', + hostname: endpoint.hostname, + port: endpoint.port ? parseInt(endpoint.port, 10) : (endpoint.protocol === 'https:' ? 443 : 80), + path: endpoint.path, + agent, + rejectUnauthorized: proxyOptions.strictSSL, + maxRedirects: 3, + headers: Object.assign({ + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)', + 'Accept-Encoding': 'gzip, deflate' + }, headers) + } + if (proxyOptions.proxyCA) { + opts.ca = fs.readFileSync(proxyOptions.proxyCA) + } + if (dataType == 'object') { + opts.headers['Content-Type'] = 'application/json' + } else if (dataType == 'string') { + opts.headers['Content-Type'] = 'text/plain' + } + if (options.user && options.password) { + opts.auth = options.user + ':' + options.password + } + if (options.timeout) { + opts.timeout = options.timeout + } + if (options.buffer) opts.buffer = true + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return opts +} + +function request(url: string, data: any, opts: any, token?: CancellationToken): Promise { + let mod = url.startsWith('https:') ? https : http + return new Promise((resolve, reject) => { + if (token) { + let disposable = token.onCancellationRequested(() => { + disposable.dispose() + req.destroy(new Error('request aborted')) + }) + } + const req = mod.request(opts, res => { + let readable: Readable = res + if ((res.statusCode >= 200 && res.statusCode < 300) || res.statusCode === 1223) { + let headers = res.headers || {} + let chunks: Buffer[] = [] + let contentType: string = headers['content-type'] || '' + readable = decompressResponse(res) + readable.on('data', chunk => { + chunks.push(chunk) + }) + readable.on('end', () => { + let buf = Buffer.concat(chunks) + if (!opts.buffer && (contentType.startsWith('application/json') || contentType.startsWith('text/'))) { + let ms = contentType.match(/charset=(\S+)/) + let encoding = ms ? ms[1] : 'utf8' + let rawData = buf.toString(encoding as BufferEncoding) + if (!contentType.includes('application/json')) { + resolve(rawData) + } else { + try { + const parsedData = JSON.parse(rawData) + resolve(parsedData) + } catch (e) { + reject(new Error(`Parse response error: ${e}`)) + } + } + } else { + resolve(buf) + } + }) + readable.on('error', err => { + reject(new Error(`Unable to connect ${url}: ${err.message}`)) + }) + } else { + reject(new Error(`Bad response from ${url}: ${res.statusCode}`)) + } + }) + req.on('error', reject) + req.on('timeout', () => { + req.destroy(new Error(`Request timeout after ${opts.timeout}ms`)) + }) + if (data) { + if (typeof data === 'string' || Buffer.isBuffer(data)) { + req.write(data) + } else { + req.write(JSON.stringify(data)) + } + } + if (opts.timeout) { + req.setTimeout(opts.timeout) + } + req.end() + }) +} + +function getDataType(data: any): string { + if (data === null) return 'null' + if (data === undefined) return 'undefined' + if (typeof data == 'string') return 'string' + if (Buffer.isBuffer(data)) return 'buffer' + if (Array.isArray(data) || objectLiteral(data)) return 'object' + return 'unknown' +} + +/** + * Send request to server for response, supports: + * + * - Send json data and parse json response. + * - Throw error for failed response statusCode. + * - Timeout support (no timeout by default). + * - Send buffer (as data) and receive data (as response). + * - Proxy support from user configuration & environment. + * - Redirect support, limited to 3. + * - Support of gzip & deflate response content. + */ +export default function fetch(url: string, options: FetchOptions = {}, token?: CancellationToken): Promise { + let opts = resolveRequestOptions(url, options) + return request(url, options.data, opts, token).catch(err => { + logger.error(`Fetch error for ${url}:`, opts, err) + if (opts.agent && opts.agent.proxy) { + let { proxy } = opts.agent + throw new Error(`Request failed using proxy ${proxy.host}: ${err.message}`) + } else { + throw err + } + }) +} diff --git a/vim-config/plugins/coc.nvim/src/model/fileSystemWatcher.ts b/vim-config/plugins/coc.nvim/src/model/fileSystemWatcher.ts new file mode 100644 index 00000000..78363132 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/fileSystemWatcher.ts @@ -0,0 +1,98 @@ +import { Disposable, Emitter, Event } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import Watchman, { FileChange } from '../watchman' +import minimatch from 'minimatch' +import path from 'path' +import { disposeAll } from '../util' +import { splitArray } from '../util/array' +const logger = require('../util/logger')('filesystem-watcher') + +export interface RenameEvent { + oldUri: URI + newUri: URI +} + +export default class FileSystemWatcher implements Disposable { + + private _onDidCreate = new Emitter() + private _onDidChange = new Emitter() + private _onDidDelete = new Emitter() + private _onDidRename = new Emitter() + + public readonly onDidCreate: Event = this._onDidCreate.event + public readonly onDidChange: Event = this._onDidChange.event + public readonly onDidDelete: Event = this._onDidDelete.event + public readonly onDidRename: Event = this._onDidRename.event + private disposables: Disposable[] = [] + + constructor( + clientPromise: Promise | null, + private globPattern: string, + public ignoreCreateEvents: boolean, + public ignoreChangeEvents: boolean, + public ignoreDeleteEvents: boolean + ) { + if (!clientPromise) return + clientPromise.then(client => { + if (client) return this.listen(client) + }).catch(error => { + logger.error('watchman initialize failed') + logger.error(error.stack) + }) + } + + private async listen(client: Watchman): Promise { + let { globPattern, + ignoreCreateEvents, + ignoreChangeEvents, + ignoreDeleteEvents } = this + let disposable = await client.subscribe(globPattern, (change: FileChange) => { + let { root, files } = change + files = files.filter(f => f.type == 'f' && minimatch(f.name, globPattern, { dot: true })) + for (let file of files) { + let uri = URI.file(path.join(root, file.name)) + if (!file.exists) { + if (!ignoreDeleteEvents) this._onDidDelete.fire(uri) + } else { + if (file.new === true) { + if (!ignoreCreateEvents) this._onDidCreate.fire(uri) + } else { + if (!ignoreChangeEvents) this._onDidChange.fire(uri) + } + } + } + // file rename + 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: URI.file(path.join(root, oldFile.name)), + newUri: URI.file(path.join(root, newFile.name)) + }) + } + } + // detect folder rename + if (files.length >= 2) { + let [oldFiles, newFiles] = splitArray(files, o => o.exists === false) + if (oldFiles.length == newFiles.length) { + for (let oldFile of oldFiles) { + let newFile = newFiles.find(o => o.size == oldFile.size && o.mtime_ms == oldFile.mtime_ms) + if (newFile) { + this._onDidRename.fire({ + oldUri: URI.file(path.join(root, oldFile.name)), + newUri: URI.file(path.join(root, newFile.name)) + }) + } + } + } + } + }) + this.disposables.push(disposable) + return disposable + } + + public dispose(): void { + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/floatFactory.ts b/vim-config/plugins/coc.nvim/src/model/floatFactory.ts new file mode 100644 index 00000000..bd866ffa --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/floatFactory.ts @@ -0,0 +1,237 @@ +import { Buffer, Neovim, Window } from '@chemzqm/neovim' +import debounce from 'debounce' +import { Disposable } from 'vscode-languageserver-protocol' +import events, { BufEvents } from '../events' +import { Documentation, parseDocuments } from '../markdown' +import { disposeAll } from '../util' +import { Mutex } from '../util/mutex' +import { equals } from '../util/object' +import { FloatConfig } from '../types' +const isVim = process.env.VIM_NODE_RPC == '1' +const logger = require('../util/logger')('model-float') + +export interface WindowConfig { + width: number + height: number + col: number + row: number + relative: 'cursor' | 'win' | 'editor' + style?: string + cursorline?: number + title?: string + border?: number[] + autohide?: number + close?: number +} + +export interface FloatWinConfig { + maxHeight?: number + maxWidth?: number + preferTop?: boolean + autoHide?: boolean + offsetX?: number + title?: string + border?: number[] + cursorline?: boolean + close?: boolean + highlight?: string + borderhighlight?: string + modes?: string[] + shadow?: boolean + winblend?: number + focusable?: boolean + excludeImages?: boolean +} + +/** + * Float window/popup factory for create float/popup around current cursor. + */ +export default class FloatFactory implements Disposable { + private winid = 0 + private _bufnr = 0 + private closeTs: number + private targetBufnr: number + private mutex: Mutex = new Mutex() + private disposables: Disposable[] = [] + private cursor: [number, number] + private onCursorMoved: ((bufnr: number, cursor: [number, number]) => void) & { clear(): void } + constructor(private nvim: Neovim) { + this.onCursorMoved = debounce(this._onCursorMoved.bind(this), 100) + } + + private bindEvents(autoHide: boolean, alignTop: boolean): void { + let eventNames: BufEvents[] = ['InsertLeave', 'InsertEnter', 'BufEnter'] + for (let ev of eventNames) { + events.on(ev, bufnr => { + if (bufnr == this._bufnr) return + this.close() + }, null, this.disposables) + } + events.on('MenuPopupChanged', () => { + // avoid intersect with pum + if (events.pumAlignTop == alignTop) { + this.close() + } + }, null, this.disposables) + this.disposables.push(Disposable.create(() => { + this.onCursorMoved.clear() + })) + events.on('CursorMoved', this.onCursorMoved.bind(this, autoHide), this, this.disposables) + events.on('CursorMovedI', this.onCursorMoved.bind(this, autoHide), this, this.disposables) + } + + public unbind(): void { + if (this.disposables.length) { + disposeAll(this.disposables) + this.disposables = [] + } + } + + public _onCursorMoved(autoHide: boolean, bufnr: number, cursor: [number, number]): void { + if (bufnr == this._bufnr) return + if (bufnr == this.targetBufnr && equals(cursor, this.cursor)) { + // cursor not moved + return + } + if (autoHide || bufnr != this.targetBufnr || !events.insertMode) { + this.close() + return + } + } + + /** + * Create float window/popup at cursor position. + * + * @deprecated use show method instead + */ + public async create(docs: Documentation[], _allowSelection = false, offsetX = 0): Promise { + await this.show(docs, { + offsetX + }) + } + + public applyFloatConfig(conf: FloatWinConfig, opts: FloatConfig): FloatWinConfig { + for (let key of Object.keys(opts)) { + if (key == 'border') { + if (opts.border) conf.border = [1, 1, 1, 1] + continue + } + conf[key] = opts[key] + } + return conf + } + + /** + * Show documentations in float window/popup around cursor. + * Window and buffer are reused when possible. + * Window is closed automatically on change buffer, InsertEnter, CursorMoved and CursorMovedI. + * + * @param docs List of documentations. + * @param config Configuration for floating window/popup. + */ + public async show(docs: Documentation[], config: FloatWinConfig = {}): Promise { + if (docs.length == 0 || docs.every(doc => doc.content.length == 0)) { + this.close() + return + } + let curr = Date.now() + let release = await this.mutex.acquire() + try { + await this.createPopup(docs, config, curr) + release() + } catch (e) { + this.nvim.echoError(e) + release() + } + } + + private async createPopup(docs: Documentation[], opts: FloatWinConfig, timestamp: number): Promise { + docs = docs.filter(o => o.content.trim().length > 0) + let { lines, codes, highlights } = parseDocuments(docs) + let config: any = { + pumAlignTop: events.pumAlignTop, + preferTop: typeof opts.preferTop === 'boolean' ? opts.preferTop : false, + offsetX: opts.offsetX || 0, + title: opts.title || '', + close: opts.close ? 1 : 0, + codes, + highlights, + modes: opts.modes || ['n', 'i', 'ic', 's'] + } + if (!isVim) { + if (typeof opts.winblend === 'number') config.winblend = opts.winblend + if (opts.focusable != null) config.focusable = opts.focusable ? 1 : 0 + if (opts.shadow) config.shadow = 1 + } + if (opts.maxHeight) config.maxHeight = opts.maxHeight + if (opts.maxWidth) config.maxWidth = opts.maxWidth + if (opts.border && !opts.border.every(o => o == 0)) { + config.border = opts.border + } + if (opts.title && !config.border) config.border = [1, 1, 1, 1] + if (opts.highlight) config.highlight = opts.highlight + if (opts.borderhighlight) config.borderhighlight = [opts.borderhighlight] + if (opts.cursorline) config.cursorline = 1 + let autoHide = opts.autoHide == false ? false : true + if (autoHide) config.autohide = 1 + this.unbind() + let arr = await this.nvim.call('coc#float#create_cursor_float', [this.winid, this._bufnr, lines, config]) + this.nvim.redrawVim() + if (!arr || arr.length == 0 || this.closeTs > timestamp) { + let winid = arr && arr.length > 0 ? arr[2] : this.winid + if (winid) { + this.winid = 0 + this.nvim.call('coc#float#close', [winid], true) + this.nvim.redrawVim() + } + return + } + let [targetBufnr, cursor, winid, bufnr, alignTop] = arr as [number, [number, number], number, number, number] + this.winid = winid + this._bufnr = bufnr + this.targetBufnr = targetBufnr + this.cursor = cursor + this.bindEvents(autoHide, alignTop == 1) + } + + /** + * Close float window + */ + public close(): void { + let { winid, nvim } = this + this.closeTs = Date.now() + this.unbind() + if (winid) { + this.winid = 0 + nvim.call('coc#float#close', [winid], true) + nvim.redrawVim() + } + } + + public checkRetrigger(bufnr: number): boolean { + if (this.winid && this.targetBufnr == bufnr) return true + return false + } + + public get bufnr(): number { + return this._bufnr + } + + public get buffer(): Buffer | null { + return this.bufnr ? this.nvim.createBuffer(this.bufnr) : null + } + + public get window(): Window | null { + return this.winid ? this.nvim.createWindow(this.winid) : null + } + + public async activated(): Promise { + if (!this.winid) return false + return await this.nvim.call('coc#float#valid', [this.winid]) != 0 + } + + public dispose(): void { + this.cursor = undefined + this.close() + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/highligher.ts b/vim-config/plugins/coc.nvim/src/model/highligher.ts new file mode 100644 index 00000000..72067641 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/highligher.ts @@ -0,0 +1,108 @@ +import { Buffer } from '@chemzqm/neovim' +import { parseAnsiHighlights } from '../util/ansiparse' +import { byteLength } from '../util/string' +import { HighlightItem } from '../types' + +export interface TextItem { + text: string + hlGroup?: string +} + +/** + * Build highlights, with lines and highlights + */ +export default class Highlighter { + private lines: string[] = [] + private highlights: HighlightItem[] = [] + + public addLine(line: string, hlGroup?: string): void { + if (line.includes('\n')) { + for (let content of line.split(/\r?\n/)) { + this.addLine(content, hlGroup) + } + return + } + if (hlGroup) { + this.highlights.push({ + lnum: this.lines.length, + colStart: line.match(/^\s*/)[0].length, + colEnd: byteLength(line), + hlGroup + }) + } // '\x1b' + if (line.includes('\x1b')) { + let res = parseAnsiHighlights(line) + for (let hl of res.highlights) { + let { span, hlGroup } = hl + if (span[0] != span[1]) { + this.highlights.push({ + lnum: this.lines.length, + colStart: span[0], + colEnd: span[1], + hlGroup + }) + } + } + this.lines.push(res.line) + } else { + this.lines.push(line) + } + } + + public addLines(lines): void { + this.lines.push(...lines) + } + + /** + * Add texts to new Lines + */ + public addTexts(items: TextItem[]): void { + this.addLines('') + for (let item of items) { + this.addText(item.text, item.hlGroup) + } + } + + public addText(text: string, hlGroup?: string): void { + let { lines } = this + let pre = lines[lines.length - 1] || '' + if (hlGroup) { + let colStart = byteLength(pre) + this.highlights.push({ + lnum: lines.length ? lines.length - 1 : 0, + colStart, + colEnd: colStart + byteLength(text), + hlGroup + }) + } + if (lines.length) { + lines[lines.length - 1] = `${pre}${text}` + } else { + lines.push(text) + } + } + + public get length(): number { + return this.lines.length + } + + public getline(line: number): string { + return this.lines[line] || '' + } + + // default to replace + public render(buffer: Buffer, start = 0, end = -1): void { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + buffer.setLines(this.lines, { start, end, strictIndexing: false }, true) + for (let item of this.highlights) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + buffer.addHighlight({ + hlGroup: item.hlGroup, + colStart: item.colStart, + colEnd: item.colEnd == null ? -1 : item.colEnd, + line: start + item.lnum, + srcId: -1 + }) + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/installBuffer.ts b/vim-config/plugins/coc.nvim/src/model/installBuffer.ts new file mode 100644 index 00000000..37c75b75 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/installBuffer.ts @@ -0,0 +1,154 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import { EventEmitter } from 'events' +import { Disposable } from 'vscode-languageserver-protocol' +import { OutputChannel } from '../types' +import { frames } from './status' +const logger = require('../util/logger')('model-installBuffer') + +export enum State { + Waiting, + Faild, + Progressing, + Success, +} + +export default class InstallBuffer extends EventEmitter implements Disposable { + private statMap: Map = new Map() + private messagesMap: Map = new Map() + private names: string[] = [] + // eslint-disable-next-line no-undef + private interval: NodeJS.Timer + public bufnr: number + + constructor( + private isUpdate = false, + private isSync = false, + private channel: OutputChannel | undefined = undefined) { + super() + } + + public setExtensions(names: string[]): void { + this.statMap.clear() + this.names = names + for (let name of names) { + this.statMap.set(name, State.Waiting) + } + } + + public addMessage(name: string, msg: string, isProgress = false): void { + if (isProgress && this.channel) return + let lines = this.messagesMap.get(name) || [] + this.messagesMap.set(name, lines.concat(msg.trim().split(/\r?\n/))) + if (this.channel) this.channel.appendLine(`[${name}] ${msg}`) + } + + public startProgress(names: string[]): void { + for (let name of names) { + this.statMap.set(name, State.Progressing) + } + } + + public finishProgress(name: string, succeed = true): void { + if (this.channel) { + if (succeed) { + this.channel.appendLine(`[${name}] install succeed!`) + } else { + this.channel.appendLine(`[${name}] install failed!`) + } + } + this.statMap.set(name, succeed ? State.Success : State.Faild) + } + + public get remains(): number { + let count = 0 + for (let name of this.names) { + let stat = this.statMap.get(name) + if (![State.Success, State.Faild].includes(stat)) { + count = count + 1 + } + } + return count + } + + private getLines(): string[] { + let lines: string[] = [] + for (let name of this.names) { + let state = this.statMap.get(name) + let processText = '*' + switch (state) { + case State.Progressing: { + let d = new Date() + let idx = Math.floor(d.getMilliseconds() / 100) + processText = frames[idx] + break + } + case State.Faild: + processText = '✗' + break + case State.Success: + processText = '✓' + break + } + let msgs = this.messagesMap.get(name) || [] + lines.push(`- ${processText} ${name} ${msgs.length ? msgs[msgs.length - 1] : ''}`) + } + return lines + } + + public getMessages(line: number): string[] { + if (line <= 1) return [] + let name = this.names[line - 2] + if (!name) return [] + return this.messagesMap.get(name) + } + + // draw frame + private draw(nvim: Neovim, buffer: Buffer): void { + let { remains } = this + let first = remains == 0 ? `${this.isUpdate ? 'Update' : 'Install'} finished` : `Installing, ${remains} remains...` + let lines = [first, '', ...this.getLines()] + // eslint-disable-next-line @typescript-eslint/no-floating-promises + buffer.setLines(lines, { start: 0, end: -1, strictIndexing: false }, true) + if (remains == 0 && this.interval) { + clearInterval(this.interval) + this.interval = null + } + if (process.env.VIM_NODE_RPC) { + nvim.command('redraw', true) + } + } + + public highlight(nvim: Neovim): void { + nvim.call('matchadd', ['CocListFgCyan', '^\\-\\s\\zs\\*'], true) + nvim.call('matchadd', ['CocListFgGreen', '^\\-\\s\\zs✓'], true) + nvim.call('matchadd', ['CocListFgRed', '^\\-\\s\\zs✗'], true) + nvim.call('matchadd', ['CocListFgYellow', '^-.\\{3\\}\\zs\\S\\+'], true) + } + + public async show(nvim: Neovim): Promise { + let { isSync } = this + if (this.channel) return + nvim.pauseNotification() + nvim.command(isSync ? 'enew' : 'vs +enew', true) + nvim.call('bufnr', ['%'], true) + nvim.command('setl buftype=nofile bufhidden=wipe noswapfile nobuflisted wrap undolevels=-1', true) + if (!isSync) { + nvim.command('nnoremap q :q', true) + } + this.highlight(nvim) + let res = await nvim.resumeNotification() + let bufnr = res && res[1] == null ? res[0][1] : null + if (!bufnr) return + this.bufnr = bufnr + let buffer = nvim.createBuffer(bufnr) + this.interval = setInterval(() => { + this.draw(nvim, buffer) + }, 100) + } + + public dispose(): void { + if (this.interval) { + clearInterval(this.interval) + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/installer.ts b/vim-config/plugins/coc.nvim/src/model/installer.ts new file mode 100644 index 00000000..1cc214f2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/installer.ts @@ -0,0 +1,258 @@ +import { EventEmitter } from 'events' +import { spawn } from 'child_process' +import { parse, ParseError } from 'jsonc-parser' +import readline from 'readline' +import fs from 'fs-extra' +import os from 'os' +import path from 'path' +import rc from 'rc' +import semver from 'semver' +import workspace from '../workspace' +import download from './download' +import fetch from './fetch' +import { statAsync } from '../util/fs' +const logger = require('../util/logger')('model-installer') + +export interface Info { + 'dist.tarball'?: string + 'engines.coc'?: string + version?: string + name?: string +} + +function registryUrl(scope = 'coc.nvim'): string { + const result = rc('npm', { registry: 'https://registry.npmjs.org/' }) + const registry = result[`${scope}:registry`] || result.config_registry || result.registry as string + return registry.endsWith('/') ? registry : registry + '/' +} + +export class Installer extends EventEmitter { + private name: string + private url: string + private version: string + constructor( + private root: string, + private npm: string, + // could be url or name@version or name + private def: string + ) { + super() + if (!fs.existsSync(root)) fs.mkdirpSync(root) + if (/^https?:/.test(def)) { + this.url = def + } else { + if (def.startsWith('@')) { + // @author/package + const idx = def.indexOf('@', 1) + if (idx > 1) { + // @author/package@1.0.0 + this.name = def.substring(0, idx) + this.version = def.substring(idx + 1) + } else { + this.name = def + } + } else { + if (def.includes('@')) { + // name@1.0.0 + let [name, version] = def.split('@', 2) + this.name = name + this.version = version + } else { + this.name = def + } + } + } + } + + public get info() { + return { name: this.name, version: this.version } + } + + public async install(): Promise { + this.log(`Using npm from: ${this.npm}`) + let info = await this.getInfo() + logger.info(`Fetched info of ${this.def}`, info) + let { name } = info + let required = info['engines.coc'] ? info['engines.coc'].replace(/^\^/, '>=') : '' + if (required && !semver.satisfies(workspace.version, required)) { + throw new Error(`${name} ${info.version} requires coc.nvim >= ${required}, please update coc.nvim.`) + } + await this.doInstall(info) + return name + } + + public async update(url?: string): Promise { + this.url = url + let folder = path.join(this.root, this.name) + let stat = await fs.lstat(folder) + if (stat.isSymbolicLink()) { + this.log(`Skipped update for symbol link`) + return + } + let version: string + if (fs.existsSync(path.join(folder, 'package.json'))) { + let content = await fs.readFile(path.join(folder, 'package.json'), 'utf8') + version = JSON.parse(content).version + } + this.log(`Using npm from: ${this.npm}`) + let info = await this.getInfo() + if (version && info.version && semver.gte(version, info.version)) { + this.log(`Current version ${version} is up to date.`) + return + } + let required = info['engines.coc'] ? info['engines.coc'].replace(/^\^/, '>=') : '' + if (required && !semver.satisfies(workspace.version, required)) { + throw new Error(`${info.version} requires coc.nvim ${required}, please update coc.nvim.`) + } + await this.doInstall(info) + let jsonFile = path.join(this.root, info.name, 'package.json') + if (fs.existsSync(jsonFile)) { + this.log(`Updated to v${info.version}`) + return path.dirname(jsonFile) + } else { + throw new Error(`Package.json not found: ${jsonFile}`) + } + } + + private async doInstall(info: Info): Promise { + let folder = path.join(this.root, info.name) + if (fs.existsSync(folder)) { + let stat = fs.statSync(folder) + if (!stat.isDirectory()) { + this.log(`${folder} is not directory skipped install`) + return + } + } + let tmpFolder = await fs.mkdtemp(path.join(os.tmpdir(), `${info.name.replace('/', '-')}-`)) + let url = info['dist.tarball'] + this.log(`Downloading from ${url}`) + await download(url, { dest: tmpFolder, onProgress: p => this.log(`Download progress ${p}%`, true), extract: 'untar' }) + this.log(`Extension download at ${tmpFolder}`) + let content = await fs.readFile(path.join(tmpFolder, 'package.json'), 'utf8') + let { dependencies } = JSON.parse(content) + if (dependencies && Object.keys(dependencies).length) { + let p = new Promise((resolve, reject) => { + let args = ['install', '--ignore-scripts', '--no-lockfile', '--production', '--no-global'] + if (url.startsWith('https://github.com')) { + args = ['install'] + } + if ((this.npm.endsWith('npm') || this.npm.endsWith('npm.CMD')) && !this.npm.endsWith('pnpm')) { + args.push('--legacy-peer-deps') + } + if (this.npm.endsWith('yarn')) { + args.push('--ignore-engines') + } + this.log(`Installing dependencies by: ${this.npm} ${args.join(' ')}.`) + const child = spawn(this.npm, args, { + cwd: tmpFolder, + }) + const rl = readline.createInterface({ + input: child.stdout + }) + rl.on('line', line => { + this.log(`[npm] ${line}`, true) + }) + child.stderr.setEncoding('utf8') + child.stdout.setEncoding('utf8') + child.on('error', reject) + let err = '' + child.stderr.on('data', data => { + err += data + }) + child.on('exit', code => { + if (code) { + if (err) this.log(err) + reject(new Error(`${this.npm} install exited with ${code}`)) + return + } + resolve() + }) + }) + await p + } + let jsonFile = path.resolve(this.root, global.hasOwnProperty('__TEST__') ? '' : '..', 'package.json') + let errors: ParseError[] = [] + let obj = parse(fs.readFileSync(jsonFile, 'utf8'), errors, { allowTrailingComma: true }) + if (errors && errors.length > 0) { + throw new Error(`Error on load ${jsonFile}`) + } + obj.dependencies = obj.dependencies || {} + if (this.url) { + obj.dependencies[info.name] = this.url + } else { + obj.dependencies[info.name] = '>=' + info.version + } + const sortedObj = { dependencies: {} } + Object.keys(obj.dependencies).sort().forEach(k => { + sortedObj.dependencies[k] = obj.dependencies[k] + }) + let stat = await statAsync(folder) + if (stat) { + if (stat.isDirectory()) { + fs.removeSync(folder) + } else { + fs.unlinkSync(folder) + } + } + await fs.move(tmpFolder, folder, { overwrite: true }) + await fs.writeFile(jsonFile, JSON.stringify(sortedObj, null, 2), { encoding: 'utf8' }) + this.log(`Update package.json at ${jsonFile}`) + this.log(`Installed extension ${this.name}@${info.version} at ${folder}`) + } + + private async getInfo(): Promise { + if (this.url) return await this.getInfoFromUri() + let registry = registryUrl() + this.log(`Get info from ${registry}`) + let buffer = await fetch(registry + this.name, { timeout: 10000, buffer: true }) + let res = JSON.parse(buffer.toString()) + if (!this.version) this.version = res['dist-tags']['latest'] + let obj = res['versions'][this.version] + if (!obj) throw new Error(`${this.def} doesn't exists in ${registry}.`) + let requiredVersion = obj['engines'] && obj['engines']['coc'] + if (!requiredVersion) { + throw new Error(`${this.def} 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 + } as Info + } + + private async getInfoFromUri(): Promise { + let { url } = this + if (!url.includes('github.com')) { + throw new Error(`"${url}" is not supported, coc.nvim support github.com only`) + } + url = url.replace(/\/$/, '') + let branch = 'master' + if (url.includes('@')) { + // https://github.com/sdras/vue-vscode-snippets@main + let idx = url.indexOf('@') + branch = url.substr(idx + 1) + url = url.substring(0, idx) + } + let fileUrl = url.replace('github.com', 'raw.githubusercontent.com') + `/${branch}/package.json` + this.log(`Get info from ${fileUrl}`) + let content = await fetch(fileUrl, { timeout: 10000 }) + let obj = typeof content == 'string' ? JSON.parse(content) : content + this.name = obj.name + return { + 'dist.tarball': `${url}/archive/${branch}.tar.gz`, + 'engines.coc': obj['engines'] ? obj['engines']['coc'] : null, + name: obj.name, + version: obj.version + } + } + + private log(msg: string, isProgress = false): void { + logger.info(msg) + this.emit('message', msg, isProgress) + } +} + +export function createInstallerFactory(npm: string, root: string): (def: string) => Installer { + return (def): Installer => new Installer(root, npm, def) +} diff --git a/vim-config/plugins/coc.nvim/src/model/memos.ts b/vim-config/plugins/coc.nvim/src/model/memos.ts new file mode 100644 index 00000000..6f72a135 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/memos.ts @@ -0,0 +1,64 @@ +import fs from 'fs' +import { readFile, statAsync } from '../util/fs' +import { deepClone } from '../util/object' +const logger = require('../util/logger')('model-memos') + +/** + * A memento represents a storage utility. It can store and retrieve + * values. + */ +export interface Memento { + get(key: string): T | undefined + get(key: string, defaultValue: T): T + update(key: string, value: any): Promise +} + +export default class Memos { + constructor(private filepath: string) { + if (!fs.existsSync(filepath)) { + fs.writeFileSync(filepath, '{}', 'utf8') + } + } + + private fetchContent(id: string, key: string): any { + try { + let content = fs.readFileSync(this.filepath, 'utf8') + let res = JSON.parse(content) + let obj = res[id] + if (!obj) return undefined + return obj[key] + } catch (e) { + return undefined + } + } + + private async update(id: string, key: string, value: any): Promise { + let { filepath } = this + try { + let content = fs.readFileSync(filepath, 'utf8') + let current = content ? JSON.parse(content) : {} + current[id] = current[id] || {} + if (value !== undefined) { + current[id][key] = deepClone(value) + } else { + delete current[id][key] + } + content = JSON.stringify(current, null, 2) + fs.writeFileSync(filepath, content, 'utf8') + } catch (e) { + logger.error(`Error on update memos:`, e) + } + } + + public createMemento(id: string): Memento { + return { + get: (key: string, defaultValue?: T): T | undefined => { + let res = this.fetchContent(id, key) + return res === undefined ? defaultValue : res + }, + update: async (key: string, value: any): Promise => { + await this.update(id, key, value) + } + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/menu.ts b/vim-config/plugins/coc.nvim/src/model/menu.ts new file mode 100644 index 00000000..b9a53706 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/menu.ts @@ -0,0 +1,181 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import { CancellationToken, Disposable, Emitter, Event } from 'vscode-languageserver-protocol' +import events from '../events' +import { disposeAll } from '../util' +import { DialogPreferences } from './dialog' +import Popup from './popup' +const logger = require('../util/logger')('model-menu') + +export interface MenuConfig { + items: string[] + title?: string +} + +/** + * Select single item from menu at cursor position. + */ +export default class Menu { + private bufnr: number + private win: Popup + private currIndex = 0 + private total: number + private disposables: Disposable[] = [] + private keyMappings: Map void> = new Map() + private readonly _onDidClose = new Emitter() + public readonly onDidClose: Event = this._onDidClose.event + constructor(private nvim: Neovim, private config: MenuConfig, token?: CancellationToken) { + this.total = config.items.length + if (token) { + token.onCancellationRequested(() => { + this.win?.close() + }) + } + this.disposables.push(this._onDidClose) + this.addKeymappings() + } + + private attachEvents(): void { + events.on('InputChar', this.onInputChar.bind(this), null, this.disposables) + events.on('BufWinLeave', bufnr => { + if (bufnr == this.bufnr) { + this._onDidClose.fire(-1) + this.bufnr = undefined + this.win = undefined + this.dispose() + } + }, null, this.disposables) + } + + private addKeymappings(): void { + let { nvim } = this + this.addKeys(['', ''], () => { + this._onDidClose.fire(-1) + this.dispose() + }) + this.addKeys(['\r', ''], () => { + this._onDidClose.fire(this.currIndex) + this.dispose() + }) + let setCursorIndex = idx => { + if (!this.win) return + nvim.pauseNotification() + this.setCursor(idx) + this.win?.refreshScrollbar() + nvim.command('redraw', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + this.addKeys('', async () => { + await this.win?.scrollForward() + }) + this.addKeys('', async () => { + await this.win?.scrollBackward() + }) + this.addKeys(['j', '', '', ''], () => { + // next + let idx = this.currIndex == this.total - 1 ? 0 : this.currIndex + 1 + setCursorIndex(idx) + }) + this.addKeys(['k', '', '', ''], () => { + // previous + let idx = this.currIndex == 0 ? this.total - 1 : this.currIndex - 1 + setCursorIndex(idx) + }) + this.addKeys(['g'], () => { + setCursorIndex(0) + }) + this.addKeys(['G'], () => { + setCursorIndex(this.total - 1) + }) + let timer: NodeJS.Timeout + let firstNumber: number + this.addKeys(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], character => { + if (timer) clearTimeout(timer) + let n = parseInt(character, 10) + if (isNaN(n) || n > this.total) return + if (firstNumber == null && n == 0) return + if (firstNumber) { + let count = firstNumber * 10 + n + firstNumber = undefined + this._onDidClose.fire(count - 1) + this.dispose() + return + } + if (this.total < 10 || n * 10 > this.total) { + this._onDidClose.fire(n - 1) + this.dispose() + return + } + timer = setTimeout(async () => { + this._onDidClose.fire(n - 1) + this.dispose() + }, 200) + firstNumber = n + }) + } + + public async show(preferences: DialogPreferences = {}): Promise { + let { nvim } = this + let { title, items } = this.config + let opts: any = {} + if (title) opts.title = title + if (preferences.maxHeight) opts.maxHeight = preferences.maxHeight + if (preferences.maxWidth) opts.maxWidth = preferences.maxWidth + if (preferences.floatHighlight) opts.highlight = preferences.floatHighlight + if (preferences.floatBorderHighlight) opts.borderhighlight = [preferences.floatBorderHighlight] + let lines = items.map((v, i) => { + if (i < 99) return `${i + 1}. ${v}` + return v + }) + if (preferences.confirmKey && preferences.confirmKey != '') { + this.addKeys(preferences.confirmKey, () => { + this._onDidClose.fire(this.currIndex) + this.dispose() + }) + } + let res = await nvim.call('coc#float#create_menu', [lines, opts]) as [number, number] + this.win = new Popup(nvim, res[0], res[1]) + this.bufnr = res[1] + this.attachEvents() + nvim.call('coc#prompt#start_prompt', ['menu'], true) + return res[0] + } + + public get buffer(): Buffer { + return this.bufnr ? this.nvim.createBuffer(this.bufnr) : undefined + } + + public dispose(): void { + disposeAll(this.disposables) + this.disposables = [] + this.nvim.call('coc#prompt#stop_prompt', ['menu'], true) + this.win?.close() + this.win = undefined + } + + private async onInputChar(session: string, character: string): Promise { + if (session != 'menu' || !this.win) return + let fn = this.keyMappings.get(character) + if (fn) { + await Promise.resolve(fn(character)) + } else { + logger.warn(`Ignored key press: ${character}`) + } + } + + private setCursor(index: number): void { + if (!this.win) return + this.currIndex = index + this.win.setCursor(index) + } + + private addKeys(keys: string | string[], fn: (character: string) => void): void { + if (Array.isArray(keys)) { + for (let key of keys) { + this.keyMappings.set(key, fn) + } + } else { + this.keyMappings.set(keys, fn) + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/mru.ts b/vim-config/plugins/coc.nvim/src/model/mru.ts new file mode 100644 index 00000000..b405bd54 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/mru.ts @@ -0,0 +1,69 @@ +import path from 'path' +import fs from 'fs-extra' + +/** + * Mru - manage string items as lines in mru file. + */ +export default class Mru { + private file: string + + /** + * @param {string} name unique name + * @param {string} base? optional directory name, default to config root of coc.nvim + */ + constructor(private name: string, base?: string) { + this.file = path.join(base || process.env.COC_DATA_HOME, name) + } + + /** + * Load iems from mru file + */ + public async load(): Promise { + let dir = path.dirname(this.file) + try { + fs.mkdirpSync(dir) + if (!fs.existsSync(this.file)) { + fs.writeFileSync(this.file, '', 'utf8') + } + let content = await fs.readFile(this.file, 'utf8') + content = content.trim() + return content.length ? content.trim().split('\n') : [] + } catch (e) { + return [] + } + } + + /** + * Add item to mru file. + */ + public async add(item: string): Promise { + let items = await this.load() + let idx = items.indexOf(item) + if (idx !== -1) items.splice(idx, 1) + items.unshift(item) + fs.writeFileSync(this.file, items.join('\n'), 'utf8') + } + + /** + * Remove item from mru file. + */ + public async remove(item: string): Promise { + let items = await this.load() + let idx = items.indexOf(item) + if (idx !== -1) { + items.splice(idx, 1) + fs.writeFileSync(this.file, items.join('\n'), 'utf8') + } + } + + /** + * Remove the data file. + */ + public async clean(): Promise { + try { + await fs.unlink(this.file) + } catch (e) { + // noop + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/notification.ts b/vim-config/plugins/coc.nvim/src/model/notification.ts new file mode 100644 index 00000000..32331198 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/notification.ts @@ -0,0 +1,111 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import events from '../events' +import { disposeAll } from '../util' +import { DialogButton } from './dialog' +const isVim = process.env.VIM_NODE_RPC == '1' +const logger = require('../util/logger')('model-notification') + +export interface NotificationPreferences { + top: number + right: number + maxWidth: number + maxHeight: number + highlight: string + minProgressWidth: number +} + +export interface NotificationConfig { + content: string + /** + * Optional title text. + */ + title?: string + /** + * Timeout in miliseconds to dismiss notification. + */ + timeout?: number + /** + * show close button, default to true when not specified. + */ + close?: boolean + /** + * highlight groups for border, default to `"dialog.borderhighlight"` or 'CocFlating' + */ + borderhighlight?: string + /** + * Buttons as bottom of dialog. + */ + buttons?: DialogButton[] + /** + * index is -1 for window close without button click + */ + callback?: (index: number) => void +} + +export default class Notification { + protected disposables: Disposable[] = [] + protected bufnr: number + protected _winid: number + protected _disposed = false + constructor(protected nvim: Neovim, protected config: NotificationConfig, attachEvents = true) { + if (attachEvents) { + events.on('BufWinLeave', bufnr => { + if (bufnr == this.bufnr) { + this.dispose() + if (config.callback) config.callback(-1) + } + }, null, this.disposables) + events.on('FloatBtnClick', (bufnr, idx) => { + if (bufnr == this.bufnr) { + this.dispose() + let btns = config?.buttons.filter(o => o.disabled != true) + if (config.callback) config.callback(btns[idx].index) + } + }, null, this.disposables) + } + } + + protected get lines(): string[] { + return this.config.content.split(/\r?\n/) + } + + public async show(preferences: Partial): Promise { + let { nvim } = this + let { title, close, timeout, buttons, borderhighlight } = this.config + let opts: any = Object.assign({}, preferences) + opts.close = close ? 1 : 0 + if (title) opts.title = title + if (borderhighlight) opts.borderhighlight = borderhighlight + if (buttons) opts.buttons = buttons.filter(o => !o.disabled).map(o => o.text) + if (timeout) opts.timeout = timeout + let res = await nvim.call('coc#float#create_notification', [this.lines, opts]) as [number, number] + if (!res) return false + if (this._disposed) { + this.nvim.call('coc#float#close', [res[0]], true) + if (isVim) this.nvim.command('redraw', true) + } else { + this._winid = res[0] + this.bufnr = res[1] + } + return this._winid != undefined + } + + public get winid(): number | undefined { + return this._winid + } + + public dispose(): void { + if (this._disposed) return + this._disposed = true + let { winid } = this + if (winid) { + this.nvim.call('coc#float#close', [winid], true) + if (isVim) this.nvim.command('redraw', true) + } + this.bufnr = undefined + this._winid = undefined + disposeAll(this.disposables) + this.disposables = [] + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/outputChannel.ts b/vim-config/plugins/coc.nvim/src/model/outputChannel.ts new file mode 100644 index 00000000..6ec409c7 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/outputChannel.ts @@ -0,0 +1,94 @@ +import { Neovim } from '@chemzqm/neovim' +import { Disposable } from 'vscode-languageserver-protocol' +import { OutputChannel } from '../types' +import { disposeAll } from '../util' +const logger = require('../util/logger')('outpubChannel') + +export default class BufferChannel implements OutputChannel { + private lines: string[] = [''] + private disposables: Disposable[] = [] + private _disposed = false + public created = false + constructor(public name: string, private nvim: Neovim, private onDispose?: () => void) { + } + + public get content(): string { + return this.lines.join('\n') + } + + private _append(value: string): void { + let { nvim } = this + let idx = this.lines.length - 1 + let newlines = value.split(/\r?\n/) + let lastline = this.lines[idx] + newlines[0] + this.lines[idx] = lastline + let append = newlines.slice(1) + this.lines = this.lines.concat(append) + if (!this.created) return + nvim.pauseNotification() + nvim.call('setbufline', [this.bufname, '$', lastline], true) + if (append.length) { + nvim.call('appendbufline', [this.bufname, '$', append], true) + } + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + + public append(value: string): void { + if (!this.validate()) return + this._append(value) + } + + public appendLine(value: string): void { + if (!this.validate()) return + this._append(value + '\n') + } + + public clear(keep?: number): void { + if (!this.validate()) return + let { nvim } = this + this.lines = keep ? this.lines.slice(-keep) : [] + if (!this.created) return + nvim.pauseNotification() + nvim.call('deletebufline', [this.bufname, 1, '$'], true) + if (this.lines.length) { + nvim.call('appendbufline', [this.bufname, '$', this.lines], true) + } + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + + public hide(): void { + this.created = false + this.nvim.command(`exe 'silent! bd! '.fnameescape('${this.bufname}')`, true) + } + + private get bufname(): string { + return `output:///${this.name}` + } + + public show(preserveFocus?: boolean): void { + let { nvim } = this + nvim.pauseNotification() + nvim.command(`exe 'vsplit '.fnameescape('${this.bufname}')`, true) + if (preserveFocus) { + nvim.command('wincmd p', true) + } + nvim.command('redraw', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + this.created = true + } + + private validate(): boolean { + return !this._disposed + } + + public dispose(): void { + if (this.onDispose) this.onDispose() + this._disposed = true + this.hide() + this.lines = [] + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/picker.ts b/vim-config/plugins/coc.nvim/src/model/picker.ts new file mode 100644 index 00000000..875b8b2d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/picker.ts @@ -0,0 +1,284 @@ +import { Buffer, Neovim } from '@chemzqm/neovim' +import { CancellationToken, Disposable, Emitter, Event } from 'vscode-languageserver-protocol' +import events from '../events' +import { disposeAll } from '../util' +import { byteLength } from '../util/string' +import { DialogPreferences } from './dialog' +import Popup from './popup' +const logger = require('../util/logger')('model-dialog') +const isVim = process.env.VIM_NODE_RPC == '1' + +interface PickerConfig { + title: string + items: QuickPickItem[] +} + +/** + * Represents an item that can be selected from + * a list of items. + */ +export interface QuickPickItem { + + /** + * A human-readable string which is rendered prominent + */ + label: string + + /** + * A human-readable string which is rendered less prominent in the same line + */ + description?: string + + /** + * Optional flag indicating if this item is picked initially. + */ + picked?: boolean +} + +/** + * Pick multiple items from dialog + */ +export default class Picker { + private bufnr: number + private win: Popup | undefined + private picked: Set = new Set() + private currIndex = 0 + private total: number + private disposables: Disposable[] = [] + private keyMappings: Map void> = new Map() + private readonly _onDidClose = new Emitter() + public readonly onDidClose: Event = this._onDidClose.event + constructor(private nvim: Neovim, private config: PickerConfig, token?: CancellationToken) { + for (let i = 0; i < config.items.length; i++) { + let item = config.items[i] + if (item.picked) this.picked.add(i) + } + this.total = config.items.length + if (token) { + token.onCancellationRequested(() => { + this.win?.close() + }) + } + this.disposables.push(this._onDidClose) + this.addKeymappings() + } + + private attachEvents(): void { + events.on('InputChar', this.onInputChar.bind(this), null, this.disposables) + events.on('BufWinLeave', bufnr => { + if (bufnr == this.bufnr) { + this._onDidClose.fire(undefined) + this.bufnr = undefined + this.win = undefined + this.dispose() + } + }, null, this.disposables) + events.on('FloatBtnClick', (bufnr, idx) => { + if (bufnr == this.bufnr) { + if (idx == 0) { + let selected = Array.from(this.picked) + this._onDidClose.fire(selected.length ? selected : undefined) + } else { + this._onDidClose.fire(undefined) + } + this.dispose() + } + }, null, this.disposables) + } + + private addKeymappings(): void { + let { nvim } = this + const toggleSelect = idx => { + if (this.picked.has(idx)) { + this.picked.delete(idx) + } else { + this.picked.add(idx) + } + } + this.addKeys('', async () => { + // not work on vim + if (isVim || !this.win) return + let [winid, lnum, col] = await nvim.eval('[v:mouse_winid,v:mouse_lnum,v:mouse_col]') as [number, number, number] + // can't simulate vvar. + if (global.hasOwnProperty('__TEST__')) { + let res = await nvim.getVar('mouse_position') + winid = res[0] + lnum = res[1] + col = res[2] + } + nvim.pauseNotification() + if (winid == this.win.winid) { + if (col <= 3) { + toggleSelect(lnum - 1) + this.changeLine(lnum - 1) + } else { + this.setCursor(lnum - 1) + } + } + nvim.call('win_gotoid', [winid], true) + nvim.call('cursor', [lnum, col], true) + nvim.call('coc#float#nvim_float_click', [], true) + nvim.command('redraw', true) + await nvim.resumeNotification() + }) + this.addKeys(['', ''], () => { + this._onDidClose.fire(undefined) + this.dispose() + }) + this.addKeys('', () => { + if (this.picked.size == 0) { + this._onDidClose.fire(undefined) + } else { + let selected = Array.from(this.picked) + this._onDidClose.fire(selected) + } + this.dispose() + }) + let setCursorIndex = idx => { + nvim.pauseNotification() + this.setCursor(idx) + this.win.refreshScrollbar() + nvim.command('redraw', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + this.addKeys(['j', '', '', ''], () => { + // next + let idx = this.currIndex == this.total - 1 ? 0 : this.currIndex + 1 + setCursorIndex(idx) + }) + this.addKeys(['k', '', '', ''], () => { + // previous + let idx = this.currIndex == 0 ? this.total - 1 : this.currIndex - 1 + setCursorIndex(idx) + }) + this.addKeys(['g'], () => { + setCursorIndex(0) + }) + this.addKeys(['G'], () => { + setCursorIndex(this.total - 1) + }) + this.addKeys(' ', async () => { + let idx = this.currIndex + toggleSelect(idx) + nvim.pauseNotification() + this.changeLine(idx) + if (this.currIndex != this.total - 1) { + this.setCursor(this.currIndex + 1) + } + nvim.command('redraw', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + await nvim.resumeNotification() + }) + this.addKeys('', async () => { + await this.win?.scrollForward() + }) + this.addKeys('', async () => { + await this.win?.scrollBackward() + }) + } + + public async show(preferences: DialogPreferences = {}): Promise { + let { nvim } = this + let { title, items } = this.config + let opts: any = { close: 1, cursorline: 1 } + if (preferences.maxHeight) opts.maxHeight = preferences.maxHeight + if (preferences.maxWidth) opts.maxWidth = preferences.maxWidth + if (title) opts.title = title + opts.close = 1 + opts.cursorline = 1 + if (preferences.floatHighlight) { + opts.highlight = preferences.floatHighlight + } + if (preferences.floatBorderHighlight) { + opts.borderhighlight = [preferences.floatBorderHighlight] + } + if (preferences.pickerButtons) { + let shortcut = preferences.pickerButtonShortcut + opts.buttons = ['Submit' + (shortcut ? ' ' : ''), 'Cancel' + (shortcut ? ' ' : '')] + } + if (preferences.confirmKey && preferences.confirmKey != '') { + this.addKeys(preferences.confirmKey, () => { + this._onDidClose.fire(undefined) + this.dispose() + }) + } + let lines = [] + let positions: [number, number][] = [] + for (let i = 0; i < items.length; i++) { + let item = items[i] + let line = `[${item.picked ? 'x' : ' '}] ${item.label}` + positions.push([i, byteLength(line)]) + if (item.description) line = line + ` ${item.description}` + lines.push(line) + } + let res = await nvim.call('coc#float#create_dialog', [lines, opts]) as [number, number] + this.win = new Popup(nvim, res[0], res[1]) + this.bufnr = res[1] + this.attachEvents() + let buf = nvim.createBuffer(this.bufnr) + nvim.pauseNotification() + for (let pos of positions) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + buf.addHighlight({ hlGroup: 'Comment', line: pos[0], srcId: 1, colStart: pos[1], colEnd: -1 }) + } + nvim.command('redraw', true) + await nvim.resumeNotification() + nvim.call('coc#prompt#start_prompt', ['picker'], true) + return res[0] + } + + public get buffer(): Buffer { + return this.bufnr ? this.nvim.createBuffer(this.bufnr) : undefined + } + + public dispose(): void { + this.picked.clear() + this.keyMappings.clear() + disposeAll(this.disposables) + this.nvim.call('coc#prompt#stop_prompt', ['picker'], true) + this.win?.close() + this.win = undefined + } + + private async onInputChar(session: string, character: string): Promise { + if (session != 'picker' || !this.win) return + let fn = this.keyMappings.get(character) + if (fn) { + await Promise.resolve(fn(character)) + } else { + logger.warn(`Ignored key press: ${character}`) + } + } + + private changeLine(index: number): void { + let { nvim } = this + let item = this.config.items[index] + if (!item) return + let line = `[${this.picked.has(index) ? 'x' : ' '}] ${item.label}` + let col = byteLength(line) + if (item.description) line = line + ` ${item.description}` + nvim.call('setbufline', [this.bufnr, index + 1, line], true) + if (!isVim) { + let buf = nvim.createBuffer(this.bufnr) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + buf.addHighlight({ hlGroup: 'Comment', line: index, srcId: 1, colStart: col, colEnd: -1 }) + } + } + + private setCursor(index: number): void { + if (!this.win) return + this.currIndex = index + this.win.setCursor(index) + } + + private addKeys(keys: string | string[], fn: (character: string) => void): void { + if (Array.isArray(keys)) { + for (let key of keys) { + this.keyMappings.set(key, fn) + } + } else { + this.keyMappings.set(keys, fn) + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/popup.ts b/vim-config/plugins/coc.nvim/src/model/popup.ts new file mode 100644 index 00000000..2437c566 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/popup.ts @@ -0,0 +1,95 @@ +import { Neovim } from '@chemzqm/neovim' +const isVim = process.env.VIM_NODE_RPC == '1' + +/** + * More methods for float window/popup + */ +export default class Popup { + constructor( + private nvim: Neovim, + public readonly winid, + public readonly bufnr) { + } + + public get valid(): Promise { + return this.nvim.call('coc#float#valid', [this.winid]).then(res => { + return !!res + }) + } + + public close(): void { + this.nvim.call('coc#float#close', [this.winid], true) + } + + public refreshScrollbar(): void { + if (!isVim) this.nvim.call('coc#float#nvim_scrollbar', [this.winid], true) + } + + public execute(cmd: string): void { + this.nvim.call('coc#compat#execute', [this.winid, cmd], true) + } + + /** + * Simple scroll method, not consider wrapped lines. + */ + public async scrollForward(): Promise { + let { nvim, bufnr, winid } = this + let buf = nvim.createBuffer(bufnr) + let total = await buf.length + let botline: number + if (!isVim) { + let infos = await nvim.call('getwininfo', [winid]) + if (!infos || !infos.length) return + botline = infos[0].botline + } else { + botline = await nvim.eval(`get(popup_getpos(${winid}), 'lastline', 0)`) as number + } + if (botline >= total || botline == 0) return + nvim.pauseNotification() + this.setCursor(botline - 1) + this.execute(`silent! noa setl scrolloff=0`) + this.execute(`normal! ${botline}Gzt`) + this.refreshScrollbar() + nvim.command('redraw', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + + /** + * Simple scroll method, not consider wrapped lines. + */ + public async scrollBackward(): Promise { + let { nvim, winid } = this + let topline: number + if (!isVim) { + let infos = await nvim.call('getwininfo', [winid]) + if (!infos || !infos.length) return + topline = infos[0].topline + } else { + topline = await nvim.eval(`get(popup_getpos(${winid}), 'firstline', 0)`) as number + } + if (topline == 1) return + nvim.pauseNotification() + this.setCursor(topline - 1) + this.execute(`normal! ${topline}Gzb`) + this.refreshScrollbar() + nvim.command('redraw', true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } + + /** + * Move cursor and highlight. + */ + public setCursor(index: number): void { + let { nvim, bufnr, winid } = this + if (isVim) { + nvim.call('win_execute', [winid, `exe ${index + 1}`], true) + } else { + let win = nvim.createWindow(winid) + win.notify('nvim_win_set_cursor', [[index + 1, 0]]) + nvim.command(`sign unplace 6 buffer=${bufnr}`, true) + nvim.command(`sign place 6 line=${index + 1} name=CocCurrentLine buffer=${bufnr}`, true) + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/progress.ts b/vim-config/plugins/coc.nvim/src/model/progress.ts new file mode 100644 index 00000000..a29245a3 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/progress.ts @@ -0,0 +1,90 @@ +import { Neovim } from '@chemzqm/neovim' +import Notification, { NotificationPreferences } from './notification' +import { CancellationToken, CancellationTokenSource } from 'vscode-languageserver-protocol' +import events from '../events' + +export interface ProgressOptions { + title?: string + cancellable?: boolean + task: (progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken) => Thenable +} + +/** + * Defines a generalized way of reporting progress updates. + */ +export interface Progress { + + /** + * Report a progress update. + * + * @param value A progress item, like a message and/or an + * report on how much work finished + */ + report(value: T): void +} + +export default class ProgressNotification extends Notification { + private tokenSource: CancellationTokenSource + constructor(nvim: Neovim, private option: ProgressOptions) { + super(nvim, { + content: '\n', + close: option.cancellable == true, + title: option.title + }, false) + events.on('BufWinLeave', bufnr => { + if (bufnr == this.bufnr) { + if (this.tokenSource) { + this.tokenSource.cancel() + } + this.dispose() + } + }, null, this.disposables) + } + + public async show(preferences: Partial): Promise { + let { task } = this.option + let tokenSource = this.tokenSource = new CancellationTokenSource() + this.disposables.push(tokenSource) + let total = 0 + let res = await new Promise((resolve, reject) => { + tokenSource.token.onCancellationRequested(() => { + resolve(undefined) + }) + super.show(Object.assign({ minWidth: preferences.minProgressWidth || 30, progress: 1 }, preferences)).then(shown => { + if (!shown) reject(new Error('Failed to create float window')) + }).catch(reject) + task({ + report: p => { + if (!this.bufnr) return + let text = '' + if (p.message) text += p.message.replace(/\r?\n/g, ' ') + if (p.increment) { + total += p.increment + text = text + (text.length ? ` ${total}%` : `${total}%`) + } + this.nvim.call('setbufline', [this.bufnr, 2, text], true) + } + }, tokenSource.token).then(res => { + if (this._disposed) return + setTimeout(() => { + this.dispose() + }, 100) + resolve(res) + }, err => { + if (this._disposed) return + this.dispose() + if (err instanceof Error) { + reject(err) + } else { + resolve(undefined) + } + }) + }) + return res + } + + public dispose(): void { + super.dispose() + this.tokenSource = undefined + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/resolver.ts b/vim-config/plugins/coc.nvim/src/model/resolver.ts new file mode 100644 index 00000000..8b09007e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/resolver.ts @@ -0,0 +1,42 @@ +import path from 'path' +import fs from 'fs' +import { executable, runCommand } from '../util' +import { statAsync } from '../util/fs' +import { memorize } from '../util/decorator' +import stripAnsi from 'strip-ansi' +const logger = require('../util/logger')('model-resolver') + +export default class Resolver { + + @memorize + private get nodeFolder(): Promise { + if (!executable('npm')) return Promise.resolve('') + return runCommand('npm --loglevel silent root -g', {}, 3000).then(root => { + return stripAnsi(root).trim() + }) + } + + @memorize + private get yarnFolder(): Promise { + if (!executable('yarnpkg')) return Promise.resolve('') + return runCommand('yarnpkg global dir', {}, 3000).then(root => { + let folder = path.join(stripAnsi(root).trim(), 'node_modules') + let exists = fs.existsSync(folder) + return exists ? folder : '' + }) + } + + public async resolveModule(mod: string): Promise { + let nodeFolder = await this.nodeFolder + let yarnFolder = await this.yarnFolder + if (yarnFolder) { + let s = await statAsync(path.join(yarnFolder, mod, 'package.json')) + if (s && s.isFile()) return path.join(yarnFolder, mod) + } + if (nodeFolder) { + let s = await statAsync(path.join(nodeFolder, mod, 'package.json')) + if (s && s.isFile()) return path.join(nodeFolder, mod) + } + return null + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/status.ts b/vim-config/plugins/coc.nvim/src/model/status.ts new file mode 100644 index 00000000..86533416 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/status.ts @@ -0,0 +1,91 @@ +import { Disposable } from 'vscode-languageserver-protocol' +import { NeovimClient as Neovim } from '@chemzqm/neovim' +import { v1 as uuidv1 } from 'uuid' +const logger = require('../util/logger')('model-status') + +export const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] + +export interface StatusBarItem { + /** + * The priority of this item. Higher value means the item should + * be shown more to the left. + */ + readonly priority: number + isProgress: boolean + text: string + show(): void + hide(): void + dispose(): void +} + +export default class StatusLine implements Disposable { + private items: Map = new Map() + private shownIds: Set = new Set() + private _text = '' + private interval: NodeJS.Timer + constructor(private nvim: Neovim) { + this.interval = setInterval(() => { + this.setStatusText().logError() + }, 100) + } + + public dispose(): void { + clearInterval(this.interval) + } + + public createStatusBarItem(priority = 0, isProgress = false): StatusBarItem { + let uid = uuidv1() + + let item: StatusBarItem = { + 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 + } + + private getText(): string { + if (this.shownIds.size == 0) return '' + let d = new Date() + let idx = Math.floor(d.getMilliseconds() / 100) + let text = '' + let items: StatusBarItem[] = [] + 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 + } + + private async setStatusText(): Promise { + 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.call('coc#util#do_autocmd', ['CocStatusChange'], true) + await nvim.resumeNotification(false, true) + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/task.ts b/vim-config/plugins/coc.nvim/src/model/task.ts new file mode 100644 index 00000000..15439187 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/task.ts @@ -0,0 +1,97 @@ +import { Neovim } from '@chemzqm/neovim' +import events from '../events' +import { Disposable, Emitter, Event } from 'vscode-languageserver-protocol' +import { disposeAll } from '../util' + +export interface TaskOptions { + cmd: string + args?: string[] + cwd?: string + pty?: boolean + env?: { [key: string]: string } + detach?: boolean +} + +/** + * Controls long running task started by vim. + * Useful to keep the task running after CocRestart. + * + * @public + */ +export default class Task implements Disposable { + private disposables: Disposable[] = [] + private readonly _onExit = new Emitter() + private readonly _onStderr = new Emitter() + private readonly _onStdout = new Emitter() + public readonly onExit: Event = this._onExit.event + public readonly onStdout: Event = this._onStdout.event + public readonly onStderr: Event = this._onStderr.event + + /** + * @param {Neovim} nvim + * @param {string} id unique id + */ + constructor(private nvim: Neovim, private id: string) { + events.on('TaskExit', (id, code) => { + if (id == this.id) { + this._onExit.fire(code) + } + }, null, this.disposables) + events.on('TaskStderr', (id, lines) => { + if (id == this.id) { + this._onStderr.fire(lines) + } + }, null, this.disposables) + let stdout: string[] = [] + let timer: NodeJS.Timeout + events.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} + */ + public async start(opts: TaskOptions): Promise { + let { nvim } = this + return await nvim.call('coc#task#start', [this.id, opts]) + } + + /** + * Stop task by SIGTERM or SIGKILL + */ + public async stop(): Promise { + let { nvim } = this + await nvim.call('coc#task#stop', [this.id]) + } + + /** + * Check if the task is running. + */ + public get running(): Promise { + let { nvim } = this + return nvim.call('coc#task#running', [this.id]) + } + + /** + * Stop task and dispose all events. + */ + public dispose(): void { + let { nvim } = this + nvim.call('coc#task#stop', [this.id], true) + this._onStdout.dispose() + this._onStderr.dispose() + this._onExit.dispose() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/terminal.ts b/vim-config/plugins/coc.nvim/src/model/terminal.ts new file mode 100644 index 00000000..7184a210 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/terminal.ts @@ -0,0 +1,106 @@ +import { Neovim } from '@chemzqm/neovim' +const logger = require('../util/logger')('model-terminal') + +export interface TerminalOptions { + /** + * A human-readable string which will be used to represent the terminal in the UI. + */ + name?: string + + /** + * A path to a custom shell executable to be used in the terminal. + */ + shellPath?: string + + /** + * Args for the custom shell executable, this does not work on Windows (see #8429) + */ + shellArgs?: string[] + + /** + * A path or URI for the current working directory to be used for the terminal. + */ + cwd?: string + + /** + * Object with environment variables that will be added to the VS Code process. + */ + env?: { [key: string]: string | null } + + /** + * Whether the terminal process environment should be exactly as provided in + * `TerminalOptions.env`. When this is false (default), the environment will be based on the + * window's environment and also apply configured platform settings like + * `terminal.integrated.windows.env` on top. When this is true, the complete environment + * must be provided as nothing will be inherited from the process or any configuration. + */ + strictEnv?: boolean +} + +export default class TerminalModel { + public bufnr: number + private pid = 0 + + constructor(private cmd: string, + private args: string[], + private nvim: Neovim, + private _name?: string) { + } + + public async start(cwd?: string, env?: { [key: string]: string | null }): Promise { + 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 + } + + public get name(): string { + return this._name || this.cmd + } + + public get processId(): Promise { + return Promise.resolve(this.pid) + } + + public sendText(text: string, addNewLine = true): void { + if (!this.bufnr) return + this.nvim.call('coc#terminal#send', [this.bufnr, text, addNewLine], true) + } + + public async show(preserveFocus?: boolean): Promise { + let { bufnr, nvim } = this + if (!bufnr) return + let [loaded, winid, curr] = await nvim.eval(`[bufloaded(${bufnr}),bufwinid(${bufnr}),win_getid()]`) as [number, number, number] + if (!loaded) return false + if (curr == winid) return true + 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 + } + + public async hide(): Promise { + let { bufnr, nvim } = this + if (!bufnr) return + let winnr = await nvim.call('bufwinnr', bufnr) + if (winnr == -1) return + await nvim.command(`${winnr}close!`) + } + + public dispose(): void { + let { bufnr, nvim } = this + if (!bufnr) return + nvim.call('coc#terminal#close', [bufnr], true) + } +} diff --git a/vim-config/plugins/coc.nvim/src/model/textdocument.ts b/vim-config/plugins/coc.nvim/src/model/textdocument.ts new file mode 100644 index 00000000..7cc84283 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/model/textdocument.ts @@ -0,0 +1,92 @@ +import { Position, Range } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' + +function computeLineOffsets(text: string, isAtLineStart: boolean, textOffset = 0): number[] { + const result: number[] = isAtLineStart ? [textOffset] : [] + for (let i = 0; i < text.length; i++) { + let ch = text.charCodeAt(i) + if (ch === 13 || ch === 10) { + if (ch === 13 && i + 1 < text.length && text.charCodeAt(i + 1) === 10) { + i++ + } + result.push(textOffset + i + 1) + } + } + return result +} + +/** + * Text document that created with readonly lines. + * + * Created for save memory since we could reuse readonly lines. + */ +export class LinesTextDocument implements TextDocument { + private _lineOffsets: number[] | undefined + constructor( + public readonly uri: string, + public readonly languageId: string, + public readonly version: number, + public readonly lines: ReadonlyArray, + private eol: boolean + ) { + + } + + private get _content(): string { + return this.lines.join('\n') + (this.eol ? '\n' : '') + } + + public get lineCount(): number { + return this.lines.length + (this.eol ? 1 : 0) + } + + public getText(range?: Range): string { + if (range) { + const start = this.offsetAt(range.start) + const end = this.offsetAt(range.end) + return this._content.substring(start, end) + } + return this._content + } + + public positionAt(offset: number): Position { + offset = Math.max(Math.min(offset, this._content.length), 0) + let lineOffsets = this.getLineOffsets() + let low = 0 + let high = lineOffsets.length + if (high === 0) { + return { line: 0, character: offset } + } + while (low < high) { + let 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 + let line = low - 1 + return { line, character: offset - lineOffsets[line] } + } + + public offsetAt(position: Position) { + let lineOffsets = this.getLineOffsets() + if (position.line >= lineOffsets.length) { + return this._content.length + } else if (position.line < 0) { + return 0 + } + let lineOffset = lineOffsets[position.line] + let nextLineOffset = (position.line + 1 < lineOffsets.length) ? lineOffsets[position.line + 1] : this._content.length + return Math.max(Math.min(lineOffset + position.character, nextLineOffset), lineOffset) + } + + private getLineOffsets(): number[] { + if (this._lineOffsets === undefined) { + this._lineOffsets = computeLineOffsets(this._content, true) + } + return this._lineOffsets + } +} diff --git a/vim-config/plugins/coc.nvim/src/plugin.ts b/vim-config/plugins/coc.nvim/src/plugin.ts new file mode 100644 index 00000000..b8b4e739 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/plugin.ts @@ -0,0 +1,370 @@ +import { NeovimClient as Neovim } from '@chemzqm/neovim' +import { EventEmitter } from 'events' +import fs from 'fs' +import path from 'path' +import { CallHierarchyItem, CodeAction, CodeActionKind } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import commandManager from './commands' +import completion from './completion' +import Cursors from './cursors' +import diagnosticManager from './diagnostic/manager' +import events from './events' +import extensions from './extensions' +import Handler from './handler' +import listManager from './list/manager' +import services from './services' +import snippetManager from './snippets/manager' +import sources from './sources' +import { OutputChannel, PatternType } from './types' +import window from './window' +import workspace from './workspace' +const logger = require('./util/logger')('plugin') + +declare const REVISION + +export default class Plugin extends EventEmitter { + private _ready = false + private handler: Handler | undefined + private infoChannel: OutputChannel + private cursors: Cursors + private actions: Map = new Map() + + constructor(public nvim: Neovim) { + super() + Object.defineProperty(workspace, 'nvim', { + get: () => this.nvim + }) + workspace.onDidChangeWorkspaceFolders(() => { + nvim.setVar('WorkspaceFolders', workspace.folderPaths, true) + }) + this.cursors = new Cursors(nvim) + commandManager.init(nvim, this) + this.addAction('checkJsonExtension', () => { + if (extensions.has('coc-json')) return + window.showMessage(`Run :CocInstall coc-json for json intellisense`, 'more') + }) + this.addAction('rootPatterns', bufnr => { + let doc = workspace.getDocument(bufnr) + if (!doc) return null + return { + buffer: workspace.getRootPatterns(doc, PatternType.Buffer), + server: workspace.getRootPatterns(doc, PatternType.LanguageServer), + global: workspace.getRootPatterns(doc, PatternType.Global) + } + }) + this.addAction('getConfig', async key => { + let document = await workspace.document + return workspace.getConfiguration(key, document ? document.uri : undefined) + }) + this.addAction('doAutocmd', async (id: number, ...args: []) => { + let autocmd = (workspace as any).autocmds.get(id) as any + if (autocmd) { + try { + await Promise.resolve(autocmd.callback.apply(autocmd.thisArg, args)) + } catch (e) { + logger.error(`Error on autocmd ${autocmd.event}`, e) + window.showMessage(`Error on autocmd ${autocmd.event}: ${e.message}`) + } + } + }) + this.addAction('openLog', async () => { + let file = logger.getLogFile() + await workspace.jumpTo(URI.file(file).toString()) + }) + this.addAction('attach', () => workspace.attach()) + this.addAction('detach', () => workspace.detach()) + this.addAction('doKeymap', async (key: string, defaultReturn = '', pressed?: string) => { + let keymap = workspace.keymaps.get(key) + if (!keymap) { + logger.error(`keymap for ${key} not found`) + this.nvim.command(`silent! unmap ${pressed.startsWith('{') && pressed.endsWith('}') ? `<${pressed.slice(1, -1)}>` : pressed}`, true) + return defaultReturn + } + let [fn, repeat] = keymap + let res = await Promise.resolve(fn()) + if (repeat) await nvim.command(`silent! call repeat#set("\\(coc-${key})", -1)`) + return res ?? defaultReturn + }) + this.addAction('registExtensions', async (...folders: string[]) => { + for (let folder of folders) { + await extensions.loadExtension(folder) + } + }) + this.addAction('snippetCheck', async (checkExpand: boolean, checkJump: boolean) => { + if (checkExpand && !extensions.has('coc-snippets')) { + console.error('coc-snippets required for check expand status!') + return false + } + if (checkJump) { + let jumpable = snippetManager.jumpable() + if (jumpable) return true + } + if (checkExpand) { + let api = extensions.getExtensionApi('coc-snippets') as any + if (api && api.hasOwnProperty('expandable')) { + let expandable = await Promise.resolve(api.expandable()) + if (expandable) return true + } + } + return false + }) + this.addAction('snippetNext', () => snippetManager.nextPlaceholder()) + this.addAction('snippetPrev', () => snippetManager.previousPlaceholder()) + this.addAction('snippetCancel', () => snippetManager.cancel()) + this.addAction('openLocalConfig', () => window.openLocalConfig()) + this.addAction('showInfo', async () => { + if (!this.infoChannel) { + this.infoChannel = window.createOutputChannel('info') + } else { + this.infoChannel.clear() + } + let channel = this.infoChannel + channel.appendLine('## versions') + channel.appendLine('') + let out = await this.nvim.call('execute', ['version']) as string + let first = out.trim().split(/\r?\n/, 2)[0].replace(/\(.*\)/, '').trim() + channel.appendLine('vim version: ' + first + `${workspace.isVim ? ' ' + workspace.env.version : ''}`) + channel.appendLine('node version: ' + process.version) + channel.appendLine('coc.nvim version: ' + this.version) + channel.appendLine('coc.nvim directory: ' + path.dirname(__dirname)) + channel.appendLine('term: ' + (process.env.TERM_PROGRAM || process.env.TERM)) + channel.appendLine('platform: ' + process.platform) + channel.appendLine('') + channel.appendLine('## Log of coc.nvim') + channel.appendLine('') + let file = logger.getLogFile() + if (fs.existsSync(file)) { + let content = fs.readFileSync(file, { encoding: 'utf8' }) + channel.appendLine(content) + } + channel.show() + }) + this.addAction('findLocations', (id: string, method: string, params: any, openCommand?: string | false) => { + return this.handler.locations.findLocations(id, method, params, openCommand) + }) + this.addAction('hasProvider', id => this.handler.hasProvider(id)) + this.addAction('getTagList', () => this.handler.locations.getTagList()) + this.addAction('hasSelected', () => completion.hasSelected()) + this.addAction('listNames', () => listManager.names) + this.addAction('listDescriptions', () => listManager.descriptions) + this.addAction('listLoadItems', name => listManager.loadItems(name)) + this.addAction('search', (...args: string[]) => this.handler.refactor.search(args)) + this.addAction('cursorsSelect', (bufnr: number, kind: string, mode: string) => this.cursors.select(bufnr, kind, mode)) + this.addAction('fillDiagnostics', (bufnr: number) => diagnosticManager.setLocationlist(bufnr)) + this.addAction('saveRefactor', bufnr => this.handler.refactor.save(bufnr)) + this.addAction('commandList', () => this.handler.commands.getCommandList()) + this.addAction('selectSymbolRange', (inner: boolean, visualmode: string, supportedSymbols: string[]) => this.handler.symbols.selectSymbolRange(inner, visualmode, supportedSymbols)) + this.addAction('openList', (...args: string[]) => listManager.start(args)) + this.addAction('listResume', (name?: string) => listManager.resume(name)) + this.addAction('listCancel', () => listManager.cancel(true)) + this.addAction('listPrev', (name?: string) => listManager.previous(name)) + this.addAction('listNext', (name?: string) => listManager.next(name)) + this.addAction('listFirst', (name?: string) => listManager.first(name)) + this.addAction('listLast', (name?: string) => listManager.last(name)) + this.addAction('sendRequest', (id: string, method: string, params?: any) => services.sendRequest(id, method, params)) + this.addAction('sendNotification', (id: string, method: string, params?: any) => services.sendNotification(id, method, params)) + this.addAction('registNotification', (id: string, method: string) => services.registNotification(id, method)) + this.addAction('updateConfig', (section: string, val: any) => workspace.configurations.updateUserConfig({ [section]: val })) + this.addAction('links', () => this.handler.links.getLinks()) + this.addAction('openLink', () => this.handler.links.openCurrentLink()) + this.addAction('pickColor', () => this.handler.colors.pickColor()) + this.addAction('colorPresentation', () => this.handler.colors.pickPresentation()) + this.addAction('highlight', () => this.handler.documentHighlighter.highlight()) + this.addAction('fold', (kind?: string) => this.handler.fold.fold(kind)) + this.addAction('startCompletion', option => completion.startCompletion(option)) + this.addAction('stopCompletion', () => completion.stop(false)) + this.addAction('sourceStat', () => sources.sourceStats()) + this.addAction('refreshSource', name => sources.refresh(name)) + this.addAction('toggleSource', name => sources.toggleSource(name)) + this.addAction('diagnosticRefresh', bufnr => diagnosticManager.refresh(bufnr)) + this.addAction('diagnosticInfo', () => diagnosticManager.echoMessage()) + this.addAction('diagnosticToggle', () => diagnosticManager.toggleDiagnostic()) + this.addAction('diagnosticToggleBuffer', async (bufnr?: number) => { + if (!bufnr) bufnr = await nvim.call('bufnr', ['%']) + return diagnosticManager.toggleDiagnosticBuffer(bufnr) + }) + this.addAction('diagnosticNext', severity => diagnosticManager.jumpNext(severity)) + this.addAction('diagnosticPrevious', severity => diagnosticManager.jumpPrevious(severity)) + this.addAction('diagnosticPreview', () => diagnosticManager.preview()) + this.addAction('diagnosticList', () => diagnosticManager.getDiagnosticList()) + this.addAction('jumpDefinition', openCommand => this.handler.locations.gotoDefinition(openCommand)) + this.addAction('definitions', () => this.handler.locations.definitions()) + this.addAction('jumpDeclaration', openCommand => this.handler.locations.gotoDeclaration(openCommand)) + this.addAction('declarations', () => this.handler.locations.declarations()) + this.addAction('jumpImplementation', openCommand => this.handler.locations.gotoImplementation(openCommand)) + this.addAction('implementations', () => this.handler.locations.implementations()) + this.addAction('jumpTypeDefinition', openCommand => this.handler.locations.gotoTypeDefinition(openCommand)) + this.addAction('typeDefinitions', () => this.handler.locations.typeDefinitions()) + this.addAction('jumpReferences', openCommand => this.handler.locations.gotoReferences(openCommand)) + this.addAction('references', () => this.handler.locations.references()) + this.addAction('jumpUsed', openCommand => this.handler.locations.gotoReferences(openCommand, false)) + this.addAction('doHover', hoverTarget => this.handler.hover.onHover(hoverTarget)) + this.addAction('definitionHover', hoverTarget => this.handler.hover.definitionHover(hoverTarget)) + this.addAction('getHover', () => this.handler.hover.getHover()) + this.addAction('showSignatureHelp', () => this.handler.signature.triggerSignatureHelp()) + this.addAction('documentSymbols', async (bufnr?: number) => { + if (!bufnr) { + let doc = await workspace.document + bufnr = doc.bufnr + } + return await this.handler.symbols.getDocumentSymbols(bufnr) + }) + this.addAction('ensureDocument', async () => { + let doc = await workspace.document + return doc && doc.attached + }) + this.addAction('symbolRanges', () => this.handler.documentHighlighter.getSymbolsRanges()) + this.addAction('selectionRanges', () => this.handler.selectionRange.getSelectionRanges()) + this.addAction('rangeSelect', (visualmode, forward) => this.handler.selectionRange.selectRange(visualmode, forward)) + this.addAction('rename', newName => this.handler.rename.rename(newName)) + this.addAction('getWorkspaceSymbols', input => this.handler.symbols.getWorkspaceSymbols(input)) + this.addAction('resolveWorkspaceSymbol', symbolInfo => this.handler.symbols.resolveWorkspaceSymbol(symbolInfo)) + this.addAction('formatSelected', mode => this.handler.format.formatCurrentRange(mode)) + this.addAction('format', () => this.handler.format.formatCurrentBuffer()) + this.addAction('commands', () => this.handler.commands.getCommands()) + this.addAction('services', () => services.getServiceStats()) + this.addAction('toggleService', name => services.toggle(name)) + this.addAction('codeAction', (mode, only) => this.handler.codeActions.doCodeAction(mode, only)) + this.addAction('organizeImport', () => this.handler.codeActions.organizeImport()) + this.addAction('fixAll', () => this.handler.codeActions.doCodeAction(null, [CodeActionKind.SourceFixAll])) + // save actions send to vim, for provider resolve + let codeActions: CodeAction[] = [] + this.addAction('doCodeAction', codeAction => { + if (codeAction.index == null) { + throw new Error(`index should exists with codeAction`) + } + let action = codeActions[codeAction.index] + if (!action) throw new Error(`invalid codeAction index: ${codeAction.index}`) + return this.handler.codeActions.applyCodeAction(action) + }) + this.addAction('codeActions', async (mode, only) => { + codeActions = await this.handler.codeActions.getCurrentCodeActions(mode, only) + // save index for retreive + return codeActions.map((o, idx) => Object.assign({ index: idx }, o)) + }) + this.addAction('quickfixes', async mode => { + codeActions = await this.handler.codeActions.getCurrentCodeActions(mode, [CodeActionKind.QuickFix]) + return codeActions.map((o, idx) => Object.assign({ index: idx }, o)) + }) + this.addAction('codeLensAction', () => this.handler.codeLens.doAction()) + this.addAction('runCommand', (...args: any[]) => this.handler.commands.runCommand(...args)) + this.addAction('doQuickfix', () => this.handler.codeActions.doQuickfix()) + this.addAction('refactor', () => this.handler.refactor.doRefactor()) + this.addAction('repeatCommand', () => this.handler.commands.repeat()) + this.addAction('installExtensions', (...list: string[]) => extensions.installExtensions(list)) + this.addAction('updateExtensions', sync => extensions.updateExtensions(sync)) + this.addAction('extensionStats', () => extensions.getExtensionStates()) + this.addAction('loadedExtensions', () => extensions.loadedExtensions()) + this.addAction('watchExtension', (id: string) => extensions.watchExtension(id)) + this.addAction('activeExtension', name => extensions.activate(name)) + this.addAction('deactivateExtension', name => extensions.deactivate(name)) + this.addAction('reloadExtension', name => extensions.reloadExtension(name)) + this.addAction('toggleExtension', name => extensions.toggleExtension(name)) + this.addAction('uninstallExtension', (...args: string[]) => extensions.uninstallExtension(args)) + this.addAction('getCurrentFunctionSymbol', () => this.handler.symbols.getCurrentFunctionSymbol()) + this.addAction('showOutline', (keep?: number) => this.handler.symbols.showOutline(keep)) + this.addAction('hideOutline', () => this.handler.symbols.hideOutline()) + this.addAction('getWordEdit', () => this.handler.rename.getWordEdit()) + this.addAction('addCommand', cmd => this.handler.commands.addVimCommand(cmd)) + this.addAction('addRanges', ranges => this.cursors.addRanges(ranges)) + this.addAction('currentWorkspacePath', () => workspace.rootPath) + this.addAction('selectCurrentPlaceholder', triggerAutocmd => snippetManager.selectCurrentPlaceholder(!!triggerAutocmd)) + this.addAction('codeActionRange', (start, end, only) => this.handler.codeActions.codeActionRange(start, end, only)) + this.addAction('incomingCalls', (item?: CallHierarchyItem) => this.handler.callHierarchy.getIncoming(item)) + this.addAction('outgoingCalls', (item?: CallHierarchyItem) => this.handler.callHierarchy.getOutgoing(item)) + this.addAction('showIncomingCalls', () => this.handler.callHierarchy.showCallHierarchyTree('incoming')) + this.addAction('showOutgoingCalls', () => this.handler.callHierarchy.showCallHierarchyTree('outgoing')) + this.addAction('semanticHighlight', () => this.handler.semanticHighlighter.highlightCurrent()) + this.addAction('showSemanticHighlightInfo', () => this.handler.semanticHighlighter.showHiglightInfo()) + } + + private addAction(key: string, fn: Function): void { + if (this.actions.has(key)) { + throw new Error(`Action ${key} already exists`) + } + this.actions.set(key, fn) + } + + public async init(): Promise { + let { nvim } = this + let s = Date.now() + try { + await extensions.init() + await workspace.init() + snippetManager.init() + completion.init() + diagnosticManager.init() + listManager.init(nvim) + sources.init() + this.handler = new Handler(nvim) + services.init() + extensions.activateExtensions() + workspace.setupDynamicAutocmd(true) + nvim.pauseNotification() + nvim.setVar('WorkspaceFolders', workspace.folderPaths, true) + nvim.setVar('coc_service_initialized', 1, true) + nvim.call('coc#util#do_autocmd', ['CocNvimInit'], true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + this._ready = true + await events.fire('ready', []) + logger.info(`coc.nvim ${this.version} initialized with node: ${process.version} after ${Date.now() - s}ms`) + this.emit('ready') + } catch (e) { + nvim.echoError(e) + } + } + + public get isReady(): boolean { + return this._ready + } + + public get ready(): Promise { + if (this._ready) return Promise.resolve() + return new Promise(resolve => { + this.once('ready', () => { + resolve() + }) + }) + } + + private get version(): string { + return workspace.version + (typeof REVISION === 'string' ? '-' + REVISION : '') + } + + public hasAction(method: string): boolean { + return this.actions.has(method) + } + + public async cocAction(method: string, ...args: any[]): Promise { + let fn = this.actions.get(method) + if (!fn) throw new Error(`Action "${method}" not exists`) + let ts = Date.now() + let res = await Promise.resolve(fn.apply(null, args)) + let dt = Date.now() - ts + if (dt > 500) logger.warn(`Slow action "${method}" cost ${dt}ms`) + return res + } + + public getHandler(): Handler { + return this.handler + } + + public dispose(): void { + this.removeAllListeners() + extensions.dispose() + listManager.dispose() + workspace.dispose() + window.dispose() + sources.dispose() + services.stopAll() + services.dispose() + if (this.handler) { + this.handler.dispose() + } + snippetManager.dispose() + commandManager.dispose() + completion.dispose() + diagnosticManager.dispose() + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/callHierarchyManager.ts b/vim-config/plugins/coc.nvim/src/provider/callHierarchyManager.ts new file mode 100644 index 00000000..bff1fbec --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/callHierarchyManager.ts @@ -0,0 +1,45 @@ +import { CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, CancellationToken, Disposable, DocumentSelector, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { CallHierarchyProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class CallHierarchyManager extends Manager { + + public register(selector: DocumentSelector, provider: CallHierarchyProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async prepareCallHierarchy(document: TextDocument, position: Position, token: CancellationToken): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + if (provider.prepareCallHierarchy === null) return null + return await Promise.resolve(provider.prepareCallHierarchy(document, position, token)) + } + + public async provideCallHierarchyOutgoingCalls(document: TextDocument, item: CallHierarchyItem, token: CancellationToken): Promise { + let providerItem = this.getProvider(document) + if (!providerItem) return null + let { provider } = providerItem + if (provider.provideCallHierarchyOutgoingCalls === null) return null + return await Promise.resolve(provider.provideCallHierarchyOutgoingCalls(item, token)) + } + + public async provideCallHierarchyIncomingCalls(document: TextDocument, item: CallHierarchyItem, token: CancellationToken): Promise { + let providerItem = this.getProvider(document) + if (!providerItem) return null + let { provider } = providerItem + if (provider.provideCallHierarchyIncomingCalls(item, token) === null) return null + + return await Promise.resolve(provider.provideCallHierarchyIncomingCalls(item, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/codeActionManager.ts b/vim-config/plugins/coc.nvim/src/provider/codeActionManager.ts new file mode 100644 index 00000000..a8889dc6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/codeActionManager.ts @@ -0,0 +1,94 @@ +import { CancellationToken, CodeAction, CodeActionContext, CodeActionKind, Command, Disposable, DocumentSelector, Range } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { CodeActionProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' +const logger = require('../util/logger')('codeActionManager') + +export default class CodeActionManager extends Manager { + // action to provider uuid + private providerMap: WeakMap = new WeakMap() + + public register(selector: DocumentSelector, provider: CodeActionProvider, clientId: string | undefined, codeActionKinds?: CodeActionKind[]): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider, + kinds: codeActionKinds, + clientId + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideCodeActions( + document: TextDocument, + range: Range, + context: CodeActionContext, + token: CancellationToken + ): Promise { + 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.includes(kind))) { + return false + } + return true + }) + } + let res: CodeAction[] = [] + await Promise.all(providers.map(item => { + let { provider, id } = item + return Promise.resolve(provider.provideCodeActions(document, range, context, token)).then(actions => { + if (!actions || actions.length == 0) return + for (let action of actions) { + if (Command.is(action)) { + let codeAction: CodeAction = { + title: action.title, + command: action + } + res.push(codeAction) + this.providerMap.set(codeAction, id) + } else { + if (context.only) { + if (!action.kind) continue + let found = false + for (let only of context.only) { + if (action.kind.startsWith(only)) { + found = true + break + } + } + if (!found) continue + } + let idx = res.findIndex(o => o.title == action.title) + if (idx == -1) { + this.providerMap.set(action, id) + res.push(action) + } + } + } + }) + })) + return res + } + + public async resolveCodeAction(codeAction: CodeAction, token: CancellationToken): Promise { + // no need to resolve + if (codeAction.edit != null) return codeAction + let id = this.providerMap.get(codeAction) + if (!id) throw new Error(`provider id not found from codeAction`) + let provider = this.getProviderById(id) + if (!provider || typeof provider.resolveCodeAction !== 'function') { + return codeAction + } + let resolved = await Promise.resolve(provider.resolveCodeAction(codeAction, token)) + // save the map to support resolveClientId + if (resolved) this.providerMap.set(resolved, id) + return resolved || codeAction + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/codeLensManager.ts b/vim-config/plugins/coc.nvim/src/provider/codeLensManager.ts new file mode 100644 index 00000000..fd48d96d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/codeLensManager.ts @@ -0,0 +1,58 @@ +import { CancellationToken, CodeLens, Disposable, DocumentSelector } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { CodeLensProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' +import { omit } from '../util/lodash' +// const logger = require('../util/logger')('codeActionManager') + +export default class CodeLensManager extends Manager { + + public register(selector: DocumentSelector, provider: CodeLensProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideCodeLenses( + document: TextDocument, + token: CancellationToken + ): Promise { + 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 as any).source = id + } + } + return res + }) + })) + return [].concat(...arr) + } + + public async resolveCodeLens( + codeLens: CodeLens, + token: CancellationToken + ): Promise { + // no need to resolve + if (codeLens.command) return codeLens + let { source } = codeLens as any + let provider = this.getProviderById(source) + if (!provider || typeof provider.resolveCodeLens != 'function') { + return codeLens + } + let res = await Promise.resolve(provider.resolveCodeLens(omit(codeLens, ['source']), token)) + Object.assign(codeLens, res) + return codeLens + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/declarationManager.ts b/vim-config/plugins/coc.nvim/src/provider/declarationManager.ts new file mode 100644 index 00000000..4cafb37d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/declarationManager.ts @@ -0,0 +1,32 @@ +import { CancellationToken, Disposable, DocumentSelector, Location, Position, LocationLink } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DeclarationProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' +const logger = require('../util/logger')('definitionManager') + +export default class DeclarationManager extends Manager { + + public register(selector: DocumentSelector, provider: DeclarationProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideDeclaration( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + return await Promise.resolve(provider.provideDeclaration(document, position, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/definitionManager.ts b/vim-config/plugins/coc.nvim/src/provider/definitionManager.ts new file mode 100644 index 00000000..79c7937e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/definitionManager.ts @@ -0,0 +1,64 @@ +import { CancellationToken, Definition, DefinitionLink, Disposable, DocumentSelector, Location, LocationLink, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DefinitionProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' +import { equals } from '../util/object' +const logger = require('../util/logger')('definitionManager') + +export default class DefinitionManager extends Manager { + + public register(selector: DocumentSelector, provider: DefinitionProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + private async getDefinitions( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise<(Definition | DefinitionLink[])[]> { + const providers = this.getProviders(document) + if (!providers.length) return [] + const arr = await Promise.all(providers.map(item => { + const { provider } = item + return Promise.resolve(provider.provideDefinition(document, position, token)) + })) + return arr + } + + public async provideDefinition( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + const arr = await this.getDefinitions(document, position, token) + return this.toLocations(arr) + } + + public async provideDefinitionLinks( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + const arr = await this.getDefinitions(document, position, token) + const defs: DefinitionLink[] = [] + for (const def of arr) { + if (!Array.isArray(def)) continue + for (const val of def) { + if (LocationLink.is(val)) { + let idx = defs.findIndex(o => o.targetUri == val.targetUri && equals(o.targetRange, val.targetRange)) + if (idx == -1) defs.push(val) + } + } + } + return defs + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/documentColorManager.ts b/vim-config/plugins/coc.nvim/src/provider/documentColorManager.ts new file mode 100644 index 00000000..0ca50f0a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/documentColorManager.ts @@ -0,0 +1,37 @@ +import { CancellationToken, ColorInformation, ColorPresentation, Disposable, DocumentSelector } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentColorProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class DocumentColorManager extends Manager { + + public register(selector: DocumentSelector, provider: DocumentColorProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideDocumentColors(document: TextDocument, token: CancellationToken): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + let res: ColorInformation[] = await Promise.resolve(provider.provideDocumentColors(document, token)) + return res + } + + public async provideColorPresentations(colorInformation: ColorInformation, document: TextDocument, token: CancellationToken): Promise { + 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 + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/documentHighlightManager.ts b/vim-config/plugins/coc.nvim/src/provider/documentHighlightManager.ts new file mode 100644 index 00000000..38f6fdb9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/documentHighlightManager.ts @@ -0,0 +1,31 @@ +import { CancellationToken, Disposable, DocumentHighlight, DocumentSelector, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentHighlightProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class DocumentHighlightManager extends Manager { + + public register(selector: DocumentSelector, provider: DocumentHighlightProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideDocumentHighlights( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + return await Promise.resolve(provider.provideDocumentHighlights(document, position, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/documentLinkManager.ts b/vim-config/plugins/coc.nvim/src/provider/documentLinkManager.ts new file mode 100644 index 00000000..866fbd15 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/documentLinkManager.ts @@ -0,0 +1,51 @@ +import { CancellationToken, Disposable, DocumentLink, DocumentSelector } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentLinkProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class DocumentLinkManager extends Manager { + + public register(selector: DocumentSelector, provider: DocumentLinkProvider): Disposable { + let item = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + private async _provideDocumentLinks(item: ProviderItem, document: TextDocument, token: CancellationToken): Promise { + 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 + } + + public async provideDocumentLinks(document: TextDocument, token: CancellationToken): Promise { + let items = this.getProviders(document) + if (items.length == 0) return [] + const arr = await Promise.all(items.map(item => this._provideDocumentLinks(item, document, token))) + return [].concat(...arr) + } + + public async resolveDocumentLink(link: DocumentLink, token: CancellationToken): Promise { + 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 + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/documentSymbolManager.ts b/vim-config/plugins/coc.nvim/src/provider/documentSymbolManager.ts new file mode 100644 index 00000000..002dae11 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/documentSymbolManager.ts @@ -0,0 +1,31 @@ +import { CancellationToken, Disposable, DocumentSelector, DocumentSymbol, SymbolInformation } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentSymbolProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class DocumentSymbolManager extends Manager { + + public register(selector: DocumentSelector, provider: DocumentSymbolProvider, displayName?: string): Disposable { + let item: ProviderItem = { + id: uuid(), + displayName, + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideDocumentSymbols( + document: TextDocument, + token: CancellationToken + ): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + return (await Promise.resolve(provider.provideDocumentSymbols(document, token))) || [] + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/foldingRangeManager.ts b/vim-config/plugins/coc.nvim/src/provider/foldingRangeManager.ts new file mode 100644 index 00000000..a8b379f7 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/foldingRangeManager.ts @@ -0,0 +1,27 @@ +import { CancellationToken, Disposable, DocumentSelector, FoldingRange } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { FoldingContext, FoldingRangeProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class FoldingRangeManager extends Manager { + + public register(selector: DocumentSelector, provider: FoldingRangeProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + return (await Promise.resolve(provider.provideFoldingRanges(document, context, token)) || []) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/formatManager.ts b/vim-config/plugins/coc.nvim/src/provider/formatManager.ts new file mode 100644 index 00000000..c20a671f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/formatManager.ts @@ -0,0 +1,38 @@ +import { CancellationToken, Disposable, DocumentSelector, FormattingOptions, TextEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentFormattingEditProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class FormatManager extends Manager { + + public register(selector: DocumentSelector, + provider: DocumentFormattingEditProvider, + priority = 0): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + priority, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public handles(doc: TextDocument): boolean { + return this.getProvider(doc) != null + } + + public async provideDocumentFormattingEdits( + document: TextDocument, + options: FormattingOptions, + token: CancellationToken + ): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + return await Promise.resolve(provider.provideDocumentFormattingEdits(document, options, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/formatRangeManager.ts b/vim-config/plugins/coc.nvim/src/provider/formatRangeManager.ts new file mode 100644 index 00000000..d3c288ca --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/formatRangeManager.ts @@ -0,0 +1,35 @@ +import { CancellationToken, Disposable, DocumentSelector, FormattingOptions, Range, TextEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentRangeFormattingEditProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class FormatRangeManager extends Manager { + + public register(selector: DocumentSelector, + provider: DocumentRangeFormattingEditProvider, + priority = 0): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider, + priority + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideDocumentRangeFormattingEdits( + document: TextDocument, + range: Range, + options: FormattingOptions, + token: CancellationToken + ): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + return await Promise.resolve(provider.provideDocumentRangeFormattingEdits(document, range, options, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/hoverManager.ts b/vim-config/plugins/coc.nvim/src/provider/hoverManager.ts new file mode 100644 index 00000000..b68773df --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/hoverManager.ts @@ -0,0 +1,36 @@ +import { CancellationToken, Disposable, DocumentSelector, Hover, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { HoverProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class HoverManager extends Manager { + + public register(selector: DocumentSelector, provider: HoverProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideHover( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + 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 + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/implementationManager.ts b/vim-config/plugins/coc.nvim/src/provider/implementationManager.ts new file mode 100644 index 00000000..dbac8fb7 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/implementationManager.ts @@ -0,0 +1,34 @@ +import { CancellationToken, Disposable, DocumentSelector, Location, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { ImplementationProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class ImplementationManager extends Manager { + + public register(selector: DocumentSelector, provider: ImplementationProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideReferences( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + 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.toLocations(arr) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/index.ts b/vim-config/plugins/coc.nvim/src/provider/index.ts new file mode 100644 index 00000000..6e22d215 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/index.ts @@ -0,0 +1,815 @@ +import { CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, CancellationToken, CodeAction, CodeActionContext, CodeActionKind, CodeLens, Color, ColorInformation, ColorPresentation, Command, CompletionContext, CompletionItem, CompletionList, Definition, DefinitionLink, DocumentHighlight, DocumentLink, DocumentSymbol, Event, FoldingRange, FormattingOptions, Hover, LinkedEditingRanges, Location, Position, Range, SelectionRange, SemanticTokens, SemanticTokensDelta, SignatureHelp, SignatureHelpContext, SymbolInformation, TextEdit, WorkspaceEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' + +/** + * A provider result represents the values a provider, like the [`HoverProvider`](#HoverProvider), + * may return. For once this is the actual result type `T`, like `Hover`, or a thenable that resolves + * to that type `T`. In addition, `null` and `undefined` can be returned - either directly or from a + * thenable. + * + * The snippets below are all valid implementations of the [`HoverProvider`](#HoverProvider): + * + * ```ts + * let a: HoverProvider = { + * provideHover(doc, pos, token): ProviderResult { + * return new Hover('Hello World') + * } + * } + * + * let b: HoverProvider = { + * provideHover(doc, pos, token): ProviderResult { + * return new Promise(resolve => { + * resolve(new Hover('Hello World')) + * }) + * } + * } + * + * let c: HoverProvider = { + * provideHover(doc, pos, token): ProviderResult { + * return; // undefined + * } + * } + * ``` + */ +export type ProviderResult = + | T + | undefined + | null + | Thenable + +/** + * The completion item provider interface defines the contract between extensions and + * [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense). + * + * Providers can delay the computation of the [`detail`](#CompletionItem.detail) + * and [`documentation`](#CompletionItem.documentation) properties by implementing the + * [`resolveCompletionItem`](#CompletionItemProvider.resolveCompletionItem)-function. However, properties that + * are needed for the initial sorting and filtering, like `sortText`, `filterText`, `insertText`, and `range`, must + * not be changed during resolve. + * + * Providers are asked for completions either explicitly by a user gesture or -depending on the configuration- + * implicitly when typing words or trigger characters. + */ +export interface CompletionItemProvider { + /** + * Provide completion items for the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @param context How the completion was triggered. + * + * @return An array of completions, a [completion list](#CompletionList), or a thenable that resolves to either. + * The lack of a result can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideCompletionItems( + document: TextDocument, + position: Position, + token: CancellationToken, + context?: CompletionContext + ): ProviderResult + + /** + * Given a completion item fill in more data, like [doc-comment](#CompletionItem.documentation) + * or [details](#CompletionItem.detail). + * + * The editor will only resolve a completion item once. + * + * @param item A completion item currently active in the UI. + * @param token A cancellation token. + * @return The resolved completion item or a thenable that resolves to of such. It is OK to return the given + * `item`. When no result is returned, the given `item` will be used. + */ + resolveCompletionItem?( + item: CompletionItem, + token: CancellationToken + ): ProviderResult +} + +/** + * The hover provider interface defines the contract between extensions and + * the [hover](https://code.visualstudio.com/docs/editor/intellisense)-feature. + */ +export interface HoverProvider { + /** + * Provide a hover for the given position and document. Multiple hovers at the same + * position will be merged by the editor. A hover can have a range which defaults + * to the word range at the position when omitted. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A hover or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideHover( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +/** + * The definition provider interface defines the contract between extensions and + * the [go to definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition) + * and peek definition features. + */ +export interface DefinitionProvider { + /** + * Provide the definition of the symbol at the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A definition or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideDefinition( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +/** + * The definition provider interface defines the contract between extensions and + * the [go to definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition) + * and peek definition features. + */ +export interface DeclarationProvider { + /** + * Provide the declaration of the symbol at the given position and document. + */ + provideDeclaration(document: TextDocument, position: Position, token: CancellationToken): ProviderResult +} + +/** + * The signature help provider interface defines the contract between extensions and + * the [parameter hints](https://code.visualstudio.com/docs/editor/intellisense)-feature. + */ +export interface SignatureHelpProvider { + /** + * Provide help for the signature at the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return Signature help or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideSignatureHelp( + document: TextDocument, + position: Position, + token: CancellationToken, + context: SignatureHelpContext + ): ProviderResult +} + +/** + * The type definition provider defines the contract between extensions and + * the go to type definition feature. + */ +export interface TypeDefinitionProvider { + /** + * Provide the type definition of the symbol at the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A definition or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideTypeDefinition( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +/** + * Value-object that contains additional information when + * requesting references. + */ +export interface ReferenceContext { + /** + * Include the declaration of the current symbol. + */ + includeDeclaration: boolean +} + +/** + * The reference provider interface defines the contract between extensions and + * the [find references](https://code.visualstudio.com/docs/editor/editingevolved#_peek)-feature. + */ +export interface ReferenceProvider { + /** + * Provide a set of project-wide references for the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param context + * @param token A cancellation token. + * @return An array of locations or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideReferences( + document: TextDocument, + position: Position, + context: ReferenceContext, + token: CancellationToken + ): ProviderResult +} + +/** + * Folding context (for future use) + */ +export interface FoldingContext {} + +/** + * The folding range provider interface defines the contract between extensions and + * [Folding](https://code.visualstudio.com/docs/editor/codebasics#_folding) in the editor. + */ +export interface FoldingRangeProvider { + /** + * Returns a list of folding ranges or null and undefined if the provider + * does not want to participate or was cancelled. + * + * @param document The document in which the command was invoked. + * @param context Additional context information (for future use) + * @param token A cancellation token. + */ + provideFoldingRanges( + document: TextDocument, + context: FoldingContext, + token: CancellationToken + ): ProviderResult +} + +/** + * The document symbol provider interface defines the contract between extensions and + * the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol)-feature. + */ +export interface DocumentSymbolProvider { + + displayName?: string + + /** + * Provide symbol information for the given document. + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of document highlights or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentSymbols( + document: TextDocument, + token: CancellationToken + ): ProviderResult +} + +/** + * The implemenetation provider interface defines the contract between extensions and + * the go to implementation feature. + */ +export interface ImplementationProvider { + /** + * Provide the implementations of the symbol at the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A definition or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideImplementation( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +/** + * The workspace symbol provider interface defines the contract between extensions and + * the [symbol search](https://code.visualstudio.com/docs/editor/editingevolved#_open-symbol-by-name)-feature. + */ +export interface WorkspaceSymbolProvider { + /** + * Project-wide search for a symbol matching the given query string. It is up to the provider + * how to search given the query string, like substring, indexOf etc. To improve performance implementors can + * skip the [location](#SymbolInformation.location) of symbols and implement `resolveWorkspaceSymbol` to do that + * later. + * + * The `query`-parameter should be interpreted in a *relaxed way* as the editor will apply its own highlighting + * and scoring on the results. A good rule of thumb is to match case-insensitive and to simply check that the + * characters of *query* appear in their order in a candidate symbol. Don't use prefix, substring, or similar + * strict matching. + * + * @param query A non-empty query string. + * @param token A cancellation token. + * @return An array of document highlights or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideWorkspaceSymbols( + query: string, + token: CancellationToken + ): ProviderResult + + /** + * Given a symbol fill in its [location](#SymbolInformation.location). This method is called whenever a symbol + * is selected in the UI. Providers can implement this method and return incomplete symbols from + * [`provideWorkspaceSymbols`](#WorkspaceSymbolProvider.provideWorkspaceSymbols) which often helps to improve + * performance. + * + * @param symbol The symbol that is to be resolved. Guaranteed to be an instance of an object returned from an + * earlier call to `provideWorkspaceSymbols`. + * @param token A cancellation token. + * @return The resolved symbol or a thenable that resolves to that. When no result is returned, + * the given `symbol` is used. + */ + resolveWorkspaceSymbol?( + symbol: SymbolInformation, + token: CancellationToken + ): ProviderResult +} + +/** + * The rename provider interface defines the contract between extensions and + * the [rename](https://code.visualstudio.com/docs/editor/editingevolved#_rename-symbol)-feature. + */ +export interface RenameProvider { + /** + * Provide an edit that describes changes that have to be made to one + * or many resources to rename a symbol to a different name. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param newName The new name of the symbol. If the given name is not valid, the provider must return a rejected promise. + * @param token A cancellation token. + * @return A workspace edit or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideRenameEdits( + document: TextDocument, + position: Position, + newName: string, + token: CancellationToken + ): ProviderResult + + /** + * Optional function for resolving and validating a position *before* running rename. The result can + * be a range or a range and a placeholder text. The placeholder text should be the identifier of the symbol + * which is being renamed - when omitted the text in the returned range is used. + * + * @param document The document in which rename will be invoked. + * @param position The position at which rename will be invoked. + * @param token A cancellation token. + * @return The range or range and placeholder text of the identifier that is to be renamed. The lack of a result can signaled by returning `undefined` or `null`. + */ + prepareRename?( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +/** + * The document formatting provider interface defines the contract between extensions and + * the formatting-feature. + */ +export interface DocumentFormattingEditProvider { + /** + * Provide formatting edits for a whole document. + * + * @param document The document in which the command was invoked. + * @param options Options controlling formatting. + * @param token A cancellation token. + * @return A set of text edits or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentFormattingEdits( + document: TextDocument, + options: FormattingOptions, + token: CancellationToken + ): ProviderResult +} + +/** + * The document formatting provider interface defines the contract between extensions and + * the formatting-feature. + */ +export interface DocumentRangeFormattingEditProvider { + /** + * Provide formatting edits for a range in a document. + * + * The given range is a hint and providers can decide to format a smaller + * or larger range. Often this is done by adjusting the start and end + * of the range to full syntax nodes. + * + * @param document The document in which the command was invoked. + * @param range The range which should be formatted. + * @param options Options controlling formatting. + * @param token A cancellation token. + * @return A set of text edits or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentRangeFormattingEdits( + document: TextDocument, + range: Range, + options: FormattingOptions, + token: CancellationToken + ): ProviderResult +} + +/** + * The code action interface defines the contract between extensions and + * the [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature. + * + * A code action can be any command that is [known](#commands.getCommands) to the system. + */ +export interface CodeActionProvider { + /** + * Provide commands for the given document and range. + * + * @param document The document in which the command was invoked. + * @param range The selector or range for which the command was invoked. This will always be a selection if + * there is a currently active editor. + * @param context Context carrying additional information. + * @param token A cancellation token. + * @return An array of commands, quick fixes, or refactorings or a thenable of such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideCodeActions( + document: TextDocument, + range: Range, + context: CodeActionContext, + token: CancellationToken + ): ProviderResult<(Command | CodeAction)[]> + + /** + * Given a code action fill in its [`edit`](#CodeAction.edit)-property. Changes to + * all other properties, like title, are ignored. A code action that has an edit + * will not be resolved. + * + * @param codeAction A code action. + * @param token A cancellation token. + * @return The resolved code action or a thenable that resolves to such. It is OK to return the given + * `item`. When no result is returned, the given `item` will be used. + */ + resolveCodeAction?(codeAction: T, token: CancellationToken): ProviderResult +} + +/** + * Metadata about the type of code actions that a [CodeActionProvider](#CodeActionProvider) providers + */ +export interface CodeActionProviderMetadata { + /** + * [CodeActionKinds](#CodeActionKind) that this provider may return. + * + * The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the provider + * may list our every specific kind they provide, such as `CodeActionKind.Refactor.Extract.append('function`)` + */ + readonly providedCodeActionKinds?: ReadonlyArray +} + +/** + * The document highlight provider interface defines the contract between extensions and + * the word-highlight-feature. + */ +export interface DocumentHighlightProvider { + + /** + * Provide a set of document highlights, like all occurrences of a variable or + * all exit-points of a function. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return An array of document highlights or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentHighlights( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult +} + +/** + * The document link provider defines the contract between extensions and feature of showing + * links in the editor. + */ +export interface DocumentLinkProvider { + + /** + * Provide links for the given document. Note that the editor ships with a default provider that detects + * `http(s)` and `file` links. + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of [document links](#DocumentLink) or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentLinks(document: TextDocument, token: CancellationToken): ProviderResult + + /** + * Given a link fill in its [target](#DocumentLink.target). This method is called when an incomplete + * link is selected in the UI. Providers can implement this method and return incomple links + * (without target) from the [`provideDocumentLinks`](#DocumentLinkProvider.provideDocumentLinks) method which + * often helps to improve performance. + * + * @param link The link that is to be resolved. + * @param token A cancellation token. + */ + resolveDocumentLink?(link: DocumentLink, token: CancellationToken): ProviderResult +} + +/** + * A code lens provider adds [commands](#Command) to source text. The commands will be shown + * as dedicated horizontal lines in between the source text. + */ +export interface CodeLensProvider { + + /** + * An optional event to signal that the code lenses from this provider have changed. + */ + onDidChangeCodeLenses?: Event + + /** + * Compute a list of [lenses](#CodeLens). This call should return as fast as possible and if + * computing the commands is expensive implementors should only return code lens objects with the + * range set and implement [resolve](#CodeLensProvider.resolveCodeLens). + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of code lenses or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideCodeLenses(document: TextDocument, token: CancellationToken): ProviderResult + + /** + * This function will be called for each visible code lens, usually when scrolling and after + * calls to [compute](#CodeLensProvider.provideCodeLenses)-lenses. + * + * @param codeLens code lens that must be resolved. + * @param token A cancellation token. + * @return The given, resolved code lens or thenable that resolves to such. + */ + resolveCodeLens?(codeLens: CodeLens, token: CancellationToken): ProviderResult +} + +/** + * The document formatting provider interface defines the contract between extensions and + * the formatting-feature. + */ +export interface OnTypeFormattingEditProvider { + + /** + * Provide formatting edits after a character has been typed. + * + * The given position and character should hint to the provider + * what range the position to expand to, like find the matching `{` + * when `}` has been entered. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param ch The character that has been typed. + * @param options Options controlling formatting. + * @param token A cancellation token. + * @return A set of text edits or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideOnTypeFormattingEdits(document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): ProviderResult +} + +/** + * The document color provider defines the contract between extensions and feature of + * picking and modifying colors in the editor. + */ +export interface DocumentColorProvider { + + /** + * Provide colors for the given document. + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of [color information](#ColorInformation) or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult + + /** + * Provide [representations](#ColorPresentation) for a color. + * + * @param color The color to show and insert. + * @param context A context object with additional information + * @param token A cancellation token. + * @return An array of color presentations or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideColorPresentations(color: Color, context: { document: TextDocument; range: Range }, token: CancellationToken): ProviderResult +} + +export interface TextDocumentContentProvider { + + /** + * An event to signal a resource has changed. + */ + onDidChange?: Event + + /** + * Provide textual content for a given uri. + * + * The editor will use the returned string-content to create a readonly + * [document](#TextDocument). Resources allocated should be released when + * the corresponding document has been [closed](#workspace.onDidCloseTextDocument). + * + * @param uri An uri which scheme matches the scheme this provider was [registered](#workspace.registerTextDocumentContentProvider) for. + * @param token A cancellation token. + * @return A string or a thenable that resolves to such. + */ + provideTextDocumentContent(uri: URI, token: CancellationToken): ProviderResult +} + +export interface SelectionRangeProvider { + /** + * Provide selection ranges starting at a given position. The first range must [contain](#Range.contains) + * position and subsequent ranges must contain the previous range. + */ + provideSelectionRanges(document: TextDocument, positions: Position[], token: CancellationToken): ProviderResult +} + +/** + * The call hierarchy provider interface describes the contract between extensions + * and the call hierarchy feature which allows to browse calls and caller of function, + * methods, constructor etc. + */ +export interface CallHierarchyProvider { + + /** + * Bootstraps call hierarchy by returning the item that is denoted by the given document + * and position. This item will be used as entry into the call graph. Providers should + * return `undefined` or `null` when there is no item at the given location. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @returns A call hierarchy item or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + prepareCallHierarchy(document: TextDocument, position: Position, token: CancellationToken): ProviderResult + + /** + * Provide all incoming calls for an item, e.g all callers for a method. In graph terms this describes directed + * and annotated edges inside the call graph, e.g the given item is the starting node and the result is the nodes + * that can be reached. + * + * @param item The hierarchy item for which incoming calls should be computed. + * @param token A cancellation token. + * @returns A set of incoming calls or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideCallHierarchyIncomingCalls(item: CallHierarchyItem, token: CancellationToken): ProviderResult + + /** + * Provide all outgoing calls for an item, e.g call calls to functions, methods, or constructors from the given item. In + * graph terms this describes directed and annotated edges inside the call graph, e.g the given item is the starting + * node and the result is the nodes that can be reached. + * + * @param item The hierarchy item for which outgoing calls should be computed. + * @param token A cancellation token. + * @returns A set of outgoing calls or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideCallHierarchyOutgoingCalls(item: CallHierarchyItem, token: CancellationToken): ProviderResult +} + +/** + * The document semantic tokens provider interface defines the contract between extensions and + * semantic tokens. + */ +export interface DocumentSemanticTokensProvider { + /** + * An optional event to signal that the semantic tokens from this provider have changed. + */ + onDidChangeSemanticTokens?: Event + + /** + * Tokens in a file are represented as an array of integers. The position of each token is expressed relative to + * the token before it, because most tokens remain stable relative to each other when edits are made in a file. + * + * --- + * In short, each token takes 5 integers to represent, so a specific token `i` in the file consists of the following array indices: + * + * - at index `5*i` - `deltaLine`: token line number, relative to the previous token + * - at index `5*i+1` - `deltaStart`: token start character, relative to the previous token (relative to 0 or the previous token's start if they are on the same line) + * - at index `5*i+2` - `length`: the length of the token. A token cannot be multiline. + * - at index `5*i+3` - `tokenType`: will be looked up in `SemanticTokensLegend.tokenTypes`. We currently ask that `tokenType` < 65536. + * - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticTokensLegend.tokenModifiers` + * + * --- + * ### How to encode tokens + * + * Here is an example for encoding a file with 3 tokens in a uint32 array: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: "property", tokenModifiers: ["private", "static"] }, + * { line: 2, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] }, + * { line: 5, startChar: 2, length: 7, tokenType: "class", tokenModifiers: [] } + * ``` + * + * 1. First of all, a legend must be devised. This legend must be provided up-front and capture all possible token types. + * For this example, we will choose the following legend which must be passed in when registering the provider: + * ``` + * tokenTypes: ['property', 'type', 'class'], + * tokenModifiers: ['private', 'static'] + * ``` + * + * 2. The first transformation step is to encode `tokenType` and `tokenModifiers` as integers using the legend. Token types are looked + * up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Multiple token modifiers can be set by using bit flags, + * so a `tokenModifier` value of `3` is first viewed as binary `0b00000011`, which means `[tokenModifiers[0], tokenModifiers[1]]` because + * bits 0 and 1 are set. Using this legend, the tokens now are: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { line: 2, startChar: 10, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { line: 5, startChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 3. The next step is to represent each token relative to the previous token in the file. In this case, the second token + * is on the same line as the first token, so the `startChar` of the second token is made relative to the `startChar` + * of the first token, so it will be `10 - 5`. The third token is on a different line than the second token, so the + * `startChar` of the third token will not be altered: + * ``` + * { deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 4. Finally, the last step is to inline each of the 5 fields for a token in a single array, which is a memory friendly representation: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * + * @see [SemanticTokensBuilder](#SemanticTokensBuilder) for a helper to encode tokens as integers. + * *NOTE*: When doing edits, it is possible that multiple edits occur until VS Code decides to invoke the semantic tokens provider. + * *NOTE*: If the provider cannot temporarily compute semantic tokens, it can indicate this by throwing an error with the message 'Busy'. + */ + provideDocumentSemanticTokens(document: TextDocument, token: CancellationToken): ProviderResult + + /** + * Instead of always returning all the tokens in a file, it is possible for a `DocumentSemanticTokensProvider` to implement + * this method (`provideDocumentSemanticTokensEdits`) and then return incremental updates to the previously provided semantic tokens. + * + * --- + * ### How tokens change when the document changes + * + * Suppose that `provideDocumentSemanticTokens` has previously returned the following semantic tokens: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * + * Also suppose that after some edits, the new semantic tokens in a file are: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * It is possible to express these new tokens in terms of an edit applied to the previous tokens: + * ``` + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] // old tokens + * [ 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] // new tokens + * + * edit: { start: 0, deleteCount: 1, data: [3] } // replace integer at offset 0 with 3 + * ``` + * + * *NOTE*: If the provider cannot compute `SemanticTokensEdits`, it can "give up" and return all the tokens in the document again. + * *NOTE*: All edits in `SemanticTokensEdits` contain indices in the old integers array, so they all refer to the previous result state. + */ + provideDocumentSemanticTokensEdits?(document: TextDocument, previousResultId: string, token: CancellationToken): ProviderResult +} + +/** + * The document range semantic tokens provider interface defines the contract between extensions and + * semantic tokens. + */ +export interface DocumentRangeSemanticTokensProvider { + /** + * @see [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens). + */ + provideDocumentRangeSemanticTokens(document: TextDocument, range: Range, token: CancellationToken): ProviderResult +} + +export interface LinkedEditingRangeProvider { + /** + * For a given position in a document, returns the range of the symbol at the position and all ranges + * that have the same content. A change to one of the ranges can be applied to all other ranges if the new content + * is valid. An optional word pattern can be returned with the result to describe valid contents. + * If no result-specific word pattern is provided, the word pattern from the language configuration is used. + * + * @param document The document in which the provider was invoked. + * @param position The position at which the provider was invoked. + * @param token A cancellation token. + * @return A list of ranges that can be edited together + */ + provideLinkedEditingRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult +} diff --git a/vim-config/plugins/coc.nvim/src/provider/linkedEditingRangeManager.ts b/vim-config/plugins/coc.nvim/src/provider/linkedEditingRangeManager.ts new file mode 100644 index 00000000..a2908c9a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/linkedEditingRangeManager.ts @@ -0,0 +1,29 @@ +import { v4 as uuid } from 'uuid' +import { CancellationToken, Disposable, DocumentSelector, LinkedEditingRanges, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { LinkedEditingRangeProvider } from './index' +import Manager, { ProviderItem } from './manager' +const logger = require('../util/logger')('linkedEditingManager') + +export default class LinkedEditingRangeManager extends Manager { + public register(selector: DocumentSelector, provider: LinkedEditingRangeProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideLinkedEditingRanges(document: TextDocument, position: Position, token: CancellationToken): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + if (!provider.provideLinkedEditingRanges) return null + + return await Promise.resolve(provider.provideLinkedEditingRanges(document, position, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/manager.ts b/vim-config/plugins/coc.nvim/src/provider/manager.ts new file mode 100644 index 00000000..412f4e51 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/manager.ts @@ -0,0 +1,79 @@ +import { Definition, DocumentSelector, Location, LocationLink } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import workspace from '../workspace' +import { equals } from '../util/object' +const logger = require('../util/logger')('provider-manager') + +export interface ProviderItem { + id: string + selector: DocumentSelector + provider: T + [key: string]: any +} + +export default class Manager { + protected providers: Set> = new Set() + + public hasProvider(document: TextDocument): boolean { + return this.getProvider(document) != null + } + + protected getProvider(document: TextDocument): ProviderItem { + let currScore = 0 + let providerItem: ProviderItem + for (let item of this.providers) { + let { selector, priority } = item + let score = workspace.match(selector, document) + if (score == 0) continue + if (typeof priority == 'number') { + score = priority + } + if (score < currScore) continue + currScore = score + providerItem = item + } + return providerItem + } + + protected getProviderById(id: string): T { + let item = Array.from(this.providers).find(o => o.id == id) + return item ? item.provider : null + } + + protected getProviders(document: TextDocument): ProviderItem[] { + let items = Array.from(this.providers) + items = items.filter(item => workspace.match(item.selector, document) > 0) + return items.sort((a, b) => workspace.match(b.selector, document) - workspace.match(a.selector, document)) + } + + protected toLocations(arr: (Definition | LocationLink[] | null)[]): Location[] { + let res: Location[] = [] + for (let def of arr) { + if (!def) continue + if (Location.is(def)) { + addLocation(res, def) + } else if (Array.isArray(def)) { + for (let d of def) { + if (Location.is(d)) { + addLocation(res, d) + } else if (LocationLink.is(d)) { + let { targetUri, targetSelectionRange, targetRange } = d + addLocation(res, Location.create(targetUri, targetSelectionRange || targetRange)) + } + } + } else { + logger.error(`Bad definition`, def) + } + } + return res + } +} + +/** + * Add unique location + */ +function addLocation(arr: Location[], location: Location): void { + let { range, uri } = location + if (arr.find(o => o.uri == uri && equals(o.range, range)) != null) return + arr.push(location) +} diff --git a/vim-config/plugins/coc.nvim/src/provider/onTypeFormatManager.ts b/vim-config/plugins/coc.nvim/src/provider/onTypeFormatManager.ts new file mode 100644 index 00000000..a6f0a83e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/onTypeFormatManager.ts @@ -0,0 +1,54 @@ +import { CancellationToken, Disposable, DocumentSelector, Position, TextEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import workspace from '../workspace' +import { OnTypeFormattingEditProvider } from './index' +const logger = require('../util/logger')('onTypeFormatManager') + +export interface ProviderItem { + triggerCharacters: string[] + selector: DocumentSelector + provider: OnTypeFormattingEditProvider +} + +export default class OnTypeFormatManager { + private providers: Set = new Set() + + public register(selector: DocumentSelector, provider: OnTypeFormattingEditProvider, triggerCharacters: string[]): Disposable { + let item: ProviderItem = { + triggerCharacters, + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public hasProvider(document: TextDocument): boolean { + for (let o of this.providers) { + let { selector } = o + if (workspace.match(selector, document) > 0) { + return true + } + } + return false + } + + public getProvider(document: TextDocument, triggerCharacter: string): OnTypeFormattingEditProvider | null { + for (let o of this.providers) { + let { triggerCharacters, selector } = o + if (workspace.match(selector, document) > 0 && triggerCharacters.includes(triggerCharacter)) { + return o.provider + } + } + return null + } + + public async onCharacterType(character: string, document: TextDocument, position: Position, token: CancellationToken): Promise { + let provider = this.getProvider(document, character) + if (!provider) return + let formatOpts = await workspace.getFormatOptions(document.uri) + return await Promise.resolve(provider.provideOnTypeFormattingEdits(document, position, character, formatOpts, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/referenceManager.ts b/vim-config/plugins/coc.nvim/src/provider/referenceManager.ts new file mode 100644 index 00000000..e07a7647 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/referenceManager.ts @@ -0,0 +1,35 @@ +import { CancellationToken, Disposable, DocumentSelector, Location, Position, ReferenceContext } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { ReferenceProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class ReferenceManager extends Manager { + + public register(selector: DocumentSelector, provider: ReferenceProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideReferences( + document: TextDocument, + position: Position, + context: ReferenceContext, + token: CancellationToken + ): Promise { + 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.toLocations(arr) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/renameManager.ts b/vim-config/plugins/coc.nvim/src/provider/renameManager.ts new file mode 100644 index 00000000..43cd5557 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/renameManager.ts @@ -0,0 +1,47 @@ +import { CancellationToken, Disposable, DocumentSelector, Position, Range, WorkspaceEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { RenameProvider } from './index' +import Manager from './manager' +import { v4 as uuid } from 'uuid' + +export default class RenameManager extends Manager { + + public register(selector: DocumentSelector, provider: RenameProvider): Disposable { + let item = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideRenameEdits( + document: TextDocument, + position: Position, + newName: string, + token: CancellationToken + ): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + return await Promise.resolve(provider.provideRenameEdits(document, position, newName, token)) + } + + public async prepareRename( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + 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) return false + return res + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/selectionRangeManager.ts b/vim-config/plugins/coc.nvim/src/provider/selectionRangeManager.ts new file mode 100644 index 00000000..7d9df328 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/selectionRangeManager.ts @@ -0,0 +1,37 @@ +import { SelectionRange, CancellationToken, Disposable, DocumentSelector, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { SelectionRangeProvider } from './index' +import Manager from './manager' +import { v4 as uuid } from 'uuid' + +export default class SelectionRangeManager extends Manager { + + public register(selector: DocumentSelector, provider: SelectionRangeProvider): Disposable { + let item = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideSelectionRanges( + document: TextDocument, + positions: Position[], + token: CancellationToken + ): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + let ranges: SelectionRange[] = await Promise.resolve(provider.provideSelectionRanges(document, positions, token)) + if (!ranges || ranges.length == 0) return [] + for (let i = 0; i < ranges.length - 1; i++) { + let r = ranges[i] + if (!r.parent) r.parent = ranges[i + 1] + } + return ranges + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/semanticTokensManager.ts b/vim-config/plugins/coc.nvim/src/provider/semanticTokensManager.ts new file mode 100644 index 00000000..e1fba09f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/semanticTokensManager.ts @@ -0,0 +1,68 @@ +import { v4 as uuid } from 'uuid' +import { CancellationToken, Disposable, DocumentSelector, SemanticTokens, SemanticTokensDelta, SemanticTokensLegend } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentSemanticTokensProvider } from './index' +import Manager, { ProviderItem } from './manager' +const logger = require('../util/logger')('semanticTokensManager') + +export default class SemanticTokensManager extends Manager { + private resolvedProvider: Map = new Map() + + public register(selector: DocumentSelector, provider: DocumentSemanticTokensProvider, legend: SemanticTokensLegend, onChange: () => void): Disposable { + let id = uuid() + let item: ProviderItem = { + id, + selector, + legend, + provider + } + this.providers.add(item) + let disposable: Disposable | undefined + if (typeof provider.onDidChangeSemanticTokens === 'function') { + disposable = provider.onDidChangeSemanticTokens(() => { + onChange() + }) + } + return Disposable.create(() => { + disposable?.dispose() + for (let [uri, providerId] of this.resolvedProvider.entries()) { + if (providerId == id) { + this.resolvedProvider.delete(uri) + } + } + this.providers.delete(item) + }) + } + + public getLegend(document: TextDocument): SemanticTokensLegend { + const item = this.getProvider(document) + if (!item) return + // save matched provider + this.resolvedProvider.set(document.uri, item.id) + return item.legend + } + + protected resolveProvider(document: TextDocument): DocumentSemanticTokensProvider { + let id = this.resolvedProvider.get(document.uri) + if (id) return this.getProviderById(id) + return this.getProvider(document)?.provider + } + + public hasSemanticTokensEdits(document: TextDocument): boolean { + let provider = this.resolveProvider(document) + if (!provider) return false + return (typeof provider.provideDocumentSemanticTokensEdits === 'function') + } + + public async provideDocumentSemanticTokens(document: TextDocument, token: CancellationToken): Promise { + let provider = this.resolveProvider(document) + if (!provider || typeof provider.provideDocumentSemanticTokens !== 'function') return null + return await Promise.resolve(provider.provideDocumentSemanticTokens(document, token)) + } + + public async provideDocumentSemanticTokensEdits(document: TextDocument, previousResultId: string, token: CancellationToken): Promise { + let provider = this.resolveProvider(document) + if (!provider || typeof provider.provideDocumentSemanticTokensEdits !== 'function') return null + return await Promise.resolve(provider.provideDocumentSemanticTokensEdits(document, previousResultId, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/semanticTokensRangeManager.ts b/vim-config/plugins/coc.nvim/src/provider/semanticTokensRangeManager.ts new file mode 100644 index 00000000..4f24766b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/semanticTokensRangeManager.ts @@ -0,0 +1,36 @@ +import { v4 as uuid } from 'uuid' +import { CancellationToken, Disposable, DocumentSelector, Range, SemanticTokens, SemanticTokensLegend } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { DocumentRangeSemanticTokensProvider } from './index' +import Manager, { ProviderItem } from './manager' +const logger = require('../util/logger')('semanticTokensRangeManager') + +export default class SemanticTokensRangeManager extends Manager { + public register(selector: DocumentSelector, provider: DocumentRangeSemanticTokensProvider, legend: SemanticTokensLegend): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + legend, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public getLegend(document: TextDocument): SemanticTokensLegend { + const item = this.getProvider(document) + if (!item) return + return item.legend + } + + public async provideDocumentRangeSemanticTokens(document: TextDocument, range: Range, token: CancellationToken): Promise { + let item = this.getProvider(document) + if (!item) return null + let { provider } = item + if (provider.provideDocumentRangeSemanticTokens === null) return null + + return await Promise.resolve(provider.provideDocumentRangeSemanticTokens(document, range, token)) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/signatureManager.ts b/vim-config/plugins/coc.nvim/src/provider/signatureManager.ts new file mode 100644 index 00000000..21d6a0f7 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/signatureManager.ts @@ -0,0 +1,42 @@ +import { CancellationToken, Disposable, DocumentSelector, Position, SignatureHelp, SignatureHelpContext } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { SignatureHelpProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class SignatureManager extends Manager { + + public register(selector: DocumentSelector, provider: SignatureHelpProvider, triggerCharacters?: string[]): Disposable { + let characters = triggerCharacters.reduce((p, c) => p.concat(c.length == 1 ? [c] : c.split(/\s*/g)), [] as string[]) + let item: ProviderItem = { + id: uuid(), + selector, + provider, + triggerCharacters: characters + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public shouldTrigger(document: TextDocument, triggerCharacter: string): boolean { + let item = this.getProvider(document) + if (!item) return false + let { triggerCharacters } = item + return triggerCharacters && triggerCharacters.indexOf(triggerCharacter) != -1 + } + + public async provideSignatureHelp( + document: TextDocument, + position: Position, + token: CancellationToken, + context: SignatureHelpContext + ): Promise { + let item = this.getProvider(document) + if (!item) return null + let res = await Promise.resolve(item.provider.provideSignatureHelp(document, position, token, context)) + if (res && res.signatures && res.signatures.length) return res + return null + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/typeDefinitionManager.ts b/vim-config/plugins/coc.nvim/src/provider/typeDefinitionManager.ts new file mode 100644 index 00000000..d392f011 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/typeDefinitionManager.ts @@ -0,0 +1,34 @@ +import { CancellationToken, Disposable, DocumentSelector, Location, Position } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { TypeDefinitionProvider } from './index' +import Manager, { ProviderItem } from './manager' +import { v4 as uuid } from 'uuid' + +export default class TypeDefinitionManager extends Manager { + + public register(selector: DocumentSelector, provider: TypeDefinitionProvider): Disposable { + let item: ProviderItem = { + id: uuid(), + selector, + provider + } + this.providers.add(item) + return Disposable.create(() => { + this.providers.delete(item) + }) + } + + public async provideTypeDefinition( + document: TextDocument, + position: Position, + token: CancellationToken + ): Promise { + 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.toLocations(arr) + } +} diff --git a/vim-config/plugins/coc.nvim/src/provider/workspaceSymbolsManager.ts b/vim-config/plugins/coc.nvim/src/provider/workspaceSymbolsManager.ts new file mode 100644 index 00000000..fb9eeeb4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/provider/workspaceSymbolsManager.ts @@ -0,0 +1,47 @@ +import { v4 as uuid } from 'uuid' +import { CancellationToken, Disposable, SymbolInformation } from 'vscode-languageserver-protocol' +import { WorkspaceSymbolProvider } from './index' + +export default class WorkspaceSymbolManager { + private providers: Map = new Map() + + public register(provider: WorkspaceSymbolProvider): Disposable { + let id = uuid() + this.providers.set(id, provider) + return Disposable.create(() => { + this.providers.delete(id) + }) + } + + public async provideWorkspaceSymbols( + query: string, + token: CancellationToken + ): Promise { + let entries = Array.from(this.providers.entries()) + if (!entries.length) return [] + let res: SymbolInformation[] = [] + await Promise.all(entries.map(o => { + let [id, p] = o + return Promise.resolve(p.provideWorkspaceSymbols(query, token)).then(list => { + if (list) res.push(...list.map(item => Object.assign({ source: id }, item))) + }) + })) + return res + } + + public async resolveWorkspaceSymbol( + symbolInfo: SymbolInformation, + token: CancellationToken + ): Promise { + let provider = this.providers.get((symbolInfo as any).source) + if (!provider) return + if (typeof provider.resolveWorkspaceSymbol != 'function') { + return Promise.resolve(symbolInfo) + } + return await Promise.resolve(provider.resolveWorkspaceSymbol(symbolInfo, token)) + } + + public hasProvider(): boolean { + return this.providers.size > 0 + } +} diff --git a/vim-config/plugins/coc.nvim/src/semanticTokensBuilder.ts b/vim-config/plugins/coc.nvim/src/semanticTokensBuilder.ts new file mode 100644 index 00000000..e21bb3de --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/semanticTokensBuilder.ts @@ -0,0 +1,207 @@ +import { Range, SemanticTokens, SemanticTokensLegend } from "vscode-languageserver-protocol" + +function isStringArray(value: any): value is string[] { + return Array.isArray(value) && (value as any[]).every(elem => typeof elem === 'string') +} + +function isStrArrayOrUndefined(arg: any): arg is string[] | undefined { + return ((typeof arg === 'undefined') || isStringArray(arg)) +} + +/** + * A semantic tokens builder can help with creating a `SemanticTokens` instance + * which contains delta encoded semantic tokens. + */ +export class SemanticTokensBuilder { + private _prevLine: number + private _prevChar: number + private _dataIsSortedAndDeltaEncoded: boolean + private _data: number[] + private _dataLen: number + private _tokenTypeStrToInt: Map + private _tokenModifierStrToInt: Map + private _hasLegend: boolean + + constructor(legend?: SemanticTokensLegend) { + this._prevLine = 0 + this._prevChar = 0 + this._dataIsSortedAndDeltaEncoded = true + this._data = [] + this._dataLen = 0 + this._tokenTypeStrToInt = new Map() + this._tokenModifierStrToInt = new Map() + this._hasLegend = false + if (legend) { + this._hasLegend = true + for (let i = 0, len = legend.tokenTypes.length; i < len; i++) { + this._tokenTypeStrToInt.set(legend.tokenTypes[i], i) + } + for (let i = 0, len = legend.tokenModifiers.length; i < len; i++) { + this._tokenModifierStrToInt.set(legend.tokenModifiers[i], i) + } + } + } + + /** + * Add another token. + * + * @param line The token start line number (absolute value). + * @param char The token start character (absolute value). + * @param length The token length in characters. + * @param tokenType The encoded token type. + * @param tokenModifiers The encoded token modifiers. + */ + public push(line: number, char: number, length: number, tokenType: number, tokenModifiers?: number): void + /** + * Add another token. Use only when providing a legend. + * + * @param range The range of the token. Must be single-line. + * @param tokenType The token type. + * @param tokenModifiers The token modifiers. + */ + public push(range: Range, tokenType: string, tokenModifiers?: string[]): void + public push(arg0: any, arg1: any, arg2: any, arg3?: any, arg4?: any): void { + if (typeof arg0 === 'number' && typeof arg1 === 'number' && typeof arg2 === 'number' && typeof arg3 === 'number' && (typeof arg4 === 'number' || typeof arg4 === 'undefined')) { + if (typeof arg4 === 'undefined') { + arg4 = 0 + } + // 1st overload + return this._pushEncoded(arg0, arg1, arg2, arg3, arg4) + } + if (Range.is(arg0) && typeof arg1 === 'string' && isStrArrayOrUndefined(arg2)) { + // 2nd overload + return this._push(arg0, arg1, arg2) + } + throw new Error('Illegal argument') + } + + private _push(range: Range, tokenType: string, tokenModifiers?: string[]): void { + if (!this._hasLegend) { + throw new Error('Legend must be provided in constructor') + } + if (range.start.line !== range.end.line) { + throw new Error('`range` cannot span multiple lines') + } + if (!this._tokenTypeStrToInt.has(tokenType)) { + throw new Error('`tokenType` is not in the provided legend') + } + const line = range.start.line + const char = range.start.character + const length = range.end.character - range.start.character + const nTokenType = this._tokenTypeStrToInt.get(tokenType)! + let nTokenModifiers = 0 + if (tokenModifiers) { + for (const tokenModifier of tokenModifiers) { + if (!this._tokenModifierStrToInt.has(tokenModifier)) { + throw new Error('`tokenModifier` is not in the provided legend') + } + const nTokenModifier = this._tokenModifierStrToInt.get(tokenModifier)! + nTokenModifiers |= (1 << nTokenModifier) >>> 0 + } + } + this._pushEncoded(line, char, length, nTokenType, nTokenModifiers) + } + + private _pushEncoded(line: number, char: number, length: number, tokenType: number, tokenModifiers: number): void { + if (this._dataIsSortedAndDeltaEncoded && (line < this._prevLine || (line === this._prevLine && char < this._prevChar))) { + // push calls were ordered and are no longer ordered + this._dataIsSortedAndDeltaEncoded = false + + // Remove delta encoding from data + const tokenCount = (this._data.length / 5) | 0 + let prevLine = 0 + let prevChar = 0 + for (let i = 0; i < tokenCount; i++) { + let line = this._data[5 * i] + let char = this._data[5 * i + 1] + + if (line === 0) { + // on the same line as previous token + line = prevLine + char += prevChar + } else { + // on a different line than previous token + line += prevLine + } + + this._data[5 * i] = line + this._data[5 * i + 1] = char + + prevLine = line + prevChar = char + } + } + + let pushLine = line + let pushChar = char + if (this._dataIsSortedAndDeltaEncoded && this._dataLen > 0) { + pushLine -= this._prevLine + if (pushLine === 0) { + pushChar -= this._prevChar + } + } + + this._data[this._dataLen++] = pushLine + this._data[this._dataLen++] = pushChar + this._data[this._dataLen++] = length + this._data[this._dataLen++] = tokenType + this._data[this._dataLen++] = tokenModifiers + + this._prevLine = line + this._prevChar = char + } + + private static _sortAndDeltaEncode(data: number[]): number[] { + let pos: number[] = [] + const tokenCount = (data.length / 5) | 0 + for (let i = 0; i < tokenCount; i++) { + pos[i] = i + } + pos.sort((a, b) => { + const aLine = data[5 * a] + const bLine = data[5 * b] + if (aLine === bLine) { + const aChar = data[5 * a + 1] + const bChar = data[5 * b + 1] + return aChar - bChar + } + return aLine - bLine + }) + const result = new Array(data.length) + let prevLine = 0 + let prevChar = 0 + for (let i = 0; i < tokenCount; i++) { + const srcOffset = 5 * pos[i] + const line = data[srcOffset + 0] + const char = data[srcOffset + 1] + const length = data[srcOffset + 2] + const tokenType = data[srcOffset + 3] + const tokenModifiers = data[srcOffset + 4] + + const pushLine = line - prevLine + const pushChar = (pushLine === 0 ? char - prevChar : char) + + const dstOffset = 5 * i + result[dstOffset + 0] = pushLine + result[dstOffset + 1] = pushChar + result[dstOffset + 2] = length + result[dstOffset + 3] = tokenType + result[dstOffset + 4] = tokenModifiers + + prevLine = line + prevChar = char + } + + return result + } + + /** + * Finish and create a `SemanticTokens` instance. + */ + public build(resultId?: string): SemanticTokens { + if (!this._dataIsSortedAndDeltaEncoded) { + return { data: SemanticTokensBuilder._sortAndDeltaEncode(this._data), resultId } + } + return { data: this._data, resultId } + } +} diff --git a/vim-config/plugins/coc.nvim/src/services.ts b/vim-config/plugins/coc.nvim/src/services.ts new file mode 100644 index 00000000..142968de --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/services.ts @@ -0,0 +1,565 @@ +import { SpawnOptions } from 'child_process' +import { EventEmitter } from 'events' +import fs from 'fs' +import net from 'net' +import { CancellationToken, Event, CancellationTokenSource, Disposable, DocumentSelector, Emitter } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { Executable, ForkOptions, LanguageClient, LanguageClientOptions, RevealOutputChannelOn, ServerOptions, State, Transport, TransportKind } from './language-client' +import { ServiceStat } from './types' +import { disposeAll, wait } from './util' +import workspace from './workspace' +import window from './window' +const logger = require('./util/logger')('services') + +interface ServiceInfo { + id: string + state: string + languageIds: string[] +} + +export interface LanguageServerConfig { + module?: string + command?: string + transport?: string + transportPort?: number + disableWorkspaceFolders?: boolean + disableSnippetCompletion?: boolean + disableDynamicRegister?: boolean + disableCompletion?: boolean + disableDiagnostics?: boolean + formatterPriority?: number + filetypes: string[] + additionalSchemes?: string[] + enable?: boolean + args?: string[] + cwd?: string + env?: any + // socket port + port?: number + host?: string + detached?: boolean + shell?: boolean + execArgv?: string[] + rootPatterns?: string[] + ignoredRootPaths?: string[] + initializationOptions?: any + progressOnInitialization?: boolean + revealOutputChannelOn?: string + configSection?: string + stdioEncoding?: string + runtime?: string +} + +export function getStateName(state: ServiceStat): string { + switch (state) { + case ServiceStat.Initial: + return 'init' + case ServiceStat.Running: + return 'running' + case ServiceStat.Starting: + return 'starting' + case ServiceStat.StartFailed: + return 'startFailed' + case ServiceStat.Stopping: + return 'stopping' + case ServiceStat.Stopped: + return 'stopped' + default: + return 'unknown' + } +} + +export interface IServiceProvider { + // unique service id + id: string + name: string + client?: LanguageClient + selector: DocumentSelector + // current state + state: ServiceStat + start(): Promise + dispose(): void + stop(): Promise | void + restart(): Promise | void + onServiceReady: Event +} + +export class ServiceManager extends EventEmitter implements Disposable { + private readonly registered: Map = new Map() + private disposables: Disposable[] = [] + + public init(): void { + workspace.onDidOpenTextDocument(document => { + this.start(document) + }, null, this.disposables) + workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('languageserver')) { + this.createCustomServices() + } + }, null, this.disposables) + this.createCustomServices() + } + + public dispose(): void { + this.removeAllListeners() + disposeAll(this.disposables) + for (let service of this.registered.values()) { + service.dispose() + } + } + + public regist(service: IServiceProvider): Disposable { + 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)) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + service.start() + } + if (service.state == ServiceStat.Running) { + this.emit('ready', id) + } + service.onServiceReady(() => { + logger.info(`service ${id} started`) + this.emit('ready', id) + }, null, this.disposables) + return Disposable.create(() => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + service.stop() + service.dispose() + this.registered.delete(id) + }) + } + + public getService(id: string): IServiceProvider { + let service = this.registered.get(id) + if (!service) service = this.registered.get(`languageserver.${id}`) + return service + } + + private shouldStart(service: IServiceProvider): boolean { + if (service.state != ServiceStat.Initial) { + return false + } + let selector = service.selector + for (let doc of workspace.documents) { + if (workspace.match(selector, doc.textDocument)) { + return true + } + } + return false + } + + private start(document: TextDocument): void { + let services = this.getServices(document) + for (let service of services) { + if (service.state == ServiceStat.Initial) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + service.start() + } + } + } + + public getServices(document: TextDocument): IServiceProvider[] { + let res: IServiceProvider[] = [] + for (let service of this.registered.values()) { + if (workspace.match(service.selector, document) > 0) { + res.push(service) + } + } + return res + } + + public stop(id: string): Promise { + let service = this.registered.get(id) + if (!service) { + window.showMessage(`Service ${id} not found`, 'error') + return + } + return Promise.resolve(service.stop()) + } + + public stopAll(): void { + for (let service of this.registered.values()) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + service.stop() + } + } + + public async toggle(id: string): Promise { + let service = this.registered.get(id) + if (!service) { + window.showMessage(`Service ${id} not found`, 'error') + return + } + let { state } = service + try { + if (state == ServiceStat.Running) { + await Promise.resolve(service.stop()) + } else if (state == ServiceStat.Initial) { + await service.start() + } else if (state == ServiceStat.Stopped) { + await service.restart() + } + } catch (e) { + window.showMessage(`Service error: ${e.message}`, 'error') + } + } + + public getServiceStats(): ServiceInfo[] { + let res: ServiceInfo[] = [] + for (let [id, service] of this.registered) { + res.push({ + id, + languageIds: documentSelectorToLanguageIds(service.selector), + state: getStateName(service.state) + }) + } + return res + } + + private createCustomServices(): void { + let lspConfig = workspace.getConfiguration().get<{ key: LanguageServerConfig }>('languageserver', {} as any) + for (let key of Object.keys(lspConfig)) { + let config: LanguageServerConfig = lspConfig[key] + if (!this.validServerConfig(key, config)) { + continue + } + this.registLanguageClient(key, config) + } + } + + private validServerConfig(key: string, config: LanguageServerConfig): boolean { + let errors: string[] = [] + if (config.module != null && typeof config.module !== 'string') { + errors.push(`"module" field of languageserver ${key} should be string`) + } + if (config.command != null && typeof config.command !== 'string') { + errors.push(`"command" field of languageserver ${key} should be string`) + } + if (config.transport != null && typeof config.transport !== 'string') { + errors.push(`"transport" field of languageserver ${key} should be string`) + } + if (config.transportPort != null && typeof config.transportPort !== 'number') { + errors.push(`"transportPort" field of languageserver ${key} should be string`) + } + if (!Array.isArray(config.filetypes) || !config.filetypes.every(s => typeof s === 'string')) { + errors.push(`"filetypes" field of languageserver ${key} should be array of string`) + } + if (config.additionalSchemes && (!Array.isArray(config.additionalSchemes) || config.additionalSchemes.some(s => typeof s !== 'string'))) { + errors.push(`"additionalSchemes" field of languageserver ${key} should be array of string`) + } + if (errors.length) { + window.showMessage(errors.join('\n'), 'error') + return false + } + return true + } + + private waitClient(id: string): Promise { + let service = this.getService(id) + if (service && service.state == 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) + }) + } + + public async registNotification(id: string, method: string): Promise { + await this.waitClient(id) + let service = this.getService(id) + if (!service.client) { + window.showMessage(`Not a language client: ${id}`, 'error') + return + } + let client = service.client + client.onNotification(method, async result => { + await workspace.nvim.call('coc#do_notify', [id, method, result]) + }) + } + + public async sendNotification(id: string, method: string, params?: any): Promise { + if (!method) throw new Error(`method required for ontification`) + let service = this.getService(id) + // wait for extension activate + if (!service || !service.client) throw new Error(`Language server ${id} not found`) + if (service.state == ServiceStat.Starting) { + await service.client.onReady() + } + if (service.state != ServiceStat.Running) { + throw new Error(`Language server ${id} not running`) + } + await Promise.resolve(service.client.sendNotification(method, params)) + } + + public async sendRequest(id: string, method: string, params?: any, token?: CancellationToken): Promise { + if (!method) throw new Error(`method required for sendRequest`) + let service = this.getService(id) + // wait for extension activate + if (!service) await wait(100) + service = this.getService(id) + if (!service || !service.client) { + throw new Error(`Language server ${id} not found`) + } + if (service.state == ServiceStat.Starting) { + await service.client.onReady() + } + if (service.state != ServiceStat.Running) { + throw new Error(`Language server ${id} not running`) + } + if (!token) { + let tokenSource = new CancellationTokenSource() + token = tokenSource.token + } + return await Promise.resolve(service.client.sendRequest(method, params, token)) + } + + public registLanguageClient(client: LanguageClient): Disposable + public registLanguageClient(name: string, config: LanguageServerConfig): Disposable + public registLanguageClient(name: string | LanguageClient, config?: LanguageServerConfig): Disposable { + let id = typeof name === 'string' ? `languageserver.${name}` : name.id + let disposables: Disposable[] = [] + let onDidServiceReady = new Emitter() + let client: LanguageClient | null = typeof name === 'string' ? null : name + if (this.registered.has(id)) return + let created = false + let service: IServiceProvider = { + id, + client, + name: typeof name === 'string' ? name : name.name, + selector: typeof name === 'string' ? getDocumentSelector(config.filetypes, config.additionalSchemes) : name.clientOptions.documentSelector, + state: ServiceStat.Initial, + onServiceReady: onDidServiceReady.event, + start: (): Promise => { + if (service.state == ServiceStat.Starting || service.state == ServiceStat.Running) { + return + } + if (client && !client.needsStart()) { + return + } + if (created && client) { + client.restart() + return Promise.resolve() + } + if (!created) { + if (typeof name == 'string' && !client) { + let config: LanguageServerConfig = workspace.getConfiguration().get<{ key: LanguageServerConfig }>('languageserver', {} as any)[name] + if (!config || config.enable === false) return + let opts = getLanguageServerOptions(id, name, config) + if (!opts) return + client = new LanguageClient(id, name, opts[1], opts[0]) + service.selector = opts[0].documentSelector + service.client = client + } + client.onDidChangeState(changeEvent => { + let { oldState, newState } = changeEvent + if (newState == State.Starting) { + service.state = ServiceStat.Starting + } else if (newState == State.Running) { + service.state = ServiceStat.Running + } else if (newState == State.Stopped) { + service.state = ServiceStat.Stopped + } + let oldStr = stateString(oldState) + let newStr = stateString(newState) + logger.info(`${client.name} state change: ${oldStr} => ${newStr}`) + }, null, disposables) + created = true + } + service.state = ServiceStat.Starting + logger.debug(`starting service: ${id}`) + let disposable = client.start() + disposables.push(disposable) + return new Promise(resolve => { + client.onReady().then(() => { + onDidServiceReady.fire(void 0) + resolve() + }, e => { + window.showMessage(`Server ${id} failed to start: ${e}`, 'error') + logger.error(`Server ${id} failed to start:`, e) + service.state = ServiceStat.StartFailed + resolve() + }) + }) + }, + dispose: async () => { + onDidServiceReady.dispose() + disposeAll(disposables) + }, + stop: async (): Promise => { + if (!client || !client.needsStop()) return + await Promise.resolve(client.stop()) + }, + restart: async (): Promise => { + if (client) { + service.state = ServiceStat.Starting + client.restart() + } else { + await service.start() + } + }, + } + return this.regist(service) + } +} + +export function documentSelectorToLanguageIds(documentSelector: DocumentSelector): string[] { + let res = documentSelector.map(filter => { + if (typeof filter == 'string') { + return filter + } + return filter.language + }) + res = res.filter(s => typeof s == 'string') + return Array.from(new Set(res)) +} + +// convert config to options +export function getLanguageServerOptions(id: string, name: string, config: LanguageServerConfig): [LanguageClientOptions, ServerOptions] { + let { command, module, port, args, filetypes } = config + args = args || [] + if (!filetypes) { + window.showMessage(`Wrong configuration of LS "${name}", filetypes not found`, 'error') + return null + } + if (!command && !module && !port) { + window.showMessage(`Wrong configuration of LS "${name}", no command or module specified.`, 'error') + return null + } + let serverOptions: ServerOptions + if (module) { + module = workspace.expand(module) + if (!fs.existsSync(module)) { + window.showMessage(`Module file "${module}" not found for LS "${name}"`, 'error') + return null + } + serverOptions = { + module, + runtime: config.runtime || process.execPath, + args, + transport: getTransportKind(config), + options: getForkOptions(config) + } + } else if (command) { + serverOptions = { + command, + args, + options: getSpawnOptions(config) + } as Executable + } else if (port) { + serverOptions = () => new Promise((resolve, reject) => { + let client = new net.Socket() + let host = config.host || '127.0.0.1' + logger.info(`languageserver "${id}" connecting to ${host}:${port}`) + client.connect(port, host, () => { + resolve({ + reader: client, + writer: client + }) + }) + client.on('error', e => { + reject(new Error(`Connection error for ${id}: ${e.message}`)) + }) + }) + } + let disableWorkspaceFolders = !!config.disableWorkspaceFolders + let disableSnippetCompletion = !!config.disableSnippetCompletion + let ignoredRootPaths = config.ignoredRootPaths || [] + let clientOptions: LanguageClientOptions = { + ignoredRootPaths: ignoredRootPaths.map(s => workspace.expand(s)), + disableWorkspaceFolders, + disableSnippetCompletion, + disableDynamicRegister: !!config.disableDynamicRegister, + disableCompletion: !!config.disableCompletion, + disableDiagnostics: !!config.disableDiagnostics, + formatterPriority: config.formatterPriority || 0, + documentSelector: getDocumentSelector(config.filetypes, config.additionalSchemes), + revealOutputChannelOn: getRevealOutputChannelOn(config.revealOutputChannelOn), + synchronize: { + configurationSection: `${id}.settings` + }, + diagnosticCollectionName: name, + outputChannelName: id, + stdioEncoding: config.stdioEncoding || 'utf8', + progressOnInitialization: config.progressOnInitialization !== false, + initializationOptions: config.initializationOptions || {} + } + return [clientOptions, serverOptions] +} + +export function getRevealOutputChannelOn(revealOn: string | undefined): RevealOutputChannelOn { + switch (revealOn) { + case 'info': + return RevealOutputChannelOn.Info + case 'warn': + return RevealOutputChannelOn.Warn + case 'error': + return RevealOutputChannelOn.Error + case 'never': + return RevealOutputChannelOn.Never + default: + return RevealOutputChannelOn.Never + } +} + +export function getDocumentSelector(filetypes: string[] | undefined, additionalSchemes?: string[]): DocumentSelector { + let documentSelector: DocumentSelector = [] + let schemes = ['file', 'untitled'].concat(additionalSchemes || []) + if (!filetypes) return schemes.map(s => ({ scheme: s })) + filetypes.forEach(filetype => { + documentSelector.push(...schemes.map(scheme => ({ language: filetype, scheme }))) + }) + return documentSelector +} + +export function getTransportKind(config: LanguageServerConfig): Transport { + let { transport, transportPort } = config + if (!transport || transport == 'ipc') return TransportKind.ipc + if (transport == 'stdio') return TransportKind.stdio + if (transport == 'pipe') return TransportKind.pipe + return { kind: TransportKind.socket, port: transportPort } +} + +function getForkOptions(config: LanguageServerConfig): ForkOptions { + return { + cwd: config.cwd, + execArgv: config.execArgv || [], + env: config.env || undefined + } +} + +function getSpawnOptions(config: LanguageServerConfig): SpawnOptions { + return { + cwd: config.cwd, + detached: !!config.detached, + shell: !!config.shell, + env: config.env || undefined + } +} + +function stateString(state: State): string { + switch (state) { + case State.Running: + return 'running' + case State.Starting: + return 'starting' + case State.Stopped: + return 'stopped' + default: + return 'unknown' + } +} + +export default new ServiceManager() diff --git a/vim-config/plugins/coc.nvim/src/snippets/manager.ts b/vim-config/plugins/coc.nvim/src/snippets/manager.ts new file mode 100644 index 00000000..a7a1817a --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/snippets/manager.ts @@ -0,0 +1,152 @@ +import { Disposable, InsertTextMode, Range } from 'vscode-languageserver-protocol' +import events from '../events' +import { StatusBarItem } from '../model/status' +import workspace from '../workspace' +import window from '../window' +import * as Snippets from "./parser" +import { SnippetSession } from './session' +import { SnippetVariableResolver } from './variableResolve' +import { SnippetString } from './string' +const logger = require('../util/logger')('snippets-manager') + +export class SnippetManager { + private sessionMap: Map = new Map() + private disposables: Disposable[] = [] + private statusItem: StatusBarItem + + constructor() { + workspace.onDidChangeTextDocument(async e => { + let session = this.getSession(e.bufnr) + if (session) { + let firstLine = e.originalLines[e.contentChanges[0].range.start.line] || '' + await session.synchronizeUpdatedPlaceholders(e.contentChanges[0], firstLine) + } + }, null, this.disposables) + + workspace.onDidCloseTextDocument(textDocument => { + let doc = workspace.getDocument(textDocument.uri) + if (!doc) return + let session = this.getSession(doc.bufnr) + if (session) session.deactivate() + }, null, this.disposables) + + events.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.on('InsertEnter', async () => { + let { session } = this + if (!session) return + await session.checkPosition() + }, null, this.disposables) + } + + public init(): void { + let config = workspace.getConfiguration('coc.preferences') + this.statusItem = window.createStatusBarItem(0) + this.statusItem.text = config.get('snippetStatusText', 'SNIP') + } + + /** + * Insert snippet at current cursor position + */ + public async insertSnippet(snippet: string | SnippetString, select = true, range?: Range, insertTextMode?: InsertTextMode): Promise { + let { bufnr } = workspace + let session = this.getSession(bufnr) + if (!session) { + session = new SnippetSession(workspace.nvim, bufnr) + this.sessionMap.set(bufnr, session) + session.onCancel(() => { + this.sessionMap.delete(bufnr) + if (workspace.bufnr == bufnr) { + this.statusItem.hide() + } + }) + } + let snippetStr = SnippetString.isSnippetString(snippet) ? snippet.value : snippet + let isActive = await session.start(snippetStr, select, range, insertTextMode) + if (isActive) this.statusItem.show() + return isActive + } + + public async selectCurrentPlaceholder(triggerAutocmd = true): Promise { + let { session } = this + if (session) return await session.selectCurrentPlaceholder(triggerAutocmd) + } + + public async nextPlaceholder(): Promise { + let { session } = this + if (session) { + await session.nextPlaceholder() + } else { + workspace.nvim.call('coc#snippet#disable', [], true) + this.statusItem.hide() + } + return '' + } + + public async previousPlaceholder(): Promise { + let { session } = this + if (session) { + await session.previousPlaceholder() + } else { + workspace.nvim.call('coc#snippet#disable', [], true) + this.statusItem.hide() + } + return '' + } + + public cancel(): void { + let session = this.getSession(workspace.bufnr) + if (session) return session.deactivate() + workspace.nvim.call('coc#snippet#disable', [], true) + if (this.statusItem) this.statusItem.hide() + } + + public get session(): SnippetSession { + let session = this.getSession(workspace.bufnr) + return session && session.isActive ? session : null + } + + public isActived(bufnr: number): boolean { + let session = this.getSession(bufnr) + return session && session.isActive ? true : false + } + + public jumpable(): boolean { + let { session } = this + if (!session) return false + let placeholder = session.placeholder + if (placeholder && !placeholder.isFinalTabstop) { + return true + } + return false + } + + public getSession(bufnr: number): SnippetSession { + return this.sessionMap.get(bufnr) + } + + public async resolveSnippet(body: string): Promise { + let parser = new Snippets.SnippetParser() + const snippet = parser.parse(body, true) + const resolver = new SnippetVariableResolver() + await snippet.resolveVariables(resolver) + return snippet + } + + public dispose(): void { + this.cancel() + for (let d of this.disposables) { + d.dispose() + } + } +} + +export default new SnippetManager() diff --git a/vim-config/plugins/coc.nvim/src/snippets/parser.ts b/vim-config/plugins/coc.nvim/src/snippets/parser.ts new file mode 100644 index 00000000..7dc05631 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/snippets/parser.ts @@ -0,0 +1,1203 @@ +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CharCode } from '../util/charCode' +import { rangeParts } from '../util/string' +import { Range } from 'vscode-languageserver-protocol' +const logger = require('../util/logger')('snippets-parser') + +export const enum TokenType { + Dollar, + Colon, + Comma, + CurlyOpen, + CurlyClose, + Backslash, + Forwardslash, + Pipe, + Int, + VariableName, + Format, + Plus, + Dash, + QuestionMark, + EOF +} + +export interface Token { + type: TokenType + pos: number + len: number +} + +export class Scanner { + + private static _table: { [ch: number]: TokenType } = { + [CharCode.DollarSign]: TokenType.Dollar, + [CharCode.Colon]: TokenType.Colon, + [CharCode.Comma]: TokenType.Comma, + [CharCode.OpenCurlyBrace]: TokenType.CurlyOpen, + [CharCode.CloseCurlyBrace]: TokenType.CurlyClose, + [CharCode.Backslash]: TokenType.Backslash, + [CharCode.Slash]: TokenType.Forwardslash, + [CharCode.Pipe]: TokenType.Pipe, + [CharCode.Plus]: TokenType.Plus, + [CharCode.Dash]: TokenType.Dash, + [CharCode.QuestionMark]: TokenType.QuestionMark, + } + + public static isDigitCharacter(ch: number): boolean { + return ch >= CharCode.Digit0 && ch <= CharCode.Digit9 + } + + public static isVariableCharacter(ch: number): boolean { + return ch === CharCode.Underline + || (ch >= CharCode.a && ch <= CharCode.z) + || (ch >= CharCode.A && ch <= CharCode.Z) + } + + public value: string + public pos: number + + constructor() { + this.text('') + } + + public text(value: string): void { + this.value = value + this.pos = 0 + } + + public tokenText(token: Token): string { + return this.value.substr(token.pos, token.len) + } + + public next(): Token { + + if (this.pos >= this.value.length) { + return { type: TokenType.EOF, pos: this.pos, len: 0 } + } + + let pos = this.pos + let len = 0 + let ch = this.value.charCodeAt(pos) + let type: TokenType + + // static types + type = Scanner._table[ch] + if (typeof type === 'number') { + this.pos += 1 + return { type, pos, len: 1 } + } + + // number + if (Scanner.isDigitCharacter(ch)) { + type = TokenType.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 = TokenType.VariableName + do { + ch = this.value.charCodeAt(pos + (++len)) + } while (Scanner.isVariableCharacter(ch) || Scanner.isDigitCharacter(ch)) + + this.pos += len + return { type, pos, len } + } + + // format + type = TokenType.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 } + } +} + +export abstract class Marker { + + public readonly _markerBrand: any + + public parent: Marker + protected _children: Marker[] = [] + + public appendChild(child: Marker): this { + 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] as Text).value += child.value + } else { + // normal adoption of child + child.parent = this + this._children.push(child) + } + return this + } + + public setOnlyChild(child: Marker): void { + child.parent = this + this._children = [child] + } + + public replace(child: Marker, others: Marker[]): void { + 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: Marker[], parent: Marker): void { + for (const child of children) { + child.parent = parent + _fixParent(child.children, child) + } + })(others, parent) + } + + public get children(): Marker[] { + return this._children + } + + public get snippet(): TextmateSnippet | undefined { + // eslint-disable-next-line @typescript-eslint/no-this-alias + let candidate: Marker = this + // eslint-disable-next-line no-constant-condition + while (true) { + if (!candidate) { + return undefined + } + if (candidate instanceof TextmateSnippet) { + return candidate + } + candidate = candidate.parent + } + } + + public toString(): string { + return this.children.reduce((prev, cur) => prev + cur.toString(), '') + } + + public abstract toTextmateString(): string + + public len(): number { + return 0 + } + + public get next(): Marker | null { + let { parent } = this + let { children } = parent + let idx = children.indexOf(this) + return children[idx + 1] + } + + public abstract clone(): Marker +} + +export class Text extends Marker { + + public static escape(value: string): string { + return value.replace(/\$|}|\\/g, '\\$&') + } + + constructor(public value: string) { + super() + } + public toString(): string { + return this.value + } + + public toTextmateString(): string { + return Text.escape(this.value) + } + public len(): number { + return this.value.length + } + public clone(): Text { + return new Text(this.value) + } +} + +export abstract class TransformableMarker extends Marker { + public transform: Transform +} + +export class Placeholder extends TransformableMarker { + public static compareByIndex(a: Placeholder, b: Placeholder): number { + 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 + } + } + + constructor(public index: number) { + super() + } + + public get isFinalTabstop(): boolean { + return this.index === 0 + } + + public get choice(): Choice | undefined { + return this._children.length === 1 && this._children[0] instanceof Choice + ? this._children[0] as Choice + : undefined + } + + public toTextmateString(): string { + 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}}` + } + } + + public clone(): Placeholder { + let ret = new Placeholder(this.index) + if (this.transform) { + ret.transform = this.transform.clone() + } + ret._children = this.children.map(child => child.clone()) + return ret + } +} + +export class Choice extends Marker { + + public readonly options: Text[] = [] + + public appendChild(marker: Marker): this { + if (marker instanceof Text) { + marker.parent = this + this.options.push(marker) + } + return this + } + + public toString(): string { + return this.options[0].value + } + + public toTextmateString(): string { + return this.options + .map(option => option.value.replace(/\||,/g, '\\$&')) + .join(',') + } + + public len(): number { + return this.options[0].len() + } + + public clone(): Choice { + let ret = new Choice() + for (let opt of this.options) { + ret.appendChild(opt as any) + } + return ret + } +} + +export class Transform extends Marker { + + public regexp: RegExp + + public resolve(value: string): string { + 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 + } + + private _replace(groups: string[]): string { + 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 + } + + public toString(): string { + return '' + } + + public toTextmateString(): string { + return `/${this.regexp.source}/${this.children.map(c => c.toTextmateString())}/${(this.regexp.ignoreCase ? 'i' : '') + (this.regexp.global ? 'g' : '')}` + } + + public clone(): Transform { + 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 + } + +} + +export class FormatString extends Marker { + + constructor( + public readonly index: number, + public readonly shorthandName?: string, + public readonly ifValue?: string, + public readonly elseValue?: string, + ) { + super() + } + + public resolve(value: string): string { + 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 (!value && typeof this.elseValue === 'string') { + return this.elseValue + } else { + return value || '' + } + } + + private _toPascalCase(value: string): string { + const match = value.match(/[a-z]+/gi) + if (!match) { + return value + } + return match.map(word => word.charAt(0).toUpperCase() + + word.substr(1).toLowerCase()) + .join('') + } + + public toTextmateString(): string { + 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 + } + + public clone(): FormatString { + let ret = new FormatString(this.index, this.shorthandName, this.ifValue, this.elseValue) + return ret + } +} + +export class Variable extends TransformableMarker { + + constructor(public name: string) { + super() + } + + public async resolve(resolver: VariableResolver): Promise { + let value = await resolver.resolve(this) + if (value && value.includes('\n')) { + // get indent from previous texts + let indent = '' + this.snippet.walk(m => { + if (m == this) { + return false + } + if (m instanceof Text) { + let lines = m.toString().split(/\r?\n/) + indent = lines[lines.length - 1].match(/^\s*/)[0] + } + return true + }) + let lines = value.split('\n') + let indents = lines.filter(s => s.length > 0).map(s => s.match(/^\s*/)[0]) + let minIndent = indents.length == 0 ? '' : + indents.reduce((p, c) => p.length < c.length ? p : c) + let newLines = lines.map((s, i) => i == 0 || s.length == 0 || !s.startsWith(minIndent) ? s : + indent + s.slice(minIndent.length)) + value = newLines.join('\n') + } + if (this.transform) { + value = this.transform.resolve(value || '') + } + if (value !== undefined) { + this._children = [new Text(value) as any] + return true + } + return false + } + + public toTextmateString(): string { + 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}}` + } + } + + public clone(): Variable { + const ret = new Variable(this.name) + if (this.transform) { + ret.transform = this.transform.clone() + } + ret._children = this.children.map(child => child.clone()) + return ret + } +} + +export interface VariableResolver { + resolve(variable: Variable): Promise +} + +function walk(marker: Marker[], visitor: (marker: Marker) => boolean): void { + const stack = [...marker] + while (stack.length > 0) { + const marker = stack.shift() + const recurse = visitor(marker) + if (!recurse) { + break + } + stack.unshift(...marker.children) + } +} + +export class TextmateSnippet extends Marker { + + private _placeholders?: { all: Placeholder[]; last?: Placeholder } + private _variables?: Variable[] + + public get placeholderInfo(): { all: Placeholder[]; last?: Placeholder } { + if (!this._placeholders) { + this._variables = [] + // fill in placeholders + let all: Placeholder[] = [] + let last: Placeholder | undefined + this.walk(candidate => { + if (candidate instanceof Placeholder) { + all.push(candidate) + last = !last || last.index < candidate.index ? candidate : last + } else if (candidate instanceof Variable) { + let first = candidate.name.charCodeAt(0) + // not jumpover for uppercase variable. + if (first < 65 || first > 90) { + this._variables.push(candidate) + } + } + return true + }) + this._placeholders = { all, last } + } + return this._placeholders + } + + public get variables(): Variable[] { + return this._variables + } + + public get placeholders(): Placeholder[] { + const { all } = this.placeholderInfo + return all + } + + public get maxIndexNumber(): number { + let { placeholders } = this + return placeholders.reduce((curr, p) => Math.max(curr, p.index), 0) + } + + public get minIndexNumber(): number { + 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 + } + + public insertSnippet(snippet: string, id: number, range: Range): number { + let placeholder = this.placeholders[id] + if (!placeholder) return + let { index } = placeholder + let [before, after] = rangeParts(placeholder.toString(), range) + let nested = new SnippetParser().parse(snippet, true) + let maxIndexAdded = nested.maxIndexNumber + 1 + let indexes: number[] = [] + for (let p of nested.placeholders) { + if (p.isFinalTabstop) { + p.index = maxIndexAdded + index + } else { + p.index = p.index + index + } + indexes.push(p.index) + } + this.walk(m => { + if (m instanceof Placeholder && m.index > index) { + m.index = m.index + maxIndexAdded + } + return true + }) + let children = nested.children + if (before) children.unshift(new Text(before)) + if (after) children.push(new Text(after)) + this.replace(placeholder, children) + return Math.min.apply(null, indexes) + } + + public updatePlaceholder(id: number, val: string): void { + 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 + } + + public updateVariable(id: number, val: string): void { + const find = this.variables[id - this.maxIndexNumber - 1] + if (find) { + let variables = this.variables.filter(o => o.name == find.name) + for (let variable of variables) { + let newText = variable.transform ? variable.transform.resolve(val) : val + variable.setOnlyChild(new Text(newText)) + } + } + } + + /** + * newText after update with value + */ + public getPlaceholderText(id: number, value: string): string { + const placeholder = this.placeholders[id] + if (!placeholder) return value + return placeholder.transform ? placeholder.transform.resolve(value) : value + } + + public offset(marker: Marker): number { + 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 + } + + public fullLen(marker: Marker): number { + let ret = 0 + walk([marker], marker => { + ret += marker.len() + return true + }) + return ret + } + + public enclosingPlaceholders(placeholder: Placeholder): Placeholder[] { + let ret: Placeholder[] = [] + let { parent } = placeholder + while (parent) { + if (parent instanceof Placeholder) { + ret.push(parent) + } + parent = parent.parent + } + return ret + } + + public async resolveVariables(resolver: VariableResolver): Promise { + let items: Variable[] = [] + this.walk(candidate => { + if (candidate instanceof Variable) { + items.push(candidate) + } + return true + }) + await Promise.all(items.map(o => o.resolve(resolver))) + } + + public appendChild(child: Marker): this { + this._placeholders = undefined + return super.appendChild(child) + } + + public replace(child: Marker, others: Marker[]): void { + this._placeholders = undefined + return super.replace(child, others) + } + + public toTextmateString(): string { + return this.children.reduce((prev, cur) => prev + cur.toTextmateString(), '') + } + + public clone(): TextmateSnippet { + let ret = new TextmateSnippet() + this._children = this.children.map(child => child.clone()) + return ret + } + + public walk(visitor: (marker: Marker) => boolean): void { + walk(this.children, visitor) + } +} + +export class SnippetParser { + + public static escape(value: string): string { + return value.replace(/\$|}|\\/g, '\\$&') + } + + private _scanner = new Scanner() + private _token: Token + + public text(value: string): string { + return this.parse(value).toString() + } + + public parse(value: string, insertFinalTabstop?: boolean): TextmateSnippet { + + 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: Placeholder[] = [] + 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 + } + + private _accept(type?: TokenType): boolean + private _accept(type: TokenType | undefined, value: true): string + private _accept(type: TokenType, value?: boolean): boolean | string { + 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 + } + + private _backTo(token: Token): false { + this._scanner.pos = token.pos + token.len + this._token = token + return false + } + + private _until(type: TokenType): false | string { + if (this._token.type === TokenType.EOF) { + return false + } + let start = this._token + while (this._token.type !== type) { + this._token = this._scanner.next() + if (this._token.type === TokenType.EOF) { + return false + } + } + let value = this._scanner.value.substring(start.pos, this._token.pos) + this._token = this._scanner.next() + return value + } + + private _parse(marker: Marker): boolean { + return this._parseEscaped(marker) + || this._parseTabstopOrVariableName(marker) + || this._parseComplexPlaceholder(marker) + || this._parseComplexVariable(marker) + || this._parseAnything(marker) + } + + // \$, \\, \} -> just text + private _parseEscaped(marker: Marker): boolean { + let value: string + // eslint-disable-next-line no-cond-assign + if (value = this._accept(TokenType.Backslash, true)) { + // saw a backslash, append escaped token or that backslash + value = this._accept(TokenType.Dollar, true) + || this._accept(TokenType.CurlyClose, true) + || this._accept(TokenType.Backslash, true) + || value + + marker.appendChild(new Text(value)) + return true + } + return false + } + + // $foo -> variable, $1 -> tabstop + private _parseTabstopOrVariableName(parent: Marker): boolean { + let value: string + const token = this._token + const match = this._accept(TokenType.Dollar) + && (value = this._accept(TokenType.VariableName, true) || this._accept(TokenType.Int, true)) + + if (!match) { + return this._backTo(token) + } + + parent.appendChild(/^\d+$/.test(value) + ? new Placeholder(Number(value)) + : new Variable(value) + ) + return true + } + + // ${1:}, ${1} -> placeholder + private _parseComplexPlaceholder(parent: Marker): boolean { + let index: string + const token = this._token + const match = this._accept(TokenType.Dollar) + && this._accept(TokenType.CurlyOpen) + && (index = this._accept(TokenType.Int, true)) + + if (!match) { + return this._backTo(token) + } + + const placeholder = new Placeholder(Number(index)) + + if (this._accept(TokenType.Colon)) { + // ${1:} + // eslint-disable-next-line no-constant-condition + while (true) { + + // ...} -> done + if (this._accept(TokenType.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(TokenType.Pipe)) { + // ${1|one,two,three|} + const choice = new Choice() + + // eslint-disable-next-line no-constant-condition + while (true) { + if (this._parseChoiceElement(choice)) { + + if (this._accept(TokenType.Comma)) { + // opt, -> more + continue + } + + if (this._accept(TokenType.Pipe)) { + placeholder.appendChild(choice) + if (this._accept(TokenType.CurlyClose)) { + // ..|} -> done + parent.appendChild(placeholder) + return true + } + } + } + + this._backTo(token) + return false + } + + } else if (this._accept(TokenType.Forwardslash)) { + // ${1///} + if (this._parseTransform(placeholder)) { + parent.appendChild(placeholder) + return true + } + + this._backTo(token) + return false + + } else if (this._accept(TokenType.CurlyClose)) { + // ${1} + parent.appendChild(placeholder) + return true + + } else { + // ${1 <- missing curly or colon + return this._backTo(token) + } + } + + private _parseChoiceElement(parent: Choice): boolean { + const token = this._token + const values: string[] = [] + + // eslint-disable-next-line no-constant-condition + while (true) { + if (this._token.type === TokenType.Comma || this._token.type === TokenType.Pipe) { + break + } + let value: string + // eslint-disable-next-line no-cond-assign + if (value = this._accept(TokenType.Backslash, true)) { + // \, \|, or \\ + value = this._accept(TokenType.Comma, true) + || this._accept(TokenType.Pipe, true) + || this._accept(TokenType.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:}, ${foo} -> variable + private _parseComplexVariable(parent: Marker): boolean { + let name: string + const token = this._token + const match = this._accept(TokenType.Dollar) + && this._accept(TokenType.CurlyOpen) + && (name = this._accept(TokenType.VariableName, true)) + + if (!match) { + return this._backTo(token) + } + + const variable = new Variable(name) + if (this._accept(TokenType.Colon)) { + // ${foo:} + // eslint-disable-next-line no-constant-condition + while (true) { + + // ...} -> done + if (this._accept(TokenType.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(TokenType.Forwardslash)) { + // ${foo///} + if (this._parseTransform(variable)) { + parent.appendChild(variable) + return true + } + + this._backTo(token) + return false + + } else if (this._accept(TokenType.CurlyClose)) { + // ${foo} + parent.appendChild(variable) + return true + + } else { + // ${foo <- missing curly or colon + return this._backTo(token) + } + } + + private _parseTransform(parent: TransformableMarker): boolean { + // ...//} + + let transform = new Transform() + let regexValue = '' + let regexOptions = '' + + // (1) /regex + // eslint-disable-next-line no-constant-condition + while (true) { + if (this._accept(TokenType.Forwardslash)) { + break + } + + let escaped: string + // eslint-disable-next-line no-cond-assign + if (escaped = this._accept(TokenType.Backslash, true)) { + escaped = this._accept(TokenType.Forwardslash, true) || escaped + regexValue += escaped + continue + } + + if (this._token.type !== TokenType.EOF) { + regexValue += this._accept(undefined, true) + continue + } + return false + } + + // (2) /format + // eslint-disable-next-line no-constant-condition + while (true) { + if (this._accept(TokenType.Forwardslash)) { + break + } + + let escaped: string + // eslint-disable-next-line no-cond-assign + if (escaped = this._accept(TokenType.Backslash, true)) { + escaped = this._accept(TokenType.Forwardslash, true) || escaped + transform.appendChild(new Text(escaped)) + continue + } + if (this._parseFormatString(transform) || this._parseAnything(transform)) { + let text = transform.children[0] as Text + if (text && text.value && text.value.includes('\\n')) { + text.value = text.value.replace(/\\n/g, '\n') + } + continue + } + return false + } + + // (3) /option + // eslint-disable-next-line no-constant-condition + while (true) { + if (this._accept(TokenType.CurlyClose)) { + break + } + if (this._token.type !== TokenType.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 + } + + private _parseFormatString(parent: Transform): boolean { + + const token = this._token + if (!this._accept(TokenType.Dollar)) { + return false + } + + let complex = false + if (this._accept(TokenType.CurlyOpen)) { + complex = true + } + + let index = this._accept(TokenType.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(TokenType.CurlyClose)) { + // ${1} + parent.appendChild(new FormatString(Number(index))) + return true + + } else if (!this._accept(TokenType.Colon)) { + this._backTo(token) + return false + } + + if (this._accept(TokenType.Forwardslash)) { + // ${1:/upcase} + let shorthand = this._accept(TokenType.VariableName, true) + if (!shorthand || !this._accept(TokenType.CurlyClose)) { + this._backTo(token) + return false + } else { + parent.appendChild(new FormatString(Number(index), shorthand)) + return true + } + + } else if (this._accept(TokenType.Plus)) { + // ${1:+} + let ifValue = this._until(TokenType.CurlyClose) + if (ifValue) { + parent.appendChild(new FormatString(Number(index), undefined, ifValue, undefined)) + return true + } + + } else if (this._accept(TokenType.Dash)) { + // ${2:-} + let elseValue = this._until(TokenType.CurlyClose) + if (elseValue) { + parent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue)) + return true + } + + } else if (this._accept(TokenType.QuestionMark)) { + // ${2:?:} + let ifValue = this._until(TokenType.Colon) + if (ifValue) { + let elseValue = this._until(TokenType.CurlyClose) + if (elseValue) { + parent.appendChild(new FormatString(Number(index), undefined, ifValue, elseValue)) + return true + } + } + + } else { + // ${1:} + let elseValue = this._until(TokenType.CurlyClose) + if (elseValue) { + parent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue)) + return true + } + } + + this._backTo(token) + return false + } + + private _parseAnything(marker: Marker): boolean { + if (this._token.type !== TokenType.EOF) { + let text = this._scanner.tokenText(this._token) + marker.appendChild(new Text(text)) + this._accept(undefined) + return true + } + return false + } +} diff --git a/vim-config/plugins/coc.nvim/src/snippets/session.ts b/vim-config/plugins/coc.nvim/src/snippets/session.ts new file mode 100644 index 00000000..0cc9f27b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/snippets/session.ts @@ -0,0 +1,331 @@ +import { Neovim } from '@chemzqm/neovim' +import { FormattingOptions } from 'jsonc-parser' +import { Emitter, Event, InsertTextMode, Range, TextDocumentContentChangeEvent, TextEdit } from 'vscode-languageserver-protocol' +import completion from '../completion' +import Document from '../model/document' +import { comparePosition, isSingleLine, positionInRange, rangeInRange } from '../util/position' +import { byteLength, characterIndex } from '../util/string' +import workspace from '../workspace' +import window from '../window' +import events from '../events' +import { CocSnippet, CocSnippetPlaceholder } from "./snippet" +import { SnippetVariableResolver } from "./variableResolve" +import { singleLineEdit } from '../util/textedit' +const logger = require('../util/logger')('snippets-session') + +export class SnippetSession { + private _isActive = false + private _currId = 0 + // Get state of line where we inserted + private applying = false + private preferComplete = false + private _snippet: CocSnippet = null + private _onCancelEvent = new Emitter() + public readonly onCancel: Event = this._onCancelEvent.event + + constructor(private nvim: Neovim, public readonly bufnr: number) { + let suggest = workspace.getConfiguration('suggest') + this.preferComplete = suggest.get('preferCompleteThanJumpPlaceholder', false) + } + + public async start(snippetString: string, select = true, range?: Range, insertTextMode?: InsertTextMode): Promise { + const { document } = this + if (!document || !document.attached) return false + void events.fire('InsertSnippet', []) + if (!range) { + let position = await window.getCursorPosition() + range = Range.create(position, position) + } + let position = range.start + const formatOptions = await workspace.getFormatOptions(this.document.uri) + await document.patchChange(true) + const currentLine = document.getline(position.line) + const currentIndent = currentLine.match(/^\s*/)[0] + let inserted = '' + if (insertTextMode === InsertTextMode.asIs) { + inserted = snippetString + } else { + inserted = normalizeSnippetString(snippetString, currentIndent, formatOptions) + } + const resolver = new SnippetVariableResolver() + const snippet = new CocSnippet(inserted, position, resolver) + await snippet.init() + const edit = 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 + } + this.applying = true + await document.applyEdits([edit]) + this.applying = false + if (this._isActive) { + // find valid placeholder + 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 + } + } + if (snippet.isPlainText) { + this.deactivate() + let placeholder = snippet.finalPlaceholder + await window.moveTo(placeholder.range.start) + return false + } + // new snippet + this._snippet = snippet + this._currId = snippet.firstPlaceholder.id + if (select) await this.selectPlaceholder(snippet.firstPlaceholder) + this.activate() + return true + } + + private activate(): void { + if (this._isActive) return + this._isActive = true + this.nvim.call('coc#snippet#enable', [], true) + } + + public deactivate(): void { + 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() + } + + public get isActive(): boolean { + return this._isActive + } + + public async nextPlaceholder(): Promise { + if (!this.isActive) return + await this.document.patchChange() + let curr = this.placeholder + let next = this.snippet.getNextPlaceholder(curr.index) + await this.selectPlaceholder(next) + } + + public async previousPlaceholder(): Promise { + if (!this.isActive) return + await this.document.patchChange() + let curr = this.placeholder + let prev = this.snippet.getPrevPlaceholder(curr.index) + await this.selectPlaceholder(prev) + } + + public async synchronizeUpdatedPlaceholders(change: TextDocumentContentChangeEvent, changedLine?: string): Promise { + if (!this.isActive || !this.document || this.applying) return + let edit: TextEdit = { range: (change as any).range, newText: change.text } + let { snippet } = this + // change outside range + let adjusted = snippet.adjustTextEdit(edit, changedLine) + if (adjusted) return + let currRange = this.placeholder.range + if (changedLine != null + && singleLineEdit(edit) + && !rangeInRange(edit.range, currRange) + && isSingleLine(currRange) + && changedLine.slice(currRange.start.character, currRange.end.character) == this.placeholder.value + && events.cursor + && events.cursor.bufnr == this.bufnr + && events.cursor.lnum == edit.range.start.line + 1) { + let col = events.cursor.col + // split changedLine with currRange + let preText = changedLine.slice(0, currRange.start.character) + let postText = changedLine.slice(currRange.end.character) + let newLine = this.document.getline(edit.range.start.line) + if (newLine.startsWith(preText) && newLine.endsWith(postText)) { + let endCharacter = newLine.length - postText.length + let cursorIdx = characterIndex(newLine, col - 1) + // make sure cursor in range + if (cursorIdx >= preText.length && cursorIdx <= endCharacter) { + let newText = newLine.slice(preText.length, endCharacter) + edit = TextEdit.replace(currRange, newText) + } + } + } + if (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 && snippet.finalCount <= 1) { + 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.applying = true + await this.document.applyEdits(edits) + this.applying = false + if (delta) { + await this.nvim.call('coc#cursor#move_by_col', delta) + } + } + + public async selectCurrentPlaceholder(triggerAutocmd = true): Promise { + let placeholder = this.snippet.getPlaceholderById(this._currId) + if (placeholder) await this.selectPlaceholder(placeholder, triggerAutocmd) + } + + public async selectPlaceholder(placeholder: CocSnippetPlaceholder, triggerAutocmd = true): Promise { + let { nvim, document } = this + if (!document || !placeholder) return + let { start, end } = placeholder.range + const len = end.character - start.character + const col = 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]) + if (triggerAutocmd) nvim.call('coc#util#do_autocmd', ['CocJumpPlaceholder'], true) + } else { + await this.select(placeholder, triggerAutocmd) + } + } + + private async select(placeholder: CocSnippetPlaceholder, triggerAutocmd = true): Promise { + let { range, value, isFinalTabstop } = placeholder + 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 ? byteLength(line.slice(0, start.character)) : 0 + let endLine = document.getline(end.line) + let endCol = endLine ? byteLength(endLine.slice(0, end.character)) : 0 + nvim.setVar('coc_last_placeholder', { + bufnr: document.bufnr, + current_text: value, + start: { line: start.line, col, character: start.character }, + end: { line: end.line, col: endCol, character: end.character } + }, true) + let [ve, selection, pumvisible, mode] = await nvim.eval('[&virtualedit, &selection, pumvisible(), mode()]') as [string, string, number, string] + let move_cmd = '' + if (pumvisible && this.preferComplete) { + let pre = completion.hasSelected() ? '' : '\\' + await nvim.eval(`feedkeys("${pre}\\", 'in')`) + return + } + // create move cmd + if (mode != 'n') move_cmd += "\\" + if (len == 0) { + if (col == 0 || (!mode.startsWith('i') && col < 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\\` + } + if (mode == 'i' && move_cmd == "\\a") { + move_cmd = '' + } + nvim.pauseNotification() + nvim.setOption('virtualedit', 'onemore', true) + nvim.call('cursor', [start.line + 1, col + (move_cmd == 'a' ? 0 : 1)], true) + if (move_cmd) { + nvim.call('eval', [`feedkeys("${move_cmd}", 'in')`], true) + } + if (mode == 'i') { + nvim.call('coc#_cancel', [], true) + } + nvim.setOption('virtualedit', ve, true) + if (isFinalTabstop) { + if (this.snippet.finalCount == 1) { + logger.info('Jump to final placeholder, cancelling snippet session') + this.deactivate() + } else { + nvim.call('coc#snippet#disable', [], true) + } + } + if (workspace.env.isVim) nvim.command('redraw', true) + await nvim.resumeNotification() + if (triggerAutocmd) nvim.call('coc#util#do_autocmd', ['CocJumpPlaceholder'], true) + } + + private async getVirtualCol(line: number, col: number): Promise { + let { nvim } = this + return await nvim.eval(`virtcol([${line}, ${col}])`) as number + } + + public async checkPosition(): Promise { + if (!this.isActive) return + let position = await window.getCursorPosition() + if (this.snippet && positionInRange(position, this.snippet.range) != 0) { + logger.info('Cursor insert out of range, cancelling snippet session') + this.deactivate() + } + } + + public findPlaceholder(range: Range): CocSnippetPlaceholder | null { + if (!this.snippet) return null + let { placeholder } = this + if (placeholder && rangeInRange(range, placeholder.range)) return placeholder + return this.snippet.getPlaceholderByRange(range) || null + } + + public get placeholder(): CocSnippetPlaceholder { + if (!this.snippet) return null + return this.snippet.getPlaceholderById(this._currId) + } + + public get snippet(): CocSnippet { + return this._snippet + } + + private get document(): Document { + return workspace.getDocument(this.bufnr) + } +} + +export function normalizeSnippetString(snippet: string, indent: string, opts: FormattingOptions): string { + 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') +} diff --git a/vim-config/plugins/coc.nvim/src/snippets/snippet.ts b/vim-config/plugins/coc.nvim/src/snippets/snippet.ts new file mode 100644 index 00000000..e38824b6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/snippets/snippet.ts @@ -0,0 +1,264 @@ +import { Position, Range, TextEdit } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { adjustPosition, comparePosition, editRange, getChangedPosition, rangeInRange, isSingleLine } from '../util/position' +import * as Snippets from "./parser" +import { VariableResolver } from './parser' +import { byteLength } from '../util/string' +const logger = require('../util/logger')('snippets-snipet') + +export interface CocSnippetPlaceholder { + index: number + id: number // unique index + line: number + // range in current buffer + range: Range + value: string + isFinalTabstop: boolean + transform: boolean + isVariable: boolean + choice?: string[] +} + +export class CocSnippet { + private _parser: Snippets.SnippetParser = new Snippets.SnippetParser() + private _placeholders: CocSnippetPlaceholder[] + private tmSnippet: Snippets.TextmateSnippet + + constructor(private _snippetString: string, + private position: Position, + private _variableResolver?: VariableResolver) { + } + + public async init(): Promise { + const snippet = this._parser.parse(this._snippetString, true) + let { _variableResolver } = this + if (_variableResolver) { + await snippet.resolveVariables(_variableResolver) + } + this.tmSnippet = snippet + this.update() + } + + public adjustPosition(characterCount: number, lineCount: number): void { + let { line, character } = this.position + this.position = { + line: line + lineCount, + character: character + characterCount + } + this.update() + } + + // adjust for edit before snippet + public adjustTextEdit(edit: TextEdit, changedLine?: string): boolean { + let { range, newText } = edit + if (comparePosition(this.range.start, range.end) < 0) { + let { start, end } = range + let overlaped = end.character - this.range.start.character + // shift single line range to left as far as possible + if (changedLine && comparePosition(this.range.start, start) > 0 + && isSingleLine(range) + && start.character - overlaped >= 0 + && changedLine.slice(start.character - overlaped, start.character) == + changedLine.slice(this.range.start.character, this.range.start.character + overlaped)) { + edit.range = range = Range.create(start.line, start.character - overlaped, end.line, end.character - overlaped) + } else { + return false + } + } + + // check change of placeholder at beginning + if (!newText.includes('\n') + && comparePosition(range.start, range.end) == 0 + && comparePosition(this.range.start, range.start) == 0) { + let idx = this._placeholders.findIndex(o => comparePosition(o.range.start, range.start) == 0) + if (idx !== -1) return false + } + let changed = getChangedPosition(this.range.start, edit) + if (changed.line == 0 && changed.character == 0) return true + this.adjustPosition(changed.character, changed.line) + return true + } + + public get isPlainText(): boolean { + if (this._placeholders.length > 1) return false + return this._placeholders.every(o => o.value == '') + } + + public get finalCount(): number { + return this._placeholders.filter(o => o.isFinalTabstop).length + } + + public toString(): string { + return this.tmSnippet.toString() + } + + public get range(): Range { + let { position } = this + const content = this.tmSnippet.toString() + const doc = 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 Range.create(position, Position.create(position.line + pos.line, end)) + } + + public get firstPlaceholder(): CocSnippetPlaceholder | null { + let index = 0 + for (let p of this._placeholders) { + if (p.index == 0) continue + if (index == 0 || p.index < index) { + index = p.index + } + } + return this.getPlaceholder(index) + } + + public get lastPlaceholder(): CocSnippetPlaceholder { + let index = 0 + for (let p of this._placeholders) { + if (index == 0 || p.index > index) { + index = p.index + } + } + return this.getPlaceholder(index) + } + + public getPlaceholderById(id: number): CocSnippetPlaceholder { + return this._placeholders.find(o => o.id == id) + } + + public getPlaceholder(index: number): CocSnippetPlaceholder { + let placeholders = this._placeholders.filter(o => o.index == index) + let filtered = placeholders.filter(o => !o.transform) + return filtered.length ? filtered[0] : placeholders[0] + } + + public getPrevPlaceholder(index: number): CocSnippetPlaceholder { + if (index == 0) return this.lastPlaceholder + let prev = this.getPlaceholder(index - 1) + if (!prev) return this.getPrevPlaceholder(index - 1) + return prev + } + + public getNextPlaceholder(index: number): CocSnippetPlaceholder { + let indexes = this._placeholders.map(o => o.index) + let max = Math.max.apply(null, indexes) + if (index >= max) return this.finalPlaceholder + let next = this.getPlaceholder(index + 1) + if (!next) return this.getNextPlaceholder(index + 1) + return next + } + + public get finalPlaceholder(): CocSnippetPlaceholder { + return this._placeholders.find(o => o.isFinalTabstop) + } + + public getPlaceholderByRange(range: Range): CocSnippetPlaceholder { + return this._placeholders.find(o => rangeInRange(range, o.range)) + } + + public insertSnippet(placeholder: CocSnippetPlaceholder, snippet: string, range: Range): number { + let { start } = placeholder.range + // let offset = position.character - start.character + let editStart = Position.create( + range.start.line - start.line, + range.start.line == start.line ? range.start.character - start.character : range.start.character + ) + let editEnd = Position.create( + range.end.line - start.line, + range.end.line == start.line ? range.end.character - start.character : range.end.character + ) + let editRange = 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 + public updatePlaceholder(placeholder: CocSnippetPlaceholder, edit: TextEdit): { edits: TextEdit[]; delta: number } { + // let { start, end } = edit.range + let { range } = this + let { value, id, index } = placeholder + let newText = editRange(placeholder.range, value, edit) + let delta = 0 + if (!newText.includes('\n')) { + 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 + byteLength(text) - byteLength(p.value) + } + } + } + if (placeholder.isVariable) { + this.tmSnippet.updateVariable(id, newText) + } else { + this.tmSnippet.updatePlaceholder(id, newText) + } + let endPosition = adjustPosition(range.end, edit) + let snippetEdit: TextEdit = { + range: Range.create(range.start, endPosition), + newText: this.tmSnippet.toString() + } + this.update() + return { edits: [snippetEdit], delta } + } + + private update(): void { + const snippet = this.tmSnippet + const { line, character } = this.position + const document = TextDocument.create('untitled:/1', 'snippet', 0, snippet.toString()) + const { placeholders, variables, maxIndexNumber } = snippet + const variableIndexMap: Map = new Map() + let variableIndex = maxIndexNumber + 1 + + this._placeholders = [...placeholders, ...variables].map((p, idx) => { + const offset = snippet.offset(p) + const position = document.positionAt(offset) + const start: Position = { + line: line + position.line, + character: position.line == 0 ? character + position.character : position.character + } + let index: number + if (p instanceof Snippets.Variable) { + let key = p.name + if (variableIndexMap.has(key)) { + index = variableIndexMap.get(key) + } else { + variableIndexMap.set(key, variableIndex) + index = variableIndex + variableIndex = variableIndex + 1 + } + // variableIndex = variableIndex + 1 + } else { + index = p.index + } + const value = p.toString() + const lines = value.split(/\r?\n/) + let res: CocSnippetPlaceholder = { + range: 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, + value, + isVariable: p instanceof Snippets.Variable, + isFinalTabstop: (p as Snippets.Placeholder).index === 0 + } + Object.defineProperty(res, 'snippet', { + enumerable: false + }) + if (p instanceof Snippets.Placeholder && p.choice) { + let { options } = p.choice + if (options && options.length) { + res.choice = options.map(o => o.value) + } + } + return res + }) + } +} diff --git a/vim-config/plugins/coc.nvim/src/snippets/string.ts b/vim-config/plugins/coc.nvim/src/snippets/string.ts new file mode 100644 index 00000000..f1f26207 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/snippets/string.ts @@ -0,0 +1,102 @@ +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export class SnippetString { + public static isSnippetString(thing: any): thing is SnippetString { + if (thing instanceof SnippetString) { + return true + } + if (!thing) { + return false + } + return typeof thing.value === 'string' + } + + private static _escape(value: string): string { + return value.replace(/\$|}|\\/g, '\\$&') + } + + private _tabstop = 1 + + public value: string + + constructor(value?: string) { + this.value = value || '' + } + + public appendText(str: string): SnippetString { + this.value += SnippetString._escape(str) + return this + } + + public appendTabstop(num: number = this._tabstop++): SnippetString { + this.value += '$' + this.value += num + return this + } + + public appendPlaceholder( + value: string | ((snippet: SnippetString) => any), + num: number = this._tabstop++ + ): SnippetString { + if (typeof value === 'function') { + const nested = new SnippetString() + nested._tabstop = this._tabstop + value(nested) + this._tabstop = nested._tabstop + value = nested.value + } else { + value = SnippetString._escape(value) + } + + this.value += '${' + this.value += num + this.value += ':' + this.value += value + this.value += '}' + + return this + } + + public appendChoice( + values: string[], + num: number = this._tabstop++ + ): SnippetString { + const value = values.map(s => s.replace(/\$|}|\\|,/g, '\\$&')).join(',') + + this.value += '${' + this.value += num + this.value += '|' + this.value += value + this.value += '|}' + + return this + } + + public appendVariable( + name: string, + defaultValue?: string | ((snippet: SnippetString) => any) + ): SnippetString { + if (typeof defaultValue === 'function') { + const nested = new SnippetString() + nested._tabstop = this._tabstop + defaultValue(nested) + this._tabstop = nested._tabstop + defaultValue = nested.value + } else if (typeof defaultValue === 'string') { + defaultValue = defaultValue.replace(/\$|}/g, '\\$&') + } + + this.value += '${' + this.value += name + if (defaultValue) { + this.value += ':' + this.value += defaultValue + } + this.value += '}' + + return this + } +} diff --git a/vim-config/plugins/coc.nvim/src/snippets/variableResolve.ts b/vim-config/plugins/coc.nvim/src/snippets/variableResolve.ts new file mode 100644 index 00000000..f04cb671 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/snippets/variableResolve.ts @@ -0,0 +1,94 @@ +import path from 'path' +import window from '../window' +import { Variable, VariableResolver } from "./parser" +const logger = require('../util/logger')('snippets-variable') + +export class SnippetVariableResolver implements VariableResolver { + private _variableToValue: { [key: string]: string } = {} + + constructor() { + const currentDate = new Date() + Object.assign(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" }), + TM_FILENAME: null, + TM_FILENAME_BASE: null, + TM_DIRECTORY: null, + TM_FILEPATH: null, + YANK: null, + TM_LINE_INDEX: null, + TM_LINE_NUMBER: null, + TM_CURRENT_LINE: null, + TM_CURRENT_WORD: null, + TM_SELECTED_TEXT: null, + CLIPBOARD: null + }) + } + + private async resolveValue(name: string): Promise { + let { nvim } = window + if (['TM_FILENAME', 'TM_FILENAME_BASE', 'TM_DIRECTORY', 'TM_FILEPATH'].includes(name)) { + let filepath = await nvim.eval('expand("%:p")') as string + if (name == 'TM_FILENAME') return path.basename(filepath) + if (name == 'TM_FILENAME_BASE') return path.basename(filepath, path.extname(filepath)) + if (name == 'TM_DIRECTORY') return path.dirname(filepath) + if (name == 'TM_FILEPATH') return filepath + } + if (name == 'YANK') { + let yank = await nvim.call('getreg', ['""']) as string + return yank + } + if (name == 'TM_LINE_INDEX') { + let lnum = await nvim.call('line', ['.']) as number + return (lnum - 1).toString() + } + if (name == 'TM_LINE_NUMBER') { + let lnum = await nvim.call('line', ['.']) as number + return lnum.toString() + } + if (name == 'TM_CURRENT_LINE') { + let line = await nvim.call('getline', ['.']) as string + return line + } + if (name == 'TM_CURRENT_WORD') { + let word = await nvim.eval(`expand('')`) as string + return word + } + if (name == 'TM_SELECTED_TEXT') { + let text = await nvim.eval(`get(g:,'coc_selected_text', '')`) as string + return text + } + if (name == 'CLIPBOARD') { + return await nvim.eval('@*') as string + } + } + + public async resolve(variable: Variable): Promise { + const name = variable.name + let resolved = this._variableToValue[name] + if (resolved != null) return resolved.toString() + // resolve value from vim + let value = await this.resolveValue(name) + if (value) return value + // use default value when resolved is undefined + if (variable.children && variable.children.length) { + return variable.toString() + } + if (!this._variableToValue.hasOwnProperty(name)) { + return name + } + return '' + } +} diff --git a/vim-config/plugins/coc.nvim/src/sources/index.ts b/vim-config/plugins/coc.nvim/src/sources/index.ts new file mode 100644 index 00000000..afb8ac7b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/sources/index.ts @@ -0,0 +1,428 @@ +import { Neovim } from '@chemzqm/neovim' +import fastDiff from 'fast-diff' +import fs from 'fs' +import path from 'path' +import util from 'util' +import { CompletionItemKind, Disposable, DocumentSelector } from 'vscode-languageserver-protocol' +import events from '../events' +import extensions from '../extensions' +import { CompletionItemProvider } from '../provider' +import { CompleteOption, ExtendedCompleteItem, ISource, SourceConfig, SourceStat, SourceType } from '../types' +import { disposeAll, getUri } from '../util' +import { statAsync } from '../util/fs' +import { score } from '../util/match' +import { isEmpty } from '../util/object' +import { byteSlice } from '../util/string' +import window from '../window' +import workspace from '../workspace' +import Source from './source' +import LanguageSource, { CompleteConfig } from './source-language' +import VimSource from './source-vim' +const logger = require('../util/logger')('sources') + +export class Sources { + private sourceMap: Map = new Map() + private disposables: Disposable[] = [] + private remoteSourcePaths: string[] = [] + private completeConfig: CompleteConfig + + public init(): void { + this.loadCompleteConfig() + workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('suggest')) { + this.loadCompleteConfig() + } + }, null, this.disposables) + this.createNativeSources() + this.createRemoteSources() + events.on('BufEnter', this.onDocumentEnter, this, this.disposables) + workspace.watchOption('runtimepath', async (oldValue, newValue) => { + let result = fastDiff(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) + } + + private loadCompleteConfig(): void { + let suggest = workspace.getConfiguration('suggest') + let labels = suggest.get<{ [key: string]: string }>('completionItemKindLabels', {}) + let map = new Map([ + [CompletionItemKind.Text, labels['text'] || 'v'], + [CompletionItemKind.Method, labels['method'] || 'f'], + [CompletionItemKind.Function, labels['function'] || 'f'], + [CompletionItemKind.Constructor, typeof labels['constructor'] == 'function' ? 'f' : labels['con' + 'structor']], + [CompletionItemKind.Field, labels['field'] || 'm'], + [CompletionItemKind.Variable, labels['variable'] || 'v'], + [CompletionItemKind.Class, labels['class'] || 'C'], + [CompletionItemKind.Interface, labels['interface'] || 'I'], + [CompletionItemKind.Module, labels['module'] || 'M'], + [CompletionItemKind.Property, labels['property'] || 'm'], + [CompletionItemKind.Unit, labels['unit'] || 'U'], + [CompletionItemKind.Value, labels['value'] || 'v'], + [CompletionItemKind.Enum, labels['enum'] || 'E'], + [CompletionItemKind.Keyword, labels['keyword'] || 'k'], + [CompletionItemKind.Snippet, labels['snippet'] || 'S'], + [CompletionItemKind.Color, labels['color'] || 'v'], + [CompletionItemKind.File, labels['file'] || 'F'], + [CompletionItemKind.Reference, labels['reference'] || 'r'], + [CompletionItemKind.Folder, labels['folder'] || 'F'], + [CompletionItemKind.EnumMember, labels['enumMember'] || 'm'], + [CompletionItemKind.Constant, labels['constant'] || 'v'], + [CompletionItemKind.Struct, labels['struct'] || 'S'], + [CompletionItemKind.Event, labels['event'] || 'E'], + [CompletionItemKind.Operator, labels['operator'] || 'O'], + [CompletionItemKind.TypeParameter, labels['typeParameter'] || 'T'], + ]) + let floatEnable = suggest.get('floatEnable', true) + let detailField = suggest.get('detailField', 'preview') + if (detailField == 'preview' && (!floatEnable || !workspace.floatSupported)) { + detailField = 'menu' + } + this.completeConfig = Object.assign(this.completeConfig || {}, { + labels: map, + floatEnable, + detailField, + defaultKindText: labels['default'] || '', + priority: suggest.get('languageSourcePriority', 99), + echodocSupport: suggest.get('echodocSupport', false), + snippetsSupport: suggest.get('snippetsSupport', true), + detailMaxLength: suggest.get('detailMaxLength', 100), + invalidInsertCharacters: suggest.get('invalidInsertCharacters', ['(', '<', '{', '[', '\r', '\n']), + }) + } + + private get nvim(): Neovim { + return workspace.nvim + } + + private createNativeSources(): void { + try { + this.disposables.push((require('./native/around')).regist(this.sourceMap)) + this.disposables.push((require('./native/buffer')).regist(this.sourceMap)) + this.disposables.push((require('./native/file')).regist(this.sourceMap)) + } catch (e) { + console.error('Create source error:' + e.message) + } + } + + public createLanguageSource( + name: string, + shortcut: string, + selector: DocumentSelector | null, + provider: CompletionItemProvider, + triggerCharacters: string[], + priority?: number | undefined, + allCommitCharacters?: string[] + ): Disposable { + let source = new LanguageSource( + name, + shortcut, + provider, + selector, + triggerCharacters || [], + allCommitCharacters || [], + priority, + this.completeConfig) + logger.debug('created service source', name) + this.sourceMap.set(name, source) + return { + dispose: () => { + this.sourceMap.delete(name) + } + } + } + + private async createVimSourceExtension(nvim: Neovim, filepath: string): Promise { + let name = path.basename(filepath, '.vim') + try { + await nvim.command(`source ${filepath}`) + let fns = await nvim.call('coc#util#remote_fns', name) as string[] + for (let fn of ['init', 'complete']) { + if (!fns.includes(fn)) { + window.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 VimSource({ + name, + filepath, + sourceType: SourceType.Remote, + optionalFns: fns.filter(n => !['init', 'complete'].includes(n)) + }) + let isActive = false + let extension: any = { + id: packageJSON.name, + packageJSON, + exports: void 0, + extensionPath: filepath, + activate: () => { + isActive = true + this.addSource(source) + return Promise.resolve() + } + } + Object.defineProperty(extension, 'isActive', { + get: () => isActive + }) + extensions.registerExtension(extension, () => { + isActive = false + this.removeSource(source) + }) + } catch (e) { + window.showMessage(`Error on create vim source ${name}: ${e.message}`, 'error') + } + } + + private createRemoteSources(): void { + let { runtimepath } = workspace.env + let paths = runtimepath.split(',') + for (let path of paths) { + this.createVimSources(path).logError() + } + } + + private async createVimSources(pluginPath: string): Promise { + if (this.remoteSourcePaths.includes(pluginPath)) return + this.remoteSourcePaths.push(pluginPath) + let folder = path.join(pluginPath, 'autoload/coc/source') + let stat = await statAsync(folder) + if (stat && stat.isDirectory()) { + let arr = await util.promisify(fs.readdir)(folder) + arr = arr.filter(s => s.endsWith('.vim')) + let files = arr.map(s => path.join(folder, s)) + if (files.length == 0) return + await Promise.all(files.map(p => this.createVimSourceExtension(this.nvim, p))) + } + } + + public get names(): string[] { + return Array.from(this.sourceMap.keys()) + } + + public get sources(): ISource[] { + return Array.from(this.sourceMap.values()) + } + + public has(name): boolean { + return this.names.findIndex(o => o == name) != -1 + } + + public getSource(name: string): ISource | null { + if (!name) return null + return this.sourceMap.get(name) || null + } + + public shouldCommit(item: ExtendedCompleteItem, commitCharacter: string): boolean { + if (!item || !item.source) return false + let source = this.getSource(item.source) + if (source && source.sourceType == SourceType.Service && typeof source.shouldCommit === 'function') { + return source.shouldCommit(item, commitCharacter) + } + return false + } + + public getCompleteSources(opt: CompleteOption): ISource[] { + let { filetype } = opt + let pre = byteSlice(opt.line, 0, opt.colnr - 1) + let isTriggered = opt.input == '' && !!opt.triggerCharacter + let uri = getUri(opt.filepath, opt.bufnr, '', workspace.env.isCygwin) + if (isTriggered) return this.getTriggerSources(pre, filetype, uri) + return this.getNormalSources(opt.filetype, uri) + } + + /** + * Get sources should be used without trigger. + * + * @param {string} filetype + * @returns {ISource[]} + */ + public getNormalSources(filetype: string, uri: string): ISource[] { + return this.sources.filter(source => { + let { filetypes, triggerOnly, documentSelector, enable } = source + if (!enable || triggerOnly || (filetypes && !filetypes.includes(filetype))) { + return false + } + if (documentSelector && score(documentSelector, uri, filetype) == 0) { + return false + } + if (this.disabledByLanguageId(source, filetype)) { + return false + } + return true + }) + } + + private checkTrigger(source: ISource, pre: string, character: string): boolean { + let { triggerCharacters, triggerPatterns } = source + if (!triggerCharacters && !triggerPatterns) return false + if (character && triggerCharacters && triggerCharacters.includes(character)) { + return true + } + if (triggerPatterns && triggerPatterns.findIndex(p => p.test(pre)) !== -1) { + return true + } + return false + } + + public shouldTrigger(pre: string, languageId: string, uri: string): boolean { + let sources = this.getTriggerSources(pre, languageId, uri) + return sources.length > 0 + } + + public getTriggerSources(pre: string, languageId: string, uri: string): ISource[] { + let character = pre.length ? pre[pre.length - 1] : '' + if (!character) return [] + return this.sources.filter(source => { + let { filetypes, enable, documentSelector } = source + if (!enable || (filetypes && !filetypes.includes(languageId))) { + return false + } + if (documentSelector && score(documentSelector, uri, languageId) == 0) { + return false + } + if (this.disabledByLanguageId(source, languageId)) return false + return this.checkTrigger(source, pre, character) + }) + } + + public addSource(source: ISource): Disposable { + let { name } = source + if (this.names.includes(name)) { + logger.warn(`Recreate source ${name}`) + } + this.sourceMap.set(name, source) + return Disposable.create(() => { + this.sourceMap.delete(name) + }) + } + + public removeSource(source: ISource | string): void { + let name = typeof source == 'string' ? source : source.name + this.sourceMap.delete(name) + } + + public async refresh(name?: string): Promise { + for (let source of this.sources) { + if (!name || source.name == name) { + if (typeof source.refresh === 'function') { + await Promise.resolve(source.refresh()) + } + } + } + } + + public toggleSource(name: string): void { + if (!name) return + let source = this.getSource(name) + if (!source) return + if (typeof source.toggle === 'function') { + source.toggle() + } + } + + public sourceStats(): SourceStat[] { + let res: SourceStat[] = [] + let items = this.sources + for (let item of items) { + res.push({ + name: item.name, + priority: item.priority, + triggerCharacters: item.triggerCharacters || [], + shortcut: item.shortcut || '', + filetypes: item.filetypes || [], + filepath: item.filepath || '', + type: item.sourceType == SourceType.Native + ? 'native' : item.sourceType == SourceType.Remote + ? 'remote' : 'service', + disabled: !item.enable + }) + } + return res + } + + private onDocumentEnter(bufnr: number): void { + let { sources } = this + for (let s of sources) { + if (s.enable && typeof s.onEnter == 'function') { + s.onEnter(bufnr) + } + } + } + + public createSource(config: SourceConfig): Disposable { + if (!config.name || !config.doComplete) { + throw new Error(`name and doComplete required for createSource`) + } + let source = new Source(Object.assign({ sourceType: SourceType.Service } as any, config)) + return this.addSource(source) + } + + private disabledByLanguageId(source: ISource, languageId: string): boolean { + let map = workspace.env.disabledSources + if (isEmpty(map)) return false + let list = map ? map[languageId] : [] + return Array.isArray(list) && list.includes(source.name) + } + + public dispose(): void { + disposeAll(this.disposables) + } +} + +export default new Sources() diff --git a/vim-config/plugins/coc.nvim/src/sources/native/around.ts b/vim-config/plugins/coc.nvim/src/sources/native/around.ts new file mode 100644 index 00000000..dcf6a8f8 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/sources/native/around.ts @@ -0,0 +1,38 @@ +import { Disposable } from 'vscode-languageserver-protocol' +import Source from '../source' +import { CompleteOption, CompleteResult, ISource } from '../../types' +import workspace from '../../workspace' +const logger = require('../../util/logger')('sources-around') + +export default class Around extends Source { + constructor() { + super({ + name: 'around', + filepath: __filename + }) + } + + public doComplete(opt: CompleteOption): Promise { + let { bufnr, input } = opt + if (input.length === 0) return null + let document = workspace.getDocument(bufnr) + if (!document) return null + let words = document.words + let moreWords = document.getMoreWords() + words.push(...moreWords) + words = this.filterWords(words, opt) + return Promise.resolve({ + items: words.map(word => ({ + word, + menu: this.menu + })) + }) + } +} + +export function regist(sourceMap: Map): Disposable { + sourceMap.set('around', new Around()) + return Disposable.create(() => { + sourceMap.delete('around') + }) +} diff --git a/vim-config/plugins/coc.nvim/src/sources/native/buffer.ts b/vim-config/plugins/coc.nvim/src/sources/native/buffer.ts new file mode 100644 index 00000000..ede62a48 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/sources/native/buffer.ts @@ -0,0 +1,53 @@ +import { Disposable } from 'vscode-languageserver-protocol' +import Source from '../source' +import { CompleteOption, CompleteResult, ISource } from '../../types' +import workspace from '../../workspace' +const logger = require('../../util/logger')('sources-buffer') + +export default class Buffer extends Source { + constructor() { + super({ + name: 'buffer', + filepath: __filename + }) + } + + public get ignoreGitignore(): boolean { + return this.getConfig('ignoreGitignore', true) + } + + private getWords(bufnr: number): string[] { + let { ignoreGitignore } = this + let words: string[] = [] + workspace.documents.forEach(document => { + if (document.bufnr == bufnr) return + if (ignoreGitignore && document.isIgnored) return + for (let word of document.words) { + if (!words.includes(word)) { + words.push(word) + } + } + }) + return words + } + + public doComplete(opt: CompleteOption): Promise { + let { bufnr, input } = opt + if (input.length == 0) return null + let words = this.getWords(bufnr) + words = this.filterWords(words, opt) + return Promise.resolve({ + items: words.map(word => ({ + word, + menu: this.menu + })) + }) + } +} + +export function regist(sourceMap: Map): Disposable { + sourceMap.set('buffer', new Buffer()) + return Disposable.create(() => { + sourceMap.delete('buffer') + }) +} diff --git a/vim-config/plugins/coc.nvim/src/sources/native/file.ts b/vim-config/plugins/coc.nvim/src/sources/native/file.ts new file mode 100644 index 00000000..70226a99 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/sources/native/file.ts @@ -0,0 +1,151 @@ +import fs from 'fs' +import minimatch from 'minimatch' +import path from 'path' +import util from 'util' +import { Disposable } from 'vscode-languageserver-protocol' +import Source from '../source' +import { CompleteOption, CompleteResult, ISource, VimCompleteItem } from '../../types' +import { statAsync } from '../../util/fs' +import { byteSlice } from '../../util/string' +import workspace from '../../workspace' +const logger = require('../../util/logger')('sources-file') +const pathRe = /(?:\.{0,2}|~|\$HOME|([\w]+)|[a-zA-Z]:|)(\/|\\)(?:[\u4e00-\u9fa5\w.@()-]+(\/|\\))*(?:[\u4e00-\u9fa5\w.@()-])*$/ + +interface PathOption { + pathstr: string + part: string + startcol: number + input: string +} + +export default class File extends Source { + constructor() { + super({ + name: 'file', + filepath: __filename + }) + } + + private resolveEnvVariables(str: string): string { + let replaced = str + // windows + replaced = replaced.replace(/%([^%]+)%/g, (_, n) => process.env[n]) + // linux and mac + replaced = replaced.replace( + /\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/gi, + (_, a, b) => process.env[a || b] + ) + return replaced + } + + private getPathOption(opt: CompleteOption): PathOption | null { + let { line, colnr } = opt + let part = byteSlice(line, 0, colnr - 1) + part = this.resolveEnvVariables(part) + if (!part || part.endsWith('//')) return null + let ms = part.match(pathRe) + if (ms && ms.length) { + const pathstr = workspace.expand(ms[0]) + let input = ms[0].match(/[^/\\]*$/)[0] + return { pathstr, part: ms[1], startcol: colnr - input.length - 1, input } + } + return null + } + + private async getFileItem(root: string, filename: string): Promise { + let f = path.join(root, filename) + let stat = await statAsync(f) + if (stat) { + let abbr = stat.isDirectory() ? filename + '/' : filename + let word = filename + return { word, abbr } + } + return null + } + + public filterFiles(files: string[]): string[] { + let ignoreHidden = this.getConfig('ignoreHidden', true) + let ignorePatterns = this.getConfig('ignorePatterns', []) + return files.filter(f => { + if (f == null) return false + if (ignoreHidden && f.startsWith(".")) return false + for (let p of ignorePatterns) { + if (minimatch(f, p, { dot: true })) return false + } + return true + }) + } + + public async getItemsFromRoot(pathstr: string, root: string): Promise { + let res = [] + let part = pathstr.endsWith("/") ? pathstr : path.dirname(pathstr) + let dir = path.isAbsolute(pathstr) ? part : path.join(root, part) + try { + let stat = await statAsync(dir) + if (stat && stat.isDirectory()) { + let files = await util.promisify(fs.readdir)(dir) + files = this.filterFiles(files) + let items = await Promise.all(files.map(filename => this.getFileItem(dir, filename))) + res = res.concat(items) + } + res = res.filter(item => item != null) + return res + } catch (e) { + logger.error(`Error on list files:`, e) + return res + } + } + + public get trimSameExts(): string[] { + return this.getConfig('trimSameExts', []) + } + + public async doComplete(opt: CompleteOption): Promise { + 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 ? '' : byteSlice(opt.line, opt.col, startcol) + let dirname = path.dirname(filepath) + let ext = path.extname(path.basename(filepath)) + let cwd = await this.nvim.call('getcwd', []) + let root + if (pathstr.startsWith(".")) { + root = filepath ? path.dirname(filepath) : cwd + } else if (pathstr.startsWith("/")) { + root = pathstr.endsWith("/") ? pathstr : path.dirname(pathstr) + } else if (part) { + if (fs.existsSync(path.join(dirname, part))) { + root = dirname + } else if (fs.existsSync(path.join(cwd, part))) { + root = cwd + } + } else { + root = cwd + } + if (!root) return null + let items = await this.getItemsFromRoot(pathstr, root) + let trimExt = this.trimSameExts.includes(ext) + let first = input[0] + if (first && col == startcol) items = items.filter(o => o.word[0] === first) + return { + items: items.map(item => { + let ex = path.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 + } + }) + } + } +} + +export function regist(sourceMap: Map): Disposable { + sourceMap.set('file', new File()) + return Disposable.create(() => { + sourceMap.delete('file') + }) +} diff --git a/vim-config/plugins/coc.nvim/src/sources/source-language.ts b/vim-config/plugins/coc.nvim/src/sources/source-language.ts new file mode 100644 index 00000000..1a28f25b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/sources/source-language.ts @@ -0,0 +1,394 @@ +import { CancellationToken, CompletionItem, CompletionItemKind, CompletionList, CompletionTriggerKind, DocumentSelector, InsertReplaceEdit, InsertTextFormat, Position, Range, TextEdit } from 'vscode-languageserver-protocol' +import commands from '../commands' +import { CompletionItemProvider } from '../provider' +import snippetManager from '../snippets/manager' +import { SnippetParser } from '../snippets/parser' +import { CompleteOption, CompleteResult, ExtendedCompleteItem, ISource, SourceType } from '../types' +import { getChangedFromEdits, rangeOverlap } from '../util/position' +import { byteIndex, byteLength, byteSlice, characterIndex } from '../util/string' +import window from '../window' +import workspace from '../workspace' +const logger = require('../util/logger')('source-language') + +export interface CompleteConfig { + labels: Map + snippetsSupport: boolean + defaultKindText: string + priority: number + echodocSupport: boolean + detailMaxLength: number + detailField: string + invalidInsertCharacters: string[] + floatEnable: boolean +} + +export default class LanguageSource implements ISource { + public priority: number + public sourceType: SourceType.Service + private _enabled = true + private filetype: string + private resolvedIndexes: Set = new Set() + private completeItems: CompletionItem[] = [] + constructor( + public readonly name: string, + public readonly shortcut: string, + private provider: CompletionItemProvider, + public readonly documentSelector: DocumentSelector, + public readonly triggerCharacters: string[], + public readonly allCommitCharacters: string[], + priority: number | undefined, + private readonly completeConfig: CompleteConfig, + ) { + this.priority = typeof priority === 'number' ? priority : completeConfig.priority + } + + public get enable(): boolean { + return this._enabled + } + + public toggle(): void { + this._enabled = !this._enabled + } + + public shouldCommit?(item: ExtendedCompleteItem, character: string): boolean { + let completeItem = this.completeItems[item.index] + if (!completeItem) return false + let commitCharacters = [...this.allCommitCharacters, ...(completeItem.commitCharacters || [])] + return commitCharacters.includes(character) + } + + public async doComplete(opt: CompleteOption, token: CancellationToken): Promise { + let { provider, name } = this + let { triggerCharacter, bufnr } = opt + this.filetype = opt.filetype + this.resolvedIndexes.clear() + this.completeItems = [] + let triggerKind: CompletionTriggerKind = this.getTriggerKind(opt) + let position = this.getPosition(opt) + let context: any = { triggerKind, option: opt } + if (triggerKind == CompletionTriggerKind.TriggerCharacter) context.triggerCharacter = triggerCharacter + let result: CompletionItem[] | CompletionList | undefined + try { + let doc = workspace.getDocument(bufnr) + result = await Promise.resolve(provider.provideCompletionItems(doc.textDocument, position, token, context)) + } catch (e) { + // don't disturb user + logger.error(`Complete "${name}" error:`, e) + return null + } + if (!result || token.isCancellationRequested) return null + let completeItems = Array.isArray(result) ? result : result.items + if (!completeItems || completeItems.length == 0) return null + this.completeItems = completeItems + let startcol = getStartColumn(opt.line, completeItems) + let option: CompleteOption = Object.assign({}, opt) + let prefix: string + if (startcol != null) { + if (startcol < option.col) { + prefix = byteSlice(opt.line, startcol, option.col) + } + option.col = startcol + } + let items: ExtendedCompleteItem[] = completeItems.map((o, index) => { + let item = this.convertVimCompleteItem(o, this.shortcut, option, prefix) + item.index = index + return item + }) + let isIncomplete = typeof result['isIncomplete'] === 'boolean' ? result['isIncomplete'] : false + return { startcol, isIncomplete, items } + } + + public async onCompleteResolve(item: ExtendedCompleteItem, token: CancellationToken): Promise { + let { index } = item + let resolving = this.completeItems[index] + if (!resolving || this.resolvedIndexes.has(index)) return + let hasResolve = typeof this.provider.resolveCompletionItem === 'function' + if (hasResolve) { + this.resolvedIndexes.add(index) + try { + let resolved = await Promise.resolve(this.provider.resolveCompletionItem(Object.assign({}, resolving), token)) + if (!resolved || token.isCancellationRequested) { + this.resolvedIndexes.delete(index) + } else if (resolved !== resolving) { + Object.assign(resolving, resolved) + } + } catch (e) { + this.resolvedIndexes.delete(index) + logger.error(`Error on complete resolve: ${e.message}`, e.stack) + } + } + if (typeof item.documentation === 'undefined') { + 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\n]+$/.test(detail) + docs.push({ filetype: isText ? 'txt' : this.filetype, content: detail }) + } + } + if (documentation) { + if (typeof documentation == 'string') { + docs.push({ filetype: 'markdown', content: documentation }) + } else if (documentation.value) { + docs.push({ + filetype: documentation.kind == 'markdown' ? 'markdown' : 'txt', + content: documentation.value + }) + } + } + item.documentation = docs + } + } + + public async onCompleteDone(vimItem: ExtendedCompleteItem, opt: CompleteOption): Promise { + let item = this.completeItems[vimItem.index] + if (!item) return + let line = opt.linenr - 1 + if (item.insertText != null && !item.textEdit) { + item.textEdit = { + range: Range.create(line, opt.col, line, opt.colnr - 1), + newText: item.insertText + } + } + if (vimItem.line) Object.assign(opt, { line: vimItem.line }) + try { + let isSnippet = await this.applyTextEdit(item, vimItem.word, opt) + let { additionalTextEdits } = item + if (additionalTextEdits && item.textEdit) { + let r = InsertReplaceEdit.is(item.textEdit) ? item.textEdit.replace : item.textEdit.range + additionalTextEdits = additionalTextEdits.filter(edit => { + let er = InsertReplaceEdit.is(edit) ? edit.replace : edit.range + if (rangeOverlap(r, er)) { + logger.error('Filtered overlap additionalTextEdit:', edit) + return false + } + return true + }) + } + await this.applyAdditionalEdits(additionalTextEdits, opt.bufnr, isSnippet) + if (isSnippet) await snippetManager.selectCurrentPlaceholder() + if (item.command && commands.has(item.command.command)) { + void commands.execute(item.command) + } + } catch (e) { + logger.error('Error on CompleteDone:', e) + } + } + + private async applyTextEdit(item: CompletionItem, word: string, option: CompleteOption): Promise { + let { nvim } = workspace + let { textEdit } = item + if (!textEdit) return false + let { line, bufnr, linenr } = option + let doc = workspace.getDocument(bufnr) + if (!doc) return false + let newText = textEdit.newText + let range = InsertReplaceEdit.is(textEdit) ? textEdit.replace : textEdit.range + let isSnippet = item.insertTextFormat === InsertTextFormat.Snippet + // replace inserted word + let start = line.substr(0, range.start.character) + let end = line.substr(range.end.character) + if (isSnippet && this.completeConfig.snippetsSupport === false) { + // could be wrong, but maybe best we can do. + isSnippet = false + newText = word + } + if (isSnippet) { + let currline = doc.getline(linenr - 1) + let endCharacter = currline.length - end.length + let r = Range.create(linenr - 1, range.start.character, linenr - 1, endCharacter) + // can't select, since additionalTextEdits would break selection + return await snippetManager.insertSnippet(newText, false, r, item.insertTextMode) + } + let newLines = `${start}${newText}${end}`.split(/\r?\n/) + if (newLines.length == 1) { + await nvim.call('coc#util#setline', [linenr, newLines[0]]) + await window.moveTo(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 window.moveTo({ line, character }) + } + return false + } + + private getTriggerKind(opt: CompleteOption): CompletionTriggerKind { + let { triggerCharacters } = this + let isTrigger = triggerCharacters.includes(opt.triggerCharacter) + let triggerKind: CompletionTriggerKind = CompletionTriggerKind.Invoked + if (opt.triggerForInComplete) { + triggerKind = CompletionTriggerKind.TriggerForIncompleteCompletions + } else if (isTrigger) { + triggerKind = CompletionTriggerKind.TriggerCharacter + } + return triggerKind + } + + private async applyAdditionalEdits(textEdits: TextEdit[], bufnr: number, snippet: boolean): Promise { + if (!textEdits || textEdits.length == 0) return + let document = workspace.getDocument(bufnr) + if (!document) return + await document.patchChange(true) + // move cursor after edit + let changed = null + let pos = await window.getCursorPosition() + if (!snippet) changed = getChangedFromEdits(pos, textEdits) + await document.applyEdits(textEdits) + if (changed) await window.moveTo(Position.create(pos.line + changed.line, pos.character + changed.character)) + } + + private convertVimCompleteItem(item: CompletionItem, shortcut: string, opt: CompleteOption, prefix: string): ExtendedCompleteItem { + let { echodocSupport, detailMaxLength, invalidInsertCharacters, detailField, labels, defaultKindText } = this.completeConfig + let hasAdditionalEdit = item.additionalTextEdits && item.additionalTextEdits.length > 0 + let isSnippet = item.insertTextFormat === InsertTextFormat.Snippet || hasAdditionalEdit + let label = item.label.trim() + let obj: ExtendedCompleteItem = { + word: getWord(item, opt, invalidInsertCharacters), + abbr: label, + menu: `[${shortcut}]`, + kind: getKindString(item.kind, labels, defaultKindText), + sortText: item.sortText || null, + sourceScore: item['score'] || null, + filterText: item.filterText || label, + isSnippet, + dup: item.data && item.data.dup == 0 ? 0 : 1 + } + if (prefix) { + if (!obj.filterText.startsWith(prefix)) { + if (item.textEdit && item.textEdit.newText.startsWith(prefix)) { + obj.filterText = item.textEdit.newText.split(/\r?\n/)[0] + } + } + if (!item.textEdit && !obj.word.startsWith(prefix)) { + // fix remains completeItem that should not change startcol + obj.word = `${prefix}${obj.word}` + } + } + if (item && item.detail && detailField != 'preview') { + let detail = item.detail.replace(/\n\s*/g, ' ') + if (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 == 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.includes('(')) { + obj.signature = s + break + } + } + } + if (item.preselect) obj.preselect = true + if (item.data?.optional) obj.abbr = obj.abbr + '?' + return obj + } + + private getPosition(opt: CompleteOption): Position { + let { line, linenr, colnr } = opt + let part = byteSlice(line, 0, colnr - 1) + return { + line: linenr - 1, + character: part.length + } + } +} + +/* + * Check new startcol by check start characters. + */ +export function getStartColumn(line: string, items: CompletionItem[]): number | null { + let first = items[0] + if (!first.textEdit) return null + let range = InsertReplaceEdit.is(first.textEdit) ? first.textEdit.replace : first.textEdit.range + let { character } = range.start + for (let i = 1; i < Math.min(10, items.length); i++) { + let o = items[i] + if (!o.textEdit) return null + let r = InsertReplaceEdit.is(o.textEdit) ? o.textEdit.replace : o.textEdit.range + if (r.start.character !== character) return null + } + return byteIndex(line, character) +} + +export function getKindString(kind: CompletionItemKind, map: Map, defaultValue = ''): string { + return map.get(kind) || defaultValue +} + +export function getWord(item: CompletionItem, opt: CompleteOption, invalidInsertCharacters: string[]): string { + let { label, data, insertTextFormat, insertText, textEdit } = item + let word: string + let newText: string + if (data && typeof data.word === 'string') return data.word + if (textEdit) { + let range = InsertReplaceEdit.is(textEdit) ? textEdit.replace : textEdit.range + newText = textEdit.newText + if (range && range.start.line == range.end.line) { + let { line, col, colnr } = opt + let character = 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 = 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 == InsertTextFormat.Snippet + && newText + && newText.includes('$')) { + let parser = new SnippetParser() + let text = parser.text(newText) + word = text ? getValidWord(text, invalidInsertCharacters) : label + } else { + word = getValidWord(newText, invalidInsertCharacters) || label + } + return word || '' +} + +export function getValidWord(text: string, invalidChars: string[]): string { + if (!text) return '' + if (!invalidChars.length) return text + for (let i = 0; i < text.length; i++) { + let c = text[i] + if (invalidChars.includes(c)) { + return text.slice(0, i) + } + } + return text +} diff --git a/vim-config/plugins/coc.nvim/src/sources/source-vim.ts b/vim-config/plugins/coc.nvim/src/sources/source-vim.ts new file mode 100644 index 00000000..c0a02a18 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/sources/source-vim.ts @@ -0,0 +1,97 @@ +import { CancellationToken } from 'vscode-languageserver-protocol' +import { CompleteOption, CompleteResult, ExtendedCompleteItem } from '../types' +import { fuzzyChar } from '../util/fuzzy' +import { byteSlice } from '../util/string' +import workspace from '../workspace' +import window from '../window' +import Source from './source' +const logger = require('../util/logger')('sources-source-vim') + +export default class VimSource extends Source { + + private async callOptinalFunc(fname: string, args: any[]): Promise { + let exists = this.optionalFns.includes(fname) + if (!exists) return null + let name = `coc#source#${this.name}#${fname}` + let res + try { + res = await this.nvim.call(name, args) + } catch (e) { + window.showMessage(`Vim error from source ${this.name}: ${e.message}`, 'error') + return null + } + return res + } + + public async shouldComplete(opt: CompleteOption): Promise { + let shouldRun = await super.shouldComplete(opt) + if (!shouldRun) return false + if (!this.optionalFns.includes('should_complete')) return true + let res = await this.callOptinalFunc('should_complete', [opt]) + return !!res + } + + public async refresh(): Promise { + await this.callOptinalFunc('refresh', []) + } + + public async onCompleteDone(item: ExtendedCompleteItem, _opt: CompleteOption): Promise { + if (!this.optionalFns.includes('on_complete')) return + await this.callOptinalFunc('on_complete', [item]) + } + + public onEnter(bufnr: number): void { + if (!this.optionalFns.includes('on_enter')) return + let doc = workspace.getDocument(bufnr) + if (!doc) return + let { filetypes } = this + if (filetypes && !filetypes.includes(doc.filetype)) return + this.callOptinalFunc('on_enter', [{ + bufnr, + uri: doc.uri, + languageId: doc.filetype + }]).logError() + } + + public async doComplete(opt: CompleteOption, token: CancellationToken): Promise { + let { col, input, line, colnr } = opt + let startcol: number | null = 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 = byteSlice(line, startcol, colnr - 1) + opt = Object.assign({}, opt, { + col: startcol, + changed: col - startcol, + input + }) + } + } + let items: ExtendedCompleteItem[] = 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 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: CompleteResult = { items } + if (startcol) res.startcol = startcol + return res + } +} diff --git a/vim-config/plugins/coc.nvim/src/sources/source.ts b/vim-config/plugins/coc.nvim/src/sources/source.ts new file mode 100644 index 00000000..4999984e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/sources/source.ts @@ -0,0 +1,170 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationToken } from 'vscode-languageserver-protocol' +import { CompleteOption, CompleteResult, ISource, SourceConfig, SourceType, VimCompleteItem } from '../types' +import { byteSlice } from '../util/string' +import workspace from '../workspace' +const logger = require('../util/logger')('sources-source') + +export default class Source implements ISource { + public readonly name: string + public readonly filepath: string + public readonly sourceType: SourceType + public readonly isSnippet: boolean + protected readonly nvim: Neovim + private _disabled = false + private defaults: any + constructor(option: SourceConfig) { + this.nvim = workspace.nvim + // readonly properties + this.name = option.name + this.filepath = option.filepath || '' + this.sourceType = option.sourceType || SourceType.Native + this.isSnippet = !!option.isSnippet + this.defaults = option + } + + /** + * Priority of source, higher priority makes items lower index. + */ + public get priority(): number { + return this.getConfig('priority', 1) + } + + /** + * When triggerOnly is true, not trigger completion on keyword character insert. + */ + public get triggerOnly(): boolean { + 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 + } + + public get triggerCharacters(): string[] { + return this.getConfig('triggerCharacters', null) + } + + // exists opitonnal function names for remote source + public get optionalFns(): string[] { + return this.defaults['optionalFns'] || [] + } + + public get triggerPatterns(): RegExp[] | null { + let patterns = this.getConfig('triggerPatterns', null) + if (!patterns || patterns.length == 0) return null + return patterns.map(s => (typeof s === 'string') ? new RegExp(s + '$') : s) + } + + public get shortcut(): string { + let shortcut = this.getConfig('shortcut', '') + return shortcut ? shortcut : this.name.slice(0, 3) + } + + public get enable(): boolean { + if (this._disabled) return false + return this.getConfig('enable', true) + } + + public get filetypes(): string[] | null { + return this.getConfig('filetypes', null) + } + + public get disableSyntaxes(): string[] { + return this.getConfig('disableSyntaxes', []) + } + + public getConfig(key: string, defaultValue?: T): T | null { + let config = workspace.getConfiguration(`coc.source.${this.name}`) + defaultValue = this.defaults.hasOwnProperty(key) ? this.defaults[key] : defaultValue + return config.get(key, defaultValue) + } + + public toggle(): void { + this._disabled = !this._disabled + } + + public get firstMatch(): boolean { + return this.getConfig('firstMatch', true) + } + + public get menu(): string { + let { shortcut } = this + return shortcut ? `[${shortcut}]` : '' + } + + /** + * Filter words that too short or doesn't match input + */ + protected filterWords(words: string[], opt: CompleteOption): string[] { + 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} + */ + protected fixStartcol(opt: CompleteOption, valids: string[]): number { + let { col, input, line, bufnr } = opt + let start = byteSlice(line, 0, col) + let document = workspace.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.includes(c)) { + break + } + input = `${c}${input}` + col = col - 1 + } + opt.col = col + opt.input = input + return col + } + + public async shouldComplete(opt: CompleteOption): Promise { + let { disableSyntaxes } = this + if (opt.synname && disableSyntaxes && disableSyntaxes.length) { + let synname = (opt.synname || '').toLowerCase() + if (disableSyntaxes.findIndex(s => synname.includes(s.toLowerCase())) !== -1) { + return false + } + } + let fn = this.defaults['shouldComplete'] + if (typeof fn === 'function') return await Promise.resolve(fn.call(this, opt)) + return true + } + + public async refresh(): Promise { + let fn = this.defaults['refresh'] + if (typeof fn === 'function') await Promise.resolve(fn.call(this)) + } + + public async onCompleteDone(item: VimCompleteItem, opt: CompleteOption): Promise { + let fn = this.defaults['onCompleteDone'] + if (typeof fn === 'function') await Promise.resolve(fn.call(this, item, opt)) + } + + public async doComplete(opt: CompleteOption, token: CancellationToken): Promise { + let fn = this.defaults['doComplete'] + if (typeof fn === 'function') return await Promise.resolve(fn.call(this, opt, token)) + return null + } +} diff --git a/vim-config/plugins/coc.nvim/src/tree/BasicDataProvider.ts b/vim-config/plugins/coc.nvim/src/tree/BasicDataProvider.ts new file mode 100644 index 00000000..6b24dbd6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/tree/BasicDataProvider.ts @@ -0,0 +1,261 @@ +import { v4 as uuid } from 'uuid' +import { CancellationToken, MarkupContent, Disposable, Emitter, Event } from 'vscode-languageserver-protocol' +import commandsManager from '../commands' +import { ProviderResult } from '../provider' +import { disposeAll } from '../util' +import { TreeDataProvider, TreeItemAction } from './index' +import { TreeItem, TreeItemCollapsibleState, TreeItemIcon, TreeItemLabel } from './TreeItem' + +export interface TreeNode { + label: string + key?: string + tooltip?: string | MarkupContent + description?: string + deprecated?: boolean + icon?: TreeItemIcon + children?: this[] +} + +export interface ProviderOptions { + provideData: () => ProviderResult + expandLevel?: number + onDispose?: () => void + handleClick?: (item: T) => ProviderResult + resolveIcon?: (item: T) => TreeItemIcon | undefined + resolveItem?: (item: TreeItem, element: T, token: CancellationToken) => ProviderResult + resolveActions?(item: TreeItem, element: T): ProviderResult[]> +} + +function isIcon(obj: any): obj is TreeItemIcon { + if (!obj) return false + return typeof obj.text === 'string' && typeof obj.hlGroup === 'string' +} + +/** + * Check lable and key, children not checked. + */ +function sameTreeNode(one: T, two: T): boolean { + if (one.label === two.label + && one.deprecated === two.deprecated + && one.key === two.key) { + return true + } + return false +} + +/** + * Check changes of nodes array, children not checked. + */ +function sameTreeNodes(one: T[], two: T[]): boolean { + if (one.length !== two.length) return false + return one.every((v, idx) => sameTreeNode(v, two[idx])) +} + +/** + * Tree data provider for resolved tree with children. + * Use update() to update data. + */ +export default class BasicDataProvider implements TreeDataProvider { + private disposables: Disposable[] = [] + private invokeCommand: string + private data: T[] | undefined + // only fired for change of exists TreeNode + private _onDidChangeTreeData = new Emitter() + public onDidChangeTreeData: Event = this._onDidChangeTreeData.event + public resolveActions: (item: TreeItem, element: T) => ProviderResult[]> + // data is shared with TreeView + constructor(private opts: ProviderOptions) { + this.invokeCommand = `_invoke_${uuid()}` + this.disposables.push(commandsManager.registerCommand(this.invokeCommand, async (node: T) => { + if (typeof opts.handleClick === 'function') { + await opts.handleClick(node) + } else { + console.error('Handler not found') + } + }, null, true)) + if (typeof opts.resolveActions === 'function') { + this.resolveActions = opts.resolveActions.bind(this) + } + } + + private iterate(node: T, parentNode: T | undefined, level: number, fn: (node: T, parentNode: T | undefined, level: number) => void | boolean): void | boolean { + let res = fn(node, parentNode, level) + if (res === false) return false + if (Array.isArray(node.children)) { + for (let element of node.children) { + let res = this.iterate(element, node, level + 1, fn) + if (res === false) return false + } + } + return res + } + + /** + * Change old array to new nodes in place, keep old reference when possible. + */ + private updateNodes(old: T[], data: T[], parentNode: T | undefined, fireEvent = true): void { + let sameNodes = sameTreeNodes(old, data) + const applyNode = (previous: T, curr: T, fireEvent: boolean): void => { + let changed = false + for (let key of Object.keys(curr)) { + if (['children', 'key'].includes(key)) continue + previous[key] = curr[key] + } + if (previous.children?.length && !curr.children?.length) { + // removed children + delete previous.children + changed = true + } + if (!previous.children?.length && curr.children?.length) { + // new children + previous.children = curr.children + changed = true + } + if (changed) { + if (fireEvent) this._onDidChangeTreeData.fire(previous) + return + } + if (previous.children?.length && curr.children?.length) { + this.updateNodes(previous.children, curr.children, previous, fireEvent) + } + } + if (sameNodes) { + for (let i = 0; i < old.length; i++) { + applyNode(old[i], data[i], fireEvent) + } + } else { + let oldNodes = old.splice(0, old.length) + let used: Set = new Set() + for (let i = 0; i < data.length; i++) { + let curr = data[i] + let findIndex: number + if (curr.key) { + findIndex = oldNodes.findIndex((o, i) => !used.has(i) && o.key == curr.key) + } else { + findIndex = oldNodes.findIndex((o, i) => !used.has(i) && o.label == curr.label) + } + if (findIndex === -1) { + old[i] = curr + } else { + used.add(findIndex) + let previous = oldNodes[findIndex] + applyNode(previous, curr, false) + old[i] = previous + } + } + if (fireEvent) { + this._onDidChangeTreeData.fire(parentNode) + } + } + } + + /** + * Update with new data, fires change event when necessary. + */ + public update(data: T[], reset?: boolean): ReadonlyArray { + if (!this.data) return + if (reset) { + this.data = data || [] + this._onDidChangeTreeData.fire(undefined) + } else { + this.updateNodes(this.data, data || [], undefined) + } + return this.data + } + + public getTreeItem(node: T): TreeItem { + let label: string | TreeItemLabel = node.label + let { expandLevel } = this.opts + let item: TreeItem + if (!node.children?.length) { + item = new TreeItem(label) + } else { + if (expandLevel && expandLevel > 0) { + let level = this.getLevel(node) + let state = level && level <= expandLevel ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed + item = new TreeItem(label, state) + } else { + item = new TreeItem(label, TreeItemCollapsibleState.Collapsed) + } + } + item.description = node.description + if (node.deprecated) item.deprecated = true + if (node.tooltip) item.tooltip = node.tooltip + if (isIcon(node.icon)) { + item.icon = node.icon + } else if (typeof this.opts.resolveIcon === 'function') { + let res = this.opts.resolveIcon(node) + if (res) item.icon = res + } + return item + } + + public async getChildren(element?: T): Promise { + if (element) return element.children || [] + if (this.data) return this.data + let data = await Promise.resolve(this.opts.provideData()) + if (!Array.isArray(data)) throw new Error(`Unable to fetch data`) + this.data = data + return data + } + + /** + * Use reference check + */ + public getParent(element: T): T | undefined { + if (!this.data) return undefined + let find: T + for (let item of this.data) { + let res = this.iterate(item, null, 0, (node, parentNode) => { + if (node === element) { + find = parentNode + return false + } + }) + if (res === false) break + } + return find + } + + private getLevel(element: T): number { + if (!this.data) return undefined + let level = 0 + for (let item of this.data) { + let res = this.iterate(item, null, 1, (node, _parentNode, l) => { + if (node === element) { + level = l + return false + } + }) + if (res === false) break + } + return level + } + + /** + * Resolve command and tooltip + */ + public async resolveTreeItem(item: TreeItem, element: T, token: CancellationToken): Promise { + if (typeof this.opts.resolveItem === 'function') { + let res = await Promise.resolve(this.opts.resolveItem(item, element, token)) + if (res) Object.assign(item, res) + } + if (!item.command) { + item.command = { + title: `invoke ${element.label}`, + command: this.invokeCommand, + arguments: [element] + } + } + return item + } + + public dispose(): void { + this.data = [] + this._onDidChangeTreeData.dispose() + if (typeof this.opts.onDispose === 'function') { + this.opts.onDispose() + } + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/tree/TreeItem.ts b/vim-config/plugins/coc.nvim/src/tree/TreeItem.ts new file mode 100644 index 00000000..2ae4fb91 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/tree/TreeItem.ts @@ -0,0 +1,62 @@ +import { Command, MarkupContent } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import path from 'path' + +export interface TreeItemLabel { + label: string + highlights?: [number, number][] +} + +// eslint-disable-next-line no-redeclare +export namespace TreeItemLabel { + export function is(obj: any): obj is TreeItemLabel { + return typeof obj.label == 'string' + } +} + +export interface TreeItemIcon { + text: string + hlGroup: string +} + +/** + * Collapsible state of the tree item + */ +export enum TreeItemCollapsibleState { + /** + * Determines an item can be neither collapsed nor expanded. Implies it has no children. + */ + None = 0, + /** + * Determines an item is collapsed + */ + Collapsed = 1, + /** + * Determines an item is expanded + */ + Expanded = 2 +} + +export class TreeItem { + public label: string | TreeItemLabel + public id?: string + public description?: string + public icon?: TreeItemIcon + public resourceUri?: URI + public command?: Command + public tooltip?: string | MarkupContent + public deprecated?: boolean + + constructor(label: string | TreeItemLabel, collapsibleState?: TreeItemCollapsibleState) + // eslint-disable-next-line @typescript-eslint/unified-signatures + constructor(resourceUri: URI, collapsibleState?: TreeItemCollapsibleState) + constructor(label: string | TreeItemLabel | URI, public collapsibleState: TreeItemCollapsibleState = TreeItemCollapsibleState.None) { + if (URI.isUri(label)) { + this.resourceUri = label + this.label = path.basename(label.path) + this.id = label.toString() + } else { + this.label = label + } + } +} diff --git a/vim-config/plugins/coc.nvim/src/tree/TreeView.ts b/vim-config/plugins/coc.nvim/src/tree/TreeView.ts new file mode 100644 index 00000000..aa034376 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/tree/TreeView.ts @@ -0,0 +1,979 @@ +import { Neovim } from '@chemzqm/neovim' +import { CancellationTokenSource, Disposable, Emitter, Event, MarkupContent, MarkupKind, Range } from 'vscode-languageserver-protocol' +import commandManager from '../commands' +import events from '../events' +import FloatFactory from '../model/floatFactory' +import { ConfigurationChangeEvent, Documentation, HighlightItem } from '../types' +import { disposeAll } from '../util' +import { Mutex } from '../util/mutex' +import { equals } from '../util/object' +import { byteLength, byteSlice } from '../util/string' +import { hasMatch, positions, score, groupPositions } from '../util/fzy' +import workspace from '../workspace' +import window from '../window' +import Filter, { sessionKey } from './filter' +import { TreeDataProvider, TreeView, TreeViewExpansionEvent, TreeViewOptions, TreeViewSelectionChangeEvent, TreeViewVisibilityChangeEvent } from './index' +import { TreeItem, TreeItemCollapsibleState, TreeItemLabel } from './TreeItem' +const logger = require('../util/logger')('BasicTreeView') +const highlightNamespace = 'tree' +const signOffset = 3000 +let globalId = 1 + +interface TreeViewConfig { + openedIcon: string + closedIcon: string +} + +interface RenderedItem { + line: string + level: number + node: T +} + +interface ExtendedItem extends RenderedItem { + index: number + score: number + highlights: HighlightItem[] +} + +interface LineState { + /** + * Line count used by message + */ + messageCount: number + /** + * Line count used by title + */ + titleCount: number +} + +interface Keys { + invoke: string + toggle: string + actions: string + collapseAll: string + toggleSelection: string + close: string + activeFilter: string + selectNext: string + selectPrevious: string +} + +interface TreeItemData { + item: TreeItem + resolved: boolean +} + +/** + * Basic TreeView implementation + */ +export default class BasicTreeView implements TreeView { + // Resolved TreeItems + private bufnr: number | undefined + private winid: number | undefined + private config: TreeViewConfig + private keys: Keys + private originalWin: number + private _creating: boolean + private _selection: T[] = [] + private _onDidExpandElement = new Emitter>() + private _onDidCollapseElement = new Emitter>() + private _onDidChangeSelection = new Emitter>() + private _onDidChangeVisibility = new Emitter() + public onDidExpandElement: Event> = this._onDidExpandElement.event + public onDidCollapseElement: Event> = this._onDidCollapseElement.event + public onDidChangeSelection: Event> = this._onDidChangeSelection.event + public onDidChangeVisibility: Event = this._onDidChangeVisibility.event + public message: string | undefined + public title: string + public description: string | undefined + private retryTimers = 0 + private renderedItems: RenderedItem[] = [] + private provider: TreeDataProvider + private nodesMap: Map = new Map() + private mutex: Mutex = new Mutex() + private timer: NodeJS.Timer + private disposables: Disposable[] = [] + private tooltipFactory: FloatFactory + private resolveTokenSource: CancellationTokenSource | undefined + private lineState: LineState = { titleCount: 0, messageCount: 0 } + private filter: Filter | undefined + private filterText: string | undefined + private itemsToFilter: T[] | undefined + private readonly canSelectMany: boolean + private readonly leafIndent: boolean + private readonly winfixwidth: boolean + constructor(private viewId: string, opts: TreeViewOptions) { + this.loadConfiguration() + workspace.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables) + if (opts.enableFilter) { + this.filter = new Filter(this.nvim, [this.keys.selectNext, this.keys.selectPrevious, this.keys.invoke]) + } + this.tooltipFactory = new FloatFactory(workspace.nvim) + this.canSelectMany = !!opts.canSelectMany + this.provider = opts.treeDataProvider + this.leafIndent = opts.disableLeafIndent !== true + this.winfixwidth = opts.winfixwidth !== false + let message: string | undefined + Object.defineProperty(this, 'message', { + set: (msg: string | undefined) => { + message = msg ? msg.replace(/\r?\n/g, ' ') : undefined + this.updateHeadLines() + }, + get: () => { + return message + } + }) + let title = viewId.replace(/\r?\n/g, ' ') + Object.defineProperty(this, 'title', { + set: (newTitle: string) => { + title = newTitle ? newTitle.replace(/\r?\n/g, ' ') : undefined + this.updateHeadLines() + }, + get: () => { + return title + } + }) + let description: string | undefined + Object.defineProperty(this, 'description', { + set: (desc: string | undefined) => { + description = desc ? desc.replace(/\r?\n/g, ' ') : undefined + this.updateHeadLines() + }, + get: () => { + return description + } + }) + let filterText: string | undefined + Object.defineProperty(this, 'filterText', { + set: (text: string | undefined) => { + let { titleCount, messageCount } = this.lineState + let start = titleCount + messageCount + if (text != null) { + let highlights: HighlightItem[] = [{ + lnum: start, + colStart: byteLength(text), + colEnd: byteLength(text) + 1, + hlGroup: 'Cursor' + }] + this.renderedItems = [] + this.updateUI([text + ' '], highlights, start, -1, true) + void this.doFilter(text) + } else if (filterText != null) { + this.updateUI([], [], start, start + 1) + } + filterText = text + }, + get: () => { + return filterText + } + }) + if (this.provider.onDidChangeTreeData) { + this.provider.onDidChangeTreeData(this.onDataChange, this, this.disposables) + } + events.on('BufUnload', bufnr => { + if (bufnr != this.bufnr) return + this.winid = undefined + this.bufnr = undefined + this._onDidChangeVisibility.fire({ visible: false }) + this.dispose() + }, null, this.disposables) + events.on('CursorHold', async bufnr => { + if (bufnr != this.bufnr) return + await this.onHover() + }, null, this.disposables) + events.on(['CursorMoved', 'BufEnter'], () => { + this.cancelResolve() + }, null, this.disposables) + events.on('WinEnter', winid => { + if (winid != this.windowId || !this.filter?.activated) return + let buf = this.nvim.createBuffer(this.bufnr) + let line = this.startLnum - 1 + let len = this.filterText ? this.filterText.length : 0 + let range = Range.create(line, len, line, len + 1) + buf.highlightRanges(highlightNamespace, 'Cursor', [range]) + this.nvim.call('coc#prompt#start_prompt', [sessionKey], true) + this.redraw() + }, null, this.disposables) + events.on('WinLeave', winid => { + if (winid != this.windowId || !this.filter?.activated) return + let buf = this.nvim.createBuffer(this.bufnr) + this.nvim.call('coc#prompt#stop_prompt', [sessionKey], true) + buf.clearNamespace(highlightNamespace, this.startLnum - 1, this.startLnum) + }, null, this.disposables) + this.disposables.push(this._onDidChangeVisibility, this._onDidChangeSelection, this._onDidCollapseElement, this._onDidExpandElement) + if (this.filter) { + this.filter.onDidExit(node => { + this.nodesMap.clear() + this.filterText = undefined + this.itemsToFilter = undefined + if (node && typeof this.provider.getParent === 'function') { + this.renderedItems = [] + void this.reveal(node, { focus: true }) + } else { + this.clearSelection() + void this.render() + } + }) + this.filter.onDidUpdate(text => { + this.filterText = text + }) + this.filter.onDidKeyPress(async character => { + let items = this.renderedItems + if (!items?.length) return + let curr = this.selection[0] + if (character == '' || character == this.keys.selectPrevious) { + let idx = items.findIndex(o => o.node == curr) + let index = idx == -1 || idx == 0 ? items.length - 1 : idx - 1 + let node = items[index]?.node + if (node) this.selectItem(node, true) + } + if (character == '' || character == this.keys.selectNext) { + let idx = items.findIndex(o => o.node == curr) + let index = idx == -1 || idx == items.length - 1 ? 0 : idx + 1 + let node = items[index]?.node + if (node) this.selectItem(node, true) + } + if (character == '' || character == this.keys.invoke) { + if (!curr) return + await this.invokeCommand(curr) + this.filter.deactivate(curr) + } + }) + } + } + + public get windowId(): number | undefined { + return this.winid + } + + private get startLnum(): number { + let filterCount = this.filterText == null ? 0 : 1 + return this.lineState.messageCount + this.lineState.titleCount + filterCount + } + + private get nvim(): Neovim { + return workspace.nvim + } + + private loadConfiguration(e?: ConfigurationChangeEvent): void { + if (!e || e.affectsConfiguration('tree')) { + let config = workspace.getConfiguration('tree') + this.config = { + openedIcon: config.get('openedIcon', ' '), + closedIcon: config.get('closedIcon', ' ') + } + this.keys = { + close: config.get('key.close'), + invoke: config.get('key.invoke'), + toggle: config.get('key.toggle'), + actions: config.get('key.actions'), + collapseAll: config.get('key.collapseAll'), + toggleSelection: config.get('key.toggleSelection'), + activeFilter: config.get('key.activeFilter'), + selectNext: config.get('key.selectNext'), + selectPrevious: config.get('key.selectPrevious') + } + if (e) { + void this.render() + } + } + } + + private async doFilter(text: string): Promise { + let items: ExtendedItem[] = [] + let index = 0 + let release = await this.mutex.acquire() + try { + if (!this.itemsToFilter) { + let itemsToFilter: T[] = [] + const addNodes = async (nodes: T[]): Promise => { + for (let n of nodes) { + itemsToFilter.push(n) + let arr = await Promise.resolve(this.provider.getChildren(n)) + if (arr?.length) await addNodes(arr) + } + } + let nodes = await Promise.resolve(this.provider.getChildren()) + await addNodes(nodes) + this.itemsToFilter = itemsToFilter + } + for (let n of this.itemsToFilter) { + let item = await this.getTreeItem(n) + let label = TreeItemLabel.is(item.label) ? item.label.label : item.label + if (!text || hasMatch(text, label)) { + let idxs = text ? positions(text, label) : [] + item.collapsibleState = TreeItemCollapsibleState.None + item.label = { label, highlights: text ? groupPositions(idxs) : [] } + let { line, highlights } = this.getRenderedLine(item, index, 0) + items.push({ + level: 0, + node: n, + line, + index, + score: text ? score(text, label) : 0, + highlights + }) + index += 1 + } + } + items.sort((a, b) => { + if (a.score != b.score) return b.score - a.score + return a.index - b.index + }) + let lnum = this.startLnum + let highlights: HighlightItem[] = [] + let renderedItems = this.renderedItems = items.map((o, idx) => { + highlights.push(...o.highlights.map(h => { + h.lnum = lnum + idx + return h + })) + delete o.index + delete o.score + delete o.highlights + return o + }) + this.updateUI(renderedItems.map(o => o.line), highlights, lnum, -1, true) + if (renderedItems.length) { + this.selectItem(renderedItems[0].node, true) + } else { + this.clearSelection() + } + this.redraw() + release() + } catch (e) { + release() + logger.error(`Error on tree filter: ${e.message}`, e) + } + } + + private async onHover(): Promise { + let { nvim } = this + let lnum = await nvim.call('line', ['.']) + let element = this.getElementByLnum(lnum - 1) + if (!element) return + let obj = this.nodesMap.get(element) + if (!obj) return + let item = obj.item + if (!obj.resolved) { + item = await this.resolveItem(element, item) + if (!item) return + } + if (!item.tooltip || !this.bufnr) return + let isMarkdown = MarkupContent.is(item.tooltip) && item.tooltip.kind == MarkupKind.Markdown + let doc: Documentation = { + filetype: isMarkdown ? 'markdown' : 'txt', + content: MarkupContent.is(item.tooltip) ? item.tooltip.value : item.tooltip + } + await this.tooltipFactory.show([doc], { modes: ['n'] }) + } + + private async onClick(element: T): Promise { + let { nvim } = this + let [line, col] = await nvim.eval(`[getline('.'),col('.')]`) as [string, number] + let pre = byteSlice(line, 0, col - 1) + let character = line[pre.length] + if (!character) return + let { openedIcon, closedIcon } = this.config + if (/^\s*$/.test(pre) && [openedIcon, closedIcon].includes(character)) { + await this.toggleExpand(element) + } else { + await this.invokeCommand(element) + } + } + + private async invokeCommand(element: T): Promise { + let obj = this.nodesMap.get(element) + if (!obj) return + this.selectItem(element) + let item = obj.item + if (!item.command) { + item = await this.resolveItem(element, item) + if (!item) return + } + if (!item.command) throw new Error(`Failed to resolve command from TreeItem.`) + await commandManager.execute(item.command) + } + + private async invokeActions(element: T): Promise { + this.selectItem(element) + if (typeof this.provider.resolveActions !== 'function') { + await window.showWarningMessage('No actions') + return + } + let obj = this.nodesMap.get(element) + let actions = await Promise.resolve(this.provider.resolveActions(obj.item, element)) + if (!actions || actions.length == 0) { + await window.showWarningMessage('No actions available') + return + } + let keys = actions.map(o => o.title) + let res = await window.showMenuPicker(keys, 'Choose action') + if (res == -1) return + await Promise.resolve(actions[res].handler(element)) + } + + private async onDataChange(node: T | undefined): Promise { + if (this.filter?.activated) { + this.itemsToFilter = undefined + await this.doFilter(this.filterText) + return + } + this.clearSelection() + if (!node) { + await this.render() + return + } + let release = await this.mutex.acquire() + try { + let items = this.renderedItems + let idx = items.findIndex(o => o.node === node) + if (idx != -1 && this.bufnr) { + let obj = items[idx] + let level = obj.level + let removeCount = 0 + for (let i = idx; i < items.length; i++) { + let o = items[i] + if (i == idx || o && o.level > level) { + removeCount += 1 + } + } + let appendItems: RenderedItem[] = [] + let highlights: HighlightItem[] = [] + let start = idx + this.startLnum + await this.appendTreeNode(node, level, start, appendItems, highlights) + items.splice(idx, removeCount, ...appendItems) + this.updateUI(appendItems.map(o => o.line), highlights, start, start + removeCount) + } + release() + } catch (e) { + let errMsg = `Error on tree refresh: ${e.message}` + logger.error(errMsg, e) + this.nvim.errWriteLine('[coc.nvim] ' + errMsg) + release() + } + } + + private async resolveItem(element: T, item: TreeItem): Promise { + if (typeof this.provider.resolveTreeItem === 'function') { + let tokenSource = this.resolveTokenSource = new CancellationTokenSource() + let token = tokenSource.token + item = await Promise.resolve(this.provider.resolveTreeItem(item, element, token)) + tokenSource.dispose() + this.resolveTokenSource = undefined + if (token.isCancellationRequested) return undefined + } + this.nodesMap.set(element, { item, resolved: true }) + return item + } + + public get visible(): boolean { + return this.winid != null + } + + public get selection(): T[] { + return this._selection.slice() + } + + public async checkLines(): Promise { + if (!this.bufnr) return + let buf = this.nvim.createBuffer(this.bufnr) + let curr = await buf.lines + let { titleCount, messageCount } = this.lineState + curr = curr.slice(titleCount + messageCount) + let lines = this.renderedItems.map(o => o.line) + return equals(curr, lines) + } + + /** + * Expand/collapse TreeItem. + */ + private async toggleExpand(element: T): Promise { + let o = this.nodesMap.get(element) + if (!o) return + let treeItem = o.item + let lnum = this.getItemLnum(element) + let nodeIdx = lnum - this.startLnum + let obj = this.renderedItems[nodeIdx] + if (!obj || treeItem.collapsibleState == TreeItemCollapsibleState.None) { + if (typeof this.provider.getParent === 'function') { + let node = await Promise.resolve(this.provider.getParent(element)) + if (node) { + await this.toggleExpand(node) + this.focusItem(node) + } + } + return + } + // remove lines + let removeCount = 0 + if (treeItem.collapsibleState == TreeItemCollapsibleState.Expanded) { + let level = obj.level + for (let i = nodeIdx + 1; i < this.renderedItems.length; i++) { + let o = this.renderedItems[i] + if (!o || o.level <= level) break + removeCount += 1 + } + treeItem.collapsibleState = TreeItemCollapsibleState.Collapsed + } else if (treeItem.collapsibleState == TreeItemCollapsibleState.Collapsed) { + treeItem.collapsibleState = TreeItemCollapsibleState.Expanded + } + let newItems: RenderedItem[] = [] + let newHighlights: HighlightItem[] = [] + await this.appendTreeNode(obj.node, obj.level, lnum, newItems, newHighlights) + this.renderedItems.splice(nodeIdx, removeCount + 1, ...newItems) + this.updateUI(newItems.map(o => o.line), newHighlights, lnum, lnum + removeCount + 1) + this.refreshSigns() + if (treeItem.collapsibleState == TreeItemCollapsibleState.Collapsed) { + this._onDidCollapseElement.fire({ element }) + } else { + this._onDidExpandElement.fire({ element }) + } + } + + private toggleSelection(element: T): void { + let idx = this._selection.findIndex(o => o === element) + if (idx !== -1) { + this.unselectItem(idx) + } else { + this.selectItem(element) + } + } + + private clearSelection(): void { + if (!this.bufnr) return + this._selection = [] + let buf = this.nvim.createBuffer(this.bufnr) + buf.unplaceSign({ group: 'CocTree' }) + this._onDidChangeSelection.fire({ selection: [] }) + } + + private selectItem(item: T, forceSingle?: boolean, noRedraw?: boolean): void { + let { nvim } = this + if (!this.bufnr || !workspace.env.sign) return + let row = this.getItemLnum(item) + if (row == null) return + let buf = nvim.createBuffer(this.bufnr) + let exists = this._selection.includes(item) + if (!this.canSelectMany || forceSingle) { + this._selection = [item] + } else if (!exists) { + this._selection.push(item) + } + nvim.pauseNotification() + if (!this.canSelectMany || forceSingle) { + buf.unplaceSign({ group: 'CocTree' }) + } + nvim.call('coc#compat#execute', [this.winid, `exe ${row + 1}`], true) + buf.placeSign({ id: signOffset + row, lnum: row + 1, name: 'CocTreeSelected', group: 'CocTree' }) + if (!noRedraw) this.redraw() + void nvim.resumeNotification(false, true) + if (!exists) this._onDidChangeSelection.fire({ selection: this._selection }) + } + + private unselectItem(idx: number): void { + let item = this._selection[idx] + let row = this.getItemLnum(item) + if (row == null || !this.bufnr || !workspace.env.sign) return + this._selection.splice(idx, 1) + let buf = this.nvim.createBuffer(this.bufnr) + buf.unplaceSign({ group: 'CocTree', id: signOffset + row }) + this._onDidChangeSelection.fire({ selection: this._selection }) + } + + public focusItem(element: T): void { + if (!this.winid) return + let lnum = this.getItemLnum(element) + if (lnum == null) return + this.nvim.call('coc#compat#execute', [this.winid, `exe ${lnum + 1}`], true) + } + + private getElementByLnum(lnum: number): T | undefined { + let item = this.renderedItems[lnum - this.startLnum] + return item ? item.node : undefined + } + + private getItemLnum(item: T): number | undefined { + let idx = this.renderedItems.findIndex(o => o.node === item) + if (idx == -1) return undefined + return this.startLnum + idx + } + + private async getTreeItem(element: T): Promise { + let exists: TreeItem + let resolved = false + let obj = this.nodesMap.get(element) + if (obj != null) { + exists = obj.item + resolved = obj.resolved + } + let item = await Promise.resolve(this.provider.getTreeItem(element)) + if (item.id && !exists) { + for (let obj of this.nodesMap.values()) { + if (obj.item.id === item.id) { + resolved = obj.resolved + exists = obj.item + break + } + } + } + if (exists + && exists.collapsibleState != TreeItemCollapsibleState.None + && item.collapsibleState != TreeItemCollapsibleState.None) { + item.collapsibleState = exists.collapsibleState + } + this.nodesMap.set(element, { item, resolved }) + return item + } + + private getRenderedLine(treeItem: TreeItem, lnum: number, level: number): { line: string, highlights: HighlightItem[] } { + let { openedIcon, closedIcon } = this.config + const highlights: HighlightItem[] = [] + const { label, deprecated, description } = treeItem + let prefix = ' '.repeat(level) + const addHighlight = (text: string, hlGroup: string) => { + let colStart = byteLength(prefix) + highlights.push({ + lnum, + hlGroup, + colStart, + colEnd: colStart + byteLength(text), + }) + } + switch (treeItem.collapsibleState) { + case TreeItemCollapsibleState.Expanded: { + addHighlight(openedIcon, 'CocTreeOpenClose') + prefix += openedIcon + ' ' + break + } + case TreeItemCollapsibleState.Collapsed: { + addHighlight(closedIcon, 'CocTreeOpenClose') + prefix += closedIcon + ' ' + break + } + default: + prefix += this.leafIndent ? ' ' : '' + } + if (treeItem.icon) { + let { text, hlGroup } = treeItem.icon + addHighlight(text, hlGroup) + prefix += text + ' ' + } + if (TreeItemLabel.is(label) && Array.isArray(label.highlights)) { + let colStart = byteLength(prefix) + for (let o of label.highlights) { + highlights.push({ + lnum, + hlGroup: 'Search', + colStart: colStart + o[0], + colEnd: colStart + o[1] + }) + } + } + let labelText = typeof label === 'string' ? label : label.label + if (deprecated) { + addHighlight(labelText, 'CocDeprecatedHighlight') + } + prefix += labelText + if (description && description.indexOf('\n') == -1) { + prefix += ' ' + addHighlight(description, 'CocTreeDescription') + prefix += description + } + return { line: prefix, highlights } + } + + private async appendTreeNode(element: T, level: number, lnum: number, items: RenderedItem[], highlights: HighlightItem[]): Promise { + let takes = 1 + let treeItem = await this.getTreeItem(element) + let res = this.getRenderedLine(treeItem, lnum, level) + highlights.push(...res.highlights) + items.push({ level, line: res.line, node: element }) + if (treeItem.collapsibleState == TreeItemCollapsibleState.Expanded) { + let l = level + 1 + let children = await Promise.resolve(this.provider.getChildren(element)) || [] + for (let el of children) { + let n = await this.appendTreeNode(el, l, lnum + takes, items, highlights) + takes = takes + n + } + } + return takes + } + + private updateUI(lines: string[], highlights: HighlightItem[], start = 0, end = -1, noRedraw = false): void { + if (!this.bufnr) return + let { nvim } = this + let buf = nvim.createBuffer(this.bufnr) + nvim.pauseNotification() + buf.setOption('modifiable', true, true) + void buf.setLines(lines, { start, end, strictIndexing: false }, true) + if (highlights.length) { + let highlightEnd = end == -1 ? -1 : start + lines.length + nvim.call('coc#highlight#update_highlights', [this.bufnr, highlightNamespace, highlights, start, highlightEnd], true) + } + buf.setOption('modifiable', false, true) + if (!noRedraw) this.redraw() + void nvim.resumeNotification(false, true) + } + + public async reveal(element: T, options: { select?: boolean; focus?: boolean; expand?: number | boolean } = {}): Promise { + if (this.filter?.activated) return + let isShown = this.getItemLnum(element) != null + let { select, focus, expand } = options + let curr = element + if (typeof this.provider.getParent !== 'function') { + throw new Error('missing getParent function from provider for reveal.') + } + if (!isShown) { + while (curr) { + let parentNode = await Promise.resolve(this.provider.getParent(curr)) + if (parentNode) { + let item = await this.getTreeItem(parentNode) + item.collapsibleState = TreeItemCollapsibleState.Expanded + curr = parentNode + } else { + break + } + } + } + if (expand) { + let item = await this.getTreeItem(element) + if (item.collapsibleState == TreeItemCollapsibleState.None) return + item.collapsibleState = TreeItemCollapsibleState.Expanded + if (typeof expand === 'number' && expand > 1) { + let curr = Math.min(expand, 2) + let nodes = await Promise.resolve(this.provider.getChildren(element)) + while (nodes?.length > 0) { + let arr: T[] = [] + for (let n of nodes) { + let item = await this.getTreeItem(n) + if (item.collapsibleState == TreeItemCollapsibleState.None) continue + item.collapsibleState = TreeItemCollapsibleState.Expanded + if (curr > 1) { + let res = await Promise.resolve(this.provider.getChildren(n)) + arr.push(...res) + } + } + nodes = arr + curr = curr - 1 + } + } + } + if (!isShown || expand) { + await this.render() + } + if (select !== false) this.selectItem(element) + if (focus) this.focusItem(element) + } + + private updateHeadLines(initialize = false): void { + let { titleCount, messageCount } = this.lineState + let end = initialize ? -1 : titleCount + messageCount + let lines: string[] = [] + let highlights: HighlightItem[] = [] + try { + if (this.message) { + highlights.push({ hlGroup: 'MoreMsg', colStart: 0, colEnd: byteLength(this.message), lnum: 0 }) + lines.push(this.message) + lines.push('') + } + if (this.title) { + highlights.push({ hlGroup: 'CocTreeTitle', colStart: 0, colEnd: byteLength(this.title), lnum: lines.length }) + if (this.description) { + let colStart = byteLength(this.title) + 1 + highlights.push({ hlGroup: 'Comment', colStart, colEnd: colStart + byteLength(this.description), lnum: lines.length }) + } + lines.push(this.title + (this.description ? ' ' + this.description : '')) + } + this.lineState.messageCount = this.message ? 2 : 0 + this.lineState.titleCount = this.title ? 1 : 0 + this.updateUI(lines, highlights, 0, end) + if (!initialize) { + this.refreshSigns() + } + } catch (e) { + this.nvim.errWriteLine('[coc.nvim] Error on update head lines:' + e.message) + logger.error('Error on update head lines:', e) + } + } + + /** + * Update signs after collapse/expand or head change + */ + private refreshSigns(): void { + let { selection, nvim, bufnr } = this + if (!selection.length || !bufnr || !workspace.env.sign) return + let buf = nvim.createBuffer(bufnr) + nvim.pauseNotification() + buf.unplaceSign({ group: 'CocTree' }) + for (let n of selection) { + let row = this.getItemLnum(n) + if (row == null) continue + buf.placeSign({ id: signOffset + row, lnum: row + 1, name: 'CocTreeSelected', group: 'CocTree' }) + } + void nvim.resumeNotification(false, true) + } + + // Render all tree items + private async render(): Promise { + if (!this.bufnr) return + let release = await this.mutex.acquire() + try { + let lines: string[] = [] + let highlights: HighlightItem[] = [] + let { startLnum } = this + let nodes = await Promise.resolve(this.provider.getChildren()) + let level = 0 + let lnum = startLnum + let renderedItems: RenderedItem[] = [] + if (!nodes?.length) { + this.message = 'No results' + } else { + for (let node of nodes) { + let n = await this.appendTreeNode(node, level, lnum, renderedItems, highlights) + lnum += n + } + } + lines.push(...renderedItems.map(o => o.line)) + this.renderedItems = renderedItems + let delta = this.startLnum - startLnum + if (delta) highlights.forEach(o => o.lnum = o.lnum + delta) + this.updateUI(lines, highlights, this.startLnum, -1) + this.retryTimers = 0 + release() + } catch (e) { + this.renderedItems = [] + this.nodesMap.clear() + this.lineState = { titleCount: 0, messageCount: 1 } + release() + let errMsg = `${e.message}`.replace(/\r?\n/g, ' ') + this.updateUI([errMsg], [{ hlGroup: 'WarningMsg', colStart: 0, colEnd: byteLength(errMsg), lnum: 0 }]) + if (this.retryTimers == 5) return + this.timer = setTimeout(() => { + this.retryTimers = this.retryTimers + 1 + void this.render() + }, 500) + } + } + + public async show(splitCommand = 'belowright 30vs'): Promise { + if (this.bufnr || this._creating) return + this._creating = true + let { nvim } = this + this.originalWin = await nvim.call('win_getid') + let winid = await nvim.call('coc#window#find', ['cocViewId', this.viewId]) + let id = globalId + globalId = globalId + 1 + nvim.pauseNotification() + if (winid != -1) { + nvim.call('win_gotoid', [winid], true) + nvim.command(`silent edit +setl\\ buftype=nofile CocTree${id}`, true) + } else { + nvim.command(`silent keepalt ${splitCommand} +setl\\ buftype=nofile CocTree${id}`, true) + } + nvim.command('setl bufhidden=wipe nolist nonumber norelativenumber foldcolumn=0', true) + nvim.command(`setl signcolumn=${this.canSelectMany ? 'yes' : 'no'}${this.winfixwidth ? ' winfixwidth' : ''}`, true) + nvim.command('setl nocursorline nobuflisted wrap undolevels=-1 filetype=coctree nomodifiable noswapfile', true) + nvim.command(`let w:cocViewId = "${this.viewId.replace(/"/g, '\\"')}"`, true) + nvim.call('bufnr', ['%'], true) + nvim.call('win_getid', [], true) + let res = await nvim.resumeNotification() + if (res[1]) throw new Error(`Error on buffer create:` + JSON.stringify(res[1])) + this._onDidChangeVisibility.fire({ visible: true }) + this.registerKeymaps() + let arr = res[0] + this.bufnr = arr[arr.length - 2] + this.winid = arr[arr.length - 1] + this._creating = false + this.updateHeadLines(true) + void this.render() + } + + private registerKeymaps(): void { + let { toggleSelection, actions, close, invoke, toggle, collapseAll, activeFilter } = this.keys + let { nvim } = this + const regist = (mode: 'n' | 'v' | 's' | 'x', key: string, fn: (element: T | undefined) => Promise, notify = false) => { + this.disposables.push(workspace.registerLocalKeymap(mode, key, async () => { + let lnum = await nvim.call('line', ['.']) + let element = this.getElementByLnum(lnum - 1) + if (element && !this.nodesMap.has(element)) return + await Promise.resolve(fn(element)) + }, notify)) + } + this.disposables.push(workspace.registerLocalKeymap('n', '', () => { + nvim.call('win_gotoid', [this.originalWin], true) + }, true)) + regist('n', '', async element => { + if (element) await this.onClick(element) + }) + this.filter && activeFilter && regist('n', activeFilter, async () => { + this.nvim.command(`exe ${this.startLnum}`, true) + this.filter.active() + this.filterText = '' + }, true) + toggleSelection && regist('n', toggleSelection, async element => { + if (element) this.toggleSelection(element) + }) + invoke && regist('n', invoke, async element => { + if (element) await this.invokeCommand(element) + }, true) + actions && regist('n', actions, async element => { + if (element) await this.invokeActions(element) + }, true) + toggle && regist('n', toggle, async element => { + if (element) await this.toggleExpand(element) + }, true) + collapseAll && regist('n', collapseAll, async () => { + for (let obj of this.nodesMap.values()) { + let item = obj.item + if (item.collapsibleState == TreeItemCollapsibleState.Expanded) { + item.collapsibleState = TreeItemCollapsibleState.Collapsed + } + } + await this.render() + }) + close && regist('n', close, async () => { + this.hide() + }, true) + } + + private hide(): void { + if (!this.bufnr) return + this.nvim.command(`bd! ${this.bufnr}`, true) + this.redraw() + this._onDidChangeVisibility.fire({ visible: false }) + this.bufnr = undefined + this.winid = undefined + } + + private redraw(): void { + if (workspace.isVim || this.filter?.activated) { + this.nvim.command('redraw', true) + } + } + + private cancelResolve(): void { + if (this.resolveTokenSource) { + this.resolveTokenSource.cancel() + this.resolveTokenSource = undefined + } + } + + public dispose(): void { + if (!this.provider) return + if (this.timer) { + clearTimeout(this.timer) + this.timer = undefined + } + this.filter?.dispose() + this._selection = [] + this.hide() + this.itemsToFilter = [] + this.cancelResolve() + this.tooltipFactory.dispose() + this.renderedItems = [] + this.nodesMap.clear() + this.provider = undefined + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/tree/filter.ts b/vim-config/plugins/coc.nvim/src/tree/filter.ts new file mode 100644 index 00000000..708501e4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/tree/filter.ts @@ -0,0 +1,95 @@ +import events from '../events' +import { Neovim } from '@chemzqm/neovim' +import { Disposable, Emitter, Event } from 'vscode-languageserver-protocol' +import { disposeAll } from '../util' +export const sessionKey = 'filter' + +export default class Filter { + private _activated = false + private text: string + private history: string[] = [] + private disposables: Disposable[] = [] + private readonly _onDidUpdate = new Emitter() + private readonly _onDidExit = new Emitter() + private readonly _onDidKeyPress = new Emitter() + public readonly onDidKeyPress: Event = this._onDidKeyPress.event + public readonly onDidUpdate: Event = this._onDidUpdate.event + public readonly onDidExit: Event = this._onDidExit.event + constructor(private nvim: Neovim, keys: string[]) { + this.text = '' + events.on('InputChar', (session, character) => { + if (session !== sessionKey || !this._activated) return + if (!keys.includes(character)) { + if (character.length == 1) { + this.text = this.text + character + this._onDidUpdate.fire(this.text) + return + } + if (character == '') { + this.text = this.text.slice(0, -1) + this._onDidUpdate.fire(this.text) + return + } + if (character == '') { + this.text = '' + this._onDidUpdate.fire(this.text) + return + } + if (character == '') { + let idx = this.history.indexOf(this.text) + let text = this.history[idx + 1] || this.history[0] + if (text) { + this.text = text + this._onDidUpdate.fire(this.text) + } + return + } + if (character == '') { + let idx = this.history.indexOf(this.text) + let text = this.history[idx - 1] || this.history[this.history.length - 1] + if (text) { + this.text = text + this._onDidUpdate.fire(this.text) + } + } + if (character == '' || character == '') { + this.deactivate() + return + } + } + this._onDidKeyPress.fire(character) + }, null, this.disposables) + } + + public active(): void { + if (this._activated) return + this._activated = true + this.text = '' + this.nvim.call('coc#prompt#start_prompt', [sessionKey], true) + } + + public deactivate(node?: T): void { + if (!this._activated) return + this.nvim.call('coc#prompt#stop_prompt', [sessionKey], true) + this._activated = false + let { text } = this + this.text = '' + this._onDidExit.fire(node) + if (text && !this.history.includes(text)) { + this.history.push(text) + } + } + + public get activated(): boolean { + return this._activated + } + + public dispose(): void { + this.deactivate() + this.history = [] + this._onDidKeyPress.dispose() + this._onDidUpdate.dispose() + this._onDidExit.dispose() + disposeAll(this.disposables) + } +} diff --git a/vim-config/plugins/coc.nvim/src/tree/index.ts b/vim-config/plugins/coc.nvim/src/tree/index.ts new file mode 100644 index 00000000..b1c70846 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/tree/index.ts @@ -0,0 +1,221 @@ +import { Disposable, Event, CancellationToken } from 'vscode-languageserver-protocol' +import { ProviderResult } from '../provider' +import { TreeItem, TreeItemIcon, TreeItemCollapsibleState } from './TreeItem' + +export { TreeItem, TreeItemIcon, TreeItemCollapsibleState } + +export interface TreeItemAction { + /** + * Label text in menu. + */ + title: string + handler: (item: T) => ProviderResult +} + +/** + * Options for creating a {@link TreeView} + */ +export interface TreeViewOptions { + /** + * Fixed width for window, default to true + */ + winfixwidth?: boolean + /** + * Enable filter feature, default to false + */ + enableFilter?: boolean + /** + * Disable indent of leaves without children, default to false + */ + disableLeafIndent?: boolean + /** + * A data provider that provides tree data. + */ + treeDataProvider: TreeDataProvider + /** + * Whether the tree supports multi-select. When the tree supports multi-select and a command is executed from the tree, + * the first argument to the command is the tree item that the command was executed on and the second argument is an + * array containing all selected tree items. + */ + canSelectMany?: boolean +} + +/** + * The event that is fired when an element in the {@link TreeView} is expanded or collapsed + */ +export interface TreeViewExpansionEvent { + /** + * Element that is expanded or collapsed. + */ + readonly element: T +} + +/** + * The event that is fired when there is a change in {@link TreeView.selection tree view's selection} + */ +export interface TreeViewSelectionChangeEvent { + readonly selection: T[] +} + +/** + * The event that is fired when there is a change in {@link TreeView.visible tree view's visibility} + */ +export interface TreeViewVisibilityChangeEvent { + readonly visible: boolean +} + +/** + * Represents a Tree view + */ +export interface TreeView extends Disposable { + + /** + * Event that is fired when an element is expanded + */ + readonly onDidExpandElement: Event> + + /** + * Event that is fired when an element is collapsed + */ + readonly onDidCollapseElement: Event> + + /** + * Currently selected elements. + */ + readonly selection: T[] + + /** + * Event that is fired when the {@link TreeView.selection selection} has changed + */ + readonly onDidChangeSelection: Event> + + /** + * `true` if the {@link TreeView tree view} is visible otherwise `false`. + * + * **NOTE:** is `true` when TreeView visible on other tab. + */ + readonly visible: boolean + + /** + * Window id used by TreeView. + */ + readonly windowId: number | undefined + + /** + * Event that is fired when {@link TreeView.visible visibility} has changed + */ + readonly onDidChangeVisibility: Event + + /** + * An optional human-readable message that will be rendered in the view. + * Setting the message to null, undefined, or empty string will remove the message from the view. + */ + message?: string + + /** + * The tree view title is initially taken from viewId of TreeView + * Changes to the title property will be properly reflected in the UI in the title of the view. + */ + title?: string + + /** + * An optional human-readable description which is rendered less prominently in the title of the view. + * Setting the title description to null, undefined, or empty string will remove the description from the view. + */ + description?: string + + /** + * Reveals the given element in the tree view. + * If the tree view is not visible then the tree view is shown and element is revealed. + * + * By default revealed element is selected. + * In order to not to select, set the option `select` to `false`. + * In order to focus, set the option `focus` to `true`. + * In order to expand the revealed element, set the option `expand` to `true`. To expand recursively set `expand` to the number of levels to expand. + * **NOTE:** You can expand only to 3 levels maximum. + * + * **NOTE:** The {@link TreeDataProvider} that the `TreeView` {@link window.createTreeView is registered with} with must implement {@link TreeDataProvider.getParent getParent} method to access this API. + */ + reveal(element: T, options?: { select?: boolean, focus?: boolean, expand?: boolean | number }): Thenable + + /** + * Create tree view in new window, does nothing when it's visible. + * + * **NOTE:** + * **NOTE:** TreeView with same viewId in current tab would be disposed. + * + * @param splitCommand The command to open TreeView window, default to 'belowright 30vs' + */ + show(splitCommand?: string): Promise +} + +/** + * A data provider that provides tree data + */ +export interface TreeDataProvider { + /** + * An optional event to signal that an element or root has changed. + * This will trigger the view to update the changed element/root and its children recursively (if shown). + * To signal that root has changed, do not pass any argument or pass `undefined` or `null`. + */ + onDidChangeTreeData?: Event + + /** + * Get {@link TreeItem} representation of the `element` + * + * @param element The element for which {@link TreeItem} representation is asked for. + * @return {@link TreeItem} representation of the element + */ + getTreeItem(element: T): TreeItem | Thenable + + /** + * Get the children of `element` or root if no element is passed. + * + * @param element The element from which the provider gets children. Can be `undefined`. + * @return Children of `element` or root if no element is passed. + */ + getChildren(element?: T): ProviderResult + + /** + * Optional method to return the parent of `element`. + * Return `null` or `undefined` if `element` is a child of root. + * + * **NOTE:** This method should be implemented in order to access {@link TreeView.reveal reveal} API. + * + * @param element The element for which the parent has to be returned. + * @return Parent of `element`. + */ + getParent?(element: T): ProviderResult + + /** + * Called on hover to resolve the {@link TreeItem.tooltip TreeItem} property if it is undefined. + * Called on tree item click/open to resolve the {@link TreeItem.command TreeItem} property if it is undefined. + * Only properties that were undefined can be resolved in `resolveTreeItem`. + * Functionality may be expanded later to include being called to resolve other missing + * properties on selection and/or on open. + * + * Will only ever be called once per TreeItem. + * + * onDidChangeTreeData should not be triggered from within resolveTreeItem. + * + * *Note* that this function is called when tree items are already showing in the UI. + * Because of that, no property that changes the presentation (label, description, etc.) + * can be changed. + * + * @param item Undefined properties of `item` should be set then `item` should be returned. + * @param element The object associated with the TreeItem. + * @param token A cancellation token. + * @return The resolved tree item or a thenable that resolves to such. It is OK to return the given + * `item`. When no result is returned, the given `item` will be used. + */ + resolveTreeItem?(item: TreeItem, element: T, token: CancellationToken): ProviderResult + + /** + * Called with current element to resolve actions. + * Called when user press 'actions' key. + * + * @param item Resolved item. + * @param element The object under cursor. + */ + resolveActions?(item: TreeItem, element: T): ProviderResult[]> +} diff --git a/vim-config/plugins/coc.nvim/src/types.ts b/vim-config/plugins/coc.nvim/src/types.ts new file mode 100644 index 00000000..2c1f217d --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/types.ts @@ -0,0 +1,870 @@ +// vim: set sw=2 ts=2 sts=2 et foldmarker={{,}} foldmethod=marker foldlevel=0 nofen: +import { Buffer, Neovim, Window } from '@chemzqm/neovim' +import { CancellationToken, CodeAction, CodeActionKind, CreateFile, CreateFileOptions, DeleteFile, DeleteFileOptions, Disposable, DocumentSelector, Event, FormattingOptions, Location, Position, Range, RenameFile, RenameFileOptions, SymbolKind, TextDocumentEdit, TextDocumentSaveReason, TextEdit, WorkspaceEdit, WorkspaceFolder } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import Configurations from './configuration' +import Document from './model/document' +import FileSystemWatcher from './model/fileSystemWatcher' +import { ProviderResult, TextDocumentContentProvider } from './provider' + +export interface Thenable { + then(onfulfilled?: (value: T) => TResult | Thenable, onrejected?: (reason: any) => TResult | Thenable): Thenable + // eslint-disable-next-line @typescript-eslint/unified-signatures + then(onfulfilled?: (value: T) => TResult | Thenable, onrejected?: (reason: any) => void): Thenable +} + +export type ProviderName = 'rename' | 'onTypeEdit' | 'documentLink' | 'documentColor' + | 'foldingRange' | 'format' | 'codeAction' | 'workspaceSymbols' | 'formatRange' | 'formatOnType' + | 'hover' | 'signature' | 'documentSymbol' | 'documentHighlight' | 'definition' + | 'declaration' | 'typeDefinition' | 'reference' | 'implementation' + | 'codeLens' | 'selectionRange' | 'callHierarchy' | 'semanticTokens' | 'linkedEditing' + +export interface CurrentState { + doc: Document + winid: number + position: Position + // :h mode() + mode: string +} + +export interface HandlerDelegate { + checkProvier: (id: ProviderName, document: TextDocument) => void + withRequestToken: (name: string, fn: (token: CancellationToken) => Thenable, checkEmpty?: boolean) => Promise + getCurrentState: () => Promise + addDisposable: (disposable: Disposable) => void + getIcon(kind: SymbolKind): { text: string, hlGroup: string } + getCodeActions(doc: Document, range?: Range, only?: CodeActionKind[]): Promise + applyCodeAction(action: CodeAction): Promise +} + +export interface FloatConfig { + border?: boolean + highlight?: string + title?: string + borderhighlight?: string + close?: boolean + maxHeight?: number + maxWidth?: number + winblend?: number + focusable?: boolean + shadow?: boolean +} + +/** + * Represent a highlight that not cross lines + * all zero based. + */ +export interface HighlightItem { + lnum: number + hlGroup: string + /** + * 0 based start column. + */ + colStart: number + /** + * 0 based end column. + */ + colEnd: number +} + +export interface BufferSyncItem { + /** + * Called on buffer unload. + */ + dispose: () => void + /** + * Called on buffer change. + */ + onChange?(e: DidChangeTextDocumentParams): void +} + +export interface Env { + completeOpt: string + runtimepath: string + disabledSources: { [filetype: string]: string[] } + readonly guicursor: string + readonly mode: string + readonly apiversion: number + readonly floating: boolean + readonly sign: boolean + readonly extensionRoot: string + readonly globalExtensions: string[] + readonly workspaceFolders: string[] + readonly config: any + readonly pid: number + readonly columns: number + readonly lines: number + readonly pumevent: boolean + readonly cmdheight: number + readonly filetypeMap: { [index: string]: string } + readonly isVim: boolean + readonly isCygwin: boolean + readonly isMacvim: boolean + readonly isiTerm: boolean + readonly version: string + readonly locationlist: boolean + readonly progpath: string + readonly dialog: boolean + readonly textprop: boolean + readonly updateHighlight: boolean + readonly vimCommands: CommandConfig[] +} + +export interface CommandConfig { + id: string + cmd: string + title?: string +} + +export interface EditerState { + document: TextDocument + position: Position +} + +/** + * An output channel is a container for readonly textual information. + * + * To get an instance of an `OutputChannel` use + * [createOutputChannel](#window.createOutputChannel). + */ +export interface OutputChannel { + + /** + * The human-readable name of this output channel. + */ + readonly name: string + + readonly content: string + /** + * Append the given value to the channel. + * + * @param value A string, falsy values will not be printed. + */ + append(value: string): void + + /** + * Append the given value and a line feed character + * to the channel. + * + * @param value A string, falsy values will be printed. + */ + appendLine(value: string): void + + /** + * Removes output from the channel. Latest `keep` lines will be remained. + */ + clear(keep?: number): void + + /** + * Reveal this channel in the UI. + * + * @param preserveFocus When `true` the channel will not take focus. + */ + show(preserveFocus?: boolean): void + + /** + * Hide this channel from the UI. + */ + hide(): void + + /** + * Dispose and free associated resources. + */ + dispose(): void +} + +export interface IWorkspace { + readonly nvim: Neovim + readonly cwd: string + readonly root: string + readonly isVim: boolean + readonly isNvim: boolean + readonly filetypes: Set + readonly pluginRoot: string + readonly initialized: boolean + readonly completeOpt: string + readonly channelNames: string[] + readonly documents: Document[] + readonly configurations: Configurations + textDocuments: TextDocument[] + workspaceFolder: WorkspaceFolder + onDidOpenTextDocument: Event + onDidCloseTextDocument: Event + onDidChangeTextDocument: Event + onWillSaveTextDocument: Event + onDidSaveTextDocument: Event + onDidChangeConfiguration: Event + onDidWorkspaceInitialized: Event + findUp(filename: string | string[]): Promise + getDocument(uri: number | string): Document + getFormatOptions(uri?: string): Promise + getConfigFile(target: ConfigurationTarget): string + applyEdit(edit: WorkspaceEdit): Promise + createFileSystemWatcher(globPattern: string, ignoreCreate?: boolean, ignoreChange?: boolean, ignoreDelete?: boolean): FileSystemWatcher + getConfiguration(section?: string, _resource?: string): WorkspaceConfiguration + registerTextDocumentContentProvider(scheme: string, provider: TextDocumentContentProvider): Disposable + getQuickfixItem(loc: Location, text?: string, type?: string): Promise + getLine(uri: string, line: number): Promise + readFile(uri: string): Promise + getCurrentState(): Promise + jumpTo(uri: string, position: Position): Promise + createFile(filepath: string, opts?: CreateFileOptions): Promise + renameFile(oldPath: string, newPath: string, opts?: RenameFileOptions): Promise + deleteFile(filepath: string, opts?: DeleteFileOptions): Promise + openResource(uri: string): Promise + resolveModule(name: string): Promise + match(selector: DocumentSelector, document: TextDocument): number + runCommand(cmd: string, cwd?: string, timeout?: number): Promise + dispose(): void +} + +// vim {{ +export interface LocationListItem { + bufnr: number + lnum: number + end_lnum: number + col: number + end_col: number + text: string + type: string +} + +export interface QuickfixItem { + uri?: string + module?: string + range?: Range + text?: string + type?: string + filename?: string + bufnr?: number + lnum?: number + end_lnum?: number + col?: number + end_col?: number + valid?: boolean + nr?: number +} +// }} + +// Enums{{ +export enum PatternType { + Buffer, + LanguageServer, + Global, +} + +export enum SourceType { + Native, + Remote, + Service, +} + +export enum MessageLevel { + More, + Warning, + Error +} + +export enum ConfigurationTarget { + Global, + User, + Workspace +} + +export enum ServiceStat { + Initial, + Starting, + StartFailed, + Running, + Stopping, + Stopped, +} + +export enum FileType { + /** + * The file type is unknown. + */ + Unknown = 0, + /** + * A regular file. + */ + File = 1, + /** + * A directory. + */ + Directory = 2, + /** + * A symbolic link to a file. + */ + SymbolicLink = 64 +} +// }} + +// TextDocument {{ +/** + * An event that is fired when a [document](#TextDocument) will be saved. + * + * To make modifications to the document before it is being saved, call the + * [`waitUntil`](#TextDocumentWillSaveEvent.waitUntil)-function with a thenable + * that resolves to an array of [text edits](#TextEdit). + */ +export interface TextDocumentWillSaveEvent { + + /** + * The document that will be saved. + */ + document: TextDocument + + /** + * The reason why save was triggered. + */ + reason: TextDocumentSaveReason + + /** + * Allows to pause the event loop and to apply [pre-save-edits](#TextEdit). + * Edits of subsequent calls to this function will be applied in order. The + * edits will be *ignored* if concurrent modifications of the document happened. + * + * *Note:* This function can only be called during event dispatch and not + * in an asynchronous manner: + * + * @param thenable A thenable that resolves to [pre-save-edits](#TextEdit). + */ + waitUntil(thenable: Thenable): void +} + +export type DocumentChange = TextDocumentEdit | CreateFile | RenameFile | DeleteFile + +/** + * An event describing a change to a text document. + */ +export interface TextDocumentContentChange { + /** + * The range of the document that changed. + */ + range: Range + /** + * The new text for the provided range. + */ + text: string +} + +export interface DidChangeTextDocumentParams { + /** + * The document that did change. The version number points + * to the version after all provided content changes have + * been applied. + */ + textDocument: { + version: number + uri: string + } + /** + * The actual content changes. The content changes describe single state changes + * to the document. So if there are two content changes c1 (at array index 0) and + * c2 (at array index 1) for a document in state S then c1 moves the document from + * S to S' and c2 from S' to S''. So c1 is computed on the state S and c2 is computed + * on the state S'. + */ + contentChanges: TextDocumentContentChange[] + /** + * Buffer number of document. + */ + bufnr: number + /** + * Original content before change + */ + original: string + /** + * Changed lines + */ + originalLines: ReadonlyArray +} +// }} + +// Completion {{ +export interface Documentation { + filetype: string + content: string + active?: [number, number] +} + +export interface VimCompleteItem { + word: string + abbr?: string + menu?: string + info?: string + kind?: string + icase?: number + equal?: number + dup?: number + empty?: number + user_data?: string +} + +export interface ExtendedCompleteItem extends VimCompleteItem { + score?: number + sortText?: string + sourceScore?: number + filterText?: string + isSnippet?: boolean + source?: string + matchScore?: number + priority?: number + preselect?: boolean + signature?: string + localBonus?: number + index?: number + // used for preview + documentation?: Documentation[] + detailShown?: number + // saved line for apply TextEdit + line?: string +} + +export interface CompleteResult { + items: ExtendedCompleteItem[] + isIncomplete?: boolean + startcol?: number + source?: string + priority?: number +} + +// option on complete & should_complete +export interface CompleteOption { + readonly bufnr: number + readonly line: string + col: number + input: string + filetype: string + readonly filepath: string + readonly word: string + triggerCharacter: string + // cursor position + colnr: number + readonly linenr: number + readonly synname: string + readonly source?: string + readonly blacklist: string[] + readonly changedtick: number + triggerForInComplete?: boolean +} + +export interface SourceStat { + name: string + priority: number + triggerCharacters: string[] + type: string + shortcut: string + filepath: string + disabled: boolean + filetypes: string[] +} + +export type SourceConfig = Omit, 'shortcut' | 'priority' | 'triggerOnly' | 'triggerCharacters' | 'triggerPatterns' | 'enable' | 'filetypes' | 'disableSyntaxes'> + +export interface ISource { + name: string + enable?: boolean + shortcut?: string + priority?: number + sourceType?: SourceType + optionalFns?: string[] + triggerCharacters?: string[] + triggerOnly?: boolean + triggerPatterns?: RegExp[] + disableSyntaxes?: string[] + isSnippet?: boolean + filetypes?: string[] + documentSelector?: DocumentSelector + filepath?: string + firstMatch?: boolean + refresh?(): Promise + toggle?(): void + onEnter?(bufnr: number): void + shouldComplete?(opt: CompleteOption): Promise + doComplete(opt: CompleteOption, token: CancellationToken): ProviderResult + onCompleteResolve?(item: ExtendedCompleteItem, token: CancellationToken): ProviderResult | void + onCompleteDone?(item: ExtendedCompleteItem, opt: CompleteOption): ProviderResult + shouldCommit?(item: ExtendedCompleteItem, character: string): boolean +} +// }} + +// Configuration {{ +/** + * An event describing the change in Configuration + */ +export interface ConfigurationChangeEvent { + + /** + * Returns `true` if the given section for the given resource (if provided) is affected. + * + * @param section Configuration name, supports _dotted_ names. + * @param resource A resource URI. + * @return `true` if the given section for the given resource (if provided) is affected. + */ + affectsConfiguration(section: string, resource?: string): boolean +} + +export interface WorkspaceConfiguration { + /** + * Return a value from this configuration. + * + * @param section Configuration name, supports _dotted_ names. + * @return The value `section` denotes or `undefined`. + */ + get(section: string): T | undefined + + /** + * Return a value from this configuration. + * + * @param section Configuration name, supports _dotted_ names. + * @param defaultValue A value should be returned when no value could be found, is `undefined`. + * @return The value `section` denotes or the default. + */ + get(section: string, defaultValue: T): T + + /** + * Check if this configuration has a certain value. + * + * @param section Configuration name, supports _dotted_ names. + * @return `true` if the section doesn't resolve to `undefined`. + */ + has(section: string): boolean + + /** + * Retrieve all information about a configuration setting. A configuration value + * often consists of a *default* value, a global or installation-wide value, + * a workspace-specific value + * + * *Note:* The configuration name must denote a leaf in the configuration tree + * (`editor.fontSize` vs `editor`) otherwise no result is returned. + * + * @param section Configuration name, supports _dotted_ names. + * @return Information about a configuration setting or `undefined`. + */ + inspect(section: string): ConfigurationInspect | undefined + /** + * Update a configuration value. The updated configuration values are persisted. + * + * + * @param section Configuration name, supports _dotted_ names. + * @param value The new value. + * @param isUser if true, always update user configuration + */ + update(section: string, value: any, isUser?: boolean): void + + /** + * Readable dictionary that backs this configuration. + */ + readonly [key: string]: any +} + +export interface ErrorItem { + location: Location + message: string +} + +export interface ConfigurationInspect { + key: string + defaultValue?: T + globalValue?: T + workspaceValue?: T +} + +export interface ConfigurationShape { + workspaceConfigFile: string + $updateConfigurationOption(target: ConfigurationTarget, key: string, value: any): void + $removeConfigurationOption(target: ConfigurationTarget, key: string): void +} + +export interface IConfigurationModel { + contents: any +} + +export interface IConfigurationData { + defaults: IConfigurationModel + user: IConfigurationModel + workspace: IConfigurationModel +} +// }} + +// File operation {{ +/** + * An event that is fired when files are going to be renamed. + * + * To make modifications to the workspace before the files are renamed, + * call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a + * thenable that resolves to a [workspace edit](#WorkspaceEdit). + */ +export interface FileWillRenameEvent { + + /** + * The files that are going to be renamed. + */ + readonly files: ReadonlyArray<{ oldUri: URI, newUri: URI }> + + /** + * Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit). + * + * *Note:* This function can only be called during event dispatch and not + * in an asynchronous manner: + * + * ```ts + * workspace.onWillCreateFiles(event => { + * // async, will *throw* an error + * setTimeout(() => event.waitUntil(promise)); + * + * // sync, OK + * event.waitUntil(promise); + * }) + * ``` + * + * @param thenable A thenable that delays saving. + */ + waitUntil(thenable: Thenable): void +} + +/** + * An event that is fired after files are renamed. + */ +export interface FileRenameEvent { + + /** + * The files that got renamed. + */ + readonly files: ReadonlyArray<{ oldUri: URI, newUri: URI }> +} + +/** + * An event that is fired when files are going to be created. + * + * To make modifications to the workspace before the files are created, + * call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a + * thenable that resolves to a [workspace edit](#WorkspaceEdit). + */ +export interface FileWillCreateEvent { + + /** + * The files that are going to be created. + */ + readonly files: ReadonlyArray + + /** + * Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit). + * + * *Note:* This function can only be called during event dispatch and not + * in an asynchronous manner: + * + * ```ts + * workspace.onWillCreateFiles(event => { + * // async, will *throw* an error + * setTimeout(() => event.waitUntil(promise)); + * + * // sync, OK + * event.waitUntil(promise); + * }) + * ``` + * + * @param thenable A thenable that delays saving. + */ + waitUntil(thenable: Thenable): void +} + +/** + * An event that is fired after files are created. + */ +export interface FileCreateEvent { + + /** + * The files that got created. + */ + readonly files: ReadonlyArray +} + +/** + * An event that is fired when files are going to be deleted. + * + * To make modifications to the workspace before the files are deleted, + * call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a + * thenable that resolves to a [workspace edit](#WorkspaceEdit). + */ +export interface FileWillDeleteEvent { + + /** + * The files that are going to be deleted. + */ + readonly files: ReadonlyArray + + /** + * Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit). + * + * *Note:* This function can only be called during event dispatch and not + * in an asynchronous manner: + * + * ```ts + * workspace.onWillCreateFiles(event => { + * // async, will *throw* an error + * setTimeout(() => event.waitUntil(promise)); + * + * // sync, OK + * event.waitUntil(promise); + * }) + * ``` + * + * @param thenable A thenable that delays saving. + */ + waitUntil(thenable: Thenable): void +} + +/** + * An event that is fired after files are deleted. + */ +export interface FileDeleteEvent { + + /** + * The files that got deleted. + */ + readonly files: ReadonlyArray +} +// }} + +// List {{ +export interface LocationWithLine { + uri: string + line: string + text?: string +} + +export interface ListItem { + label: string + filterText?: string + /** + * A string that should be used when comparing this item + * with other items, only used for fuzzy filter. + */ + sortText?: string + location?: Location | LocationWithLine | string + data?: any + ansiHighlights?: AnsiHighlight[] + resolved?: boolean +} + +export interface ListHighlights { + // column indexes + spans: [number, number][] + hlGroup?: string +} + +export interface ListItemWithHighlights extends ListItem { + highlights?: ListHighlights +} + +export interface AnsiHighlight { + span: [number, number] + hlGroup: string +} + +export interface ListItemsEvent { + items: ListItem[] + finished: boolean + append?: boolean + reload?: boolean +} + +export type ListMode = 'normal' | 'insert' + +export type Matcher = 'strict' | 'fuzzy' | 'regex' + +export interface ListOptions { + position: string + input: string + ignorecase: boolean + interactive: boolean + sort: boolean + mode: ListMode + matcher: Matcher + autoPreview: boolean + numberSelect: boolean + noQuit: boolean + first: boolean +} + +export interface ListContext { + args: string[] + input: string + cwd: string + options: ListOptions + window: Window + buffer: Buffer + listWindow: Window +} + +export interface ListAction { + name: string + persist?: boolean + reload?: boolean + parallel?: boolean + multiple?: boolean + execute: (item: ListItem | ListItem[], context: ListContext) => ProviderResult +} + +export interface ListTask { + on(event: 'data', callback: (item: ListItem) => void): void + on(event: 'end', callback: () => void): void + on(event: 'error', callback: (msg: string | Error) => void): void + dispose(): void +} + +export interface ListArgument { + key?: string + hasValue?: boolean + name: string + description: string +} + +export interface IList { + /** + * Unique name of list. + */ + name: string + /** + * Action list. + */ + actions: ListAction[] + /** + * Default action name. + */ + defaultAction: string + /** + * Load list items. + */ + loadItems(context: ListContext, token: CancellationToken): Promise + /** + * Resolve list item. + */ + resolveItem?(item: ListItem): Promise + /** + * Should be true when interactive is supported. + */ + interactive?: boolean + /** + * Description of list. + */ + description?: string + /** + * Detail description, shown in help. + */ + detail?: string + /** + * Options supported by list. + */ + options?: ListArgument[] + /** + * Highlight buffer by vim's syntax commands. + */ + doHighlight?(): void + dispose?(): void +} +// }} diff --git a/vim-config/plugins/coc.nvim/src/util/ansiparse.ts b/vim-config/plugins/coc.nvim/src/util/ansiparse.ts new file mode 100644 index 00000000..61fb37dd --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/ansiparse.ts @@ -0,0 +1,243 @@ +import { byteLength, upperFirst } from './string' + +export interface AnsiItem { + foreground?: string + background?: string + bold?: boolean + italic?: boolean + underline?: boolean + text: string +} + +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' +} + +export interface AnsiHighlight { + span: [number, number] + hlGroup: string +} + +export interface AnsiResult { + line: string + highlights: AnsiHighlight[] +} + +export function parseAnsiHighlights(line: string, markdown = false): AnsiResult { + let items = ansiparse(line) + let highlights: AnsiHighlight[] = [] + let newLabel = '' + for (let item of items) { + if (!item.text) continue + let { foreground, background, bold, italic, underline } = item + let len = byteLength(newLabel) + if (foreground || background || bold || italic || underline) { + let span: [number, number] = [len, len + byteLength(item.text)] + let hlGroup = '' + if (foreground && background) { + hlGroup = `CocList${upperFirst(foreground)}${upperFirst(background)}` + } else if (foreground) { + if (markdown) { + if (foreground == 'yellow') { + hlGroup = 'CocMarkdownCode' + } else if (foreground == 'blue') { + hlGroup = 'CocMarkdownLink' + } else if (foreground == 'magenta') { + hlGroup = 'CocMarkdownHeader' + } else { + hlGroup = `CocListFg${upperFirst(foreground)}` + } + } else { + hlGroup = `CocListFg${upperFirst(foreground)}` + } + } else if (background) { + hlGroup = `CocListBg${upperFirst(background)}` + } else if (bold) { + hlGroup = 'CocBold' + } else if (italic) { + hlGroup = 'CocItalic' + } else if (underline) { + hlGroup = 'CocUnderline' + } + highlights.push({ span, hlGroup }) + } + newLabel = newLabel + item.text + } + return { line: newLabel, highlights } +} + +export function ansiparse(str: string): AnsiItem[] { + // + // I'm terrible at writing parsers. + // + let matchingControl = null + let matchingData = null + let matchingText = '' + let ansiState = [] + let result = [] + let state: Partial = {} + 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++) { + 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 +} diff --git a/vim-config/plugins/coc.nvim/src/util/array.ts b/vim-config/plugins/coc.nvim/src/util/array.ts new file mode 100644 index 00000000..d123c055 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/array.ts @@ -0,0 +1,70 @@ + +export function intersect(array: T[], other: T[]): boolean { + for (let item of other) { + if (array.includes(item)) { + return true + } + } + return false +} + +export function splitArray(array: T[], fn: (item: T) => boolean): [T[], T[]] { + let res: [T[], T[]] = [[], []] + for (let item of array) { + if (fn(item)) { + res[0].push(item) + } else { + res[1].push(item) + } + } + return res +} + +export function tail(array: T[], n = 0): T { + return array[array.length - (1 + n)] +} + +export function group(array: T[], size: number): T[][] { + let len = array.length + let res: T[][] = [] + for (let i = 0; i < Math.ceil(len / size); i++) { + res.push(array.slice(i * size, (i + 1) * size)) + } + return res +} + +/** + * 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. + */ +export function distinct(array: T[], keyFn?: (t: T) => string): T[] { + if (!keyFn) { + return array.filter((element, position) => array.indexOf(element) === position) + } + + const seen: { [key: string]: boolean } = Object.create(null) + return array.filter(elem => { + const key = keyFn(elem) + if (seen[key]) { + return false + } + + seen[key] = true + + return true + }) +} + +export function lastIndex(array: T[], fn: (t: T) => boolean): number { + let i = array.length - 1 + while (i >= 0) { + if (fn(array[i])) { + break + } + i-- + } + return i +} + +export const flatMap = (xs: T[], f: (item: T) => U[]): U[] => + xs.reduce((x: U[], y: T) => [...x, ...f(y)], []) diff --git a/vim-config/plugins/coc.nvim/src/util/callSequence.ts b/vim-config/plugins/coc.nvim/src/util/callSequence.ts new file mode 100644 index 00000000..2b7a396f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/callSequence.ts @@ -0,0 +1,43 @@ + +export default class CallSequence { + private funcs: Set = new Set() + private _canceled = false + private _resolved = false + private promise: Promise + + public addFunction(fn: Function): void { + this.funcs.add(fn) + } + + public start(): Promise { + this.promise = new Promise(async (resolve, reject) => { + for (let fn of this.funcs) { + if (this._canceled) return resolve(true) + try { + let cancel = await Promise.resolve(fn()) + if (cancel === true) { + this._canceled = true + return resolve(true) + } + } catch (e) { + reject(e) + return + } + } + this._resolved = true + resolve(false) + }) + return this.promise + } + + public ready(): Promise { + return this.promise + } + + public cancel(): Promise { + if (this._resolved) return Promise.resolve(void 0) + if (this._canceled) return this.promise + this._canceled = true + return this.promise + } +} diff --git a/vim-config/plugins/coc.nvim/src/util/charCode.ts b/vim-config/plugins/coc.nvim/src/util/charCode.ts new file mode 100644 index 00000000..34f5a1bb --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/charCode.ts @@ -0,0 +1,424 @@ +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// Names from https://blog.codinghorror.com/ascii-pronunciation-rules-for-programmers/ + +/** + * An inlined enum containing useful character codes (to be used with String.charCodeAt). + * Please leave the const keyword such that it gets inlined when compiled to JavaScript! + */ +export const enum CharCode { + Null = 0, + /** + * The `\b` character. + */ + Backspace = 8, + /** + * The `\t` character. + */ + Tab = 9, + /** + * The `\n` character. + */ + LineFeed = 10, + /** + * The `\r` character. + */ + CarriageReturn = 13, + Space = 32, + /** + * The `!` character. + */ + ExclamationMark = 33, + /** + * The `"` character. + */ + DoubleQuote = 34, + /** + * The `#` character. + */ + Hash = 35, + /** + * The `$` character. + */ + DollarSign = 36, + /** + * The `%` character. + */ + PercentSign = 37, + /** + * The `&` character. + */ + Ampersand = 38, + /** + * The `'` character. + */ + SingleQuote = 39, + /** + * The `(` character. + */ + OpenParen = 40, + /** + * The `)` character. + */ + CloseParen = 41, + /** + * The `*` character. + */ + Asterisk = 42, + /** + * The `+` character. + */ + Plus = 43, + /** + * The `,` character. + */ + Comma = 44, + /** + * The `-` character. + */ + Dash = 45, + /** + * The `.` character. + */ + Period = 46, + /** + * The `/` character. + */ + Slash = 47, + + Digit0 = 48, + Digit1 = 49, + Digit2 = 50, + Digit3 = 51, + Digit4 = 52, + Digit5 = 53, + Digit6 = 54, + Digit7 = 55, + Digit8 = 56, + Digit9 = 57, + + /** + * The `:` character. + */ + Colon = 58, + /** + * The `;` character. + */ + Semicolon = 59, + /** + * The `<` character. + */ + LessThan = 60, + /** + * The `=` character. + */ + Equals = 61, + /** + * The `>` character. + */ + GreaterThan = 62, + /** + * The `?` character. + */ + QuestionMark = 63, + /** + * The `@` character. + */ + AtSign = 64, + + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + + /** + * The `[` character. + */ + OpenSquareBracket = 91, + /** + * The `\` character. + */ + Backslash = 92, + /** + * The `]` character. + */ + CloseSquareBracket = 93, + /** + * The `^` character. + */ + Caret = 94, + /** + * The `_` character. + */ + Underline = 95, + /** + * The ``(`)`` character. + */ + BackTick = 96, + + a = 97, + b = 98, + c = 99, + d = 100, + e = 101, + f = 102, + g = 103, + h = 104, + i = 105, + j = 106, + k = 107, + l = 108, + m = 109, + n = 110, + o = 111, + p = 112, + q = 113, + r = 114, + s = 115, + t = 116, + u = 117, + v = 118, + w = 119, + x = 120, + y = 121, + z = 122, + + /** + * The `{` character. + */ + OpenCurlyBrace = 123, + /** + * The `|` character. + */ + Pipe = 124, + /** + * The `}` character. + */ + CloseCurlyBrace = 125, + /** + * The `~` character. + */ + Tilde = 126, + + U_Combining_Grave_Accent = 0x0300, // U+0300 Combining Grave Accent + U_Combining_Acute_Accent = 0x0301, // U+0301 Combining Acute Accent + U_Combining_Circumflex_Accent = 0x0302, // U+0302 Combining Circumflex Accent + U_Combining_Tilde = 0x0303, // U+0303 Combining Tilde + U_Combining_Macron = 0x0304, // U+0304 Combining Macron + U_Combining_Overline = 0x0305, // U+0305 Combining Overline + U_Combining_Breve = 0x0306, // U+0306 Combining Breve + U_Combining_Dot_Above = 0x0307, // U+0307 Combining Dot Above + U_Combining_Diaeresis = 0x0308, // U+0308 Combining Diaeresis + U_Combining_Hook_Above = 0x0309, // U+0309 Combining Hook Above + U_Combining_Ring_Above = 0x030A, // U+030A Combining Ring Above + U_Combining_Double_Acute_Accent = 0x030B, // U+030B Combining Double Acute Accent + U_Combining_Caron = 0x030C, // U+030C Combining Caron + U_Combining_Vertical_Line_Above = 0x030D, // U+030D Combining Vertical Line Above + U_Combining_Double_Vertical_Line_Above = 0x030E, // U+030E Combining Double Vertical Line Above + U_Combining_Double_Grave_Accent = 0x030F, // U+030F Combining Double Grave Accent + U_Combining_Candrabindu = 0x0310, // U+0310 Combining Candrabindu + U_Combining_Inverted_Breve = 0x0311, // U+0311 Combining Inverted Breve + U_Combining_Turned_Comma_Above = 0x0312, // U+0312 Combining Turned Comma Above + U_Combining_Comma_Above = 0x0313, // U+0313 Combining Comma Above + U_Combining_Reversed_Comma_Above = 0x0314, // U+0314 Combining Reversed Comma Above + U_Combining_Comma_Above_Right = 0x0315, // U+0315 Combining Comma Above Right + U_Combining_Grave_Accent_Below = 0x0316, // U+0316 Combining Grave Accent Below + U_Combining_Acute_Accent_Below = 0x0317, // U+0317 Combining Acute Accent Below + U_Combining_Left_Tack_Below = 0x0318, // U+0318 Combining Left Tack Below + U_Combining_Right_Tack_Below = 0x0319, // U+0319 Combining Right Tack Below + U_Combining_Left_Angle_Above = 0x031A, // U+031A Combining Left Angle Above + U_Combining_Horn = 0x031B, // U+031B Combining Horn + U_Combining_Left_Half_Ring_Below = 0x031C, // U+031C Combining Left Half Ring Below + U_Combining_Up_Tack_Below = 0x031D, // U+031D Combining Up Tack Below + U_Combining_Down_Tack_Below = 0x031E, // U+031E Combining Down Tack Below + U_Combining_Plus_Sign_Below = 0x031F, // U+031F Combining Plus Sign Below + U_Combining_Minus_Sign_Below = 0x0320, // U+0320 Combining Minus Sign Below + U_Combining_Palatalized_Hook_Below = 0x0321, // U+0321 Combining Palatalized Hook Below + U_Combining_Retroflex_Hook_Below = 0x0322, // U+0322 Combining Retroflex Hook Below + U_Combining_Dot_Below = 0x0323, // U+0323 Combining Dot Below + U_Combining_Diaeresis_Below = 0x0324, // U+0324 Combining Diaeresis Below + U_Combining_Ring_Below = 0x0325, // U+0325 Combining Ring Below + U_Combining_Comma_Below = 0x0326, // U+0326 Combining Comma Below + U_Combining_Cedilla = 0x0327, // U+0327 Combining Cedilla + U_Combining_Ogonek = 0x0328, // U+0328 Combining Ogonek + U_Combining_Vertical_Line_Below = 0x0329, // U+0329 Combining Vertical Line Below + U_Combining_Bridge_Below = 0x032A, // U+032A Combining Bridge Below + U_Combining_Inverted_Double_Arch_Below = 0x032B, // U+032B Combining Inverted Double Arch Below + U_Combining_Caron_Below = 0x032C, // U+032C Combining Caron Below + U_Combining_Circumflex_Accent_Below = 0x032D, // U+032D Combining Circumflex Accent Below + U_Combining_Breve_Below = 0x032E, // U+032E Combining Breve Below + U_Combining_Inverted_Breve_Below = 0x032F, // U+032F Combining Inverted Breve Below + U_Combining_Tilde_Below = 0x0330, // U+0330 Combining Tilde Below + U_Combining_Macron_Below = 0x0331, // U+0331 Combining Macron Below + U_Combining_Low_Line = 0x0332, // U+0332 Combining Low Line + U_Combining_Double_Low_Line = 0x0333, // U+0333 Combining Double Low Line + U_Combining_Tilde_Overlay = 0x0334, // U+0334 Combining Tilde Overlay + U_Combining_Short_Stroke_Overlay = 0x0335, // U+0335 Combining Short Stroke Overlay + U_Combining_Long_Stroke_Overlay = 0x0336, // U+0336 Combining Long Stroke Overlay + U_Combining_Short_Solidus_Overlay = 0x0337, // U+0337 Combining Short Solidus Overlay + U_Combining_Long_Solidus_Overlay = 0x0338, // U+0338 Combining Long Solidus Overlay + U_Combining_Right_Half_Ring_Below = 0x0339, // U+0339 Combining Right Half Ring Below + U_Combining_Inverted_Bridge_Below = 0x033A, // U+033A Combining Inverted Bridge Below + U_Combining_Square_Below = 0x033B, // U+033B Combining Square Below + U_Combining_Seagull_Below = 0x033C, // U+033C Combining Seagull Below + U_Combining_X_Above = 0x033D, // U+033D Combining X Above + U_Combining_Vertical_Tilde = 0x033E, // U+033E Combining Vertical Tilde + U_Combining_Double_Overline = 0x033F, // U+033F Combining Double Overline + U_Combining_Grave_Tone_Mark = 0x0340, // U+0340 Combining Grave Tone Mark + U_Combining_Acute_Tone_Mark = 0x0341, // U+0341 Combining Acute Tone Mark + U_Combining_Greek_Perispomeni = 0x0342, // U+0342 Combining Greek Perispomeni + U_Combining_Greek_Koronis = 0x0343, // U+0343 Combining Greek Koronis + U_Combining_Greek_Dialytika_Tonos = 0x0344, // U+0344 Combining Greek Dialytika Tonos + U_Combining_Greek_Ypogegrammeni = 0x0345, // U+0345 Combining Greek Ypogegrammeni + U_Combining_Bridge_Above = 0x0346, // U+0346 Combining Bridge Above + U_Combining_Equals_Sign_Below = 0x0347, // U+0347 Combining Equals Sign Below + U_Combining_Double_Vertical_Line_Below = 0x0348, // U+0348 Combining Double Vertical Line Below + U_Combining_Left_Angle_Below = 0x0349, // U+0349 Combining Left Angle Below + U_Combining_Not_Tilde_Above = 0x034A, // U+034A Combining Not Tilde Above + U_Combining_Homothetic_Above = 0x034B, // U+034B Combining Homothetic Above + U_Combining_Almost_Equal_To_Above = 0x034C, // U+034C Combining Almost Equal To Above + U_Combining_Left_Right_Arrow_Below = 0x034D, // U+034D Combining Left Right Arrow Below + U_Combining_Upwards_Arrow_Below = 0x034E, // U+034E Combining Upwards Arrow Below + U_Combining_Grapheme_Joiner = 0x034F, // U+034F Combining Grapheme Joiner + U_Combining_Right_Arrowhead_Above = 0x0350, // U+0350 Combining Right Arrowhead Above + U_Combining_Left_Half_Ring_Above = 0x0351, // U+0351 Combining Left Half Ring Above + U_Combining_Fermata = 0x0352, // U+0352 Combining Fermata + U_Combining_X_Below = 0x0353, // U+0353 Combining X Below + U_Combining_Left_Arrowhead_Below = 0x0354, // U+0354 Combining Left Arrowhead Below + U_Combining_Right_Arrowhead_Below = 0x0355, // U+0355 Combining Right Arrowhead Below + U_Combining_Right_Arrowhead_And_Up_Arrowhead_Below = 0x0356, // U+0356 Combining Right Arrowhead And Up Arrowhead Below + U_Combining_Right_Half_Ring_Above = 0x0357, // U+0357 Combining Right Half Ring Above + U_Combining_Dot_Above_Right = 0x0358, // U+0358 Combining Dot Above Right + U_Combining_Asterisk_Below = 0x0359, // U+0359 Combining Asterisk Below + U_Combining_Double_Ring_Below = 0x035A, // U+035A Combining Double Ring Below + U_Combining_Zigzag_Above = 0x035B, // U+035B Combining Zigzag Above + U_Combining_Double_Breve_Below = 0x035C, // U+035C Combining Double Breve Below + U_Combining_Double_Breve = 0x035D, // U+035D Combining Double Breve + U_Combining_Double_Macron = 0x035E, // U+035E Combining Double Macron + U_Combining_Double_Macron_Below = 0x035F, // U+035F Combining Double Macron Below + U_Combining_Double_Tilde = 0x0360, // U+0360 Combining Double Tilde + U_Combining_Double_Inverted_Breve = 0x0361, // U+0361 Combining Double Inverted Breve + U_Combining_Double_Rightwards_Arrow_Below = 0x0362, // U+0362 Combining Double Rightwards Arrow Below + U_Combining_Latin_Small_Letter_A = 0x0363, // U+0363 Combining Latin Small Letter A + U_Combining_Latin_Small_Letter_E = 0x0364, // U+0364 Combining Latin Small Letter E + U_Combining_Latin_Small_Letter_I = 0x0365, // U+0365 Combining Latin Small Letter I + U_Combining_Latin_Small_Letter_O = 0x0366, // U+0366 Combining Latin Small Letter O + U_Combining_Latin_Small_Letter_U = 0x0367, // U+0367 Combining Latin Small Letter U + U_Combining_Latin_Small_Letter_C = 0x0368, // U+0368 Combining Latin Small Letter C + U_Combining_Latin_Small_Letter_D = 0x0369, // U+0369 Combining Latin Small Letter D + U_Combining_Latin_Small_Letter_H = 0x036A, // U+036A Combining Latin Small Letter H + U_Combining_Latin_Small_Letter_M = 0x036B, // U+036B Combining Latin Small Letter M + U_Combining_Latin_Small_Letter_R = 0x036C, // U+036C Combining Latin Small Letter R + U_Combining_Latin_Small_Letter_T = 0x036D, // U+036D Combining Latin Small Letter T + U_Combining_Latin_Small_Letter_V = 0x036E, // U+036E Combining Latin Small Letter V + U_Combining_Latin_Small_Letter_X = 0x036F, // U+036F Combining Latin Small Letter X + + /** + * Unicode Character 'LINE SEPARATOR' (U+2028) + * http://www.fileformat.info/info/unicode/char/2028/index.htm + */ + LINE_SEPARATOR_2028 = 8232, + + // http://www.fileformat.info/info/unicode/category/Sk/list.htm + U_CIRCUMFLEX = 0x005E, // U+005E CIRCUMFLEX + U_GRAVE_ACCENT = 0x0060, // U+0060 GRAVE ACCENT + U_DIAERESIS = 0x00A8, // U+00A8 DIAERESIS + U_MACRON = 0x00AF, // U+00AF MACRON + U_ACUTE_ACCENT = 0x00B4, // U+00B4 ACUTE ACCENT + U_CEDILLA = 0x00B8, // U+00B8 CEDILLA + U_MODIFIER_LETTER_LEFT_ARROWHEAD = 0x02C2, // U+02C2 MODIFIER LETTER LEFT ARROWHEAD + U_MODIFIER_LETTER_RIGHT_ARROWHEAD = 0x02C3, // U+02C3 MODIFIER LETTER RIGHT ARROWHEAD + U_MODIFIER_LETTER_UP_ARROWHEAD = 0x02C4, // U+02C4 MODIFIER LETTER UP ARROWHEAD + U_MODIFIER_LETTER_DOWN_ARROWHEAD = 0x02C5, // U+02C5 MODIFIER LETTER DOWN ARROWHEAD + U_MODIFIER_LETTER_CENTRED_RIGHT_HALF_RING = 0x02D2, // U+02D2 MODIFIER LETTER CENTRED RIGHT HALF RING + U_MODIFIER_LETTER_CENTRED_LEFT_HALF_RING = 0x02D3, // U+02D3 MODIFIER LETTER CENTRED LEFT HALF RING + U_MODIFIER_LETTER_UP_TACK = 0x02D4, // U+02D4 MODIFIER LETTER UP TACK + U_MODIFIER_LETTER_DOWN_TACK = 0x02D5, // U+02D5 MODIFIER LETTER DOWN TACK + U_MODIFIER_LETTER_PLUS_SIGN = 0x02D6, // U+02D6 MODIFIER LETTER PLUS SIGN + U_MODIFIER_LETTER_MINUS_SIGN = 0x02D7, // U+02D7 MODIFIER LETTER MINUS SIGN + U_BREVE = 0x02D8, // U+02D8 BREVE + U_DOT_ABOVE = 0x02D9, // U+02D9 DOT ABOVE + U_RING_ABOVE = 0x02DA, // U+02DA RING ABOVE + U_OGONEK = 0x02DB, // U+02DB OGONEK + U_SMALL_TILDE = 0x02DC, // U+02DC SMALL TILDE + U_DOUBLE_ACUTE_ACCENT = 0x02DD, // U+02DD DOUBLE ACUTE ACCENT + U_MODIFIER_LETTER_RHOTIC_HOOK = 0x02DE, // U+02DE MODIFIER LETTER RHOTIC HOOK + U_MODIFIER_LETTER_CROSS_ACCENT = 0x02DF, // U+02DF MODIFIER LETTER CROSS ACCENT + U_MODIFIER_LETTER_EXTRA_HIGH_TONE_BAR = 0x02E5, // U+02E5 MODIFIER LETTER EXTRA-HIGH TONE BAR + U_MODIFIER_LETTER_HIGH_TONE_BAR = 0x02E6, // U+02E6 MODIFIER LETTER HIGH TONE BAR + U_MODIFIER_LETTER_MID_TONE_BAR = 0x02E7, // U+02E7 MODIFIER LETTER MID TONE BAR + U_MODIFIER_LETTER_LOW_TONE_BAR = 0x02E8, // U+02E8 MODIFIER LETTER LOW TONE BAR + U_MODIFIER_LETTER_EXTRA_LOW_TONE_BAR = 0x02E9, // U+02E9 MODIFIER LETTER EXTRA-LOW TONE BAR + U_MODIFIER_LETTER_YIN_DEPARTING_TONE_MARK = 0x02EA, // U+02EA MODIFIER LETTER YIN DEPARTING TONE MARK + U_MODIFIER_LETTER_YANG_DEPARTING_TONE_MARK = 0x02EB, // U+02EB MODIFIER LETTER YANG DEPARTING TONE MARK + U_MODIFIER_LETTER_UNASPIRATED = 0x02ED, // U+02ED MODIFIER LETTER UNASPIRATED + U_MODIFIER_LETTER_LOW_DOWN_ARROWHEAD = 0x02EF, // U+02EF MODIFIER LETTER LOW DOWN ARROWHEAD + U_MODIFIER_LETTER_LOW_UP_ARROWHEAD = 0x02F0, // U+02F0 MODIFIER LETTER LOW UP ARROWHEAD + U_MODIFIER_LETTER_LOW_LEFT_ARROWHEAD = 0x02F1, // U+02F1 MODIFIER LETTER LOW LEFT ARROWHEAD + U_MODIFIER_LETTER_LOW_RIGHT_ARROWHEAD = 0x02F2, // U+02F2 MODIFIER LETTER LOW RIGHT ARROWHEAD + U_MODIFIER_LETTER_LOW_RING = 0x02F3, // U+02F3 MODIFIER LETTER LOW RING + U_MODIFIER_LETTER_MIDDLE_GRAVE_ACCENT = 0x02F4, // U+02F4 MODIFIER LETTER MIDDLE GRAVE ACCENT + U_MODIFIER_LETTER_MIDDLE_DOUBLE_GRAVE_ACCENT = 0x02F5, // U+02F5 MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT + U_MODIFIER_LETTER_MIDDLE_DOUBLE_ACUTE_ACCENT = 0x02F6, // U+02F6 MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT + U_MODIFIER_LETTER_LOW_TILDE = 0x02F7, // U+02F7 MODIFIER LETTER LOW TILDE + U_MODIFIER_LETTER_RAISED_COLON = 0x02F8, // U+02F8 MODIFIER LETTER RAISED COLON + U_MODIFIER_LETTER_BEGIN_HIGH_TONE = 0x02F9, // U+02F9 MODIFIER LETTER BEGIN HIGH TONE + U_MODIFIER_LETTER_END_HIGH_TONE = 0x02FA, // U+02FA MODIFIER LETTER END HIGH TONE + U_MODIFIER_LETTER_BEGIN_LOW_TONE = 0x02FB, // U+02FB MODIFIER LETTER BEGIN LOW TONE + U_MODIFIER_LETTER_END_LOW_TONE = 0x02FC, // U+02FC MODIFIER LETTER END LOW TONE + U_MODIFIER_LETTER_SHELF = 0x02FD, // U+02FD MODIFIER LETTER SHELF + U_MODIFIER_LETTER_OPEN_SHELF = 0x02FE, // U+02FE MODIFIER LETTER OPEN SHELF + U_MODIFIER_LETTER_LOW_LEFT_ARROW = 0x02FF, // U+02FF MODIFIER LETTER LOW LEFT ARROW + U_GREEK_LOWER_NUMERAL_SIGN = 0x0375, // U+0375 GREEK LOWER NUMERAL SIGN + U_GREEK_TONOS = 0x0384, // U+0384 GREEK TONOS + U_GREEK_DIALYTIKA_TONOS = 0x0385, // U+0385 GREEK DIALYTIKA TONOS + U_GREEK_KORONIS = 0x1FBD, // U+1FBD GREEK KORONIS + U_GREEK_PSILI = 0x1FBF, // U+1FBF GREEK PSILI + U_GREEK_PERISPOMENI = 0x1FC0, // U+1FC0 GREEK PERISPOMENI + U_GREEK_DIALYTIKA_AND_PERISPOMENI = 0x1FC1, // U+1FC1 GREEK DIALYTIKA AND PERISPOMENI + U_GREEK_PSILI_AND_VARIA = 0x1FCD, // U+1FCD GREEK PSILI AND VARIA + U_GREEK_PSILI_AND_OXIA = 0x1FCE, // U+1FCE GREEK PSILI AND OXIA + U_GREEK_PSILI_AND_PERISPOMENI = 0x1FCF, // U+1FCF GREEK PSILI AND PERISPOMENI + U_GREEK_DASIA_AND_VARIA = 0x1FDD, // U+1FDD GREEK DASIA AND VARIA + U_GREEK_DASIA_AND_OXIA = 0x1FDE, // U+1FDE GREEK DASIA AND OXIA + U_GREEK_DASIA_AND_PERISPOMENI = 0x1FDF, // U+1FDF GREEK DASIA AND PERISPOMENI + U_GREEK_DIALYTIKA_AND_VARIA = 0x1FED, // U+1FED GREEK DIALYTIKA AND VARIA + U_GREEK_DIALYTIKA_AND_OXIA = 0x1FEE, // U+1FEE GREEK DIALYTIKA AND OXIA + U_GREEK_VARIA = 0x1FEF, // U+1FEF GREEK VARIA + U_GREEK_OXIA = 0x1FFD, // U+1FFD GREEK OXIA + U_GREEK_DASIA = 0x1FFE, // U+1FFE GREEK DASIA + + U_OVERLINE = 0x203E, // Unicode Character 'OVERLINE' + + /** + * UTF-8 BOM + * Unicode Character 'ZERO WIDTH NO-BREAK SPACE' (U+FEFF) + * http://www.fileformat.info/info/unicode/char/feff/index.htm + */ + UTF8_BOM = 65279 +} diff --git a/vim-config/plugins/coc.nvim/src/util/color.ts b/vim-config/plugins/coc.nvim/src/util/color.ts new file mode 100644 index 00000000..00a92551 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/color.ts @@ -0,0 +1,32 @@ +import { Color } from 'vscode-languageserver-protocol' + +function pad(str: string): string { + return str.length == 1 ? `0${str}` : str +} + +export function toHexString(color: Color): string { + let c = toHexColor(color) + return `${pad(c.red.toString(16))}${pad(c.green.toString(16))}${pad(c.blue.toString(16))}` +} + +export function toHexColor(color: Color): { red: number; green: number; blue: number } { + let { red, green, blue } = color + return { + red: Math.round(red * 255), + green: Math.round(green * 255), + blue: Math.round(blue * 255) + } +} + +export function isDark(color: Color): boolean { + // 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 +} + diff --git a/vim-config/plugins/coc.nvim/src/util/convert.ts b/vim-config/plugins/coc.nvim/src/util/convert.ts new file mode 100644 index 00000000..48c7c2b2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/convert.ts @@ -0,0 +1,60 @@ +import { SymbolKind } from 'vscode-languageserver-protocol' + +export function getSymbolKind(kind: SymbolKind): string { + switch (kind) { + case SymbolKind.File: + return 'File' + case SymbolKind.Module: + return 'Module' + case SymbolKind.Namespace: + return 'Namespace' + case SymbolKind.Package: + return 'Package' + case SymbolKind.Class: + return 'Class' + case SymbolKind.Method: + return 'Method' + case SymbolKind.Property: + return 'Property' + case SymbolKind.Field: + return 'Field' + case SymbolKind.Constructor: + return 'Constructor' + case SymbolKind.Enum: + return 'Enum' + case SymbolKind.Interface: + return 'Interface' + case SymbolKind.Function: + return 'Function' + case SymbolKind.Variable: + return 'Variable' + case SymbolKind.Constant: + return 'Constant' + case SymbolKind.String: + return 'String' + case SymbolKind.Number: + return 'Number' + case SymbolKind.Boolean: + return 'Boolean' + case SymbolKind.Array: + return 'Array' + case SymbolKind.Object: + return 'Object' + case SymbolKind.Key: + return 'Key' + case SymbolKind.Null: + return 'Null' + case SymbolKind.EnumMember: + return 'EnumMember' + case SymbolKind.Struct: + return 'Struct' + case SymbolKind.Event: + return 'Event' + case SymbolKind.Operator: + return 'Operator' + case SymbolKind.TypeParameter: + return 'TypeParameter' + default: + return 'Unknown' + } +} diff --git a/vim-config/plugins/coc.nvim/src/util/decorator.ts b/vim-config/plugins/coc.nvim/src/util/decorator.ts new file mode 100644 index 00000000..d1bbde6b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/decorator.ts @@ -0,0 +1,19 @@ +const logger = require('./logger')('util-decorator') + +export function memorize Promise>(_target: any, key: string, descriptor: any): void { + let fn = descriptor.value + if (typeof fn !== 'function') return + let memoKey = '$' + key + + descriptor.value = function(...args): Promise { + if (this.hasOwnProperty(memoKey)) return Promise.resolve(this[memoKey]) + return new Promise((resolve, reject): void => { + Promise.resolve(fn.apply(this, args)).then(res => { + this[memoKey] = res + resolve(res) + }, e => { + reject(e) + }) + }) + } +} diff --git a/vim-config/plugins/coc.nvim/src/util/diff.ts b/vim-config/plugins/coc.nvim/src/util/diff.ts new file mode 100644 index 00000000..83b42d71 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/diff.ts @@ -0,0 +1,140 @@ +import fastDiff from 'fast-diff' +import { byteLength } from './string' +const logger = require('./logger')('util-diff') + +export interface ChangedLines { + start: number + end: number + replacement: string[] +} + +interface Change { + start: number + end: number + newText: string +} + +export function diffLines(oldLines: ReadonlyArray, newLines: ReadonlyArray, startLine: number): ChangedLines { + let endOffset = 0 + let startOffset = 0 + let parts = oldLines.slice(startLine + 1) + for (let i = 0; i < Math.min(parts.length, newLines.length); i++) { + if (parts[parts.length - 1 - i] == newLines[newLines.length - 1 - i]) { + endOffset = endOffset + 1 + } else { + break + } + } + for (let i = 0; i <= Math.min(startLine, newLines.length - 1 - endOffset); i++) { + if (oldLines[i] == newLines[i]) { + startOffset = startOffset + 1 + } else { + break + } + } + let replacement = newLines.slice(startOffset, newLines.length - endOffset) + let end = oldLines.length - endOffset + if (end > startOffset && replacement.length) { + let offset = 0 + for (let i = 0; i < Math.min(replacement.length, end - startOffset); i++) { + if (replacement[i] == oldLines[startOffset + i]) { + offset = offset + 1 + } else { + break + } + } + if (offset) { + return { + start: startOffset + offset, + end, + replacement: replacement.slice(offset) + } + } + } + return { + start: startOffset, + end, + replacement + } +} + +export function getChange(oldStr: string, newStr: string, cursorEnd?: number): Change { + let ol = oldStr.length + let nl = newStr.length + let max = Math.min(ol, nl) + let newText = '' + let startOffset = 0 + let endOffset = -1 + let shouldLimit = false + // find first endOffset, could <= this. one + for (let i = 0; i <= max; i++) { + if (cursorEnd != null && i == cursorEnd) { + endOffset = i + shouldLimit = true + break + } + if (oldStr[ol - i - 1] != newStr[nl - i - 1]) { + endOffset = i + break + } + } + if (endOffset == -1) return null + // find start offset + let remain = max - endOffset + if (remain == 0) { + startOffset = 0 + } else { + for (let i = 0; i <= remain; i++) { + if (oldStr[i] != newStr[i] || i == remain) { + startOffset = i + break + } + } + } + // limit to minimal change + remain = remain - startOffset + if (shouldLimit && remain > 0) { + let end = endOffset + for (let i = 0; i < remain; i++) { + let oc = oldStr[ol - end - 1 - i] + let nc = newStr[nl - end - 1 - i] + if (oc == nc) { + endOffset = endOffset + 1 + } else { + break + } + } + } + let end = ol - endOffset + if (ol == nl && startOffset == end) return null + newText = newStr.slice(startOffset, nl - endOffset) + // optimize for add new line(s) + if (startOffset == end) { + let pre = startOffset == 0 ? '' : newStr[startOffset - 1] + if (pre && pre != '\n' + && oldStr[startOffset] == '\n' + && newText.startsWith('\n')) { + return { start: startOffset + 1, end: end + 1, newText: newText.slice(1) + '\n' } + } + } + return { start: startOffset, end, newText } +} + +export function patchLine(from: string, to: string, fill = ' '): string { + if (from == to) return to + let idx = to.indexOf(from) + if (idx !== -1) return fill.repeat(idx) + from + let result = fastDiff(from, to) + let str = '' + for (let item of result) { + if (item[0] == fastDiff.DELETE) { + // not allowed + return to + } else if (item[0] == fastDiff.INSERT) { + str = str + fill.repeat(byteLength(item[1])) + } else { + str = str + item[1] + } + } + return str +} diff --git a/vim-config/plugins/coc.nvim/src/util/extensions.ts b/vim-config/plugins/coc.nvim/src/util/extensions.ts new file mode 100644 index 00000000..aaf59ead --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/extensions.ts @@ -0,0 +1,15 @@ +declare interface Promise { + /** + * Catches task error and ignores them. + */ + logError(): void +} + +/** + * Explicitly tells that promise should be run asynchonously. + */ +Promise.prototype.logError = function (this: Promise): void { + this.catch(e => { + require('./logger')('extensions').error(e) + }) +} diff --git a/vim-config/plugins/coc.nvim/src/util/factory.ts b/vim-config/plugins/coc.nvim/src/util/factory.ts new file mode 100644 index 00000000..79890865 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/factory.ts @@ -0,0 +1,171 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +import fs from 'fs' +import { Logger } from 'log4js' +import path from 'path' +import * as vm from 'vm' +import { defaults } from './lodash' +const createLogger = require('./logger') +const logger = createLogger('util-factoroy') + +export interface ExtensionExport { + activate: (context: unknown) => any + deactivate: () => any | null +} + +export interface IModule { + new(name: string): any + _resolveFilename: (file: string, context: any) => string + _extensions: {} + _cache: { [file: string]: any } + _compile: () => void + wrap: (content: string) => string + require: (file: string) => NodeModule + _nodeModulePaths: (filename: string) => string[] +} + +const Module: IModule = require('module') +const REMOVED_GLOBALS = [ + 'reallyExit', + 'abort', + 'umask', + 'setuid', + 'setgid', + 'setgroups', + '_fatalException', + 'exit', + 'kill', +] + +function removedGlobalStub(name: string): Function { + return () => { + throw new Error(`process.${name}() is not allowed in extension sandbox`) + } +} + +// @see node/lib/internal/module.js +function makeRequireFunction(this: any): any { + const req: any = (p: string) => { + if (p === 'coc.nvim') { + return require('../index') + } + return this.require(p) + } + req.resolve = (request: string) => 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: ISandbox): Function { + // eslint-disable-next-line + return function(this: any, content: string, filename: string): any { + 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) + } +} + +export interface ISandbox { + process: NodeJS.Process + module: NodeModule + require: (p: string) => any + console: { [key in keyof Console]?: Function } + Buffer: any + Reflect: any + // eslint-disable-next-line id-blacklist + String: any + Promise: any +} + +function createSandbox(filename: string, logger: Logger): ISandbox { + const module = new Module(filename) + module.paths = Module._nodeModulePaths(filename) + + const sandbox = vm.createContext({ + module, + Buffer, + console: { + debug: (...args: any[]) => { + logger.debug.apply(logger, args) + }, + log: (...args: any[]) => { + logger.info.apply(logger, args) + }, + error: (...args: any[]) => { + logger.error.apply(logger, args) + }, + info: (...args: any[]) => { + logger.info.apply(logger, args) + }, + warn: (...args: any[]) => { + logger.warn.apply(logger, args) + } + } + }) as ISandbox + + defaults(sandbox, global) + sandbox.Reflect = Reflect + + sandbox.require = function sandboxRequire(p): any { + 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 as any).constructor() + for (let key of Object.keys(process)) { + sandbox.process[key] = process[key] + } + + REMOVED_GLOBALS.forEach(name => { + sandbox.process[name] = removedGlobalStub(name) + }) + sandbox.process['chdir'] = () => {} + + // read-only umask + sandbox.process.umask = (mask?: number) => { + 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 +export function createExtension(id: string, filename: string, isEmpty = false): ExtensionExport { + if (isEmpty || !fs.existsSync(filename)) return { + activate: () => {}, + deactivate: null + } + const sandbox = createSandbox(filename, createLogger(`extension:${id}`)) + + delete Module._cache[require.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') { + return { activate: () => {}, deactivate: null } + } + return { + activate, + deactivate: typeof defaultImport.deactivate === 'function' ? defaultImport.deactivate : null + } +} diff --git a/vim-config/plugins/coc.nvim/src/util/fs.ts b/vim-config/plugins/coc.nvim/src/util/fs.ts new file mode 100644 index 00000000..af5f44d8 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/fs.ts @@ -0,0 +1,251 @@ +import { exec } from 'child_process' +import fs from 'fs-extra' +import net from 'net' +import os from 'os' +import path from 'path' +import readline from 'readline' +import util from 'util' +import minimatch from 'minimatch' +const logger = require('./logger')('util-fs') + +export type OnReadLine = (line: string) => void + +export async function statAsync(filepath: string): Promise { + let stat = null + try { + stat = await fs.stat(filepath) + } catch (e) { } + return stat +} + +export async function isDirectory(filepath: string): Promise { + let stat = await statAsync(filepath) + return stat && stat.isDirectory() +} + +export async function unlinkAsync(filepath: string): Promise { + try { + await fs.unlink(filepath) + } catch (e) { } +} + +export function renameAsync(oldPath: string, newPath: string): Promise { + return new Promise((resolve, reject) => { + fs.rename(oldPath, newPath, err => { + if (err) return reject(err) + resolve() + }) + }) +} + +export async function isGitIgnored(fullpath: string): Promise { + if (!fullpath) return false + let stat = await statAsync(fullpath) + if (!stat || !stat.isFile()) return false + let root = null + try { + let { stdout } = await util.promisify(exec)('git rev-parse --show-toplevel', { cwd: path.dirname(fullpath) }) + root = stdout.trim() + } catch (e) { } + if (!root) return false + let file = path.relative(root, fullpath) + try { + let { stdout } = await util.promisify(exec)(`git check-ignore ${file}`, { cwd: root }) + return stdout.trim() == file + } catch (e) { } + return false +} + +export function resolveRoot(folder: string, subs: string[], cwd?: string, bottomup = false, checkCwd = true): string | null { + let home = os.homedir() + let dir = fixDriver(folder) + if (isParentFolder(dir, home, true)) return null + if (checkCwd && cwd && isParentFolder(cwd, dir, true) && inDirectory(cwd, subs)) return cwd + let parts = dir.split(path.sep) + if (bottomup) { + while (parts.length > 0) { + let dir = parts.join(path.sep) + if (dir == home) { + break + } + if (dir != home && inDirectory(dir, subs)) { + return dir + } + parts.pop() + } + return null + } else { + let curr: string[] = [parts.shift()] + for (let part of parts) { + curr.push(part) + let dir = curr.join(path.sep) + if (dir != home && inDirectory(dir, subs)) { + return dir + } + } + return null + } +} + +export function inDirectory(dir: string, subs: string[]): boolean { + try { + let files = fs.readdirSync(dir) + for (let pattern of subs) { + // note, only '*' expanded + let is_wildcard = (pattern.includes('*')) + let res = is_wildcard ? + (minimatch.match(files, pattern, { nobrace: true, noext: true, nocomment: true, nonegate: true, dot: true }).length !== 0) : + (files.includes(pattern)) + if (res) return true + } + } catch (e) { + // could be failed without permission + } + return false +} + +export function findUp(name: string | string[], cwd: string): string { + let root = path.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.join(cwd, sub) + if (fs.existsSync(filepath)) { + return filepath + } + } + } + cwd = path.dirname(cwd) + } + return null +} + +export function readFile(fullpath: string, encoding: string): Promise { + return new Promise((resolve, reject) => { + fs.readFile(fullpath, encoding, (err, content) => { + if (err) reject(err) + resolve(content) + }) + }) +} + +export function getFileLineCount(filepath: string): Promise { + let i + let count = 0 + return new Promise((resolve, reject) => { + fs.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)) + }) +} + +export function readFileLines(fullpath: string, start: number, end: number): Promise { + if (!fs.existsSync(fullpath)) { + return Promise.reject(new Error(`file does not exist: ${fullpath}`)) + } + let res: string[] = [] + const rl = readline.createInterface({ + input: fs.createReadStream(fullpath, { encoding: 'utf8' }), + crlfDelay: Infinity, + terminal: false + } as any) + 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) + }) +} + +export function readFileLine(fullpath: string, count: number): Promise { + if (!fs.existsSync(fullpath)) { + return Promise.reject(new Error(`file does not exist: ${fullpath}`)) + } + const rl = readline.createInterface({ + input: fs.createReadStream(fullpath, { encoding: 'utf8' }), + crlfDelay: Infinity, + terminal: false + } as any) + 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) + }) +} + +export async function writeFile(fullpath: string, content: string): Promise { + await fs.writeFile(fullpath, content, { encoding: 'utf8' }) +} + +export function validSocket(path: string): Promise { + let clientSocket = new net.Socket() + return new Promise(resolve => { + clientSocket.on('error', () => { + resolve(false) + }) + clientSocket.connect({ path }, () => { + clientSocket.unref() + resolve(true) + }) + }) +} + +export function isFile(uri: string): boolean { + return uri.startsWith('file:') +} + +export function parentDirs(pth: string): string[] { + let { root, dir } = path.parse(pth) + if (dir === root) return [root] + const dirs = [root] + const parts = dir.slice(root.length).split(path.sep) + for (let i = 1; i <= parts.length; i++) { + dirs.push(path.join(root, parts.slice(0, i).join(path.sep))) + } + return dirs +} + +export function isParentFolder(folder: string, filepath: string, checkEqual = false): boolean { + let pdir = fixDriver(path.resolve(path.normalize(folder))) + let dir = fixDriver(path.resolve(path.normalize(filepath))) + if (pdir == '//') pdir = '/' + if (pdir == dir) return checkEqual ? true : false + if (pdir.endsWith(path.sep)) return dir.startsWith(pdir) + return dir.startsWith(pdir) && dir[pdir.length] == path.sep +} + +// use uppercase for windows driver +export function fixDriver(filepath: string): string { + if (os.platform() != 'win32' || filepath[1] != ':') return filepath + return filepath[0].toUpperCase() + filepath.slice(1) +} diff --git a/vim-config/plugins/coc.nvim/src/util/fuzzy.ts b/vim-config/plugins/coc.nvim/src/util/fuzzy.ts new file mode 100644 index 00000000..03421285 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/fuzzy.ts @@ -0,0 +1,48 @@ + +export function getCharCodes(str: string): number[] { + let res = [] + for (let i = 0, l = str.length; i < l; i++) { + res.push(str.charCodeAt(i)) + } + return res +} + +export function wordChar(ch: number): boolean { + return (ch >= 97 && ch <= 122) || (ch >= 65 && ch <= 90) +} + +export function caseMatch(input: number, code: number): boolean { + if (input == code) return true + if (input >= 97 && input <= 122 && code + 32 === input) return true + return false +} + +export function fuzzyChar(a: string, b: string): boolean { + 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 +} + +// upper case must match, lower case ignore case +export function fuzzyMatch(needle: number[], text: string): boolean { + 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 +} diff --git a/vim-config/plugins/coc.nvim/src/util/fzy.ts b/vim-config/plugins/coc.nvim/src/util/fzy.ts new file mode 100644 index 00000000..cc71f60e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/fzy.ts @@ -0,0 +1,201 @@ +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): boolean { + return s.toLowerCase() === s +} + +function isupper(s): boolean { + return s.toUpperCase() === s +} + +function precompute_bonus(haystack): number[] { + /* 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): void { + 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 + } + } + } +} + +export function score(needle, haystack): number { + 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] +} + +export function groupPositions(arr: number[]): [number, number][] { + let res: [number, number][] = [] + for (let i = 0; i < arr.length; i++) { + let last = res.length ? res[res.length - 1] : undefined + let curr = arr[i] + if (last && curr == last[1]) { + last[1] = curr + 1 + } else { + res.push([curr, curr + 1]) + } + } + return res +} + +export function positions(needle: string, haystack: string): number[] { + 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 +} + +export function hasMatch(needle: string, haystack: string): boolean { + 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 +} diff --git a/vim-config/plugins/coc.nvim/src/util/index.ts b/vim-config/plugins/coc.nvim/src/util/index.ts new file mode 100644 index 00000000..45067c0b --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/index.ts @@ -0,0 +1,157 @@ +import { exec, ExecOptions } from 'child_process' +import debounce from 'debounce' +import fs from 'fs' +import isuri from 'isuri' +import path from 'path' +import { Disposable, MarkupContent, MarkupKind } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import which from 'which' +import * as platform from './platform' +export { platform } +const logger = require('./logger')('util-index') + +export type MapMode = 'n' | 'i' | 'v' | 'x' | 's' | 'o' + +export const CONFIG_FILE_NAME = 'coc-settings.json' + +export function isMarkdown(content: MarkupContent | string | undefined): boolean { + if (MarkupContent.is(content) && content.kind == MarkupKind.Markdown) { + return true + } + return false +} + +export function escapeSingleQuote(str: string): string { + return str.replace(/'/g, "''") +} + +export function wait(ms: number): Promise { + return new Promise(resolve => { + setTimeout(() => { + resolve(undefined) + }, ms) + }) +} + +export function waitNextTick(fn: () => void): Promise { + return new Promise(resolve => { + process.nextTick(() => { + fn() + resolve(undefined) + }) + }) +} + +export function getUri(fullpath: string, id: number, buftype: string, isCygwin: boolean): string { + if (!fullpath) return `untitled:${id}` + // https://github.com/neoclide/coc-java/issues/82 + if (platform.isWindows && !isCygwin && !fullpath.startsWith('jdt://')) fullpath = path.win32.normalize(fullpath) + if (path.isAbsolute(fullpath)) return URI.file(fullpath).toString() + if (isuri.isValid(fullpath)) return URI.parse(fullpath).toString() + if (buftype != '') return `${buftype}:${id}` + return `unknown:${id}` +} + +export function disposeAll(disposables: Disposable[]): void { + while (disposables.length) { + const item = disposables.pop() + if (item) { + item.dispose() + } + } +} + +export function executable(command: string): boolean { + try { + which.sync(command) + } catch (e) { + return false + } + return true +} + +export function runCommand(cmd: string, opts: ExecOptions = {}, timeout?: number): Promise { + if (!platform.isWindows) { + opts.shell = opts.shell || process.env.SHELL + } + opts.maxBuffer = 500 * 1024 + return new Promise((resolve, reject) => { + let timer: NodeJS.Timer + if (timeout) { + timer = setTimeout(() => { + reject(new Error(`timeout after ${timeout}s`)) + }, timeout * 1000) + } + 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) + }) + }) +} + +export function watchFile(filepath: string, onChange: () => void): Disposable { + let callback = debounce(onChange, 100) + try { + let watcher = fs.watch(filepath, { + persistent: true, + recursive: false, + encoding: 'utf8' + }, () => { + callback() + }) + return Disposable.create(() => { + callback.clear() + watcher.close() + }) + } catch (e) { + return Disposable.create(() => { + callback.clear() + }) + } +} + +export function isRunning(pid: number): boolean { + try { + let res: any = process.kill(pid, 0) + return res == true + } + catch (e) { + return e.code === 'EPERM' + } +} + +export function getKeymapModifier(mode: MapMode): string { + if (mode == 'n' || mode == 'o' || mode == 'x' || mode == 'v') return '' + if (mode == 'i') return '' + if (mode == 's') return '' + return '' +} + +export function concurrent(arr: T[], fn: (val: T) => Promise, limit = 3): Promise { + if (arr.length == 0) return Promise.resolve() + let finished = 0 + let total = arr.length + let remain = arr.slice() + return new Promise(resolve => { + let run = (val): void => { + let cb = () => { + finished = finished + 1 + if (finished == total) { + resolve() + } else if (remain.length) { + let next = remain.shift() + run(next) + } + } + fn(val).then(cb, cb) + } + for (let i = 0; i < Math.min(limit, remain.length); i++) { + let val = remain.shift() + run(val) + } + }) +} diff --git a/vim-config/plugins/coc.nvim/src/util/is.ts b/vim-config/plugins/coc.nvim/src/util/is.ts new file mode 100644 index 00000000..38ac2f0f --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/is.ts @@ -0,0 +1,58 @@ +import { VimCompleteItem } from '../types' +/* eslint-disable id-blacklist */ +const hasOwnProperty = Object.prototype.hasOwnProperty + +export function vimCompleteItem(value: any): value is VimCompleteItem { + return value && typeof value.word === 'string' +} + +export function boolean(value: any): value is boolean { + return typeof value === 'boolean' +} + +export function string(value: any): value is string { + return typeof value === 'string' +} + +export function number(value: any): value is number { + return typeof value === 'number' +} + +export function array(array: any): array is any[] { + return Array.isArray(array) +} + +export function func(value: any): value is Function { + return typeof value == 'function' +} + +export function objectLiteral(obj: any): obj is object { + return ( + obj != null && + typeof obj === 'object' && + !Array.isArray(obj) && + !(obj instanceof RegExp) && + !(obj instanceof Date) + ) +} + +export function emptyObject(obj: any): boolean { + if (!objectLiteral(obj)) { + return false + } + + for (let key in obj) { + if (hasOwnProperty.call(obj, key)) { + return false + } + } + + return true +} + +export function typedArray( + value: any, + check: (value: any) => boolean +): value is T[] { + return Array.isArray(value) && (value as any).every(check) +} diff --git a/vim-config/plugins/coc.nvim/src/util/lodash.ts b/vim-config/plugins/coc.nvim/src/util/lodash.ts new file mode 100644 index 00000000..609c0ed6 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/lodash.ts @@ -0,0 +1,52 @@ + +/** 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 } + */ +export function defaults(obj: any, ...sources: any[]): any { + obj = Object(obj) + sources.forEach(source => { + if (source != null) { + source = Object(source) + for (const key in source) { + const value = obj[key] + if (value === undefined || + (value === objectProto[key] && !hasOwnProperty.call(obj, key))) { + obj[key] = source[key] + } + } + } + }) + return obj +} + +export function omit(obj: T, properties: string[]): T { + let o = {} + for (let key of Object.keys(obj)) { + if (!properties.includes(key)) { + o[key] = obj[key] + } + } + return o as T +} diff --git a/vim-config/plugins/coc.nvim/src/util/logger.ts b/vim-config/plugins/coc.nvim/src/util/logger.ts new file mode 100644 index 00000000..1c5c080e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/logger.ts @@ -0,0 +1,65 @@ +import fs from 'fs' +import log4js from 'log4js' +import path from 'path' +import os from 'os' +import { mkdirpSync } from 'fs-extra' + +function getLogFile(): string { + let file = process.env.NVIM_COC_LOG_FILE + if (file) return file + let dir = process.env.XDG_RUNTIME_DIR + if (dir) { + try { + fs.accessSync(dir, fs.constants.R_OK | fs.constants.W_OK) + return path.join(dir, `coc-nvim-${process.pid}.log`) + } catch (err) { + // noop + } + } + let tmpdir = os.tmpdir() + dir = path.join(tmpdir, `coc.nvim-${process.pid}`) + if (!fs.existsSync(dir)) mkdirpSync(dir) + return path.join(dir, `coc-nvim.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.existsSync(logfile)) { + // cleanup if exists + try { + fs.writeFileSync(logfile, '', { encoding: 'utf8', mode: 0o666 }) + } catch (e) { + // noop + } +} + +log4js.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'): log4js.Logger => { + let logger = log4js.getLogger(name) + ; (logger as any).getLogFile = () => logfile + return logger +} diff --git a/vim-config/plugins/coc.nvim/src/util/match.ts b/vim-config/plugins/coc.nvim/src/util/match.ts new file mode 100644 index 00000000..2281b0d4 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/match.ts @@ -0,0 +1,71 @@ +import minimatch from 'minimatch' +import { DocumentFilter, DocumentSelector } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import * as platform from './platform' + +export function score(selector: DocumentSelector | DocumentFilter | string, uri: string, languageId: string): number { + 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 = 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) { + let caseInsensitive = platform.isWindows || platform.isMacintosh + let p = caseInsensitive ? pattern.toLowerCase() : pattern + let f = caseInsensitive ? u.fsPath.toLowerCase() : u.fsPath + if (p === f || minimatch(f, p, { dot: true })) { + ret = 5 + } else { + return 0 + } + } + + return ret + } else { + return 0 + } +} diff --git a/vim-config/plugins/coc.nvim/src/util/mutex.ts b/vim-config/plugins/coc.nvim/src/util/mutex.ts new file mode 100644 index 00000000..7d2b9bd2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/mutex.ts @@ -0,0 +1,46 @@ +export class Mutex { + private tasks: (() => void)[] = [] + private count = 1 + + private sched(): void { + if (this.count > 0 && this.tasks.length > 0) { + this.count-- + let next = this.tasks.shift() + next() + } + } + + public get busy(): boolean { + return this.count == 0 + } + + public acquire(): Promise<() => void> { + return new Promise<() => void>(res => { + let task = () => { + let released = false + res(() => { + if (!released) { + released = true + this.count++ + this.sched() + } + }) + } + this.tasks.push(task) + process.nextTick(this.sched.bind(this)) + }) + } + + public use(f: () => Promise): Promise { + return this.acquire() + .then(release => f() + .then(res => { + release() + return res + }) + .catch(err => { + release() + throw err + })) + } +} diff --git a/vim-config/plugins/coc.nvim/src/util/object.ts b/vim-config/plugins/coc.nvim/src/util/object.ts new file mode 100644 index 00000000..f2589db2 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/object.ts @@ -0,0 +1,137 @@ +import * as Is from './is' + +export function isEmpty(obj: object | null | undefined): boolean { + if (!obj) return true + if (Array.isArray(obj)) return obj.length == 0 + return Object.keys(obj).length == 0 +} + +export function deepClone(obj: T): T { + if (!obj || typeof obj !== 'object') { + return obj + } + if (obj instanceof RegExp) { + // See https://github.com/Microsoft/TypeScript/issues/10990 + return obj as any + } + const result: any = 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 +} + +const _hasOwnProperty = Object.prototype.hasOwnProperty + +export function deepFreeze(obj: T): T { + if (!obj || typeof obj !== 'object') { + return obj + } + const stack: any[] = [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 +} + +/** + * 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). + */ +export function mixin( + destination: any, + source: any, + overwrite = true +): any { + 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 +} + +export function equals(one: any, other: any): boolean { + 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: number + let key: string + + 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: string[] = [] + + for (key in one) { + oneKeys.push(key) + } + oneKeys.sort() + const otherKeys: string[] = [] + for (key in other) { + 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 +} diff --git a/vim-config/plugins/coc.nvim/src/util/platform.ts b/vim-config/plugins/coc.nvim/src/util/platform.ts new file mode 100644 index 00000000..d7d262fa --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/platform.ts @@ -0,0 +1,83 @@ +let _isWindows = false +let _isMacintosh = false +let _isLinux = false +let _isNative = false +let _isWeb = false + +export interface IProcessEnvironment { + [key: string]: string +} + +interface INodeProcess { + nextTick: Function + platform: string + env: IProcessEnvironment + getuid(): number +} + +declare let process: INodeProcess +declare let global: any + +interface INavigator { + userAgent: string + language: string +} +declare let self: any + +export const 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 +} + +export enum Platform { + Web, + Mac, + Linux, + Windows +} + +let _platform: Platform = Platform.Web +if (_isNative) { + if (_isMacintosh) { + _platform = Platform.Mac + } else if (_isWindows) { + _platform = Platform.Windows + } else if (_isLinux) { + _platform = Platform.Linux + } +} + +export const isWindows = _isWindows +export const isMacintosh = _isMacintosh +export const isLinux = _isLinux +export const isNative = _isNative +export const isWeb = _isWeb +export const platform = _platform + +const _globals = + typeof self === 'object' + ? self + : typeof global === 'object' + ? global + : ({} as any) +export const globals: any = _globals + +export const enum OperatingSystem { + Windows = 1, + Macintosh = 2, + Linux = 3 +} +export const OS = _isMacintosh + ? OperatingSystem.Macintosh + : _isWindows + ? OperatingSystem.Windows + : OperatingSystem.Linux diff --git a/vim-config/plugins/coc.nvim/src/util/position.ts b/vim-config/plugins/coc.nvim/src/util/position.ts new file mode 100644 index 00000000..9d247a29 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/position.ts @@ -0,0 +1,132 @@ +import { Position, Range, TextEdit } from 'vscode-languageserver-protocol' + +export function rangeInRange(r: Range, range: Range): boolean { + return positionInRange(r.start, range) === 0 && positionInRange(r.end, range) === 0 +} + +/** + * Check if two ranges have overlap character. + */ +export function rangeOverlap(r: Range, range: Range): boolean { + let { start, end } = r + if (comparePosition(end, range.start) <= 0) { + return false + } + if (comparePosition(start, range.end) >= 0) { + return false + } + return true +} + +/** + * Check if two ranges have overlap or nested + */ +export function rangeIntersect(r: Range, range: Range): boolean { + if (positionInRange(r.start, range) == 0) { + return true + } + if (positionInRange(r.end, range) == 0) { + return true + } + if (rangeInRange(range, r)) { + return true + } + return false +} + +export function lineInRange(line: number, range: Range): boolean { + let { start, end } = range + return line >= start.line && line <= end.line +} + +export function emptyRange(range: Range): boolean { + let { start, end } = range + return start.line == end.line && start.character == end.character +} + +export function positionInRange(position: Position, range: Range): number { + let { start, end } = range + if (comparePosition(position, start) < 0) return -1 + if (comparePosition(position, end) > 0) return 1 + return 0 +} + +export function comparePosition(position: Position, other: Position): number { + 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 +} + +export function isSingleLine(range: Range): boolean { + return range.start.line == range.end.line +} + +export function getChangedPosition(start: Position, edit: TextEdit): { line: number; character: number } { + 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 } +} + +export function adjustPosition(pos: Position, edit: TextEdit): Position { + 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 + } +} + +export function positionToOffset(lines: string[], line: number, character: number): number { + let offset = 0 + for (let i = 0; i <= line; i++) { + if (i == line) { + offset += character + } else { + offset += lines[i].length + 1 + } + } + return offset +} + +// edit a range to newText +export function editRange(range: Range, text: string, edit: TextEdit): string { + // 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)}` +} + +export function getChangedFromEdits(start: Position, edits: TextEdit[]): Position | null { + 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 +} diff --git a/vim-config/plugins/coc.nvim/src/util/processes.ts b/vim-config/plugins/coc.nvim/src/util/processes.ts new file mode 100644 index 00000000..6d50327e --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/processes.ts @@ -0,0 +1,56 @@ + +/* --------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as cp from 'child_process' +import { join, dirname, resolve } from 'path' +import fs from 'fs' +import ChildProcess = cp.ChildProcess + +declare const ESBUILD + +const isWindows = process.platform === 'win32' +const isMacintosh = process.platform === 'darwin' +const isLinux = process.platform === 'linux' +const pluginRoot = typeof ESBUILD === 'undefined' ? resolve(__dirname, '../..') : dirname(__dirname) + +export function terminate(process: ChildProcess, cwd?: string): boolean { + if (process.killed) return + 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: any = { + 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 filepath = join(pluginRoot, 'bin/terminateProcess.sh') + if (!fs.existsSync(filepath)) { + console.error(`"${filepath}" not found`) + return false + } + let result = cp.spawnSync(filepath, [process.pid.toString()]) + return result.error ? false : true + } catch (err) { + return false + } + } else { + process.kill('SIGKILL') + return true + } +} diff --git a/vim-config/plugins/coc.nvim/src/util/score.ts b/vim-config/plugins/coc.nvim/src/util/score.ts new file mode 100644 index 00000000..d07b4acd --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/score.ts @@ -0,0 +1,140 @@ +import { sep as pathSeparator } from 'path' +import { getCharCodes, fuzzyMatch, fuzzyChar, caseMatch } from './fuzzy' + +export interface MatchResult { + score: number + matches?: number[] // character indexes +} + +// 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 + +export function getMatchResult(text: string, query: string, filename = ''): MatchResult { + if (!text) return { score: 0 } + if (!query) return { score: 1 } + let matches: number[] = [] + let codes = getCharCodes(query) + let filenameIdx = filename ? text.indexOf(filename) : -1 + let matchBase = filenameIdx != -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 (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 == pathSeparator && 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 (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 }) +} + +/** + * + * @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: number[], text: string, idx: number, curr: MatchResult): MatchResult | null { + let { score, matches } = curr + let results: MatchResult[] = [] + let c = codes[0] + let remain = codes.slice(1) + let result: MatchResult + + function getRemianResult(index: number): void { + 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 (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] == pathSeparator && 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 (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: MatchResult[]): MatchResult { + let res = results[0] + for (let i = 1; i < results.length; i++) { + if (results[i].score > res.score) { + res = results[i] + } + } + return res +} diff --git a/vim-config/plugins/coc.nvim/src/util/string.ts b/vim-config/plugins/coc.nvim/src/util/string.ts new file mode 100644 index 00000000..d19bd19c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/string.ts @@ -0,0 +1,126 @@ +import { Range } from 'vscode-languageserver-protocol' + +export function rangeParts(text: string, range: Range): [string, string] { + let { start, end } = range + let lines = text.split(/\r?\n/) + let before = '' + let after = '' + let len = lines.length + // get start and end parts + for (let i = 0; i < len; i++) { + let curr = lines[i] + if (i < start.line) { + before += curr + '\n' + continue + } + if (i > end.line) { + after += curr + (i == len - 1 ? '' : '\n') + continue + } + if (i == start.line) { + before += curr.slice(0, start.character) + } + if (i == end.line) { + after += curr.slice(end.character) + (i == len - 1 ? '' : '\n') + } + } + return [before, after] +} + +// nvim use utf8 +export function byteLength(str: string): number { + return Buffer.byteLength(str) +} + +export function upperFirst(str: string): string { + return str ? str[0].toUpperCase() + str.slice(1) : '' +} + +export function byteIndex(content: string, index: number): number { + let s = content.slice(0, index) + return Buffer.byteLength(s) +} + +export function indexOf(str: string, ch: string, count = 1): number { + 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 +} + +export function characterIndex(content: string, byteIndex: number): number { + let buf = Buffer.from(content, 'utf8') + return buf.slice(0, byteIndex).toString('utf8').length +} + +export function byteSlice(content: string, start: number, end?: number): string { + let buf = Buffer.from(content, 'utf8') + return buf.slice(start, end).toString('utf8') +} + +export function isWord(character: string): boolean { + 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 +} + +export function isTriggerCharacter(character: string): boolean { + 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 +} + +export function isAsciiLetter(code: number): boolean { + if (code >= 65 && code <= 90) return true + if (code >= 97 && code <= 122) return true + return false +} + +function doEqualsIgnoreCase(a: string, b: string, stopAt = a.length): boolean { + 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 +} + +export function equalsIgnoreCase(a: string, b: string): boolean { + const len1 = a ? a.length : 0 + const len2 = b ? b.length : 0 + if (len1 !== len2) { + return false + } + return doEqualsIgnoreCase(a, b) +} diff --git a/vim-config/plugins/coc.nvim/src/util/textedit.ts b/vim-config/plugins/coc.nvim/src/util/textedit.ts new file mode 100644 index 00000000..2c8b9042 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/textedit.ts @@ -0,0 +1,6 @@ +import { TextEdit } from 'vscode-languageserver-protocol' + +export function singleLineEdit(edit: TextEdit): boolean { + let { range, newText } = edit + return range.start.line == range.end.line && newText.indexOf('\n') == -1 +} diff --git a/vim-config/plugins/coc.nvim/src/util/throttle.ts b/vim-config/plugins/coc.nvim/src/util/throttle.ts new file mode 100644 index 00000000..38bed3d5 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/util/throttle.ts @@ -0,0 +1,42 @@ + +/** + * Returns a new function that, when invoked, invokes `func` at most once per `wait` milliseconds. + * + * @param {Function} func Function to wrap. + * @param {Number} wait Number of milliseconds that must elapse between `func` invocations. + * @return {Function} A new function that wraps the `func` function passed in. + */ + +export default function throttle(func: Function, wait: number): Function & { clear(): void } { + let args + let rtn + let timeoutID + let last = 0 + + function fn(): any { + args = arguments + let delta = Date.now() - last + if (!timeoutID) { + if (last != 0 && delta >= wait) { + call() + } else { + timeoutID = setTimeout(call, wait - delta) + } + } + return rtn + } + + function call(): any { + timeoutID = 0 + last = Date.now() + rtn = func.apply(null, args) + args = null + } + + fn.clear = () => { + if (timeoutID) { + clearTimeout(timeoutID) + } + } + return fn +} diff --git a/vim-config/plugins/coc.nvim/src/watchman.ts b/vim-config/plugins/coc.nvim/src/watchman.ts new file mode 100644 index 00000000..285c81e7 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/watchman.ts @@ -0,0 +1,196 @@ +import watchman, { Client } from 'fb-watchman' +import os from 'os' +import path from 'path' +import { OutputChannel } from './types' +import { v1 as uuidv1 } from 'uuid' +import { Disposable } from 'vscode-languageserver-protocol' +import minimatch from 'minimatch' +import { isParentFolder } from './util/fs' +const logger = require('./util/logger')('watchman') +const requiredCapabilities = ['relative_root', 'cmd-watch-project', 'wildmatch', 'field-new'] + +export interface WatchResponse { + warning?: string + watcher: string + watch: string + relative_path?: string +} + +export interface FileChangeItem { + size: number + name: string + exists: boolean + new: boolean + type: 'f' | 'd' + mtime_ms: number +} + +export interface FileChange { + root: string + subscription: string + files: FileChangeItem[] +} + +export type ChangeCallback = (FileChange) => void + +const clientsMap: Map> = new Map() +/** + * Watchman wrapper for fb-watchman client + * + * @public + */ +export default class Watchman { + private client: Client + private watch: string | undefined + private relative_path: string | undefined + private _disposed = false + + constructor(binaryPath: string, private channel?: OutputChannel) { + this.client = new watchman.Client({ + watchmanBinaryPath: binaryPath + }) + this.client.setMaxListeners(300) + } + + public checkCapability(): Promise { + 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) + }) + }) + } + + public async watchProject(root: string): Promise { + try { + let resp = await this.command(['watch-project', root]) + let { watch, warning, relative_path } = (resp as WatchResponse) + 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 + } + + private command(args: any[]): Promise { + return new Promise((resolve, reject) => { + this.client.command(args, (error, resp) => { + if (error) return reject(error) + resolve(resp) + }) + }) + } + + public async subscribe(globPattern: string, cb: ChangeCallback): Promise { + 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: any = { + expression: ['allof', ['match', '**/*', 'wholename']], + fields: ['name', 'size', 'new', 'exists', 'type', 'mtime_ms', 'ctime_ms'], + since: clock, + } + let root = watch + if (relative_path) { + sub.relative_root = relative_path + root = path.join(watch, relative_path) + } + let { subscribe } = await this.command(['subscribe', watch, uid, sub]) + if (global.hasOwnProperty('__TEST__')) (global as any).subscribe = subscribe + this.appendOutput(`subscribing "${globPattern}" in ${root}`) + this.client.on('subscription', resp => { + if (!resp || resp.subscription != uid) return + let { files } = resp as FileChange + if (!files) return + files = files.filter(f => f.type == 'f' && minimatch(f.name, globPattern, { dot: true })) + if (!files.length) return + let ev: FileChange = Object.assign({}, resp) + if (this.relative_path) ev.root = path.resolve(resp.root, this.relative_path) + this.appendOutput(`file change detected: ${JSON.stringify(ev, null, 2)}`) + cb(ev) + }) + return Disposable.create(() => this.unsubscribe(subscribe)) + } + + public unsubscribe(subscription: string): Promise { + 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) + }) + } + + public dispose(): void { + if (this._disposed) return + this._disposed = true + this.client.removeAllListeners() + this.client.end() + } + + private appendOutput(message: string, type = "Info"): void { + if (this.channel) { + this.channel.appendLine(`[${type} - ${(new Date().toLocaleTimeString())}] ${message}`) + } + } + + public static dispose(): void { + for (let promise of clientsMap.values()) { + promise.then(client => { + client.dispose() + }, _e => { + // noop + }) + } + } + + public static createClient(binaryPath: string, root: string, channel?: OutputChannel): Promise { + if (!isValidWatchRoot(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 + } +} + +/** + * Exclude user's home, driver, tmpdir + */ +export function isValidWatchRoot(root: string): boolean { + if (root == '/' || root == '/tmp' || root == '/private/tmp') return false + if (root.toLowerCase() === os.homedir().toLowerCase()) return false + if (path.parse(root).base == root) return false + if (root.startsWith('/tmp/') || root.startsWith('/private/tmp/')) return false + if (isParentFolder(os.tmpdir(), root, true)) return false + return true +} diff --git a/vim-config/plugins/coc.nvim/src/window.ts b/vim-config/plugins/coc.nvim/src/window.ts new file mode 100644 index 00000000..1088889c --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/window.ts @@ -0,0 +1,657 @@ +import { Neovim } from '@chemzqm/neovim' +import fs from 'fs' +import os from 'os' +import path from 'path' +import { CancellationToken, Disposable, Position } from 'vscode-languageserver-protocol' +import { URI } from 'vscode-uri' +import channels from './channels' +import events from './events' +import Dialog, { DialogConfig, DialogPreferences } from './model/dialog' +import Menu from './model/menu' +import Notification, { NotificationConfig, NotificationPreferences } from './model/notification' +import Picker, { QuickPickItem } from './model/picker' +import ProgressNotification, { Progress } from './model/progress' +import StatusLine, { StatusBarItem } from './model/status' +import { TreeView, TreeViewOptions } from './tree' +import { MessageLevel, OutputChannel } from './types' +import { CONFIG_FILE_NAME, disposeAll } from './util' +import { Mutex } from './util/mutex' +import { isWindows } from './util/platform' +import workspace from './workspace' +const logger = require('./util/logger')('window') + +export type MsgTypes = 'error' | 'warning' | 'more' + +export interface StatusItemOption { + progress?: boolean +} + +export interface ScreenPosition { + row: number + col: number +} + +export interface OpenTerminalOption { + /** + * Cwd of terminal, default to result of |getcwd()| + */ + cwd?: string + /** + * Close terminal on job finish, default to true. + */ + autoclose?: boolean + /** + * Keep foucus current window, default to false, + */ + keepfocus?: boolean +} + +export interface TerminalResult { + bufnr: number + success: boolean + content?: string +} +/** + * Value-object describing where and how progress should show. + */ +export interface ProgressOptions { + + /** + * A human-readable string which will be used to describe the + * operation. + */ + title?: string + + /** + * Controls if a cancel button should show to allow the user to + * cancel the long running operation. + */ + cancellable?: boolean +} + +/** + * Represents an action that is shown with an information, warning, or + * error message. + * + * @see [showInformationMessage](#window.showInformationMessage) + * @see [showWarningMessage](#window.showWarningMessage) + * @see [showErrorMessage](#window.showErrorMessage) + */ +export interface MessageItem { + + /** + * A short title like 'Retry', 'Open Log' etc. + */ + title: string + + /** + * A hint for modal dialogs that the item should be triggered + * when the user cancels the dialog (e.g. by pressing the ESC + * key). + * + * Note: this option is ignored for non-modal messages. + * Note: not used by coc.nvim for now. + */ + isCloseAffordance?: boolean +} + +class Window { + private mutex = new Mutex() + private statusLine: StatusLine | undefined + + public get nvim(): Neovim { + return workspace.nvim + } + + public dispose(): void { + this.statusLine?.dispose() + } + + /** + * Reveal message with message type. + * + * @param msg Message text to show. + * @param messageType Type of message, could be `error` `warning` and `more`, default to `more` + */ + public showMessage(msg: string, messageType: MsgTypes = 'more'): void { + if (this.mutex.busy || !this.nvim) return + let { messageLevel } = this + let method = process.env.VIM_NODE_RPC == '1' ? 'callTimer' : 'call' + if (global.hasOwnProperty('__TEST__')) logger.info(msg) + let hl = 'Error' + let level = MessageLevel.Error + switch (messageType) { + case 'more': + level = MessageLevel.More + hl = 'MoreMsg' + break + case 'warning': + level = MessageLevel.Warning + hl = 'WarningMsg' + break + } + if (level >= messageLevel) { + this.nvim[method]('coc#util#echo_messages', [hl, ('[coc.nvim] ' + msg).split('\n')], true) + } + } + + /** + * Run command in vim terminal for result + * + * @param cmd Command to run. + * @param cwd Cwd of terminal, default to result of |getcwd()|. + */ + public async runTerminalCommand(cmd: string, cwd?: string, keepfocus = false): Promise { + cwd = cwd || workspace.cwd + return await this.nvim.callAsync('coc#util#run_terminal', { cmd, cwd, keepfocus: keepfocus ? 1 : 0 }) as TerminalResult + } + + /** + * Open terminal window. + * + * @param cmd Command to run. + * @param opts Terminal option. + * @returns buffer number of terminal. + */ + public async openTerminal(cmd: string, opts: OpenTerminalOption = {}): Promise { + let bufnr = await this.nvim.call('coc#util#open_terminal', { cmd, ...opts }) + return bufnr as number + } + + /** + * Show quickpick for single item, use `window.menuPick` for menu at current current position. + * + * @param items Label list. + * @param placeholder Prompt text, default to 'choose by number'. + * @returns Index of selected item, or -1 when canceled. + */ + public async showQuickpick(items: string[], placeholder = 'Choose by number'): Promise { + let release = await this.mutex.acquire() + try { + let title = placeholder + ':' + items = items.map((s, idx) => `${idx + 1}. ${s}`) + let res = await this.nvim.callAsync('coc#util#quickpick', [title, items.map(s => s.trim())]) + release() + let n = parseInt(res, 10) + if (isNaN(n) || n <= 0 || n > items.length) return -1 + return n - 1 + } catch (e) { + release() + return -1 + } + } + + /** + * Show menu picker at current cursor position, |inputlist()| is used as fallback. + * Use `workspace.env.dialog` to check if the picker window/popup could work. + * + * @param items Array of texts. + * @param title Optional title of float/popup window. + * @param token A token that can be used to signal cancellation. + * @returns Selected index (0 based), -1 when canceled. + */ + public async showMenuPicker(items: string[], title?: string, token?: CancellationToken): Promise { + if (workspace.env.dialog) { + let release = await this.mutex.acquire() + if (token && token.isCancellationRequested) { + release() + return -1 + } + try { + let menu = new Menu(this.nvim, { items: items.map(s => s.trim()), title }, token) + let promise = new Promise(resolve => { + menu.onDidClose(selected => { + resolve(selected) + }) + }) + await menu.show(this.dialogPreference) + let res = await promise + release() + return res + } catch (e) { + logger.error(`Error on showMenuPicker:`, e) + release() + } + } + return await this.showQuickpick(items) + } + + /** + * Open local config file + */ + public async openLocalConfig(): Promise { + let { root } = workspace + if (root == os.homedir()) { + this.showMessage(`Can't create local config in home directory`, 'warning') + return + } + let dir = path.join(root, '.vim') + if (!fs.existsSync(dir)) { + let res = await this.showPrompt(`Would you like to create folder'${root}/.vim'?`) + if (!res) return + fs.mkdirSync(dir) + } + await workspace.jumpTo(URI.file(path.join(dir, CONFIG_FILE_NAME)).toString()) + } + + /** + * Prompt user for confirm, a float/popup window would be used when possible, + * use vim's |confirm()| function as callback. + * + * @param title The prompt text. + * @returns Result of confirm. + */ + public async showPrompt(title: string): Promise { + let release = await this.mutex.acquire() + try { + let res = await this.nvim.callAsync('coc#float#prompt_confirm', [title]) + release() + return res == 1 + } catch (e) { + release() + return false + } + } + + /** + * Show dialog window at the center of screen. + * Note that the dialog would always be closed after button click. + * Use `workspace.env.dialog` to check if dialog could work. + * + * @param config Dialog configuration. + * @returns Dialog or null when dialog can't work. + */ + public async showDialog(config: DialogConfig): Promise

    { + if (!this.checkDialog()) return null + let dialog = new Dialog(this.nvim, config) + await dialog.show(this.dialogPreference) + return dialog + } + + /** + * Request input from user + * + * @param title Title text of prompt window. + * @param defaultValue Default value of input, empty text by default. + */ + public async requestInput(title: string, defaultValue?: string): Promise { + let { nvim } = this + const preferences = workspace.getConfiguration('coc.preferences') + if (workspace.env.dialog && preferences.get('promptInput', true) && !isWindows) { + let release = await this.mutex.acquire() + let preferences = this.dialogPreference + try { + let opts: any = {} + if (preferences.floatHighlight) opts.highlight = preferences.floatHighlight + if (preferences.floatBorderHighlight) opts.borderhighlight = preferences.floatBorderHighlight + let arr = await nvim.call('coc#float#create_prompt_win', [title, defaultValue || '', opts]) as [number, number] + let [bufnr, winid] = arr + let res = await new Promise(resolve => { + let disposables: Disposable[] = [] + events.on('BufWinLeave', nr => { + if (nr == bufnr) { + disposeAll(disposables) + resolve(null) + } + }, null, disposables) + events.on('PromptInsert', async value => { + disposeAll(disposables) + await nvim.call('coc#float#close', [winid]) + if (!value) { + this.showMessage('Empty word, canceled', 'warning') + resolve(null) + } else { + resolve(value) + } + }, null, disposables) + }) + release() + return res + } catch (e) { + logger.error('Error on requestInput:', e) + release() + } + } else { + let res = await workspace.callAsync('input', [title + ': ', defaultValue || '']) + nvim.command('normal! :', true) + if (!res) { + this.showMessage('Empty word, canceled', 'warning') + return null + } + return res + } + } + + /** + * Create statusbar item that would be included in `g:coc_status`. + * + * @param priority Higher priority item would be shown right. + * @param option + * @return A new status bar item. + */ + public createStatusBarItem(priority = 0, option: StatusItemOption = {}): StatusBarItem { + if (!workspace.env) { + let fn = () => {} + return { text: '', show: fn, dispose: fn, hide: fn, priority: 0, isProgress: false } + } + if (!this.statusLine) { + this.statusLine = new StatusLine(this.nvim) + } + return this.statusLine.createStatusBarItem(priority, option.progress || false) + } + + /** + * Create a new output channel + * + * @param name Unique name of output channel. + * @returns A new output channel. + */ + public createOutputChannel(name: string): OutputChannel { + return channels.create(name, this.nvim) + } + + /** + * Reveal buffer of output channel. + * + * @param name Name of output channel. + * @param preserveFocus Preserve window focus when true. + */ + public showOutputChannel(name: string, preserveFocus?: boolean): void { + channels.show(name, preserveFocus) + } + + /** + * Echo lines at the bottom of vim. + * + * @param lines Line list. + * @param truncate Truncate the lines to avoid 'press enter to continue' when true + */ + public async echoLines(lines: string[], truncate = false): Promise { + let { nvim } = this + let cmdHeight = workspace.env.cmdheight + if (lines.length > cmdHeight && truncate) { + lines = lines.slice(0, cmdHeight) + } + let maxLen = workspace.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} ...` + } + await nvim.call('coc#util#echo_lines', [lines]) + } + + /** + * Get current cursor position (line, character both 0 based). + * + * @returns Cursor position. + */ + public async getCursorPosition(): Promise { + // vim can't count utf16 + let [line, content] = await this.nvim.eval(`[line('.')-1, strpart(getline('.'), 0, col('.') - 1)]`) as [number, string] + return Position.create(line, content.length) + } + + /** + * Move cursor to position. + * + * @param position LSP position. + */ + public async moveTo(position: Position): Promise { + await this.nvim.call('coc#cursor#move_to', [position.line, position.character]) + if (workspace.env.isVim) this.nvim.command('redraw', true) + } + + /** + * Get current cursor character offset in document, + * length of line break would always be 1. + * + * @returns Character offset. + */ + public async getOffset(): Promise { + return await this.nvim.call('coc#cursor#char_offset') as number + } + + /** + * Get screen position of current cursor(relative to editor), + * both `row` and `col` are 0 based. + * + * @returns Cursor screen position. + */ + public async getCursorScreenPosition(): Promise { + let [row, col] = await this.nvim.call('coc#cursor#screen_pos') as [number, number] + return { row, col } + } + + /** + * Show multiple picker at center of screen. + * Use `workspace.env.dialog` to check if dialog could work. + * + * @param items Array of QuickPickItem or string. + * @param title Title of picker dialog. + * @param token A token that can be used to signal cancellation. + * @return A promise that resolves to the selected items or `undefined`. + */ + public async showPickerDialog(items: string[], title: string, token?: CancellationToken): Promise + public async showPickerDialog(items: T[], title: string, token?: CancellationToken): Promise + public async showPickerDialog(items: any, title: string, token?: CancellationToken): Promise { + if (!this.checkDialog()) return undefined + let release = await this.mutex.acquire() + if (token && token.isCancellationRequested) { + release() + return undefined + } + try { + let useString = typeof items[0] === 'string' + let picker = new Picker(this.nvim, { + title, + items: useString ? items.map(s => { + return { label: s } + }) : items, + }, token) + let promise = new Promise(resolve => { + picker.onDidClose(selected => { + resolve(selected) + }) + }) + await picker.show(this.dialogPreference) + let picked = await promise + let res = picked == undefined ? undefined : items.filter((_, i) => picked.includes(i)) + release() + return res + } catch (e) { + logger.error(`Error on showPickerDialog:`, e) + release() + } + } + + /** + * Show an information message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + public async showInformationMessage(message: string, ...items: string[]): Promise + public async showInformationMessage(message: string, ...items: T[]): Promise + public async showInformationMessage(message: string, ...items: T[]): Promise { + if (!this.enableMessageDialog) return await this.showConfirm(message, items, 'Info') as any + let texts = typeof items[0] === 'string' ? items : (items as any[]).map(s => s.title) + let idx = await this.createNotification('CocInfoFloat', message, texts) + return idx == -1 ? undefined : items[idx] + } + + /** + * Show an warning message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + public async showWarningMessage(message: string, ...items: string[]): Promise + public async showWarningMessage(message: string, ...items: T[]): Promise + public async showWarningMessage(message: string, ...items: T[]): Promise { + if (!this.enableMessageDialog) return await this.showConfirm(message, items, 'Warning') as any + let texts = typeof items[0] === 'string' ? items : (items as any[]).map(s => s.title) + let idx = await this.createNotification('CocWarningFloat', message, texts) + return idx == -1 ? undefined : items[idx] + } + + /** + * Show an error message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + public async showErrorMessage(message: string, ...items: string[]): Promise + public async showErrorMessage(message: string, ...items: T[]): Promise + public async showErrorMessage(message: string, ...items: T[]): Promise { + if (!this.enableMessageDialog) return await this.showConfirm(message, items, 'Error') as any + let texts = typeof items[0] === 'string' ? items : (items as any[]).map(s => s.title) + let idx = await this.createNotification('CocErrorFloat', message, texts) + return idx == -1 ? undefined : items[idx] + } + + public async showNotification(config: NotificationConfig): Promise { + if (!this.checkDialog()) return false + let notification = new Notification(this.nvim, config) + return await notification.show(this.notificationPreference) + } + + // fallback for vim without dialog + private async showConfirm(message: string, items: T[], kind: 'Info' | 'Warning' | 'Error'): Promise { + if (!items || items.length == 0) { + let msgType: MsgTypes = kind == 'Info' ? 'more' : kind == 'Error' ? 'error' : 'warning' + this.showMessage(message, msgType) + return undefined + } + let titles: string[] = typeof items[0] === 'string' ? items.slice() as string[] : items.map(o => (o as MessageItem).title) + let choices = titles.map((s, i) => `${i + 1}${s}`) + let res = await this.nvim.callAsync('coc#util#with_callback', ['confirm', [message, choices.join('\n'), 0, kind]]) + return items[res - 1] + } + + /** + * Show progress in the editor. Progress is shown while running the given callback + * and while the promise it returned isn't resolved nor rejected. + * + * @param task A callback returning a promise. Progress state can be reported with + * the provided [progress](#Progress)-object. + * + * To report discrete progress, use `increment` to indicate how much work has been completed. Each call with + * a `increment` value will be summed up and reflected as overall progress until 100% is reached (a value of + * e.g. `10` accounts for `10%` of work done). + * + * To monitor if the operation has been cancelled by the user, use the provided [`CancellationToken`](#CancellationToken). + * + * @return The thenable the task-callback returned. + */ + public async withProgress(options: ProgressOptions, task: (progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken) => Thenable): Promise { + if (!this.checkDialog()) return undefined + let progress = new ProgressNotification(this.nvim, { + task, + title: options.title, + cancellable: options.cancellable + }) + return await progress.show(this.notificationPreference) + } + + /** + * Create a {@link TreeView} instance. + * + * @param viewId Id of the view, used as title of TreeView when title not exists. + * @param options Options for creating the {@link TreeView} + * @returns a {@link TreeView}. + */ + public createTreeView(viewId: string, options: TreeViewOptions): TreeView { + const BasicTreeView = require('./tree/TreeView').default + return new BasicTreeView(viewId, options) + } + + private createNotification(borderhighlight: string, message: string, items: string[]): Promise { + return new Promise(resolve => { + let config: NotificationConfig = { + content: message, + borderhighlight, + close: true, + buttons: items.map((s, index) => { + return { text: s, index } + }), + callback: idx => { + resolve(idx) + } + } + let notification = new Notification(this.nvim, config) + notification.show(this.notificationPreference).then(shown => { + if (!shown) { + logger.error('Unable to open notification window') + resolve(-1) + } + if (!items.length) resolve(-1) + }, e => { + logger.error('Unable to open notification window', e) + resolve(-1) + }) + }) + } + + private get dialogPreference(): DialogPreferences { + let config = workspace.getConfiguration('dialog') + return { + maxWidth: config.get('maxWidth'), + maxHeight: config.get('maxHeight'), + floatHighlight: config.get('floatHighlight'), + floatBorderHighlight: config.get('floatBorderHighlight'), + pickerButtons: config.get('pickerButtons'), + pickerButtonShortcut: config.get('pickerButtonShortcut'), + confirmKey: config.get('confirmKey'), + } + } + + private get notificationPreference(): NotificationPreferences { + let config = workspace.getConfiguration('notification') + return { + top: config.get('marginTop'), + right: config.get('marginRight'), + maxWidth: config.get('maxWidth'), + maxHeight: config.get('maxHeight'), + highlight: config.get('highlightGroup'), + minProgressWidth: config.get('minProgressWidth'), + } + } + + private checkDialog(): boolean { + if (workspace.env.dialog) return true + this.showMessage('Dialog requires vim >= 8.2.0750 or neovim >= 0.4.0, please upgrade your vim', 'warning') + return false + } + + private get enableMessageDialog(): boolean { + if (!workspace.env.dialog) return false + let config = workspace.getConfiguration('coc.preferences') + return config.get('enableMessageDialog', false) + } + + private get messageLevel(): MessageLevel { + let config = workspace.getConfiguration('coc.preferences') + let level = config.get('messageLevel', 'more') + switch (level) { + case 'error': + return MessageLevel.Error + case 'warning': + return MessageLevel.Warning + default: + return MessageLevel.More + } + } +} + +export default new Window() diff --git a/vim-config/plugins/coc.nvim/src/workspace.ts b/vim-config/plugins/coc.nvim/src/workspace.ts new file mode 100644 index 00000000..ea53c190 --- /dev/null +++ b/vim-config/plugins/coc.nvim/src/workspace.ts @@ -0,0 +1,1727 @@ +import { Buffer, NeovimClient as Neovim } from '@chemzqm/neovim' +import bytes from 'bytes' +import fastDiff from 'fast-diff' +import fs from 'fs-extra' +import os from 'os' +import path from 'path' +import { v1 as uuid } from 'uuid' +import { CancellationTokenSource, CreateFile, CreateFileOptions, DeleteFile, DeleteFileOptions, Disposable, DocumentSelector, Emitter, Event, FormattingOptions, Location, LocationLink, Position, Range, RenameFile, RenameFileOptions, TextDocumentEdit, TextDocumentSaveReason, TextEdit, WorkspaceEdit, WorkspaceFolder, WorkspaceFoldersChangeEvent } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import which from 'which' +import channels from './channels' +import Configurations from './configuration' +import ConfigurationShape from './configuration/shape' +import events from './events' +import DB from './model/db' +import Document from './model/document' +import FileSystemWatcher from './model/fileSystemWatcher' +import Mru from './model/mru' +import Resolver from './model/resolver' +import Task from './model/task' +import TerminalModel, { TerminalOptions } from './model/terminal' +import BufferSync, { SyncItem } from './model/bufferSync' +import { TextDocumentContentProvider } from './provider' +import { ConfigurationChangeEvent, ConfigurationTarget, DidChangeTextDocumentParams, DocumentChange, EditerState, Env, FileCreateEvent, FileDeleteEvent, FileRenameEvent, FileWillCreateEvent, FileWillDeleteEvent, FileWillRenameEvent, IWorkspace, OutputChannel, PatternType, QuickfixItem, TextDocumentWillSaveEvent, WorkspaceConfiguration } from './types' +import { distinct } from './util/array' +import { findUp, fixDriver, inDirectory, isFile, isParentFolder, readFileLine, renameAsync, resolveRoot, statAsync } from './util/fs' +import { CONFIG_FILE_NAME, disposeAll, getKeymapModifier, platform, runCommand, wait, MapMode } from './util/index' +import { score } from './util/match' +import { getChangedFromEdits } from './util/position' +import { byteIndex, byteLength } from './util/string' +import Watchman from './watchman' +import window from './window' +import { version as VERSION } from '../package.json' + +export interface KeymapOption { + sync: boolean + cancel: boolean + silent: boolean + repeat: boolean +} + +export interface Autocmd { + pattern?: string + event: string | string[] + arglist?: string[] + request?: boolean + thisArg?: any + callback: Function +} + +const APIVERSION = 10 +const logger = require('./util/logger')('workspace') +let NAME_SPACE = 2000 +const methods = [ + 'showMessage', + 'runTerminalCommand', + 'openTerminal', + 'showQuickpick', + 'menuPick', + 'openLocalConfig', + 'showPrompt', + 'createStatusBarItem', + 'createOutputChannel', + 'showOutputChannel', + 'requestInput', + 'echoLines', + 'getCursorPosition', + 'moveTo', + 'getOffset'] + +export class Workspace implements IWorkspace { + public readonly nvim: Neovim + public readonly version: string + public readonly keymaps: Map = new Map() + public bufnr: number + private maxFileSize: number + private resolver: Resolver = new Resolver() + private rootPatterns: Map = new Map() + private _workspaceFolders: WorkspaceFolder[] = [] + private _insertMode = false + private _env: Env + private _root: string + private _cwd = process.cwd() + private _initialized = false + private _attached = false + private buffers: Map = new Map() + private autocmdMaxId = 0 + private autocmds: Map = new Map() + private terminals: Map = new Map() + private creatingSources: Map = new Map() + private schemeProviderMap: Map = new Map() + private namespaceMap: Map = new Map() + private disposables: Disposable[] = [] + private watchedOptions: Set = new Set() + + private _dynAutocmd = false + private _disposed = false + private _onDidOpenDocument = new Emitter() + private _onDidCloseDocument = new Emitter() + private _onDidChangeDocument = new Emitter() + private _onWillSaveDocument = new Emitter() + private _onDidSaveDocument = new Emitter() + private _onDidChangeWorkspaceFolders = new Emitter() + private _onDidChangeConfiguration = new Emitter() + private _onDidWorkspaceInitialized = new Emitter() + private _onDidOpenTerminal = new Emitter() + private _onDidCloseTerminal = new Emitter() + private _onDidRuntimePathChange = new Emitter() + + public readonly onDidCloseTerminal: Event = this._onDidCloseTerminal.event + public readonly onDidOpenTerminal: Event = this._onDidOpenTerminal.event + public readonly onDidChangeWorkspaceFolders: Event = this._onDidChangeWorkspaceFolders.event + public readonly onDidOpenTextDocument: Event = this._onDidOpenDocument.event + public readonly onDidCloseTextDocument: Event = this._onDidCloseDocument.event + public readonly onDidChangeTextDocument: Event = this._onDidChangeDocument.event + public readonly onWillSaveTextDocument: Event = this._onWillSaveDocument.event + public readonly onDidSaveTextDocument: Event = this._onDidSaveDocument.event + public readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event + public readonly onDidWorkspaceInitialized: Event = this._onDidWorkspaceInitialized.event + public readonly onDidRuntimePathChange: Event = this._onDidRuntimePathChange.event + public readonly configurations: Configurations + + private _onDidCreateFiles = new Emitter() + private _onDidRenameFiles = new Emitter() + private _onDidDeleteFiles = new Emitter() + private _onWillCreateFiles = new Emitter() + private _onWillRenameFiles = new Emitter() + private _onWillDeleteFiles = new Emitter() + + public readonly onDidCreateFiles: Event = this._onDidCreateFiles.event + public readonly onDidRenameFiles: Event = this._onDidRenameFiles.event + public readonly onDidDeleteFiles: Event = this._onDidDeleteFiles.event + public readonly onWillCreateFiles: Event = this._onWillCreateFiles.event + public readonly onWillRenameFiles: Event = this._onWillRenameFiles.event + public readonly onWillDeleteFiles: Event = this._onWillDeleteFiles.event + + constructor() { + this.version = VERSION + this.configurations = this.createConfigurations() + let cwd = process.cwd() + if (cwd != os.homedir() && inDirectory(cwd, ['.vim'])) { + this._workspaceFolders.push({ + uri: URI.file(cwd).toString(), + name: path.basename(cwd) + }) + } + } + + public async init(): Promise { + let { nvim } = this + for (let method of methods) { + Object.defineProperty(this, method, { + get: () => { + return (...args: any[]) => { + // logger.warn(`workspace.${method} is deprecated, please use window.${method} instead.`, Error().stack) + return window[method].apply(window, args) + } + } + }) + } + this._env = await nvim.call('coc#util#vim_info') as Env + if (this._env.apiversion != APIVERSION) { + console.error(`API version ${this._env.apiversion} is not ${APIVERSION}, please build coc.nvim by 'yarn install' after pull source code.`) + process.exit() + } + this._insertMode = this._env.mode.startsWith('insert') + if (this._env.workspaceFolders && Array.isArray(this._env.workspaceFolders)) { + this._workspaceFolders = this._env.workspaceFolders.map(f => ({ + uri: URI.file(f).toString(), + name: path.dirname(f) + })) + } + this.configurations.updateUserConfig(this._env.config) + let preferences = this.getConfiguration('coc.preferences') + let maxFileSize = preferences.get('maxFileSize', '10MB') + this.maxFileSize = bytes.parse(maxFileSize) + events.on(['InsertEnter', 'CursorMovedI'], () => { + this._insertMode = true + }, null, this.disposables) + events.on(['InsertLeave', 'CursorMoved'], () => { + this._insertMode = false + }, null, this.disposables) + events.on('BufEnter', this.onBufEnter, this, this.disposables) + events.on('CursorMoved', this.checkCurrentBuffer, this, this.disposables) + events.on('CursorMovedI', this.checkCurrentBuffer, this, this.disposables) + events.on('DirChanged', this.onDirChanged, this, this.disposables) + events.on('BufCreate', this.onBufCreate, this, this.disposables) + events.on('BufUnload', this.onBufUnload, this, this.disposables) + events.on('TermOpen', this.onBufCreate, this, this.disposables) + events.on('TermClose', this.onBufUnload, this, this.disposables) + events.on('BufWritePost', this.onBufWritePost, this, this.disposables) + events.on('BufWritePre', this.onBufWritePre, this, this.disposables) + events.on('FileType', this.onFileTypeChange, this, this.disposables) + events.on('CursorHold', this.checkCurrentBuffer, this, this.disposables) + events.on('TextChanged', this.checkBuffer, this, this.disposables) + events.on('BufReadCmd', this.onBufReadCmd, this, this.disposables) + events.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', (oldValue, newValue: string) => { + let result = fastDiff(oldValue, newValue) + for (let [changeType, value] of result) { + if (changeType == 1) { + let paths = value.replace(/,$/, '').split(',') + this._onDidRuntimePathChange.fire(paths) + } + } + this._env.runtimepath = newValue + }, this.disposables) + this.watchGlobal('coc_sources_disable_map', async (_, newValue) => { + this.env.disabledSources = newValue + }) + this.disposables.push(this.registerTextDocumentContentProvider('output', channels.getProvider(nvim))) + } + + public getConfigFile(target: ConfigurationTarget): string { + return this.configurations.getConfigFile(target) + } + + /** + * Register autocmd on vim. + */ + public registerAutocmd(autocmd: Autocmd): Disposable { + this.autocmdMaxId += 1 + let id = this.autocmdMaxId + this.autocmds.set(id, autocmd) + this.setupDynamicAutocmd() + return Disposable.create(() => { + this.autocmds.delete(id) + this.setupDynamicAutocmd() + }) + } + + /** + * Watch for option change. + */ + public watchOption(key: string, callback: (oldValue: any, newValue: any) => Thenable | void, disposables?: Disposable[]): void { + let watching = this.watchedOptions.has(key) + if (!watching) { + this.watchedOptions.add(key) + this.setupDynamicAutocmd() + } + let disposable = events.on('OptionSet', async (changed: string, oldValue: any, newValue: any) => { + if (changed == key && callback) { + await Promise.resolve(callback(oldValue, newValue)) + } + }) + if (disposables) { + disposables.push( + Disposable.create(() => { + disposable.dispose() + if (watching) return + this.watchedOptions.delete(key) + this.setupDynamicAutocmd() + }) + ) + } + } + + /** + * Watch global variable, works on neovim only. + */ + public watchGlobal(key: string, callback?: (oldValue: any, newValue: any) => Thenable | void, disposables?: Disposable[]): void { + let { nvim } = this + nvim.call('coc#_watch', key, true) + let disposable = events.on('GlobalChange', async (changed: string, oldValue: any, newValue: any) => { + if (changed == key && callback) { + await Promise.resolve(callback(oldValue, newValue)) + } + }) + if (disposables) { + disposables.push( + Disposable.create(() => { + disposable.dispose() + nvim.call('coc#_unwatch', key, true) + }) + ) + } + } + + public get cwd(): string { + return this._cwd + } + + public get env(): Env { + return this._env + } + + public get root(): string { + return this._root || this.cwd + } + + public get rootPath(): string { + return this.root + } + + public get workspaceFolders(): WorkspaceFolder[] { + return this._workspaceFolders + } + + /** + * uri of current file, could be null + * + * @deprecated this method is reliable, will be removed in the feature. + */ + public get uri(): string { + let { bufnr } = this + if (bufnr) { + let document = this.getDocument(bufnr) + if (document && document.schema == 'file') { + return document.uri + } + } + return null + } + + public get workspaceFolder(): WorkspaceFolder { + let { rootPath } = this + if (rootPath == os.homedir()) return null + return { + uri: URI.file(rootPath).toString(), + name: path.basename(rootPath) + } + } + + public get textDocuments(): TextDocument[] { + let docs: TextDocument[] = [] + for (let b of this.buffers.values()) { + docs.push(b.textDocument) + } + return docs + } + + public get documents(): Document[] { + return Array.from(this.buffers.values()) + } + + public createNameSpace(name = ''): number { + if (this.namespaceMap.has(name)) return this.namespaceMap.get(name) + NAME_SPACE = NAME_SPACE + 1 + this.namespaceMap.set(name, NAME_SPACE) + return NAME_SPACE + } + + public get channelNames(): string[] { + return channels.names + } + + public get pluginRoot(): string { + return path.dirname(__dirname) + } + + public get isVim(): boolean { + return this._env.isVim + } + + public get isNvim(): boolean { + return !this._env.isVim + } + + public get completeOpt(): string { + return this._env.completeOpt + } + + public get initialized(): boolean { + return this._initialized + } + + public get ready(): Promise { + if (this._initialized) return Promise.resolve() + return new Promise(resolve => { + let disposable = this.onDidWorkspaceInitialized(() => { + disposable.dispose() + resolve() + }) + }) + } + + /** + * Current filetypes. + */ + public get filetypes(): Set { + let res = new Set() + for (let doc of this.documents) { + res.add(doc.filetype) + } + return res + } + + /** + * Check if selector match document. + */ + public match(selector: DocumentSelector, document: TextDocument): number { + return score(selector, document.uri, document.languageId) + } + + /** + * Findup for filename or filenames from current filepath or root. + */ + public async findUp(filename: string | string[]): Promise { + let { cwd } = this + let filepath = await this.nvim.call('expand', '%:p') as string + filepath = path.normalize(filepath) + let isFile = filepath && path.isAbsolute(filepath) + if (isFile && !isParentFolder(cwd, filepath, true)) { + // can't use cwd + return findUp(filename, path.dirname(filepath)) + } + let res = findUp(filename, cwd) + if (res && res != os.homedir()) return res + if (isFile) return findUp(filename, path.dirname(filepath)) + return null + } + + // eslint-disable-next-line @typescript-eslint/require-await + public async resolveRootFolder(uri: URI, patterns: string[]): Promise { + let { cwd } = this + if (uri.scheme != 'file') return cwd + let filepath = path.normalize(uri.fsPath) + let dir = path.dirname(filepath) + return resolveRoot(dir, patterns) || dir + } + + /** + * Create a FileSystemWatcher instance, + * doesn't fail when watchman not found. + */ + public createFileSystemWatcher(globPattern: string, ignoreCreate?: boolean, ignoreChange?: boolean, ignoreDelete?: boolean): FileSystemWatcher { + let watchmanPath = global.hasOwnProperty('__TEST__') ? null : this.getWatchmanPath() + let channel: OutputChannel = watchmanPath ? window.createOutputChannel('watchman') : null + let promise = watchmanPath ? Watchman.createClient(watchmanPath, this.root, channel) : Promise.resolve(null) + let watcher = new FileSystemWatcher( + promise, + globPattern, + !!ignoreCreate, + !!ignoreChange, + !!ignoreDelete + ) + return watcher + } + + public getWatchmanPath(): string | null { + const preferences = this.getConfiguration('coc.preferences') + let watchmanPath = preferences.get('watchmanPath', 'watchman') + try { + return which.sync(watchmanPath) + } catch (e) { + return null + } + } + + /** + * Get configuration by section and optional resource uri. + */ + public getConfiguration(section?: string, resource?: string): WorkspaceConfiguration { + return this.configurations.getConfiguration(section, resource) + } + + /** + * Get created document by uri or bufnr. + */ + public getDocument(uri: number | string): Document { + if (typeof uri === 'number') { + return this.buffers.get(uri) + } + const caseInsensitive = platform.isWindows || platform.isMacintosh + uri = URI.parse(uri).toString() + for (let doc of this.buffers.values()) { + if (!doc) continue + if (doc.uri === uri) return doc + if (path.resolve(doc.uri) === path.resolve(uri)) return doc + if (caseInsensitive && doc.uri.toLowerCase() === uri.toLowerCase()) return doc + } + return null + } + + /** + * Apply WorkspaceEdit. + */ + public async applyEdit(edit: WorkspaceEdit): Promise { + let { nvim } = this + let { documentChanges, changes } = edit + let [bufnr, cursor] = await nvim.eval('[bufnr("%"),coc#cursor#position()]') as [number, [number, number]] + let document = this.getDocument(bufnr) + let uri = document ? document.uri : null + let currEdits = null + let locations: Location[] = [] + let changeCount = 0 + const preferences = this.getConfiguration('coc.preferences') + let promptUser = !global.hasOwnProperty('__TEST__') && preferences.get('promptWorkspaceEdit', true) + let listTarget = preferences.get('listOfWorkspaceEdit', 'quickfix') + try { + if (documentChanges && documentChanges.length) { + let changedUris = this.getChangedUris(documentChanges) + changeCount = changedUris.length + if (promptUser) { + let diskCount = changedUris.reduce((p, c) => { + return p + (this.getDocument(c) == null ? 1 : 0) + }, 0) + if (diskCount) { + let res = await window.showPrompt(`${diskCount} documents on disk would be loaded for change, confirm?`) + if (!res) return + } + } + let changedMap: Map = new Map() + for (const change of documentChanges) { + if (TextDocumentEdit.is(change)) { + let { textDocument, edits } = change + let doc = await this.loadFile(textDocument.uri) + if (textDocument.uri == uri) currEdits = edits + await doc.applyEdits(edits) + for (let edit of edits) { + locations.push({ uri: doc.uri, range: edit.range }) + } + } else if (CreateFile.is(change)) { + let file = URI.parse(change.uri).fsPath + await this.createFile(file, change.options) + } else if (RenameFile.is(change)) { + changedMap.set(change.oldUri, change.newUri) + await this.renameFile(URI.parse(change.oldUri).fsPath, URI.parse(change.newUri).fsPath, change.options) + } else if (DeleteFile.is(change)) { + await this.deleteFile(URI.parse(change.uri).fsPath, change.options) + } + } + // fix location uris on renameFile + if (changedMap.size) { + locations.forEach(location => { + let newUri = changedMap.get(location.uri) + if (newUri) location.uri = newUri + }) + } + } else if (changes) { + let uris = Object.keys(changes) + let unloaded = uris.filter(uri => this.getDocument(uri) == null) + if (unloaded.length) { + if (promptUser) { + let res = await window.showPrompt(`${unloaded.length} documents on disk would be loaded for change, confirm?`) + if (!res) return + } + await this.loadFiles(unloaded) + } + for (let uri of Object.keys(changes)) { + let document = this.getDocument(uri) + if (URI.parse(uri).toString() == uri) currEdits = changes[uri] + let edits = changes[uri] + for (let edit of edits) { + locations.push({ uri: document.uri, range: edit.range }) + } + await document.applyEdits(edits) + } + changeCount = uris.length + } + if (currEdits) { + let changed = getChangedFromEdits({ line: cursor[0], character: cursor[1] }, currEdits) + if (changed) await window.moveTo({ + line: cursor[0] + changed.line, + character: cursor[1] + changed.character + }) + } + if (locations.length) { + let items = await Promise.all(locations.map(loc => this.getQuickfixItem(loc))) + let silent = locations.every(l => l.uri == uri) + if (listTarget == 'quickfix') { + await this.nvim.call('setqflist', [items]) + if (!silent) window.showMessage(`changed ${changeCount} buffers, use :wa to save changes to disk and :copen to open quickfix list`, 'more') + } else if (listTarget == 'location') { + await nvim.setVar('coc_jump_locations', items) + if (!silent) window.showMessage(`changed ${changeCount} buffers, use :wa to save changes to disk and :CocList location to manage changed locations`, 'more') + } + } + } catch (e) { + logger.error('Error on applyEdits:', edit, e) + window.showMessage(`Error on applyEdits: ${e.message}`, 'error') + return false + } + await wait(50) + return true + } + + /** + * Convert location to quickfix item. + */ + public async getQuickfixItem(loc: Location | LocationLink, text?: string, type = '', module?: string): Promise { + if (LocationLink.is(loc)) { + loc = Location.create(loc.targetUri, loc.targetRange) + } + let doc = this.getDocument(loc.uri) + let { uri, range } = loc + let { line, character } = range.start + let sl = range.start.line + let sc = range.start.character + let el = range.end.line + let ec = range.end.character + let u = URI.parse(uri) + let bufnr = doc ? doc.bufnr : -1 + if (!text && u.scheme == 'file') { + text = await this.getLine(uri, line) + character = byteIndex(text, character) + } + let item: QuickfixItem = { + uri, + filename: u.scheme == 'file' ? u.fsPath : uri, + lnum: sl + 1, + end_lnum: el + 1, + col: sc + 1, + end_col: ec + 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. + */ + public createMru(name: string): Mru { + return new Mru(name) + } + + /** + * Get selected range for current document + */ + public async getSelectedRange(mode: string, document: Document): Promise { + let { nvim } = this + if (mode === 'line') { + let line = await nvim.call('line', ['.']) + let content = document.getline(line - 1) + if (!content.length) return null + return Range.create(line - 1, 0, line, 0) + } + if (mode === 'cursor') { + let [line, character] = await nvim.eval("coc#cursor#position()") as [number, number] + return Range.create(line, character, line, character) + } + if (!['v', 'V', 'char', 'line', '\x16'].includes(mode)) { + throw new Error(`Mode '${mode}' not supported`) + } + let isVisual = ['v', 'V', '\x16'].includes(mode) + let [, sl, sc] = await nvim.call('getpos', isVisual ? `'<` : `'[`) as [number, number, number] + let [, el, ec] = await nvim.call('getpos', isVisual ? `'>` : `']`) as [number, number, number] + let range = 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 + */ + public async selectRange(range: Range): Promise { + let { nvim } = this + let { start, end } = range + let [bufnr, ve, selection] = await nvim.eval(`[bufnr('%'), &virtualedit, &selection]`) as [number, string, string] + let doc = this.getDocument(bufnr) + if (!doc || !doc.attached) return + let line = doc.getline(start.line) + let col = line ? byteLength(line.slice(0, start.character)) : 0 + let endLine = doc.getline(end.line) + let endCol = endLine ? 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}])`) as number + 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}])`) as number + 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. + */ + public async showLocations(locations: Location[]): Promise { + let items = await Promise.all(locations.map(loc => this.getQuickfixItem(loc))) + let { nvim } = this + const preferences = this.getConfiguration('coc.preferences') + if (preferences.get('useQuickfixForLocations', false)) { + let openCommand = await nvim.getVar('coc_quickfix_open_command') as string + if (typeof openCommand != 'string') { + openCommand = items.length < 10 ? `copen ${items.length}` : 'copen' + } + nvim.pauseNotification() + nvim.call('setqflist', [items], true) + nvim.command(openCommand, true) + // eslint-disable-next-line @typescript-eslint/no-floating-promises + nvim.resumeNotification(false, true) + } else { + await nvim.setVar('coc_jump_locations', items) + if (this.env.locationlist) { + nvim.command('CocList --normal --auto-preview location', true) + } else { + nvim.call('coc#util#do_autocmd', ['CocLocationsChange'], true) + } + } + } + + /** + * Get content of line by uri and line. + */ + public async getLine(uri: string, line: number): Promise { + let document = this.getDocument(uri) + if (document) return document.getline(line) || '' + if (!uri.startsWith('file:')) return '' + let fsPath = URI.parse(uri).fsPath + if (!fs.existsSync(fsPath)) return '' + return await readFileLine(fsPath, line) + } + + /** + * Get WorkspaceFolder of uri + */ + public getWorkspaceFolder(uri: string): WorkspaceFolder | null { + this.workspaceFolders.sort((a, b) => b.uri.length - a.uri.length) + let filepath = URI.parse(uri).fsPath + return this.workspaceFolders.find(folder => isParentFolder(URI.parse(folder.uri).fsPath, filepath, true)) + } + + /** + * Get content from buffer of file by uri. + */ + public async readFile(uri: string): Promise { + let document = this.getDocument(uri) + if (document) { + await document.patchChange() + return document.content + } + let u = URI.parse(uri) + if (u.scheme != 'file') return '' + let lines = await this.nvim.call('readfile', [u.fsPath]) as string[] + return lines.join('\n') + '\n' + } + + /** + * Current document. + */ + public get document(): Promise { + return new Promise((resolve, reject) => { + this.nvim.buffer.then(buf => { + let bufnr = buf.id + this.bufnr = bufnr + if (this.buffers.has(bufnr)) { + resolve(this.buffers.get(bufnr)) + return + } + this.onBufCreate(bufnr).catch(reject) + let disposable = this.onDidOpenTextDocument(doc => { + disposable.dispose() + resolve(this.getDocument(doc.uri)) + }) + }, reject) + }) + } + + /** + * Get current document and position. + */ + public async getCurrentState(): Promise { + let document = await this.document + let position = await window.getCursorPosition() + return { + document: document.textDocument, + position + } + } + + /** + * Get format options + */ + public async getFormatOptions(uri?: string): Promise { + let doc: Document + if (uri) doc = this.getDocument(uri) + let bufnr = doc ? doc.bufnr : 0 + let [tabSize, insertSpaces] = await this.nvim.call('coc#util#get_format_opts', [bufnr]) as [number, number] + return { + tabSize, + insertSpaces: insertSpaces == 1 + } as FormattingOptions + } + + /** + * Jump to location. + */ + public async jumpTo(uri: string, position?: Position | null, openCommand?: string): Promise { + 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 + if (bufnr != -1 && jumpCommand == 'edit') { + // use buffer command since edit command would reload the buffer + nvim.pauseNotification() + nvim.command(`silent! normal! m'`, true) + nvim.command(`buffer ${bufnr}`, true) + if (position) { + let line = doc.getline(position.line) + let col = byteLength(line.slice(0, position.character)) + 1 + nvim.call('cursor', [position.line + 1, col], true) + } + if (this.isVim) nvim.command('redraw', true) + await nvim.resumeNotification() + } else { + let { fsPath, scheme } = URI.parse(uri) + let pos = position == null ? null : [position.line, position.character] + if (scheme == 'file') { + let bufname = fixDriver(path.normalize(fsPath)) + await this.nvim.call('coc#util#jump', [jumpCommand, bufname, pos]) + } else { + if (os.platform() == 'win32') { + uri = uri.replace(/\/?/, '?') + } + await this.nvim.call('coc#util#jump', [jumpCommand, uri, pos]) + } + } + } + + /** + * Create a file in vim and disk + */ + public async createFile(filepath: string, opts: CreateFileOptions = {}): Promise { + let stat = await statAsync(filepath) + if (stat && !opts.overwrite && !opts.ignoreIfExists) { + window.showMessage(`${filepath} already exists!`, 'error') + return + } + if (!stat || opts.overwrite) { + // directory + if (filepath.endsWith('/')) { + try { + filepath = this.expand(filepath) + await fs.mkdirp(filepath) + } catch (e) { + window.showMessage(`Can't create ${filepath}: ${e.message}`, 'error') + } + } else { + let uri = URI.file(filepath).toString() + let doc = this.getDocument(uri) + if (doc) return + if (!fs.existsSync(path.dirname(filepath))) { + fs.mkdirpSync(path.dirname(filepath)) + } + fs.writeFileSync(filepath, '', 'utf8') + await this.loadFile(uri) + } + } + } + + /** + * Load uri as document. + */ + public async loadFile(uri: string): Promise { + let doc = this.getDocument(uri) + if (doc) return doc + let { nvim } = this + let filepath = uri.startsWith('file') ? 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 = 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 + */ + public async loadFiles(uris: string[]): Promise { + 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 => URI.parse(u).fsPath)]) as number[] + let create = bufnrs.filter(bufnr => this.getDocument(bufnr) == null) + if (!create.length) return + 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 + */ + public async renameFile(oldPath: string, newPath: string, opts: RenameFileOptions = {}): Promise { + let { overwrite, ignoreIfExists } = opts + let { nvim } = this + try { + let stat = await statAsync(newPath) + if (stat && !overwrite && !ignoreIfExists) { + throw new Error(`${newPath} already exists`) + } + if (!stat || overwrite) { + let uri = URI.file(oldPath).toString() + let newUri = URI.file(newPath).toString() + let doc = this.getDocument(uri) + if (doc != null) { + let isCurrent = doc.bufnr == this.bufnr + let newDoc = this.getDocument(newUri) + if (newDoc) await this.nvim.command(`silent ${newDoc.bufnr}bwipeout!`) + let content = doc.getDocumentContent() + await fs.writeFile(newPath, content, 'utf8') + // open renamed file + if (!isCurrent) { + await nvim.call('coc#util#open_files', [[newPath]]) + await nvim.command(`silent ${doc.bufnr}bwipeout!`) + } else { + let view = await nvim.call('winsaveview') + nvim.pauseNotification() + nvim.call('coc#util#open_file', ['keepalt edit', newPath], true) + nvim.command(`silent ${doc.bufnr}bwipeout!`, true) + nvim.call('winrestview', [view], true) + await nvim.resumeNotification() + } + // avoid vim detect file unlink + await fs.unlink(oldPath) + } else { + await renameAsync(oldPath, newPath) + } + } + } catch (e) { + window.showMessage(`Rename error: ${e.message}`, 'error') + } + } + + /** + * Delete file from vim and disk. + */ + public async deleteFile(filepath: string, opts: DeleteFileOptions = {}): Promise { + let { ignoreIfNotExists, recursive } = opts + let stat = await statAsync(filepath.replace(/\/$/, '')) + let isDir = stat && stat.isDirectory() + if (filepath.endsWith('/') && !isDir) { + window.showMessage(`${filepath} is not directory`, 'error') + return + } + if (!stat && !ignoreIfNotExists) { + window.showMessage(`${filepath} not exists`, 'error') + return + } + if (stat == null) return + if (isDir && !recursive) { + window.showMessage(`Can't remove directory, recursive not set`, 'error') + return + } + try { + if (isDir && recursive) { + await fs.remove(filepath) + } else if (isDir) { + await fs.rmdir(filepath) + } else { + await fs.unlink(filepath) + } + if (!isDir) { + let uri = URI.file(filepath).toString() + let doc = this.getDocument(uri) + if (doc) await this.nvim.command(`silent! bwipeout! ${doc.bufnr}`) + } + } catch (e) { + window.showMessage(`Error on delete ${filepath}: ${e.message}`, 'error') + } + } + + /** + * Open resource by uri + */ + public async openResource(uri: string): Promise { + 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) + } + + /** + * Resolve module from yarn or npm. + */ + public async resolveModule(name: string): Promise { + return await this.resolver.resolveModule(name) + } + + /** + * Run nodejs command + */ + public async runCommand(cmd: string, cwd?: string, timeout?: number): Promise { + cwd = cwd || this.cwd + return runCommand(cmd, { cwd }, timeout) + } + + /** + * Expand filepath with `~` and/or environment placeholders + */ + public expand(filepath: string): string { + if (!filepath) return filepath + if (filepath.startsWith('~')) { + filepath = os.homedir() + filepath.slice(1) + } + if (filepath.includes('$')) { + let doc = this.getDocument(this.bufnr) + let fsPath = doc ? URI.parse(doc.uri).fsPath : '' + filepath = filepath.replace(/\$\{(.*?)\}/g, (match: string, name: string) => { + if (name.startsWith('env:')) { + let key = name.split(':')[1] + let val = key ? process.env[key] : '' + return val + } + switch (name) { + case 'workspace': + case 'workspaceRoot': + case 'workspaceFolder': + return this.root + case 'workspaceFolderBasename': + return path.dirname(this.root) + case 'cwd': + return this.cwd + case 'file': + return fsPath + case 'fileDirname': + return fsPath ? path.dirname(fsPath) : '' + case 'fileExtname': + return fsPath ? path.extname(fsPath) : '' + case 'fileBasename': + return fsPath ? path.basename(fsPath) : '' + case 'fileBasenameNoExtension': { + let basename = fsPath ? path.basename(fsPath) : '' + return basename ? basename.slice(0, basename.length - path.extname(basename).length) : '' + } + default: + return match + } + }) + filepath = filepath.replace(/\$[\w]+/g, match => { + if (match == '$HOME') return os.homedir() + return process.env[match.slice(1)] || match + }) + } + return filepath + } + + public async createTerminal(opts: TerminalOptions): Promise { + let cmd = opts.shellPath + let args = opts.shellArgs + if (!cmd) cmd = await this.nvim.getOption('shell') as string + let terminal = new TerminalModel(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 + } + + public async callAsync(method: string, args: any[]): Promise { + if (this.isNvim) return await this.nvim.call(method, args) + return await this.nvim.callAsync('coc#util#with_callback', [method, args]) + } + + /** + * registerTextDocumentContentProvider + */ + public registerTextDocumentContentProvider(scheme: string, provider: TextDocumentContentProvider): Disposable { + this.schemeProviderMap.set(scheme, provider) + this.setupDynamicAutocmd() + let disposables: Disposable[] = [] + if (provider.onDidChange) { + provider.onDidChange(async uri => { + let doc = this.getDocument(uri.toString()) + if (doc) { + let { buffer } = doc + let tokenSource = new CancellationTokenSource() + let content = await Promise.resolve(provider.provideTextDocumentContent(uri, tokenSource.token)) + await buffer.setLines(content.split(/\r?\n/), { + start: 0, + end: -1, + strictIndexing: false + }) + } + }, null, disposables) + } + return Disposable.create(() => { + this.schemeProviderMap.delete(scheme) + disposeAll(disposables) + this.setupDynamicAutocmd() + }) + } + + /** + * Register unique keymap uses `(coc-{key})` as lhs + * Throw error when {key} already exists. + * + * @param {MapMode[]} modes - array of 'n' | 'i' | 'v' | 'x' | 's' | 'o' + * @param {string} key - unique name + * @param {Function} fn - callback function + * @param {Partial} opts + * @returns {Disposable} + */ + public registerKeymap(modes: MapMode[], key: string, fn: Function, opts: Partial = {}): Disposable { + if (!key) throw new Error(`Invalid key ${key} of registerKeymap`) + if (this.keymaps.has(key)) throw new Error(`${key} already exists.`) + 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 ? '' : '' + for (let m of modes) { + if (m == 'i') { + nvim.command(`inoremap ${silent} (coc-${key}) coc#_insert_key('${method}', '${key}', ${opts.cancel ? 1 : 0})`, true) + } else { + let modify = getKeymapModifier(m) + nvim.command(`${m}noremap ${silent} (coc-${key}) :${modify}call coc#rpc#${method}('doKeymap', ['${key}'])`, true) + } + } + return Disposable.create(() => { + this.keymaps.delete(key) + for (let m of modes) { + nvim.command(`${m}unmap (coc-${key})`, true) + } + }) + } + + /** + * Register expr keymap. + */ + public registerExprKeymap(mode: 'i' | 'n' | 'v' | 's' | 'x', key: string, fn: Function, buffer = false): Disposable { + if (!key) return + let id = `${mode}${global.Buffer.from(key).toString('base64')}${buffer ? '1' : '0'}` + let { nvim } = this + this.keymaps.set(id, [fn, false]) + if (mode == 'i') { + nvim.command(`inoremap ${buffer ? '' : ''} ${key} coc#_insert_key('request', '${id}')`, true) + } else { + nvim.command(`${mode}noremap ${buffer ? '' : ''} ${key} coc#rpc#request('doKeymap', ['${id}'])`, true) + } + return Disposable.create(() => { + this.keymaps.delete(id) + nvim.command(`${mode}unmap ${buffer ? '' : ''} ${key}`, true) + }) + } + + public registerLocalKeymap(mode: 'n' | 'v' | 's' | 'x', key: string, fn: Function, notify = false): Disposable { + let id = uuid() + let { nvim, bufnr } = this + this.keymaps.set(id, [fn, false]) + let method = notify ? 'notify' : 'request' + let modify = getKeymapModifier(mode) + // neoivm's bug '<' can't be used. + let escaped = key.startsWith('<') && key.endsWith('>') ? `{${key.slice(1, -1)}}` : key + if (this.isNvim && !global.hasOwnProperty('__TEST__')) { + nvim.call('nvim_buf_set_keymap', [0, mode, key, `:${modify}call coc#rpc#${method}('doKeymap', ['${id}', '', '${escaped}'])`, { + silent: true, + nowait: true + }], true) + } else { + let cmd = `${mode}noremap ${key} :${modify}call coc#rpc#${method}('doKeymap', ['${id}', '', '${escaped}'])` + nvim.command(cmd, true) + } + return Disposable.create(() => { + this.keymaps.delete(id) + nvim.call('coc#compat#buf_del_keymap', [bufnr, mode, key], true) + }) + } + + /** + * Create DB instance at extension root. + */ + public createDatabase(name: string): DB { + let root: string + if (global.hasOwnProperty('__TEST__')) { + root = path.join(os.tmpdir(), `coc-${process.pid}`) + fs.mkdirpSync(root) + } else { + root = path.dirname(this.env.extensionRoot) + } + let filepath = path.join(root, name + '.json') + return new DB(filepath) + } + + /** + * Create Task instance that runs in vim. + */ + public createTask(id: string): Task { + return new Task(this.nvim, id) + } + + public registerBufferSync(create: (doc: Document) => T | undefined): BufferSync { + return new BufferSync(create, this) + } + + public setupDynamicAutocmd(initialize = false): void { + if (!initialize && !this._dynAutocmd) return + this._dynAutocmd = true + let schemes = this.schemeProviderMap.keys() + let cmds: string[] = [] + for (let scheme of schemes) { + cmds.push(`autocmd BufReadCmd,FileReadCmd,SourceCmd ${scheme}:/* call coc#rpc#request('CocAutocmd', ['BufReadCmd','${scheme}', expand('')])`) + } + 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 = autocmd.pattern != null ? autocmd.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(''), v:option_old, v:option_new])`) + } + let content = ` +augroup coc_dynamic_autocmd + autocmd! + ${cmds.join('\n ')} +augroup end` + try { + let dir = path.join(process.env.TMPDIR || os.tmpdir(), `coc.nvim-${process.pid}`) + if (!fs.existsSync(dir)) fs.mkdirpSync(dir) + let filepath = path.join(dir, `coc-${process.pid}.vim`) + fs.writeFileSync(filepath, content, 'utf8') + let cmd = `source ${filepath}` + if (this.env.isCygwin && platform.isWindows) { + cmd = `execute "source" . substitute(system('cygpath ${filepath.replace(/\\/g, '/')}'), '\\n', '', 'g')` + } + this.nvim.command(cmd).logError() + } catch (e) { + window.showMessage(`Can't create tmp file: ${e.message}`, 'error') + } + } + + private async onBufReadCmd(scheme: string, uri: string): Promise { + let provider = this.schemeProviderMap.get(scheme) + if (!provider) { + window.showMessage(`Provider for ${scheme} not found`, 'error') + return + } + let tokenSource = new CancellationTokenSource() + let content = await Promise.resolve(provider.provideTextDocumentContent(URI.parse(uri), tokenSource.token)) + let buf = await this.nvim.buffer + await buf.setLines(content.split(/\r?\n/), { + start: 0, + end: -1, + strictIndexing: false + }) + setTimeout(async () => { + await events.fire('BufCreate', [buf.id]) + }, 30) + } + + public async attach(): Promise { + if (this._attached) return + this._attached = true + let [bufs, bufnr, winid] = await this.nvim.eval(`[map(getbufinfo({'bufloaded': 1}),'v:val["bufnr"]'),bufnr('%'),win_getid()]`) as [number[], number, number] + this.bufnr = bufnr + await Promise.all(bufs.map(buf => this.onBufCreate(buf))) + if (!this._initialized) { + this._onDidWorkspaceInitialized.fire(void 0) + this._initialized = true + } + await events.fire('BufEnter', [bufnr]) + await events.fire('BufWinEnter', [bufnr, winid]) + } + + // count of document need change + private getChangedUris(documentChanges: DocumentChange[] | null): string[] { + let uris: Set = new Set() + let createUris: Set = new Set() + for (let change of documentChanges) { + if (TextDocumentEdit.is(change)) { + let { textDocument } = change + let { uri, version } = textDocument + uris.add(uri) + if (version != null && version > 0) { + let doc = this.getDocument(uri) + if (!doc) { + throw new Error(`${uri} not loaded`) + } + if (doc.version != version) { + throw new Error(`${uri} changed before apply edit`) + } + } + } else if (CreateFile.is(change) || DeleteFile.is(change)) { + if (!isFile(change.uri)) { + throw new Error(`change of scheme ${change.uri} not supported`) + } + createUris.add(change.uri) + uris.add(change.uri) + } else if (RenameFile.is(change)) { + if (!isFile(change.oldUri) || !isFile(change.newUri)) { + throw new Error(`change of scheme ${change.oldUri} not supported`) + } + let newFile = URI.parse(change.newUri).fsPath + if (fs.existsSync(newFile)) { + throw new Error(`file "${newFile}" already exists for rename`) + } + uris.add(change.oldUri) + } else { + throw new Error(`Invalid document change: ${JSON.stringify(change, null, 2)}`) + } + } + return Array.from(uris) + } + + private createConfigurations(): Configurations { + let home = path.normalize(process.env.COC_VIMCONFIG) || path.join(os.homedir(), '.vim') + let userConfigFile = path.join(home, CONFIG_FILE_NAME) + return new Configurations(userConfigFile, new ConfigurationShape(this)) + } + + // events for sync buffer of vim + private attachChangedEvents(): void { + if (this.isVim) { + const onChange = (bufnr: number) => { + let doc = this.getDocument(bufnr) + if (doc && doc.attached) doc.fetchContent() + } + events.on('TextChangedP', onChange, null, this.disposables) + events.on('TextChangedI', onChange, null, this.disposables) + events.on('TextChanged', onChange, null, this.disposables) + } + } + + private async onBufCreate(buf: number | Buffer): Promise { + 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 CancellationTokenSource() + try { + if (document) this.onBufUnload(bufnr, true) + document = new Document(buffer, this._env, this.maxFileSize) + 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.attached) { + document.onDocumentDetach(bufnr => { + let doc = this.getDocument(bufnr) + if (doc) this.onBufUnload(doc.bufnr) + }) + } + if (document.buftype == '' && document.schema == 'file') { + this.configurations.checkFolderConfiguration(document.uri) + let config = this.getConfiguration('workspace') + let filetypes = config.get('ignoredFiletypes', []) + if (!filetypes.includes(document.filetype)) { + let root = this.resolveRoot(document) + if (root) { + this.addWorkspaceFolder(root) + if (this.bufnr == buffer.id) { + this._root = root + } + } + } + } + if (document.enabled) { + let textDocument: TextDocument & { bufnr: number } = Object.assign(document.textDocument, { bufnr }) + this._onDidOpenDocument.fire(textDocument) + document.onDocumentChange(e => this._onDidChangeDocument.fire(e)) + } + logger.debug('buffer created', buffer.id) + } + + private onBufEnter(bufnr: number): void { + 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 = URI.parse(workspaceFolder.uri).fsPath + } + } + + private async checkCurrentBuffer(bufnr: number): Promise { + this.bufnr = bufnr + await this.checkBuffer(bufnr) + } + + private onBufWritePost(bufnr: number): void { + let doc = this.buffers.get(bufnr) + if (!doc) return + this._onDidSaveDocument.fire(doc.textDocument) + } + + private onBufUnload(bufnr: number, recreate = false): void { + 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) { + let textDocument: TextDocument & { bufnr: number } = Object.assign(doc.textDocument, { bufnr }) + this._onDidCloseDocument.fire(textDocument) + this.buffers.delete(bufnr) + doc.detach() + } + } + + private async onBufWritePre(bufnr: number): Promise { + let doc = this.buffers.get(bufnr) + if (!doc || !doc.attached) return + await doc.synchronize() + let firing = true + let thenables: Thenable[] = [] + let event: TextDocumentWillSaveEvent = { + document: doc.textDocument, + reason: TextDocumentSaveReason.Manual, + waitUntil: (thenable: Thenable) => { + if (!firing) { + logger.error(`Can't call waitUntil in async manner:`, Error().stack) + window.showMessage(`waitUntil can't be used in async manner, check log for details`, 'error') + } else { + thenables.push(thenable) + } + } + } + this._onWillSaveDocument.fire(event) + firing = false + let total = thenables.length + if (total) { + let promise = new Promise(resolve => { + const preferences = this.getConfiguration('coc.preferences') + const willSaveHandlerTimeout = preferences.get('willSaveHandlerTimeout', 500) + let timer = setTimeout(() => { + window.showMessage(`Will save handler timeout after ${willSaveHandlerTimeout}ms`, 'warning') + resolve(undefined) + }, willSaveHandlerTimeout) + let i = 0 + let called = false + for (let p of thenables) { + let cb = (res: any) => { + if (called) return + called = true + clearTimeout(timer) + resolve(res) + } + p.then(res => { + if (Array.isArray(res) && res.length && TextEdit.is(res[0])) { + return cb(res) + } + i = i + 1 + if (i == total) cb(undefined) + }, () => { + i = i + 1 + if (i == total) cb(undefined) + }) + } + }) + let edits = await promise + if (edits) await doc.applyEdits(edits) + } + } + + private onDirChanged(cwd: string): void { + if (cwd == this._cwd) return + this._cwd = cwd + } + + private onFileTypeChange(filetype: string, bufnr: number): void { + let doc = this.getDocument(bufnr) + if (!doc) return + let converted = doc.convertFiletype(filetype) + if (converted == doc.filetype) return + let textDocument: TextDocument & { bufnr: number } = Object.assign(doc.textDocument, { bufnr }) + this._onDidCloseDocument.fire(textDocument) + doc.setFiletype(filetype) + this._onDidOpenDocument.fire(Object.assign(doc.textDocument, { bufnr })) + } + + private async checkBuffer(bufnr: number): Promise { + if (this._disposed || !bufnr) return + let doc = this.getDocument(bufnr) + if (!doc && !this.creatingSources.has(bufnr)) await this.onBufCreate(bufnr) + } + + private resolveRoot(document: Document): string { + let types = [PatternType.Buffer, PatternType.LanguageServer, PatternType.Global] + let u = URI.parse(document.uri) + let dir = path.dirname(u.fsPath) + let { cwd } = this + let config = this.getConfiguration('workspace') + let bottomUpFileTypes = config.get('bottomUpFiletypes', []) + let checkCwd = config.get('workspaceFolderCheckCwd', true) + for (let patternType of types) { + let patterns = this.getRootPatterns(document, patternType) + if (patterns && patterns.length) { + let isBottomUp = bottomUpFileTypes.includes(document.filetype) + let root = resolveRoot(dir, patterns, cwd, isBottomUp, checkCwd) + if (root) return root + } + } + if (this.cwd != os.homedir() && isParentFolder(this.cwd, dir, true)) return this.cwd + return null + } + + public getRootPatterns(document: Document, patternType: PatternType): string[] { + let { uri } = document + if (patternType == PatternType.Buffer) return document.getVar('root_patterns', []) || [] + if (patternType == PatternType.LanguageServer) return this.getServerRootPatterns(document.filetype) + const preferences = this.getConfiguration('coc.preferences', uri) + return preferences.get('rootPatterns', ['.git', '.hg', '.projections.json']).slice() + } + + public async renameCurrent(): Promise { + 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 = URI.parse(doc.uri).fsPath + // await nvim.callAsync() + let newPath = await nvim.callAsync('coc#util#with_callback', ['input', ['New path: ', oldPath, 'file']]) + newPath = newPath ? newPath.trim() : null + if (newPath == oldPath || !newPath) return + let lines = await doc.buffer.lines + let exists = fs.existsSync(oldPath) + if (exists) { + let modified = await nvim.eval('&modified') + if (modified) await nvim.command('noa w') + if (oldPath.toLowerCase() != newPath.toLowerCase() && fs.existsSync(newPath)) { + let overwrite = await window.showPrompt(`${newPath} exists, overwrite?`) + if (!overwrite) return + fs.unlinkSync(newPath) + } + fs.renameSync(oldPath, newPath) + } + this._onWillRenameFiles.fire({ + files: [{ newUri: URI.parse(newPath), oldUri: URI.parse(oldPath) }], + waitUntil: async thenable => { + const edit = await Promise.resolve(thenable) + if (edit && WorkspaceEdit.is(edit)) { + await this.applyEdit(edit) + } + } + }) + this._onDidRenameFiles.fire({ + files: [{ newUri: URI.parse(newPath), oldUri: URI.parse(oldPath) }], + }) + let filepath = isParentFolder(cwd, newPath) ? path.relative(cwd, newPath) : newPath + let view = await nvim.call('winsaveview') + 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('winrestview', [view], true) + await nvim.resumeNotification() + } + + public get folderPaths(): string[] { + return this.workspaceFolders.map(f => URI.parse(f.uri).fsPath) + } + + public get floatSupported(): boolean { + let { env } = this + return env.floating || env.textprop + } + + public removeWorkspaceFolder(fsPath: string): void { + let idx = this._workspaceFolders.findIndex(f => 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: [] + }) + } + } + + public renameWorkspaceFolder(oldPath: string, newPath: string): void { + let idx = this._workspaceFolders.findIndex(f => URI.parse(f.uri).fsPath == oldPath) + if (idx == -1) return + let removed = this._workspaceFolders[idx] + let added: WorkspaceFolder = { + uri: URI.file(newPath).toString(), + name: path.dirname(newPath) + } + this._workspaceFolders.splice(idx, 1) + this._workspaceFolders.push(added) + this._onDidChangeWorkspaceFolders.fire({ + removed: [removed], + added: [added] + }) + } + + public addRootPattern(filetype: string, rootPatterns: string[]): void { + let patterns = this.rootPatterns.get(filetype) || [] + for (let p of rootPatterns) { + if (!patterns.includes(p)) { + patterns.push(p) + } + } + this.rootPatterns.set(filetype, patterns) + } + + public get insertMode(): boolean { + return this._insertMode + } + + public async detach(): Promise { + if (!this._attached) return + this._attached = false + channels.dispose() + for (let bufnr of this.buffers.keys()) { + await events.fire('BufUnload', [bufnr]) + } + } + + public dispose(): void { + this._disposed = true + for (let doc of this.documents) { + doc.detach() + } + disposeAll(this.disposables) + Watchman.dispose() + this.configurations.dispose() + this.buffers.clear() + } + + private addWorkspaceFolder(rootPath: string): WorkspaceFolder { + if (rootPath == os.homedir()) return + let { _workspaceFolders } = this + let uri = URI.file(rootPath).toString() + let workspaceFolder: WorkspaceFolder = { uri, name: path.basename(rootPath) } + if (_workspaceFolders.findIndex(o => o.uri == uri) == -1) { + _workspaceFolders.push(workspaceFolder) + if (this._initialized) { + this._onDidChangeWorkspaceFolders.fire({ + added: [workspaceFolder], + removed: [] + }) + } + } + return workspaceFolder + } + + private getServerRootPatterns(filetype: string): string[] { + let lspConfig = this.getConfiguration().get<{ [key: string]: unknown }>('languageserver', {}) + let patterns: string[] = [] + for (let key of Object.keys(lspConfig)) { + let config: any = lspConfig[key] + let { filetypes, rootPatterns } = config + if (Array.isArray(filetypes) && rootPatterns && filetypes.includes(filetype)) { + patterns.push(...rootPatterns) + } + } + patterns = patterns.concat(this.rootPatterns.get(filetype) || []) + return patterns.length ? distinct(patterns) : null + } +} + +export default new Workspace() diff --git a/vim-config/plugins/coc.nvim/tsconfig.json b/vim-config/plugins/coc.nvim/tsconfig.json new file mode 100644 index 00000000..a73b1415 --- /dev/null +++ b/vim-config/plugins/coc.nvim/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "outDir": "lib", + "noEmit": true, + "sourceMap": true, + "importHelpers": true, + "allowUnreachableCode": false, + "forceConsistentCasingInFileNames": true, + "noImplicitAny": false, + "noImplicitThis": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "strictPropertyInitialization": false, + "target": "es2017", + "module": "commonjs", + "moduleResolution": "node", + "experimentalDecorators": true, + "lib": ["es2017", "es2018", "es2019"], + "declaration": false, + "resolveJsonModule": true, + "esModuleInterop": true, + "strictNullChecks": false, + "strictFunctionTypes": false, + "plugins": [] + }, + "include": ["src"], + "exclude": ["typings", "build", "node_modules"] +} diff --git a/vim-config/plugins/coc.nvim/typings/LICENSE b/vim-config/plugins/coc.nvim/typings/LICENSE new file mode 100644 index 00000000..fc9556c9 --- /dev/null +++ b/vim-config/plugins/coc.nvim/typings/LICENSE @@ -0,0 +1,19 @@ +Copyright 2020 chemzqm@gmail.com + +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. diff --git a/vim-config/plugins/coc.nvim/typings/Readme.md b/vim-config/plugins/coc.nvim/typings/Readme.md new file mode 100644 index 00000000..b3ebe4eb --- /dev/null +++ b/vim-config/plugins/coc.nvim/typings/Readme.md @@ -0,0 +1,18 @@ +This package contains typings of coc.nvim only. + +Files were exported from https://github.com/neoclide/coc.nvim/blob/master/typings + +## Installation + + npm install --save-dev coc.nvim + +## Support coc.nvim + +If you like my work, consider supporting me on Patreon or PayPal: + +Patreon donate button +PayPal donate button + +## Credits + +[Visual Studio Code](https://github.com/microsoft/vscode), and [Microsoft](https://github.com/microsoft) diff --git a/vim-config/plugins/coc.nvim/typings/index.d.ts b/vim-config/plugins/coc.nvim/typings/index.d.ts new file mode 100644 index 00000000..261c6c4d --- /dev/null +++ b/vim-config/plugins/coc.nvim/typings/index.d.ts @@ -0,0 +1,8794 @@ +// vim: set sw=2 ts=2 sts=2 et foldmarker={{,}} foldmethod=marker foldlevel=0 nofen: +/****************************************************************** +MIT License http://www.opensource.org/licenses/mit-license.php +Author Qiming Zhao (https://github.com/chemzqm) +*******************************************************************/ + +/// +import cp from 'child_process' + +declare module 'coc.nvim' { + // Language server protocol interfaces {{ + export interface Thenable { + then(onfulfilled?: (value: T) => TResult | Thenable, onrejected?: (reason: any) => TResult | Thenable): Thenable + // eslint-disable-next-line @typescript-eslint/unified-signatures + then(onfulfilled?: (value: T) => TResult | Thenable, onrejected?: (reason: any) => void): Thenable + } + + export interface Disposable { + /** + * Dispose this object. + */ + dispose(): void + } + + export namespace Disposable { + function create(func: () => void): Disposable + } + /** + * The declaration of a symbol representation as one or many [locations](#Location). + */ + export type Declaration = Location | Location[] + /** + * Information about where a symbol is declared. + * + * Provides additional metadata over normal [location](#Location) declarations, including the range of + * the declaring symbol. + * + * Servers should prefer returning `DeclarationLink` over `Declaration` if supported + * by the client. + */ + export type DeclarationLink = LocationLink + + export type ProgressToken = number | string + + export interface WorkDoneProgressBegin { + kind: 'begin' + /** + * Mandatory title of the progress operation. Used to briefly inform about + * the kind of operation being performed. + * + * Examples: "Indexing" or "Linking dependencies". + */ + title: string + /** + * Controls if a cancel button should show to allow the user to cancel the + * long running operation. Clients that don't support cancellation are allowed + * to ignore the setting. + */ + cancellable?: boolean + /** + * Optional, more detailed associated progress message. Contains + * complementary information to the `title`. + * + * Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". + * If unset, the previous progress message (if any) is still valid. + */ + message?: string + /** + * Optional progress percentage to display (value 100 is considered 100%). + * If not provided infinite progress is assumed and clients are allowed + * to ignore the `percentage` value in subsequent in report notifications. + * + * The value should be steadily rising. Clients are free to ignore values + * that are not following this rule. + */ + percentage?: number + } + + export interface WorkDoneProgressReport { + kind: 'report' + /** + * Controls enablement state of a cancel button. This property is only valid if a cancel + * button got requested in the `WorkDoneProgressStart` payload. + * + * Clients that don't support cancellation or don't support control the button's + * enablement state are allowed to ignore the setting. + */ + cancellable?: boolean + /** + * Optional, more detailed associated progress message. Contains + * complementary information to the `title`. + * + * Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". + * If unset, the previous progress message (if any) is still valid. + */ + message?: string + /** + * Optional progress percentage to display (value 100 is considered 100%). + * If not provided infinite progress is assumed and clients are allowed + * to ignore the `percentage` value in subsequent in report notifications. + * + * The value should be steadily rising. Clients are free to ignore values + * that are not following this rule. + */ + percentage?: number + } + + /** + * The file event type + */ + export namespace FileChangeType { + /** + * The file got created. + */ + const Created = 1 + /** + * The file got changed. + */ + const Changed = 2 + /** + * The file got deleted. + */ + const Deleted = 3 + } + + export type FileChangeType = 1 | 2 | 3 + + /** + * An event describing a file change. + */ + export interface FileEvent { + /** + * The file's uri. + */ + uri: string + /** + * The change type. + */ + type: FileChangeType + } + + export interface WorkDoneProgressEnd { + kind: 'end' + /** + * Optional, a final message indicating to for example indicate the outcome + * of the operation. + */ + message?: string + } + + /** + * A literal to identify a text document in the client. + */ + export interface TextDocumentIdentifier { + /** + * The text document's uri. + */ + uri: string + } + + /** + * A parameter literal used in requests to pass a text document and a position inside that + * document. + */ + export interface TextDocumentPositionParams { + /** + * The text document. + */ + textDocument: TextDocumentIdentifier + /** + * The position inside the text document. + */ + position: Position + } + + export interface WorkspaceFolder { + /** + * The associated URI for this workspace folder. + */ + uri: string + /** + * The name of the workspace folder. Used to refer to this + * workspace folder in the user interface. + */ + name: string + } + + /** + * An event describing a change to a text document. + */ + export interface TextDocumentContentChange { + /** + * The range of the document that changed. + */ + range: Range + /** + * The new text for the provided range. + */ + text: string + } + + /** + * The workspace folder change event. + */ + export interface WorkspaceFoldersChangeEvent { + /** + * The array of added workspace folders + */ + added: WorkspaceFolder[] + /** + * The array of the removed workspace folders + */ + removed: WorkspaceFolder[] + } + + /** + * An event that is fired when a [document](#TextDocument) will be saved. + * + * To make modifications to the document before it is being saved, call the + * [`waitUntil`](#TextDocumentWillSaveEvent.waitUntil)-function with a thenable + * that resolves to an array of [text edits](#TextEdit). + */ + export interface TextDocumentWillSaveEvent { + + /** + * The document that will be saved. + */ + document: TextDocument + + /** + * The reason why save was triggered. + */ + reason: 1 | 2 | 3 + } + + /** + * A document filter denotes a document by different properties like + * the [language](#TextDocument.languageId), the [scheme](#Uri.scheme) of + * its resource, or a glob-pattern that is applied to the [path](#TextDocument.fileName). + * + * Glob patterns can have the following syntax: + * - `*` to match one or more characters in a path segment + * - `?` to match on one character in a path segment + * - `**` to match any number of path segments, including none + * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) + * - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + * - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) + * + * @sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` + * @sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` + */ + export type DocumentFilter = { + /** A language id, like `typescript`. */ + language: string + /** A Uri [scheme](#Uri.scheme), like `file` or `untitled`. */ + scheme?: string + /** A glob pattern, like `*.{ts,js}`. */ + pattern?: string + } | { + /** A language id, like `typescript`. */ + language?: string + /** A Uri [scheme](#Uri.scheme), like `file` or `untitled`. */ + scheme: string + /** A glob pattern, like `*.{ts,js}`. */ + pattern?: string + } | { + /** A language id, like `typescript`. */ + language?: string + /** A Uri [scheme](#Uri.scheme), like `file` or `untitled`. */ + scheme?: string + /** A glob pattern, like `*.{ts,js}`. */ + pattern: string + } + /** + * A document selector is the combination of one or many document filters. + * + * @sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`; + */ + export type DocumentSelector = (string | DocumentFilter)[] + /** + * A selection range represents a part of a selection hierarchy. A selection range + * may have a parent selection range that contains it. + */ + export interface SelectionRange { + /** + * The [range](#Range) of this selection range. + */ + range: Range + /** + * The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. + */ + parent?: SelectionRange + } + + /** + * MarkedString can be used to render human readable text. It is either a markdown string + * or a code-block that provides a language and a code snippet. The language identifier + * is semantically equal to the optional language identifier in fenced code blocks in GitHub + * issues. See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + * + * The pair of a language and a value is an equivalent to markdown: + * ```${language} + * ${value} + * ``` + * + * Note that markdown strings will be sanitized - that means html will be escaped. + * @deprecated use MarkupContent instead. + */ + export type MarkedString = string | { + language: string + value: string + } + /** + * The result of a hover request. + */ + export interface Hover { + /** + * The hover's content + */ + contents: MarkupContent | MarkedString | MarkedString[] + /** + * An optional range + */ + range?: Range + } + + /** + * The definition of a symbol represented as one or many [locations](#Location). + * For most programming languages there is only one location at which a symbol is + * defined. + * + * Servers should prefer returning `DefinitionLink` over `Definition` if supported + * by the client. + */ + export type Definition = Location | Location[] + + /** + * Information about where a symbol is defined. + * + * Provides additional metadata over normal [location](#Location) definitions, including the range of + * the defining symbol + */ + export type DefinitionLink = LocationLink + + /** + * How a signature help was triggered. + */ + export namespace SignatureHelpTriggerKind { + /** + * Signature help was invoked manually by the user or by a command. + */ + const Invoked: 1 + /** + * Signature help was triggered by a trigger character. + */ + const TriggerCharacter: 2 + /** + * Signature help was triggered by the cursor moving or by the document content changing. + */ + const ContentChange: 3 + } + + export type SignatureHelpTriggerKind = 1 | 2 | 3 + + /** + * Represents the signature of something callable. A signature + * can have a label, like a function-name, a doc-comment, and + * a set of parameters. + */ + export interface SignatureInformation { + /** + * The label of this signature. Will be shown in + * the UI. + */ + label: string + /** + * The human-readable doc-comment of this signature. Will be shown + * in the UI but can be omitted. + */ + documentation?: string | MarkupContent + /** + * The parameters of this signature. + */ + parameters?: ParameterInformation[] + } + + /** + * Represents a parameter of a callable-signature. A parameter can + * have a label and a doc-comment. + */ + export interface ParameterInformation { + /** + * The label of this parameter information. + * + * Either a string or an inclusive start and exclusive end offsets within its containing + * signature label. (see SignatureInformation.label). The offsets are based on a UTF-16 + * string representation as `Position` and `Range` does. + * + * *Note*: a label of type string should be a substring of its containing signature label. + * Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`. + */ + label: string | [number, number] + /** + * The human-readable doc-comment of this signature. Will be shown + * in the UI but can be omitted. + */ + documentation?: string | MarkupContent + } + + /** + * Signature help represents the signature of something + * callable. There can be multiple signature but only one + * active and only one active parameter. + */ + export interface SignatureHelp { + /** + * One or more signatures. + */ + signatures: SignatureInformation[] + /** + * The active signature. Set to `null` if no + * signatures exist. + */ + activeSignature: number | null + /** + * The active parameter of the active signature. Set to `null` + * if the active signature has no parameters. + */ + activeParameter: number | null + } + /** + * Additional information about the context in which a signature help request was triggered. + * + * @since 3.15.0 + */ + export interface SignatureHelpContext { + /** + * Action that caused signature help to be triggered. + */ + triggerKind: SignatureHelpTriggerKind + /** + * Character that caused signature help to be triggered. + * + * This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter` + */ + triggerCharacter?: string + /** + * `true` if signature help was already showing when it was triggered. + * + * Retriggers occur when the signature help is already active and can be caused by actions such as + * typing a trigger character, a cursor move, or document content changes. + */ + isRetrigger: boolean + /** + * The currently active `SignatureHelp`. + * + * The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on + * the user navigating through available signatures. + */ + activeSignatureHelp?: SignatureHelp + } + + /** + * Represents a folding range. + */ + export interface FoldingRange { + /** + * The zero-based line number from where the folded range starts. + */ + startLine: number + /** + * The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. + */ + startCharacter?: number + /** + * The zero-based line number where the folded range ends. + */ + endLine: number + /** + * The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. + */ + endCharacter?: number + /** + * Describes the kind of the folding range such as `comment' or 'region'. The kind + * is used to categorize folding ranges and used by commands like 'Fold all comments'. See + * [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds. + */ + kind?: string + } + + /** + * A symbol kind. + */ + export namespace SymbolKind { + const File: 1 + const Module: 2 + const Namespace: 3 + const Package: 4 + const Class: 5 + const Method: 6 + const Property: 7 + const Field: 8 + const Constructor: 9 + const Enum: 10 + const Interface: 11 + const Function: 12 + const Variable: 13 + const Constant: 14 + const String: 15 + const Number: 16 + const Boolean: 17 + const Array: 18 + const Object: 19 + const Key: 20 + const Null: 21 + const EnumMember: 22 + const Struct: 23 + const Event: 24 + const Operator: 25 + const TypeParameter: 26 + } + + export type SymbolKind = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 + + /** + * Represents information about programming constructs like variables, classes, + * interfaces etc. + */ + export interface SymbolInformation { + /** + * The name of this symbol. + */ + name: string + /** + * The kind of this symbol. + */ + kind: SymbolKind + /** + * Indicates if this symbol is deprecated. + */ + deprecated?: boolean + /** + * The location of this symbol. The location's range is used by a tool + * to reveal the location in the editor. If the symbol is selected in the + * tool the range's start information is used to position the cursor. So + * the range usually spans more than the actual symbol's name and does + * normally include thinks like visibility modifiers. + * + * The range doesn't have to denote a node range in the sense of a abstract + * syntax tree. It can therefore not be used to re-construct a hierarchy of + * the symbols. + */ + location: Location + /** + * The name of the symbol containing this symbol. This information is for + * user interface purposes (e.g. to render a qualifier in the user interface + * if necessary). It can't be used to re-infer a hierarchy for the document + * symbols. + */ + containerName?: string + } + + /** + * 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. + */ + export interface DocumentSymbol { + /** + * The name of this symbol. Will be displayed in the user interface and therefore must not be + * an empty string or a string only consisting of white spaces. + */ + name: string + /** + * More detail for this symbol, e.g the signature of a function. + */ + detail?: string + /** + * The kind of this symbol. + */ + kind: SymbolKind + /** + * Indicates if this symbol is deprecated. + */ + deprecated?: boolean + /** + * The range enclosing this symbol not including leading/trailing whitespace but everything else + * like comments. This information is typically used to determine if the the clients cursor is + * inside the symbol to reveal in the symbol in the UI. + */ + range: Range + /** + * The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. + * Must be contained by the the `range`. + */ + selectionRange: Range + /** + * Children of this symbol, e.g. properties of a class. + */ + children?: DocumentSymbol[] + } + + export interface FormattingOptions { + /** + * If indentation is based on spaces (`insertSpaces` = true), the number of spaces that make an indent. + */ + tabSize?: number + /** + * Is indentation based on spaces? + */ + insertSpaces?: boolean + /** + * The default 'end of line' character. If not set, '\n' is used as default. + */ + eol?: string + } + + /** + * Contains additional diagnostic information about the context in which + * a [code action](#CodeActionProvider.provideCodeActions) is run. + */ + export interface CodeActionContext { + /** + * An array of diagnostics known on the client side overlapping the range provided to the + * `textDocument/codeAction` request. They are provied so that the server knows which + * errors are currently presented to the user for the given range. There is no guarantee + * that these accurately reflect the error state of the resource. The primary parameter + * to compute code actions is the provided range. + */ + diagnostics: Diagnostic[] + /** + * Requested kind of actions to return. + * + * Actions not of this kind are filtered out by the client before being shown. So servers + * can omit computing them. + */ + only?: string[] + } + + + /** + * A document highlight kind. + */ + export namespace DocumentHighlightKind { + /** + * A textual occurrence. + */ + const Text: 1 + /** + * Read-access of a symbol, like reading a variable. + */ + const Read: 2 + /** + * Write-access of a symbol, like writing to a variable. + */ + const Write: 3 + } + + export type DocumentHighlightKind = 1 | 2 | 3 + /** + * A document highlight is a range inside a text document which deserves + * special attention. Usually a document highlight is visualized by changing + * the background color of its range. + */ + export interface DocumentHighlight { + /** + * The range this highlight applies to. + */ + range: Range + /** + * The highlight kind, default is [text](#DocumentHighlightKind.Text). + */ + kind?: DocumentHighlightKind + } + + /** + * 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. + */ + export interface DocumentLink { + /** + * The range this link applies to. + */ + range: Range + /** + * The uri this link points to. + */ + target?: string + /** + * The tooltip text when you hover over this link. + * + * If a tooltip is provided, is will be displayed in a string that includes instructions on how to + * trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS, + * user settings, and localization. + * + * @since 3.15.0 + */ + tooltip?: string + /** + * A data entry field that is preserved on a document link between a + * DocumentLinkRequest and a DocumentLinkResolveRequest. + */ + data?: any + } + + /** + * Represents a color in RGBA space. + */ + export interface Color { + /** + * The red component of this color in the range [0-1]. + */ + readonly red: number + /** + * The green component of this color in the range [0-1]. + */ + readonly green: number + /** + * The blue component of this color in the range [0-1]. + */ + readonly blue: number + /** + * The alpha component of this color in the range [0-1]. + */ + readonly alpha: number + } + + /** + * Represents a color range from a document. + */ + export interface ColorInformation { + /** + * The range in the document where this color appers. + */ + range: Range + /** + * The actual color value for this color range. + */ + color: Color + } + + export interface ColorPresentation { + /** + * The label of this color presentation. It will be shown on the color + * picker header. By default this is also the text that is inserted when selecting + * this color presentation. + */ + label: string + /** + * An [edit](#TextEdit) which is applied to a document when selecting + * this presentation for the color. When `falsy` the [label](#ColorPresentation.label) + * is used. + */ + textEdit?: TextEdit + /** + * An optional array of additional [text edits](#TextEdit) that are applied when + * selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves. + */ + additionalTextEdits?: TextEdit[] + } + + /** + * A code lens represents a [command](#Command) that should be shown along with + * source text, like the number of references, a way to run tests, etc. + * + * A code lens is _unresolved_ when no command is associated to it. For performance + * reasons the creation of a code lens and resolving should be done to two stages. + */ + export interface CodeLens { + /** + * The range in which this code lens is valid. Should only span a single line. + */ + range: Range + /** + * The command this code lens represents. + */ + command?: Command + /** + * An data entry field that is preserved on a code lens item between + * a [CodeLensRequest](#CodeLensRequest) and a [CodeLensResolveRequest] + * (#CodeLensResolveRequest) + */ + data?: any + } + + /** + * Represents the connection of two locations. Provides additional metadata over normal [locations](#Location), + * including an origin range. + */ + export interface LocationLink { + /** + * Span of the origin of this link. + * + * Used as the underlined span for mouse definition hover. Defaults to the word range at + * the definition position. + */ + originSelectionRange?: Range + /** + * The target resource identifier of this link. + */ + targetUri: string + /** + * The full target range of this link. If the target for example is a symbol then target range is the + * range enclosing this symbol not including leading/trailing whitespace but everything else + * like comments. This information is typically used to highlight the range in the editor. + */ + targetRange: Range + /** + * The range that should be selected and revealed when this link is being followed, e.g the name of a function. + * Must be contained by the the `targetRange`. See also `DocumentSymbol#range` + */ + targetSelectionRange: Range + } + + /** + * The LocationLink namespace provides helper functions to work with + * [LocationLink](#LocationLink) literals. + */ + export namespace 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: string, targetRange: Range, targetSelectionRange: Range, originSelectionRange?: Range): LocationLink + /** + * Checks whether the given literal conforms to the [LocationLink](#LocationLink) interface. + */ + function is(value: any): value is LocationLink + } + + export type MarkupKind = 'plaintext' | 'markdown' + + /** + * 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. + */ + export namespace MarkupKind { + /** + * Plain text is supported as a content format + */ + const PlainText: 'plaintext' + /** + * Markdown is supported as a content format + */ + const Markdown: 'markdown' + } + /** + * A `MarkupContent` literal represents a string value which content is interpreted base on its + * kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds. + * + * If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues. + * See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + * + * Here is an example how such a string can be constructed using JavaScript / TypeScript: + * ```ts + * let markdown: MarkdownContent = { + * kind: MarkupKind.Markdown, + * value: [ + * '# Header', + * 'Some text', + * '```typescript', + * 'someCode();', + * '```' + * ].join('\n') + * }; + * ``` + * + * *Please Note* that clients might sanitize the return markdown. A client could decide to + * remove HTML from the markdown to avoid script execution. + */ + export interface MarkupContent { + /** + * The type of the Markup + */ + kind: MarkupKind + /** + * The content itself + */ + value: string + } + + /** + * The kind of a completion entry. + */ + export namespace CompletionItemKind { + const Text: 1 + const Method: 2 + const Function: 3 + const Constructor: 4 + const Field: 5 + const Variable: 6 + const Class: 7 + const Interface: 8 + const Module: 9 + const Property: 10 + const Unit: 11 + const Value: 12 + const Enum: 13 + const Keyword: 14 + const Snippet: 15 + const Color: 16 + const File: 17 + const Reference: 18 + const Folder: 19 + const EnumMember: 20 + const Constant: 21 + const Struct: 22 + const Event: 23 + const Operator: 24 + const TypeParameter: 25 + } + + export type CompletionItemKind = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 + + /** + * Defines whether the insert text in a completion item should be interpreted as + * plain text or a snippet. + */ + export namespace InsertTextFormat { + /** + * The primary text to be inserted is treated as a plain string. + */ + const 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/main/src/vs/editor/contrib/snippet/snippet.md + */ + const Snippet: 2 + } + export type InsertTextFormat = 1 | 2 + + /** + * A completion item represents a text snippet that is + * proposed to complete text that is being typed. + */ + export interface CompletionItem { + /** + * The label of this completion item. By default + * also the text that is inserted when selecting + * this completion. + */ + label: string + /** + * The kind of this completion item. Based of the kind + * an icon is chosen by the editor. + */ + kind?: CompletionItemKind + /** + * Tags for this completion item. + * + * @since 3.15.0 + */ + tags?: number[] + /** + * A human-readable string with additional information + * about this item, like type or symbol information. + */ + detail?: string + /** + * A human-readable string that represents a doc-comment. + */ + documentation?: string | MarkupContent + /** + * Indicates if this item is deprecated. + * @deprecated Use `tags` instead. + */ + deprecated?: boolean + /** + * Select this item when showing. + * + * *Note* that only one completion item can be selected and that the + * tool / client decides which item that is. The rule is that the *first* + * item of those that match best is selected. + */ + preselect?: boolean + /** + * A string that should be used when comparing this item + * with other items. When `falsy` the [label](#CompletionItem.label) + * is used. + */ + sortText?: string + /** + * A string that should be used when filtering a set of + * completion items. When `falsy` the [label](#CompletionItem.label) + * is used. + */ + filterText?: string + /** + * A string that should be inserted into a document when selecting + * this completion. When `falsy` the [label](#CompletionItem.label) + * is used. + * + * The `insertText` is subject to interpretation by the client side. + * Some tools might not take the string literally. For example + * VS Code when code complete is requested in this example `con` + * and a completion item with an `insertText` of `console` is provided it + * will only insert `sole`. Therefore it is recommended to use `textEdit` instead + * since it avoids additional client side interpretation. + */ + insertText?: string + /** + * The format of the insert text. The format applies to both the `insertText` property + * and the `newText` property of a provided `textEdit`. If omitted defaults to + * `InsertTextFormat.PlainText`. + */ + insertTextFormat?: InsertTextFormat + /** + * An [edit](#TextEdit) which is applied to a document when selecting + * this completion. When an edit is provided the value of + * [insertText](#CompletionItem.insertText) is ignored. + * + * *Note:* The text edit's range must be a [single line] and it must contain the position + * at which completion has been requested. + */ + textEdit?: TextEdit + /** + * An optional array of additional [text edits](#TextEdit) that are applied when + * selecting this completion. Edits must not overlap (including the same insert position) + * with the main [edit](#CompletionItem.textEdit) nor with themselves. + * + * Additional text edits should be used to change text unrelated to the current cursor position + * (for example adding an import statement at the top of the file if the completion item will + * insert an unqualified type). + */ + additionalTextEdits?: TextEdit[] + /** + * An optional set of characters that when pressed while this completion is active will accept it first and + * then type that character. *Note* that all commit characters should have `length=1` and that superfluous + * characters will be ignored. + */ + commitCharacters?: string[] + /** + * An optional [command](#Command) that is executed *after* inserting this completion. *Note* that + * additional modifications to the current document should be described with the + * [additionalTextEdits](#CompletionItem.additionalTextEdits)-property. + */ + command?: Command + /** + * An data entry field that is preserved on a completion item between + * a [CompletionRequest](#CompletionRequest) and a [CompletionResolveRequest] + * (#CompletionResolveRequest) + */ + data?: any + } + + /** + * Represents a collection of [completion items](#CompletionItem) to be presented + * in the editor. + */ + export interface CompletionList { + /** + * This list it not complete. Further typing results in recomputing this list. + */ + isIncomplete: boolean + /** + * The completion items. + */ + items: CompletionItem[] + } + + /** + * How a completion was triggered + */ + export namespace CompletionTriggerKind { + /** + * Completion was triggered by typing an identifier (24x7 code + * complete), manual invocation (e.g Ctrl+Space) or via API. + */ + const Invoked: 1 + /** + * Completion was triggered by a trigger character specified by + * the `triggerCharacters` properties of the `CompletionRegistrationOptions`. + */ + const TriggerCharacter: 2 + /** + * Completion was re-triggered as current completion list is incomplete + */ + const TriggerForIncompleteCompletions: 3 + } + + export type CompletionTriggerKind = 1 | 2 | 3 + + /** + * Contains additional information about the context in which a completion request is triggered. + */ + export interface CompletionContext { + /** + * How the completion was triggered. + */ + triggerKind: CompletionTriggerKind, + /** + * The trigger character (a single character) that has trigger code complete. + * Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter` + */ + triggerCharacter?: string + + option?: CompleteOption + } + + /** + * Represents a reference to a command. Provides a title which + * will be used to represent a command in the UI and, optionally, + * an array of arguments which will be passed to the command handler + * function when invoked. + */ + export interface Command { + /** + * Title of the command, like `save`. + */ + title: string + /** + * The identifier of the actual command handler. + */ + command: string + /** + * Arguments that the command handler should be + * invoked with. + */ + arguments?: any[] + } + + export interface TextDocumentEdit { + /** + * The text document to change. + */ + textDocument: { + uri: string + version: number | null + } + /** + * The edits to be applied. + */ + edits: TextEdit[] + } + + /** + * A workspace edit represents changes to many resources managed in the workspace. The edit + * should either provide `changes` or `documentChanges`. If documentChanges are present + * they are preferred over `changes` if the client can handle versioned document edits. + */ + export interface WorkspaceEdit { + /** + * Holds changes to existing resources. + */ + changes?: { + [uri: string]: TextEdit[] + } + /** + * Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes + * are either an array of `TextDocumentEdit`s to express changes to n different text documents + * where each text document edit addresses a specific version of a text document. Or it can contain + * above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations. + * + * Whether a client supports versioned document edits is expressed via + * `workspace.workspaceEdit.documentChanges` client capability. + * + * If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then + * only plain `TextEdit`s using the `changes` property are supported. + */ + documentChanges?: (TextDocumentEdit | CreateFile | RenameFile | DeleteFile)[] + } + + interface ResourceOperation { + kind: string + } + + /** + * Delete file options + */ + export interface DeleteFileOptions { + /** + * Delete the content recursively if a folder is denoted. + */ + recursive?: boolean + /** + * Ignore the operation if the file doesn't exist. + */ + ignoreIfNotExists?: boolean + } + /** + * Delete file operation + */ + export interface DeleteFile extends ResourceOperation { + /** + * A delete + */ + kind: 'delete' + /** + * The file to delete. + */ + uri: string + /** + * Delete options. + */ + options?: DeleteFileOptions + } + + /** + * Options to create a file. + */ + export interface CreateFileOptions { + /** + * Overwrite existing file. Overwrite wins over `ignoreIfExists` + */ + overwrite?: boolean + /** + * Ignore if exists. + */ + ignoreIfExists?: boolean + } + /** + * Create file operation. + */ + export interface CreateFile extends ResourceOperation { + /** + * A create + */ + kind: 'create' + /** + * The resource to create. + */ + uri: string + /** + * Additional options + */ + options?: CreateFileOptions + } + + /** + * Rename file options + */ + export interface RenameFileOptions { + /** + * Overwrite target if existing. Overwrite wins over `ignoreIfExists` + */ + overwrite?: boolean + /** + * Ignores if target exists. + */ + ignoreIfExists?: boolean + } + /** + * Rename file operation + */ + export interface RenameFile extends ResourceOperation { + /** + * A rename + */ + kind: 'rename' + /** + * The old (existing) location. + */ + oldUri: string + /** + * The new location. + */ + newUri: string + /** + * Rename options. + */ + options?: RenameFileOptions + } + /** + * Represents a related message and source code location for a diagnostic. This should be + * used to point to code locations that cause or related to a diagnostics, e.g when duplicating + * a symbol in a scope. + */ + export interface DiagnosticRelatedInformation { + /** + * The location of this related diagnostic information. + */ + location: Location + /** + * The message of this related diagnostic information. + */ + message: string + } + + /** + * The diagnostic's severity. + */ + export namespace DiagnosticSeverity { + /** + * Reports an error. + */ + const Error: 1 + /** + * Reports a warning. + */ + const Warning: 2 + /** + * Reports an information. + */ + const Information: 3 + /** + * Reports a hint. + */ + const Hint: 4 + } + + export type DiagnosticSeverity = 1 | 2 | 3 | 4 + + /** + * The diagnostic tags. + * + * @since 3.15.0 + */ + export namespace DiagnosticTag { + /** + * Unused or unnecessary code. + * + * Clients are allowed to render diagnostics with this tag faded out instead of having + * an error squiggle. + */ + const Unnecessary: 1 + /** + * Deprecated or obsolete code. + * + * Clients are allowed to rendered diagnostics with this tag strike through. + */ + const Deprecated: 2 + } + + export type DiagnosticTag = 1 | 2 + + /** + * Represents a diagnostic, such as a compiler error or warning. Diagnostic objects + * are only valid in the scope of a resource. + */ + export interface Diagnostic { + /** + * The range at which the message applies + */ + range: Range + /** + * The diagnostic's severity. Can be omitted. If omitted it is up to the + * client to interpret diagnostics as error, warning, info or hint. + */ + severity?: DiagnosticSeverity + /** + * The diagnostic's code, which usually appear in the user interface. + */ + code?: number | string + /** + * A human-readable string describing the source of this + * diagnostic, e.g. 'typescript' or 'super lint'. It usually + * appears in the user interface. + */ + source?: string + /** + * The diagnostic's message. It usually appears in the user interface + */ + message: string + /** + * Additional metadata about the diagnostic. + */ + tags?: DiagnosticTag[] + /** + * An array of related diagnostic information, e.g. when symbol-names within + * a scope collide all definitions can be marked via this property. + */ + relatedInformation?: DiagnosticRelatedInformation[] + } + + /** + * The Diagnostic namespace provides helper functions to work with + * [Diagnostic](#Diagnostic) literals. + */ + export namespace Diagnostic { + /** + * Creates a new Diagnostic literal. + */ + function create(range: Range, message: string, severity?: DiagnosticSeverity, code?: number | string, source?: string, relatedInformation?: DiagnosticRelatedInformation[]): Diagnostic + /** + * Checks whether the given literal conforms to the [Diagnostic](#Diagnostic) interface. + */ + function is(value: any): value is Diagnostic + } + + /** + * A code action represents a change that can be performed in code, e.g. to fix a problem or + * to refactor code. + * + * A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed. + */ + export interface CodeAction { + /** + * A short, human-readable, title for this code action. + */ + title: string + /** + * The kind of the code action. + * + * Used to filter code actions. + */ + kind?: CodeActionKind + /** + * The diagnostics that this code action resolves. + */ + diagnostics?: Diagnostic[] + /** + * Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted + * by keybindings. + * + * A quick fix should be marked preferred if it properly addresses the underlying error. + * A refactoring should be marked preferred if it is the most reasonable choice of actions to take. + * + * @since 3.15.0 + */ + isPreferred?: boolean + /** + * The workspace edit this code action performs. + */ + edit?: WorkspaceEdit + /** + * A command this code action executes. If a code action + * provides a edit and a command, first the edit is + * executed and then the command. + */ + command?: Command + /** + * Id of client that provide codeAction. + */ + clientId?: string + } + + /** + * The kind of a code action. + * + * Kinds are a hierarchical list of identifiers separated by `.`, e.g. `"refactor.extract.function"`. + * + * The set of kinds is open and client needs to announce the kinds it supports to the server during + * initialization. + */ + export type CodeActionKind = string + /** + * A set of predefined code action kinds + */ + export namespace CodeActionKind { + /** + * Empty kind. + */ + const Empty: CodeActionKind + /** + * Base kind for quickfix actions: 'quickfix' + */ + const QuickFix: CodeActionKind + /** + * Base kind for refactoring actions: 'refactor' + */ + const Refactor: CodeActionKind + /** + * Base kind for refactoring extraction actions: 'refactor.extract' + * + * Example extract actions: + * + * - Extract method + * - Extract function + * - Extract variable + * - Extract interface from class + * - ... + */ + const RefactorExtract: CodeActionKind + /** + * Base kind for refactoring inline actions: 'refactor.inline' + * + * Example inline actions: + * + * - Inline function + * - Inline variable + * - Inline constant + * - ... + */ + const RefactorInline: CodeActionKind + /** + * 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 + * - ... + */ + const RefactorRewrite: CodeActionKind + /** + * Base kind for source actions: `source` + * + * Source code actions apply to the entire file. + */ + const Source: CodeActionKind + /** + * Base kind for an organize imports source action: `source.organizeImports` + */ + const SourceOrganizeImports: CodeActionKind + /** + * Base kind for auto-fix source actions: `source.fixAll`. + * + * Fix all actions automatically fix errors that have a clear fix that do not require user input. + * They should not suppress errors or perform unsafe fixes such as generating new types or classes. + * + * @since 3.15.0 + */ + const SourceFixAll: CodeActionKind + } + + /** + * Position in a text document expressed as zero-based line and character offset. + * The offsets are based on a UTF-16 string representation. So a string of the form + * `a𐐀b` the character offset of the character `a` is 0, the character offset of `𐐀` + * is 1 and the character offset of b is 3 since `𐐀` is represented using two code + * units in UTF-16. + * + * Positions are line end character agnostic. So you can not specify a position that + * denotes `\r|\n` or `\n|` where `|` represents the character offset. + */ + export interface Position { + /** + * Line position in a document (zero-based). + * If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document. + * If a line number is negative, it defaults to 0. + */ + line: number + /** + * Character offset on a line in a document (zero-based). Assuming that the line is + * represented as a string, the `character` value represents the gap between the + * `character` and `character + 1`. + * + * If the character value is greater than the line length it defaults back to the + * line length. + * If a line number is negative, it defaults to 0. + */ + character: number + } + + /** + * The Position namespace provides helper functions to work with + * [Position](#Position) literals. + */ + export namespace 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: number, character: number): Position + /** + * Checks whether the given liternal conforms to the [Position](#Position) interface. + */ + function is(value: any): value is Position + } + + /** + * Represents a typed event. + * + * A function that represents an event to which you subscribe by calling it with + * a listener function as argument. + * + * @example + * item.onDidChange(function(event) { console.log("Event happened: " + event); }); + */ + export interface Event { + + /** + * A function that represents an event to which you subscribe by calling it with + * a listener function as argument. + * + * @param listener The listener function will be called when the event happens. + * @param thisArgs The `this`-argument which will be used when calling the event listener. + * @param disposables An array to which a [disposable](#Disposable) will be added. + * @return A disposable which unsubscribes the event listener. + */ + (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]): Disposable + } + + export namespace Event { + const None: Event + } + + export interface EmitterOptions { + onFirstListenerAdd?: Function + onLastListenerRemove?: Function + } + + export class Emitter { + constructor(_options?: EmitterOptions | undefined) + /** + * For the public to allow to subscribe + * to events from this Emitter + */ + get event(): Event + /** + * To be kept private to fire an event to + * subscribers + */ + fire(event: T): any + dispose(): void + } + + /** + * Represents a location inside a resource, such as a line + * inside a text file. + */ + export interface Location { + uri: string + range: Range + } + + /** + * The Location namespace provides helper functions to work with + * [Location](#Location) literals. + */ + export namespace Location { + /** + * Creates a Location literal. + * @param uri The location's uri. + * @param range The location's range. + */ + function create(uri: string, range: Range): Location + /** + * Checks whether the given literal conforms to the [Location](#Location) interface. + */ + function is(value: any): value is Location + } + + /** + * A range in a text document expressed as (zero-based) start and end positions. + * + * If you want to specify a range that contains a line including the line ending + * character(s) then use an end position denoting the start of the next line. + * For example: + * ```ts + * { + * start: { line: 5, character: 23 } + * end : { line 6, character : 0 } + * } + * ``` + */ + export interface Range { + /** + * The range's start position + */ + start: Position + /** + * The range's end position. + */ + end: Position + } + + /** + * The Range namespace provides helper functions to work with + * [Range](#Range) literals. + */ + export namespace Range { + /** + * Create a new Range liternal. + * @param start The range's start position. + * @param end The range's end position. + */ + function create(start: Position, end: Position): Range + /** + * Create a new Range liternal. + * @param startLine The start line number. + * @param startCharacter The start character. + * @param endLine The end line number. + * @param endCharacter The end character. + */ + function create(startLine: number, startCharacter: number, endLine: number, endCharacter: number): Range + /** + * Checks whether the given literal conforms to the [Range](#Range) interface. + */ + function is(value: any): value is Range + } + + /** + * A text edit applicable to a text document. + */ + export interface TextEdit { + /** + * The range of the text document to be manipulated. To insert + * text into a document create a range where start === end. + */ + range: Range + /** + * The string to be inserted. For delete operations use an + * empty string. + */ + newText: string + } + + /** + * The TextEdit namespace provides helper function to create replace, + * insert and delete edits more easily. + */ + export namespace TextEdit { + /** + * Creates a replace text edit. + * @param range The range of text to be replaced. + * @param newText The new text. + */ + function replace(range: Range, newText: string): TextEdit + /** + * Creates a insert text edit. + * @param position The position to insert the text at. + * @param newText The text to be inserted. + */ + function insert(position: Position, newText: string): TextEdit + /** + * Creates a delete text edit. + * @param range The range of text to be deleted. + */ + function del(range: Range): TextEdit + function is(value: any): value is TextEdit + } + + /** + * Defines a CancellationToken. This interface is not + * intended to be implemented. A CancellationToken must + * be created via a CancellationTokenSource. + */ + export interface CancellationToken { + /** + * Is `true` when the token has been cancelled, `false` otherwise. + */ + readonly isCancellationRequested: boolean + /** + * An [event](#Event) which fires upon cancellation. + */ + readonly onCancellationRequested: Event + } + + export namespace CancellationToken { + const None: CancellationToken + const Cancelled: CancellationToken + function is(value: any): value is CancellationToken + } + + export class CancellationTokenSource { + get token(): CancellationToken + cancel(): void + dispose(): void + } + + /** + * A simple text document. Not to be implemented. The document keeps the content + * as string. + */ + export interface TextDocument { + /** + * The associated URI for this document. Most documents have the __file__-scheme, indicating that they + * represent files on disk. However, some documents may have other schemes indicating that they are not + * available on disk. + * + * @readonly + */ + readonly uri: string + /** + * The identifier of the language associated with this document. + * + * @readonly + */ + readonly languageId: string + /** + * The version number of this document (it will increase after each + * change, including undo/redo). + * + * @readonly + */ + readonly version: number + /** + * Get the text of this document. A substring can be retrieved by + * providing a range. + * + * @param range (optional) An range within the document to return. + * If no range is passed, the full content is returned. + * Invalid range positions are adjusted as described in [Position.line](#Position.line) + * and [Position.character](#Position.character). + * If the start range position is greater than the end range position, + * then the effect of getText is as if the two positions were swapped. + + * @return The text of this document or a substring of the text if a + * range is provided. + */ + getText(range?: Range): string + /** + * Converts a zero-based offset to a position. + * + * @param offset A zero-based offset. + * @return A valid [position](#Position). + */ + positionAt(offset: number): Position + /** + * Converts the position to a zero-based offset. + * Invalid positions are adjusted as described in [Position.line](#Position.line) + * and [Position.character](#Position.character). + * + * @param position A position. + * @return A valid zero-based offset. + */ + offsetAt(position: Position): number + /** + * The number of lines in this document. + * + * @readonly + */ + readonly lineCount: number + } + + /** + * @since 3.16.0 + */ + export interface SemanticTokensLegend { + /** + * The token types a server uses. + */ + tokenTypes: string[] + /** + * The token modifiers a server uses. + */ + tokenModifiers: string[] + } + + /** + * @since 3.16.0 + */ + export interface SemanticTokens { + /** + * An optional result id. If provided and clients support delta updating + * the client will include the result id in the next semantic token request. + * A server can then instead of computing all semantic tokens again simply + * send a delta. + */ + resultId?: string + /** + * The actual tokens. + */ + data: number[] + } + + /** + * @since 3.16.0 + */ + export interface SemanticTokensEdit { + /** + * The start offset of the edit. + */ + start: number + /** + * The count of elements to remove. + */ + deleteCount: number + /** + * The elements to insert. + */ + data?: number[] + } + + /** + * @since 3.16.0 + */ + export interface SemanticTokensDelta { + readonly resultId?: string + /** + * The semantic token edits to transform a previous result into a new result. + */ + edits: SemanticTokensEdit[] + } + + /** + * The result of a linked editing range request. + * + * @since 3.16.0 + */ + export interface LinkedEditingRanges { + /** + * A list of ranges that can be edited together. The ranges must have + * identical length and contain identical text content. The ranges cannot overlap. + */ + ranges: Range[] + /** + * An optional word pattern (regular expression) that describes valid contents for + * the given ranges. If no pattern is provided, the client configuration's word + * pattern will be used. + */ + wordPattern?: string + } + + /** + * Represents programming constructs like functions or constructors in the context + * of call hierarchy. + * + * @since 3.16.0 + */ + export interface CallHierarchyItem { + /** + * The name of this item. + */ + name: string + /** + * The kind of this item. + */ + kind: SymbolKind + /** + * Tags for this item. + */ + tags?: number[] + /** + * More detail for this item, e.g. the signature of a function. + */ + detail?: string + /** + * The resource identifier of this item. + */ + uri: string + /** + * The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. + */ + range: Range + /** + * The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. + * Must be contained by the [`range`](#CallHierarchyItem.range). + */ + selectionRange: Range + /** + * A data entry field that is preserved between a call hierarchy prepare and + * incoming calls or outgoing calls requests. + */ + data?: unknown + } + + /** + * Represents an incoming call, e.g. a caller of a method or constructor. + * + * @since 3.16.0 + */ + export interface CallHierarchyIncomingCall { + /** + * The item that makes the call. + */ + from: CallHierarchyItem + /** + * The ranges at which the calls appear. This is relative to the caller + * denoted by [`this.from`](#CallHierarchyIncomingCall.from). + */ + fromRanges: Range[] + } + /** + * Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc. + * + * @since 3.16.0 + */ + export interface CallHierarchyOutgoingCall { + /** + * The item that is called. + */ + to: CallHierarchyItem + /** + * The range at which this item is called. This is the range relative to the caller, e.g the item + * passed to [`provideCallHierarchyOutgoingCalls`](#CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls) + * and not [`this.to`](#CallHierarchyOutgoingCall.to). + */ + fromRanges: Range[] + } + // }} + + // nvim interfaces {{ + type VimValue = + | number + | boolean + | string + | number[] + | { [key: string]: any } + + // see `:h nvim_set_client_info()` for details. + export interface VimClientInfo { + name: string + version: { + major?: number + minor?: number + patch?: number + prerelease?: string + commit?: string + } + type: 'remote' | 'embedder' | 'host' + methods?: { + [index: string]: any + } + attributes?: { + [index: string]: any + } + } + + export interface UiAttachOptions { + rgb?: boolean + ext_popupmenu?: boolean + ext_tabline?: boolean + ext_wildmenu?: boolean + ext_cmdline?: boolean + ext_linegrid?: boolean + ext_hlstate?: boolean + } + + export interface ChanInfo { + id: number + stream: 'stdio' | 'stderr' | 'socket' | 'job' + mode: 'bytes' | 'terminal' | 'rpc' + pty?: number + buffer?: number + client?: VimClientInfo + } + + /** + * Returned by nvim_get_commands api. + */ + export interface VimCommandDescription { + name: string + bang: boolean + bar: boolean + register: boolean + definition: string + count?: number | null + script_id: number + complete?: string + nargs?: string + range?: string + complete_arg?: string + } + + export interface NvimFloatOptions { + standalone?: boolean + focusable?: boolean + relative?: 'editor' | 'cursor' | 'win' + anchor?: 'NW' | 'NE' | 'SW' | 'SE' + height: number + width: number + row: number + col: number + } + + export interface NvimProc { + ppid: number + name: string + pid: number + } + + export interface SignPlaceOption { + id?: number + group?: string + name: string + lnum: number + priority?: number + } + + export interface SignUnplaceOption { + group?: string + id?: number + } + + export interface SignPlacedOption { + /** + * Use '*' for all group, default to '' as unnamed group. + */ + group?: string + id?: number + lnum?: number + } + + export interface SignItem { + group: string + id: number + lnum: number + name: string + priority: number + } + + export interface HighlightItem { + hlGroup: string + /** + * 0 based + */ + lnum: number + /** + * 0 based + */ + colStart: number + /** + * 0 based + */ + colEnd: number + } + + export interface BufferKeymapOption { + nowait?: boolean + silent?: boolean + script?: boolean + expr?: boolean + unique?: boolean + } + + export interface BufferHighlight { + /** + * Name of the highlight group to use + */ + hlGroup?: string + /** + * Namespace to use or -1 for ungrouped highlight + */ + srcId?: number + /** + * Line to highlight (zero-indexed) + */ + line?: number + /** + * Start of (byte-indexed) column range to highlight + */ + colStart?: number + /** + * End of (byte-indexed) column range to highlight, or -1 to highlight to end of line + */ + colEnd?: number + } + + export interface BufferClearHighlight { + srcId?: number + lineStart?: number + lineEnd?: number + } + + interface BaseApi { + /** + * unique identify number + */ + id: number + + /** + * Check if same by compare id. + */ + equals(other: T): boolean + + /** + * Request to vim, name need to be nvim_ prefixed and supported by vim. + * + * @param {string} name - nvim function name + * @param {VimValue[]} args + * @returns {Promise} + */ + request(name: string, args?: VimValue[]): Promise + + /** + * Send notification to vim, name need to be nvim_ prefixed and supported + * by vim + */ + notify(name: string, args?: VimValue[]): void + + /** + * Retrieves scoped variable, returns null when value not exists. + */ + getVar(name: string): Promise + + /** + * Set scoped variable by request. + * + * @param {string} name + * @param {VimValue} value + * @returns {Promise} + */ + setVar(name: string, value: VimValue): Promise + + /** + * Set scoped variable by notification. + */ + setVar(name: string, value: VimValue, isNotify: true): void + + /** + * Delete scoped variable by notification. + */ + deleteVar(name: string): void + + /** + * Retrieves a scoped option, not exists for tabpage. + */ + getOption(name: string): Promise + + /** + * Set scoped option by request, not exists for tabpage. + */ + setOption(name: string, value: VimValue): Promise + + /** + * Set scoped variable by notification, not exists for tabpage. + */ + setOption(name: string, value: VimValue, isNotify: true): void + } + + export interface Neovim extends BaseApi { + + /** + * Echo error message to vim and log error stack. + */ + echoError(msg: string | Error): void + + /** + * Check if `nvim_` function exists. + */ + hasFunction(name: string): boolean + + /** + * Get channelid used by coc.nvim. + */ + channelId: Promise + + /** + * Create buffer instance by id. + */ + createBuffer(id: number): Buffer + + /** + * Create window instance by id. + */ + createWindow(id: number): Window + + /** + * Create tabpage instance by id. + */ + createTabpage(id: number): Tabpage + + /** + * Stop send subsequent notifications. + */ + pauseNotification(): void + + /** + * Send paused notifications by nvim_call_atomic request + * + * **Note**: avoid call async function between pauseNotification and + * resumeNotification. + */ + resumeNotification(): Promise<[any[], [string, number, string] | null]> + + /** + * Send paused notifications by nvim_call_atomic notification + */ + resumeNotification(cancel: boolean, notify: true): void + + /** + * Get list of current buffers. + */ + buffers: Promise + + /** + * Get current buffer. + */ + buffer: Promise + + /** + * Set current buffer + */ + setBuffer(buffer: Buffer): Promise + + /** + * Get list of current tabpages. + */ + tabpages: Promise + + /** + * Get current tabpage. + */ + tabpage: Promise + + /** + * Set current tabpage + */ + setTabpage(tabpage: Tabpage): Promise + + /** + * Get list of current windows. + */ + windows: Promise + + /** + * Get current window. + */ + window: Promise + + /** + * Set current window. + */ + setWindow(window: Window): Promise + + /** + * Get information of all channels, + * **Note:** works on neovim only. + */ + chans: Promise + + /** + * Get information of channel by id, + * **Note:** works on neovim only. + */ + getChanInfo(id: number): Promise + + /** + * Creates a new namespace, or gets an existing one. + * `:h nvim_create_namespace()` + */ + createNamespace(name?: string): Promise + + /** + * Gets existing, non-anonymous namespaces. + * + * @return dict that maps from names to namespace ids. + */ + namespaces: Promise<{ [name: string]: number }> + + /** + * Gets a map of global (non-buffer-local) Ex commands. + * + * @return Map of maps describing commands. + */ + getCommands(opt?: { builtin: boolean }): Promise<{ [name: string]: VimCommandDescription }> + + /** + * Get list of all runtime paths + */ + runtimePaths: Promise + + /** + * Set global working directory. + * **Note:** works on neovim only. + */ + setDirectory(dir: string): Promise + + /** + * Get current line. + */ + line: Promise + + /** + * Creates a new, empty, unnamed buffer. + * + * **Note:** works on neovim only. + */ + createNewBuffer(listed?: boolean, scratch?: boolean): Promise + + /** + * Create float window of neovim. + * + * **Note:** works on neovim only, use high level api provided by window + * module is recommended. + */ + openFloatWindow(buffer: Buffer, enter: boolean, options: NvimFloatOptions): Promise + + /** + * Set current line. + */ + setLine(line: string): Promise + + /** + * Gets a list of global (non-buffer-local) |mapping| definitions. + * `:h nvim_get_keymap` + * + * **Note:** works on neovim only. + */ + getKeymap(mode: string): Promise + + /** + * Gets the current mode. |mode()| "blocking" is true if Nvim is waiting for input. + * + * **Note:** blocking would always be false when used with vim. + */ + mode: Promise<{ mode: string; blocking: boolean }> + + /** + * Returns a map of color names and RGB values. + * + * **Note:** works on neovim only. + */ + colorMap(): Promise<{ [name: string]: number }> + + /** + * Returns the 24-bit RGB value of a |nvim_get_color_map()| color name or + * "#rrggbb" hexadecimal string. + * + * **Note:** works on neovim only. + */ + getColorByName(name: string): Promise + + /** + * Gets a highlight definition by id. |hlID()| + * + * **Note:** works on neovim only. + */ + getHighlight(nameOrId: string | number, isRgb?: boolean): Promise + + /** + * Get a highlight by name, return rgb by default. + * + * **Note:** works on neovim only. + */ + getHighlightByName(name: string, isRgb?: boolean): Promise + + /** + * Get a highlight by id, return rgb by default. + * + * **Note:** works on neovim only. + */ + getHighlightById(id: number, isRgb?: boolean): Promise + + /** + * Delete current line in buffer. + */ + deleteCurrentLine(): Promise + + /** + * 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: string): Promise + + /** + * Executes lua, it's possible neovim client does not support this + * + * **Note:** works on neovim only. + */ + executeLua(code: string, args?: VimValue[]): Promise + + /** + * Calls a VimL |Dictionary-function| with the given arguments. + */ + callDictFunction(dict: object | string, fname: string, args: VimValue | VimValue[]): Promise + + /** + * Call a vim function. + * + * @param {string} fname - function name + * @param {VimValue | VimValue[]} args + * @returns {Promise} + */ + call(fname: string, args?: VimValue | VimValue[]): Promise + + /** + * Call a vim function by notification. + */ + call(fname: string, args: VimValue | VimValue[], isNotify: true): void + + /** + * Call a vim function with timer of timeout 0. + * + * @param {string} fname - function name + * @param {VimValue | VimValue[]} args + * @returns {Promise} + */ + callTimer(fname: string, args?: VimValue | VimValue[]): Promise + + /** + * Call a vim function with timer of timeout 0 by notification. + */ + callTimer(fname: string, args: VimValue | VimValue[], isNotify: true): void + + /** + * Call async vim function that accept callback as argument + * by using notifications. + */ + callAsync(fname: string, args?: VimValue | VimValue[]): Promise + + /** + * Calls many API methods atomically. + */ + callAtomic(calls: [string, VimValue[]][]): Promise<[any[], any[] | null]> + + /** + * Executes an ex-command by request. + */ + command(arg: string): Promise + + /** + * Executes an ex-command by notification. + */ + command(arg: string, isNotify: true): void + + /** + * Runs a command and returns output. + * + * **Note:** works on neovim only. + */ + commandOutput(arg: string): Promise + + /** + * Gets a v: variable. + */ + getVvar(name: string): Promise + + /** + * `:h nvim_feedkeys` + */ + feedKeys(keys: string, mode: string, escapeCsi: boolean): Promise + + /** + * Queues raw user-input. Unlike |nvim_feedkeys()|, this uses a + * low-level input buffer and the call is non-blocking (input is + * processed asynchronously by the eventloop). + * + * On execution error: does not fail, but updates v:errmsg. + * + * **Note:** works on neovim only. + */ + input(keys: string): Promise + + /** + * Parse a VimL Expression. + */ + parseExpression(expr: string, flags: string, highlight: boolean): Promise + + /** + * Get process info, neovim only. + * + * **Note:** works on neovim only. + */ + getProc(pid: number): Promise + + /** + * Gets the immediate children of process `pid`. + * + * **Note:** works on neovim only. + */ + getProcChildren(pid: number): Promise + + /** + * Replaces terminal codes and |keycodes| (, , ...) + * in a string with the internal representation. + * + * **Note:** works on neovim only. + */ + replaceTermcodes(str: string, fromPart: boolean, doIt: boolean, special: boolean): Promise + + /** + * Gets width(display cells) of string. + */ + strWidth(str: string): Promise + + /** + * Gets a list of dictionaries representing attached UIs. + * + * **Note:** works on neovim only. + */ + uis: Promise + + /** + * Subscribe to nvim event broadcasts. + * + * **Note:** works on neovim only. + */ + subscribe(event: string): Promise + + /** + * Unsubscribe to nvim event broadcasts + * + * **Note:** works on neovim only. + */ + unsubscribe(event: string): Promise + + /** + * Activates UI events on the channel. + * + * **Note:** works on neovim only. + */ + uiAttach(width: number, height: number, options: UiAttachOptions): Promise + + /** + * `:h nvim_ui_try_resize` + * + * **Note:** works on neovim only. + */ + uiTryResize(width: number, height: number): Promise + + /** + * Deactivates UI events on the channel. + * + * **Note:** works on neovim only. + */ + uiDetach(): Promise + + /** + * Quit vim. + */ + quit(): Promise + } + + export interface Buffer extends BaseApi { + id: number + + /** Total number of lines in buffer */ + length: Promise + + /** + * Get lines of buffer. + */ + lines: Promise + + /** + * Get changedtick of buffer. + */ + changedtick: Promise + + /** + * Add buffer keymap by notification. + */ + setKeymap(mode: string, lhs: string, rhs: string, opts?: BufferKeymapOption): void + + /** + * Add sign to buffer by notification. + * + * @param {SignPlaceOption} sign + */ + placeSign(sign: SignPlaceOption): void + + /** + * Unplace signs by notification + */ + unplaceSign(opts: SignUnplaceOption): void + + /** + * Get signs by group name or id and lnum. + * + * @param {SignPlacedOption} opts + */ + getSigns(opts: SignPlacedOption): Promise + + /** + * Get highlight items by namespace (end exclusive). + * + * @param {string | number} ns Namespace key or id. + * @param {number} start 0 based line number, default to 0. + * @param {number} end 0 based line number, default to -1. + */ + getHighlights(ns: string | number, start?: number, end?: number): Promise + + /** + * Update namespaced highlights in range by notification. + * + * @param {string | number} ns Namespace key or id. + * @param {HighlightItem[]} highlights Highlight items. + * @param {number} start 0 based line number, default to 0. + * @param {number} end 0 based line number, default to -1. + */ + updateHighlights(ns: string | number, highlights: HighlightItem[], start?: number, end?: number): void + + /** + * Gets a map of buffer-local |user-commands|. + * + * **Note:** works on neovim only. + */ + getCommands(options?: {}): Promise + + /** + * Get lines of buffer, get all lines by default. + */ + getLines(opts?: { start: number, end: number, strictIndexing?: boolean }): Promise + + /** + * Set lines of buffer given indeces use request. + */ + setLines(lines: string[], opts?: { start: number, end: number, strictIndexing?: boolean }): Promise + + /** + * Set lines of buffer given indeces use notification. + */ + setLines(lines: string[], opts: { start: number, end: number, strictIndexing?: boolean }, isNotify: true): void + + /** + * 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} + */ + setVirtualText(src_id: number, line: number, chunks: [string, string][], opts?: { [index: string]: any }): Promise + + /** + * Append a string or list of lines to end of buffer + */ + append(lines: string[] | string): Promise + + /** + * Get buffer name. + */ + name: Promise + + /** + * Set buffer name. + */ + setName(name: string): Promise + + /** + * Check if buffer valid. + */ + valid: Promise + + /** + * Get mark position given mark name + * + * **Note:** works on neovim only. + */ + mark(name: string): Promise<[number, number]> + + /** + * Gets a list of buffer-local |mapping| definitions. + * + * @return Array of maparg()-like dictionaries describing mappings. + * The "buffer" key holds the associated buffer handle. + */ + getKeymap(mode: string): Promise + + /** + * Check if buffer loaded. + */ + loaded: Promise + + /** + * 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: number): Promise + + /** + * Adds a highlight to buffer, checkout |nvim_buf_add_highlight|. + * + * Note: when `srcId = 0`, request is made for new `srcId`, otherwire, use notification. + * Note: `hlGroup` as empty string is not supported. + * + * @deprecated use `highlightRanges()` instead. + */ + addHighlight(opts: BufferHighlight): Promise + + /** + * Clear highlights of specified lins. + * + * @deprecated use clearNamespace instead. + */ + clearHighlight(args?: BufferClearHighlight) + + /** + * Add highlight to ranges by notification, works on both vim & neovim. + * + * Works on neovim and `workspace.isVim && workspace.env.textprop` is true + * + * @param {string | number} srcId Unique key or namespace number. + * @param {string} hlGroup Highlight group. + * @param {Range[]} ranges List of highlight ranges + */ + highlightRanges(srcId: string | number, hlGroup: string, ranges: Range[]): void + + /** + * Clear namespace by id or name by notification, works on both vim & neovim. + * + * Works on neovim and `workspace.isVim && workspace.env.textprop` is true + * + * @param key Unique key or namespace number, use -1 for all namespaces + * @param lineStart Start of line, 0 based, default to 0. + * @param lineEnd End of line, 0 based, default to -1. + */ + clearNamespace(key: number | string, lineStart?: number, lineEnd?: number) + } + + export interface Window extends BaseApi { + /** + * The windowid that not change within a Vim session + */ + id: number + + /** + * Buffer in window. + */ + buffer: Promise + + /** + * Tabpage contains window. + */ + tabpage: Promise + + /** + * Cursor position as [line, col], 1 based. + */ + cursor: Promise<[number, number]> + + /** + * Window height. + */ + height: Promise + + /** + * Window width. + */ + width: Promise + + /** + * Set cursor position by request. + */ + setCursor(pos: [number, number]): Promise + + /** + * Set cursor position by notification. + */ + setCursor(pos: [number, number], isNotify: true): void + + /** + * Set height + */ + setHeight(height: number): Promise + + /** + * Set height by notification. + */ + setHeight(height: number, isNotify: true): void + + /** + * Set width. + */ + setWidth(width: number): Promise + + /** + * Set width by notification. + */ + setWidth(width: number, isNotify: true): void + + /** + * Get window position, not work with vim8's popup. + */ + position: Promise<[number, number]> + + /** 0-indexed, on-screen window position(row) in display cells. */ + row: Promise + + /** 0-indexed, on-screen window position(col) in display cells. */ + col: Promise + + /** + * Check if window valid. + */ + valid: Promise + + /** + * Get window number, throws for invalid window. + */ + number: Promise + + /** + * Config float window with options. + * + * **Note:** works on neovim only. + */ + setConfig(options: NvimFloatOptions): Promise + + /** + * Config float window with options by send notification. + * + * **Note:** works on neovim only. + */ + setConfig(options: NvimFloatOptions, isNotify: true): void + + /** + * Gets window configuration. + * + * **Note:** works on neovim only. + * + * @returns Map defining the window configuration, see |nvim_open_win()| + */ + getConfig(): Promise + + /** + * Close window by send request. + */ + close(force: boolean): Promise + + /** + * Close window by send notification. + */ + close(force: boolean, isNotify: true): void + + /** + * Add highlight to ranges by request (matchaddpos is used) + * + * @return {Promise} match ids. + */ + highlightRanges(hlGroup: string, ranges: Range[], priority?: number): Promise + + /** + * Add highlight to ranges by notification (matchaddpos is used) + */ + highlightRanges(hlGroup: string, ranges: Range[], priority: number, isNotify: true): void + + /** + * Clear match of highlight group by send notification. + */ + clearMatchGroup(hlGroup: string): void + + /** + * Clear match of match ids by send notification. + */ + clearMatches(ids: number[]): void + } + + export interface Tabpage extends BaseApi { + /** + * tabpage number. + */ + number: Promise + + /** + * Is current tabpage valid. + */ + valid: Promise + + /** + * Returns all windows of tabpage. + */ + windows: Promise + + /** + * Current window of tabpage. + */ + window: Promise + } + // }} + + // vscode-uri {{ + export interface UriComponents { + scheme: string + authority: string + path: string + query: string + fragment: string + } + /** + * 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. + * + * ```txt + * foo://example.com:8042/over/there?name=ferret#nose + * \_/ \______________/\_________/ \_________/ \__/ + * | | | | | + * scheme authority path query fragment + * | _____________________|__ + * / \ / \ + * urn:example:animal:ferret:nose + * ``` + */ + export class Uri implements UriComponents { + static isUri(thing: any): thing is Uri + /** + * scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'. + * The part before the first colon. + */ + readonly scheme: string + /** + * authority is the 'www.msft.com' part of 'http://www.msft.com/some/path?query#fragment'. + * The part between the first double slashes and the next slash. + */ + readonly authority: string + /** + * path is the '/some/path' part of 'http://www.msft.com/some/path?query#fragment'. + */ + readonly path: string + /** + * query is the 'query' part of 'http://www.msft.com/some/path?query#fragment'. + */ + readonly query: string + /** + * fragment is the 'fragment' part of 'http://www.msft.com/some/path?query#fragment'. + */ + readonly fragment: string + /** + * @internal + */ + protected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string, _strict?: boolean) + /** + * @internal + */ + protected constructor(components: UriComponents) + /** + * 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). + */ + readonly fsPath: string + with(change: { + scheme?: string + authority?: string | null + path?: string | null + query?: string | null + fragment?: string | null + }): Uri + /** + * 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`). + */ + static parse(value: string, _strict?: boolean): Uri + /** + * 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`) + */ + static file(path: string): Uri + static from(components: { + scheme: string + authority?: string + path?: string + query?: string + fragment?: string + }): Uri + /** + * 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` + */ + toString(skipEncoding?: boolean): string + toJSON(): UriComponents + } + // }} + + // vim interfaces {{ + /** + * See `:h complete-items` + */ + export interface VimCompleteItem { + word: string + abbr?: string + menu?: string + info?: string + kind?: string + icase?: number + equal?: number + dup?: number + empty?: number + user_data?: string + } + + export interface LocationListItem { + bufnr: number + lnum: number + col: number + text: string + type: string + } + + export interface QuickfixItem { + uri?: string + bufnr?: number + module?: string + range?: Range + text?: string + type?: string + filename?: string + lnum?: number + col?: number + valid?: boolean + nr?: number + } + // }} + + // provider interfaces {{ + /** + * A provider result represents the values a provider, like the [`HoverProvider`](#HoverProvider), + * may return. For once this is the actual result type `T`, like `Hover`, or a thenable that resolves + * to that type `T`. In addition, `null` and `undefined` can be returned - either directly or from a + * thenable. + * + * The snippets below are all valid implementations of the [`HoverProvider`](#HoverProvider): + * + * ```ts + * let a: HoverProvider = { + * provideHover(doc, pos, token): ProviderResult { + * return new Hover('Hello World') + * } + * } + * + * let b: HoverProvider = { + * provideHover(doc, pos, token): ProviderResult { + * return new Promise(resolve => { + * resolve(new Hover('Hello World')) + * }) + * } + * } + * + * let c: HoverProvider = { + * provideHover(doc, pos, token): ProviderResult { + * return; // undefined + * } + * } + * ``` + */ + export type ProviderResult = + | T + | undefined + | null + | Thenable + + /** + * Supported provider names. + */ + export type ProviderName = 'rename' | 'onTypeEdit' | 'documentLink' | 'documentColor' + | 'foldingRange' | 'format' | 'codeAction' | 'workspaceSymbols' | 'formatRange' | 'formatOnType' + | 'hover' | 'signature' | 'documentSymbol' | 'documentHighlight' | 'definition' + | 'declaration' | 'typeDefinition' | 'reference' | 'implementation' + | 'codeLens' | 'selectionRange' | 'callHierarchy' | 'semanticTokens' | 'linkedEditing' + + /** + * The completion item provider interface defines the contract between extensions and + * [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense). + * + * Providers can delay the computation of the [`detail`](#CompletionItem.detail) + * and [`documentation`](#CompletionItem.documentation) properties by implementing the + * [`resolveCompletionItem`](#CompletionItemProvider.resolveCompletionItem)-function. However, properties that + * are needed for the initial sorting and filtering, like `sortText`, `filterText`, `insertText`, and `range`, must + * not be changed during resolve. + * + * Providers are asked for completions either explicitly by a user gesture or -depending on the configuration- + * implicitly when typing words or trigger characters. + */ + export interface CompletionItemProvider { + /** + * Provide completion items for the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @param context How the completion was triggered. + * + * @return An array of completions, a [completion list](#CompletionList), or a thenable that resolves to either. + * The lack of a result can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideCompletionItems( + document: TextDocument, + position: Position, + token: CancellationToken, + context?: CompletionContext + ): ProviderResult + + /** + * Given a completion item fill in more data, like [doc-comment](#CompletionItem.documentation) + * or [details](#CompletionItem.detail). + * + * The editor will only resolve a completion item once. + * + * @param item A completion item currently active in the UI. + * @param token A cancellation token. + * @return The resolved completion item or a thenable that resolves to of such. It is OK to return the given + * `item`. When no result is returned, the given `item` will be used. + */ + resolveCompletionItem?( + item: CompletionItem, + token: CancellationToken + ): ProviderResult + } + + /** + * The hover provider interface defines the contract between extensions and + * the [hover](https://code.visualstudio.com/docs/editor/intellisense)-feature. + */ + export interface HoverProvider { + /** + * Provide a hover for the given position and document. Multiple hovers at the same + * position will be merged by the editor. A hover can have a range which defaults + * to the word range at the position when omitted. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A hover or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideHover( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult + } + + /** + * The definition provider interface defines the contract between extensions and + * the [go to definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition) + * and peek definition features. + */ + export interface DefinitionProvider { + /** + * Provide the definition of the symbol at the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A definition or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideDefinition( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult + } + + /** + * The definition provider interface defines the contract between extensions and + * the [go to definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition) + * and peek definition features. + */ + export interface DeclarationProvider { + /** + * Provide the declaration of the symbol at the given position and document. + */ + provideDeclaration( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult + } + + /** + * The signature help provider interface defines the contract between extensions and + * the [parameter hints](https://code.visualstudio.com/docs/editor/intellisense)-feature. + */ + export interface SignatureHelpProvider { + /** + * Provide help for the signature at the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return Signature help or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideSignatureHelp( + document: TextDocument, + position: Position, + token: CancellationToken, + context: SignatureHelpContext + ): ProviderResult + } + + /** + * The type definition provider defines the contract between extensions and + * the go to type definition feature. + */ + export interface TypeDefinitionProvider { + /** + * Provide the type definition of the symbol at the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A definition or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideTypeDefinition( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult + } + + /** + * Value-object that contains additional information when + * requesting references. + */ + export interface ReferenceContext { + /** + * Include the declaration of the current symbol. + */ + includeDeclaration: boolean + } + + /** + * The reference provider interface defines the contract between extensions and + * the [find references](https://code.visualstudio.com/docs/editor/editingevolved#_peek)-feature. + */ + export interface ReferenceProvider { + /** + * Provide a set of project-wide references for the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param context + * @param token A cancellation token. + * @return An array of locations or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideReferences( + document: TextDocument, + position: Position, + context: ReferenceContext, + token: CancellationToken + ): ProviderResult + } + + /** + * Folding context (for future use) + */ + export interface FoldingContext {} + + /** + * The folding range provider interface defines the contract between extensions and + * [Folding](https://code.visualstudio.com/docs/editor/codebasics#_folding) in the editor. + */ + export interface FoldingRangeProvider { + /** + * Returns a list of folding ranges or null and undefined if the provider + * does not want to participate or was cancelled. + * + * @param document The document in which the command was invoked. + * @param context Additional context information (for future use) + * @param token A cancellation token. + */ + provideFoldingRanges( + document: TextDocument, + context: FoldingContext, + token: CancellationToken + ): ProviderResult + } + + /** + * The document symbol provider interface defines the contract between extensions and + * the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol)-feature. + */ + export interface DocumentSymbolProvider { + /** + * Provide symbol information for the given document. + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of document highlights or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentSymbols( + document: TextDocument, + token: CancellationToken + ): ProviderResult + } + + /** + * The implemenetation provider interface defines the contract between extensions and + * the go to implementation feature. + */ + export interface ImplementationProvider { + /** + * Provide the implementations of the symbol at the given position and document. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A definition or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideImplementation( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult + } + + /** + * The workspace symbol provider interface defines the contract between extensions and + * the [symbol search](https://code.visualstudio.com/docs/editor/editingevolved#_open-symbol-by-name)-feature. + */ + export interface WorkspaceSymbolProvider { + /** + * Project-wide search for a symbol matching the given query string. It is up to the provider + * how to search given the query string, like substring, indexOf etc. To improve performance implementors can + * skip the [location](#SymbolInformation.location) of symbols and implement `resolveWorkspaceSymbol` to do that + * later. + * + * The `query`-parameter should be interpreted in a *relaxed way* as the editor will apply its own highlighting + * and scoring on the results. A good rule of thumb is to match case-insensitive and to simply check that the + * characters of *query* appear in their order in a candidate symbol. Don't use prefix, substring, or similar + * strict matching. + * + * @param query A non-empty query string. + * @param token A cancellation token. + * @return An array of document highlights or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideWorkspaceSymbols( + query: string, + token: CancellationToken + ): ProviderResult + + /** + * Given a symbol fill in its [location](#SymbolInformation.location). This method is called whenever a symbol + * is selected in the UI. Providers can implement this method and return incomplete symbols from + * [`provideWorkspaceSymbols`](#WorkspaceSymbolProvider.provideWorkspaceSymbols) which often helps to improve + * performance. + * + * @param symbol The symbol that is to be resolved. Guaranteed to be an instance of an object returned from an + * earlier call to `provideWorkspaceSymbols`. + * @param token A cancellation token. + * @return The resolved symbol or a thenable that resolves to that. When no result is returned, + * the given `symbol` is used. + */ + resolveWorkspaceSymbol?( + symbol: SymbolInformation, + token: CancellationToken + ): ProviderResult + } + + /** + * The rename provider interface defines the contract between extensions and + * the [rename](https://code.visualstudio.com/docs/editor/editingevolved#_rename-symbol)-feature. + */ + export interface RenameProvider { + /** + * Provide an edit that describes changes that have to be made to one + * or many resources to rename a symbol to a different name. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param newName The new name of the symbol. If the given name is not valid, the provider must return a rejected promise. + * @param token A cancellation token. + * @return A workspace edit or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideRenameEdits( + document: TextDocument, + position: Position, + newName: string, + token: CancellationToken + ): ProviderResult + + /** + * Optional function for resolving and validating a position *before* running rename. The result can + * be a range or a range and a placeholder text. The placeholder text should be the identifier of the symbol + * which is being renamed - when omitted the text in the returned range is used. + * + * @param document The document in which rename will be invoked. + * @param position The position at which rename will be invoked. + * @param token A cancellation token. + * @return The range or range and placeholder text of the identifier that is to be renamed. The lack of a result can signaled by returning `undefined` or `null`. + */ + prepareRename?( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult + } + + /** + * The document formatting provider interface defines the contract between extensions and + * the formatting-feature. + */ + export interface DocumentFormattingEditProvider { + /** + * Provide formatting edits for a whole document. + * + * @param document The document in which the command was invoked. + * @param options Options controlling formatting. + * @param token A cancellation token. + * @return A set of text edits or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentFormattingEdits( + document: TextDocument, + options: FormattingOptions, + token: CancellationToken + ): ProviderResult + } + + /** + * The document formatting provider interface defines the contract between extensions and + * the formatting-feature. + */ + export interface DocumentRangeFormattingEditProvider { + /** + * Provide formatting edits for a range in a document. + * + * The given range is a hint and providers can decide to format a smaller + * or larger range. Often this is done by adjusting the start and end + * of the range to full syntax nodes. + * + * @param document The document in which the command was invoked. + * @param range The range which should be formatted. + * @param options Options controlling formatting. + * @param token A cancellation token. + * @return A set of text edits or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentRangeFormattingEdits( + document: TextDocument, + range: Range, + options: FormattingOptions, + token: CancellationToken + ): ProviderResult + } + + /** + * The code action interface defines the contract between extensions and + * the [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature. + * + * A code action can be any command that is [known](#commands.getCommands) to the system. + */ + export interface CodeActionProvider { + /** + * Provide commands for the given document and range. + * + * @param document The document in which the command was invoked. + * @param range The selector or range for which the command was invoked. This will always be a selection if + * there is a currently active editor. + * @param context Context carrying additional information. + * @param token A cancellation token. + * @return An array of commands, quick fixes, or refactorings or a thenable of such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideCodeActions( + document: TextDocument, + range: Range, + context: CodeActionContext, + token: CancellationToken + ): ProviderResult<(Command | CodeAction)[]> + + /** + * Given a code action fill in its [`edit`](#CodeAction.edit)-property. Changes to + * all other properties, like title, are ignored. A code action that has an edit + * will not be resolved. + * + * @param codeAction A code action. + * @param token A cancellation token. + * @return The resolved code action or a thenable that resolves to such. It is OK to return the given + * `item`. When no result is returned, the given `item` will be used. + */ + resolveCodeAction?(codeAction: T, token: CancellationToken): ProviderResult + } + + /** + * Metadata about the type of code actions that a [CodeActionProvider](#CodeActionProvider) providers + */ + export interface CodeActionProviderMetadata { + /** + * [CodeActionKinds](#CodeActionKind) that this provider may return. + * + * The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the provider + * may list our every specific kind they provide, such as `CodeActionKind.Refactor.Extract.append('function`)` + */ + readonly providedCodeActionKinds?: ReadonlyArray + } + + /** + * The document highlight provider interface defines the contract between extensions and + * the word-highlight-feature. + */ + export interface DocumentHighlightProvider { + + /** + * Provide a set of document highlights, like all occurrences of a variable or + * all exit-points of a function. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return An array of document highlights or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentHighlights( + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult + } + + /** + * The document link provider defines the contract between extensions and feature of showing + * links in the editor. + */ + export interface DocumentLinkProvider { + + /** + * Provide links for the given document. Note that the editor ships with a default provider that detects + * `http(s)` and `file` links. + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of [document links](#DocumentLink) or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentLinks(document: TextDocument, token: CancellationToken): ProviderResult + + /** + * Given a link fill in its [target](#DocumentLink.target). This method is called when an incomplete + * link is selected in the UI. Providers can implement this method and return incomple links + * (without target) from the [`provideDocumentLinks`](#DocumentLinkProvider.provideDocumentLinks) method which + * often helps to improve performance. + * + * @param link The link that is to be resolved. + * @param token A cancellation token. + */ + resolveDocumentLink?(link: DocumentLink, token: CancellationToken): ProviderResult + } + + /** + * A code lens provider adds [commands](#Command) to source text. The commands will be shown + * as dedicated horizontal lines in between the source text. + */ + export interface CodeLensProvider { + + /** + * Compute a list of [lenses](#CodeLens). This call should return as fast as possible and if + * computing the commands is expensive implementors should only return code lens objects with the + * range set and implement [resolve](#CodeLensProvider.resolveCodeLens). + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of code lenses or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideCodeLenses(document: TextDocument, token: CancellationToken): ProviderResult + + /** + * This function will be called for each visible code lens, usually when scrolling and after + * calls to [compute](#CodeLensProvider.provideCodeLenses)-lenses. + * + * @param codeLens code lens that must be resolved. + * @param token A cancellation token. + * @return The given, resolved code lens or thenable that resolves to such. + */ + resolveCodeLens?(codeLens: CodeLens, token: CancellationToken): ProviderResult + } + + /** + * The document formatting provider interface defines the contract between extensions and + * the formatting-feature. + */ + export interface OnTypeFormattingEditProvider { + + /** + * Provide formatting edits after a character has been typed. + * + * The given position and character should hint to the provider + * what range the position to expand to, like find the matching `{` + * when `}` has been entered. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param ch The character that has been typed. + * @param options Options controlling formatting. + * @param token A cancellation token. + * @return A set of text edits or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined`, `null`, or an empty array. + */ + provideOnTypeFormattingEdits(document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): ProviderResult + } + + /** + * The document color provider defines the contract between extensions and feature of + * picking and modifying colors in the editor. + */ + export interface DocumentColorProvider { + + /** + * Provide colors for the given document. + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of [color information](#ColorInformation) or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult + + /** + * Provide [representations](#ColorPresentation) for a color. + * + * @param color The color to show and insert. + * @param context A context object with additional information + * @param token A cancellation token. + * @return An array of color presentations or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideColorPresentations(color: Color, context: { document: TextDocument; range: Range }, token: CancellationToken): ProviderResult + } + + export interface TextDocumentContentProvider { + + /** + * An event to signal a resource has changed. + */ + onDidChange?: Event + + /** + * Provide textual content for a given uri. + * + * The editor will use the returned string-content to create a readonly + * [document](#TextDocument). Resources allocated should be released when + * the corresponding document has been [closed](#workspace.onDidCloseTextDocument). + * + * @param uri An uri which scheme matches the scheme this provider was [registered](#workspace.registerTextDocumentContentProvider) for. + * @param token A cancellation token. + * @return A string or a thenable that resolves to such. + */ + provideTextDocumentContent(uri: Uri, token: CancellationToken): ProviderResult + } + + export interface SelectionRangeProvider { + /** + * Provide selection ranges starting at a given position. The first range must [contain](#Range.contains) + * position and subsequent ranges must contain the previous range. + */ + provideSelectionRanges(document: TextDocument, positions: Position[], token: CancellationToken): ProviderResult + } + + /** + * The call hierarchy provider interface describes the contract between extensions + * and the call hierarchy feature which allows to browse calls and caller of function, + * methods, constructor etc. + */ + export interface CallHierarchyProvider { + + /** + * Bootstraps call hierarchy by returning the item that is denoted by the given document + * and position. This item will be used as entry into the call graph. Providers should + * return `undefined` or `null` when there is no item at the given location. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @returns A call hierarchy item or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + prepareCallHierarchy(document: TextDocument, position: Position, token: CancellationToken): ProviderResult + + /** + * Provide all incoming calls for an item, e.g all callers for a method. In graph terms this describes directed + * and annotated edges inside the call graph, e.g the given item is the starting node and the result is the nodes + * that can be reached. + * + * @param item The hierarchy item for which incoming calls should be computed. + * @param token A cancellation token. + * @returns A set of incoming calls or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideCallHierarchyIncomingCalls(item: CallHierarchyItem, token: CancellationToken): ProviderResult + + /** + * Provide all outgoing calls for an item, e.g call calls to functions, methods, or constructors from the given item. In + * graph terms this describes directed and annotated edges inside the call graph, e.g the given item is the starting + * node and the result is the nodes that can be reached. + * + * @param item The hierarchy item for which outgoing calls should be computed. + * @param token A cancellation token. + * @returns A set of outgoing calls or a thenable that resolves to such. The lack of a result can be + * signaled by returning `undefined` or `null`. + */ + provideCallHierarchyOutgoingCalls(item: CallHierarchyItem, token: CancellationToken): ProviderResult + } + + /** + * The document semantic tokens provider interface defines the contract between extensions and + * semantic tokens. + */ + export interface DocumentSemanticTokensProvider { + /** + * An optional event to signal that the semantic tokens from this provider have changed. + */ + // TODO: SemantiTokens + onDidChangeSemanticTokens?: Event + + /** + * Tokens in a file are represented as an array of integers. The position of each token is expressed relative to + * the token before it, because most tokens remain stable relative to each other when edits are made in a file. + * + * --- + * In short, each token takes 5 integers to represent, so a specific token `i` in the file consists of the following array indices: + * + * - at index `5*i` - `deltaLine`: token line number, relative to the previous token + * - at index `5*i+1` - `deltaStart`: token start character, relative to the previous token (relative to 0 or the previous token's start if they are on the same line) + * - at index `5*i+2` - `length`: the length of the token. A token cannot be multiline. + * - at index `5*i+3` - `tokenType`: will be looked up in `SemanticTokensLegend.tokenTypes`. We currently ask that `tokenType` < 65536. + * - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticTokensLegend.tokenModifiers` + * + * --- + * ### How to encode tokens + * + * Here is an example for encoding a file with 3 tokens in a uint32 array: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: "property", tokenModifiers: ["private", "static"] }, + * { line: 2, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] }, + * { line: 5, startChar: 2, length: 7, tokenType: "class", tokenModifiers: [] } + * ``` + * + * 1. First of all, a legend must be devised. This legend must be provided up-front and capture all possible token types. + * For this example, we will choose the following legend which must be passed in when registering the provider: + * ``` + * tokenTypes: ['property', 'type', 'class'], + * tokenModifiers: ['private', 'static'] + * ``` + * + * 2. The first transformation step is to encode `tokenType` and `tokenModifiers` as integers using the legend. Token types are looked + * up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Multiple token modifiers can be set by using bit flags, + * so a `tokenModifier` value of `3` is first viewed as binary `0b00000011`, which means `[tokenModifiers[0], tokenModifiers[1]]` because + * bits 0 and 1 are set. Using this legend, the tokens now are: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { line: 2, startChar: 10, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { line: 5, startChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 3. The next step is to represent each token relative to the previous token in the file. In this case, the second token + * is on the same line as the first token, so the `startChar` of the second token is made relative to the `startChar` + * of the first token, so it will be `10 - 5`. The third token is on a different line than the second token, so the + * `startChar` of the third token will not be altered: + * ``` + * { deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 4. Finally, the last step is to inline each of the 5 fields for a token in a single array, which is a memory friendly representation: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * + * @see [SemanticTokensBuilder](#SemanticTokensBuilder) for a helper to encode tokens as integers. + * *NOTE*: When doing edits, it is possible that multiple edits occur until VS Code decides to invoke the semantic tokens provider. + * *NOTE*: If the provider cannot temporarily compute semantic tokens, it can indicate this by throwing an error with the message 'Busy'. + */ + provideDocumentSemanticTokens(document: TextDocument, token: CancellationToken): ProviderResult + + /** + * Instead of always returning all the tokens in a file, it is possible for a `DocumentSemanticTokensProvider` to implement + * this method (`provideDocumentSemanticTokensEdits`) and then return incremental updates to the previously provided semantic tokens. + * + * --- + * ### How tokens change when the document changes + * + * Suppose that `provideDocumentSemanticTokens` has previously returned the following semantic tokens: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * + * Also suppose that after some edits, the new semantic tokens in a file are: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * It is possible to express these new tokens in terms of an edit applied to the previous tokens: + * ``` + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] // old tokens + * [ 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] // new tokens + * + * edit: { start: 0, deleteCount: 1, data: [3] } // replace integer at offset 0 with 3 + * ``` + * + * *NOTE*: If the provider cannot compute `SemanticTokensEdits`, it can "give up" and return all the tokens in the document again. + * *NOTE*: All edits in `SemanticTokensEdits` contain indices in the old integers array, so they all refer to the previous result state. + */ + provideDocumentSemanticTokensEdits?(document: TextDocument, previousResultId: string, token: CancellationToken): ProviderResult + } + + /** + * The document range semantic tokens provider interface defines the contract between extensions and + * semantic tokens. + */ + export interface DocumentRangeSemanticTokensProvider { + /** + * @see [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens). + */ + provideDocumentRangeSemanticTokens(document: TextDocument, range: Range, token: CancellationToken): ProviderResult + } + + export interface LinkedEditingRangeProvider { + /** + * For a given position in a document, returns the range of the symbol at the position and all ranges + * that have the same content. A change to one of the ranges can be applied to all other ranges if the new content + * is valid. An optional word pattern can be returned with the result to describe valid contents. + * If no result-specific word pattern is provided, the word pattern from the language configuration is used. + * + * @param document The document in which the provider was invoked. + * @param position The position at which the provider was invoked. + * @param token A cancellation token. + * @return A list of ranges that can be edited together + */ + provideLinkedEditingRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + // }} + + // Classes {{ + + export interface FloatWinConfig { + maxHeight?: number + maxWidth?: number + preferTop?: boolean + autoHide?: boolean + offsetX?: number + title?: string + border?: number[] + cursorline?: boolean + close?: boolean + highlight?: string + borderhighlight?: string + modes?: string[] + shadow?: boolean + winblend?: number + focusable?: boolean + excludeImages?: boolean + } + + export interface Documentation { + /** + * Filetype used for highlight, markdown is supported. + */ + filetype: string + /** + * Content of document. + */ + content: string + /** + * Byte offset (0 based) that should be undelined. + */ + active?: [number, number] + } + + /** + * Float window factory for create float around current cursor, works on vim and neovim. + * Use `workspace.floatSupported` to check if float could work. + * + * Float windows are automatic reused and hidden on specific events including: + * - BufEnter + * - InsertEnter + * - InsertLeave + * - MenuPopupChanged + * - CursorMoved + * - CursorMovedI + */ + export class FloatFactory implements Disposable { + get bufnr(): number | undefined + get buffer(): Buffer | null + get window(): Window | null + activated(): Promise + + constructor(nvim: Neovim) + + /** + * Show documentations in float window/popup around cursor. + * Window and buffer are reused when possible. + * Window is closed automatically on change buffer, InsertEnter, CursorMoved and CursorMovedI. + * + * @param docs List of documentations. + * @param config Configuration for floating window/popup. + */ + show(docs: Documentation[], config?: FloatWinConfig): Promise + + /** + * Close float window. + */ + close(): void + dispose(): void + } + + /** + * Build buffer with lines and highlights + */ + export class Highlighter { + constructor(srcId?: number) + /** + * Add a line with highlight group. + */ + addLine(line: string, hlGroup?: string): void + /** + * Add lines without highlights. + */ + addLines(lines: string[]): void + /** + * Add text with highlight. + */ + addText(text: string, hlGroup?: string): void + /** + * Get line count + */ + get length(): number + /** + * Render lines to buffer at specified range. + * Since notifications is used, use `nvim.pauseNotification` & `nvim.resumeNotification` + * when you need to wait for the request finish. + * + * @param {Buffer} buffer + * @param {number} start + * @param {number} end + * @returns {void} + */ + render(buffer: Buffer, start?: number, end?: number): void + } + + export interface ListConfiguration { + get(key: string, defaultValue?: T): T + previousKey(): string + nextKey(): string + dispose(): void + } + + export interface ListActionOptions { + persist?: boolean + reload?: boolean + parallel?: boolean + } + + export interface CommandTaskOption { + /** + * Command to run. + */ + cmd: string + /** + * Arguments of command. + */ + args: string[] + cwd: string + /** + * Runs for each line, return undefined for invalid item. + */ + onLine: (line: string) => ListItem | undefined + } + + export interface CommandTask extends ListTask { + } + + export abstract class BasicList implements IList { + /** + * Unique name, must be provided by implementation class. + */ + name: string + /** + * Default action name invoked by by default, must be provided by implementation class. + */ + defaultAction: string + /** + * Registered actions. + */ + readonly actions: ListAction[] + /** + * Arguments configuration of list. + */ + options: ListArgument[] + protected nvim: Neovim + protected disposables: Disposable[] + protected config: ListConfiguration + constructor(nvim: Neovim) + /** + * Should align columns when true. + */ + get alignColumns(): boolean + get hlGroup(): string + get previewHeight(): string + get splitRight(): boolean + /** + * Parse argument string array for argument object from `this.options`. + * Could be used inside `this.loadItems()` + */ + protected parseArguments(args: string[]): { [key: string]: string | boolean } + /** + * Get configurations of current list + */ + protected getConfig(): WorkspaceConfiguration + /** + * Add an action + */ + protected addAction(name: string, fn: (item: ListItem, context: ListContext) => ProviderResult, options?: ListActionOptions): void + /** + * Add action that support multiple selection. + */ + protected addMultipleAction(name: string, fn: (item: ListItem[], context: ListContext) => ProviderResult, options?: ListActionOptions): void + /** + * Create task from command task option. + */ + protected createCommandTask(opt: CommandTaskOption): ListTask + /** + * Add location related actions, should be called in constructor. + */ + protected addLocationActions(): void + protected convertLocation(location: Location | LocationWithLine | string): Promise + /** + * Jump to location + * + * @method + */ + protected jumpTo(location: Location | LocationWithLine | string, command?: string): Promise + /** + * Preview location. + * + * @method + */ + protected previewLocation(location: Location, context: ListContext): Promise + /** + * Preview lines. + * + * @method + */ + protected preview(options: PreviewOptions, context: ListContext): Promise + /** + * Use for syntax highlights, invoked after buffer loaded. + */ + doHighlight(): void + /** + * Invoked for listItems or listTask, could throw error when failed to load. + */ + abstract loadItems(context: ListContext, token?: CancellationToken): Promise + } + + export class Mutex { + /** + * Returns true when task is running. + */ + get busy(): boolean + /** + * Resolved release function that must be called after task finish. + */ + acquire(): Promise<() => void> + /** + * Captrue the async task function that ensures to be executed one by one. + */ + use(f: () => Promise): Promise + } + // }} + + // functions {{ + + export interface AnsiItem { + foreground?: string + background?: string + bold?: boolean + italic?: boolean + underline?: boolean + text: string + } + + export interface ParsedUrlQueryInput { + [key: string]: unknown + } + + export interface FetchOptions { + /** + * Default to 'GET' + */ + method?: string + /** + * Default no timeout + */ + timeout?: number + /** + * Always return buffer instead of parsed response. + */ + buffer?: boolean + /** + * Data send to server. + */ + data?: string | { [key: string]: any } | Buffer + /** + * Plain object added as query of url + */ + query?: ParsedUrlQueryInput + headers?: any + /** + * User for http basic auth, should use with password + */ + user?: string + /** + * Password for http basic auth, should use with user + */ + password?: string + } + + export interface DownloadOptions extends Omit { + /** + * Folder that contains downloaded file or extracted files by untar or unzip + */ + dest: string + /** + * Remove the specified number of leading path elements for *untar* only, default to `1`. + */ + strip?: number + /** + * If true, use untar for `.tar.gz` filename + */ + extract?: boolean | 'untar' | 'unzip' + onProgress?: (percent: string) => void + } + + export type ResponseResult = string | Buffer | { + [name: string]: any + } + + /** + * Parse ansi result from string contains ansi characters. + */ + export function ansiparse(str: string): AnsiItem[] + + /** + * Send request to server for response, supports: + * + * - Send json data and parse json response. + * - Throw error for failed response statusCode. + * - Timeout support (no timeout by default). + * - Send buffer (as data) and receive data (as response). + * - Proxy support from user configuration & environment. + * - Redirect support, limited to 3. + * - Support of gzip & deflate response content. + * + * @return Parsed object if response content type is application/json, text if content type starts with `text/` + */ + export function fetch(url: string, options?: FetchOptions, token?: CancellationToken): Promise + + /** + * Download file from url, with optional untar/unzip support. + * + * Note: you may need to set `strip` to 0 when using untar as extract method. + * + * @param {string} url + * @param {DownloadOptions} options contains dest folder and optional onProgress callback + */ + export function download(url: string, options: DownloadOptions, token?: CancellationToken): Promise + + interface ExecOptions { + cwd?: string + env?: NodeJS.ProcessEnv + shell?: string + timeout?: number + maxBuffer?: number + killSignal?: string + uid?: number + gid?: number + windowsHide?: boolean + } + + /** + * Dispose all disposables. + */ + export function disposeAll(disposables: Disposable[]): void + + /** + * Concurrent run async functions with limit support. + */ + export function concurrent(arr: T[], fn: (val: T) => Promise, limit?: number): Promise + + /** + * Create promise resolved after ms miliseconds. + */ + export function wait(ms: number): Promise + + /** + * Run command with `child_process.exec` + */ + export function runCommand(cmd: string, opts?: ExecOptions, timeout?: number): Promise + + /** + * Check if process with pid is running + */ + export function isRunning(pid: number): boolean + + /** + * Check if command is executable. + */ + export function executable(command: string): boolean + + /** + * Watch single file for change, the filepath needs to be exists file. + * + * @param filepath Full path of file. + * @param onChange Handler on file change detected. + */ + export function watchFile(filepath: string, onChange: () => void): Disposable + // }} + + // commands module {{ + export interface CommandItem { + id: string + internal?: boolean + execute(...args: any[]): any + } + /** + * Namespace for dealing with commands of coc.nvim + */ + export namespace commands { + /** + * Registered commands. + */ + export const commandList: CommandItem[] + + /** + * Execute specified command. + * + * @deprecated use `executeCommand()` instead. + */ + export function execute(command: { name: string, arguments?: any[] }): void + + /** + * Check if command is registered. + * + * @param id Unique id of command. + */ + export function has(id: string): boolean + + /** + * 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. + */ + export function registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any, internal?: boolean): Disposable + + /** + * 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. + */ + export function executeCommand(command: string, ...rest: any[]): Promise + + /** + * Open uri with external tool, use `open` on mac, use `xdg-open` on linux. + */ + export function executeCommand(command: 'vscode.open', uri: string | Uri): Promise + + /** + * Reload current buffer by `:edit` command. + */ + export function executeCommand(command: 'workbench.action.reloadWindow'): Promise + + /** + * Insert snippet at range of current buffer. + * + * @param edit Contains snippet text and range to replace. + */ + export function executeCommand(command: 'editor.action.insertSnippet', edit: TextEdit): Promise + + /** + * Invoke specified code action. + */ + export function executeCommand(command: 'editor.action.doCodeAction', action: CodeAction): Promise + + /** + * Trigger coc.nvim's completion at current cursor position. + */ + export function executeCommand(command: 'editor.action.triggerSuggest'): Promise + + /** + * Trigger signature help at current cursor position. + */ + export function executeCommand(command: 'editor.action.triggerParameterHints'): Promise + + /** + * Add ranges to cursors session for multiple cursors. + */ + export function executeCommand(command: 'editor.action.addRanges', ranges: Range[]): Promise + + /** + * Restart coc.nvim service by `:CocRestart` command. + */ + export function executeCommand(command: 'editor.action.restart'): Promise + + /** + * Show locations by location list or vim's quickfix list. + */ + export function executeCommand(command: 'editor.action.showReferences', filepath: string | undefined, position: Position | undefined, locations: Location[]): Promise + + /** + * Invoke rename action at position of specified uri. + */ + export function executeCommand(command: 'editor.action.rename', uri: string, position: Position): Promise + + /** + * Run format action for current buffer. + */ + export function executeCommand(command: 'editor.action.format'): Promise + } + // }} + + // events module {{ + type MoveEvents = 'CursorMoved' | 'CursorMovedI' + type EventResult = void | Promise + type BufEvents = 'BufHidden' | 'BufEnter' | 'BufWritePost' + | 'CursorHold' | 'InsertLeave' | 'TermOpen' | 'TermClose' | 'InsertEnter' + | 'BufCreate' | 'BufUnload' | 'BufWritePre' | 'CursorHoldI' | 'Enter' + type EmptyEvents = 'FocusGained' | 'FocusLost' | 'InsertSnippet' + type InsertChangeEvents = 'TextChangedP' | 'TextChangedI' + type TaskEvents = 'TaskExit' | 'TaskStderr' | 'TaskStdout' + type WindowEvents = 'WinLeave' | 'WinEnter' + type AllEvents = BufEvents | EmptyEvents | MoveEvents | TaskEvents | WindowEvents | InsertChangeEvents | 'CompleteDone' | 'TextChanged' | 'MenuPopupChanged' | 'InsertCharPre' | 'FileType' | 'BufWinEnter' | 'BufWinLeave' | 'VimResized' | 'DirChanged' | 'OptionSet' | 'Command' | 'BufReadCmd' | 'GlobalChange' | 'InputChar' | 'WinLeave' | 'MenuInput' | 'PromptInsert' | 'FloatBtnClick' | 'InsertSnippet' + type OptionValue = string | number | boolean + + export interface CursorPosition { + bufnr: number + lnum: number + col: number + insert: boolean + } + + export interface InsertChange { + lnum: number + col: number + pre: string + changedtick: number + } + + export interface PopupChangeEvent { + completed_item: VimCompleteItem + height: number + width: number + row: number + col: number + size: number + scrollbar: boolean + } + + /** + * Used for listen to events send from vim. + */ + export namespace events { + /** + * Latest cursor position. + */ + export const cursor: CursorPosition + /** + * Latest pum position, is true when pum positioned above current line. + */ + export const pumAlignTop: boolean + /** + * Insert mode detected by latest events. + */ + export const insertMode: boolean + export function on(event: EmptyEvents | AllEvents[], handler: () => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + /** + * Attach handler to buffer events. + */ + export function on(event: BufEvents, handler: (bufnr: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + /** + * Attach handler to mouse move events. + */ + export function on(event: MoveEvents, handler: (bufnr: number, cursor: [number, number]) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + /** + * Attach handler to TextChangedI or TextChangedP. + */ + export function on(event: InsertChangeEvents, handler: (bufnr: number, info: InsertChange) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + /** + * Attach handler to window event. + */ + export function on(event: WindowEvents, handler: (winid: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + /** + * Attach handler to float button click. + */ + export function on(event: 'FloatBtnClick', handler: (bufnr: number, index: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + /** + * Fired on vim's TextChanged event. + */ + export function on(event: 'TextChanged', handler: (bufnr: number, changedtick: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'TaskExit', handler: (id: string, code: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'TaskStderr' | 'TaskStdout', handler: (id: string, lines: string[]) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + /** + * Fired on vim's BufReadCmd event. + */ + export function on(event: 'BufReadCmd', handler: (scheme: string, fullpath: string) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + /** + * Fired on vim's VimResized event. + */ + export function on(event: 'VimResized', handler: (columns: number, lines: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'MenuPopupChanged', handler: (event: PopupChangeEvent, cursorline: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'CompleteDone', handler: (item: VimCompleteItem) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'InsertCharPre', handler: (character: string) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'FileType', handler: (filetype: string, bufnr: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'BufWinEnter' | 'BufWinLeave', handler: (bufnr: number, winid: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'DirChanged', handler: (cwd: string) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'OptionSet' | 'GlobalChange', handler: (option: string, oldVal: OptionValue, newVal: OptionValue) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'InputChar', handler: (session: string, character: string, mode: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'PromptInsert', handler: (value: string, bufnr: number) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + export function on(event: 'Command', handler: (name: string) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + + /** + * Fired after user insert character and made change to the buffer. + * Fired before TextChangedI & TextChanged event. + */ + export function on(event: 'TextInsert', handler: (bufnr: number, info: InsertChange, character: string) => EventResult, thisArg?: any, disposables?: Disposable[]): Disposable + } + // }} + + // languages module {{ + export interface DocumentSymbolProviderMetadata { + /** + * A human-readable string that is shown when multiple outlines trees show for one document. + */ + label?: string + } + + export namespace languages { + /** + * Create a diagnostics collection. + * + * @param name The [name](#DiagnosticCollection.name) of the collection. + * @return A new diagnostic collection. + */ + export function createDiagnosticCollection(name?: string): DiagnosticCollection + + /** + * Register a formatting provider that works on type. The provider is active when the user enables the setting `coc.preferences.formatOnType`. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#languages.match) and the best-matching provider is used. Failure + * of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider An on type formatting edit provider. + * @param triggerCharacters Trigger character that should trigger format on type. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerOnTypeFormattingEditProvider(selector: DocumentSelector, provider: OnTypeFormattingEditProvider, triggerCharacters: string[]): Disposable + + /** + * Register a completion provider. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#languages.match) and groups of equal score are sequentially asked for + * completion items. The process stops when one or many providers of a group return a + * result. A failing provider (rejected promise or exception) will not fail the whole + * operation. + * + * A completion item provider can be associated with a set of `triggerCharacters`. When trigger + * characters are being typed, completions are requested but only from providers that registered + * the typed character. Because of that trigger characters should be different than [word characters](#LanguageConfiguration.wordPattern), + * a common trigger character is `.` to trigger member completions. + * + * @param name Name of completion source. + * @param shortcut Shortcut used in completion menu. + * @param selector Document selector of created completion source. + * @param provider A completion provider. + * @param triggerCharacters Trigger completion when the user types one of the characters. + * @param priority Higher priority would shown first. + * @param allCommitCharacters Commit characters of completion source. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerCompletionItemProvider(name: string, shortcut: string, selector: DocumentSelector | null, provider: CompletionItemProvider, triggerCharacters?: string[], priority?: number, allCommitCharacters?: string[]): Disposable + + /** + * Register a code action provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A code action provider. + * @param clientId Optional id of language client. + * @param codeActionKinds Optional supported code action kinds. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerCodeActionProvider(selector: DocumentSelector, provider: CodeActionProvider, clientId: string | undefined, codeActionKinds?: string[]): Disposable + + /** + * Register a hover provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A hover provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerHoverProvider(selector: DocumentSelector, provider: HoverProvider): Disposable + + /** + * Register a selection range provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A selection range provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerSelectionRangeProvider(selector: DocumentSelector, provider: SelectionRangeProvider): Disposable + + /** + * Register a signature help provider. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#languages.match) and called sequentially until a provider returns a + * valid result. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A signature help provider. + * @param triggerCharacters Trigger signature help when the user types one of the characters, like `,` or `(`. + * @param metadata Information about the provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerSignatureHelpProvider(selector: DocumentSelector, provider: SignatureHelpProvider, triggerCharacters?: string[]): Disposable + + /** + * Register a document symbol provider. + * + * Multiple providers can be registered for a language. In that case providers only first provider + * are asked for result. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document symbol provider. + * @param metadata Optional meta data. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDocumentSymbolProvider(selector: DocumentSelector, provider: DocumentSymbolProvider, metadata?: DocumentSymbolProviderMetadata): Disposable + + /** + * Register a folding range provider. + * + * Multiple providers can be registered for a language. In that case providers only first provider + * are asked for result. + * + * A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A folding range provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerFoldingRangeProvider(selector: DocumentSelector, provider: FoldingRangeProvider): Disposable + + /** + * Register a document highlight provider. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#languages.match) and groups sequentially asked for document highlights. + * The process stops when a provider returns a `non-falsy` or `non-failure` result. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document highlight provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDocumentHighlightProvider(selector: DocumentSelector, provider: any): Disposable + + /** + * Register a code lens provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A code lens provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerCodeLensProvider(selector: DocumentSelector, provider: CodeLensProvider): Disposable + + /** + * Register a document link provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document link provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDocumentLinkProvider(selector: DocumentSelector, provider: DocumentLinkProvider): Disposable + + /** + * Register a color provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A color provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDocumentColorProvider(selector: DocumentSelector, provider: DocumentColorProvider): Disposable + + /** + * Register a definition provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A definition provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDefinitionProvider(selector: DocumentSelector, provider: DefinitionProvider): Disposable + + /** + * Register a declaration provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A declaration provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDeclarationProvider(selector: DocumentSelector, provider: DeclarationProvider): Disposable + + + /** + * Register a type definition provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A type definition provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerTypeDefinitionProvider(selector: DocumentSelector, provider: TypeDefinitionProvider): Disposable + + /** + * Register an implementation provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider An implementation provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerImplementationProvider(selector: DocumentSelector, provider: ImplementationProvider): Disposable + + /** + * Register a reference provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A reference provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerReferencesProvider(selector: DocumentSelector, provider: ReferenceProvider): Disposable + + /** + * Register a rename provider. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#workspace.match) and asked in sequence. The first provider producing a result + * defines the result of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A rename provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerRenameProvider(selector: DocumentSelector, provider: RenameProvider): Disposable + + /** + * Register a workspace symbol provider. + * + * Multiple providers can be registered. In that case providers are asked in parallel and + * the results are merged. A failing provider (rejected promise or exception) will not cause + * a failure of the whole operation. + * + * @param provider A workspace symbol provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerWorkspaceSymbolProvider(provider: WorkspaceSymbolProvider): Disposable + + /** + * Register a formatting provider for a document. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their priority. Failure of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document formatting edit provider. + * @param priority default to 0. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDocumentFormatProvider(selector: DocumentSelector, provider: DocumentFormattingEditProvider, priority?: number): Disposable + + /** + * Register a formatting provider for a document range. + * + * *Note:* A document range provider is also a [document formatter](#DocumentFormattingEditProvider) + * which means there is no need to [register](#languages.registerDocumentFormattingEditProvider) a document + * formatter when also registering a range provider. + * + * Multiple providers can be registered for a language. In that case provider with highest priority is used. + * Failure of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document range formatting edit provider. + * @param priority default to 0. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDocumentRangeFormatProvider(selector: DocumentSelector, provider: DocumentRangeFormattingEditProvider, priority?: number): Disposable + + /** + * Register a call hierarchy provider. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A call hierarchy provider. + * @return A {@link Disposable} that unregisters this provider when being disposed. + */ + export function registerCallHierarchyProvider(selector: DocumentSelector, provider: CallHierarchyProvider): Disposable + + /** + * Register a semantic tokens provider for a whole document. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their {@link languages.match score} and the best-matching provider is used. Failure + * of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document semantic tokens provider. + * @return A {@link Disposable} that unregisters this provider when being disposed. + */ + export function registerDocumentSemanticTokensProvider(selector: DocumentSelector, provider: DocumentSemanticTokensProvider, legend: SemanticTokensLegend): Disposable + + /** + * Register a semantic tokens provider for a document range. + * + * *Note:* If a document has both a `DocumentSemanticTokensProvider` and a `DocumentRangeSemanticTokensProvider`, + * the range provider will be invoked only initially, for the time in which the full document provider takes + * to resolve the first request. Once the full document provider resolves the first request, the semantic tokens + * provided via the range provider will be discarded and from that point forward, only the document provider + * will be used. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their {@link languages.match score} and the best-matching provider is used. Failure + * of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document range semantic tokens provider. + * @return A {@link Disposable} that unregisters this provider when being disposed. + */ + export function registerDocumentRangeSemanticTokensProvider(selector: DocumentSelector, provider: DocumentRangeSemanticTokensProvider, legend: SemanticTokensLegend): Disposable + + /** + * Register a linked editing range provider. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their {@link languages.match score} and the best-matching provider that has a result is used. Failure + * of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A linked editing range provider. + * @return A {@link Disposable} that unregisters this provider when being disposed. + */ + export function registerLinkedEditingRangeProvider(selector: DocumentSelector, provider: LinkedEditingRangeProvider): Disposable + } + // }} + + // services module {{ + export enum ServiceStat { + Initial, + Starting, + StartFailed, + Running, + Stopping, + Stopped, + } + + export interface IServiceProvider { + // unique service id + id: string + name: string + client?: LanguageClient + selector: DocumentSelector + // current state + state: ServiceStat + start(): Promise + dispose(): void + stop(): Promise | void + restart(): Promise | void + onServiceReady: Event + } + + export namespace services { + /** + * Register languageClient as service provider. + */ + export function registLanguageClient(client: LanguageClient): Disposable + /** + * Register service, nothing happens when `service.id` already exists. + */ + export function regist(service: IServiceProvider): Disposable + /** + * Get service by id. + */ + export function getService(id: string): IServiceProvider + /** + * Stop service by id. + */ + export function stop(id: string): Promise + /** + * Stop running service or start stopped service. + */ + export function toggle(id: string): Promise + } + // }} + + // sources module {{ + /** + * Source options to create source that could respect configuration from `coc.source.{name}` + */ + export type SourceConfig = Omit + + export interface SourceStat { + name: string + priority: number + triggerCharacters: string[] + type: 'native' | 'remote' | 'service' + shortcut: string + filepath: string + disabled: boolean + filetypes: string[] + } + + export enum SourceType { + Native, + Remote, + Service, + } + + export interface CompleteResult { + items: VimCompleteItem[] + isIncomplete?: boolean + startcol?: number + source?: string + priority?: number + } + + // option on complete & should_complete + export interface CompleteOption { + /** + * Current buffer number. + */ + readonly bufnr: number + /** + * Current line. + */ + readonly line: string + /** + * Column to start completion, determined by iskeyword options of buffer. + */ + readonly col: number + /** + * Input text. + */ + readonly input: string + readonly filetype: string + readonly filepath: string + /** + * Word under cursor. + */ + readonly word: string + /** + * Trigger character, could be empty string. + */ + readonly triggerCharacter: string + /** + * Col of cursor, 1 based. + */ + readonly colnr: number + readonly linenr: number + readonly synname: string + /** + * Black list words specified by user. + */ + readonly blacklist: string[] + /** + * Buffer changetick + */ + readonly changedtick: number + /** + * Is trigger for in complete completion. + */ + readonly triggerForInComplete?: boolean + } + + export interface ISource { + /** + * Identifier name + */ + name: string + /** + * @deprecated use documentSelector instead. + */ + filetypes?: string[] + /** + * Filters of document. + */ + documentSelector?: DocumentSelector + enable?: boolean + shortcut?: string + priority?: number + sourceType?: SourceType + /** + * Should only be used when completion is triggered, requirs `triggerPatterns` or `triggerCharacters` defined. + */ + triggerOnly?: boolean + triggerCharacters?: string[] + // regex to detect trigger completion, ignored when triggerCharacters exists. + triggerPatterns?: RegExp[] + disableSyntaxes?: string[] + filepath?: string + // should the first character always match + firstMatch?: boolean + refresh?(): Promise + /** + * For disable/enable + */ + toggle?(): void + + /** + * Triggered on BufEnter, used for cache normally + */ + onEnter?(bufnr: number): void + + /** + * Check if this source should doComplete + * + * @public + * @param {CompleteOption} opt + * @returns {Promise } + */ + shouldComplete?(opt: CompleteOption): Promise + + /** + * Run completion + * + * @public + * @param {CompleteOption} opt + * @param {CancellationToken} token + * @returns {Promise} + */ + doComplete(opt: CompleteOption, token: CancellationToken): ProviderResult + + /** + * Action for complete item on complete item selected + * + * @public + * @param {VimCompleteItem} item + * @param {CancellationToken} token + * @returns {Promise} + */ + onCompleteResolve?(item: VimCompleteItem, token: CancellationToken): ProviderResult + + /** + * Action for complete item on complete done + * + * @public + * @param {VimCompleteItem} item + * @returns {Promise} + */ + onCompleteDone?(item: VimCompleteItem, opt: CompleteOption): ProviderResult + + shouldCommit?(item: VimCompleteItem, character: string): boolean + } + + export namespace sources { + /** + * Names of registered sources. + */ + export const names: ReadonlyArray + export const sources: ReadonlyArray + /** + * Check if source exists by name. + */ + export function has(name: string): boolean + /** + * Get source by name. + */ + export function getSource(name: string): ISource | null + + /** + * Add source to sources list. + * + * Note: Use `sources.createSource()` for regist new source is recommended for + * user configuration support. + */ + export function addSource(source: ISource): Disposable + + /** + * Create source by source config, configurations starts with `coc.source.{name}` + * are automatically supported. + * + * `name` and `doComplete()` must be provided in config. + */ + export function createSource(config: SourceConfig): Disposable + + /** + * Get list of all source stats. + */ + export function sourceStats(): SourceStat[] + + /** + * Call refresh for _name_ source or all sources. + */ + export function refresh(name?: string): Promise + + /** + * Toggle state of _name_ source. + */ + export function toggleSource(name: string): void + + /** + * Remove source by name. + */ + export function removeSource(name: string): void + } + // }} + + // TreeView related {{ + export interface TreeItemLabel { + label: string + highlights?: [number, number][] + } + + export interface TreeItemIcon { + text: string + hlGroup: string + } + + /** + * Collapsible state of the tree item + */ + export enum TreeItemCollapsibleState { + /** + * Determines an item can be neither collapsed nor expanded. Implies it has no children. + */ + None = 0, + /** + * Determines an item is collapsed + */ + Collapsed = 1, + /** + * Determines an item is expanded + */ + Expanded = 2 + } + + export class TreeItem { + /** + * A human-readable string describing this item. When `falsy`, it is derived from {@link TreeItem.resourceUri resourceUri}. + */ + label?: string | TreeItemLabel + + /** + * Description rendered less prominently after label. + */ + description?: string + + /** + * The icon path or {@link ThemeIcon} for the tree item. + * When `falsy`, {@link ThemeIcon.Folder Folder Theme Icon} is assigned, if item is collapsible otherwise {@link ThemeIcon.File File Theme Icon}. + * When a file or folder {@link ThemeIcon} is specified, icon is derived from the current file icon theme for the specified theme icon using {@link TreeItem.resourceUri resourceUri} (if provided). + */ + icon?: TreeItemIcon + + /** + * Optional id for the tree item that has to be unique across tree. The id is used to preserve the selection and expansion state of the tree item. + * + * If not provided, an id is generated using the tree item's resourceUri when exists. **Note** that when labels change, ids will change and that selection and expansion state cannot be kept stable anymore. + */ + id?: string + + /** + * The {@link Uri} of the resource representing this item. + * + * Will be used to derive the {@link TreeItem.label label}, when it is not provided. + * Will be used to derive the icon from current file icon theme, when {@link TreeItem.iconPath iconPath} has {@link ThemeIcon} value. + */ + resourceUri?: Uri + + /** + * The tooltip text when you hover over this item. + */ + tooltip?: string | MarkupContent + + /** + * The {@link Command} that should be executed when the tree item is selected. + * + * Please use `vscode.open` or `vscode.diff` as command IDs when the tree item is opening + * something in the editor. Using these commands ensures that the resulting editor will + * appear consistent with how other built-in trees open editors. + */ + command?: Command + + /** + * {@link TreeItemCollapsibleState} of the tree item. + */ + collapsibleState?: TreeItemCollapsibleState + + /** + * @param label A human-readable string describing this item + * @param collapsibleState {@link TreeItemCollapsibleState} of the tree item. Default is {@link TreeItemCollapsibleState.None} + */ + constructor(label: string | TreeItemLabel, collapsibleState?: TreeItemCollapsibleState) + + /** + * @param resourceUri The {@link Uri} of the resource representing this item. + * @param collapsibleState {@link TreeItemCollapsibleState} of the tree item. Default is {@link TreeItemCollapsibleState.None} + */ + constructor(resourceUri: Uri, collapsibleState?: TreeItemCollapsibleState) + } + + /** + * Action resolved by {@link TreeDataProvider} + */ + export interface TreeItemAction { + /** + * Label text in menu. + */ + title: string + handler: (item: T) => ProviderResult + } + + /** + * Options for creating a {@link TreeView} + */ + export interface TreeViewOptions { + /** + * Fixed width for window, default to true + */ + winfixwidth?: boolean + /** + * Enable filter feature, default to false + */ + enableFilter?: boolean + /** + * Disable indent of leaves without children, default to false + */ + disableLeafIndent?: boolean + /** + * A data provider that provides tree data. + */ + treeDataProvider: TreeDataProvider + /** + * Whether the tree supports multi-select. When the tree supports multi-select and a command is executed from the tree, + * the first argument to the command is the tree item that the command was executed on and the second argument is an + * array containing all selected tree items. + */ + canSelectMany?: boolean + } + + /** + * The event that is fired when an element in the {@link TreeView} is expanded or collapsed + */ + export interface TreeViewExpansionEvent { + + /** + * Element that is expanded or collapsed. + */ + readonly element: T + + } + + /** + * The event that is fired when there is a change in {@link TreeView.selection tree view's selection} + */ + export interface TreeViewSelectionChangeEvent { + + /** + * Selected elements. + */ + readonly selection: T[] + + } + + /** + * The event that is fired when there is a change in {@link TreeView.visible tree view's visibility} + */ + export interface TreeViewVisibilityChangeEvent { + + /** + * `true` if the {@link TreeView tree view} is visible otherwise `false`. + */ + readonly visible: boolean + + } + + /** + * Represents a Tree view + */ + export interface TreeView extends Disposable { + + /** + * Event that is fired when an element is expanded + */ + readonly onDidExpandElement: Event> + + /** + * Event that is fired when an element is collapsed + */ + readonly onDidCollapseElement: Event> + + /** + * Currently selected elements. + */ + readonly selection: T[] + + /** + * Event that is fired when the {@link TreeView.selection selection} has changed + */ + readonly onDidChangeSelection: Event> + + /** + * Event that is fired when {@link TreeView.visible visibility} has changed + */ + readonly onDidChangeVisibility: Event + + /** + * `true` if the {@link TreeView tree view} is visible otherwise `false`. + * + * **NOTE:** is `true` when TreeView visible on other tab. + */ + readonly visible: boolean + + /** + * Window id used by TreeView. + */ + readonly windowId: number | undefined + + /** + * An optional human-readable message that will be rendered in the view. + * Setting the message to null, undefined, or empty string will remove the message from the view. + */ + message?: string + + /** + * The tree view title is initially taken from viewId of TreeView + * Changes to the title property will be properly reflected in the UI in the title of the view. + */ + title?: string + + /** + * An optional human-readable description which is rendered less prominently in the title of the view. + * Setting the title description to null, undefined, or empty string will remove the description from the view. + */ + description?: string + + /** + * Reveals the given element in the tree view. + * If the tree view is not visible then the tree view is shown and element is revealed. + * + * By default revealed element is selected. + * In order to not to select, set the option `select` to `false`. + * In order to focus, set the option `focus` to `true`. + * In order to expand the revealed element, set the option `expand` to `true`. To expand recursively set `expand` to the number of levels to expand. + * **NOTE:** You can expand only to 3 levels maximum. + * + * **NOTE:** The {@link TreeDataProvider} that the `TreeView` {@link window.createTreeView is registered with} with must implement {@link TreeDataProvider.getParent getParent} method to access this API. + */ + reveal(element: T, options?: { select?: boolean, focus?: boolean, expand?: boolean | number }): Thenable + + /** + * Create tree view in new window. + * + * **NOTE:** TreeView with same viewId in current tab would be disposed. + * + * @param splitCommand The command to open TreeView window, default to 'belowright 30vs' + */ + show(splitCommand?: string): Promise + } + + /** + * A data provider that provides tree data + */ + export interface TreeDataProvider { + /** + * An optional event to signal that an element or root has changed. + * This will trigger the view to update the changed element/root and its children recursively (if shown). + * To signal that root has changed, do not pass any argument or pass `undefined` or `null`. + */ + onDidChangeTreeData?: Event + + /** + * Get {@link TreeItem} representation of the `element` + * + * @param element The element for which {@link TreeItem} representation is asked for. + * @return {@link TreeItem} representation of the element + */ + getTreeItem(element: T): TreeItem | Thenable + + /** + * Get the children of `element` or root if no element is passed. + * + * @param element The element from which the provider gets children. Can be `undefined`. + * @return Children of `element` or root if no element is passed. + */ + getChildren(element?: T): ProviderResult + + /** + * Optional method to return the parent of `element`. + * Return `null` or `undefined` if `element` is a child of root. + * + * **NOTE:** This method should be implemented in order to access {@link TreeView.reveal reveal} API. + * + * @param element The element for which the parent has to be returned. + * @return Parent of `element`. + */ + getParent?(element: T): ProviderResult + + /** + * Called on hover to resolve the {@link TreeItem.tooltip TreeItem} property if it is undefined. + * Called on tree item click/open to resolve the {@link TreeItem.command TreeItem} property if it is undefined. + * Only properties that were undefined can be resolved in `resolveTreeItem`. + * Functionality may be expanded later to include being called to resolve other missing + * properties on selection and/or on open. + * + * Will only ever be called once per TreeItem. + * + * onDidChangeTreeData should not be triggered from within resolveTreeItem. + * + * *Note* that this function is called when tree items are already showing in the UI. + * Because of that, no property that changes the presentation (label, description, etc.) + * can be changed. + * + * @param item Undefined properties of `item` should be set then `item` should be returned. + * @param element The object associated with the TreeItem. + * @param token A cancellation token. + * @return The resolved tree item or a thenable that resolves to such. It is OK to return the given + * `item`. When no result is returned, the given `item` will be used. + */ + resolveTreeItem?(item: TreeItem, element: T, token: CancellationToken): ProviderResult + + /** + * Called with current element to resolve actions. + * Called when user press 'actions' key. + * + * @param item Resolved item. + * @param element The object under cursor. + */ + resolveActions?(item: TreeItem, element: T): ProviderResult[]> + } + // }} + + // workspace module {{ + /** + * An event describing the change in Configuration + */ + export interface ConfigurationChangeEvent { + + /** + * Returns `true` if the given section for the given resource (if provided) is affected. + * + * @param section Configuration name, supports _dotted_ names. + * @param resource A resource URI. + * @return `true` if the given section for the given resource (if provided) is affected. + */ + affectsConfiguration(section: string, resource?: string): boolean + } + + export interface WillSaveEvent extends TextDocumentWillSaveEvent { + /** + * Allows to pause the event loop and to apply [pre-save-edits](#TextEdit). + * Edits of subsequent calls to this function will be applied in order. The + * edits will be *ignored* if concurrent modifications of the document happened. + * + * *Note:* This function can only be called during event dispatch and not + * in an asynchronous manner: + * + * ```ts + * workspace.onWillSaveTextDocument(event => { + * // async, will *throw* an error + * setTimeout(() => event.waitUntil(promise)); + * + * // sync, OK + * event.waitUntil(promise); + * }) + * ``` + * + * @param thenable A thenable that resolves to [pre-save-edits](#TextEdit). + */ + waitUntil(thenable: Thenable): void + } + + export interface KeymapOption { + /** + * Use request instead of notify, default true + */ + sync: boolean + /** + * Cancel completion before invoke callback, default true + */ + cancel: boolean + /** + * Use for keymap, default false + */ + silent: boolean + /** + * Enable repeat support for repeat.vim, default false + */ + repeat: boolean + } + + export interface DidChangeTextDocumentParams { + /** + * The document that did change. The version number points + * to the version after all provided content changes have + * been applied. + */ + textDocument: { + version: number + uri: string + } + /** + * The actual content changes. The content changes describe single state changes + * to the document. So if there are two content changes c1 (at array index 0) and + * c2 (at array index 1) for a document in state S then c1 moves the document from + * S to S' and c2 from S' to S''. So c1 is computed on the state S and c2 is computed + * on the state S'. + */ + contentChanges: TextDocumentContentChange[] + /** + * Buffer number of document. + */ + bufnr: number + /** + * Original content before change + */ + original: string + } + + export interface EditerState { + document: TextDocument + position: Position + } + + export type MapMode = 'n' | 'i' | 'v' | 'x' | 's' | 'o' + + export interface Autocmd { + /** + * Vim event or event set. + */ + event: string | string[] + /** + * Callback functions that called with evaled arguments. + */ + callback: Function + /** + * Match pattern, default to `*`. + */ + pattern?: string + /** + * Vim expression that eval to arguments of callback, default to `[]` + */ + arglist?: string[] + /** + * Use request when `true`, use notification by default. + */ + request?: boolean + /** + * `this` of callback. + */ + thisArg?: any + } + + export interface Env { + /** + * |completeopt| option of (neo)vim. + */ + readonly completeOpt: string + /** + * |runtimepath| option of (neo)vim. + */ + readonly runtimepath: string + /** + * |guicursor| option of (neo)vim + */ + readonly guicursor: string + /** + * Could use float window on neovim, always false on vim. + */ + readonly floating: boolean + /** + * |sign_place()| and |sign_unplace()| can be used when true. + */ + readonly sign: boolean + /** + * Root directory of extensions. + */ + readonly extensionRoot: string + /** + * Process id of (neo)vim. + */ + readonly pid: number + /** + * Total columns of screen. + */ + readonly columns: number + /** + * Total lines of screen. + */ + readonly lines: number + /** + * Is true when |CompleteChanged| event is supported. + */ + readonly pumevent: boolean + /** + * |cmdheight| option of (neo)vim. + */ + readonly cmdheight: number + /** + * Value of |g:coc_filetype_map| + */ + readonly filetypeMap: { [index: string]: string } + /** + * Is true when not using neovim. + */ + readonly isVim: boolean + /** + * Is cygvim when true. + */ + readonly isCygwin: boolean + /** + * Is macvim when true. + */ + readonly isMacvim: boolean + /** + * Is true when iTerm.app is used on mac. + */ + readonly isiTerm: boolean + /** + * version of (neo)vim, on vim it's like: 8020750, on neoivm it's like: 0.5.0 + */ + readonly version: string + /** + * |v:progpath| value, could be empty. + */ + readonly progpath: string + /** + * Is true when dialog feature is supported, which need vim >= 8.2.750 or neovim >= 0.4.0 + */ + readonly dialog: boolean + /** + * Is true when vim's textprop is supported. + */ + readonly textprop: boolean + } + + export interface TerminalOptions { + /** + * A human-readable string which will be used to represent the terminal in the UI. + */ + name?: string + + /** + * A path to a custom shell executable to be used in the terminal. + */ + shellPath?: string + + /** + * Args for the custom shell executable, this does not work on Windows (see #8429) + */ + shellArgs?: string[] + + /** + * A path or URI for the current working directory to be used for the terminal. + */ + cwd?: string + + /** + * Object with environment variables that will be added to the VS Code process. + */ + env?: { [key: string]: string | null } + + /** + * Whether the terminal process environment should be exactly as provided in + * `TerminalOptions.env`. When this is false (default), the environment will be based on the + * window's environment and also apply configured platform settings like + * `terminal.integrated.windows.env` on top. When this is true, the complete environment + * must be provided as nothing will be inherited from the process or any configuration. + */ + strictEnv?: boolean + } + + /** + * An individual terminal instance within the integrated terminal. + */ + export interface Terminal { + + /** + * The bufnr of terminal buffer. + */ + readonly bufnr: number + + /** + * The name of the terminal. + */ + readonly name: string + + /** + * The process ID of the shell process. + */ + readonly processId: Promise + + /** + * Send text to the terminal. The text is written to the stdin of the underlying pty process + * (shell) of the terminal. + * + * @param text The text to send. + * @param addNewLine Whether to add a new line to the text being sent, this is normally + * required to run a command in the terminal. The character(s) added are \n or \r\n + * depending on the platform. This defaults to `true`. + */ + sendText(text: string, addNewLine?: boolean): void + + /** + * Show the terminal panel and reveal this terminal in the UI, return false when failed. + * + * @param preserveFocus When `true` the terminal will not take focus. + */ + show(preserveFocus?: boolean): Promise + + /** + * Hide the terminal panel if this terminal is currently showing. + */ + hide(): void + + /** + * Dispose and free associated resources. + */ + dispose(): void + } + + export interface Document { + readonly buffer: Buffer + /** + * Document is attached to vim. + */ + readonly attached: boolean + /** + * Is command line document. + */ + readonly isCommandLine: boolean + /** + * `buftype` option of buffer. + */ + readonly buftype: string + /** + * Text document that synchronized. + */ + readonly textDocument: TextDocument + /** + * Fired when document change. + */ + readonly onDocumentChange: Event + /** + * Fired on document detach. + */ + readonly onDocumentDetach: Event + /** + * Get current buffer changedtick. + */ + readonly changedtick: number + /** + * Scheme of document. + */ + readonly schema: string + /** + * Line count of current buffer. + */ + readonly lineCount: number + /** + * Window ID when buffer create, could be -1 when no window associated. + */ + readonly winid: number + /** + * Returns if current document is opended with previewwindow + */ + readonly previewwindow: boolean + /** + * Check if document changed after last synchronize + */ + readonly dirty: boolean + /** + * Buffer number + */ + readonly bufnr: number + /** + * Content of textDocument. + */ + readonly content: string + /** + * Converted filetype. + */ + readonly filetype: string + readonly uri: string + readonly version: number + /** + * Apply textEdits to current buffer lines, fire content change event. + */ + applyEdits(edits: TextEdit[]): Promise + + /** + * Change individual lines. + * + * @param {[number, string][]} lines + * @returns {void} + */ + changeLines(lines: [number, string][]): Promise + + /** + * Get offset from lnum & col + */ + getOffset(lnum: number, col: number): number + + /** + * Check string is word. + */ + isWord(word: string): boolean + + /** + * Word range at position. + * + * @param {Position} position + * @param {string} extraChars Extra characters that should be keyword. + * @param {boolean} current Use current lines instead of textDocument, default to true. + * @returns {Range | null} + */ + getWordRangeAtPosition(position: Position, extraChars?: string, current?: boolean): Range | null + + /** + * Get ranges of word in textDocument. + */ + getSymbolRanges(word: string): Range[] + + /** + * Get line for buffer + * + * @param {number} line 0 based line index. + * @param {boolean} current Use textDocument lines when false, default to true. + * @returns {string} + */ + getline(line: number, current?: boolean): string + + /** + * Get range of current lines, zero indexed, end exclude. + */ + getLines(start?: number, end?: number): string[] + + /** + * Get variable value by key, defined by `b:coc_{key}` + */ + getVar(key: string, defaultValue?: T): T + + /** + * Get position from lnum & col + */ + getPosition(lnum: number, col: number): Position + + /** + * Adjust col with new valid character before position. + */ + fixStartcol(position: Position, valids: string[]): number + + /** + * Get current content text. + */ + getDocumentContent(): string + } + + /** + * Store & retrive most recent used items. + */ + export interface Mru { + /** + * Load iems from mru file + */ + + load(): Promise + /** + * Add item to mru file. + */ + add(item: string): Promise + + /** + * Remove item from mru file. + */ + + remove(item: string): Promise + + /** + * Remove the data file. + */ + clean(): Promise + } + + /** + * Option to create task that runs in (neo)vim. + */ + export interface TaskOptions { + /** + * The command to run, without arguments + */ + cmd: string + /** + * Arguments of command. + */ + args?: string[] + /** + * Current working directory of the task, Default to current vim's cwd. + */ + cwd?: string + /** + * Additional environment key-value pairs. + */ + env?: { [key: string]: string } + /** + * Use pty when true. + */ + pty?: boolean + /** + * Detach child process when true. + */ + detach?: boolean + } + + /** + * Controls long running task started by (neo)vim. + * Useful to keep the task running after CocRestart. + */ + export interface Task extends Disposable { + /** + * Fired on task exit with exit code. + */ + onExit: Event + /** + * Fired with lines on stdout received. + */ + onStdout: Event + /** + * Fired with lines on stderr received. + */ + onStderr: Event + /** + * Start task, task will be restarted when already running. + * + * @param {TaskOptions} opts + * @returns {Promise} + */ + start(opts: TaskOptions): Promise + /** + * Stop task by SIGTERM or SIGKILL + */ + stop(): Promise + /** + * Check if the task is running. + */ + running: Promise + } + + /** + * A simple json database. + */ + export interface JsonDB { + filepath: string + /** + * Get data by key. + * + * @param {string} key unique key allows dot notation. + * @returns {any} + */ + fetch(key: string): any + /** + * Check if key exists + * + * @param {string} key unique key allows dot notation. + */ + exists(key: string): boolean + /** + * Delete data by key + * + * @param {string} key unique key allows dot notation. + */ + delete(key: string): void + /** + * Save data with key + */ + push(key: string, data: number | null | boolean | string | { [index: string]: any }): void + /** + * Empty db file. + */ + clear(): void + /** + * Remove db file. + */ + destroy(): void + } + + export interface RenameEvent { + oldUri: Uri + newUri: Uri + } + + export interface FileSystemWatcher { + readonly ignoreCreateEvents: boolean + readonly ignoreChangeEvents: boolean + readonly ignoreDeleteEvents: boolean + readonly onDidCreate: Event + readonly onDidChange: Event + readonly onDidDelete: Event + readonly onDidRename: Event + dispose(): void + } + + export interface ConfigurationInspect { + key: string + defaultValue?: T + globalValue?: T + workspaceValue?: T + } + + export interface WorkspaceConfiguration { + /** + * Return a value from this configuration. + * + * @param section Configuration name, supports _dotted_ names. + * @return The value `section` denotes or `undefined`. + */ + get(section: string): T | undefined + + /** + * Return a value from this configuration. + * + * @param section Configuration name, supports _dotted_ names. + * @param defaultValue A value should be returned when no value could be found, is `undefined`. + * @return The value `section` denotes or the default. + */ + get(section: string, defaultValue: T): T + + /** + * Check if this configuration has a certain value. + * + * @param section Configuration name, supports _dotted_ names. + * @return `true` if the section doesn't resolve to `undefined`. + */ + has(section: string): boolean + + /** + * Retrieve all information about a configuration setting. A configuration value + * often consists of a *default* value, a global or installation-wide value, + * a workspace-specific value + * + * *Note:* The configuration name must denote a leaf in the configuration tree + * (`editor.fontSize` vs `editor`) otherwise no result is returned. + * + * @param section Configuration name, supports _dotted_ names. + * @return Information about a configuration setting or `undefined`. + */ + inspect(section: string): ConfigurationInspect | undefined + /** + * Update a configuration value. The updated configuration values are persisted. + * + * + * @param section Configuration name, supports _dotted_ names. + * @param value The new value. + * @param isUser if true, always update user configuration + */ + update(section: string, value: any, isUser?: boolean): void + + /** + * Readable dictionary that backs this configuration. + */ + readonly [key: string]: any + } + + export interface BufferSyncItem { + /** + * Called on buffer unload. + */ + dispose: () => void + /** + * Called on buffer change. + */ + onChange?(e: DidChangeTextDocumentParams): void + } + + export interface BufferSync { + /** + * Current items. + */ + readonly items: Iterable + /** + * Get created item by uri + */ + getItem(uri: string): T | undefined + /** + * Get created item by bufnr + */ + getItem(bufnr: number): T | undefined + dispose: () => void + } + + export namespace workspace { + export const nvim: Neovim + /** + * Current buffer number, could be wrong since vim could not send autocmd as expected. + * + * @deprecated will be removed in the feature. + */ + export const bufnr: number + /** + * Current document. + */ + export const document: Promise + /** + * Environments or current (neo)vim. + */ + export const env: Env + /** + * Float window or popup can work. + */ + export const floatSupported: boolean + /** + * Current working directory of vim. + */ + export const cwd: string + /** + * Current workspace root. + */ + export const root: string + /** + * @deprecated aliased to root. + */ + export const rootPath: string + /** + * Not neovim when true. + */ + export const isVim: boolean + /** + * Is neovim when true. + */ + export const isNvim: boolean + /** + * Is true when current mode is insert, could be wrong when user cancel insert by + * + * @deprecated + */ + export const insertMode: boolean + /** + * All filetypes of loaded documents. + */ + export const filetypes: ReadonlySet + /** + * Root directory of coc.nvim + */ + export const pluginRoot: string + /** + * Current `&completeopt` of vim, may not correct. + */ + export const completeOpt: string + /** + * Exists channel names. + */ + export const channelNames: ReadonlyArray + /** + * Current document array. + */ + export const documents: ReadonlyArray + /** + * Current document array. + */ + export const textDocuments: ReadonlyArray + /** + * Current workspace folders. + */ + export const workspaceFolders: ReadonlyArray + /** + * Directory paths of workspaceFolders. + */ + export const folderPaths: ReadonlyArray + /** + * Current workspace folder, could be null when vim started from user's home. + */ + export const workspaceFolder: WorkspaceFolder | null + /** + * Event fired after terminal created, only fired with Terminal that created + * by `workspace.createTerminal` + */ + export const onDidOpenTerminal: Event + /** + * Event fired on terminal close, only fired with Terminal that created by + * `workspace.createTerminal` + */ + export const onDidCloseTerminal: Event + /** + * Event fired on workspace folder change. + */ + export const onDidChangeWorkspaceFolders: Event + /** + * Event fired after document create. + */ + export const onDidOpenTextDocument: Event + /** + * Event fired after document unload. + */ + export const onDidCloseTextDocument: Event + /** + * Event fired on document change. + */ + export const onDidChangeTextDocument: Event + /** + * Event fired before document save. + */ + export const onWillSaveTextDocument: Event + /** + * Event fired after document save. + */ + export const onDidSaveTextDocument: Event + + /** + * Event fired on configuration change. Configuration change could by many + * reasons, including: + * + * - Changes detected from `coc-settings.json`. + * - Change to document that using another configuration file. + * - Configuration change by call update API of WorkspaceConfiguration. + */ + export const onDidChangeConfiguration: Event + + /** + * Fired when vim's runtimepath change detected. + */ + export const onDidRuntimePathChange: Event> + + /** + * Create new namespace id by name. + */ + export function createNameSpace(name: string): number + + /** + * Register autocmd on vim. + * + * Note: avoid request autocmd when possible since vim could be blocked + * forever when request triggered during request. + */ + export function registerAutocmd(autocmd: Autocmd): Disposable + + /** + * Watch for vim's global option change. + */ + export function watchOption(key: string, callback: (oldValue: any, newValue: any) => Thenable | void, disposables?: Disposable[]): void + + /** + * Watch for vim's global variable change, works on neovim only. + */ + export function watchGlobal(key: string, callback?: (oldValue: any, newValue: any) => Thenable | void, disposables?: Disposable[]): void + + /** + * Check if selector match document. + */ + export function match(selector: DocumentSelector, document: TextDocument): number + + /** + * Findup from filename or filenames from current filepath or root. + * + * @return fullpath of file or null when not found. + */ + export function findUp(filename: string | string[]): Promise + + /** + * Resolve root folder of uri with match patterns. + * Cwd is returned when uri is not file scheme. + * Parent folder of uri is returned when failed to resolve. + * + * @deprecated avoid use it when possible. + */ + export function resolveRootFolder(uri: Uri, patterns: string[]): Promise + + /** + * Get possible watchman binary path. + */ + export function getWatchmanPath(): string | null + + /** + * Get configuration by section and optional resource uri. + */ + export function getConfiguration(section?: string, resource?: string): WorkspaceConfiguration + + /** + * Get created document by uri or bufnr. + */ + export function getDocument(uri: number | string): Document + + /** + * Apply WorkspaceEdit. + */ + export function applyEdit(edit: WorkspaceEdit): Promise + + /** + * Convert location to quickfix item. + */ + export function getQuickfixItem(loc: Location | LocationLink, text?: string, type?: string, module?: string): Promise + + /** + * Get selected range for current document + */ + export function getSelectedRange(visualmode: string, document: Document): Promise + + /** + * Visual select range of current document + */ + export function selectRange(range: Range): Promise + + /** + * Populate locations to UI. + */ + export function showLocations(locations: Location[]): Promise + + /** + * Get content of line by uri and line. + */ + export function getLine(uri: string, line: number): Promise + + /** + * Get WorkspaceFolder of uri + */ + export function getWorkspaceFolder(uri: string): WorkspaceFolder | null + + /** + * Get content from buffer of file by uri. + */ + export function readFile(uri: string): Promise + + /** + * Get current document and position. + */ + export function getCurrentState(): Promise + + /** + * Get format options of uri or current buffer. + */ + export function getFormatOptions(uri?: string): Promise + + /** + * Jump to location. + */ + export function jumpTo(uri: string, position?: Position | null, openCommand?: string): Promise + + /** + * Create a file in vim and disk + */ + export function createFile(filepath: string, opts?: CreateFileOptions): Promise + + /** + * Load uri as document, buffer would be invisible if not loaded. + */ + export function loadFile(uri: string): Promise + + /** + * Load the files that not loaded + */ + export function loadFiles(uris: string[]): Promise + + /** + * Rename file in vim and disk + */ + export function renameFile(oldPath: string, newPath: string, opts?: RenameFileOptions): Promise + + /** + * Delete file from vim and disk. + */ + export function deleteFile(filepath: string, opts?: DeleteFileOptions): Promise + + /** + * Open resource by uri + */ + export function openResource(uri: string): Promise + + /** + * Resolve full path of module from yarn or npm global directory. + */ + export function resolveModule(name: string): Promise + + /** + * Run nodejs command + */ + export function runCommand(cmd: string, cwd?: string, timeout?: number): Promise + + /** + * Expand filepath with `~` and/or environment placeholders + */ + export function expand(filepath: string): string + + /** + * Call a function by use notifications, useful for functions like |input| that could block vim. + */ + export function callAsync(method: string, args: any[]): Promise + + /** + * registerTextDocumentContentProvider + */ + export function registerTextDocumentContentProvider(scheme: string, provider: TextDocumentContentProvider): Disposable + + /** + * Register unique keymap uses `(coc-{key})` as lhs + * Throw error when {key} already exists. + * + * @param {MapMode[]} modes - array of 'n' | 'i' | 'v' | 'x' | 's' | 'o' + * @param {string} key - unique name + * @param {Function} fn - callback function + * @param {Partial} opts + * @returns {Disposable} + */ + export function registerKeymap(modes: MapMode[], key: string, fn: () => ProviderResult, opts?: Partial): Disposable + + /** + * Register expr key-mapping. + */ + export function registerExprKeymap(mode: 'i' | 'n' | 'v' | 's' | 'x', key: string, fn: () => ProviderResult, buffer?: boolean): Disposable + + /** + * Register local key-mapping. + */ + export function registerLocalKeymap(mode: 'n' | 'v' | 's' | 'x', key: string, fn: () => ProviderResult, notify?: boolean): Disposable + + /** + * Register for buffer sync objects, created item should be disposable + * and provide optional `onChange` which called when document change. + * + * The document is always attached and not command line buffer. + * + * @param create Called for each attached document and on document create. + * @returns Disposable + */ + export function registerBufferSync(create: (doc: Document) => T | undefined): BufferSync + + /** + * Create a FileSystemWatcher instance, when watchman not exists, the + * returned FileSystemWatcher can stil be used, but not work at all. + */ + export function createFileSystemWatcher(globPattern: string, ignoreCreate?: boolean, ignoreChange?: boolean, ignoreDelete?: boolean): FileSystemWatcher + /** + * Create persistence Mru instance. + */ + export function createMru(name: string): Mru + + /** + * Create Task instance that runs in (neo)vim, no shell. + * + * @param id Unique id string, like `TSC` + */ + export function createTask(id: string): Task + + /** + * Create terminal in (neo)vim. + */ + export function createTerminal(opts: TerminalOptions): Promise + + /** + * Create DB instance at extension root. + */ + export function createDatabase(name: string): JsonDB + } + // }} + + // window module {{ + /** + * Option for create status item. + */ + export interface StatusItemOption { + progress?: boolean + } + + /** + * Status item that included in `g:coc_status` + */ + export interface StatusBarItem { + /** + * The priority of this item. Higher value means the item should + * be shown more to the left. + */ + readonly priority: number + + isProgress: boolean + + /** + * The text to show for the entry. You can embed icons in the text by leveraging the syntax: + * + * `My text $(icon-name) contains icons like $(icon-name) this one.` + * + * Where the icon-name is taken from the [octicon](https://octicons.github.com) icon set, e.g. + * `light-bulb`, `thumbsup`, `zap` etc. + */ + text: string + + /** + * Shows the entry in the status bar. + */ + show(): void + + /** + * Hide the entry in the status bar. + */ + hide(): void + + /** + * Dispose and free associated resources. Call + * [hide](#StatusBarItem.hide). + */ + dispose(): void + } + + /** + * Value-object describing where and how progress should show. + */ + export interface ProgressOptions { + + /** + * A human-readable string which will be used to describe the + * operation. + */ + title?: string + + /** + * Controls if a cancel button should show to allow the user to + * cancel the long running operation. + */ + cancellable?: boolean + } + + /** + * Defines a generalized way of reporting progress updates. + */ + export interface Progress { + + /** + * Report a progress update. + * + * @param value A progress item, like a message and/or an + * report on how much work finished + */ + report(value: T): void + } + + /** + * Represents an action that is shown with an information, warning, or + * error message. + * + * @see [showInformationMessage](#window.showInformationMessage) + * @see [showWarningMessage](#window.showWarningMessage) + * @see [showErrorMessage](#window.showErrorMessage) + */ + export interface MessageItem { + + /** + * A short title like 'Retry', 'Open Log' etc. + */ + title: string + + /** + * A hint for modal dialogs that the item should be triggered + * when the user cancels the dialog (e.g. by pressing the ESC + * key). + * + * Note: this option is ignored for non-modal messages. + * Note: not used by coc.nvim for now. + */ + isCloseAffordance?: boolean + } + + export interface DialogButton { + /** + * Use by callback, should >= 0 + */ + index: number + text: string + /** + * Not shown when true + */ + disabled?: boolean + } + + export interface DialogConfig { + /** + * Content shown in window. + */ + content: string + /** + * Optional title text. + */ + title?: string + /** + * show close button, default to true when not specified. + */ + close?: boolean + /** + * highlight group for dialog window, default to `"dialog.floatHighlight"` or 'CocFlating' + */ + highlight?: string + /** + * highlight groups for border, default to `"dialog.borderhighlight"` or 'CocFlating' + */ + borderhighlight?: string + /** + * Buttons as bottom of dialog. + */ + buttons?: DialogButton[] + /** + * index is -1 for window close without button click + */ + callback?: (index: number) => void + } + + export interface NotificationConfig extends DialogConfig { + /** + * Timeout in miliseconds to dismiss notification, default no timeout. + */ + timeout?: number + } + + /** + * Represents an item that can be selected from + * a list of items. + */ + export interface QuickPickItem { + /** + * A human-readable string which is rendered prominent + */ + label: string + /** + * A human-readable string which is rendered less prominent in the same line + */ + description?: string + /** + * Optional flag indicating if this item is picked initially. + */ + picked?: boolean + } + + export interface ScreenPosition { + row: number + col: number + } + + export type MsgTypes = 'error' | 'warning' | 'more' + + export interface OpenTerminalOption { + /** + * Cwd of terminal, default to result of |getcwd()| + */ + cwd?: string + /** + * Close terminal on job finish, default to true. + */ + autoclose?: boolean + /** + * Keep foucus current window, default to false, + */ + keepfocus?: boolean + } + + /** + * An output channel is a container for readonly textual information. + * + * To get an instance of an `OutputChannel` use + * [createOutputChannel](#window.createOutputChannel). + */ + export interface OutputChannel { + + /** + * The human-readable name of this output channel. + */ + readonly name: string + + readonly content: string + /** + * Append the given value to the channel. + * + * @param value A string, falsy values will not be printed. + */ + append(value: string): void + + /** + * Append the given value and a line feed character + * to the channel. + * + * @param value A string, falsy values will be printed. + */ + appendLine(value: string): void + + /** + * Removes output from the channel. Latest `keep` lines will be remained. + */ + clear(keep?: number): void + + /** + * Reveal this channel in the UI. + * + * @param preserveFocus When `true` the channel will not take focus. + */ + show(preserveFocus?: boolean): void + + /** + * Hide this channel from the UI. + */ + hide(): void + + /** + * Dispose and free associated resources. + */ + dispose(): void + } + + export interface TerminalResult { + bufnr: number + success: boolean + content?: string + } + + export interface Dialog { + /** + * Buffer number of dialog. + */ + bufnr: number + /** + * Window id of dialog. + */ + winid: Promise + dispose: () => void + } + + export namespace window { + /** + * Reveal message with message type. + * + * @param msg Message text to show. + * @param messageType Type of message, could be `error` `warning` and `more`, default to `more` + */ + export function showMessage(msg: string, messageType?: MsgTypes): void + + /** + * Run command in vim terminal for result + * + * @param cmd Command to run. + * @param cwd Cwd of terminal, default to result of |getcwd()|. + */ + export function runTerminalCommand(cmd: string, cwd?: string, keepfocus?: boolean): Promise + + /** + * Open terminal window. + * + * @param cmd Command to run. + * @param opts Terminal option. + * @returns buffer number of terminal. + */ + export function openTerminal(cmd: string, opts?: OpenTerminalOption): Promise + + /** + * Show quickpick for single item, use `window.menuPick` for menu at current current position. + * + * @param items Label list. + * @param placeholder Prompt text, default to 'choose by number'. + * @returns Index of selected item, or -1 when canceled. + */ + export function showQuickpick(items: string[], placeholder?: string): Promise + + /** + * Show menu picker at current cursor position, |inputlist()| is used as fallback. + * Use `workspace.env.dialog` to check if the picker window/popup could work. + * + * @param items Array of texts. + * @param title Optional title of float/popup window. + * @param token A token that can be used to signal cancellation. + * @returns Selected index (0 based), -1 when canceled. + */ + export function showMenuPicker(items: string[], title?: string, token?: CancellationToken): Promise + + /** + * Open local config file + */ + export function openLocalConfig(): Promise + + /** + * Prompt user for confirm, a float/popup window would be used when possible, + * use vim's |confirm()| function as callback. + * + * @param title The prompt text. + * @returns Result of confirm. + */ + export function showPrompt(title: string): Promise + + /** + * Show dialog window at the center of screen. + * Note that the dialog would always be closed after button click. + * Use `workspace.env.dialog` to check if dialog could work. + * + * @param config Dialog configuration. + * @returns Dialog or null when dialog can't work. + */ + export function showDialog(config: DialogConfig): Promise + + /** + * Request input from user + * + * @param title Title text of prompt window. + * @param defaultValue Default value of input, empty text by default. + */ + export function requestInput(title: string, defaultValue?: string): Promise + + /** + * Create statusbar item that would be included in `g:coc_status`. + * + * @param priority Higher priority item would be shown right. + * @param option + * @return A new status bar item. + */ + export function createStatusBarItem(priority?: number, option?: StatusItemOption): StatusBarItem + + /** + * Create a new output channel + * + * @param name Unique name of output channel. + * @returns A new output channel. + */ + export function createOutputChannel(name: string): OutputChannel + + /** + * Create a {@link TreeView} instance, call `show()` method to render. + * + * @param viewId Id of the view, used as title of TreeView when title not exists. + * @param options Options for creating the {@link TreeView} + * @returns a {@link TreeView}. + */ + export function createTreeView(viewId: string, options: TreeViewOptions): TreeView + + /** + * Reveal buffer of output channel. + * + * @param name Name of output channel. + * @param preserveFocus Preserve window focus when true. + */ + export function showOutputChannel(name: string, preserveFocus: boolean): void + + /** + * Echo lines at the bottom of vim. + * + * @param lines Line list. + * @param truncate Truncate the lines to avoid 'press enter to continue' when true + */ + export function echoLines(lines: string[], truncate?: boolean): Promise + + /** + * Get current cursor position (line, character both 0 based). + * + * @returns Cursor position. + */ + export function getCursorPosition(): Promise + + /** + * Move cursor to position (line, character both 0 based). + * + * @param position LSP position. + */ + export function moveTo(position: Position): Promise + + /** + * Get current cursor character offset in document, + * length of line break would always be 1. + * + * @returns Character offset. + */ + export function getOffset(): Promise + + /** + * Get screen position of current cursor(relative to editor), + * both `row` and `col` are 0 based. + * + * @returns Cursor screen position. + */ + export function getCursorScreenPosition(): Promise + + /** + * Show multiple picker at center of screen. + * Use `workspace.env.dialog` to check if dialog could work. + * + * @param items A set of items that will be rendered as actions in the message. + * @param title Title of picker dialog. + * @param token A token that can be used to signal cancellation. + * @return A promise that resolves to the selected items or `undefined`. + */ + export function showPickerDialog(items: string[], title: string, token?: CancellationToken): Promise + + /** + * Show multiple picker at center of screen. + * Use `workspace.env.dialog` to check if dialog could work. + * + * @param items A set of items that will be rendered as actions in the message. + * @param title Title of picker dialog. + * @param token A token that can be used to signal cancellation. + * @return A promise that resolves to the selected items or `undefined`. + */ + export function showPickerDialog(items: T[], title: string, token?: CancellationToken): Promise + + /** + * Show an information message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + export function showInformationMessage(message: string, ...items: string[]): Promise + /** + * Show an information message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + export function showInformationMessage(message: string, ...items: T[]): Promise + + /** + * Show an warning message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + export function showWarningMessage(message: string, ...items: string[]): Promise + /** + * Show an warning message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + export function showWarningMessage(message: string, ...items: T[]): Promise + + /** + * Show an error message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + export function showErrorMessage(message: string, ...items: string[]): Promise + /** + * Show an error message to users. Optionally provide an array of items which will be presented as + * clickable buttons. + * + * @param message The message to show. + * @param items A set of items that will be rendered as actions in the message. + * @return Promise that resolves to the selected item or `undefined` when being dismissed. + */ + export function showErrorMessage(message: string, ...items: T[]): Promise + + /** + * Show notification window at right of screen. + */ + export function showNotification(config: NotificationConfig): Promise + + /** + * Show progress in the editor. Progress is shown while running the given callback + * and while the promise it returned isn't resolved nor rejected. + * + * @param task A callback returning a promise. Progress state can be reported with + * the provided [progress](#Progress)-object. + * + * To report discrete progress, use `increment` to indicate how much work has been completed. Each call with + * a `increment` value will be summed up and reflected as overall progress until 100% is reached (a value of + * e.g. `10` accounts for `10%` of work done). + * + * To monitor if the operation has been cancelled by the user, use the provided [`CancellationToken`](#CancellationToken). + * + * @return The thenable the task-callback returned. + */ + export function withProgress(options: ProgressOptions, task: (progress: Progress<{ + message?: string + increment?: number + }>, token: CancellationToken) => Thenable): Promise + } + // }} + + // extensions module {{ + export interface Logger { + readonly category: string + readonly level: string + log(...args: any[]): void + trace(message: any, ...args: any[]): void + debug(message: any, ...args: any[]): void + info(message: any, ...args: any[]): void + warn(message: any, ...args: any[]): void + error(message: any, ...args: any[]): void + fatal(message: any, ...args: any[]): void + mark(message: any, ...args: any[]): void + } + + /** + * A memento represents a storage utility. It can store and retrieve + * values. + */ + export interface Memento { + + /** + * Return a value. + * + * @param key A string. + * @return The stored value or `undefined`. + */ + get(key: string): T | undefined + + /** + * Return a value. + * + * @param key A string. + * @param defaultValue A value that should be returned when there is no + * value (`undefined`) with the given key. + * @return The stored value or the defaultValue. + */ + get(key: string, defaultValue: T): T + + /** + * Store a value. The value must be JSON-stringifyable. + * + * @param key A string. + * @param value A value. MUST not contain cyclic references. + */ + update(key: string, value: any): Promise + } + + export type ExtensionState = 'disabled' | 'loaded' | 'activated' | 'unknown' + + export enum ExtensionType { + Global, + Local, + SingleFile, + Internal + } + + export interface ExtensionJson { + name: string + main?: string + engines: { + [key: string]: string + } + version?: string + [key: string]: any + } + + export interface ExtensionInfo { + id: string + version: string + description: string + root: string + exotic: boolean + uri?: string + state: ExtensionState + isLocal: boolean + packageJSON: Readonly + } + + /** + * Represents an extension. + * + * To get an instance of an `Extension` use [getExtension](#extensions.getExtension). + */ + export interface Extension { + + /** + * The canonical extension identifier in the form of: `publisher.name`. + */ + readonly id: string + + /** + * The absolute file path of the directory containing this extension. + */ + readonly extensionPath: string + + /** + * `true` if the extension has been activated. + */ + readonly isActive: boolean + + /** + * The parsed contents of the extension's package.json. + */ + readonly packageJSON: any + + /** + * The public API exported by this extension. It is an invalid action + * to access this field before this extension has been activated. + */ + readonly exports: T + + /** + * Activates this extension and returns its public API. + * + * @return A promise that will resolve when this extension has been activated. + */ + activate(): Promise + } + + /** + * An extension context is a collection of utilities private to an + * extension. + * + * An instance of an `ExtensionContext` is provided as the first + * parameter to the `activate`-call of an extension. + */ + export interface ExtensionContext { + + /** + * An array to which disposables can be added. When this + * extension is deactivated the disposables will be disposed. + */ + subscriptions: Disposable[] + + /** + * The absolute file path of the directory containing the extension. + */ + extensionPath: string + + /** + * Get the absolute path of a resource contained in the extension. + * + * @param relativePath A relative path to a resource contained in the extension. + * @return The absolute path of the resource. + */ + asAbsolutePath(relativePath: string): string + + /** + * The absolute directory path for extension to download persist data. + * The directory could be not exists. + */ + storagePath: string + + /** + * A memento object that stores state in the context + * of the currently opened [workspace](#workspace.workspaceFolders). + */ + workspaceState: Memento + + /** + * A memento object that stores state independent + * of the current opened [workspace](#workspace.workspaceFolders). + */ + globalState: Memento + + logger: Logger + } + + export type ExtensionApi = { + [index: string]: any + } | void | null | undefined + + export interface PropertyScheme { + type: string + default: any + description: string + enum?: string[] + items?: any + [key: string]: any + } + + export namespace extensions { + /** + * Fired on extension loaded, extension not activated yet. + */ + export const onDidLoadExtension: Event> + + /** + * Fired on extension activated. + */ + export const onDidActiveExtension: Event> + + /** + * Fired with extension id on extension unload. + */ + export const onDidUnloadExtension: Event + + /** + * Get all loaded extensions, without disabled extensions, extension may not activated. + */ + export const all: ReadonlyArray> + + /** + * Get state of specific extension. + */ + export function getExtensionState(id: string): ExtensionState + + /** + * Get state of all extensions, including disabled extensions. + */ + export function getExtensionStates(): Promise + + /** + * Check if extension is activated. + */ + export function isActivated(id: string): boolean + + /** + * Dynamic add custom json schemes without using package.json. + */ + export function addSchemeProperty(key: string, def: PropertyScheme): void + } + // }} + + // listManager module {{ + export interface LocationWithLine { + uri: string + /** + * Match text of line. + */ + line: string + /** + * Highlight text in line. + */ + text?: string + } + + export interface AnsiHighlight { + /** + * Byte indexes, 0 based. + */ + span: [number, number] + hlGroup: string + } + + export interface ListItem { + label: string + filterText?: string + /** + * A string that should be used when comparing this item + * with other items, only used for fuzzy filter. + */ + sortText?: string + location?: Location | LocationWithLine | string + data?: any + ansiHighlights?: AnsiHighlight[] + resolved?: boolean + } + + export interface ListHighlights { + /** + * Byte indexes list, 0 based. + */ + spans: [number, number][] + /** + * `list.matchHighlightGroup` is used when not exists. + */ + hlGroup?: string + } + + export type ListMode = 'normal' | 'insert' + + export type ListMatcher = 'strict' | 'fuzzy' | 'regex' + + export interface ListOptions { + position: string + input: string + ignorecase: boolean + interactive: boolean + sort: boolean + mode: ListMode + matcher: ListMatcher + autoPreview: boolean + numberSelect: boolean + noQuit: boolean + first: boolean + } + + export interface ListContext { + /** + * Input on list activated. + */ + input: string + /** + * Current work directory on activated. + */ + cwd: string + /** + * Options of list. + */ + options: ListOptions + /** + * Arguments passed to list. + */ + args: string[] + /** + * Original window on list invoke. + */ + window: Window + /** + * Original buffer on list invoke. + */ + buffer: Buffer + listWindow: Window | null + } + + export interface ListAction { + /** + * Action name + */ + name: string + /** + * Should persist list window on invoke. + */ + persist?: boolean + /** + * Should reload list after invoke. + */ + reload?: boolean + /** + * Inovke all selected items in parallel. + */ + parallel?: boolean + /** + * Support handle multiple items at once. + */ + multiple?: boolean + /** + * Item is array of selected items when multiple is true. + */ + execute: (item: ListItem | ListItem[], context: ListContext) => ProviderResult + } + + export interface MutipleListAction extends ListAction { + multiple: true + execute: (item: ListItem[], context: ListContext) => ProviderResult + } + + export interface ListTask { + on(event: 'data', callback: (item: ListItem) => void): void + on(event: 'end', callback: () => void): void + on(event: 'error', callback: (msg: string | Error) => void): void + dispose(): void + } + + export interface ListArgument { + key?: string + hasValue?: boolean + name: string + description: string + } + + export interface IList { + /** + * Unique name of list. + */ + name: string + /** + * Default action name. + */ + defaultAction: string + /** + * Action list. + */ + actions: ListAction[] + /** + * Load list items. + */ + loadItems(context: ListContext, token: CancellationToken): Promise + /** + * Should be true when interactive is supported. + */ + interactive?: boolean + /** + * Description of list. + */ + description?: string + /** + * Detail description, shown in help. + */ + detail?: string + /** + * Options supported by list. + */ + options?: ListArgument[] + /** + * Resolve list item. + */ + resolveItem?(item: ListItem): Promise + /** + * Highlight buffer by vim's syntax commands. + */ + doHighlight?(): void + /** + * Called on list unregisted. + */ + dispose?(): void + } + + export interface PreviewOptions { + bufname?: string + lines: string[] + filetype: string + lnum?: number + range?: Range + /** + * @deprecated not used + */ + sketch?: boolean + } + + export namespace listManager { + /** + * Registered list names set. + */ + export const names: ReadonlyArray + /** + * Register list, list session can be created by `CocList [name]` after registered. + */ + export function registerList(list: IList): Disposable + } + // }} + + // snippetManager module {{ + export interface SnippetSession { + isActive: boolean + } + export interface TextmateSnippet { + toString(): string + } + /** + * A snippet string is a template which allows to insert text + * and to control the editor cursor when insertion happens. + * + * 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. Variables are defined with `$name` and + * `${name:default value}`. The full snippet syntax is documented + * [here](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_creating-your-own-snippets). + */ + export class SnippetString { + /** + * The snippet string. + */ + value: string + + constructor( + /** + * The default snippet string. + */ + value?: string + ) + + /** + * Builder-function that appends the given string to + * the {@link SnippetString.value `value`} of this snippet string. + * + * @param string A value to append 'as given'. The string will be escaped. + * @return This snippet string. + */ + appendText(string: string): SnippetString + + /** + * Builder-function that appends a tabstop (`$1`, `$2` etc) to + * the {@link SnippetString.value `value`} of this snippet string. + * + * @param number The number of this tabstop, defaults to an auto-increment + * value starting at 1. + * @return This snippet string. + */ + appendTabstop(number?: number): SnippetString + + /** + * Builder-function that appends a placeholder (`${1:value}`) to + * the {@link SnippetString.value `value`} of this snippet string. + * + * @param value The value of this placeholder - either a string or a function + * with which a nested snippet can be created. + * @param number The number of this tabstop, defaults to an auto-increment + * value starting at 1. + * @return This snippet string. + */ + appendPlaceholder(value: string | ((snippet: SnippetString) => any), number?: number): SnippetString + + /** + * Builder-function that appends a choice (`${1|a,b,c|}`) to + * the {@link SnippetString.value `value`} of this snippet string. + * + * @param values The values for choices - the array of strings + * @param number The number of this tabstop, defaults to an auto-increment + * value starting at 1. + * @return This snippet string. + */ + appendChoice(values: string[], number?: number): SnippetString + + /** + * Builder-function that appends a variable (`${VAR}`) to + * the {@link SnippetString.value `value`} of this snippet string. + * + * @param name The name of the variable - excluding the `$`. + * @param defaultValue The default value which is used when the variable name cannot + * be resolved - either a string or a function with which a nested snippet can be created. + * @return This snippet string. + */ + appendVariable(name: string, defaultValue: string | ((snippet: SnippetString) => any)): SnippetString + } + /** + * Manage snippet sessions. + */ + export namespace snippetManager { + /** + * Get snippet session by bufnr. + */ + export function getSession(bufnr: number): SnippetSession | undefined + /** + * Parse snippet string to TextmateSnippet. + */ + export function resolveSnippet(body: string): Promise + /** + * Insert snippet at current buffer. + * + * @param {string} snippet Textmate snippet string. + * @param {boolean} select Not select first placeholder when false, default `true`. + * @param {Range} range Repalce range, insert to current cursor position when undefined. + * @returns {Promise} true when insert success. + */ + export function insertSnippet(snippet: string | SnippetString, select?: boolean, range?: Range): Promise + + /** + * Jump to next placeholder, only works when snippet session activated. + */ + export function nextPlaceholder(): Promise + /** + * Jump to previous placeholder, only works when snippet session activated. + */ + export function previousPlaceholder(): Promise + /** + * Cancel snippet session of current buffer, does nothing when no session activated. + */ + export function cancel(): void + /** + * Check if snippet activated for bufnr. + */ + export function isActived(bufnr: number): boolean + } + // }} + + // diagnosticManager module {{ + export interface DiagnosticItem { + file: string + lnum: number + col: number + source: string + code: string | number + message: string + severity: string + level: number + location: Location + } + + export enum DiagnosticKind { + Syntax, + Semantic, + Suggestion, + } + + /** + * A diagnostics collection is a container that manages a set of + * [diagnostics](#Diagnostic). Diagnostics are always scopes to a + * diagnostics collection and a resource. + * + * To get an instance of a `DiagnosticCollection` use + * [createDiagnosticCollection](#languages.createDiagnosticCollection). + */ + export interface DiagnosticCollection { + + /** + * The name of this diagnostic collection, for instance `typescript`. Every diagnostic + * from this collection will be associated with this name. Also, the task framework uses this + * name when defining [problem matchers](https://code.visualstudio.com/docs/editor/tasks#_defining-a-problem-matcher). + */ + readonly name: string + + /** + * Assign diagnostics for given resource. Will replace + * existing diagnostics for that resource. + * + * @param uri A resource identifier. + * @param diagnostics Array of diagnostics or `undefined` + */ + set(uri: string, diagnostics: Diagnostic[] | null): void + /** + * Replace all entries in this collection. + * + * Diagnostics of multiple tuples of the same uri will be merged, e.g + * `[[file1, [d1]], [file1, [d2]]]` is equivalent to `[[file1, [d1, d2]]]`. + * If a diagnostics item is `undefined` as in `[file1, undefined]` + * all previous but not subsequent diagnostics are removed. + * + * @param entries An array of tuples, like `[[file1, [d1, d2]], [file2, [d3, d4, d5]]]`, or `undefined`. + */ + set(entries: [string, Diagnostic[] | null][] | string, diagnostics?: Diagnostic[]): void + + /** + * Remove all diagnostics from this collection that belong + * to the provided `uri`. The same as `#set(uri, undefined)`. + * + * @param uri A resource identifier. + */ + delete(uri: string): void + + /** + * Remove all diagnostics from this collection. The same + * as calling `#set(undefined)` + */ + clear(): void + + /** + * Iterate over each entry in this collection. + * + * @param callback Function to execute for each entry. + * @param thisArg The `this` context used when invoking the handler function. + */ + forEach(callback: (uri: string, diagnostics: Diagnostic[], collection: DiagnosticCollection) => any, thisArg?: any): void + + /** + * Get the diagnostics for a given resource. *Note* that you cannot + * modify the diagnostics-array returned from this call. + * + * @param uri A resource identifier. + * @returns An immutable array of [diagnostics](#Diagnostic) or `undefined`. + */ + get(uri: string): Diagnostic[] | undefined + + /** + * Check if this collection contains diagnostics for a + * given resource. + * + * @param uri A resource identifier. + * @returns `true` if this collection has diagnostic for the given resource. + */ + has(uri: string): boolean + + /** + * Dispose and free associated resources. Calls + * [clear](#DiagnosticCollection.clear). + */ + dispose(): void + } + + export interface DiagnosticEventParams { + bufnr: number + uri: string + diagnostics: ReadonlyArray + } + + export namespace diagnosticManager { + + export const onDidRefresh: Event + /** + * Create collection by name + */ + export function create(name: string): DiagnosticCollection + + /** + * Get readonly diagnostics for uri + */ + export function getDiagnostics(uri: string): { [collection: string]: Diagnostic[] } + + /** + * Get readonly diagnostics by document and range. + */ + export function getDiagnosticsInRange(doc: TextDocumentIdentifier, range: Range): ReadonlyArray + /** + * All diagnostics of current workspace + */ + export function getDiagnosticList(): ReadonlyArray + + /** + * All diagnostics at current cursor position. + */ + export function getCurrentDiagnostics(): Promise> + + /** + * Get diagnostic collection. + */ + export function getCollectionByName(name: string): DiagnosticCollection + } + // }} + + // language client {{ + /** + * An action to be performed when the connection is producing errors. + */ + export enum ErrorAction { + /** + * Continue running the server. + */ + Continue = 1, + /** + * Shutdown the server. + */ + Shutdown = 2 + } + /** + * An action to be performed when the connection to a server got closed. + */ + export enum CloseAction { + /** + * Don't restart the server. The connection stays closed. + */ + DoNotRestart = 1, + /** + * Restart the server. + */ + Restart = 2 + } + /** + * A pluggable error handler that is invoked when the connection is either + * producing errors or got closed. + */ + export interface ErrorHandler { + /** + * An error has occurred while writing or reading from the connection. + * + * @param error - the error received + * @param message - the message to be delivered to the server if know. + * @param count - a count indicating how often an error is received. Will + * be reset if a message got successfully send or received. + */ + error(error: Error, message: { jsonrpc: string }, count: number): ErrorAction + /** + * The connection to the server got closed. + */ + closed(): CloseAction + } + export interface InitializationFailedHandler { + (error: Error | any): boolean + } + + export interface SynchronizeOptions { + configurationSection?: string | string[] + fileEvents?: FileSystemWatcher | FileSystemWatcher[] + } + + export enum RevealOutputChannelOn { + Info = 1, + Warn = 2, + Error = 3, + Never = 4 + } + export interface ConfigurationItem { + /** + * The scope to get the configuration section for. + */ + scopeUri?: string + /** + * The configuration section asked for. + */ + section?: string + } + export interface ResponseError { + code: number + data: D | undefined + } + + export type HandlerResult = R | ResponseError | Thenable | Thenable> | Thenable> + + export interface RequestHandler { + (params: P, token: CancellationToken): HandlerResult + } + + export interface RequestHandler0 { + (token: CancellationToken): HandlerResult + } + /** + * The parameters of a configuration request. + */ + export interface ConfigurationParams { + items: ConfigurationItem[] + } + + export interface ConfigurationWorkspaceMiddleware { + configuration?: (params: ConfigurationParams, token: CancellationToken, next: RequestHandler) => HandlerResult + } + + export interface WorkspaceFolderWorkspaceMiddleware { + workspaceFolders?: (token: CancellationToken, next: RequestHandler0) => HandlerResult + didChangeWorkspaceFolders?: NextSignature + } + + export interface ProvideTypeDefinitionSignature { + ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken + ): ProviderResult + } + + export interface TypeDefinitionMiddleware { + provideTypeDefinition?: ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken, + next: ProvideTypeDefinitionSignature + ) => ProviderResult + } + + export interface ProvideImplementationSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + + export interface ImplementationMiddleware { + provideImplementation?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: ProvideImplementationSignature) => ProviderResult + } + export type ProvideDocumentColorsSignature = (document: TextDocument, token: CancellationToken) => ProviderResult + + export type ProvideColorPresentationSignature = ( + color: Color, + context: { document: TextDocument; range: Range }, + token: CancellationToken + ) => ProviderResult + + export interface ColorProviderMiddleware { + provideDocumentColors?: ( + this: void, + document: TextDocument, + token: CancellationToken, + next: ProvideDocumentColorsSignature + ) => ProviderResult + provideColorPresentations?: ( + this: void, + color: Color, + context: { document: TextDocument; range: Range }, + token: CancellationToken, + next: ProvideColorPresentationSignature + ) => ProviderResult + } + + export interface ProvideDeclarationSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + + export interface DeclarationMiddleware { + provideDeclaration?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: ProvideDeclarationSignature) => ProviderResult + } + + export type ProvideFoldingRangeSignature = ( + this: void, + document: TextDocument, + context: FoldingContext, + token: CancellationToken + ) => ProviderResult + + export interface FoldingRangeProviderMiddleware { + provideFoldingRanges?: ( + this: void, + document: TextDocument, + context: FoldingContext, + token: CancellationToken, + next: ProvideFoldingRangeSignature + ) => ProviderResult + } + + export interface PrepareCallHierarchySignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + + export interface CallHierarchyIncomingCallsSignature { + (this: void, item: CallHierarchyItem, token: CancellationToken): ProviderResult + } + + export interface CallHierarchyOutgoingCallsSignature { + (this: void, item: CallHierarchyItem, token: CancellationToken): ProviderResult + } + export interface CallHierarchyMiddleware { + prepareCallHierarchy?: ( + this: void, + document: TextDocument, + positions: Position, + token: CancellationToken, + next: PrepareCallHierarchySignature + ) => ProviderResult + provideCallHierarchyIncomingCalls?: ( + this: void, + item: CallHierarchyItem, + token: CancellationToken, + next: CallHierarchyIncomingCallsSignature + ) => ProviderResult + provideCallHierarchyOutgoingCalls?: ( + this: void, + item: CallHierarchyItem, + token: CancellationToken, + next: CallHierarchyOutgoingCallsSignature + ) => ProviderResult + } + + export interface DocumentSemanticsTokensSignature { + (this: void, document: TextDocument, token: CancellationToken): ProviderResult + } + + export interface DocumentSemanticsTokensEditsSignature { + (this: void, document: TextDocument, previousResultId: string, token: CancellationToken): ProviderResult + } + + export interface DocumentRangeSemanticTokensSignature { + (this: void, document: TextDocument, range: Range, token: CancellationToken): ProviderResult + } + + export interface SemanticTokensMiddleware { + provideDocumentSemanticTokens?: ( + this: void, + document: TextDocument, + token: CancellationToken, + next: DocumentSemanticsTokensSignature + ) => ProviderResult + provideDocumentSemanticTokensEdits?: ( + this: void, + document: TextDocument, + previousResultId: string, + token: CancellationToken, + next: DocumentSemanticsTokensEditsSignature + ) => ProviderResult + provideDocumentRangeSemanticTokens?: ( + this: void, + document: TextDocument, + range: Range, + token: CancellationToken, + next: DocumentRangeSemanticTokensSignature + ) => ProviderResult + } + + export interface ProvideLinkedEditingRangeSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + + export interface LinkedEditingRangeMiddleware { + provideLinkedEditingRange?: ( + this: void, + document: TextDocument, + position: Position, + token: CancellationToken, + next: ProvideLinkedEditingRangeSignature + ) => ProviderResult + } + + export interface ProvideSelectionRangeSignature { + (this: void, document: TextDocument, positions: Position[], token: CancellationToken): ProviderResult + } + + export interface SelectionRangeProviderMiddleware { + provideSelectionRanges?: (this: void, document: TextDocument, positions: Position[], token: CancellationToken, next: ProvideSelectionRangeSignature) => ProviderResult + } + + export interface HandleWorkDoneProgressSignature { + (this: void, token: ProgressToken, params: WorkDoneProgressBegin | WorkDoneProgressReport | WorkDoneProgressEnd): void + } + + export interface HandleDiagnosticsSignature { + (this: void, uri: string, diagnostics: Diagnostic[]): void + } + + export interface ProvideCompletionItemsSignature { + (this: void, document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken): ProviderResult + } + + export interface ResolveCompletionItemSignature { + (this: void, item: CompletionItem, token: CancellationToken): ProviderResult + } + + export interface ProvideHoverSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + + export interface ProvideSignatureHelpSignature { + (this: void, document: TextDocument, position: Position, context: SignatureHelpContext, token: CancellationToken): ProviderResult + } + + export interface ProvideDefinitionSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + + export interface ProvideReferencesSignature { + (this: void, document: TextDocument, position: Position, options: { + includeDeclaration: boolean + }, token: CancellationToken): ProviderResult + } + + export interface ProvideDocumentHighlightsSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + + export interface ProvideDocumentSymbolsSignature { + (this: void, document: TextDocument, token: CancellationToken): ProviderResult + } + + export interface ProvideWorkspaceSymbolsSignature { + (this: void, query: string, token: CancellationToken): ProviderResult + } + + export interface ProvideCodeActionsSignature { + (this: void, document: TextDocument, range: Range, context: CodeActionContext, token: CancellationToken): ProviderResult<(Command | CodeAction)[]> + } + + export interface ResolveCodeActionSignature { + (this: void, item: CodeAction, token: CancellationToken): ProviderResult + } + + export interface ProvideCodeLensesSignature { + (this: void, document: TextDocument, token: CancellationToken): ProviderResult + } + + export interface ResolveCodeLensSignature { + (this: void, codeLens: CodeLens, token: CancellationToken): ProviderResult + } + + export interface ProvideDocumentFormattingEditsSignature { + (this: void, document: TextDocument, options: FormattingOptions, token: CancellationToken): ProviderResult + } + + export interface ProvideDocumentRangeFormattingEditsSignature { + (this: void, document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult + } + + export interface ProvideOnTypeFormattingEditsSignature { + (this: void, document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): ProviderResult + } + + export interface PrepareRenameSignature { + (this: void, document: TextDocument, position: Position, token: CancellationToken): ProviderResult + } + + export interface ProvideRenameEditsSignature { + (this: void, document: TextDocument, position: Position, newName: string, token: CancellationToken): ProviderResult + } + + export interface ProvideDocumentLinksSignature { + (this: void, document: TextDocument, token: CancellationToken): ProviderResult + } + + export interface ResolveDocumentLinkSignature { + (this: void, link: DocumentLink, token: CancellationToken): ProviderResult + } + + export interface ExecuteCommandSignature { + (this: void, command: string, args: any[]): ProviderResult + } + + export interface NextSignature { + (this: void, data: P, next: (data: P) => R): R + } + + export interface DidChangeConfigurationSignature { + (this: void, sections: string[] | undefined): void + } + + export interface DidChangeWatchedFileSignature { + (this: void, event: FileEvent): void + } + + export interface _WorkspaceMiddleware { + didChangeConfiguration?: (this: void, sections: string[] | undefined, next: DidChangeConfigurationSignature) => void + didChangeWatchedFile?: (this: void, event: FileEvent, next: DidChangeWatchedFileSignature) => void + } + + export type WorkspaceMiddleware = _WorkspaceMiddleware & ConfigurationWorkspaceMiddleware & WorkspaceFolderWorkspaceMiddleware + + /** + * Params to show a document. + * + * @since 3.16.0 + */ + export interface ShowDocumentParams { + /** + * The document uri to show. + */ + uri: string + /** + * Indicates to show the resource in an external program. + * To show for example `https://code.visualstudio.com/` + * in the default WEB browser set `external` to `true`. + */ + external?: boolean + /** + * An optional property to indicate whether the editor + * showing the document should take focus or not. + * Clients might ignore this property if an external + * program in started. + */ + takeFocus?: boolean + /** + * An optional selection range if the document is a text + * document. Clients might ignore the property if an + * external program is started or the file is not a text + * file. + */ + selection?: Range + } + /** + * The result of an show document request. + * + * @since 3.16.0 + */ + export interface ShowDocumentResult { + /** + * A boolean indicating if the show was successful. + */ + success: boolean + } + + export interface _WindowMiddleware { + showDocument?: ( + this: void, + params: ShowDocumentParams, + next: RequestHandler + ) => Promise + } + export type WindowMiddleware = _WindowMiddleware + + /** + * The Middleware lets extensions intercept the request and notications send and received + * from the server + */ + interface _Middleware { + didOpen?: NextSignature + didChange?: NextSignature + willSave?: NextSignature + willSaveWaitUntil?: NextSignature> + didSave?: NextSignature + didClose?: NextSignature + handleDiagnostics?: (this: void, uri: string, diagnostics: Diagnostic[], next: HandleDiagnosticsSignature) => void + provideCompletionItem?: (this: void, document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature) => ProviderResult + resolveCompletionItem?: (this: void, item: CompletionItem, token: CancellationToken, next: ResolveCompletionItemSignature) => ProviderResult + provideHover?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: ProvideHoverSignature) => ProviderResult + provideSignatureHelp?: (this: void, document: TextDocument, position: Position, context: SignatureHelpContext, token: CancellationToken, next: ProvideSignatureHelpSignature) => ProviderResult + provideDefinition?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: ProvideDefinitionSignature) => ProviderResult + provideReferences?: (this: void, document: TextDocument, position: Position, options: { + includeDeclaration: boolean + }, token: CancellationToken, next: ProvideReferencesSignature) => ProviderResult + provideDocumentHighlights?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: ProvideDocumentHighlightsSignature) => ProviderResult + provideDocumentSymbols?: (this: void, document: TextDocument, token: CancellationToken, next: ProvideDocumentSymbolsSignature) => ProviderResult + provideWorkspaceSymbols?: (this: void, query: string, token: CancellationToken, next: ProvideWorkspaceSymbolsSignature) => ProviderResult + provideCodeActions?: (this: void, document: TextDocument, range: Range, context: CodeActionContext, token: CancellationToken, next: ProvideCodeActionsSignature) => ProviderResult<(Command | CodeAction)[]> + handleWorkDoneProgress?: (this: void, token: ProgressToken, params: WorkDoneProgressBegin | WorkDoneProgressReport | WorkDoneProgressEnd, next: HandleWorkDoneProgressSignature) => void + resolveCodeAction?: (this: void, item: CodeAction, token: CancellationToken, next: ResolveCodeActionSignature) => ProviderResult + provideCodeLenses?: (this: void, document: TextDocument, token: CancellationToken, next: ProvideCodeLensesSignature) => ProviderResult + resolveCodeLens?: (this: void, codeLens: CodeLens, token: CancellationToken, next: ResolveCodeLensSignature) => ProviderResult + provideDocumentFormattingEdits?: (this: void, document: TextDocument, options: FormattingOptions, token: CancellationToken, next: ProvideDocumentFormattingEditsSignature) => ProviderResult + provideDocumentRangeFormattingEdits?: (this: void, document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken, next: ProvideDocumentRangeFormattingEditsSignature) => ProviderResult + provideOnTypeFormattingEdits?: (this: void, document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken, next: ProvideOnTypeFormattingEditsSignature) => ProviderResult + prepareRename?: (this: void, document: TextDocument, position: Position, token: CancellationToken, next: PrepareRenameSignature) => ProviderResult + provideRenameEdits?: (this: void, document: TextDocument, position: Position, newName: string, token: CancellationToken, next: ProvideRenameEditsSignature) => ProviderResult + provideDocumentLinks?: (this: void, document: TextDocument, token: CancellationToken, next: ProvideDocumentLinksSignature) => ProviderResult + resolveDocumentLink?: (this: void, link: DocumentLink, token: CancellationToken, next: ResolveDocumentLinkSignature) => ProviderResult + executeCommand?: (this: void, command: string, args: any[], next: ExecuteCommandSignature) => ProviderResult + workspace?: WorkspaceMiddleware + window?: WindowMiddleware + } + export type Middleware = _Middleware & TypeDefinitionMiddleware & ImplementationMiddleware & ColorProviderMiddleware & DeclarationMiddleware & FoldingRangeProviderMiddleware & CallHierarchyMiddleware & SemanticTokensMiddleware & LinkedEditingRangeMiddleware & SelectionRangeProviderMiddleware + + export interface ConnectionOptions { + // cancellationStrategy: CancellationStrategy + maxRestartCount?: number + } + + export interface LanguageClientOptions { + ignoredRootPaths?: string[] + disableWorkspaceFolders?: boolean + disableSnippetCompletion?: boolean + disableDynamicRegister?: boolean + disableDiagnostics?: boolean + disableCompletion?: boolean + formatterPriority?: number + documentSelector?: DocumentSelector | string[] + synchronize?: SynchronizeOptions + diagnosticCollectionName?: string + outputChannelName?: string + outputChannel?: OutputChannel + revealOutputChannelOn?: RevealOutputChannelOn + /** + * The encoding use to read stdout and stderr. Defaults + * to 'utf8' if omitted. + */ + stdioEncoding?: string + initializationOptions?: any | (() => any) + initializationFailedHandler?: InitializationFailedHandler + progressOnInitialization?: boolean + errorHandler?: ErrorHandler + middleware?: Middleware + workspaceFolder?: WorkspaceFolder + connectionOptions?: ConnectionOptions + markdown?: { + isTrusted: boolean + } + } + export enum State { + Stopped = 1, + Running = 2, + Starting = 3 + } + export interface StateChangeEvent { + oldState: State + newState: State + } + export enum ClientState { + Initial = 0, + Starting = 1, + StartFailed = 2, + Running = 3, + Stopping = 4, + Stopped = 5 + } + export interface RegistrationData { + id: string + registerOptions: T + } + /** + * A static feature. A static feature can't be dynamically activate via the + * server. It is wired during the initialize sequence. + */ + export interface StaticFeature { + /** + * Called to fill the initialize params. + * + * @params the initialize params. + */ + fillInitializeParams?: (params: any) => void + /** + * Called to fill in the client capabilities this feature implements. + * + * @param capabilities The client capabilities to fill. + */ + fillClientCapabilities(capabilities: any): void + /** + * Initialize the feature. This method is called on a feature instance + * when the client has successfully received the initialize request from + * the server and before the client sends the initialized notification + * to the server. + * + * @param capabilities the server capabilities + * @param documentSelector the document selector pass to the client's constuctor. + * May be `undefined` if the client was created without a selector. + */ + initialize(capabilities: any, documentSelector: DocumentSelector | undefined): void + /** + * Called when the client is stopped to dispose this feature. Usually a feature + * unregisters listeners registered hooked up with the VS Code extension host. + */ + dispose(): void + } + + class ParameterStructures { + private readonly kind + /** + * The parameter structure is automatically inferred on the number of parameters + * and the parameter type in case of a single param. + */ + static readonly auto: ParameterStructures + /** + * Forces `byPosition` parameter structure. This is useful if you have a single + * parameter which has a literal type. + */ + static readonly byPosition: ParameterStructures + /** + * Forces `byName` parameter structure. This is only useful when having a single + * parameter. The library will report errors if used with a different number of + * parameters. + */ + static readonly byName: ParameterStructures + private constructor() + static is(value: any): value is ParameterStructures + toString(): string + } + /** + * An interface to type messages. + */ + export interface MessageSignature { + readonly method: string + readonly numberOfParams: number + readonly parameterStructures: ParameterStructures + } + + /** + * + * An abstract implementation of a MessageType. + */ + abstract class AbstractMessageSignature implements MessageSignature { + readonly method: string + readonly numberOfParams: number + constructor(method: string, numberOfParams: number) + get parameterStructures(): ParameterStructures + } + + /** + * Classes to type request response pairs + */ + export class RequestType0 extends AbstractMessageSignature { + /** + * Clients must not use this property. It is here to ensure correct typing. + */ + readonly _: [R, E, _EM] | undefined + constructor(method: string) + } + + export class RequestType extends AbstractMessageSignature { + private _parameterStructures + /** + * Clients must not use this property. It is here to ensure correct typing. + */ + readonly _: [P, R, E, _EM] | undefined + constructor(method: string, _parameterStructures?: ParameterStructures) + get parameterStructures(): ParameterStructures + } + + export class NotificationType

    extends AbstractMessageSignature { + /** + * Clients must not use this property. It is here to ensure correct typing. + */ + readonly _: [P, _EM] | undefined + constructor(method: string) + } + + export class NotificationType0 extends AbstractMessageSignature { + /** + * Clients must not use this property. It is here to ensure correct typing. + */ + readonly _: [_EM] | undefined + constructor(method: string) + } + + export interface InitializeParams { + /** + * The process Id of the parent process that started + * the server. + */ + processId: number | null + /** + * Information about the client + * + * @since 3.15.0 + */ + clientInfo?: { + /** + * The name of the client as defined by the client. + */ + name: string + /** + * The client's version as defined by the client. + */ + version?: string + } + /** + * The rootPath of the workspace. Is null + * if no folder is open. + * + * @deprecated in favour of rootUri. + */ + rootPath?: string | null + /** + * The rootUri of the workspace. Is null if no + * folder is open. If both `rootPath` and `rootUri` are set + * `rootUri` wins. + * + * @deprecated in favour of workspaceFolders. + */ + rootUri: string | null + /** + * The capabilities provided by the client (editor or tool) + */ + capabilities: any + /** + * User provided initialization options. + */ + initializationOptions?: any + /** + * The initial trace setting. If omitted trace is disabled ('off'). + */ + trace?: 'off' | 'messages' | 'verbose' + /** + * An optional token that a server can use to report work done progress. + */ + workDoneToken?: ProgressToken + } + class RegistrationType { + /** + * Clients must not use this property. It is here to ensure correct typing. + */ + readonly ____: [RO, _EM] | undefined + readonly method: string + constructor(method: string) + } + /** + * The result returned from an initialize request. + */ + export interface InitializeResult { + /** + * The capabilities the language server provides. + */ + capabilities: any + /** + * Information about the server. + * + * @since 3.15.0 + */ + serverInfo?: { + /** + * The name of the server as defined by the server. + */ + name: string + /** + * The servers's version as defined by the server. + */ + version?: string + } + /** + * Custom initialization results. + */ + [custom: string]: any + } + + export interface DynamicFeature { + /** + * Called to fill the initialize params. + * + * @params the initialize params. + */ + fillInitializeParams?: (params: InitializeParams) => void + /** + * Called to fill in the client capabilities this feature implements. + * + * @param capabilities The client capabilities to fill. + */ + fillClientCapabilities(capabilities: any): void + /** + * Initialize the feature. This method is called on a feature instance + * when the client has successfully received the initialize request from + * the server and before the client sends the initialized notification + * to the server. + * + * @param capabilities the server capabilities. + * @param documentSelector the document selector pass to the client's constructor. + * May be `undefined` if the client was created without a selector. + */ + initialize(capabilities: any, documentSelector: DocumentSelector | undefined): void + /** + * The signature (e.g. method) for which this features support dynamic activation / registration. + */ + registrationType: RegistrationType + /** + * Is called when the server send a register request for the given message. + * + * @param data additional registration data as defined in the protocol. + */ + register(data: RegistrationData): void + /** + * Is called when the server wants to unregister a feature. + * + * @param id the id used when registering the feature. + */ + unregister(id: string): void + /** + * Called when the client is stopped to dispose this feature. Usually a feature + * unregisters listeners registered hooked up with the VS Code extension host. + */ + dispose(): void + } + + export interface NotificationFeature { + /** + * Triggers the corresponding RPC method. + */ + getProvider(document: TextDocument): { + send: T + } + } + + export interface ExecutableOptions { + cwd?: string + env?: any + detached?: boolean + shell?: boolean + } + + export interface Executable { + command: string + args?: string[] + options?: ExecutableOptions + } + + export interface ForkOptions { + cwd?: string + env?: any + execPath?: string + encoding?: string + execArgv?: string[] + } + + export interface StreamInfo { + writer: NodeJS.WritableStream + reader: NodeJS.ReadableStream + detached?: boolean + } + + export enum TransportKind { + stdio = 0, + ipc = 1, + pipe = 2, + socket = 3 + } + + export interface SocketTransport { + kind: TransportKind.socket + port: number + } + + export interface NodeModule { + module: string + transport?: TransportKind | SocketTransport + args?: string[] + runtime?: string + options?: ForkOptions + } + + export interface ChildProcessInfo { + process: cp.ChildProcess + detached: boolean + } + + export interface PartialMessageInfo { + readonly messageToken: number + readonly waitingTime: number + } + + export interface MessageReader { + readonly onError: Event + readonly onClose: Event + readonly onPartialMessage: Event + listen(callback: (data: { jsonrpc: string }) => void): void + dispose(): void + } + + export interface MessageWriter { + readonly onError: Event<[Error, { jsonrpc: string } | undefined, number | undefined]> + readonly onClose: Event + write(msg: { jsonrpc: string }): void + dispose(): void + } + + export class NullLogger { + constructor() + error(message: string): void + warn(message: string): void + info(message: string): void + log(message: string): void + } + + export interface MessageTransports { + reader: MessageReader + writer: MessageWriter + detached?: boolean + } + + export namespace MessageTransports { + /** + * Checks whether the given value conforms to the [MessageTransports](#MessageTransports) interface. + */ + function is(value: any): value is MessageTransports + } + + export type ServerOptions = Executable | NodeModule | { + run: Executable + debug: Executable + } | { + run: NodeModule + debug: NodeModule + } | (() => Promise) + + export interface _EM { + _$endMarker$_: number + } + + export class ProgressType

    { + /** + * Clients must not use this property. It is here to ensure correct typing. + */ + readonly __?: [P, _EM] + constructor() + } + + export enum Trace { + Off = 0, + Messages = 1, + Verbose = 2 + } + + /** + * A language server for manage a language server. + * It's recommended to use `services.registLanguageClient` for regist language client to serviers, + * you can have language client listed in `CocList services` and services could start the language client + * by `documentselector` of `clientOptions`. + */ + export class LanguageClient { + readonly id: string + readonly name: string + constructor(id: string, name: string, serverOptions: ServerOptions, clientOptions: LanguageClientOptions, forceDebug?: boolean) + /** + * Create language client by name and options, don't forget regist language client + * to services by `services.registLanguageClient` + */ + constructor(name: string, serverOptions: ServerOptions, clientOptions: LanguageClientOptions, forceDebug?: boolean) + /** + * R => result + * E => Error result + */ + sendRequest(type: RequestType0, token?: CancellationToken): Promise + /** + * P => params + * R => result + * E => Error result + */ + sendRequest(type: RequestType, params: P, token?: CancellationToken): Promise + sendRequest(method: string, token?: CancellationToken): Promise + sendRequest(method: string, param: any, token?: CancellationToken): Promise + + onRequest(type: RequestType0, handler: RequestHandler0): Disposable + onRequest(type: RequestType, handler: RequestHandler): Disposable + onRequest(method: string, handler: (...params: any[]) => HandlerResult): Disposable + + sendNotification(type: NotificationType0): void + sendNotification

    (type: NotificationType

    , params?: P): void + sendNotification(method: string): void + sendNotification(method: string, params: any): void + + onNotification(type: NotificationType0, handler: () => void): Disposable + onNotification

    (type: NotificationType

    , handler: (params: P) => void): Disposable + onNotification(method: string, handler: (...params: any[]) => void): Disposable + + onProgress

    (type: ProgressType, token: string | number, handler: (params: P) => void): Disposable + sendProgress

    (type: ProgressType

    , token: string | number, value: P): void + + /** + * Append info to outputChannel + */ + info(message: string, data?: any): void + /** + * Append warning to outputChannel + */ + warn(message: string, data?: any): void + /** + * append error to outputChannel + */ + error(message: string, data?: any): void + getPublicState(): State + get initializeResult(): InitializeResult | undefined + + get clientOptions(): LanguageClientOptions + /** + * Fired on language server state change. + */ + get onDidChangeState(): Event + get outputChannel(): OutputChannel + get diagnostics(): DiagnosticCollection | undefined + + /** + * Current running state. + */ + get serviceState(): ServiceStat + /** + * Check if server could start. + */ + needsStart(): boolean + /** + * Check if server could stop. + */ + needsStop(): boolean + onReady(): Promise + get started(): boolean + set trace(value: Trace) + + /** + * Stop language server. + */ + stop(): Promise + + /** + * Start language server, not needed when registered to services by `services.registLanguageClient` + */ + start(): Disposable + /** + * Restart language client. + */ + restart(): void + + /** + * Regist custom feature. + */ + registerFeature(feature: StaticFeature | DynamicFeature): void + + /** + * Log failed request to outputChannel. + */ + handleFailedRequest(type: MessageSignature, token: CancellationToken | undefined, error: any, defaultValue: T) + } + + /** + * Monitor for setting change, restart language server when specified setting changed. + */ + export class SettingMonitor { + constructor(client: LanguageClient, setting: string) + start(): Disposable + } + // }} +} diff --git a/vim-config/plugins/coc.nvim/yarn.lock b/vim-config/plugins/coc.nvim/yarn.lock new file mode 100644 index 00000000..8b240bb8 --- /dev/null +++ b/vim-config/plugins/coc.nvim/yarn.lock @@ -0,0 +1,3713 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" + integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== + dependencies: + "@babel/highlight" "^7.14.5" + +"@babel/compat-data@^7.14.5": + version "7.14.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08" + integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw== + +"@babel/compat-data@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" + integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== + +"@babel/core@^7.1.0", "@babel/core@^7.7.5": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.8.tgz#20cdf7c84b5d86d83fac8710a8bc605a7ba3f010" + integrity sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.14.8" + "@babel/helper-compilation-targets" "^7.14.5" + "@babel/helper-module-transforms" "^7.14.8" + "@babel/helpers" "^7.14.8" + "@babel/parser" "^7.14.8" + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.14.8" + "@babel/types" "^7.14.8" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/core@^7.7.2": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.0.tgz#749e57c68778b73ad8082775561f67f5196aafa8" + integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.0" + "@babel/helper-compilation-targets" "^7.15.0" + "@babel/helper-module-transforms" "^7.15.0" + "@babel/helpers" "^7.14.8" + "@babel/parser" "^7.15.0" + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/generator@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.8.tgz#bf86fd6af96cf3b74395a8ca409515f89423e070" + integrity sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg== + dependencies: + "@babel/types" "^7.14.8" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.15.0", "@babel/generator@^7.7.2": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15" + integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ== + dependencies: + "@babel/types" "^7.15.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-compilation-targets@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz#7a99c5d0967911e972fe2c3411f7d5b498498ecf" + integrity sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw== + dependencies: + "@babel/compat-data" "^7.14.5" + "@babel/helper-validator-option" "^7.14.5" + browserslist "^4.16.6" + semver "^6.3.0" + +"@babel/helper-compilation-targets@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz#973df8cbd025515f3ff25db0c05efc704fa79818" + integrity sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A== + dependencies: + "@babel/compat-data" "^7.15.0" + "@babel/helper-validator-option" "^7.14.5" + browserslist "^4.16.6" + semver "^6.3.0" + +"@babel/helper-function-name@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4" + integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ== + dependencies: + "@babel/helper-get-function-arity" "^7.14.5" + "@babel/template" "^7.14.5" + "@babel/types" "^7.14.5" + +"@babel/helper-get-function-arity@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz#25fbfa579b0937eee1f3b805ece4ce398c431815" + integrity sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-hoist-variables@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz#e0dd27c33a78e577d7c8884916a3e7ef1f7c7f8d" + integrity sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-member-expression-to-functions@^7.14.5": + version "7.14.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz#97e56244beb94211fe277bd818e3a329c66f7970" + integrity sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-member-expression-to-functions@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz#0ddaf5299c8179f27f37327936553e9bba60990b" + integrity sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg== + dependencies: + "@babel/types" "^7.15.0" + +"@babel/helper-module-imports@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz#6d1a44df6a38c957aa7c312da076429f11b422f3" + integrity sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-module-transforms@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.8.tgz#d4279f7e3fd5f4d5d342d833af36d4dd87d7dc49" + integrity sha512-RyE+NFOjXn5A9YU1dkpeBaduagTlZ0+fccnIcAGbv1KGUlReBj7utF7oEth8IdIBQPcux0DDgW5MFBH2xu9KcA== + dependencies: + "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-replace-supers" "^7.14.5" + "@babel/helper-simple-access" "^7.14.8" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/helper-validator-identifier" "^7.14.8" + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.14.8" + "@babel/types" "^7.14.8" + +"@babel/helper-module-transforms@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz#679275581ea056373eddbe360e1419ef23783b08" + integrity sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg== + dependencies: + "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-replace-supers" "^7.15.0" + "@babel/helper-simple-access" "^7.14.8" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/helper-validator-identifier" "^7.14.9" + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + +"@babel/helper-optimise-call-expression@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c" + integrity sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" + integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== + +"@babel/helper-replace-supers@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz#0ecc0b03c41cd567b4024ea016134c28414abb94" + integrity sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.14.5" + "@babel/helper-optimise-call-expression" "^7.14.5" + "@babel/traverse" "^7.14.5" + "@babel/types" "^7.14.5" + +"@babel/helper-replace-supers@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz#ace07708f5bf746bf2e6ba99572cce79b5d4e7f4" + integrity sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.15.0" + "@babel/helper-optimise-call-expression" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + +"@babel/helper-simple-access@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz#82e1fec0644a7e775c74d305f212c39f8fe73924" + integrity sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg== + dependencies: + "@babel/types" "^7.14.8" + +"@babel/helper-split-export-declaration@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz#22b23a54ef51c2b7605d851930c1976dd0bc693a" + integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA== + dependencies: + "@babel/types" "^7.14.5" + +"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz#32be33a756f29e278a0d644fa08a2c9e0f88a34c" + integrity sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow== + +"@babel/helper-validator-identifier@^7.14.9": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" + integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== + +"@babel/helper-validator-option@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" + integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== + +"@babel/helpers@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.14.8.tgz#839f88f463025886cff7f85a35297007e2da1b77" + integrity sha512-ZRDmI56pnV+p1dH6d+UN6GINGz7Krps3+270qqI9UJ4wxYThfAIcI5i7j5vXC4FJ3Wap+S9qcebxeYiqn87DZw== + dependencies: + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.14.8" + "@babel/types" "^7.14.8" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== + dependencies: + "@babel/helper-validator-identifier" "^7.14.5" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.5", "@babel/parser@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.8.tgz#66fd41666b2d7b840bd5ace7f7416d5ac60208d4" + integrity sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA== + +"@babel/parser@^7.15.0", "@babel/parser@^7.7.2": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.3.tgz#3416d9bea748052cfcb63dbcc27368105b1ed862" + integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" + integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/template@^7.14.5", "@babel/template@^7.3.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" + integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/parser" "^7.14.5" + "@babel/types" "^7.14.5" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.8.tgz#c0253f02677c5de1a8ff9df6b0aacbec7da1a8ce" + integrity sha512-kexHhzCljJcFNn1KYAQ6A5wxMRzq9ebYpEDV4+WdNyr3i7O44tanbDOR/xjiG2F3sllan+LgwK+7OMk0EmydHg== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.14.8" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-hoist-variables" "^7.14.5" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/parser" "^7.14.8" + "@babel/types" "^7.14.8" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.15.0", "@babel/traverse@^7.7.2": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98" + integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.0" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-hoist-variables" "^7.14.5" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/parser" "^7.15.0" + "@babel/types" "^7.15.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.8.tgz#38109de8fcadc06415fbd9b74df0065d4d41c728" + integrity sha512-iob4soQa7dZw8nodR/KlOQkPh9S4I8RwCxwRIFuiMRYjOzH/KJzdUfDgz6cGi5dDaclXF4P2PAhCdrBJNIg68Q== + dependencies: + "@babel/helper-validator-identifier" "^7.14.8" + to-fast-properties "^2.0.0" + +"@babel/types@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd" + integrity sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ== + dependencies: + "@babel/helper-validator-identifier" "^7.14.9" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@chemzqm/neovim@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@chemzqm/neovim/-/neovim-5.4.0.tgz#ca7261d963507b4843db0efaa76df238203d2055" + integrity sha512-BjOAR5sliE2kp3EGZsyUmrYwTMRrxvXe6WBQTxL0m5uRIvfxShRaWyKOGbqoe0+sHCfgT67QsMevUAjB1Ovskw== + dependencies: + msgpack-lite "^0.1.26" + +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" + integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.0.6.tgz#3eb72ea80897495c3d73dd97aab7f26770e2260f" + integrity sha512-fMlIBocSHPZ3JxgWiDNW/KPj6s+YRd0hicb33IrmelCcjXo/pXPwvuiKFmZz+XuqI/1u7nbUK10zSsWL/1aegg== + dependencies: + "@jest/types" "^27.0.6" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^27.0.6" + jest-util "^27.0.6" + slash "^3.0.0" + +"@jest/core@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.0.6.tgz#c5f642727a0b3bf0f37c4b46c675372d0978d4a1" + integrity sha512-SsYBm3yhqOn5ZLJCtccaBcvD/ccTLCeuDv8U41WJH/V1MW5eKUkeMHT9U+Pw/v1m1AIWlnIW/eM2XzQr0rEmow== + dependencies: + "@jest/console" "^27.0.6" + "@jest/reporters" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-changed-files "^27.0.6" + jest-config "^27.0.6" + jest-haste-map "^27.0.6" + jest-message-util "^27.0.6" + jest-regex-util "^27.0.6" + jest-resolve "^27.0.6" + jest-resolve-dependencies "^27.0.6" + jest-runner "^27.0.6" + jest-runtime "^27.0.6" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + jest-validate "^27.0.6" + jest-watcher "^27.0.6" + micromatch "^4.0.4" + p-each-series "^2.1.0" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.0.6.tgz#ee293fe996db01d7d663b8108fa0e1ff436219d2" + integrity sha512-4XywtdhwZwCpPJ/qfAkqExRsERW+UaoSRStSHCCiQTUpoYdLukj+YJbQSFrZjhlUDRZeNiU9SFH0u7iNimdiIg== + dependencies: + "@jest/fake-timers" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/node" "*" + jest-mock "^27.0.6" + +"@jest/fake-timers@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.0.6.tgz#cbad52f3fe6abe30e7acb8cd5fa3466b9588e3df" + integrity sha512-sqd+xTWtZ94l3yWDKnRTdvTeZ+A/V7SSKrxsrOKSqdyddb9CeNRF8fbhAU0D7ZJBpTTW2nbp6MftmKJDZfW2LQ== + dependencies: + "@jest/types" "^27.0.6" + "@sinonjs/fake-timers" "^7.0.2" + "@types/node" "*" + jest-message-util "^27.0.6" + jest-mock "^27.0.6" + jest-util "^27.0.6" + +"@jest/globals@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.0.6.tgz#48e3903f99a4650673d8657334d13c9caf0e8f82" + integrity sha512-DdTGCP606rh9bjkdQ7VvChV18iS7q0IMJVP1piwTWyWskol4iqcVwthZmoJEf7obE1nc34OpIyoVGPeqLC+ryw== + dependencies: + "@jest/environment" "^27.0.6" + "@jest/types" "^27.0.6" + expect "^27.0.6" + +"@jest/reporters@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.0.6.tgz#91e7f2d98c002ad5df94d5b5167c1eb0b9fd5b00" + integrity sha512-TIkBt09Cb2gptji3yJXb3EE+eVltW6BjO7frO7NEfjI9vSIYoISi5R3aI3KpEDXlB1xwB+97NXIqz84qYeYsfA== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.4" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.3" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^27.0.6" + jest-resolve "^27.0.6" + jest-util "^27.0.6" + jest-worker "^27.0.6" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^8.0.0" + +"@jest/source-map@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.0.6.tgz#be9e9b93565d49b0548b86e232092491fb60551f" + integrity sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.4" + source-map "^0.6.0" + +"@jest/test-result@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.0.6.tgz#3fa42015a14e4fdede6acd042ce98c7f36627051" + integrity sha512-ja/pBOMTufjX4JLEauLxE3LQBPaI2YjGFtXexRAjt1I/MbfNlMx0sytSX3tn5hSLzQsR3Qy2rd0hc1BWojtj9w== + dependencies: + "@jest/console" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.0.6.tgz#80a913ed7a1130545b1cd777ff2735dd3af5d34b" + integrity sha512-bISzNIApazYOlTHDum9PwW22NOyDa6VI31n6JucpjTVM0jD6JDgqEZ9+yn575nDdPF0+4csYDxNNW13NvFQGZA== + dependencies: + "@jest/test-result" "^27.0.6" + graceful-fs "^4.2.4" + jest-haste-map "^27.0.6" + jest-runtime "^27.0.6" + +"@jest/transform@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.0.6.tgz#189ad7107413208f7600f4719f81dd2f7278cc95" + integrity sha512-rj5Dw+mtIcntAUnMlW/Vju5mr73u8yg+irnHwzgtgoeI6cCPOvUwQ0D1uQtc/APmWgvRweEb1g05pkUpxH3iCA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^27.0.6" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^27.0.6" + jest-regex-util "^27.0.6" + jest-util "^27.0.6" + micromatch "^4.0.4" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.0.6.tgz#9a992bc517e0c49f035938b8549719c2de40706b" + integrity sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@sinonjs/commons@^1.7.0": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^7.0.2": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5" + integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": + version "7.1.15" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.15.tgz#2ccfb1ad55a02c83f8e0ad327cbc332f55eb1024" + integrity sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5" + integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" + integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== + dependencies: + "@babel/types" "^7.3.0" + +"@types/cli-table@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@types/cli-table/-/cli-table-0.3.0.tgz#f1857156bf5fd115c6a2db260ba0be1f8fc5671c" + integrity sha512-QnZUISJJXyhyD6L1e5QwXDV/A5i2W1/gl6D6YMc8u0ncPepbv/B4w3S+izVvtAg60m6h+JP09+Y/0zF2mojlFQ== + +"@types/debounce@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/debounce/-/debounce-3.0.0.tgz#ea4290f6e2d7ab99464c93b4a69b843d0993b181" + integrity sha512-SbehVj+zL0QFTufW3HP/Xvwr/kFWw1sFMLCvmyJdp5Xegbo81sqA2tByWlyeryvSwWBrY4drpLOtGPh0fkxjCQ== + +"@types/fb-watchman@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/fb-watchman/-/fb-watchman-2.0.1.tgz#4f44c7b7ac98463488765d41d269272dd34cb815" + integrity sha512-iJ7/e6drSmuCzAp96/dpksm8YjxbhhyXWV6m1HPbRHvZwUOUZ5vZvZIAUJxKDtI0UpdNfDvLPiai0MTJmmS+HA== + +"@types/fs-extra@^9.0.6": + version "9.0.12" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.12.tgz#9b8f27973df8a7a3920e8461517ebf8a7d4fdfaf" + integrity sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw== + dependencies: + "@types/node" "*" + +"@types/graceful-fs@^4.1.2": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^27.0.1": + version "27.0.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.0.1.tgz#fafcc997da0135865311bb1215ba16dba6bdf4ca" + integrity sha512-HTLpVXHrY69556ozYkcq47TtQJXpcWAWfkoqz+ZGz2JnmZhzlRjprCIyFnetSy8gpDWwTTGBcRVv1J1I1vBrHw== + dependencies: + jest-diff "^27.0.0" + pretty-format "^27.0.0" + +"@types/json-schema@^7.0.7": + version "7.0.8" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818" + integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg== + +"@types/marked@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/marked/-/marked-2.0.4.tgz#34a0ea548afe6e0c01095229d47b48b2af650613" + integrity sha512-L9VRSe0Id8xbPL99mUo/4aKgD7ZoRwFZqUQScNKHi2pFjF9ZYSMNShUHD6VlMT6J/prQq0T1mxuU25m3R7dFzg== + +"@types/minimatch@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + +"@types/minipass@*": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@types/minipass/-/minipass-2.2.1.tgz#a52138867c493ff14f07616efcbe2af7662b76fb" + integrity sha512-0bI74UwEJ+JjGqzkyoiCxLVGK5C3Vy5MYdDB6VCtUAulcrulHvqhIrQP9lh/gvMgaNzvvJljMW97rRHVvbTe8Q== + dependencies: + "@types/node" "*" + +"@types/mkdirp@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-1.0.2.tgz#8d0bad7aa793abe551860be1f7ae7f3198c16666" + integrity sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ== + dependencies: + "@types/node" "*" + +"@types/node@*": + version "16.4.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.3.tgz#c01c1a215721f6dec71b47d88b4687463601ba48" + integrity sha512-GKM4FLMkWDc0sfx7tXqPWkM6NBow1kge0fgQh0bOnlqo4iT1kvTvMEKE0c1RtUGnbLlGRXiAA8SumE//90uKAg== + +"@types/node@12.12.12": + version "12.12.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.12.tgz#529bc3e73dbb35dd9e90b0a1c83606a9d3264bdb" + integrity sha512-MGuvYJrPU0HUwqF7LqvIj50RZUX23Z+m583KBygKYUZLlZ88n6w28XRNJRJgsHukLEnLz6w6SvxZoLgbr5wLqQ== + +"@types/prettier@^2.1.5": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" + integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== + +"@types/semver@^7.3.4": + version "7.3.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.8.tgz#508a27995498d7586dcecd77c25e289bfaf90c59" + integrity sha512-D/2EJvAlCEtYFEYmmlGwbGXuK886HzyCc3nZX/tkFTQdEU8jZDAgiv08P162yB17y4ZXZoq7yFAnW4GDBb9Now== + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/tar@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tar/-/tar-4.0.5.tgz#5f953f183e36a15c6ce3f336568f6051b7b183f3" + integrity sha512-cgwPhNEabHaZcYIy5xeMtux2EmYBitfqEceBUi2t5+ETy4dW6kswt6WX4+HqLeiiKOo42EXbGiDmVJ2x+vi37Q== + dependencies: + "@types/minipass" "*" + "@types/node" "*" + +"@types/uuid@^8.3.0": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f" + integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg== + +"@types/which@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.2.tgz#9c246fc0c93ded311c8512df2891fb41f6227fdf" + integrity sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA== + +"@types/yargs-parser@*": + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^4.11.1": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz#8197f1473e7da8218c6a37ff308d695707835684" + integrity sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q== + dependencies: + "@typescript-eslint/experimental-utils" "4.28.5" + "@typescript-eslint/scope-manager" "4.28.5" + debug "^4.3.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@4.28.5", "@typescript-eslint/experimental-utils@^4.0.1": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz#66c28bef115b417cf9d80812a713e0e46bb42a64" + integrity sha512-bGPLCOJAa+j49hsynTaAtQIWg6uZd8VLiPcyDe4QPULsvQwLHGLSGKKcBN8/lBxIX14F74UEMK2zNDI8r0okwA== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.28.5" + "@typescript-eslint/types" "4.28.5" + "@typescript-eslint/typescript-estree" "4.28.5" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@^4.11.1": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.5.tgz#9c971668f86d1b5c552266c47788a87488a47d1c" + integrity sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw== + dependencies: + "@typescript-eslint/scope-manager" "4.28.5" + "@typescript-eslint/types" "4.28.5" + "@typescript-eslint/typescript-estree" "4.28.5" + debug "^4.3.1" + +"@typescript-eslint/scope-manager@4.28.5": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz#3a1b70c50c1535ac33322786ea99ebe403d3b923" + integrity sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ== + dependencies: + "@typescript-eslint/types" "4.28.5" + "@typescript-eslint/visitor-keys" "4.28.5" + +"@typescript-eslint/types@4.28.5": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.5.tgz#d33edf8e429f0c0930a7c3d44e9b010354c422e9" + integrity sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA== + +"@typescript-eslint/typescript-estree@4.28.5": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz#4906d343de693cf3d8dcc301383ed638e0441cd1" + integrity sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw== + dependencies: + "@typescript-eslint/types" "4.28.5" + "@typescript-eslint/visitor-keys" "4.28.5" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/visitor-keys@4.28.5": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz#ffee2c602762ed6893405ee7c1144d9cc0a29675" + integrity sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg== + dependencies: + "@typescript-eslint/types" "4.28.5" + eslint-visitor-keys "^2.0.0" + +abab@^2.0.3, abab@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.1.1, acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.2.4: + version "8.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c" + integrity sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.6.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.2.tgz#2fb45e0e5fcbc0813326c1c3da535d1881bb0571" + integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +babel-jest@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.0.6.tgz#e99c6e0577da2655118e3608b68761a5a69bd0d8" + integrity sha512-iTJyYLNc4wRofASmofpOc5NK9QunwMk+TLFgGXsTFS8uEqmd8wdI7sga0FPe2oVH3b5Agt/EAK1QjPEuKL8VfA== + dependencies: + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^27.0.6" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + +babel-plugin-istanbul@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" + integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^4.0.0" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.6.tgz#f7c6b3d764af21cb4a2a1ab6870117dbde15b456" + integrity sha512-CewFeM9Vv2gM7Yr9n5eyyLVPRSiBnk6lKZRjgwYnGKSl9M14TMn2vkN02wTF04OGuSDLEzlWiMzvjXuW9mB6Gw== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.0.6.tgz#909ef08e9f24a4679768be2f60a3df0856843f9d" + integrity sha512-WObA0/Biw2LrVVwZkF/2GqbOdzhKD6Fkdwhoy9ASIrOWr/zodcSpQh72JOkEn6NWyjmnPDjNSqaGN4KnpKzhXw== + dependencies: + babel-plugin-jest-hoist "^27.0.6" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" + integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk= + dependencies: + buffers "~0.1.1" + chainsaw "~0.1.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + +browserslist@^4.16.6: + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== + dependencies: + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" + escalade "^3.1.1" + node-releases "^1.1.71" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1, bser@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffers@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" + integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s= + +bytes@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + +caniuse-lite@^1.0.30001219: + version "1.0.30001247" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001247.tgz#105be7a8fb30cdd303275e769a9dfb87d4b3577a" + integrity sha512-4rS7co+7+AoOSPRPOPUt5/GdaqZc0EsUpWk66ofE3HJTAajUK2Ss2VwoNzVN69ghg8lYYlh0an0Iy4LIHHo9UQ== + +chainsaw@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" + integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg= + dependencies: + traverse ">=0.3.0 <0.4" + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" + integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +ci-info@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" + integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== + +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + +cli-table@^0.3.4: + version "0.3.6" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.6.tgz#e9d6aa859c7fe636981fd3787378c2a20bce92fc" + integrity sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ== + dependencies: + colors "1.0.3" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +comment-parser@^0.7.6: + version "0.7.6" + resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.6.tgz#0e743a53c8e646c899a1323db31f6cd337b10f12" + integrity sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +content-disposition@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + +date-format@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf" + integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA== + +date-format@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-3.0.0.tgz#eb8780365c7d2b1511078fb491e6479780f3ad95" + integrity sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w== + +debounce@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== + dependencies: + ms "2.1.2" + +decimal.js@^10.2.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723" + integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + +electron-to-chromium@^1.3.723: + version "1.3.787" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.787.tgz#0d814dcc374bb8a0ae7a17c0308c39fb18fcc7bb" + integrity sha512-zeM5AFwvTlSYvGpBaFZKVo7GQEWSk6hS3rQ7mdrr3qB7CiqVl84K6nIPznyKSu0b8ABiEeMEIqyBuzqMkxnjjg== + +emittery@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +esbuild@^0.12.7: + version "0.12.16" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.16.tgz#c397144ce13b445a6ead9c1f747da11f79ec5e67" + integrity sha512-XqI9cXP2bmQ6MREIqrYBb13KfYFSERsV1+e5jSVWps8dNlLZK+hln7d0mznzDIpfISsg/AgQW0DW3kSInXWhrg== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-plugin-jest@^24.1.3: + version "24.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.4.0.tgz#fa4b614dbd46a98b652d830377971f097bda9262" + integrity sha512-8qnt/hgtZ94E9dA6viqfViKBfkJwFHXgJmTWlMGDgunw1XJEGqm3eiPjDsTanM3/u/3Az82nyQM9GX7PM/QGmg== + dependencies: + "@typescript-eslint/experimental-utils" "^4.0.1" + +eslint-plugin-jsdoc@^30.7.13: + version "30.7.13" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-30.7.13.tgz#52e5c74fb806d3bbeb51d04a0c829508c3c6b563" + integrity sha512-YM4WIsmurrp0rHX6XiXQppqKB8Ne5ATiZLJe2+/fkp9l9ExXFr43BbAbjZaVrpCT+tuPYOZ8k1MICARHnURUNQ== + dependencies: + comment-parser "^0.7.6" + debug "^4.3.1" + jsdoctypeparser "^9.0.0" + lodash "^4.17.20" + regextras "^0.7.1" + semver "^7.3.4" + spdx-expression-parse "^3.0.1" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint@^7.15.0: + version "7.31.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.31.0.tgz#f972b539424bf2604907a970860732c5d99d3aca" + integrity sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.1.2" + globals "^13.6.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-lite@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/event-lite/-/event-lite-0.1.2.tgz#838a3e0fdddef8cc90f128006c8e55a4e4e4c11b" + integrity sha512-HnSYx1BsJ87/p6swwzv+2v6B4X+uxUteoDfRxsAb1S1BePzQqOLevVmkdA15GHJVd9A9Ok6wygUR18Hu0YeV9g== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + +expect@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.0.6.tgz#a4d74fbe27222c718fff68ef49d78e26a8fd4c05" + integrity sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw== + dependencies: + "@jest/types" "^27.0.6" + ansi-styles "^5.0.0" + jest-get-type "^27.0.6" + jest-matcher-utils "^27.0.6" + jest-message-util "^27.0.6" + jest-regex-util "^27.0.6" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.1.1: + version "3.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" + integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807" + integrity sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0, fb-watchman@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + +flatted@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.1.tgz#bbef080d95fca6709362c73044a1634f7c6e7d05" + integrity sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg== + +follow-redirects@^1.13.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" + integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.0.1: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.6.0, globals@^13.9.0: + version "13.10.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.10.0.tgz#60ba56c3ac2ca845cfbf4faeca727ad9dd204676" + integrity sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g== + dependencies: + type-fest "^0.20.2" + +globby@^11.0.3: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.8: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +int64-buffer@^0.1.9: + version "0.1.10" + resolved "https://registry.yarnpkg.com/int64-buffer/-/int64-buffer-0.1.10.tgz#277b228a87d95ad777d07c13832022406a473423" + integrity sha1-J3siiofZWtd30HwTgyAiQGpHNCM= + +is-ci@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.0.tgz#c7e7be3c9d8eef7d0fa144390bd1e4b88dc4c994" + integrity sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ== + dependencies: + ci-info "^3.1.1" + +is-core-module@^2.2.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" + integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +isarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +isuri@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/isuri/-/isuri-2.0.3.tgz#3437121db2fe65af0ba080b7e1a8636f632cca91" + integrity sha1-NDcSHbL+Za8LoIC34ahjb2MsypE= + dependencies: + rfc-3986 "1.0.1" + +jest-changed-files@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.0.6.tgz#bed6183fcdea8a285482e3b50a9a7712d49a7a8b" + integrity sha512-BuL/ZDauaq5dumYh5y20sn4IISnf1P9A0TDswTxUi84ORGtVa86ApuBHqICL0vepqAnZiY6a7xeSPWv2/yy4eA== + dependencies: + "@jest/types" "^27.0.6" + execa "^5.0.0" + throat "^6.0.1" + +jest-circus@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.0.6.tgz#dd4df17c4697db6a2c232aaad4e9cec666926668" + integrity sha512-OJlsz6BBeX9qR+7O9lXefWoc2m9ZqcZ5Ohlzz0pTEAG4xMiZUJoacY8f4YDHxgk0oKYxj277AfOk9w6hZYvi1Q== + dependencies: + "@jest/environment" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + expect "^27.0.6" + is-generator-fn "^2.0.0" + jest-each "^27.0.6" + jest-matcher-utils "^27.0.6" + jest-message-util "^27.0.6" + jest-runtime "^27.0.6" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + pretty-format "^27.0.6" + slash "^3.0.0" + stack-utils "^2.0.3" + throat "^6.0.1" + +jest-cli@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.0.6.tgz#d021e5f4d86d6a212450d4c7b86cb219f1e6864f" + integrity sha512-qUUVlGb9fdKir3RDE+B10ULI+LQrz+MCflEH2UJyoUjoHHCbxDrMxSzjQAPUMsic4SncI62ofYCcAvW6+6rhhg== + dependencies: + "@jest/core" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/types" "^27.0.6" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + import-local "^3.0.2" + jest-config "^27.0.6" + jest-util "^27.0.6" + jest-validate "^27.0.6" + prompts "^2.0.1" + yargs "^16.0.3" + +jest-config@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.0.6.tgz#119fb10f149ba63d9c50621baa4f1f179500277f" + integrity sha512-JZRR3I1Plr2YxPBhgqRspDE2S5zprbga3swYNrvY3HfQGu7p/GjyLOqwrYad97tX3U3mzT53TPHVmozacfP/3w== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^27.0.6" + "@jest/types" "^27.0.6" + babel-jest "^27.0.6" + chalk "^4.0.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.4" + is-ci "^3.0.0" + jest-circus "^27.0.6" + jest-environment-jsdom "^27.0.6" + jest-environment-node "^27.0.6" + jest-get-type "^27.0.6" + jest-jasmine2 "^27.0.6" + jest-regex-util "^27.0.6" + jest-resolve "^27.0.6" + jest-runner "^27.0.6" + jest-util "^27.0.6" + jest-validate "^27.0.6" + micromatch "^4.0.4" + pretty-format "^27.0.6" + +jest-diff@^27.0.0, jest-diff@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.0.6.tgz#4a7a19ee6f04ad70e0e3388f35829394a44c7b5e" + integrity sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.0.6" + jest-get-type "^27.0.6" + pretty-format "^27.0.6" + +jest-docblock@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3" + integrity sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA== + dependencies: + detect-newline "^3.0.0" + +jest-each@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.0.6.tgz#cee117071b04060158dc8d9a66dc50ad40ef453b" + integrity sha512-m6yKcV3bkSWrUIjxkE9OC0mhBZZdhovIW5ergBYirqnkLXkyEn3oUUF/QZgyecA1cF1QFyTE8bRRl8Tfg1pfLA== + dependencies: + "@jest/types" "^27.0.6" + chalk "^4.0.0" + jest-get-type "^27.0.6" + jest-util "^27.0.6" + pretty-format "^27.0.6" + +jest-environment-jsdom@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.0.6.tgz#f66426c4c9950807d0a9f209c590ce544f73291f" + integrity sha512-FvetXg7lnXL9+78H+xUAsra3IeZRTiegA3An01cWeXBspKXUhAwMM9ycIJ4yBaR0L7HkoMPaZsozCLHh4T8fuw== + dependencies: + "@jest/environment" "^27.0.6" + "@jest/fake-timers" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/node" "*" + jest-mock "^27.0.6" + jest-util "^27.0.6" + jsdom "^16.6.0" + +jest-environment-node@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.0.6.tgz#a6699b7ceb52e8d68138b9808b0c404e505f3e07" + integrity sha512-+Vi6yLrPg/qC81jfXx3IBlVnDTI6kmRr08iVa2hFCWmJt4zha0XW7ucQltCAPhSR0FEKEoJ3i+W4E6T0s9is0w== + dependencies: + "@jest/environment" "^27.0.6" + "@jest/fake-timers" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/node" "*" + jest-mock "^27.0.6" + jest-util "^27.0.6" + +jest-get-type@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.6.tgz#0eb5c7f755854279ce9b68a9f1a4122f69047cfe" + integrity sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg== + +jest-haste-map@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.0.6.tgz#4683a4e68f6ecaa74231679dca237279562c8dc7" + integrity sha512-4ldjPXX9h8doB2JlRzg9oAZ2p6/GpQUNAeiYXqcpmrKbP0Qev0wdZlxSMOmz8mPOEnt4h6qIzXFLDi8RScX/1w== + dependencies: + "@jest/types" "^27.0.6" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^27.0.6" + jest-serializer "^27.0.6" + jest-util "^27.0.6" + jest-worker "^27.0.6" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +jest-jasmine2@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.0.6.tgz#fd509a9ed3d92bd6edb68a779f4738b100655b37" + integrity sha512-cjpH2sBy+t6dvCeKBsHpW41mjHzXgsavaFMp+VWRf0eR4EW8xASk1acqmljFtK2DgyIECMv2yCdY41r2l1+4iA== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^27.0.6" + "@jest/source-map" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^27.0.6" + is-generator-fn "^2.0.0" + jest-each "^27.0.6" + jest-matcher-utils "^27.0.6" + jest-message-util "^27.0.6" + jest-runtime "^27.0.6" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + pretty-format "^27.0.6" + throat "^6.0.1" + +jest-leak-detector@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.0.6.tgz#545854275f85450d4ef4b8fe305ca2a26450450f" + integrity sha512-2/d6n2wlH5zEcdctX4zdbgX8oM61tb67PQt4Xh8JFAIy6LRKUnX528HulkaG6nD5qDl5vRV1NXejCe1XRCH5gQ== + dependencies: + jest-get-type "^27.0.6" + pretty-format "^27.0.6" + +jest-matcher-utils@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz#2a8da1e86c620b39459f4352eaa255f0d43e39a9" + integrity sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA== + dependencies: + chalk "^4.0.0" + jest-diff "^27.0.6" + jest-get-type "^27.0.6" + pretty-format "^27.0.6" + +jest-message-util@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.0.6.tgz#158bcdf4785706492d164a39abca6a14da5ab8b5" + integrity sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.0.6" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.4" + pretty-format "^27.0.6" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.0.6.tgz#0efdd40851398307ba16778728f6d34d583e3467" + integrity sha512-lzBETUoK8cSxts2NYXSBWT+EJNzmUVtVVwS1sU9GwE1DLCfGsngg+ZVSIe0yd0ZSm+y791esiuo+WSwpXJQ5Bw== + dependencies: + "@jest/types" "^27.0.6" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + +jest-regex-util@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.6.tgz#02e112082935ae949ce5d13b2675db3d8c87d9c5" + integrity sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ== + +jest-resolve-dependencies@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.0.6.tgz#3e619e0ef391c3ecfcf6ef4056207a3d2be3269f" + integrity sha512-mg9x9DS3BPAREWKCAoyg3QucCr0n6S8HEEsqRCKSPjPcu9HzRILzhdzY3imsLoZWeosEbJZz6TKasveczzpJZA== + dependencies: + "@jest/types" "^27.0.6" + jest-regex-util "^27.0.6" + jest-snapshot "^27.0.6" + +jest-resolve@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.0.6.tgz#e90f436dd4f8fbf53f58a91c42344864f8e55bff" + integrity sha512-yKmIgw2LgTh7uAJtzv8UFHGF7Dm7XfvOe/LQ3Txv101fLM8cx2h1QVwtSJ51Q/SCxpIiKfVn6G2jYYMDNHZteA== + dependencies: + "@jest/types" "^27.0.6" + chalk "^4.0.0" + escalade "^3.1.1" + graceful-fs "^4.2.4" + jest-pnp-resolver "^1.2.2" + jest-util "^27.0.6" + jest-validate "^27.0.6" + resolve "^1.20.0" + slash "^3.0.0" + +jest-runner@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.0.6.tgz#1325f45055539222bbc7256a6976e993ad2f9520" + integrity sha512-W3Bz5qAgaSChuivLn+nKOgjqNxM7O/9JOJoKDCqThPIg2sH/d4A/lzyiaFgnb9V1/w29Le11NpzTJSzga1vyYQ== + dependencies: + "@jest/console" "^27.0.6" + "@jest/environment" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-docblock "^27.0.6" + jest-environment-jsdom "^27.0.6" + jest-environment-node "^27.0.6" + jest-haste-map "^27.0.6" + jest-leak-detector "^27.0.6" + jest-message-util "^27.0.6" + jest-resolve "^27.0.6" + jest-runtime "^27.0.6" + jest-util "^27.0.6" + jest-worker "^27.0.6" + source-map-support "^0.5.6" + throat "^6.0.1" + +jest-runtime@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.0.6.tgz#45877cfcd386afdd4f317def551fc369794c27c9" + integrity sha512-BhvHLRVfKibYyqqEFkybsznKwhrsu7AWx2F3y9G9L95VSIN3/ZZ9vBpm/XCS2bS+BWz3sSeNGLzI3TVQ0uL85Q== + dependencies: + "@jest/console" "^27.0.6" + "@jest/environment" "^27.0.6" + "@jest/fake-timers" "^27.0.6" + "@jest/globals" "^27.0.6" + "@jest/source-map" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.4" + jest-haste-map "^27.0.6" + jest-message-util "^27.0.6" + jest-mock "^27.0.6" + jest-regex-util "^27.0.6" + jest-resolve "^27.0.6" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + jest-validate "^27.0.6" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^16.0.3" + +jest-serializer@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.0.6.tgz#93a6c74e0132b81a2d54623251c46c498bb5bec1" + integrity sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-snapshot@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.0.6.tgz#f4e6b208bd2e92e888344d78f0f650bcff05a4bf" + integrity sha512-NTHaz8He+ATUagUgE7C/UtFcRoHqR2Gc+KDfhQIyx+VFgwbeEMjeP+ILpUTLosZn/ZtbNdCF5LkVnN/l+V751A== + dependencies: + "@babel/core" "^7.7.2" + "@babel/generator" "^7.7.2" + "@babel/parser" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^27.0.6" + graceful-fs "^4.2.4" + jest-diff "^27.0.6" + jest-get-type "^27.0.6" + jest-haste-map "^27.0.6" + jest-matcher-utils "^27.0.6" + jest-message-util "^27.0.6" + jest-resolve "^27.0.6" + jest-util "^27.0.6" + natural-compare "^1.4.0" + pretty-format "^27.0.6" + semver "^7.3.2" + +jest-util@^27.0.0, jest-util@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.0.6.tgz#e8e04eec159de2f4d5f57f795df9cdc091e50297" + integrity sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ== + dependencies: + "@jest/types" "^27.0.6" + "@types/node" "*" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^3.0.0" + picomatch "^2.2.3" + +jest-validate@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.0.6.tgz#930a527c7a951927df269f43b2dc23262457e2a6" + integrity sha512-yhZZOaMH3Zg6DC83n60pLmdU1DQE46DW+KLozPiPbSbPhlXXaiUTDlhHQhHFpaqIFRrInko1FHXjTRpjWRuWfA== + dependencies: + "@jest/types" "^27.0.6" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^27.0.6" + leven "^3.1.0" + pretty-format "^27.0.6" + +jest-watcher@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.0.6.tgz#89526f7f9edf1eac4e4be989bcb6dec6b8878d9c" + integrity sha512-/jIoKBhAP00/iMGnTwUBLgvxkn7vsOweDrOTSPzc7X9uOyUtJIDthQBTI1EXz90bdkrxorUZVhJwiB69gcHtYQ== + dependencies: + "@jest/test-result" "^27.0.6" + "@jest/types" "^27.0.6" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^27.0.6" + string-length "^4.0.1" + +jest-worker@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.6.tgz#a5fdb1e14ad34eb228cfe162d9f729cdbfa28aed" + integrity sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.0.6.tgz#10517b2a628f0409087fbf473db44777d7a04505" + integrity sha512-EjV8aETrsD0wHl7CKMibKwQNQc3gIRBXlTikBmmHUeVMKaPFxdcUIBfoDqTSXDoGJIivAYGqCWVlzCSaVjPQsA== + dependencies: + "@jest/core" "^27.0.6" + import-local "^3.0.2" + jest-cli "^27.0.6" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsdoctypeparser@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz#8c97e2fb69315eb274b0f01377eaa5c940bd7b26" + integrity sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw== + +jsdom@^16.6.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json5@2.x, json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + +jsonc-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" + integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + +lodash@4.x, lodash@^4.17.20, lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log4js@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.3.0.tgz#10dfafbb434351a3e30277a00b9879446f715bcb" + integrity sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw== + dependencies: + date-format "^3.0.0" + debug "^4.1.1" + flatted "^2.0.1" + rfdc "^1.1.4" + streamroller "^2.2.4" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-error@1.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + +marked@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/marked/-/marked-2.1.3.tgz#bd017cef6431724fd4b27e0657f5ceb14bff3753" + integrity sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +mime-db@1.48.0: + version "1.48.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" + integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== + +mime-types@^2.1.12: + version "2.1.31" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" + integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== + dependencies: + mime-db "1.48.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minipass@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" + integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== + dependencies: + yallist "^4.0.0" + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +msgpack-lite@^0.1.26: + version "0.1.26" + resolved "https://registry.yarnpkg.com/msgpack-lite/-/msgpack-lite-0.1.26.tgz#dd3c50b26f059f25e7edee3644418358e2a9ad89" + integrity sha1-3TxQsm8FnyXn7e42REGDWOKprYk= + dependencies: + event-lite "^0.1.1" + ieee754 "^1.1.8" + int64-buffer "^0.1.9" + isarray "^1.0.0" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-modules-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= + +node-releases@^1.1.71: + version "1.1.73" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" + integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +p-each-series@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" + integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.0.4, picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + +pirates@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== + dependencies: + node-modules-regexp "^1.0.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +pretty-format@^27.0.0, pretty-format@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f" + integrity sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ== + dependencies: + "@jest/types" "^27.0.6" + ansi-regex "^5.0.0" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +prompts@^2.0.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.1.tgz#befd3b1195ba052f9fd2fde8a486c4e82ee77f61" + integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +psl@^1.1.33: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +regexpp@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regextras@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.7.1.tgz#be95719d5f43f9ef0b9fa07ad89b7c606995a3b2" + integrity sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rfc-3986@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rfc-3986/-/rfc-3986-1.0.1.tgz#eeeb88342fadbe8027c0f36ada921a13e6f96206" + integrity sha1-7uuINC+tvoAnwPNq2pIaE+b5YgY= + +rfdc@^1.1.4: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@5.1.2, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + +semver@7.x, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +source-map-support@^0.5.6: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz#8a595135def9592bda69709474f1cbeea7c2467f" + integrity sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +stack-utils@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" + integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== + dependencies: + escape-string-regexp "^2.0.0" + +streamroller@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-2.2.4.tgz#c198ced42db94086a6193608187ce80a5f2b0e53" + integrity sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ== + dependencies: + date-format "^2.1.0" + debug "^4.1.1" + fs-extra "^8.1.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" + integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +table@^6.0.9: + version "6.7.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" + integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== + dependencies: + ajv "^8.0.1" + lodash.clonedeep "^4.5.0" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" + +tar@^6.1.9: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +throat@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" + integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== + +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.1.2" + +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + +"traverse@>=0.3.0 <0.4": + version "0.3.9" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" + integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk= + +ts-jest@^27.0.5: + version "27.0.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.0.5.tgz#0b0604e2271167ec43c12a69770f0bb65ad1b750" + integrity sha512-lIJApzfTaSSbtlksfFNHkWOzLJuuSm4faFAfo5kvzOiRAuoN4/eKxVJ2zEAho8aecE04qX6K1pAzfH5QHL1/8w== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^27.0.0" + json5 "2.x" + lodash "4.x" + make-error "1.x" + semver "7.x" + yargs-parser "20.x" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@^4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" + integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== + +universalify@^0.1.0, universalify@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unzip-stream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/unzip-stream/-/unzip-stream-0.3.1.tgz#2333b5cd035d29db86fb701ca212cf8517400083" + integrity sha512-RzaGXLNt+CW+T41h1zl6pGz3EaeVhYlK+rdAap+7DxW5kqsqePO8kRtWPaCiVqdhZc86EctSPVYNix30YOMzmw== + dependencies: + binary "^0.3.0" + mkdirp "^0.5.1" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +v8-to-istanbul@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.0.0.tgz#4229f2a99e367f3f018fa1d5c2b8ec684667c69c" + integrity sha512-LkmXi8UUNxnCC+JlH7/fsfsKr5AU110l+SYGJimWNkWhxbN5EyeOtm1MJ0hhvqMMOhGwBj1Fp70Yv9i+hX0QAg== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +vscode-jsonrpc@6.0.0, vscode-jsonrpc@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e" + integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg== + +vscode-languageserver-protocol@3.16.0, vscode-languageserver-protocol@^3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821" + integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A== + dependencies: + vscode-jsonrpc "6.0.0" + vscode-languageserver-types "3.16.0" + +vscode-languageserver-textdocument@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f" + integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA== + +vscode-languageserver-types@3.16.0, vscode-languageserver-types@^3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== + +vscode-languageserver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz#49b068c87cfcca93a356969d20f5d9bdd501c6b0" + integrity sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw== + dependencies: + vscode-languageserver-protocol "3.16.0" + +vscode-uri@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" + integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== + +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +walker@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.4.6: + version "7.5.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" + integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.x, yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs@^16.0.3: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" diff --git a/vim-config/plugins/fugitive/.gitattributes b/vim-config/plugins/fugitive/.gitattributes new file mode 100644 index 00000000..50afa416 --- /dev/null +++ b/vim-config/plugins/fugitive/.gitattributes @@ -0,0 +1,2 @@ +.git* export-ignore +*.markdown export-ignore diff --git a/vim-config/plugins/fugitive/.github/FUNDING.yml b/vim-config/plugins/fugitive/.github/FUNDING.yml new file mode 100644 index 00000000..e2a49d11 --- /dev/null +++ b/vim-config/plugins/fugitive/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: tpope +custom: ["https://www.paypal.me/vimpope"] diff --git a/vim-config/plugins/fugitive/.gitignore b/vim-config/plugins/fugitive/.gitignore new file mode 100644 index 00000000..0a56e3fc --- /dev/null +++ b/vim-config/plugins/fugitive/.gitignore @@ -0,0 +1 @@ +/doc/tags diff --git a/vim-config/plugins/vim-fugitive/CONTRIBUTING.markdown b/vim-config/plugins/fugitive/CONTRIBUTING.markdown similarity index 100% rename from vim-config/plugins/vim-fugitive/CONTRIBUTING.markdown rename to vim-config/plugins/fugitive/CONTRIBUTING.markdown diff --git a/vim-config/plugins/vim-fugitive/README.markdown b/vim-config/plugins/fugitive/README.markdown similarity index 79% rename from vim-config/plugins/vim-fugitive/README.markdown rename to vim-config/plugins/fugitive/README.markdown index dd3bcc97..f572ce2f 100644 --- a/vim-config/plugins/vim-fugitive/README.markdown +++ b/vim-config/plugins/fugitive/README.markdown @@ -36,11 +36,11 @@ Additional commands are provided for higher level operations: * View any blob, tree, commit, or tag in the repository with `:Gedit` (and `:Gsplit`, etc.). For example, `:Gedit HEAD~3:%` loads the current file as it existed 3 commits ago. -* `:Gdiffsplit` brings up the staged version of the file side by side with the - working tree version. Use Vim's diff handling capabilities to apply changes - to the staged version, and write that buffer to stage the changes. You can - also give an arbitrary `:Gedit` argument to diff against older versions of - the file. +* `:Gdiffsplit` (or `:Gvdiffsplit`) brings up the staged version of the file + side by side with the working tree version. Use Vim's diff handling + capabilities to apply changes to the staged version, and write that buffer + to stage the changes. You can also give an arbitrary `:Gedit` argument to + diff against older versions of the file. * `:Gread` is a variant of `git checkout -- filename` that operates on the buffer rather than the file itself. This means you can use `u` to undo it and you never get any warnings about the file changing outside Vim. @@ -58,8 +58,9 @@ Additional commands are provided for higher level operations: hosting provider, with optional line range (try it in visual mode). Plugins are available for popular providers such as [GitHub][rhubarb.vim], [GitLab][fugitive-gitlab.vim], [Bitbucket][fubitive.vim], - [Gitee][fugitive-gitee.vim], [Pagure][pagure], and - [Phabricator][vim-phabricator]. + [Gitee][fugitive-gitee.vim], [Pagure][pagure], + [Phabricator][vim-phabricator], [Azure DevOps][fugitive-azure-devops.vim], + and [sourcehut][srht.vim]. [rhubarb.vim]: https://github.com/tpope/vim-rhubarb [fugitive-gitlab.vim]: https://github.com/shumphrey/fugitive-gitlab.vim @@ -67,6 +68,8 @@ Additional commands are provided for higher level operations: [fugitive-gitee.vim]: https://github.com/linuxsuren/fugitive-gitee.vim [pagure]: https://github.com/FrostyX/vim-fugitive-pagure [vim-phabricator]: https://github.com/jparise/vim-phabricator +[fugitive-azure-devops.vim]: https://github.com/cedarbaum/fugitive-azure-devops.vim +[srht.vim]: https://git.sr.ht/~willdurand/srht.vim Add `%{FugitiveStatusline()}` to `'statusline'` to get an indicator with the current branch in your statusline. @@ -92,19 +95,20 @@ Install using your favorite package manager, or use Vim's built-in package suppo ## FAQ -> Why can't I enter my password when I `:Git push`? +> What happened to the dispatch.vim backed asynchronous `:Gpush` and +> `:Gfetch`? -It is highly recommended to use SSH keys or [credentials caching][] to avoid -entering your password on every upstream interaction. If this isn't an -option, the official solution is to use the `core.askPass` Git option to -request the password via a GUI. Fugitive will configure this for you -automatically if you have `ssh-askpass` or `git-gui` installed; otherwise it's -your responsibility to set this up. +This behavior was divisive, confusing, and complicated inputting passwords, so +it was removed. Use `:Git! push` to use Fugitive's own asynchronous +execution, or retroactively make `:Git push` asynchronous by pressing +`CTRL-D`. -If you absolutely must type in your password by hand, sidestep Fugitive and -use `:terminal git push`. +> So I have a symlink and... -[credentials caching]: https://help.github.com/en/articles/caching-your-github-password-in-git +Stop. Just stop. If Git won't deal with your symlink, then Fugitive won't +either. Consider using a [plugin that resolves +symlinks](https://github.com/aymericbeaumet/symlink.vim), or even better, +using fewer symlinks. ## Self-Promotion diff --git a/vim-config/plugins/vim-fugitive/autoload/fugitive.vim b/vim-config/plugins/fugitive/autoload/fugitive.vim similarity index 61% rename from vim-config/plugins/vim-fugitive/autoload/fugitive.vim rename to vim-config/plugins/fugitive/autoload/fugitive.vim index 7b59f139..56badb51 100644 --- a/vim-config/plugins/vim-fugitive/autoload/fugitive.vim +++ b/vim-config/plugins/fugitive/autoload/fugitive.vim @@ -1,17 +1,14 @@ " Location: autoload/fugitive.vim " Maintainer: Tim Pope +" The functions contained within this file are for internal use only. For the +" official API, see the commented functions in plugin/fugitive.vim. + if exists('g:autoloaded_fugitive') finish endif let g:autoloaded_fugitive = 1 -if !exists('g:fugitive_git_executable') - let g:fugitive_git_executable = 'git' -elseif g:fugitive_git_executable =~# '^\w\+=' - let g:fugitive_git_executable = 'env ' . g:fugitive_git_executable -endif - " Section: Utility function! s:function(name) abort @@ -41,13 +38,21 @@ function! s:Uniq(list) abort return a:list endfunction +function! s:JoinChomp(list) abort + if empty(a:list[-1]) + return join(a:list[0:-2], "\n") + else + return join(a:list, "\n") + endif +endfunction + function! s:winshell() abort return has('win32') && &shellcmdflag !~# '^-' endfunction function! s:WinShellEsc(arg) abort if type(a:arg) == type([]) - return join(map(copy(a:arg), 's:shellesc(v:val)')) + return join(map(copy(a:arg), 's:WinShellEsc(v:val)')) elseif a:arg =~# '^[A-Za-z0-9_/:.-]\+$' return a:arg else @@ -82,8 +87,32 @@ function! s:throw(string) abort throw 'fugitive: '.a:string endfunction +function! s:VersionCheck() abort + if v:version < 703 + return 'return ' . string('echoerr "fugitive: Vim 7.3 or newer required"') + elseif empty(fugitive#GitVersion()) + let exe = get(s:GitCmd(), 0, '') + if len(exe) && !executable(exe) + return 'return ' . string('echoerr "fugitive: cannot find ' . string(exe) . ' in PATH"') + endif + return 'return ' . string('echoerr "fugitive: cannot execute Git"') + elseif !fugitive#GitVersion(1, 8, 5) + return 'return ' . string('echoerr "fugitive: Git 1.8.5 or newer required"') + else + return '' + endif +endfunction + +let s:worktree_error = "core.worktree is required when using an external Git dir" function! s:DirCheck(...) abort - if !empty(a:0 ? s:Dir(a:1) : s:Dir()) + let vcheck = s:VersionCheck() + if !empty(vcheck) + return vcheck + endif + let dir = call('FugitiveGitDir', a:000) + if !empty(dir) && FugitiveWorkTree(dir, 1) is# 0 + return 'return ' . string('echoerr "fugitive: ' . s:worktree_error . '"') + elseif !empty(dir) return '' elseif empty(bufname('')) return 'return ' . string('echoerr "fugitive: working directory does not belong to a Git repository"') @@ -96,18 +125,28 @@ function! s:Mods(mods, ...) abort let mods = substitute(a:mods, '\C', '', '') let mods = mods =~# '\S$' ? mods . ' ' : mods if a:0 && mods !~# '\<\%(aboveleft\|belowright\|leftabove\|rightbelow\|topleft\|botright\|tab\)\>' - let mods = a:1 . ' ' . mods + if a:1 ==# 'Edge' + if mods =~# '\' ? &splitright : &splitbelow + let mods = 'botright ' . mods + else + let mods = 'topleft ' . mods + endif + else + let mods = a:1 . ' ' . mods + endif endif return substitute(mods, '\s\+', ' ', 'g') endfunction -function! s:Slash(path) abort - if exists('+shellslash') +if exists('+shellslash') + function! s:Slash(path) abort return tr(a:path, '\', '/') - else + endfunction +else + function! s:Slash(path) abort return a:path - endif -endfunction + endfunction +endif function! s:Resolve(path) abort let path = resolve(a:path) @@ -146,66 +185,251 @@ endif function! s:TempScript(...) abort let body = join(a:000, "\n") if !has_key(s:temp_scripts, body) - let temp = tempname() . '.sh' + let s:temp_scripts[body] = tempname() . '.sh' + endif + let temp = s:temp_scripts[body] + if !filereadable(temp) call writefile(['#!/bin/sh'] + a:000, temp) - let s:temp_scripts[body] = temp endif - return FugitiveGitPath(s:temp_scripts[body]) + return FugitiveGitPath(temp) endfunction -function! s:DoAutocmd(cmd) abort +function! s:DoAutocmd(...) abort if v:version >= 704 || (v:version == 703 && has('patch442')) - return 'doautocmd ' . a:cmd + return join(map(copy(a:000), "'doautocmd ' . v:val"), '|') elseif &modelines > 0 - return 'try|set modelines=0|doautocmd ' . a:cmd . '|finally|set modelines=' . &modelines . '|endtry' + return 'try|set modelines=0|' . join(map(copy(a:000), "'doautocmd ' . v:val"), '|') . '|finally|set modelines=' . &modelines . '|endtry' else - return 'doautocmd ' . a:cmd + return join(map(copy(a:000), "'doautocmd ' . v:val"), '|') endif endfunction let s:nowait = v:version >= 704 ? '' : '' function! s:Map(mode, lhs, rhs, ...) abort + let maps = [] for mode in split(a:mode, '\zs') + let skip = 0 let flags = (a:0 ? a:1 : '') . (a:rhs =~# '' ? '' : '