⚡ perf(vscode): React 规则认组件体里的块时不合组件函数写法的直接放过,同一棵语法树的组件体只读一次;规格补上 React 三种卡片的图标
This commit is contained in:
1 parent
6568182709
commit
70a53e5a68
3 files changed
+33
-8
No files matched your search
@@ -391,6 +391,18 @@ interface Analysis {
|
||||
body: BodyFacts
|
||||
}
|
||||
|
||||
/** 一棵语法树里各组件体读出来的(按组件主体的起始下标):认领组件和它里面每一块时都要用,同一棵树读一次就够。 */
|
||||
const bodies = new WeakMap<object, Map<number, BodyFacts>>()
|
||||
|
||||
function analysisOf(component: ComponentFacts): Analysis {
|
||||
const tree = component.body.tree
|
||||
const known = bodies.get(tree) ?? new Map<number, BodyFacts>()
|
||||
bodies.set(tree, known)
|
||||
const body = known.get(component.body.startIndex) ?? bodyOf(component)
|
||||
known.set(component.body.startIndex, body)
|
||||
return { component, body }
|
||||
}
|
||||
|
||||
function keyword(text: string): Inline {
|
||||
return { text, role: 'keyword' }
|
||||
}
|
||||
@@ -724,7 +736,7 @@ function nestedCard(block: CodeBlock, env: Env): RuleCard | undefined {
|
||||
const component = enclosingComponent(block.node)
|
||||
if (!component)
|
||||
return undefined
|
||||
const body = bodyOf(component)
|
||||
const { body } = analysisOf(component)
|
||||
const at = (facts: { statement: Node }): boolean => sameNode(facts.statement, block.node)
|
||||
const effect = body.effects.find(at)
|
||||
if (effect)
|
||||
@@ -927,7 +939,7 @@ function renderRow(analysis: Analysis, env: Env): PropertyRow {
|
||||
/** 组件卡片。 */
|
||||
function componentCard(block: CodeBlock, component: ComponentFacts, env: Env): RuleCard {
|
||||
const { words } = env
|
||||
const analysis: Analysis = { component, body: bodyOf(component) }
|
||||
const analysis = analysisOf(component)
|
||||
const { body } = analysis
|
||||
const rows: PropertyRow[] = [nameRow(component, env), ...docRows(component, env), propsRow(component, env)]
|
||||
const absorbs: CodeBlock[] = []
|
||||
|
||||
@@ -282,13 +282,26 @@ export function componentsIn(root: Node): ComponentFacts[] {
|
||||
/** 语句直接写在哪个组件的组件体里(组件体是语句块时);不是组件体里的语句时没有。 */
|
||||
export function enclosingComponent(statement: Node): ComponentFacts | undefined {
|
||||
const body = statement.parent
|
||||
if (body?.type !== 'statement_block')
|
||||
const fn = body?.type === 'statement_block' ? body.parent : null
|
||||
if (!fn || !isFunction(fn))
|
||||
return undefined
|
||||
let outer: Node | null = body.parent
|
||||
while (outer && !['export_statement', 'lexical_declaration', 'variable_declaration', 'function_declaration'].includes(outer.type))
|
||||
// 组件函数只会是函数声明、变量的值,或 memo / forwardRef 的实参(可以套几层);别的函数(副作用、处理函数)里的语句不用再往上找
|
||||
let outer: Node | null = fn
|
||||
if (fn.type !== 'function_declaration') {
|
||||
let value: Node = fn
|
||||
for (let parent = value.parent; parent; parent = value.parent) {
|
||||
const call = parent.type === 'arguments' ? parent.parent : null
|
||||
if (parent.type === 'parenthesized_expression')
|
||||
value = parent
|
||||
else if (call?.type === 'call_expression' && WRAPPERS[calleeName(call)?.text ?? ''])
|
||||
value = call
|
||||
else
|
||||
break
|
||||
}
|
||||
outer = value.parent?.type === 'variable_declarator' ? value.parent.parent : null
|
||||
}
|
||||
if (outer?.parent?.type === 'export_statement')
|
||||
outer = outer.parent
|
||||
if (outer?.type === 'lexical_declaration' || outer?.type === 'variable_declaration' || outer?.type === 'function_declaration')
|
||||
outer = outer.parent?.type === 'export_statement' ? outer.parent : outer
|
||||
const component = outer ? componentAt(outer) : undefined
|
||||
return component && sameNode(component.body, body) ? component : undefined
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user