coc-vscode-loader 1.2.1 → 1.2.2
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.
- package/assets/tui-preview.png +0 -0
- package/converter/package.json +1 -1
- package/converter/src/convert.ts +33 -6
- package/converter/src/steps/bridge.ts +26 -4
- package/converter/src/steps/language-client.ts +15 -5
- package/converter/src/steps/source.ts +39 -6
- package/converter/src/transforms/import-mapping.ts +164 -18
- package/converter/src/types.ts +5 -0
- package/lib/index.js +33 -9
- package/package.json +29 -8
package/assets/tui-preview.png
CHANGED
|
Binary file
|
package/converter/package.json
CHANGED
package/converter/src/convert.ts
CHANGED
|
@@ -68,7 +68,9 @@ export async function convert(opts: ConvertOptions): Promise<void> {
|
|
|
68
68
|
}
|
|
69
69
|
console.log(result.summary)
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
// Source-only steps need source files; bridge/language-client steps can generate code
|
|
72
|
+
const hasNonSourceStep = steps.some(s => s.type !== 'source' && s.type !== 'mark-unsupported')
|
|
73
|
+
if (result.files.length === 0 && !hasNonSourceStep) {
|
|
72
74
|
console.log('No VS Code API usage found, nothing to convert.')
|
|
73
75
|
return
|
|
74
76
|
}
|
|
@@ -174,7 +176,7 @@ export async function convert(opts: ConvertOptions): Promise<void> {
|
|
|
174
176
|
if (fs.existsSync(outputSrc)) {
|
|
175
177
|
for (const f of fs.readdirSync(outputSrc, { recursive: true })) {
|
|
176
178
|
const fp = typeof f === 'string' ? path.join(outputSrc, f) : f
|
|
177
|
-
if (!fp.endsWith('.ts')) continue
|
|
179
|
+
if (!fp.endsWith('.ts') && !fp.endsWith('.js')) continue
|
|
178
180
|
let content = fs.readFileSync(fp, 'utf-8')
|
|
179
181
|
let changed = false
|
|
180
182
|
|
|
@@ -198,13 +200,38 @@ export async function convert(opts: ConvertOptions): Promise<void> {
|
|
|
198
200
|
}
|
|
199
201
|
|
|
200
202
|
if (content.includes('.fileName') || content.includes('.uri.fsPath')) {
|
|
201
|
-
// .fileName → .uri (coc's TextDocument#uri returns a
|
|
202
|
-
content = content.replace(/(document|this\.document|textDocument|scope)\.fileName/g, '$1.uri')
|
|
203
|
-
//
|
|
204
|
-
content = content.replace(
|
|
203
|
+
// .fileName → Uri.parse($1.uri).fsPath (coc's TextDocument#uri returns a file:// URI string)
|
|
204
|
+
content = content.replace(/(document|this\.document|textDocument|scope|doc)\.fileName/g, 'Uri.parse($1.uri).fsPath')
|
|
205
|
+
// Handle destructuring: const { fileName, ...rest } = document/doc/textDocument
|
|
206
|
+
content = content.replace(
|
|
207
|
+
/^(\s*)(const|let|var)\s*\{([^}]*)\}\s*=\s*(document|doc|textDocument)\s*;?\s*$/gm,
|
|
208
|
+
(m: string, indent: string, kw: string, props: string, varName: string) => {
|
|
209
|
+
const parts = props.split(',').map((p: string) => p.trim())
|
|
210
|
+
if (!parts.some((p: string) => p === 'fileName')) return m
|
|
211
|
+
const rest = parts.filter((p: string) => p !== 'fileName' && p !== '')
|
|
212
|
+
return rest.length > 0
|
|
213
|
+
? `${indent}${kw} {${rest.join(', ')}} = ${varName};\n${indent}const fileName = Uri.parse(${varName}.uri).fsPath`
|
|
214
|
+
: `${indent}const fileName = Uri.parse(${varName}.uri).fsPath`
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
// .uri.fsPath → Uri.parse(...).fsPath (coc's uri is a file:// URI string, not a path)
|
|
218
|
+
content = content.replace(/(\w+(?:\.\w+)*?)\.uri\.fsPath/g, 'Uri.parse($1.uri).fsPath')
|
|
205
219
|
changed = true
|
|
206
220
|
}
|
|
207
221
|
|
|
222
|
+
// Ensure Uri is imported when introduced by Uri.parse() replacements
|
|
223
|
+
if (content.includes('Uri.parse(') && content.match(/from\s+['"]coc\.nvim['"]/)) {
|
|
224
|
+
content = content.replace(
|
|
225
|
+
/(import\s*\{\s*)([^}]*?)(\s*\}\s*from\s*['"]coc\.nvim['"])/g,
|
|
226
|
+
(_m: string, prefix: string, existing: string, suffix: string) => {
|
|
227
|
+
if (!existing.includes('Uri')) {
|
|
228
|
+
const sep = existing.trim() ? ', ' : ''
|
|
229
|
+
return `${prefix}${existing.trim()}${sep}Uri${suffix}`
|
|
230
|
+
}
|
|
231
|
+
return _m
|
|
232
|
+
}
|
|
233
|
+
)
|
|
234
|
+
}
|
|
208
235
|
if (changed) fs.writeFileSync(fp, content)
|
|
209
236
|
}
|
|
210
237
|
}
|
|
@@ -72,7 +72,32 @@ export const bridgeGenerator: StepGenerator = {
|
|
|
72
72
|
${code}`
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
const extIds = generated.injectExts || []
|
|
76
|
+
const svcIds = generated.injectSvcs || []
|
|
77
|
+
const callAfter = generated.callAfter
|
|
78
|
+
const isStandalone = !callAfter && extIds.length === 0 && svcIds.length === 0
|
|
79
|
+
|
|
80
|
+
if (isStandalone) {
|
|
81
|
+
// Standalone preset (e.g. prettier): generate entry point directly
|
|
82
|
+
const moduleContent = `\
|
|
83
|
+
import { ExtensionContext, languages, Range, TextEdit, Uri, window, workspace } from 'coc.nvim'
|
|
84
|
+
|
|
85
|
+
export async function activate(context: ExtensionContext): Promise<void> {
|
|
86
|
+
${code}
|
|
87
|
+
}
|
|
88
|
+
`
|
|
89
|
+
return {
|
|
90
|
+
generatedFiles: [{ path: 'src/index.ts', content: moduleContent }],
|
|
91
|
+
entryPoint: 'src/index.ts',
|
|
92
|
+
keepDeps: Object.fromEntries((generated.extraDeps || []).map((d: string) => {
|
|
93
|
+
const ver = ctx.origPkg.dependencies?.[d] || ctx.origPkg.devDependencies?.[d]
|
|
94
|
+
return [d, ver || '*']
|
|
95
|
+
})),
|
|
96
|
+
activationEvents: ['*'],
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Generate the bridge module (for tsserver-forward etc)
|
|
76
101
|
const moduleContent = `\
|
|
77
102
|
import { commands, ExtensionContext } from 'coc.nvim'
|
|
78
103
|
|
|
@@ -83,9 +108,6 @@ ${code}
|
|
|
83
108
|
|
|
84
109
|
// Build code injections
|
|
85
110
|
const codeInjections: StepResult['codeInjections'] = []
|
|
86
|
-
const extIds = generated.injectExts || []
|
|
87
|
-
const svcIds = generated.injectSvcs || []
|
|
88
|
-
const callAfter = generated.callAfter
|
|
89
111
|
|
|
90
112
|
if (callAfter) {
|
|
91
113
|
codeInjections.push({
|
|
@@ -42,21 +42,30 @@ export const languageClientGenerator: StepGenerator = {
|
|
|
42
42
|
const entry = ls.server.entry || 'main'
|
|
43
43
|
|
|
44
44
|
// Same resolution as old converter: resolve main entry first, then walk for bin
|
|
45
|
+
// Use require.resolve('pkg/package.json') as fallback for packages without main entry
|
|
46
|
+
const binName = ls.server.binName || ''
|
|
47
|
+
const binLookupCode = binName
|
|
48
|
+
? `(_pkg.bin && _pkg.bin['${escapeStr(binName)}'] ? _pkg.bin['${escapeStr(binName)}'] : Object.values(_pkg.bin)[0])`
|
|
49
|
+
: `(typeof _pkg.bin === 'string' ? _pkg.bin : Object.values(_pkg.bin)[0])`
|
|
45
50
|
serverPathCode = `\
|
|
46
51
|
let serverPath: string | undefined
|
|
52
|
+
let _mainEntry: string | undefined
|
|
47
53
|
try {
|
|
48
|
-
|
|
54
|
+
_mainEntry = require.resolve('${escapeStr(pkg)}')
|
|
49
55
|
} catch {}
|
|
56
|
+
if (!_mainEntry) {
|
|
57
|
+
try { _mainEntry = require.resolve('${escapeStr(pkg)}/package.json') } catch {}
|
|
58
|
+
}
|
|
50
59
|
try {
|
|
51
60
|
// Walk up from the resolved main entry to find the package's package.json
|
|
52
61
|
// We can't use require.resolve('pkg/package.json') because exports field may block it
|
|
53
|
-
let _dir = require('path').dirname(
|
|
54
|
-
while (_dir !== require('path').dirname(_dir)) {
|
|
62
|
+
let _dir = _mainEntry ? require('path').dirname(_mainEntry) : undefined;
|
|
63
|
+
while (_dir && _dir !== require('path').dirname(_dir)) {
|
|
55
64
|
const _pkgPath = require('path').join(_dir, 'package.json');
|
|
56
65
|
if (require('fs').existsSync(_pkgPath)) {
|
|
57
66
|
const _pkg = JSON.parse(require('fs').readFileSync(_pkgPath, 'utf-8'));
|
|
58
67
|
if (_pkg.bin) {
|
|
59
|
-
const _entry =
|
|
68
|
+
const _entry = ${binLookupCode};
|
|
60
69
|
serverPath = require('path').join(_dir, _entry);
|
|
61
70
|
}
|
|
62
71
|
break;
|
|
@@ -65,7 +74,7 @@ export const languageClientGenerator: StepGenerator = {
|
|
|
65
74
|
}
|
|
66
75
|
} catch {}`
|
|
67
76
|
// Use full require.resolve path (including bin walking) if available, else fallback to simple main entry
|
|
68
|
-
serverOptionsCode = `{ module: serverPath || require.resolve('${escapeStr(pkg)}'), transport: ${transportExpr} }`
|
|
77
|
+
serverOptionsCode = `{ module: serverPath || _mainEntry || require.resolve('${escapeStr(pkg)}/package.json'), transport: ${transportExpr} }`
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
const docSelectorCode = `[${languages.map(l => `{ scheme: 'file', language: '${l}' }`).join(', ')}]`
|
|
@@ -99,6 +108,7 @@ ${ls.verbose ? ` console.log('[${escapeStr(id)}] creating LanguageClient')\n`
|
|
|
99
108
|
{
|
|
100
109
|
documentSelector: ${docSelectorCode},
|
|
101
110
|
outputChannelName: '${escapeStr(description)}',
|
|
111
|
+
${ls.initializationOptions ? `initializationOptions: ${ls.initializationOptions},` : ''}
|
|
102
112
|
},
|
|
103
113
|
)
|
|
104
114
|
context.subscriptions.push({ dispose: () => c.stop() })
|
|
@@ -39,18 +39,19 @@ export const sourceGenerator: StepGenerator = {
|
|
|
39
39
|
const outputsDir = path.join(output, 'src')
|
|
40
40
|
fs.mkdirSync(outputsDir, { recursive: true })
|
|
41
41
|
|
|
42
|
-
// Copy ALL .ts/.tsx files from source directory (try src/ first, fall back to input root)
|
|
42
|
+
// Copy ALL .ts/.tsx/.js files from source directory (try src/ first, fall back to input root)
|
|
43
43
|
let srcDir = path.join(input, 'src')
|
|
44
44
|
if (!fs.existsSync(srcDir)) {
|
|
45
45
|
srcDir = input
|
|
46
46
|
}
|
|
47
47
|
const hasStripVolar = ss.transforms.includes('strip-volar')
|
|
48
48
|
const allFiles: Array<{ src: string; rel: string }> = []
|
|
49
|
+
const jsFiles: string[] = []
|
|
49
50
|
const vscodeFiles: string[] = []
|
|
50
51
|
|
|
51
52
|
for (const f of walkFiles(srcDir)) {
|
|
52
53
|
const rel = path.relative(srcDir, f)
|
|
53
|
-
if (!rel.endsWith('.ts') && !rel.endsWith('.tsx')) continue
|
|
54
|
+
if (!rel.endsWith('.ts') && !rel.endsWith('.tsx') && !rel.endsWith('.js')) continue
|
|
54
55
|
|
|
55
56
|
// Skip framework files that are replaced by generated code
|
|
56
57
|
if (hasStripVolar) {
|
|
@@ -61,8 +62,10 @@ export const sourceGenerator: StepGenerator = {
|
|
|
61
62
|
allFiles.push({ src: f, rel })
|
|
62
63
|
|
|
63
64
|
const content = fs.readFileSync(f, 'utf-8')
|
|
64
|
-
|
|
65
|
+
const hasVscode = content.includes("from 'vscode'") || content.includes('from "vscode"') || content.includes('require("vscode")')
|
|
66
|
+
if (hasVscode) {
|
|
65
67
|
vscodeFiles.push(rel)
|
|
68
|
+
if (rel.endsWith('.js')) jsFiles.push(rel)
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -74,13 +77,13 @@ export const sourceGenerator: StepGenerator = {
|
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
if (verbose) {
|
|
77
|
-
console.log(` source: copied ${allFiles.length} files (${vscodeFiles.length} with vscode imports)`)
|
|
80
|
+
console.log(` source: copied ${allFiles.length} files (${vscodeFiles.length} with vscode imports, ${jsFiles.length} .js)`)
|
|
78
81
|
}
|
|
79
82
|
|
|
80
|
-
// Apply transforms via ts-morph (only to files with vscode imports)
|
|
83
|
+
// Apply transforms via ts-morph (only to TS files with vscode imports; .js files get text-level only)
|
|
81
84
|
for (const rel of vscodeFiles) {
|
|
82
85
|
const fp = path.join(outputsDir, rel)
|
|
83
|
-
if (!fs.existsSync(fp)) continue
|
|
86
|
+
if (!fs.existsSync(fp) || rel.endsWith('.js')) continue
|
|
84
87
|
try { project.addSourceFileAtPath(fp) } catch {}
|
|
85
88
|
}
|
|
86
89
|
|
|
@@ -104,6 +107,36 @@ export const sourceGenerator: StepGenerator = {
|
|
|
104
107
|
sf.saveSync()
|
|
105
108
|
}
|
|
106
109
|
|
|
110
|
+
// Apply text-level replacements to .js files (ts-morph can't handle JS)
|
|
111
|
+
for (const rel of jsFiles) {
|
|
112
|
+
const fp = path.join(outputsDir, rel)
|
|
113
|
+
if (!fs.existsSync(fp)) continue
|
|
114
|
+
let code = fs.readFileSync(fp, 'utf-8')
|
|
115
|
+
const orig = code
|
|
116
|
+
code = code.replace(/require\(['"]vscode['"]\)/g, "require('coc.nvim')")
|
|
117
|
+
code = code.replace(/(\w+)\.fileName\b/g, "Uri.parse($1.uri).fsPath")
|
|
118
|
+
code = code.replace(/(\w+(?:\.\w+)*?)\.uri\.fsPath/g, 'Uri.parse($1.uri).fsPath')
|
|
119
|
+
if (code.includes('window.activeTextEditor')) {
|
|
120
|
+
code = `\
|
|
121
|
+
if (typeof window !== 'undefined' && !('activeTextEditor' in window)) {
|
|
122
|
+
try {
|
|
123
|
+
Object.defineProperty(window, 'activeTextEditor', {
|
|
124
|
+
get() {
|
|
125
|
+
try {
|
|
126
|
+
var doc = typeof workspace !== 'undefined' ? workspace.getDocument() : undefined;
|
|
127
|
+
return doc ? { document: doc } : undefined;
|
|
128
|
+
} catch(e) { return undefined }
|
|
129
|
+
},
|
|
130
|
+
configurable: true,
|
|
131
|
+
});
|
|
132
|
+
} catch {}
|
|
133
|
+
}
|
|
134
|
+
` + code
|
|
135
|
+
}
|
|
136
|
+
code = code.replace(/window\.onDidChangeActiveTextEditor/g, 'workspace.onDidOpenTextDocument')
|
|
137
|
+
if (code !== orig) fs.writeFileSync(fp, code)
|
|
138
|
+
}
|
|
139
|
+
|
|
107
140
|
// Resolve keepDeps from origPkg (with workspace root fallback)
|
|
108
141
|
const keepDeps: Record<string, string> = {}
|
|
109
142
|
if (ss.keepDeps) {
|
|
@@ -5,12 +5,12 @@ import { Transform } from '../types.js'
|
|
|
5
5
|
* and apply name remapping for known API differences.
|
|
6
6
|
*/
|
|
7
7
|
const MAPPINGS: Record<string, string> = {
|
|
8
|
-
// namespace
|
|
9
|
-
'vscode': 'coc.nvim',
|
|
8
|
+
// namespace (module specifier is rewritten by AST, keep identifier as-is)
|
|
10
9
|
|
|
11
10
|
// naming differences
|
|
12
11
|
'EventEmitter': 'Emitter',
|
|
13
12
|
'Disposable': 'Disposable',
|
|
13
|
+
'StatusBarAlignment': '(void 0) as any',
|
|
14
14
|
|
|
15
15
|
// function/method renames
|
|
16
16
|
'getExtension': 'getExtensionById',
|
|
@@ -25,23 +25,169 @@ export const transformImportMapping: Transform = (ctx) => {
|
|
|
25
25
|
const { file } = ctx
|
|
26
26
|
|
|
27
27
|
// Rewrite import declarations
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
try {
|
|
29
|
+
file.getImportDeclarations().forEach(decl => {
|
|
30
|
+
const mod = decl.getModuleSpecifierValue()
|
|
31
|
+
if (mod === 'vscode') {
|
|
32
|
+
decl.setModuleSpecifier('coc.nvim')
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
} catch {}
|
|
34
36
|
|
|
35
37
|
// Rewrite named references
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
try {
|
|
39
|
+
file.getDescendantsOfKind(80 /* Identifier */).forEach(node => {
|
|
40
|
+
const text = node.getText()
|
|
41
|
+
if (Object.prototype.hasOwnProperty.call(MAPPINGS, text)) {
|
|
42
|
+
const mapped = MAPPINGS[text]
|
|
43
|
+
if (mapped !== text) {
|
|
44
|
+
const parent = node.getParent()
|
|
45
|
+
if (parent && parent.getKindName() !== 'StringLiteral') {
|
|
46
|
+
node.replaceWithText(mapped)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
} catch {}
|
|
52
|
+
|
|
53
|
+
// Replace CodeActionKind.SourceFixAll.append('xxx') with string literal
|
|
54
|
+
try {
|
|
55
|
+
file.getDescendantsOfKind(214 /* CallExpression */).forEach(node => {
|
|
56
|
+
const text = node.getText()
|
|
57
|
+
const match = text.match(/^CodeActionKind\.SourceFixAll\.append\(['"](.+)['"]\)$/)
|
|
58
|
+
if (match) {
|
|
59
|
+
node.replaceWithText(`'source.fixAll.${match[1]}'`)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
} catch {}
|
|
63
|
+
|
|
64
|
+
// Text-level replacements for coc.nvim API differences
|
|
65
|
+
|
|
66
|
+
// Convert require('vscode') to require('coc.nvim') (JS-style imports)
|
|
67
|
+
let content = file.getText()
|
|
68
|
+
let newContent = content.replace(
|
|
69
|
+
/require\(['"]vscode['"]\)/g,
|
|
70
|
+
"require('coc.nvim')",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
// Convert dynamic import() to require()
|
|
74
|
+
newContent = newContent.replace(
|
|
75
|
+
/await\s+import\(/g,
|
|
76
|
+
'require(',
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
// Convert createStatusBarItem(name, alignment, priority) → createStatusBarItem(priority)
|
|
80
|
+
newContent = newContent.replace(
|
|
81
|
+
/createStatusBarItem\([^,]+,\s*(?:\w+\.)?(?:Right|Left),\s*/g,
|
|
82
|
+
'createStatusBarItem(',
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
// Replace LanguageStatusSeverity.xxx → 2
|
|
86
|
+
newContent = newContent.replace(
|
|
87
|
+
/LanguageStatusSeverity\.\w+/g,
|
|
88
|
+
'2',
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
// Replace StatusBar with a no-op mock so formatting works without status UI
|
|
92
|
+
newContent = newContent.replace(
|
|
93
|
+
/new\s+StatusBar\(\)/g,
|
|
94
|
+
'new (class { update(){} hide(){} updateConfig(){} dispose(){} } as any)()',
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
// Treat all workspaces as trusted (coc.nvim doesn't have workspace.isTrusted)
|
|
98
|
+
newContent = newContent.replace(
|
|
99
|
+
/workspace\.isTrusted/g,
|
|
100
|
+
'true',
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
// Wrap new CodeAction() in try-catch (coc.nvim may not have CodeAction)
|
|
104
|
+
newContent = newContent.replace(
|
|
105
|
+
/const action = new CodeAction\(/g,
|
|
106
|
+
'let action; try { action = new CodeAction(',
|
|
107
|
+
)
|
|
108
|
+
// Close the try-catch before return [action]
|
|
109
|
+
newContent = newContent.replace(
|
|
110
|
+
/return \[action\];/g,
|
|
111
|
+
'}catch(e){action={title:"",kind:""}};return [action];',
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
// window.createOutputChannel works in coc.nvim (workspace variant is deprecated)
|
|
115
|
+
// no replacement needed
|
|
116
|
+
|
|
117
|
+
// Polyfill window.activeTextEditor (VS Code API, not in coc.nvim)
|
|
118
|
+
if (newContent.includes('window.activeTextEditor')) {
|
|
119
|
+
newContent = `\
|
|
120
|
+
if (typeof window !== 'undefined' && !('activeTextEditor' in window)) {
|
|
121
|
+
try {
|
|
122
|
+
Object.defineProperty(window, 'activeTextEditor', {
|
|
123
|
+
get() {
|
|
124
|
+
try {
|
|
125
|
+
var doc = typeof workspace !== 'undefined' ? workspace.getDocument() : undefined;
|
|
126
|
+
return doc ? { document: doc } : undefined;
|
|
127
|
+
} catch(e) { return undefined }
|
|
128
|
+
},
|
|
129
|
+
configurable: true,
|
|
130
|
+
});
|
|
131
|
+
} catch {}
|
|
132
|
+
}
|
|
133
|
+
` + newContent
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// window.onDidChangeActiveTextEditor → workspace.onDidOpenTextDocument
|
|
137
|
+
newContent = newContent.replace(/window\.onDidChangeActiveTextEditor/g, 'workspace.onDidOpenTextDocument')
|
|
138
|
+
|
|
139
|
+
// languages.createLanguageStatusItem → no-op (coc.nvim doesn't have this)
|
|
140
|
+
newContent = newContent.replace(
|
|
141
|
+
/languages\.createLanguageStatusItem\([^)]+\)/g,
|
|
142
|
+
'({ dispose(){}, text: "", command: void 0, name: "", accessibilityInformation: void 0, severity: void 0 }) as any'
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
// window.showOpenDialog → not available in coc, return undefined
|
|
146
|
+
newContent = newContent.replace(
|
|
147
|
+
/window\.showOpenDialog\([^)]*\)/g,
|
|
148
|
+
'void 0 as any'
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
// Add priority 1 to document format providers (default 0 gets overridden by LanguageClient)
|
|
152
|
+
newContent = newContent.replace(
|
|
153
|
+
/registerDocumentFormatProvider\s*\(\s*(\w[\w.]*)\s*,\s*(\w[\w.]*)\s*,?\s*\)/g,
|
|
154
|
+
'registerDocumentFormatProvider($1, $2, 1)'
|
|
155
|
+
)
|
|
156
|
+
newContent = newContent.replace(
|
|
157
|
+
/registerDocumentRangeFormatProvider\s*\(\s*(\w[\w.]*)\s*,\s*(\w[\w.]*)\s*,?\s*\)/g,
|
|
158
|
+
'registerDocumentRangeFormatProvider($1, $2, 1)'
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
// authentication.getSession → undefined (coc.nvim has no auth API)
|
|
162
|
+
newContent = newContent.replace(
|
|
163
|
+
/authentication\.getSession\s*\([^)]*\)/g,
|
|
164
|
+
'undefined as any'
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
// editor.setDecorations → no-op (coc has different decoration API)
|
|
168
|
+
newContent = newContent.replace(/editor\.setDecorations\s*\([^)]+\)/g, '/* setDecorations */')
|
|
169
|
+
|
|
170
|
+
// Guard workspace.workspaceFolders when accessed via index (coc.nvim may return undefined)
|
|
171
|
+
newContent = newContent.replace(
|
|
172
|
+
/workspace\.workspaceFolders(?=\[)/g,
|
|
173
|
+
'(workspace.workspaceFolders || [])'
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
// Ensure workspace is imported from coc.nvim when we introduced workspace. references
|
|
177
|
+
if (newContent.includes('workspace.') && newContent.match(/from\s+['"]coc\.nvim['"]/)) {
|
|
178
|
+
newContent = newContent.replace(
|
|
179
|
+
/(import\s*\{\s*)([^}]*?)(\s*\}\s*from\s*['"]coc\.nvim['"])/g,
|
|
180
|
+
(match, prefix, existing, suffix) => {
|
|
181
|
+
if (!existing.includes('workspace')) {
|
|
182
|
+
const sep = existing.trim() ? ', ' : ''
|
|
183
|
+
return `${prefix}${existing.trim()}${sep}workspace${suffix}`
|
|
184
|
+
}
|
|
185
|
+
return match
|
|
44
186
|
}
|
|
45
|
-
|
|
46
|
-
}
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (newContent !== content) {
|
|
191
|
+
file.replaceWithText(newContent)
|
|
192
|
+
}
|
|
47
193
|
}
|
package/converter/src/types.ts
CHANGED
|
@@ -13,6 +13,9 @@ export interface ServerModuleConfig {
|
|
|
13
13
|
kind: 'module'
|
|
14
14
|
package: string
|
|
15
15
|
entry?: 'main' | 'bin'
|
|
16
|
+
/** When entry is 'bin', pick a specific bin entry by name (e.g. "tailwindcss-language-server").
|
|
17
|
+
* Defaults to the first entry in the bin object. */
|
|
18
|
+
binName?: string
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
export interface ServerBinaryConfig {
|
|
@@ -37,6 +40,8 @@ export interface LanguageClientStep {
|
|
|
37
40
|
multiRoot?: boolean
|
|
38
41
|
/** Enable debug logging in generated code */
|
|
39
42
|
verbose?: boolean
|
|
43
|
+
/** Extra options passed as initializationOptions to LanguageClient (JS object expression, inserted as-is) */
|
|
44
|
+
initializationOptions?: string
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
export interface SourceStep {
|
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.2.
|
|
42
|
+
version: "1.2.2",
|
|
43
43
|
description: "Run VS Code extensions seamlessly in coc.nvim",
|
|
44
44
|
main: "lib/index.js",
|
|
45
45
|
keywords: [
|
|
@@ -89,13 +89,34 @@ var require_package = __commonJS({
|
|
|
89
89
|
],
|
|
90
90
|
contributes: {
|
|
91
91
|
commands: [
|
|
92
|
-
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
{
|
|
93
|
+
command: "loader.open",
|
|
94
|
+
title: "Open VS Code extension loader"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
command: "loader.install",
|
|
98
|
+
title: "Install a VS Code extension"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
command: "loader.uninstall",
|
|
102
|
+
title: "Uninstall a package"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
command: "loader.update",
|
|
106
|
+
title: "Update a package"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
command: "loader.uninstallAll",
|
|
110
|
+
title: "Uninstall all packages"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
command: "loader.updateRegistry",
|
|
114
|
+
title: "Update package registry"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
command: "loader._dispatch",
|
|
118
|
+
title: ""
|
|
119
|
+
}
|
|
99
120
|
]
|
|
100
121
|
}
|
|
101
122
|
};
|
|
@@ -630,12 +651,15 @@ async function buildPackage(name, inputDir, info, onProgress) {
|
|
|
630
651
|
fs3.mkdirSync(serverDir2, { recursive: true });
|
|
631
652
|
if (filename.endsWith(".zip")) {
|
|
632
653
|
await run("unzip", ["-o", filename, "-d", serverDir2], build);
|
|
654
|
+
} else if (filename.endsWith(".tar.gz") || filename.endsWith(".tgz")) {
|
|
655
|
+
await run("tar", ["xzf", filename, "-C", serverDir2], build);
|
|
633
656
|
} else if (filename.endsWith(".gz") && !filename.endsWith(".tar.gz")) {
|
|
634
657
|
const outName = filename.replace(/\.gz$/, "");
|
|
635
658
|
await run("gunzip", [filename], build);
|
|
636
659
|
fs3.renameSync(path3.join(build, outName), path3.join(serverDir2, outName));
|
|
637
660
|
} else {
|
|
638
|
-
|
|
661
|
+
const binName = sb.binaryPath || filename;
|
|
662
|
+
fs3.renameSync(path3.join(build, filename), path3.join(serverDir2, binName));
|
|
639
663
|
}
|
|
640
664
|
try {
|
|
641
665
|
fs3.readdirSync(serverDir2).forEach((f) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coc-vscode-loader",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Run VS Code extensions seamlessly in coc.nvim",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -50,13 +50,34 @@
|
|
|
50
50
|
],
|
|
51
51
|
"contributes": {
|
|
52
52
|
"commands": [
|
|
53
|
-
{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
{
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
{
|
|
54
|
+
"command": "loader.open",
|
|
55
|
+
"title": "Open VS Code extension loader"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"command": "loader.install",
|
|
59
|
+
"title": "Install a VS Code extension"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"command": "loader.uninstall",
|
|
63
|
+
"title": "Uninstall a package"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"command": "loader.update",
|
|
67
|
+
"title": "Update a package"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"command": "loader.uninstallAll",
|
|
71
|
+
"title": "Uninstall all packages"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"command": "loader.updateRegistry",
|
|
75
|
+
"title": "Update package registry"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"command": "loader._dispatch",
|
|
79
|
+
"title": ""
|
|
80
|
+
}
|
|
60
81
|
]
|
|
61
82
|
}
|
|
62
83
|
}
|