feat: 支持了联合类型的检查,可用于checker中的context调用检查

This commit is contained in:
Pan Qiancheng 2026-01-04 16:23:36 +08:00
parent dc071a47fd
commit 628cc31704
2 changed files with 96 additions and 45 deletions

View File

@ -52,6 +52,22 @@ function readCustomConfig(configPath) {
// 返回自定义配置,如果不存在则返回默认值
return config.oakBuildChecks || {};
}
function printDiagnostic(diagnostic, index) {
if (diagnostic.file && diagnostic.start !== undefined) {
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
const isError = diagnostic.category === ts.DiagnosticCategory.Error;
const category = isError ? 'error' : 'warning';
const categoryColor = isError ? colors.red : colors.yellow;
console.log(`${index + 1}.→ ${colors.cyan}${diagnostic.file.fileName}${colors.reset}:${colors.yellow}${line + 1}${colors.reset}:${colors.yellow}${character + 1}${colors.reset} - ${categoryColor}${category}${colors.reset} ${colors.gray}TS${diagnostic.code}${colors.reset}: ${message}`);
}
else {
const isError = diagnostic.category === ts.DiagnosticCategory.Error;
const category = isError ? 'error' : 'warning';
const categoryColor = isError ? colors.red : colors.yellow;
console.log(`${index + 1}.→ ${categoryColor}${category}${colors.reset} ${colors.gray}TS${diagnostic.code}${colors.reset}: ${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`);
}
}
function performCustomChecks(program, typeChecker, customConfig) {
const diagnostics = [];
// 如果自定义检查被禁用,直接返回
@ -102,6 +118,11 @@ function performCustomChecks(program, typeChecker, customConfig) {
if (ts.isReturnStatement(node.parent)) {
return;
}
// 检查箭头函数的隐式返回,让外层函数调用来处理
// 例如:() => context.select()
if (ts.isArrowFunction(node.parent) && node.parent.body === node) {
return;
}
const propertyAccess = node.expression;
const objectExpression = propertyAccess.expression;
// 获取对象的类型
@ -190,6 +211,10 @@ function performCustomChecks(program, typeChecker, customConfig) {
if (checkTypeSymbol(type, modules)) {
return true;
}
// 检查联合类型(例如 RuntimeCxt = FRC | BRC
if (type.isUnion()) {
return type.types.some(t => isAsyncContextType(t, modules));
}
// 检查基类型(继承关系)
const baseTypes = type.getBaseTypes?.() || [];
for (const baseType of baseTypes) {
@ -367,6 +392,11 @@ function performCustomChecks(program, typeChecker, customConfig) {
// 警告会传播到调用当前函数的地方
return;
}
// 检查箭头函数的隐式返回
// 例如:() => someFunction()
if (ts.isArrowFunction(node.parent) && node.parent.body === node) {
return;
}
// 检查是否被 await
if (!isAwaited(node)) {
const sourceFile = node.getSourceFile();
@ -550,31 +580,24 @@ function compile(configPath) {
const typeChecker = program.getTypeChecker();
// 执行自定义检查(传入自定义配置)
const customDiagnostics = performCustomChecks(program, typeChecker, customConfig);
if (customDiagnostics.length > 0) {
log(`Found ${customDiagnostics.length} custom diagnostics.`);
console.log(`${colors.yellow}Oak-Compiler 发现了相关问题,如果确定逻辑正确,可以使用注释标签来忽略:${colors.reset}`);
exports.OAK_IGNORE_TAGS.forEach(tag => {
console.log(` ${colors.cyan}// ${tag}${colors.reset}`);
});
console.log('');
customDiagnostics.forEach(printDiagnostic);
}
// 执行编译
const emitResult = program.emit();
// 获取诊断信息
const allDiagnostics = [
...ts.getPreEmitDiagnostics(program),
...emitResult.diagnostics,
...customDiagnostics || []
];
// 输出诊断信息
allDiagnostics.forEach((diagnostic) => {
if (diagnostic.file && diagnostic.start !== undefined) {
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
const isError = diagnostic.category === ts.DiagnosticCategory.Error;
const category = isError ? 'error' : 'warning';
const categoryColor = isError ? colors.red : colors.yellow;
console.log(`${colors.cyan}${diagnostic.file.fileName}${colors.reset}:${colors.yellow}${line + 1}${colors.reset}:${colors.yellow}${character + 1}${colors.reset} - ${categoryColor}${category}${colors.reset} ${colors.gray}TS${diagnostic.code}${colors.reset}: ${message}`);
}
else {
const isError = diagnostic.category === ts.DiagnosticCategory.Error;
const category = isError ? 'error' : 'warning';
const categoryColor = isError ? colors.red : colors.yellow;
console.log(`${categoryColor}${category}${colors.reset} ${colors.gray}TS${diagnostic.code}${colors.reset}: ${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`);
}
});
allDiagnostics.forEach(printDiagnostic);
// 输出编译统计
const errorCount = allDiagnostics.filter(d => d.category === ts.DiagnosticCategory.Error).length;
const warningCount = allDiagnostics.filter(d => d.category === ts.DiagnosticCategory.Warning).length;

View File

@ -85,6 +85,33 @@ function readCustomConfig(configPath: string): OakBuildChecksConfig {
};
}
function printDiagnostic(diagnostic: ts.Diagnostic | CustomDiagnostic, index: number) {
if (diagnostic.file && diagnostic.start !== undefined) {
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(
diagnostic.start
);
const message = ts.flattenDiagnosticMessageText(
diagnostic.messageText,
'\n'
);
const isError = diagnostic.category === ts.DiagnosticCategory.Error;
const category = isError ? 'error' : 'warning';
const categoryColor = isError ? colors.red : colors.yellow;
console.log(
`${index + 1}.→ ${colors.cyan}${diagnostic.file.fileName}${colors.reset}:${colors.yellow}${line + 1}${colors.reset}:${colors.yellow}${character + 1}${colors.reset} - ${categoryColor}${category}${colors.reset} ${colors.gray}TS${diagnostic.code}${colors.reset}: ${message}`
);
} else {
const isError = diagnostic.category === ts.DiagnosticCategory.Error;
const category = isError ? 'error' : 'warning';
const categoryColor = isError ? colors.red : colors.yellow;
console.log(
`${index + 1}.→ ${categoryColor}${category}${colors.reset} ${colors.gray}TS${diagnostic.code}${colors.reset}: ${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`
);
}
}
function performCustomChecks(
program: ts.Program,
typeChecker: ts.TypeChecker,
@ -158,6 +185,12 @@ function performCustomChecks(
return;
}
// 检查箭头函数的隐式返回,让外层函数调用来处理
// 例如:() => context.select()
if (ts.isArrowFunction(node.parent) && node.parent.body === node) {
return;
}
const propertyAccess = node.expression;
const objectExpression = propertyAccess.expression;
@ -270,6 +303,11 @@ function performCustomChecks(
return true;
}
// 检查联合类型(例如 RuntimeCxt = FRC | BRC
if (type.isUnion()) {
return type.types.some(t => isAsyncContextType(t, modules));
}
// 检查基类型(继承关系)
const baseTypes = type.getBaseTypes?.() || [];
for (const baseType of baseTypes) {
@ -480,6 +518,12 @@ function performCustomChecks(
return;
}
// 检查箭头函数的隐式返回
// 例如:() => someFunction()
if (ts.isArrowFunction(node.parent) && node.parent.body === node) {
return;
}
// 检查是否被 await
if (!isAwaited(node)) {
const sourceFile = node.getSourceFile();
@ -698,43 +742,27 @@ function compile(configPath: string): void {
// 执行自定义检查(传入自定义配置)
const customDiagnostics = performCustomChecks(program, typeChecker, customConfig);
if (customDiagnostics.length > 0) {
log(`Found ${customDiagnostics.length} custom diagnostics.`);
console.log(`${colors.yellow}Oak-Compiler 发现了相关问题,如果确定逻辑正确,可以使用注释标签来忽略:${colors.reset}`);
OAK_IGNORE_TAGS.forEach(tag => {
console.log(` ${colors.cyan}// ${tag}${colors.reset}`);
});
console.log('');
customDiagnostics.forEach(printDiagnostic);
}
// 执行编译
const emitResult = program.emit();
// 获取诊断信息
const allDiagnostics: readonly (ts.Diagnostic | CustomDiagnostic)[] = [
const allDiagnostics: readonly ts.Diagnostic[] = [
...ts.getPreEmitDiagnostics(program),
...emitResult.diagnostics,
...customDiagnostics || []
];
// 输出诊断信息
allDiagnostics.forEach((diagnostic: ts.Diagnostic | CustomDiagnostic) => {
if (diagnostic.file && diagnostic.start !== undefined) {
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(
diagnostic.start
);
const message = ts.flattenDiagnosticMessageText(
diagnostic.messageText,
'\n'
);
const isError = diagnostic.category === ts.DiagnosticCategory.Error;
const category = isError ? 'error' : 'warning';
const categoryColor = isError ? colors.red : colors.yellow;
console.log(
`${colors.cyan}${diagnostic.file.fileName}${colors.reset}:${colors.yellow}${line + 1}${colors.reset}:${colors.yellow}${character + 1}${colors.reset} - ${categoryColor}${category}${colors.reset} ${colors.gray}TS${diagnostic.code}${colors.reset}: ${message}`
);
} else {
const isError = diagnostic.category === ts.DiagnosticCategory.Error;
const category = isError ? 'error' : 'warning';
const categoryColor = isError ? colors.red : colors.yellow;
console.log(
`${categoryColor}${category}${colors.reset} ${colors.gray}TS${diagnostic.code}${colors.reset}: ${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`
);
}
});
allDiagnostics.forEach(printDiagnostic);
// 输出编译统计
const errorCount = allDiagnostics.filter(d => d.category === ts.DiagnosticCategory.Error).length;