feat(语法要求): 能要求「调用 print() 时必须用 sep 参数」,题目说要用 sep/end 的不再被绕过
Deploy / deploy (push) Canceled after 0s

原来只能数 print 调用几次,写成 print("1-2-3***4") + print() 也算达标。
新加 must_use_keyword(只有 Python),后台「关键字参数」一组里配函数名和参数名。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-27 22:16:44 +08:00
1 parent 0e05f7e3c7
commit 179d5fa67d
3 files changed
+52 -3

No files matched your search

+17
View File
@@ -115,6 +115,8 @@ export function describeAstRule(rule: AstRule, language?: string): string {
return `不能调用 .${target}()`
case 'must_use_operator':
return `必须使用 ${astOperatorLabel(target, language)} 运算符`
case 'must_use_keyword':
return `调用 ${target}() 时必须用 ${rule.keyword ?? ''} 参数`
case 'must_have_nesting': {
// 这两个走 astNodeLabel 而不是裸值 —— 少了这一步文案就是
// 「必须使用 for_loop 嵌套」,旧栈 ast_checker/engines/nesting.py 是翻的
@@ -194,6 +196,9 @@ export function astRulesError(astRules: AstRules | null): string | null {
}
} else if (!target.trim()) {
return `${at}:要检查的函数名/方法名不能为空`
} else if (rule.engine === 'must_use_keyword') {
if (language !== 'Python') return `${at}:${language} 没有关键字参数`
if (!rule.keyword?.trim()) return `${at}:参数名不能为空`
}
if (!astRuleIsMeaningful(rule)) return `${at}:次数检查至少要填一个数字`
}
@@ -248,6 +253,13 @@ function functionCalls(root: Node, target: string, language: string) {
})
}
/** 带了 `keyword=...` 的那些 target() 调用。`**kwargs` 展开的不算,看不出里面有没有 */
function keywordCalls(root: Node, target: string, keyword: string, language: string) {
return functionCalls(root, target, language).filter((call) =>
call.childForFieldName('arguments')?.namedChildren.some((arg) => arg.type === 'keyword_argument' && arg.childForFieldName('name')?.text === keyword),
)
}
function methodCalls(root: Node, target: string, language: string) {
// C++ 的 `a.push_back()` / `p->push_back()` 都是 call_expression + field_expression,
// 和 Python 的 attribute 不是一回事 —— 少了这个分支,C++ 的「必须调用 .push_back()」
@@ -325,6 +337,11 @@ function evaluateRule(root: Node, rule: AstRule, language: string): AstResult |
description: describeAstRule(rule, language),
passed: hasNode(root, nodeType),
}
case 'must_use_keyword':
return {
description: describeAstRule(rule, language),
passed: keywordCalls(root, target, rule.keyword ?? '', language).length > 0,
}
case 'must_have_nesting': {
const outer = rule.outer ?? ''
const inner = rule.inner ?? ''