fix: 修复了在箭头函数下检查不生效的问题
This commit is contained in:
parent
d71a223138
commit
dc071a47fd
|
|
@ -6,6 +6,12 @@ const ts = tslib_1.__importStar(require("typescript"));
|
|||
const path = tslib_1.__importStar(require("path"));
|
||||
const fs = tslib_1.__importStar(require("fs"));
|
||||
const process_1 = require("process");
|
||||
const verboseLogging = false;
|
||||
const log = (...args) => {
|
||||
if (verboseLogging) {
|
||||
console.log('[tscBuilder]', ...args);
|
||||
}
|
||||
};
|
||||
exports.OAK_IGNORE_TAGS = [
|
||||
'@oak-ignore',
|
||||
'@oak-ignore-asynccontext',
|
||||
|
|
@ -92,6 +98,10 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
|||
if (!ts.isPropertyAccessExpression(node.expression)) {
|
||||
return;
|
||||
}
|
||||
// 如果上一层是return,则先跳过,让外层函数调用来处理
|
||||
if (ts.isReturnStatement(node.parent)) {
|
||||
return;
|
||||
}
|
||||
const propertyAccess = node.expression;
|
||||
const objectExpression = propertyAccess.expression;
|
||||
// 获取对象的类型
|
||||
|
|
@ -315,17 +325,26 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
|||
if (!ts.isCallExpression(node)) {
|
||||
return;
|
||||
}
|
||||
// 添加这里 - 打印所有函数调用
|
||||
const sourceFile = node.getSourceFile();
|
||||
const callText = node.expression.getText(sourceFile);
|
||||
log(`[DEBUG] 检查函数调用: ${callText}`);
|
||||
// 获取被调用函数的符号
|
||||
const signature = typeChecker.getResolvedSignature(node);
|
||||
if (!signature) {
|
||||
log(`[DEBUG] ${callText} - 无法获取签名`);
|
||||
return;
|
||||
}
|
||||
const declaration = signature.getDeclaration();
|
||||
if (!declaration) {
|
||||
log(`[DEBUG] ${callText} - 无法获取声明`);
|
||||
return;
|
||||
}
|
||||
log(`[DEBUG] ${callText} - 声明类型: ${ts.SyntaxKind[declaration.kind]}`);
|
||||
// 检查这个函数是否包含 context 调用
|
||||
if (containsContextCall(declaration)) {
|
||||
const hasContext = containsContextCall(declaration);
|
||||
log(`[DEBUG] ${callText} - 包含context调用: ${hasContext}`);
|
||||
if (hasContext) {
|
||||
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
||||
// 如果函数不返回 Promise,说明内部已经正确处理了异步调用
|
||||
// 此时调用该函数不需要 await
|
||||
|
|
@ -336,14 +355,18 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
|||
const containingFunction = findContainingFunction(node);
|
||||
if (containingFunction) {
|
||||
const fname = getFunctionName(containingFunction);
|
||||
if (!fname) {
|
||||
return;
|
||||
}
|
||||
const symbol = typeChecker.getSymbolAtLocation(fname);
|
||||
if (symbol) {
|
||||
functionsWithContextCalls.add(symbol);
|
||||
if (fname) { // 只有当有名称时才标记,但不影响后续检查
|
||||
const symbol = typeChecker.getSymbolAtLocation(fname);
|
||||
if (symbol) {
|
||||
functionsWithContextCalls.add(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ts.isReturnStatement(node.parent)) {
|
||||
// 如果在 return 语句中,不在这里报警告
|
||||
// 警告会传播到调用当前函数的地方
|
||||
return;
|
||||
}
|
||||
// 检查是否被 await
|
||||
if (!isAwaited(node)) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
|
|
@ -366,7 +389,9 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
|||
// 辅助函数:检查函数声明是否包含 context 调用
|
||||
function containsContextCall(node) {
|
||||
const symbol = getSymbolOfDeclaration(node);
|
||||
log(`[DEBUG containsContextCall] 节点类型: ${ts.SyntaxKind[node.kind]}, 有符号: ${!!symbol}`);
|
||||
if (symbol && checkedFunctions.has(symbol)) {
|
||||
log(`[DEBUG containsContextCall] 使用缓存结果: ${checkedFunctions.get(symbol)}`);
|
||||
return checkedFunctions.get(symbol);
|
||||
}
|
||||
let hasContextCall = false;
|
||||
|
|
@ -380,6 +405,7 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
|||
const targetModules = customConfig.context?.targetModules ||
|
||||
['@project/context/BackendRuntimeContext'];
|
||||
if (isAsyncContextType(objectType, targetModules)) {
|
||||
log(`[DEBUG containsContextCall] 找到context调用: ${n.expression.getText()}`);
|
||||
hasContextCall = true;
|
||||
return;
|
||||
}
|
||||
|
|
@ -392,16 +418,23 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
|||
if (declaration && !isSameOrDescendant(declaration, node)) {
|
||||
// 避免无限递归
|
||||
const symbol = getSymbolOfDeclaration(declaration);
|
||||
// 先检查缓存
|
||||
if (symbol && functionsWithContextCalls.has(symbol)) {
|
||||
hasContextCall = true;
|
||||
return;
|
||||
}
|
||||
// 如果缓存中没有,递归检查该函数
|
||||
if (containsContextCall(declaration)) {
|
||||
hasContextCall = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ts.forEachChild(n, visit);
|
||||
}
|
||||
visit(node);
|
||||
log(`[DEBUG containsContextCall] 最终结果: ${hasContextCall}`);
|
||||
if (symbol) {
|
||||
checkedFunctions.set(symbol, hasContextCall);
|
||||
}
|
||||
|
|
@ -451,9 +484,21 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
|||
}
|
||||
// 辅助函数:获取声明的符号
|
||||
function getSymbolOfDeclaration(declaration) {
|
||||
// 处理有名称的声明(函数声明、方法声明等)
|
||||
if ('name' in declaration && declaration.name) {
|
||||
return typeChecker.getSymbolAtLocation(declaration.name);
|
||||
}
|
||||
// 处理箭头函数:尝试从父节点(变量声明)获取符号
|
||||
if (ts.isArrowFunction(declaration) || ts.isFunctionExpression(declaration)) {
|
||||
const parent = declaration.parent;
|
||||
if (ts.isVariableDeclaration(parent) && parent.name) {
|
||||
return typeChecker.getSymbolAtLocation(parent.name);
|
||||
}
|
||||
// 处理作为属性值的情况
|
||||
if (ts.isPropertyAssignment(parent) && parent.name) {
|
||||
return typeChecker.getSymbolAtLocation(parent.name);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return diagnostics;
|
||||
|
|
@ -511,7 +556,7 @@ function compile(configPath) {
|
|||
const allDiagnostics = [
|
||||
...ts.getPreEmitDiagnostics(program),
|
||||
...emitResult.diagnostics,
|
||||
...customDiagnostics
|
||||
...customDiagnostics || []
|
||||
];
|
||||
// 输出诊断信息
|
||||
allDiagnostics.forEach((diagnostic) => {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,14 @@ import * as path from 'path';
|
|||
import * as fs from 'fs';
|
||||
import { cwd } from 'process';
|
||||
|
||||
const verboseLogging = false;
|
||||
|
||||
const log = (...args: any[]) => {
|
||||
if (verboseLogging) {
|
||||
console.log('[tscBuilder]', ...args);
|
||||
}
|
||||
};
|
||||
|
||||
export const OAK_IGNORE_TAGS = [
|
||||
'@oak-ignore',
|
||||
'@oak-ignore-asynccontext',
|
||||
|
|
@ -145,6 +153,11 @@ function performCustomChecks(
|
|||
return;
|
||||
}
|
||||
|
||||
// 如果上一层是return,则先跳过,让外层函数调用来处理
|
||||
if (ts.isReturnStatement(node.parent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const propertyAccess = node.expression;
|
||||
const objectExpression = propertyAccess.expression;
|
||||
|
||||
|
|
@ -416,19 +429,31 @@ function performCustomChecks(
|
|||
return;
|
||||
}
|
||||
|
||||
// 添加这里 - 打印所有函数调用
|
||||
const sourceFile = node.getSourceFile();
|
||||
const callText = node.expression.getText(sourceFile);
|
||||
log(`[DEBUG] 检查函数调用: ${callText}`);
|
||||
|
||||
// 获取被调用函数的符号
|
||||
const signature = typeChecker.getResolvedSignature(node);
|
||||
if (!signature) {
|
||||
log(`[DEBUG] ${callText} - 无法获取签名`);
|
||||
return;
|
||||
}
|
||||
|
||||
const declaration = signature.getDeclaration();
|
||||
if (!declaration) {
|
||||
log(`[DEBUG] ${callText} - 无法获取声明`);
|
||||
return;
|
||||
}
|
||||
|
||||
log(`[DEBUG] ${callText} - 声明类型: ${ts.SyntaxKind[declaration.kind]}`);
|
||||
|
||||
// 检查这个函数是否包含 context 调用
|
||||
if (containsContextCall(declaration)) {
|
||||
const hasContext = containsContextCall(declaration);
|
||||
log(`[DEBUG] ${callText} - 包含context调用: ${hasContext}`);
|
||||
|
||||
if (hasContext) {
|
||||
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
||||
|
||||
// 如果函数不返回 Promise,说明内部已经正确处理了异步调用
|
||||
|
|
@ -436,22 +461,25 @@ function performCustomChecks(
|
|||
if (!isPromiseType(returnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 标记当前所在的函数
|
||||
const containingFunction = findContainingFunction(node);
|
||||
if (containingFunction) {
|
||||
const fname = getFunctionName(containingFunction)
|
||||
if (!fname) {
|
||||
return;
|
||||
}
|
||||
const symbol = typeChecker.getSymbolAtLocation(
|
||||
fname
|
||||
);
|
||||
if (symbol) {
|
||||
functionsWithContextCalls.add(symbol);
|
||||
const fname = getFunctionName(containingFunction);
|
||||
if (fname) { // 只有当有名称时才标记,但不影响后续检查
|
||||
const symbol = typeChecker.getSymbolAtLocation(fname);
|
||||
if (symbol) {
|
||||
functionsWithContextCalls.add(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ts.isReturnStatement(node.parent)) {
|
||||
// 如果在 return 语句中,不在这里报警告
|
||||
// 警告会传播到调用当前函数的地方
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否被 await
|
||||
if (!isAwaited(node)) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
|
|
@ -478,10 +506,15 @@ function performCustomChecks(
|
|||
// 辅助函数:检查函数声明是否包含 context 调用
|
||||
function containsContextCall(node: ts.Node): boolean {
|
||||
const symbol = getSymbolOfDeclaration(node as ts.SignatureDeclaration);
|
||||
|
||||
log(`[DEBUG containsContextCall] 节点类型: ${ts.SyntaxKind[node.kind]}, 有符号: ${!!symbol}`);
|
||||
|
||||
if (symbol && checkedFunctions.has(symbol)) {
|
||||
log(`[DEBUG containsContextCall] 使用缓存结果: ${checkedFunctions.get(symbol)}`);
|
||||
return checkedFunctions.get(symbol)!;
|
||||
}
|
||||
|
||||
|
||||
let hasContextCall = false;
|
||||
|
||||
function visit(n: ts.Node): void {
|
||||
|
|
@ -495,6 +528,7 @@ function performCustomChecks(
|
|||
['@project/context/BackendRuntimeContext'];
|
||||
|
||||
if (isAsyncContextType(objectType, targetModules)) {
|
||||
log(`[DEBUG containsContextCall] 找到context调用: ${n.expression.getText()}`);
|
||||
hasContextCall = true;
|
||||
return;
|
||||
}
|
||||
|
|
@ -508,10 +542,18 @@ function performCustomChecks(
|
|||
if (declaration && !isSameOrDescendant(declaration, node)) {
|
||||
// 避免无限递归
|
||||
const symbol = getSymbolOfDeclaration(declaration);
|
||||
|
||||
// 先检查缓存
|
||||
if (symbol && functionsWithContextCalls.has(symbol)) {
|
||||
hasContextCall = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果缓存中没有,递归检查该函数
|
||||
if (containsContextCall(declaration)) {
|
||||
hasContextCall = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -520,6 +562,8 @@ function performCustomChecks(
|
|||
}
|
||||
|
||||
visit(node);
|
||||
log(`[DEBUG containsContextCall] 最终结果: ${hasContextCall}`);
|
||||
|
||||
if (symbol) {
|
||||
checkedFunctions.set(symbol, hasContextCall);
|
||||
}
|
||||
|
|
@ -573,9 +617,23 @@ function performCustomChecks(
|
|||
|
||||
// 辅助函数:获取声明的符号
|
||||
function getSymbolOfDeclaration(declaration: ts.SignatureDeclaration): ts.Symbol | undefined {
|
||||
// 处理有名称的声明(函数声明、方法声明等)
|
||||
if ('name' in declaration && declaration.name) {
|
||||
return typeChecker.getSymbolAtLocation(declaration.name);
|
||||
}
|
||||
|
||||
// 处理箭头函数:尝试从父节点(变量声明)获取符号
|
||||
if (ts.isArrowFunction(declaration) || ts.isFunctionExpression(declaration)) {
|
||||
const parent = declaration.parent;
|
||||
if (ts.isVariableDeclaration(parent) && parent.name) {
|
||||
return typeChecker.getSymbolAtLocation(parent.name);
|
||||
}
|
||||
// 处理作为属性值的情况
|
||||
if (ts.isPropertyAssignment(parent) && parent.name) {
|
||||
return typeChecker.getSymbolAtLocation(parent.name);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
|
@ -647,7 +705,7 @@ function compile(configPath: string): void {
|
|||
const allDiagnostics: readonly (ts.Diagnostic | CustomDiagnostic)[] = [
|
||||
...ts.getPreEmitDiagnostics(program),
|
||||
...emitResult.diagnostics,
|
||||
...customDiagnostics
|
||||
...customDiagnostics || []
|
||||
];
|
||||
|
||||
// 输出诊断信息
|
||||
|
|
|
|||
Loading…
Reference in New Issue