mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 15:31:27 +00:00
Merge pull request #2744 from LaZzyMan/fix/tree-sitter-symlink-wasm
fix(core): resolve tree-sitter wasm path for symlinked CLI
This commit is contained in:
commit
fcaa1729d6
2 changed files with 82 additions and 5 deletions
|
|
@ -4,12 +4,14 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import path from 'node:path';
|
||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
||||
import {
|
||||
initParser,
|
||||
isShellCommandReadOnlyAST,
|
||||
extractCommandRules,
|
||||
_resetParser,
|
||||
_resolveWasmPathForTesting,
|
||||
} from './shellAstParser.js';
|
||||
|
||||
beforeAll(async () => {
|
||||
|
|
@ -20,6 +22,44 @@ afterAll(() => {
|
|||
_resetParser();
|
||||
});
|
||||
|
||||
describe('WASM path resolution', () => {
|
||||
it('resolves bundled WASM relative to the real CLI path when launched via symlink', () => {
|
||||
const symlinkedCliPath = path.join('/usr', 'bin', 'qwen');
|
||||
const realCliPath = path.join(
|
||||
'/opt',
|
||||
'homebrew',
|
||||
'lib',
|
||||
'node_modules',
|
||||
'@qwen-code',
|
||||
'qwen-code',
|
||||
'dist',
|
||||
'cli.js',
|
||||
);
|
||||
|
||||
const result = _resolveWasmPathForTesting(
|
||||
'tree-sitter.wasm',
|
||||
symlinkedCliPath,
|
||||
() => realCliPath,
|
||||
);
|
||||
|
||||
expect(result).toBe(
|
||||
path.join(
|
||||
'/opt',
|
||||
'homebrew',
|
||||
'lib',
|
||||
'node_modules',
|
||||
'@qwen-code',
|
||||
'qwen-code',
|
||||
'dist',
|
||||
'vendor',
|
||||
'tree-sitter',
|
||||
'tree-sitter.wasm',
|
||||
),
|
||||
);
|
||||
expect(result).not.toContain(path.join('/usr', 'bin', 'vendor'));
|
||||
});
|
||||
});
|
||||
|
||||
// =========================================================================
|
||||
// isShellCommandReadOnlyAST — mirror all tests from shellReadOnlyChecker.test.ts
|
||||
// =========================================================================
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
import Parser from 'web-tree-sitter';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
|
|
@ -22,8 +23,18 @@ import { fileURLToPath } from 'node:url';
|
|||
// Constants
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const __filename_ = fileURLToPath(import.meta.url);
|
||||
const __dirname_ = path.dirname(__filename_);
|
||||
const __filename_ = resolveModuleFilePath(fileURLToPath(import.meta.url));
|
||||
|
||||
function resolveModuleFilePath(moduleFilePath: string): string {
|
||||
try {
|
||||
const resolved = fs.realpathSync(moduleFilePath);
|
||||
// Guard against test environments where `fs` is mocked and realpathSync
|
||||
// returns undefined rather than throwing.
|
||||
return typeof resolved === 'string' ? resolved : moduleFilePath;
|
||||
} catch {
|
||||
return moduleFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Root commands considered read-only by default (no sub-command analysis needed
|
||||
|
|
@ -569,10 +580,24 @@ let initPromise: Promise<void> | null = null;
|
|||
* - Bundle (dist/cli.js): vendor at same level (0 levels)
|
||||
*/
|
||||
function resolveWasmPath(filename: string): string {
|
||||
const inSrcUtils = __filename_.includes(path.join('src', 'utils'));
|
||||
const levelsUp = !inSrcUtils ? 0 : __filename_.endsWith('.ts') ? 2 : 3;
|
||||
return resolveWasmPathForModule(filename, __filename_);
|
||||
}
|
||||
|
||||
function resolveWasmPathForModule(
|
||||
filename: string,
|
||||
moduleFilePath: string,
|
||||
resolvePath: (moduleFilePath: string) => string = resolveModuleFilePath,
|
||||
): string {
|
||||
const resolvedModuleFilePath = resolvePath(moduleFilePath);
|
||||
const moduleDir = path.dirname(resolvedModuleFilePath);
|
||||
const inSrcUtils = resolvedModuleFilePath.includes(path.join('src', 'utils'));
|
||||
const levelsUp = !inSrcUtils
|
||||
? 0
|
||||
: resolvedModuleFilePath.endsWith('.ts')
|
||||
? 2
|
||||
: 3;
|
||||
return path.join(
|
||||
__dirname_,
|
||||
moduleDir,
|
||||
...Array<string>(levelsUp).fill('..'),
|
||||
'vendor',
|
||||
'tree-sitter',
|
||||
|
|
@ -1084,3 +1109,15 @@ export function _resetParser(): void {
|
|||
bashLanguage = null;
|
||||
initPromise = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal helper exposed for tests.
|
||||
* @internal
|
||||
*/
|
||||
export function _resolveWasmPathForTesting(
|
||||
filename: string,
|
||||
moduleFilePath: string,
|
||||
resolvePath?: (moduleFilePath: string) => string,
|
||||
): string {
|
||||
return resolveWasmPathForModule(filename, moduleFilePath, resolvePath);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue