coc-vscode-loader 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,136 @@
1
+ import * as fs from 'fs'
2
+ import * as path from 'path'
3
+
4
+ export interface ScanResult {
5
+ files: ScannedFile[]
6
+ hasTsBridge: boolean
7
+ hasDecoration: boolean
8
+ hasWebview: boolean
9
+ summary: string
10
+ }
11
+
12
+ export interface ScannedFile {
13
+ path: string
14
+ apis: string[]
15
+ actions: string[]
16
+ }
17
+
18
+ const UNSUPPORTED_PATTERNS = [
19
+ { pattern: 'createTextEditorDecorationType', action: 'mark-unsupported', label: 'decoration API' },
20
+ { pattern: 'setDecorations', action: 'mark-unsupported', label: 'decoration API' },
21
+ { pattern: 'createWebviewPanel', action: 'mark-unsupported', label: 'webview API' },
22
+ { pattern: 'registerTreeDataProvider', action: 'mark-unsupported', label: 'tree data provider' },
23
+ { pattern: 'window.showInputBox', action: 'needs-rewrite', label: 'use requestInput instead' },
24
+ { pattern: 'env.openExternal', action: 'mark-unsupported', label: 'no equivalent' },
25
+ { pattern: 'showOpenDialog', action: 'mark-unsupported', label: 'no equivalent' },
26
+ { pattern: 'showSaveDialog', action: 'mark-unsupported', label: 'no equivalent' },
27
+ ]
28
+
29
+ const TS_BRIDGE_PATTERNS = [
30
+ 'tsserver/request',
31
+ 'tsserver/response',
32
+ '_vue:',
33
+ 'typescript.tsserverRequest',
34
+ ]
35
+
36
+ export function scan(dir: string): ScanResult {
37
+ const files: ScannedFile[] = []
38
+ let hasTsBridge = false
39
+ let hasDecoration = false
40
+ let hasWebview = false
41
+
42
+ const tsFiles = walk(dir).filter(f => f.endsWith('.ts') || f.endsWith('.tsx'))
43
+
44
+ for (const filePath of tsFiles) {
45
+ const content = fs.readFileSync(filePath, 'utf-8')
46
+ const apis: string[] = []
47
+ const actions: string[] = []
48
+ const relative = path.relative(dir, filePath)
49
+
50
+ // Check for vscode imports
51
+ if (content.includes("from 'vscode'") || content.includes('from "vscode"') || content.includes('require("vscode")')) {
52
+ apis.push('vscode')
53
+ }
54
+
55
+ // Check for unsupported patterns
56
+ for (const { pattern, action, label } of UNSUPPORTED_PATTERNS) {
57
+ if (content.includes(pattern)) {
58
+ apis.push(label)
59
+ actions.push(action)
60
+ if (action === 'mark-unsupported') {
61
+ if (label.includes('decoration')) hasDecoration = true
62
+ if (label.includes('webview')) hasWebview = true
63
+ }
64
+ }
65
+ }
66
+
67
+ // Check for TS bridge
68
+ for (const pattern of TS_BRIDGE_PATTERNS) {
69
+ if (content.includes(pattern)) {
70
+ hasTsBridge = true
71
+ apis.push('tsserver bridge')
72
+ break
73
+ }
74
+ }
75
+
76
+ // Check for LanguageClient
77
+ if (content.includes('LanguageClient')) {
78
+ apis.push('LanguageClient')
79
+ }
80
+
81
+ // Check for typescriptServerPlugins in package.json
82
+ if (relative === 'package.json' || filePath.endsWith('package.json')) {
83
+ if (content.includes('typescriptServerPlugins')) {
84
+ hasTsBridge = true
85
+ apis.push('typescriptServerPlugins')
86
+ }
87
+ }
88
+
89
+ if (apis.length > 0) {
90
+ files.push({ path: relative, apis, actions })
91
+ }
92
+ }
93
+
94
+ // Read package.json
95
+ const pkgPath = path.join(dir, 'package.json')
96
+ if (fs.existsSync(pkgPath)) {
97
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
98
+ const apis: string[] = []
99
+ if (pkg.contributes?.typescriptServerPlugins) {
100
+ hasTsBridge = true
101
+ apis.push('typescriptServerPlugins')
102
+ }
103
+ if (pkg.activationEvents) {
104
+ apis.push(`activationEvents: ${pkg.activationEvents.length}`)
105
+ }
106
+ if (apis.length > 0) {
107
+ files.push({ path: 'package.json', apis, actions: [] })
108
+ }
109
+ }
110
+
111
+ return {
112
+ files,
113
+ hasTsBridge,
114
+ hasDecoration,
115
+ hasWebview,
116
+ summary: [
117
+ `found ${files.length} files with vscode API`,
118
+ hasTsBridge ? ', ts-bridge detected' : '',
119
+ hasDecoration ? ', decoration API (marked)' : '',
120
+ hasWebview ? ', webview API (marked)' : '',
121
+ ].join(''),
122
+ }
123
+ }
124
+
125
+ function walk(dir: string): string[] {
126
+ const files: string[] = []
127
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
128
+ const p = path.join(dir, entry.name)
129
+ if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
130
+ files.push(...walk(p))
131
+ } else if (entry.isFile()) {
132
+ files.push(p)
133
+ }
134
+ }
135
+ return files
136
+ }
@@ -0,0 +1,54 @@
1
+ import { Transform } from '../types.js'
2
+ import { SyntaxKind } from 'ts-morph'
3
+
4
+ const FACTORY_TYPES = new Set([
5
+ 'Position', 'Range', 'Location', 'LocationLink',
6
+ 'Diagnostic', 'DiagnosticRelatedInformation',
7
+ 'TextEdit',
8
+ 'Hover', 'CompletionItem', 'CompletionList',
9
+ 'CodeAction', 'CodeLens', 'DocumentLink',
10
+ 'Color', 'ColorInformation', 'ColorPresentation',
11
+ 'FoldingRange', 'SelectionRange',
12
+ 'DocumentHighlight', 'SymbolInformation', 'DocumentSymbol',
13
+ 'ParameterInformation', 'SignatureInformation',
14
+ 'CallHierarchyItem', 'CallHierarchyIncomingCall', 'CallHierarchyOutgoingCall',
15
+ 'TypeHierarchyItem', 'LinkedEditingRanges',
16
+ ])
17
+
18
+ export const transformClassToFactory: Transform = (ctx) => {
19
+ const { file } = ctx
20
+
21
+ // AST approach: try to replace via ts-morph
22
+ const nodes = file.getDescendantsOfKind(SyntaxKind.NewExpression)
23
+ const astReplacements: Array<{ node: any, text: string }> = []
24
+ for (const expr of nodes) {
25
+ const text = expr.getText()
26
+ const m = text.match(/^new\s+(\w+)\(/)
27
+ if (!m || !FACTORY_TYPES.has(m[1])) continue
28
+ const args = text.slice(m[0].length, -1)
29
+ astReplacements.push({ node: expr, text: `${m[1]}.create(${args})` })
30
+ }
31
+ for (const { node, text } of astReplacements) {
32
+ try { node.replaceWithText(text) } catch {}
33
+ }
34
+
35
+ // Text fallback: catch remaining new Xxx() that AST might have missed
36
+ let text = file.getText()
37
+ text = text.replace(
38
+ /\bnew\s+(Position|Range|Location|Diagnostic|TextEdit)\s*\(/g,
39
+ (match, type) => `${type}.create(`
40
+ )
41
+
42
+ // CompletionItem.create(label) doesn't accept kind in coc.
43
+ // Convert `CompletionItem.create(label, kind)` to `item = CompletionItem.create(label); item.kind = kind`
44
+ text = text.replace(
45
+ /const\s+(\w+)\s*=\s*CompletionItem\.create\(([^,]+),\s*([^)]+)\)/g,
46
+ (_, varName, label, kind) => {
47
+ return `const ${varName} = CompletionItem.create(${label}); ${varName}.kind = ${kind}`
48
+ }
49
+ )
50
+
51
+ if (text !== file.getText()) {
52
+ file.replaceWithText(text)
53
+ }
54
+ }
@@ -0,0 +1,49 @@
1
+ import { Transform } from '../types.js'
2
+
3
+ /**
4
+ * Handle enum value offsets between VS Code (0-based) and coc (1-based LSP).
5
+ * Some enums like DiagnosticSeverity, CompletionItemKind, SymbolKind have
6
+ * different numeric values, but since coc re-exports them with correct values,
7
+ * symbol references (like CompletionItemKind.Value) work correctly at runtime.
8
+ *
9
+ * This transform handles cases where hardcoded numbers are used instead of
10
+ * enum symbols, which is rare but can happen in extensions.
11
+ *
12
+ * Affected enums and their offset:
13
+ * CompletionItemKind: vscode Text=0 → coc Text:1 (differs by 1 for first ~11 values)
14
+ * SymbolKind: vscode File=0 → coc File:1
15
+ * DocumentHighlightKind: vscode Text=0 → coc Text:1
16
+ * DiagnosticSeverity: vscode Error=0 → coc Error:1
17
+ */
18
+ export const transformEnumOffset: Transform = (ctx) => {
19
+ const { file } = ctx
20
+ let content = file.getText()
21
+
22
+ // Detect hardcoded numbers used in enum position (e.g., CompletionItemKind.Xxx).
23
+ // This is hard to detect perfectly, so we log a note when numeric literals
24
+ // appear near enum-type names.
25
+ const enumPatterns = [
26
+ 'CompletionItemKind', 'SymbolKind', 'DocumentHighlightKind', 'DiagnosticSeverity',
27
+ 'CompletionTriggerKind', 'InlineCompletionTriggerKind',
28
+ ]
29
+
30
+ for (const enumName of enumPatterns) {
31
+ // Check if the enum is imported/used with a hardcoded number nearby
32
+ const enumRefs = content.match(new RegExp(`${enumName}\\.\\w+`, 'g'))
33
+ if (enumRefs) {
34
+ // Symbol references are fine - they resolve at runtime
35
+ // Only note if there are raw numbers being compared
36
+ }
37
+ }
38
+
39
+ // Replace any numeric enum comparisons with comments
40
+ // e.g., `severity === 0` → `severity === 0 /* DiagnosticSeverity.Error = 1 in coc */`
41
+ content = content.replace(
42
+ /(severity\s*[=!]==?\s*)(\d+)/g,
43
+ '$1$2 /* DiagnosticSeverity values differ in coc (1-4 vs 0-3) */'
44
+ )
45
+
46
+ if (content !== file.getText()) {
47
+ file.replaceWithText(content)
48
+ }
49
+ }
@@ -0,0 +1,47 @@
1
+ import { Transform } from '../types.js'
2
+
3
+ /**
4
+ * Replace `from 'vscode'` with `from 'coc.nvim'`,
5
+ * and apply name remapping for known API differences.
6
+ */
7
+ const MAPPINGS: Record<string, string> = {
8
+ // namespace
9
+ 'vscode': 'coc.nvim',
10
+
11
+ // naming differences
12
+ 'EventEmitter': 'Emitter',
13
+ 'Disposable': 'Disposable',
14
+
15
+ // function/method renames
16
+ 'getExtension': 'getExtensionById',
17
+ 'registerReferenceProvider': 'registerReferencesProvider',
18
+ 'registerCodeActionsProvider': 'registerCodeActionProvider',
19
+ 'registerColorProvider': 'registerDocumentColorProvider',
20
+ 'registerDocumentFormattingEditProvider': 'registerDocumentFormatProvider',
21
+ 'registerDocumentRangeFormattingEditProvider': 'registerDocumentRangeFormatProvider',
22
+ }
23
+
24
+ export const transformImportMapping: Transform = (ctx) => {
25
+ const { file } = ctx
26
+
27
+ // Rewrite import declarations
28
+ file.getImportDeclarations().forEach(decl => {
29
+ const mod = decl.getModuleSpecifierValue()
30
+ if (mod === 'vscode') {
31
+ decl.setModuleSpecifier('coc.nvim')
32
+ }
33
+ })
34
+
35
+ // Rewrite named references
36
+ file.getDescendantsOfKind(192 /* Identifier */).forEach(node => {
37
+ const text = node.getText()
38
+ const mapped = MAPPINGS[text]
39
+ if (mapped && mapped !== text) {
40
+ // Only replace if it's a direct reference, not part of a string
41
+ const parent = node.getParent()
42
+ if (parent && parent.getKindName() !== 'StringLiteral') {
43
+ node.replaceWithText(mapped)
44
+ }
45
+ }
46
+ })
47
+ }
@@ -0,0 +1,48 @@
1
+ import { Transform } from '../types.js'
2
+
3
+ /**
4
+ * Adapt LanguageClient construction from VS Code style to coc style.
5
+ *
6
+ * VS Code:
7
+ * new LanguageClient('id', 'name', serverOptions, clientOptions)
8
+ * serverOptions = { run: { module, transport }, debug: { module, transport } }
9
+ *
10
+ * coc:
11
+ * new LanguageClient('id', 'name', serverOptions, clientOptions)
12
+ * serverOptions = { module, transport, options? }
13
+ */
14
+ export const transformLanguageClient: Transform = (ctx) => {
15
+ const { file } = ctx
16
+
17
+ file.getDescendantsOfKind(199 /* CallExpression */).forEach(call => {
18
+ const text = call.getText()
19
+
20
+ // Match: new LanguageClient(...)
21
+ if (!text.startsWith('new LanguageClient(')) return
22
+
23
+ // Extract serverOptions argument (3rd positional arg)
24
+ const args = call.getArguments()
25
+ if (args.length < 3) return
26
+
27
+ const serverOpts = args[2].getText()
28
+
29
+ // Check if it has the VS Code style { run, debug } structure
30
+ if (!serverOpts.includes('run:') || !serverOpts.includes('debug:')) return
31
+
32
+ // Extract module and transport from run block
33
+ const moduleMatch = serverOpts.match(/module:\s*(\S+)/)
34
+ const transportMatch = serverOpts.match(/transport:\s*(\S+)/)
35
+
36
+ if (!moduleMatch) return
37
+
38
+ // Build coc-style serverOptions
39
+ let cocOpts = `{\n module: ${moduleMatch[1]}`
40
+ if (transportMatch) {
41
+ cocOpts += `,\n transport: ${transportMatch[1]}`
42
+ }
43
+ cocOpts += '\n }'
44
+
45
+ // Replace the argument
46
+ args[2].replaceWithText(cocOpts)
47
+ })
48
+ }
@@ -0,0 +1,55 @@
1
+ import { Transform } from '../types.js'
2
+
3
+ /**
4
+ * Adapt provider registration function signatures.
5
+ *
6
+ * registerCompletionItemProvider(sel, p, t) → registerCompletionItemProvider('name', 'sc', sel, p, [t])
7
+ * registerCodeActionsProvider(sel, p, m?) → registerCodeActionProvider(sel, p, clientId?, kinds?)
8
+ * registerReferenceProvider(sel, p) → registerReferencesProvider(sel, p)
9
+ * registerDocumentFormattingEditProvider → registerDocumentFormatProvider(sel, p, priority?)
10
+ * registerColorProvider → registerDocumentColorProvider(sel, p)
11
+ */
12
+ const RENAMES: Record<string, string> = {
13
+ registerCodeActionsProvider: 'registerCodeActionProvider',
14
+ registerReferenceProvider: 'registerReferencesProvider',
15
+ registerDocumentFormattingEditProvider: 'registerDocumentFormatProvider',
16
+ registerDocumentRangeFormattingEditProvider: 'registerDocumentRangeFormatProvider',
17
+ registerColorProvider: 'registerDocumentColorProvider',
18
+ }
19
+
20
+ export const transformProviderRegister: Transform = (ctx) => {
21
+ let { file } = ctx
22
+ let content = file.getText()
23
+ let changed = false
24
+
25
+ // 1. Simple renames
26
+ for (const [from, to] of Object.entries(RENAMES)) {
27
+ const re = new RegExp(`\\b${from}\\b`, 'g')
28
+ if (re.test(content)) {
29
+ content = content.replace(re, to)
30
+ changed = true
31
+ }
32
+ }
33
+
34
+ // 2. registerCompletionItemProvider: insert name + shortcut at beginning
35
+ if (content.includes('registerCompletionItemProvider')) {
36
+ content = content.replace(
37
+ /registerCompletionItemProvider\(/g,
38
+ `registerCompletionItemProvider('plugin', 'PL', `
39
+ )
40
+ // Wrap the last argument in an array if it's a string (trigger chars)
41
+ content = content.replace(
42
+ /(registerCompletionItemProvider\([^)]+),\s*'([^']+)'\)/g,
43
+ '$1, ["$2"])'
44
+ )
45
+ content = content.replace(
46
+ /(registerCompletionItemProvider\([^)]+),\s*"([^"]+)"\)/g,
47
+ '$1, ["$2"])'
48
+ )
49
+ changed = true
50
+ }
51
+
52
+ if (changed) {
53
+ file.replaceWithText(content)
54
+ }
55
+ }
@@ -0,0 +1,8 @@
1
+ import { Project, SourceFile } from 'ts-morph'
2
+
3
+ export interface TransformContext {
4
+ file: SourceFile
5
+ project: Project
6
+ }
7
+
8
+ export type Transform = (ctx: TransformContext) => void
package/lib/index.js CHANGED
@@ -39,7 +39,7 @@ var require_package = __commonJS({
39
39
  "package.json"(exports2, module2) {
40
40
  module2.exports = {
41
41
  name: "coc-vscode-loader",
42
- version: "1.1.2",
42
+ version: "1.1.4",
43
43
  description: "Run VS Code extensions seamlessly in coc.nvim",
44
44
  main: "lib/index.js",
45
45
  keywords: [
@@ -58,6 +58,12 @@ var require_package = __commonJS({
58
58
  url: "https://github.com/coc-plugin/coc-vscode-loader/issues"
59
59
  },
60
60
  homepage: "https://www.npmjs.com/package/coc-vscode-loader",
61
+ files: [
62
+ "lib/",
63
+ "converter/src/",
64
+ "converter/package.json",
65
+ "assets/"
66
+ ],
61
67
  license: "MIT",
62
68
  engines: {
63
69
  coc: ">= 0.0.80"
@@ -157,8 +163,8 @@ async function updateRegistry() {
157
163
  return data.length;
158
164
  }
159
165
  function satisfiesVersion(required) {
160
- const a = pluginVersion().split(".").map(Number);
161
- const b = required.split(".").map(Number);
166
+ const a = pluginVersion().replace(/-.*$/, "").split(".").map(Number);
167
+ const b = required.replace(/-.*$/, "").split(".").map(Number);
162
168
  for (let i = 0; i < Math.max(a.length, b.length); i++) {
163
169
  const va = a[i] || 0, vb = b[i] || 0;
164
170
  if (va > vb) return true;
@@ -433,10 +439,15 @@ async function run(cmd, args, cwd, onLine) {
433
439
  };
434
440
  child.stdout.on("data", handler);
435
441
  child.stderr.on("data", handler);
442
+ let stderrBuf = "";
443
+ child.stderr.on("data", (d) => {
444
+ stderrBuf += d.toString();
445
+ });
436
446
  child.on("close", (code) => {
437
447
  clearTimeout(timer);
438
448
  if (code === 0) resolve2();
439
- else reject(new Error(`${cmd} ${args.join(" ")} exited with code ${code}`));
449
+ else reject(new Error(`${cmd} ${args.join(" ")} exited with code ${code}
450
+ ${stderrBuf.trim()}`));
440
451
  });
441
452
  child.on("error", (e) => {
442
453
  clearTimeout(timer);
@@ -500,7 +511,17 @@ async function buildPackage(name, inputDir, info, onProgress) {
500
511
  }
501
512
  if (!pythonBin) throw new Error("python3 not found, cannot install pip packages: " + info.pipPackages.join(", "));
502
513
  const pipArgs = ["-m", "pip", "install"];
503
- if (process.platform === "linux") pipArgs.push("--break-system-packages");
514
+ if (process.platform === "linux" || process.platform === "darwin") {
515
+ try {
516
+ const verOut = await runWithOutput(pythonBin, ["--version"], build);
517
+ const m = verOut.match(/^Python\s+(\d+)\.(\d+)/);
518
+ if (m) {
519
+ const pyMajor = parseInt(m[1]), pyMinor = parseInt(m[2]);
520
+ if (pyMajor > 3 || pyMajor === 3 && pyMinor >= 11) pipArgs.push("--break-system-packages");
521
+ }
522
+ } catch {
523
+ }
524
+ }
504
525
  onProgress(3, 5, "Installing pip packages...", `${pythonBin} -m pip install ${info.pipPackages.join(" ")}`);
505
526
  await run(pythonBin, pipArgs.concat(...info.pipPackages), build, pipLog);
506
527
  }
@@ -577,6 +598,10 @@ async function buildPackage(name, inputDir, info, onProgress) {
577
598
  /try\s*\{[^}]*?require\.resolve\([^)]+\)\s*;?\s*\}\s*catch\s*\{\s*\}/g,
578
599
  `try { serverModule = ${serverPath} } catch {}`
579
600
  );
601
+ code = code.replace(
602
+ /let\s+serverModule\s*=\s*config\.get\([^)]+\)\s*;?\s*/g,
603
+ `let serverModule = ${serverPath};`
604
+ );
580
605
  fs3.writeFileSync(indexPath, code);
581
606
  }
582
607
  } catch (e) {
@@ -591,7 +616,6 @@ async function buildPackage(name, inputDir, info, onProgress) {
591
616
  /documentSelector:\s*\[\s*\{[^}]*?language:\s*['"][^'"]*['"][^}]*\}\s*\]/,
592
617
  `documentSelector: [${langSelector}]`
593
618
  );
594
- code = code.replace(/serverModule\s*=\s*require\("path"\)\.join\(_dir,\s*_entry\);\s*/g, "");
595
619
  code = code.replace(
596
620
  /client\.start\(\);/g,
597
621
  "client.start().catch(() => {/* init may complete async */});"
@@ -625,6 +649,7 @@ async function installToCoc(name, onProgress) {
625
649
  fs3.cpSync(src, dest, { recursive: true });
626
650
  const pkgPath = extensionsPkgPath();
627
651
  const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
652
+ pkg.dependencies = pkg.dependencies || {};
628
653
  const depName = `coc-${name}`;
629
654
  if (!pkg.dependencies[depName]) {
630
655
  pkg.dependencies[depName] = `file:${dest}`;
@@ -697,6 +722,7 @@ async function uninstallPackage(state, name) {
697
722
  state.setPackageStatus(name, "uninstalling", { progress: "[2/3] Removing from package.json..." });
698
723
  const pkgPath = extensionsPkgPath();
699
724
  const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
725
+ pkg.dependencies = pkg.dependencies || {};
700
726
  const depName = `coc-${name}`;
701
727
  if (pkg.dependencies[depName]) {
702
728
  delete pkg.dependencies[depName];
@@ -958,6 +984,7 @@ var TUI = class {
958
984
  G: "G"
959
985
  };
960
986
  this.rendering = false;
987
+ this.pendingRender = false;
961
988
  this.state = state;
962
989
  }
963
990
  async open() {
@@ -1003,7 +1030,8 @@ var TUI = class {
1003
1030
  await nvim.call("nvim_win_set_option", [this.winid, "spell", false]);
1004
1031
  await nvim.call("nvim_win_set_option", [this.winid, "foldenable", false]);
1005
1032
  this.unsubscribe = this.state.subscribe(() => {
1006
- this.render();
1033
+ this.render().catch(() => {
1034
+ });
1007
1035
  });
1008
1036
  this.disposables.push(
1009
1037
  import_coc2.workspace.registerAutocmd({
@@ -1123,7 +1151,7 @@ var TUI = class {
1123
1151
  }
1124
1152
  const ok = await import_coc2.window.showPrompt(`Uninstall ${removed.length} orphaned package(s)?`);
1125
1153
  if (ok) {
1126
- for (const p of removed) uninstallPackage(this.state, p.info.name);
1154
+ for (const p of removed) await uninstallPackage(this.state, p.info.name);
1127
1155
  }
1128
1156
  return;
1129
1157
  }
@@ -1141,7 +1169,7 @@ var TUI = class {
1141
1169
  if (installed.length === 0) return;
1142
1170
  const ok = await import_coc2.window.showPrompt(`Uninstall all ${installed.length} packages?`);
1143
1171
  if (ok) {
1144
- for (const pkg of installed) uninstallPackage(this.state, pkg.info.name);
1172
+ for (const pkg of installed) await uninstallPackage(this.state, pkg.info.name);
1145
1173
  }
1146
1174
  return;
1147
1175
  }
@@ -1235,8 +1263,13 @@ var TUI = class {
1235
1263
  }
1236
1264
  }
1237
1265
  async render() {
1238
- if (!this.winid || this.rendering) return;
1266
+ if (!this.winid) return;
1267
+ if (this.rendering) {
1268
+ this.pendingRender = true;
1269
+ return;
1270
+ }
1239
1271
  this.rendering = true;
1272
+ this.pendingRender = false;
1240
1273
  try {
1241
1274
  const nvim = import_coc2.workspace.nvim;
1242
1275
  const state = this.state.getState();
@@ -1259,6 +1292,7 @@ var TUI = class {
1259
1292
  this.logLineSet = result.logLines;
1260
1293
  } finally {
1261
1294
  this.rendering = false;
1295
+ if (this.pendingRender) this.render();
1262
1296
  }
1263
1297
  }
1264
1298
  renderHelp() {
@@ -1505,7 +1539,7 @@ async function activate(context) {
1505
1539
  const ok = await import_coc3.window.showPrompt(`Uninstall all ${installed.length} packages?`);
1506
1540
  if (ok) {
1507
1541
  for (const pkg of installed) {
1508
- uninstallPackage(state, pkg.info.name);
1542
+ await uninstallPackage(state, pkg.info.name);
1509
1543
  }
1510
1544
  }
1511
1545
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coc-vscode-loader",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "Run VS Code extensions seamlessly in coc.nvim",
5
5
  "main": "lib/index.js",
6
6
  "keywords": [
@@ -19,6 +19,12 @@
19
19
  "url": "https://github.com/coc-plugin/coc-vscode-loader/issues"
20
20
  },
21
21
  "homepage": "https://www.npmjs.com/package/coc-vscode-loader",
22
+ "files": [
23
+ "lib/",
24
+ "converter/src/",
25
+ "converter/package.json",
26
+ "assets/"
27
+ ],
22
28
  "license": "MIT",
23
29
  "engines": {
24
30
  "coc": ">= 0.0.80"