feat: 支持了联合类型的检查,可用于checker中的context调用检查
This commit is contained in:
parent
dc071a47fd
commit
628cc31704
|
|
@ -52,6 +52,22 @@ function readCustomConfig(configPath) {
|
||||||
// 返回自定义配置,如果不存在则返回默认值
|
// 返回自定义配置,如果不存在则返回默认值
|
||||||
return config.oakBuildChecks || {};
|
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) {
|
function performCustomChecks(program, typeChecker, customConfig) {
|
||||||
const diagnostics = [];
|
const diagnostics = [];
|
||||||
// 如果自定义检查被禁用,直接返回
|
// 如果自定义检查被禁用,直接返回
|
||||||
|
|
@ -102,6 +118,11 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
||||||
if (ts.isReturnStatement(node.parent)) {
|
if (ts.isReturnStatement(node.parent)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 检查箭头函数的隐式返回,让外层函数调用来处理
|
||||||
|
// 例如:() => context.select()
|
||||||
|
if (ts.isArrowFunction(node.parent) && node.parent.body === node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const propertyAccess = node.expression;
|
const propertyAccess = node.expression;
|
||||||
const objectExpression = propertyAccess.expression;
|
const objectExpression = propertyAccess.expression;
|
||||||
// 获取对象的类型
|
// 获取对象的类型
|
||||||
|
|
@ -190,6 +211,10 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
||||||
if (checkTypeSymbol(type, modules)) {
|
if (checkTypeSymbol(type, modules)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// 检查联合类型(例如 RuntimeCxt = FRC | BRC)
|
||||||
|
if (type.isUnion()) {
|
||||||
|
return type.types.some(t => isAsyncContextType(t, modules));
|
||||||
|
}
|
||||||
// 检查基类型(继承关系)
|
// 检查基类型(继承关系)
|
||||||
const baseTypes = type.getBaseTypes?.() || [];
|
const baseTypes = type.getBaseTypes?.() || [];
|
||||||
for (const baseType of baseTypes) {
|
for (const baseType of baseTypes) {
|
||||||
|
|
@ -367,6 +392,11 @@ function performCustomChecks(program, typeChecker, customConfig) {
|
||||||
// 警告会传播到调用当前函数的地方
|
// 警告会传播到调用当前函数的地方
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 检查箭头函数的隐式返回
|
||||||
|
// 例如:() => someFunction()
|
||||||
|
if (ts.isArrowFunction(node.parent) && node.parent.body === node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 检查是否被 await
|
// 检查是否被 await
|
||||||
if (!isAwaited(node)) {
|
if (!isAwaited(node)) {
|
||||||
const sourceFile = node.getSourceFile();
|
const sourceFile = node.getSourceFile();
|
||||||
|
|
@ -550,31 +580,24 @@ function compile(configPath) {
|
||||||
const typeChecker = program.getTypeChecker();
|
const typeChecker = program.getTypeChecker();
|
||||||
// 执行自定义检查(传入自定义配置)
|
// 执行自定义检查(传入自定义配置)
|
||||||
const customDiagnostics = performCustomChecks(program, typeChecker, customConfig);
|
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 emitResult = program.emit();
|
||||||
// 获取诊断信息
|
// 获取诊断信息
|
||||||
const allDiagnostics = [
|
const allDiagnostics = [
|
||||||
...ts.getPreEmitDiagnostics(program),
|
...ts.getPreEmitDiagnostics(program),
|
||||||
...emitResult.diagnostics,
|
...emitResult.diagnostics,
|
||||||
...customDiagnostics || []
|
|
||||||
];
|
];
|
||||||
// 输出诊断信息
|
// 输出诊断信息
|
||||||
allDiagnostics.forEach((diagnostic) => {
|
allDiagnostics.forEach(printDiagnostic);
|
||||||
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')}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 输出编译统计
|
// 输出编译统计
|
||||||
const errorCount = allDiagnostics.filter(d => d.category === ts.DiagnosticCategory.Error).length;
|
const errorCount = allDiagnostics.filter(d => d.category === ts.DiagnosticCategory.Error).length;
|
||||||
const warningCount = allDiagnostics.filter(d => d.category === ts.DiagnosticCategory.Warning).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(
|
function performCustomChecks(
|
||||||
program: ts.Program,
|
program: ts.Program,
|
||||||
typeChecker: ts.TypeChecker,
|
typeChecker: ts.TypeChecker,
|
||||||
|
|
@ -158,6 +185,12 @@ function performCustomChecks(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查箭头函数的隐式返回,让外层函数调用来处理
|
||||||
|
// 例如:() => context.select()
|
||||||
|
if (ts.isArrowFunction(node.parent) && node.parent.body === node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const propertyAccess = node.expression;
|
const propertyAccess = node.expression;
|
||||||
const objectExpression = propertyAccess.expression;
|
const objectExpression = propertyAccess.expression;
|
||||||
|
|
||||||
|
|
@ -270,6 +303,11 @@ function performCustomChecks(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查联合类型(例如 RuntimeCxt = FRC | BRC)
|
||||||
|
if (type.isUnion()) {
|
||||||
|
return type.types.some(t => isAsyncContextType(t, modules));
|
||||||
|
}
|
||||||
|
|
||||||
// 检查基类型(继承关系)
|
// 检查基类型(继承关系)
|
||||||
const baseTypes = type.getBaseTypes?.() || [];
|
const baseTypes = type.getBaseTypes?.() || [];
|
||||||
for (const baseType of baseTypes) {
|
for (const baseType of baseTypes) {
|
||||||
|
|
@ -480,6 +518,12 @@ function performCustomChecks(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查箭头函数的隐式返回
|
||||||
|
// 例如:() => someFunction()
|
||||||
|
if (ts.isArrowFunction(node.parent) && node.parent.body === node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否被 await
|
// 检查是否被 await
|
||||||
if (!isAwaited(node)) {
|
if (!isAwaited(node)) {
|
||||||
const sourceFile = node.getSourceFile();
|
const sourceFile = node.getSourceFile();
|
||||||
|
|
@ -698,43 +742,27 @@ function compile(configPath: string): void {
|
||||||
// 执行自定义检查(传入自定义配置)
|
// 执行自定义检查(传入自定义配置)
|
||||||
const customDiagnostics = performCustomChecks(program, typeChecker, customConfig);
|
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 emitResult = program.emit();
|
||||||
|
|
||||||
// 获取诊断信息
|
// 获取诊断信息
|
||||||
const allDiagnostics: readonly (ts.Diagnostic | CustomDiagnostic)[] = [
|
const allDiagnostics: readonly ts.Diagnostic[] = [
|
||||||
...ts.getPreEmitDiagnostics(program),
|
...ts.getPreEmitDiagnostics(program),
|
||||||
...emitResult.diagnostics,
|
...emitResult.diagnostics,
|
||||||
...customDiagnostics || []
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// 输出诊断信息
|
// 输出诊断信息
|
||||||
allDiagnostics.forEach((diagnostic: ts.Diagnostic | CustomDiagnostic) => {
|
allDiagnostics.forEach(printDiagnostic);
|
||||||
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')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 输出编译统计
|
// 输出编译统计
|
||||||
const errorCount = allDiagnostics.filter(d => d.category === ts.DiagnosticCategory.Error).length;
|
const errorCount = allDiagnostics.filter(d => d.category === ts.DiagnosticCategory.Error).length;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue