Code Cleanup Reference
tool::cleanup implements the code_cleanup configuration section and code-cleanup command.
For invocation examples, see Clean Up the Code.
Configuration
The shipped policy is tool/conf/tools/code_cleanup.elcl.
Filesystem paths are project-relative and confined through the framework’s ProjectFiles service.
Directory globs must match existing directories; walks skip symlinks and reparse points.
Setting |
Meaning and default |
|---|---|
|
Implementation root for resolution; |
|
Compiler-visible directory before mapped header names; |
|
Canonical-first output of |
|
Required list of dotted suffixes; shipped: |
|
Optional exact filenames excluded from transformation; shipped: |
|
Required list of project-relative directory globs; matched directories are scanned recursively. |
|
|
|
Optional extra local header search roots scoped to this tree. |
|
Version written in simple CMake files; |
|
Explicit recursive CMake source-list target; the deepest matching directory wins. |
|
|
|
One style file for all sources; |
|
Disposable cache; |
Generated CMake headers use the framework’s shared Rendering copyright and license settings.
The default copyright spelling is Copyright (c).
Cleanup preserves existing copyright notices in C++ sources; their generators own those headers.
The shipped C++ scope covers library sources, unit tests, demos, constant-time and profiling tools, adapters, build
helpers, fuzzers, interoperability and heap tests, macOS tests, CMake fixtures, and maintenance tool sources, tests, and
test helpers.
Selections use actual source directories so sibling data and generator templates are preserved.
CMake cleanup covers src, test/unittest/src, tool/src, and tool/test/unittest/src.
Directories accepts plain paths, * within a path component, and recursive ** patterns.
Each pattern matches complete directory paths and must select at least one directory.
Empty, malformed, absolute, and parent-traversing patterns are rejected.
Selection is resolved on every configuration read in deterministic order without following links.
Duplicate and nested roots within one named policy collapse to one scan; roots from different policies must not overlap.
Each expanded tree automatically uses its own root for local includes, plus that policy’s literal Include Roots.
Relative includes into an explicit include root retain their spelling, even when the root lies outside the source tree.
Include roots do not select additional files for cleanup.
The library’s relative-include policy must still select only Library Directory.
CMake tree Directory settings remain literal because each mapping names one explicit build target.
Include Repair and Layout
The leading region contains ordinary line comments, blank lines, #pragma once, and include directives.
API documentation comments, clang-format off, other directives, continued directives, or C++ code end that region.
Conditional includes and trailing template includes remain outside path repair and sorting.
Standalone comments and macro includes form ordering barriers; literal includes never cross them.
Trailing comments remain attached to their include.
Only identical complete include lines deduplicate, preserving different annotations and case-sensitive paths.
Library Directory determines the source prefix used to recognize project includes; no source directory name is
hard-coded in the resolver.
Public Include Prefix is independent of that physical directory and must be a nonempty slash-separated include
directory without . or .. components.
Mapping source names are relative to Library Directory; mapping destination names are relative to
Public Include Prefix.
For example, Library Directory: "vendor/base/source" and Public Include Prefix: "vendor/base" allow
vendor/base/source/a/Widget.hpp to become <vendor/base/Widget.hpp> when the map contains
a/Widget.hpp;Widget.hpp.
Existing relative library targets resolve first.
Consumer-local headers and their .in templates then take precedence over guessing a Core header.
Library resolution uses exact source paths, unique path suffixes, and finally filenames with a unique closest library
context.
Ambiguities and missing quoted project headers produce contextual errors.
Canonical mapping preserves merged public wrappers, internal includes, and unrelated Erbsland libraries.
Includes use one case-insensitive comparison; equal folded spellings retain their original order.
Groups are the corresponding source header, local filenames, local subdirectories, one-level parent paths, deeper parent
paths, angle includes ending in .h or .hpp, extensionless angle includes, and remaining angle includes.
Each group is separated by one blank line.
The corresponding header also matches Class_part.cpp to Class.hpp.
The cheap layout pass removes the gap between the copyright comments and #pragma once, leaves a blank line after
#pragma once, inserts blank lines around namespace blocks, and separates namespace-scope function definitions in
.cpp files.
Core’s C++ tokenizer distinguishes comments, literals, raw strings, and complete preprocessor directives.
Manual clang-format off blocks and compact empty namespace declarations retain their spacing.
It is a structural scanner, not a C++ compiler or a general-purpose formatter.
Simple CMake Grammar
The managed prefix accepts the simple cmake_minimum_required(VERSION number) form, single-argument
add_subdirectory, and plain target_sources(target PRIVATE ...) commands.
Subdirectories sort and deduplicate; source lists merge, sort, and gain unlisted local source files.
A source referenced in a recognized conditional block is not added unconditionally.
Conditional source lists retain their indentation and surrounding conditional text.
Files containing unsupported commands or argument syntax are preserved.
Examples include public/interface visibility, expressions, quoted arguments, multiple targets, annotated source lists,
and additional add_subdirectory arguments such as EXCLUDE_FROM_ALL.
Missing directory-local files or subdirectories in an otherwise supported file are errors.
The tool does not create CMake files or infer new subdirectory commands.
Smart Formatting and Failures
One inventory collects regular files and builds read-only header and local-source indexes.
One Core worker pool reads and transforms independent files with ordered results.
Jobs share immutable source policies through managed pointers.
Text helpers use COW StringList values; the spacing scanner owns per-file state and tokenizes only when its cheap
candidate scan finds a potential gap.
Native token byte positions allow a single forward traversal of the physical lines, without counting code points or
maintaining a line-offset search table.
CMake commands are parsed and validated once using cached expressions, then rendered from the per-file document.
--jobs accepts 1 through 64; the default is the logical CPU count clamped to that range.
Workers never wait on jobs submitted to the same pool.
Cheap cleanup runs first in memory.
The formatter cache compares SHA-256 fingerprints of the remaining code after removing the leading comment, pragma, and
include region.
A selected file is formatted to captured stdout without -i, then passed through cheap cleanup again to compensate
for clang-format’s spacing gaps and normalize paths after its include reordering.
The first run formats all files, including Git-clean files.
A missing, incompatible, or invalid cache also requires a new full baseline.
The cache signature includes the cache/cleanup version, resolved executable path, formatter version output, and style
file contents.
The formatter uses EnvironmentVariables::executableCandidatesOrThrow() for portable PATH lookup and native strings
for path arguments.
Cache records are streamed through StringSplitter, and serialization reserves its final size once.
An explicit --full-format ignores prior fingerprints.
There is no timestamp-based periodic rescan.
All transformations must succeed before any source is written.
Configuration, resolution, parsing, or formatter failure leaves source files and the previous cache unchanged.
Output truncation is an error; truncated formatter output is never written.
The main thread reports results and replaces changed files through ProjectFiles.
Equivalent files retain their original bytes and modification time.
Cache updates occur only after successful application; --check never writes them.
A filesystem failure during application can leave earlier successful replacements in place; this is not a multi-file
transaction.
Tests
Focused tests cover include resolution, literal preservation, CMake semantics, spacing, cold and warm formatter runs, style invalidation, failure-before-write behavior, and serial/parallel consistency. Performance comparisons must use the optimized tool build and the same source corpus; measure cold full formatting separately from warm pre-commit runs.