feat: 支持了联合类型的检查,可用于checker中的context调用检查
This commit is contained in:
parent
dc071a47fd
commit
628cc31704
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue