🐛 fix(vscode): 调用树不统计测试代码
This commit is contained in:
1 parent
eff84a4df3
commit
066681d601
3 files changed
+80
-2
No files matched your search
@@ -10,6 +10,10 @@ function range(line: number, character = 0): CallRange {
|
||||
return { line, character, endLine: line, endCharacter: character + 3 }
|
||||
}
|
||||
|
||||
function symbolIn(path: string, name: string): CallSymbol {
|
||||
return { ...symbol(name), path }
|
||||
}
|
||||
|
||||
describe('顺着调用者往上收集调用边', () => {
|
||||
it('有环就停,不再问已经走过的那个', async () => {
|
||||
const target = symbol('mask_phone')
|
||||
@@ -85,6 +89,73 @@ describe('顺着调用者往上收集调用边', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('业务代码的调用者里有测试函数:测试函数不当调用者,也不再往上问', async () => {
|
||||
const target = symbolIn('app/sync.py', 'sync_users')
|
||||
const job = symbolIn('app/jobs.py', 'run_jobs')
|
||||
const inTestsDir = symbolIn('tests/test_sync.py', 'test_sync_runs')
|
||||
const byFileName = symbolIn('test_x.py', 'test_x')
|
||||
const asked: string[] = []
|
||||
const outgoingAsked: string[] = []
|
||||
const edges = await collectCallEdges(target, async (node) => {
|
||||
asked.push(node.name)
|
||||
if (node.name === 'sync_users') {
|
||||
return [
|
||||
{ from: inTestsDir, ranges: [range(3)] },
|
||||
{ from: byFileName, ranges: [range(5)] },
|
||||
{ from: job, ranges: [range(7)] },
|
||||
]
|
||||
}
|
||||
return []
|
||||
}, async (node) => {
|
||||
outgoingAsked.push(node.name)
|
||||
return []
|
||||
})
|
||||
expect(asked).toEqual(['sync_users', 'run_jobs'])
|
||||
expect(outgoingAsked).toEqual(['run_jobs'])
|
||||
expect(edges).toEqual([{ caller: job, callee: target, at: range(7) }])
|
||||
})
|
||||
|
||||
it('往下问到的被调用方在测试文件里,这条边不收', async () => {
|
||||
const target = symbolIn('app/sync.py', 'sync_users')
|
||||
const job = symbolIn('app/jobs.py', 'run_jobs')
|
||||
const fixture = symbolIn('tests/conftest.py', 'make_user')
|
||||
const side = symbolIn('app/log.py', 'log_event')
|
||||
const edges = await collectCallEdges(target, async (node) => {
|
||||
if (node.name === 'sync_users')
|
||||
return [{ from: job, ranges: [range(4)] }]
|
||||
return []
|
||||
}, async () => [
|
||||
{ to: target, ranges: [range(4)] },
|
||||
{ to: fixture, ranges: [range(6)] },
|
||||
{ to: side, ranges: [range(8)] },
|
||||
])
|
||||
expect(edges).toEqual([
|
||||
{ caller: job, callee: target, at: range(4) },
|
||||
{ caller: job, callee: side, at: range(8) },
|
||||
])
|
||||
})
|
||||
|
||||
it('当前块本身在测试文件里:测试函数照样当调用者,往下问到的测试代码也收', async () => {
|
||||
const target = symbolIn('tests/conftest.py', 'make_user')
|
||||
const caller = symbolIn('tests/test_sync.py', 'test_sync_runs')
|
||||
const helper = symbolIn('tests/helpers.py', 'fake_db')
|
||||
const asked: string[] = []
|
||||
const edges = await collectCallEdges(target, async (node) => {
|
||||
asked.push(node.name)
|
||||
if (node.name === 'make_user')
|
||||
return [{ from: caller, ranges: [range(2)] }]
|
||||
return []
|
||||
}, async () => [
|
||||
{ to: target, ranges: [range(2)] },
|
||||
{ to: helper, ranges: [range(5)] },
|
||||
])
|
||||
expect(asked).toEqual(['make_user', 'test_sync_runs'])
|
||||
expect(edges).toEqual([
|
||||
{ caller, callee: target, at: range(2) },
|
||||
{ caller, callee: helper, at: range(5) },
|
||||
])
|
||||
})
|
||||
|
||||
it('取消之后不再问下一个人', async () => {
|
||||
const target = symbol('mask_phone')
|
||||
const caller = symbol('get_profile')
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import type { CallEdge, CallRange, CallSymbol } from './model'
|
||||
import { isTestFile } from '../uncommitted/testFiles'
|
||||
import { CALL_TREE_MAX_DEPTH, symbolKey } from './model'
|
||||
|
||||
/** 一个调用者,以及它里面每一处调用的范围。 */
|
||||
@@ -22,6 +23,8 @@ export interface OutgoingHit {
|
||||
* 收集通向 start 的调用边,再加上这些调用者通向别处的边。
|
||||
* 有环就停。往上最多 8 层。cancelled 变成真就停,已经收到的也不要了。
|
||||
* start 自己不再往下问:它调用了谁不画在这棵树上。
|
||||
* start 不在测试文件里时,测试文件(见 isTestFile)里的符号不算:不当调用者,不再往上问,往下问到的被调用方在测试文件里也不收。
|
||||
* start 本身在测试文件里,说明正在读测试代码,就照常全收。
|
||||
*/
|
||||
export async function collectCallEdges(
|
||||
start: CallSymbol,
|
||||
@@ -36,6 +39,8 @@ export async function collectCallEdges(
|
||||
const ancestors = new Map<string, CallSymbol>()
|
||||
const walked = new Map<string, number>()
|
||||
const startKey = symbolKey(start)
|
||||
const readingTests = isTestFile(start.path)
|
||||
const counted = (symbol: CallSymbol) => readingTests || !isTestFile(symbol.path)
|
||||
|
||||
const add = (caller: CallSymbol, callee: CallSymbol, at: CallRange) => {
|
||||
const edge: CallEdge = { caller, callee, at }
|
||||
@@ -57,7 +62,7 @@ export async function collectCallEdges(
|
||||
const next = new Map<string, CallSymbol>()
|
||||
for (const call of calls) {
|
||||
const key = symbolKey(call.from)
|
||||
if (here.has(key))
|
||||
if (here.has(key) || !counted(call.from))
|
||||
continue
|
||||
for (const at of uniqueRanges(call.ranges))
|
||||
add(call.from, node, at)
|
||||
@@ -87,6 +92,8 @@ export async function collectCallEdges(
|
||||
if (cancelled())
|
||||
return []
|
||||
for (const call of calls) {
|
||||
if (!counted(call.to))
|
||||
continue
|
||||
for (const at of uniqueRanges(call.ranges))
|
||||
add(ancestor, call.to, at)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const TEST_FILE_NAMES: readonly RegExp[] = [
|
||||
|
||||
/**
|
||||
* 是不是测试文件:路径上有一层目录是测试目录,或者文件名照测试文件的约定起。
|
||||
* 「未提交的更改」和审查隐藏测试文件时按它剔除。
|
||||
* 「未提交的更改」和审查隐藏测试文件、调用树不算测试代码,都按它认。
|
||||
* @param path 相对仓库根,`/` 分隔
|
||||
*/
|
||||
export function isTestFile(path: string): boolean {
|
||||
|
||||
Reference in new issue
Block a user