Repository navigation
tools: refactor code-quality scorer and add header/macro/PARAM rules - #8158
Merged
Merged
Conversation
added 3 commits
October 16, 2026 11:16
The 2349-line scorer now delegates to five single-responsibility
modules while keeping the entry command unchanged:
cqs_config.py - weights/caps/thresholds/regexes/prefix helpers
cqs_text.py - comment/string stripping, comment-block extraction
cqs_rules.py - rule-detection (find_*/analyze_*) functions
cqs_analyze.py - per-file analysis orchestration, file discovery
cqs_report.py - Finding/FileReport dataclasses, text/JSON renderers
Also folds in the two rule additions made just before the split:
- complex_argument_expression (AGENTS.md §14): penalises a ternary
?:, && or || used as a top-level call argument (weight 1, cap 5)
- ifdef_in_call_args: penalises #if/#ifdef blocks wrapping arguments
inside a call's argument list (weight 1, cap 5)
and broadens the using-namespace rule from std-only to any
`using namespace X;` directive.
Verification: python3 -m py_compile on all six files; smoke sample
(ternary/&&/|| args + #ifdef-wrapped args) scores identically before
and after the split (92, rule A hits L7-L11, rule B hits L22, no false
positives); full source_base/ scan (284 files) produces the same
module rollup, text/JSON and -o output.
Add two .h-specific rules to the code-quality scorer:
- header_too_long: .h file exceeding 120 lines costs 1 per extra
10-line block, capped at 5 (stacks with the generic 500-line
file rule)
- header_function_body: a non-inline, non-template function body
exceeding 20 lines in a .h file costs 1 per extra 10-line block,
capped at 5. `inline` functions, `template <...>` functions, and
bodies at or below 20 lines (typical accessors) are exempt.
Verification: python3 -m py_compile on all touched modules; smoke
header with a 23-line plain body, a 23-line inline body, a 23-line
template body and a 6-line plain body scores only the plain long one
(1 point); real source_base/matrix.h shows no header_function_body
false positive.
…, 17)
Add AGENTS.md rules 16 and 17 and the matching scorer checks:
- new_macro_definition: a `#define NAME ...` in a .h/.cpp file costs
3 per definition (cap 10). Guard-style macros (name ending in
_H/_HPP with no parameter list or replacement text) are exempt.
- param_member_init: a member variable initialized from PARAM in a
.h/.hpp file costs 5 per declaration (cap 10). Function default
arguments and constructor member-initializer lists are out of
scope (already covered by default_parameter / global_dependency).
Verification: python3 -m py_compile on all touched modules.
Smoke .h with a guard macro, an object-like macro and a function-like
macro: only the latter two are charged (3 each); the guard is exempt;
source_md/msst.h (guard only) shows no new_macro_definition finding.
Smoke .h with `= PARAM...`, `{PARAM...}`, `static const = PARAM...`,
a method default argument and a constructor init list: the three
declaration-site initializations are charged (5 each), the method and
constructor forms are not; source_base/matrix.h and source_md/md_base.h
show no param_member_init finding.
AsTonyshment
left a comment
Collaborator
There was a problem hiding this comment.
There are a few small edge cases in the new checks that need refinement.
Resolve AGENTS.md rule-numbering conflict: keep upstream rules 16-19 (file-read confirmation, no shell mkdir/rm in unit tests, no non-reentrant C stdlib functions, stream-state checks on numerical input) and renumber the local rules to 20 (no new #define macros) and 21 (no PARAM member-variable init in headers). Update the rule-number references in the code_quality_score tools accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes four issues raised in PR deepmodeling#8158 review: 1. complex_argument_expression false positives & negatives - skip declarations with any return-type prefix (e.g. `void f(int&&)`, `ESolver_KS_LCAO<T,TR>&&`), not just the 2-segment form - treat `<`/`>` as template nesting only in the glued form `Foo<int>`; spaced comparison operators (`a < b`, `>=`) no longer corrupt the call-argument depth - resume scanning inside the argument list so nested callees (`f(g(a ? b : c))`) are visited on their own 2. ifdef_in_call_args missed bare/method/keyword call forms - reorder _classify_opener: strip the callee name first, then decide call vs declaration from what remains; bare `f(`, `obj.f(`, `ptr->f(`, `return f(`, `else f(` are now call contexts 3. param_member_init false positives & negatives - new find_param_member_inits strips comments AND strings over the whole file, scans only top-level class bodies, and requires the match to sit at the class's own brace/paren depth (excludes locals in inline functions, default arguments, comment blocks, strings) - regex now matches cross-line declarations and `= <expr> PARAM...` initializers; reported line aligns with the declaration text 4. header_function_body template detection - one-line `template <...> void f(...)`, multi-line template headers above the signature, and members of templated classes are exempt - formatting (line breaks) no longer changes the verdict Verification: py_compile of all modules; reviewer's exact samples now score as expected; full source/ scan (1944 files) changes only 25 findings, all verified as true improvements (avg 82.6507 -> 82.6697).
AsTonyshment
approved these changes
Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Refactor
tools/03_code_analysis/code_quality_score.pyand extend itwith new AGENTS.md-backed rules. All changes are confined to the
scoring tool and
AGENTS.md; no solver or build code is touched.Changes
1. Split the scorer into focused modules (
bfecaf3cb)The 2349-line
code_quality_score.pynow delegates to fivesingle-responsibility modules under
tools/03_code_analysis/, whilethe entry command (
python3 code_quality_score.py ...) is unchanged:cqs_config.pycqs_text.pycqs_rules.pyfind_*/analyze_*) functionscqs_analyze.pycqs_report.pyFinding/FileReportdataclasses, text/JSON renderersThis commit also folds in two rule additions made just before the
split and broadens one existing rule:
complex_argument_expression(AGENTS.md §14): penalises a ternary?:,&&or||used as a top-level call argument (weight 1, cap 5).ifdef_in_call_args: penalises#if/#ifdefblocks wrappingarguments inside a call's argument list (weight 1, cap 5).
using namespace X;directive instead of only
using namespace std;.2. Header-specific rules (
f005fb6c4)header_too_long: a.hfile exceeding 120 lines costs 1 per extra10-line block, capped at 5 (stacks with the generic 500-line rule).
header_function_body: a non-inline, non-template function bodyexceeding 20 lines in a
.hfile costs 1 per extra 10-line block,capped at 5.
inlinefunctions,template <...>functions, andbodies at or below 20 lines are exempt.
3. New AGENTS.md rules 16 and 17 (
ebb2716ca)new_macro_definition: a#define NAME ...in a.h/.cppfile costs 3 per definition (cap 10). Guard-style macros(name ending in
_H/_HPPwith no parameter list or replacementtext) and
#ifdef/#ifndefusages of existing macros are exempt.param_member_init: a member variable initialized fromPARAMin a.h/.hppfile costs 5 per declaration (cap 10).Function default arguments and constructor member-initializer lists
are out of scope (already covered by
default_parameter/global_dependency).Verification
No ABACUS compilation or runtime test was run (tooling-only change);
all checks are Python-level:
python3 -m py_compilepasses on all touched modules after everycommit.
&&/||args +#ifdef-wrappedargs) scores identically before and after the split (92; rule A hits
L7-L11, rule B hits L22, no false positives); a full
source_base/scan (284 files) produces the same module rollup, text/JSON and
-ooutput as before the split.
header_function_body: a smoke header with a 23-line plain body, a23-line
inlinebody, a 23-linetemplatebody and a 6-line bodycharges only the plain long one;
source_base/matrix.hshows nofalse positive.
new_macro_definition: a smoke header with a guard macro, anobject-like macro and a function-like macro charges only the latter
two;
source_md/msst.h(guard only) shows no finding.param_member_init: a smoke header with= PARAM...,{PARAM...},static const = PARAM..., a method default argument and aconstructor init list charges only the three declaration-site
initializations;
source_base/matrix.handsource_md/md_base.hshow no finding.
Notes
invocations of
code_quality_score.pykeep working.inlinewritten on the lineabove a signature is not detected by
header_function_body.