Files
superwork/vscode/src/codeReader/languages/rust.test.ts
T

183 lines
6.1 KiB
TypeScript

import type { BlockView } from '../blockView'
import { describe, expect, it } from 'vitest'
import { toBlockViews } from '../blockView'
import { blockMarks } from '../diff/viewDiff'
import { rustImplRule } from '../rules/rustImpl'
import { readFixture, viewLines, WASM_DIR, withBlocks } from '../testSupport'
import { rustZhTranslator } from '../translators/rustZh'
import { createRustAdapter } from './rust'
const adapter = createRustAdapter(WASM_DIR)
const sample = readFixture('rustLang.rs')
function views(source: string): Promise<BlockView[]> {
return withBlocks(adapter, 'rust', source, blocks =>
toBlockViews(blocks, { source, language: adapter, markers: [] }, rustZhTranslator, {
rules: [rustImplRule],
report: () => {},
}))
}
function card(list: BlockView[], kind: string): BlockView {
const found = list.find(block => block.kind === kind)
if (!found)
throw new Error(`没有 ${kind}`)
return found
}
describe('rust 语言卡片', () => {
it('use、结构体、枚举、实现、函数、特质', async () => {
expect(viewLines(await views(sample))).toEqual([
'import 1',
' 来源: serde',
' 导入项: 1 个',
' Serialize | —',
'import 2',
' 来源: std::sync',
' 导入项: 1 个',
' Arc | —',
'import 3',
' 来源: foo',
' 导入项: 2 个',
' Bar | Baz',
' Qux | —',
'class 5',
' 名称: AgentRow',
' 说明: 桌面端列表里的一行代理。',
' 可见性: 公开',
' 字段: 2 个',
' id | Uuid | 公开',
' name | String | 本模块',
'class 12',
' 名称: CrateOnly',
' 可见性: 本 crate',
' 字段: 1 个',
' up | u8 | 父模块',
'enum 16',
' 名称: AgentState',
' 说明: 这个代理现在处在哪一步。',
' 变体: 3 个',
' Idle | —',
' Running | { pid: u32 }',
' Failed | String',
'rust.impl 23',
' 名称: AgentRow 的方法',
' 方法: 1 个',
' rename | &mut self, name: String | ()',
' function 24',
' 名称: rename',
' 可见性: 本模块',
' 参数: 2 个',
' self | &mut self',
' name | String',
' 返回: ()',
'function 27',
' 名称: start_server',
' 说明: 在本机拉起接口服务。',
' 异步: 是',
' 可见性: 公开',
' 输入参数: 1 个',
' addr | SocketAddr',
' 返回: Result<(), StartError>',
' 分情况: 2 支',
' Ok(listener) | 记下监听地址',
' Err(err) | 返回 StartError',
'trait 41',
' 名称: Store',
' 说明: 按 id 读写代理。',
' 方法: 2 个',
' get | &self, id: Uuid | Result<AgentRow, StoreError>',
' save | &mut self, row: AgentRow | Result<(), StoreError>',
])
})
it('实现的方法放进方法表那一行', async () => {
const impl = card(await views(sample), 'rust.impl')
const [method] = impl.children
expect(method?.slot).toEqual({ row: 1, item: 0 })
})
it('给结构体加一个字段,多出来的那一行标成新增', async () => {
const before = 'pub struct AgentRow {\n name: String,\n}\n'
const after = 'pub struct AgentRow {\n name: String,\n id: Uuid,\n}\n'
const [oldCard] = await views(before)
const [newCard] = await views(after)
const marks = oldCard && newCard ? blockMarks(oldCard, newCard) : undefined
const field = newCard && 'properties' in newCard ? newCard.properties.findIndex(row => row.label === '字段') : -1
expect(field).toBeGreaterThanOrEqual(0)
expect(marks?.rows?.changed[field]).toEqual({
items: { changed: { 1: { added: true } }, removed: [] },
})
})
it('带身体的模块拆成子块,常量和外部函数是卡片', async () => {
const source = [
'/// 平台相关。',
'pub mod platform {',
' /// 读入。',
' use std::io::Read;',
' /// 上限。',
' pub const LIMIT: u32 = 8;',
' static NAME: &str = "a";',
' pub fn open() -> u32 { LIMIT }',
' extern "C" {',
' /// 外部。',
' pub fn bar(x: i32) -> i32;',
' }',
' let local = 1;',
' println!("hi");',
'}',
'mod other;',
'',
'impl Agent {',
' pub const N: u8 = 2;',
'}',
'',
].join('\n')
const list = await views(source)
const mod = list.find(block => block.kind === 'module')
expect(mod?.kind).toBe('module')
expect(list.some(block => block.kind === 'statement' && block.code.includes('const LIMIT'))).toBe(false)
expect(list.filter(block => block.kind === 'statement').map(block => block.code)).toEqual(['mod other;'])
expect(mod?.children.map(block => block.kind)).toEqual(['import', 'const', 'variable', 'function', 'function', 'statement', 'statement'])
expect(viewLines(mod ? [mod] : [])).toEqual([
'module 1',
' 名称: platform',
' 说明: 平台相关。',
' 可见性: 公开',
' import 3',
' 来源: std::io',
' 导入项: 1 个',
' Read | —',
' const 5',
' 名称: LIMIT',
' 说明: 上限。',
' 访问级别: 公共',
' 类型: u32',
' 值: 8',
' variable 7',
' 名称: NAME',
' 类型: &str',
' 初始值: "a"',
' function 8',
' 名称: open',
' 可见性: 公开',
' 返回: u32',
' function 10',
' 名称: bar',
' 说明: 外部。',
' 可见性: 公开',
' 输入参数: 1 个',
' x | i32',
' 返回: i32',
' statement 13: 令 local = 1;',
' statement 14: println!("hi")',
])
const impl = list.find(block => block.kind === 'rust.impl')
const inner = impl?.children.find(block => block.kind === 'const')
expect(inner?.kind).toBe('const')
expect(viewLines(inner ? [inner] : []).join('\n')).toContain('名称: N')
expect(viewLines(inner ? [inner] : []).join('\n')).toMatch(/类型: u8|值: 2/)
})
})