import { describe, expect, it } from 'vitest' import { createBashAdapter } from '../languages/bash' import { createPythonAdapter } from '../languages/python' import { createRustAdapter } from '../languages/rust' import { createTypeScriptAdapter } from '../languages/typescript' import { runtime, WASM_DIR } from '../testSupport' import { locateInSource } from './featureLocate' const typescript = createTypeScriptAdapter(WASM_DIR) const python = createPythonAdapter(WASM_DIR) const rust = createRustAdapter(WASM_DIR) const bash = createBashAdapter(WASM_DIR) /** 找到的那块的名字在源码里是哪几个字、种类;找不到是 undefined */ async function find(adapter: typeof typescript, languageId: string, source: string, symbol: string): Promise<{ text: string, kind: string } | undefined> { const found = await locateInSource(runtime, adapter, languageId, source, symbol) return found && { text: source.slice(found.range.startIndex, found.range.endIndex), kind: found.kind } } const TS = ` import { api } from './api' export function login(name: string) { return api.post('/login', { name }) } export class AuthService { private token = '' async login(name: string) { return login(name) } static create() { return new AuthService() } } export const LoginPage = () => { const submit = () => login('a') return submit } ` const PY = ` class UserService: def renew(self, user): return self._charge(user) class Retry: def schedule(self): pass def renew_all(): pass ` const RS = ` pub struct Order; impl Order { pub fn pay(&self) {} } fn main() {} ` describe('按符号名在源码里找(语言插件解析出的块)', () => { it('函数、类、组件按名字找;同名时取先出现的', async () => { expect(await find(typescript, 'typescript', TS, 'login')).toEqual({ text: 'login', kind: 'function' }) expect(await find(typescript, 'typescript', TS, 'AuthService')).toEqual({ text: 'AuthService', kind: 'class' }) expect(await find(typescript, 'typescriptreact', TS, 'LoginPage')).toEqual({ text: 'LoginPage', kind: 'function' }) }) it('方法写成「类名.方法名」:先找类,再在里面找方法', async () => { const found = await locateInSource(runtime, typescript, 'typescript', TS, 'AuthService.login') expect(found?.kind).toBe('function') // 是类里的那个 login,不是文件开头的函数 expect(found!.range.startIndex).toBeGreaterThan(TS.indexOf('class AuthService')) expect(await find(typescript, 'typescript', TS, 'AuthService.create')).toEqual({ text: 'create', kind: 'function' }) expect(await find(typescript, 'typescript', TS, 'LoginPage.submit')).toEqual({ text: 'submit', kind: 'variable' }) }) it('类里的方法、嵌套类里的方法(Python);impl 里的方法按类型名找(Rust)', async () => { expect(await find(python, 'python', PY, 'UserService.renew')).toEqual({ text: 'renew', kind: 'function' }) expect(await find(python, 'python', PY, 'UserService.Retry.schedule')).toEqual({ text: 'schedule', kind: 'function' }) expect(await find(python, 'python', PY, 'renew_all')).toEqual({ text: 'renew_all', kind: 'function' }) expect(await find(rust, 'rust', RS, 'Order.pay')).toEqual({ text: 'pay', kind: 'function' }) }) it('类型(interface、type)和它们的成员按声明的名字找;shell 命令不算名字', async () => { const types = 'export interface Favorite {\n uri: string\n}\ntype Slot = number\n' expect(await find(typescript, 'typescript', types, 'Favorite')).toEqual({ text: 'Favorite', kind: 'interface' }) expect(await find(typescript, 'typescript', types, 'Favorite.uri')).toEqual({ text: 'uri', kind: 'field' }) expect(await find(typescript, 'typescript', types, 'Slot')).toEqual({ text: 'Slot', kind: 'type' }) expect(await find(rust, 'rust', 'pub type Id = u32;\n', 'Id')).toEqual({ text: 'Id', kind: 'statement' }) expect(await find(bash, 'shellscript', 'deploy() {\n echo hi\n}\n', 'deploy')).toEqual({ text: 'deploy', kind: 'function' }) expect(await find(bash, 'shellscript', 'deploy() {\n echo hi\n}\n', 'deploy.echo')).toBeUndefined() }) it('找不到:没有这个名字、类里没有这个方法、写法不对', async () => { expect(await find(typescript, 'typescript', TS, 'logout')).toBeUndefined() expect(await find(typescript, 'typescript', TS, 'AuthService.logout')).toBeUndefined() expect(await find(typescript, 'typescript', TS, 'Missing.login')).toBeUndefined() expect(await find(typescript, 'typescript', TS, 'AuthService.')).toBeUndefined() expect(await find(python, 'python', PY, 'UserService.schedule.renew')).toBeUndefined() }) })