✨ feat(vscode): 代码阅读预览里跨几行写的列表按项拆开,列表里整项是调用的带着自己的实参表,一层层能往下套
This commit is contained in:
1 parent
7d6e7592c9
commit
2c490cac2d
22 files changed
+848
-314
No files matched your search
@@ -304,33 +304,66 @@ describe('python 属性表信息(facts)', () => {
|
||||
expect(found[10]).not.toHaveProperty('access')
|
||||
})
|
||||
|
||||
it('字典字面量的各项:字符串键、名字键、嵌套字典连它的各项、**展开;空字典是空数组,别的值没有;类属性也有', async () => {
|
||||
it('声明的值照源码给,字面量的各项不在 facts 里(见 LanguageAdapter.collection)', async () => {
|
||||
const found = await facts('EMPTY = {}\nITEMS = [1]\nclass K:\n labels = {"x": 1}')
|
||||
expect(found[1]).toEqual({ access: 'public', declarators: [{ name: 'EMPTY', value: '{}' }] })
|
||||
expect(found[2]).toEqual({ access: 'public', declarators: [{ name: 'ITEMS', value: '[1]' }] })
|
||||
expect(found[4]).toEqual({ access: 'public', declarators: [{ name: 'labels', value: '{"x": 1}' }] })
|
||||
})
|
||||
})
|
||||
|
||||
describe('python 字面量的各项', () => {
|
||||
const collections = (source: string): Promise<unknown[]> => nodeFacts(adapter, 'python', source, node => adapter.collection?.(node))
|
||||
|
||||
it('字典:字符串键、名字键、**展开,注释不算一项;值里的字典另有自己的各项,空字典没有项', async () => {
|
||||
const source = [
|
||||
'_KEYS = {',
|
||||
' "published": "contests:publish",',
|
||||
' key: 1,',
|
||||
' # 注释不算一项',
|
||||
' "nested": {"a": {}, "b": [1]},',
|
||||
' "nested": {"a": {}},',
|
||||
' **other,',
|
||||
'}',
|
||||
'EMPTY = {}',
|
||||
'ITEMS = [1]',
|
||||
'class K:',
|
||||
' labels = {"x": 1}',
|
||||
].join('\n')
|
||||
const found = await facts(source)
|
||||
expect(found[1]).toMatchObject({ access: 'private', declarators: [{ name: '_KEYS', entries: [
|
||||
{ kind: 'pair', key: '"published"', value: '"contests:publish"' },
|
||||
{ kind: 'pair', key: 'key', value: '1' },
|
||||
{ kind: 'pair', key: '"nested"', value: '{"a": {}, "b": [1]}', entries: [
|
||||
{ kind: 'pair', key: '"a"', value: '{}', entries: [] },
|
||||
{ kind: 'pair', key: '"b"', value: '[1]' },
|
||||
expect(await collections(source)).toEqual([
|
||||
{ kind: 'map', entries: [
|
||||
{ kind: 'pair', key: '"published"', value: '"contests:publish"' },
|
||||
{ kind: 'pair', key: 'key', value: '1' },
|
||||
{ kind: 'pair', key: '"nested"', value: '{"a": {}}' },
|
||||
{ kind: 'spread', value: 'other' },
|
||||
] },
|
||||
{ kind: 'spread', value: 'other' },
|
||||
] }] })
|
||||
expect(found[8]).toEqual({ access: 'public', declarators: [{ name: 'EMPTY', value: '{}', entries: [] }] })
|
||||
expect(found[9]).toEqual({ access: 'public', declarators: [{ name: 'ITEMS', value: '[1]' }] })
|
||||
expect(found[11]).toEqual({ access: 'public', declarators: [{ name: 'labels', value: '{"x": 1}', entries: [{ kind: 'pair', key: '"x"', value: '1' }] }] })
|
||||
{ kind: 'map', entries: [{ kind: 'pair', key: '"a"', value: '{}' }] },
|
||||
{ kind: 'map', entries: [] },
|
||||
])
|
||||
})
|
||||
|
||||
it('列表、元组、集合:各项照源码顺序,*x 是展开,注释不算一项;值里的字面量另有自己的各项,空列表没有项', async () => {
|
||||
const source = [
|
||||
'filters = [',
|
||||
' Filter(field="user_id"),',
|
||||
' # 注释不算一项',
|
||||
' *rest,',
|
||||
' (a, b),',
|
||||
' {1},',
|
||||
' [],',
|
||||
']',
|
||||
].join('\n')
|
||||
expect(await collections(source)).toEqual([
|
||||
{ kind: 'sequence', elements: [
|
||||
{ kind: 'item', value: 'Filter(field="user_id")' },
|
||||
{ kind: 'spread', value: 'rest' },
|
||||
{ kind: 'item', value: '(a, b)' },
|
||||
{ kind: 'item', value: '{1}' },
|
||||
{ kind: 'item', value: '[]' },
|
||||
] },
|
||||
{ kind: 'sequence', elements: [{ kind: 'item', value: 'a' }, { kind: 'item', value: 'b' }] },
|
||||
{ kind: 'sequence', elements: [{ kind: 'item', value: '1' }] },
|
||||
{ kind: 'sequence', elements: [] },
|
||||
])
|
||||
})
|
||||
|
||||
it('推导式、括号里的一个式子、调用的实参列表、别的值不是', async () => {
|
||||
expect(await collections('x = [a for a in b]\ny = (a)\nf(a, b)\nz = a, b')).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Access, BlockShape, CallArgument, CallFacts, ClassFacts, CodeBlock, CommentBlock, EntryFacts, FunctionFacts, ImportFacts, ImportItem, IterationClause, IterationFacts, IterationResult, LanguageAdapter, Node, ParameterFacts, TextKind, TokenRole } from '../contract'
|
||||
import type { Access, BlockShape, CallArgument, CallFacts, ClassFacts, CodeBlock, CollectionFacts, CommentBlock, ElementFacts, EntryFacts, FunctionFacts, ImportFacts, ImportItem, IterationClause, IterationFacts, IterationResult, LanguageAdapter, Node, ParameterFacts, TextKind, TokenRole } from '../contract'
|
||||
import type { CommentRules, ExceptionRules } from './shared'
|
||||
import * as path from 'node:path'
|
||||
import { pythonNameReader } from './pythonNames'
|
||||
@@ -303,7 +303,7 @@ function expressionBlock(node: Node, scope: Scope, doc: Node | undefined): CodeB
|
||||
facts: {
|
||||
access: scopeAccess(left, scope),
|
||||
doc,
|
||||
declarators: [{ name: left, type: type ?? undefined, value: value ?? undefined, entries: dictionaryEntries(value) }],
|
||||
declarators: [{ name: left, type: type ?? undefined, value: value ?? undefined }],
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -314,21 +314,34 @@ function assignmentIn(statement: Node): Node | undefined {
|
||||
return expression?.type === 'assignment' ? expression : undefined
|
||||
}
|
||||
|
||||
/** 字典字面量的各项:`键: 值`(值又是字典时连它的各项)、`**other`;值不是字典字面量时没有。 */
|
||||
function dictionaryEntries(value: Node | null): EntryFacts[] | undefined {
|
||||
if (value?.type !== 'dictionary')
|
||||
/** 列表、元组、集合字面量(各项是 ElementFacts)的节点类型。 */
|
||||
const SEQUENCES = new Set(['list', 'tuple', 'set'])
|
||||
|
||||
/** 字面量的各项:字典的 `键: 值`、`**other`,列表、元组、集合的各项、`*other`;别的节点没有。 */
|
||||
function pythonCollection(node: Node): CollectionFacts | undefined {
|
||||
if (node.type === 'dictionary')
|
||||
return { kind: 'map', entries: syntaxChildren(node).flatMap(dictionaryEntry) }
|
||||
if (!SEQUENCES.has(node.type))
|
||||
return undefined
|
||||
return syntaxChildren(value).flatMap((item): EntryFacts[] => {
|
||||
if (item.type === 'dictionary_splat') {
|
||||
const [spread] = syntaxChildren(item)
|
||||
return {
|
||||
kind: 'sequence',
|
||||
elements: syntaxChildren(node).flatMap((element): ElementFacts[] => {
|
||||
if (element.type !== 'list_splat')
|
||||
return [{ kind: 'item', value: element }]
|
||||
const [spread] = syntaxChildren(element)
|
||||
return spread ? [{ kind: 'spread', value: spread }] : []
|
||||
}
|
||||
const key = item.childForFieldName('key')
|
||||
const itemValue = item.childForFieldName('value')
|
||||
if (item.type !== 'pair' || !key || !itemValue)
|
||||
return []
|
||||
return [{ kind: 'pair', key, value: itemValue, entries: dictionaryEntries(itemValue) }]
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
function dictionaryEntry(item: Node): EntryFacts[] {
|
||||
if (item.type === 'dictionary_splat') {
|
||||
const [spread] = syntaxChildren(item)
|
||||
return spread ? [{ kind: 'spread', value: spread }] : []
|
||||
}
|
||||
const key = item.childForFieldName('key')
|
||||
const value = item.childForFieldName('value')
|
||||
return item.type === 'pair' && key && value ? [{ kind: 'pair', key, value }] : []
|
||||
}
|
||||
|
||||
const ITERATION_RESULTS: Record<string, IterationResult> = {
|
||||
@@ -671,6 +684,7 @@ export function createPythonAdapter(wasmDir: string): LanguageAdapter {
|
||||
freshDoc,
|
||||
iteration: pythonIteration,
|
||||
call: pythonCall,
|
||||
collection: pythonCollection,
|
||||
displayNames: pythonNameReader,
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { toBlockViews } from '../blockView'
|
||||
import { blockMarks } from '../diff/viewDiff'
|
||||
import { rustImplRule } from '../rules/rustImpl'
|
||||
import { isCrateRoot } from '../rules/rustTree'
|
||||
import { commentText, outline, propertyLines, readFixture, viewLines, WASM_DIR, withBlocks } from '../testSupport'
|
||||
import { commentText, nodeFacts, outline, propertyLines, readFixture, viewLines, WASM_DIR, withBlocks } from '../testSupport'
|
||||
import { rustZhTranslator } from '../translators/rustZh'
|
||||
import { createRustAdapter } from './rust'
|
||||
|
||||
@@ -188,6 +188,29 @@ describe('rust 语言卡片', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('rust 字面量的各项', () => {
|
||||
it('数组、元组的各项照源码顺序,注释不算一项;[值; 个数]、别的值不是', async () => {
|
||||
const source = 'const A: [&str; 2] = [\n "a", // 第一个\n "b",\n];\nconst Z: [u8; 4] = [0; 4];\nconst T: (u8, u8) = (1, 2);\nfn f() { g(a, b); }'
|
||||
expect(await nodeFacts(adapter, 'rust', source, node => adapter.collection?.(node))).toEqual([
|
||||
{ kind: 'sequence', elements: [{ kind: 'item', value: '"a"' }, { kind: 'item', value: '"b"' }] },
|
||||
{ kind: 'sequence', elements: [{ kind: 'item', value: '1' }, { kind: 'item', value: '2' }] },
|
||||
])
|
||||
})
|
||||
|
||||
it('常量的值是跨几行写的数组、元组时按项拆开:「数组 N 项」,每项一行「第 N 项 | 值」;写在一行里的照旧', async () => {
|
||||
const source = 'pub const NAMES: [&str; 2] = [\n "a",\n "b",\n];\npub const PAIR: (u8, u8) = (\n 1,\n 2,\n);\npub const ONE: [u8; 2] = [1, 2];\n'
|
||||
expect(viewLines(await views(source)).filter(line => /[值第|]/.test(line))).toEqual([
|
||||
' 值: 数组 2 项',
|
||||
' 第 1 项 | "a"',
|
||||
' 第 2 项 | "b"',
|
||||
' 值: 元组 2 项',
|
||||
' 第 1 项 | 1',
|
||||
' 第 2 项 | 2',
|
||||
' 值: [1, 2]',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('rust 注释', () => {
|
||||
it('连着写的 // 合成一块注释,空的 // 是分段,预览是去掉 // 的 Markdown;后面的 use 照常是导入', async () => {
|
||||
const list = await views(readFixture('rustComments.rs'))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Access, AttributeFacts, AttributeItem, CfgPredicate, ClassFacts, CodeBlock, CommentBlock, EnumBlock, FunctionBlock, ImplBlock, ImportBlock, ImportItem, LanguageAdapter, Node, ParameterFacts, SourceSpan, TokenRole, TraitBlock } from '../contract'
|
||||
import type { Access, AttributeFacts, AttributeItem, CfgPredicate, ClassFacts, CodeBlock, CollectionFacts, CommentBlock, EnumBlock, FunctionBlock, ImplBlock, ImportBlock, ImportItem, LanguageAdapter, Node, ParameterFacts, SourceSpan, TokenRole, TraitBlock } from '../contract'
|
||||
import type { CommentRules } from './shared'
|
||||
import * as path from 'node:path'
|
||||
import { leadingAttributes, visibilityFacts } from '../rules/rustTree'
|
||||
import { attachComments, children, compoundShape, extendHeader, headerSpan, isCommentNode, leafBlock, leafShape, listBlocks, named } from './shared'
|
||||
import { attachComments, children, compoundShape, extendHeader, headerSpan, isCommentNode, leafBlock, leafShape, listBlocks, named, syntaxChildren } from './shared'
|
||||
|
||||
const STORAGE = new Set(['pub', 'async', 'const', 'static', 'mut', 'let'])
|
||||
|
||||
@@ -15,9 +15,18 @@ export function createRustAdapter(wasmDir: string): LanguageAdapter {
|
||||
tokenRole: rustTokenRole,
|
||||
lineComment: '//',
|
||||
freshDoc,
|
||||
collection: rustCollection,
|
||||
}
|
||||
}
|
||||
|
||||
/** 数组 `[a, b]`、元组 `(a, b)` 的各项;`[值; 个数]` 不是一项项写出来的,别的节点也没有。项前面的 `#[…]` 不算一项。 */
|
||||
function rustCollection(node: Node): CollectionFacts | undefined {
|
||||
const listed = node.type === 'tuple_expression' || (node.type === 'array_expression' && !node.childForFieldName('length'))
|
||||
if (!listed)
|
||||
return undefined
|
||||
return { kind: 'sequence', elements: syntaxChildren(node).filter(child => child.type !== 'attribute_item').map(value => ({ kind: 'item', value })) }
|
||||
}
|
||||
|
||||
/** extern 块本身不成一块源码,里面的签名跟所在这一层的别的项走同一条路。 */
|
||||
function unwrapExtern(item: Node): Node[] {
|
||||
if (item.type !== 'foreign_mod_item')
|
||||
|
||||
@@ -338,54 +338,13 @@ describe('typeScript 属性表信息(facts)', () => {
|
||||
name: 'result',
|
||||
type: 'EnvLockResult',
|
||||
value: '{ total: files.length, ok: [], failed: [] }',
|
||||
entries: [
|
||||
{ kind: 'pair', key: 'total', value: 'files.length' },
|
||||
{ kind: 'pair', key: 'ok', value: '[]' },
|
||||
{ kind: 'pair', key: 'failed', value: '[]' },
|
||||
],
|
||||
}] })
|
||||
})
|
||||
|
||||
it('对象字面量的各项:各种键、简写(键和值是同一个节点)、展开、方法(头部到主体之前)、嵌套对象连它的各项;空对象是空数组,别的值没有', async () => {
|
||||
const source = [
|
||||
'const o = {',
|
||||
' a: 1,',
|
||||
' \'b-c\': x,',
|
||||
' [k]: 2,',
|
||||
' s,',
|
||||
' ...rest,',
|
||||
' // 注释不算一项',
|
||||
' async load(id: string): Promise<void> {',
|
||||
' await run(id)',
|
||||
' },',
|
||||
' get size() { return 1 },',
|
||||
' n: { d: 4, e: {} },',
|
||||
'}',
|
||||
'const empty = {}',
|
||||
'const list = [1]',
|
||||
].join('\n')
|
||||
const at = (text: string): number => source.indexOf(text)
|
||||
const found = await facts(source)
|
||||
expect(found[1]).toMatchObject({ declarators: [{ entries: [
|
||||
{ kind: 'pair', key: 'a', value: '1' },
|
||||
{ kind: 'pair', key: '\'b-c\'', value: 'x' },
|
||||
{ kind: 'pair', key: '[k]', value: '2' },
|
||||
{ kind: 'pair', key: 's', value: 's' },
|
||||
{ kind: 'spread', value: 'rest' },
|
||||
{
|
||||
kind: 'method',
|
||||
name: 'load',
|
||||
node: 'async load(id: string): Promise<void> {\n await run(id)\n }',
|
||||
header: { startIndex: at('async load'), endIndex: at(' {\n await'), startRow: 7, endRow: 7 },
|
||||
},
|
||||
{ kind: 'method', name: 'size', header: { startIndex: at('get size'), endIndex: at(' { return 1'), startRow: 10, endRow: 10 } },
|
||||
{ kind: 'pair', key: 'n', value: '{ d: 4, e: {} }', entries: [
|
||||
{ kind: 'pair', key: 'd', value: '4' },
|
||||
{ kind: 'pair', key: 'e', value: '{}', entries: [] },
|
||||
] },
|
||||
] }] })
|
||||
expect(found[14]).toEqual({ access: 'private', declarators: [{ name: 'empty', value: '{}', entries: [] }] })
|
||||
expect(found[15]).toEqual({ access: 'private', declarators: [{ name: 'list', value: '[1]' }] })
|
||||
it('声明的值照源码给,字面量的各项不在 facts 里(见 LanguageAdapter.collection)', async () => {
|
||||
const found = await facts('const empty = {}\nconst list = [1]')
|
||||
expect(found[1]).toEqual({ access: 'private', declarators: [{ name: 'empty', value: '{}' }] })
|
||||
expect(found[2]).toEqual({ access: 'private', declarators: [{ name: 'list', value: '[1]' }] })
|
||||
})
|
||||
|
||||
it('导入:默认导入、* as、仅类型、副作用导入、require', async () => {
|
||||
@@ -485,6 +444,72 @@ describe('typeScript 属性表信息(facts)', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('typeScript 字面量的各项', () => {
|
||||
const collections = (source: string): Promise<unknown[]> => nodeFacts(adapter, 'typescript', source, node => adapter.collection?.(node))
|
||||
|
||||
it('对象:各种键、简写(键和值是同一个节点)、展开、方法(头部到主体之前),注释不算一项;值里的对象另有自己的各项,空对象没有项', async () => {
|
||||
const source = [
|
||||
'const o = {',
|
||||
' a: 1,',
|
||||
' \'b-c\': x,',
|
||||
' [k]: 2,',
|
||||
' s,',
|
||||
' ...rest,',
|
||||
' // 注释不算一项',
|
||||
' async load(id: string): Promise<void> {',
|
||||
' await run(id)',
|
||||
' },',
|
||||
' get size() { return 1 },',
|
||||
' n: { d: 4, e: {} },',
|
||||
'}',
|
||||
].join('\n')
|
||||
const at = (text: string): number => source.indexOf(text)
|
||||
expect(await collections(source)).toEqual([
|
||||
{ kind: 'map', entries: [
|
||||
{ kind: 'pair', key: 'a', value: '1' },
|
||||
{ kind: 'pair', key: '\'b-c\'', value: 'x' },
|
||||
{ kind: 'pair', key: '[k]', value: '2' },
|
||||
{ kind: 'pair', key: 's', value: 's' },
|
||||
{ kind: 'spread', value: 'rest' },
|
||||
{
|
||||
kind: 'method',
|
||||
name: 'load',
|
||||
node: 'async load(id: string): Promise<void> {\n await run(id)\n }',
|
||||
header: { startIndex: at('async load'), endIndex: at(' {\n await'), startRow: 7, endRow: 7 },
|
||||
},
|
||||
{ kind: 'method', name: 'size', node: 'get size() { return 1 }', header: { startIndex: at('get size'), endIndex: at(' { return 1'), startRow: 10, endRow: 10 } },
|
||||
{ kind: 'pair', key: 'n', value: '{ d: 4, e: {} }' },
|
||||
] },
|
||||
{ kind: 'map', entries: [{ kind: 'pair', key: 'd', value: '4' }, { kind: 'pair', key: 'e', value: '{}' }] },
|
||||
{ kind: 'map', entries: [] },
|
||||
])
|
||||
})
|
||||
|
||||
it('数组:各项照源码顺序,...x 是展开,注释不算一项;值里的字面量另有自己的各项,空数组没有项', async () => {
|
||||
const source = [
|
||||
'const filters = [',
|
||||
' new Filter({ field: \'user_id\' }),',
|
||||
' // 注释不算一项',
|
||||
' ...rest,',
|
||||
' [],',
|
||||
']',
|
||||
].join('\n')
|
||||
expect(await collections(source)).toEqual([
|
||||
{ kind: 'sequence', elements: [
|
||||
{ kind: 'item', value: 'new Filter({ field: \'user_id\' })' },
|
||||
{ kind: 'spread', value: 'rest' },
|
||||
{ kind: 'item', value: '[]' },
|
||||
] },
|
||||
{ kind: 'map', entries: [{ kind: 'pair', key: 'field', value: '\'user_id\'' }] },
|
||||
{ kind: 'sequence', elements: [] },
|
||||
])
|
||||
})
|
||||
|
||||
it('数组形式的解构、类型里的元组、别的值不是', async () => {
|
||||
expect(await collections('const [a, b] = pair\nlet t: [string, number]\nf(a, b)')).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('typeScript 类', () => {
|
||||
it('classes.ts:紧贴的 JSDoc(隔着装饰器也算)算进类头部;类表达式赋给变量、类字段也是类块;函数里的类照常成块', async () => {
|
||||
expect(await tree(readFixture('classes.ts.txt'))).toEqual([
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Access, BaseFacts, BlockShape, CallArgument, CallFacts, ClassFacts, CodeBlock, CommentBlock, DeclaratorFacts, EntryFacts, EnumMemberFacts, FunctionFacts, ImportFacts, ImportItem, LanguageAdapter, Node, ParameterFacts, TextKind, TokenRole } from '../contract'
|
||||
import type { Access, BaseFacts, BlockShape, CallArgument, CallFacts, ClassFacts, CodeBlock, CollectionFacts, CommentBlock, DeclaratorFacts, ElementFacts, EntryFacts, EnumMemberFacts, FunctionFacts, ImportFacts, ImportItem, LanguageAdapter, Node, ParameterFacts, TextKind, TokenRole } from '../contract'
|
||||
import type { CommentRules, ExceptionRules } from './shared'
|
||||
import * as path from 'node:path'
|
||||
import { attachComments, children, compoundShape, extendHeader, headerSpan, leafBlock, leafShape, listBlocks, named, nodeSpan, sameNode, syntaxChildren, withExceptions } from './shared'
|
||||
@@ -153,36 +153,47 @@ function declaratorFacts(declarator: Node): DeclaratorFacts {
|
||||
name: declarator.childForFieldName('name') ?? declarator,
|
||||
type: annotatedType(declarator.childForFieldName('type')),
|
||||
value: value ?? undefined,
|
||||
entries: objectEntries(value),
|
||||
}
|
||||
}
|
||||
|
||||
/** 对象字面量的各项:`键: 值`(值又是对象时连它的各项)、简写 `{ a }`、`...other`、方法;值不是对象字面量时没有。 */
|
||||
function objectEntries(value: Node | null): EntryFacts[] | undefined {
|
||||
if (value?.type !== 'object')
|
||||
/** 字面量的各项:对象的 `键: 值`、简写 `{ a }`、`...other`、方法,数组的各项、`...other`;别的节点没有。 */
|
||||
function typescriptCollection(node: Node): CollectionFacts | undefined {
|
||||
if (node.type === 'object')
|
||||
return { kind: 'map', entries: syntaxChildren(node).flatMap(objectEntry) }
|
||||
if (node.type !== 'array')
|
||||
return undefined
|
||||
return syntaxChildren(value).flatMap((member): EntryFacts[] => {
|
||||
switch (member.type) {
|
||||
case 'pair': {
|
||||
const key = member.childForFieldName('key')
|
||||
const memberValue = member.childForFieldName('value')
|
||||
return key && memberValue ? [{ kind: 'pair', key, value: memberValue, entries: objectEntries(memberValue) }] : []
|
||||
}
|
||||
case 'shorthand_property_identifier':
|
||||
return [{ kind: 'pair', key: member, value: member }]
|
||||
case 'spread_element': {
|
||||
const [spread] = syntaxChildren(member)
|
||||
return spread ? [{ kind: 'spread', value: spread }] : []
|
||||
}
|
||||
case 'method_definition': {
|
||||
const name = member.childForFieldName('name')
|
||||
const body = member.childForFieldName('body')
|
||||
return name ? [{ kind: 'method', name, node: member, header: body ? headerSpan(member, body.startIndex) : nodeSpan(member) }] : []
|
||||
}
|
||||
default:
|
||||
return []
|
||||
return {
|
||||
kind: 'sequence',
|
||||
elements: syntaxChildren(node).flatMap((element): ElementFacts[] => {
|
||||
if (element.type !== 'spread_element')
|
||||
return [{ kind: 'item', value: element }]
|
||||
const [spread] = syntaxChildren(element)
|
||||
return spread ? [{ kind: 'spread', value: spread }] : []
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
function objectEntry(member: Node): EntryFacts[] {
|
||||
switch (member.type) {
|
||||
case 'pair': {
|
||||
const key = member.childForFieldName('key')
|
||||
const value = member.childForFieldName('value')
|
||||
return key && value ? [{ kind: 'pair', key, value }] : []
|
||||
}
|
||||
})
|
||||
case 'shorthand_property_identifier':
|
||||
return [{ kind: 'pair', key: member, value: member }]
|
||||
case 'spread_element': {
|
||||
const [spread] = syntaxChildren(member)
|
||||
return spread ? [{ kind: 'spread', value: spread }] : []
|
||||
}
|
||||
case 'method_definition': {
|
||||
const name = member.childForFieldName('name')
|
||||
const body = member.childForFieldName('body')
|
||||
return name ? [{ kind: 'method', name, node: member, header: body ? headerSpan(member, body.startIndex) : nodeSpan(member) }] : []
|
||||
}
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/** import 语句:默认导入、`* as x`、`{ a as b }`、`import x = require('m')`;TypeScript(typed)的 `import type` 只导入类型。 */
|
||||
@@ -658,6 +669,7 @@ export function createTypeScriptAdapter(wasmDir: string): LanguageAdapter {
|
||||
lineComment: '//',
|
||||
freshDoc,
|
||||
call: typescriptCall,
|
||||
collection: typescriptCollection,
|
||||
displayNames: typescriptNameReader,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user