Sponsored Content
Skip to content

chore: Enable clang-tidy include cleaner - #6947

Merged
ximinez merged 22 commits into
XRPLF:developfrom
godexsoft:chore/clang-tidy-includes
Apr 17, 2026
Merged

chore: Enable clang-tidy include cleaner#6947
ximinez merged 22 commits into
XRPLF:developfrom
godexsoft:chore/clang-tidy-includes

Conversation

@godexsoft

Copy link
Copy Markdown
Contributor

High Level Overview of Change

This PR enables the misc-include-cleaner check which automatically keeps the includes tidy.

As a bonus this PR also fixes clang-format to automatically detect and place the main include first, without having to add extra '//' markers to separate them.

Context of Change

Fixing clang-tidy for all source.

API Impact

No impact.

@godexsoft godexsoft added the DraftRunCI Normally CI does not run on draft PRs. This opts in. label Apr 14, 2026
@github-actions

Copy link
Copy Markdown

This PR has conflicts, please resolve them in order for the PR to be reviewed.

@github-actions

Copy link
Copy Markdown

All conflicts have been resolved. Assigned reviewers can now start or resume their review.

@codecov

codecov Bot commented Apr 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.6%. Comparing base (f1a5ba4) to head (cc53293).
⚠️ Report is 4 commits behind head on develop.

Files with missing lines Patch % Lines
src/libxrpl/rdb/SociDB.cpp 0.0% 2 Missing ⚠️
src/libxrpl/net/HTTPClient.cpp 0.0% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           develop   #6947     +/-   ##
=========================================
- Coverage     81.6%   81.6%   -0.0%     
=========================================
  Files         1010    1010             
  Lines        75992   75992             
  Branches      7603    7620     +17     
=========================================
- Hits         62013   61988     -25     
- Misses       13979   14004     +25     
Files with missing lines Coverage Δ
src/libxrpl/basics/Archive.cpp 0.0% <ø> (ø)
src/libxrpl/basics/BasicConfig.cpp 87.9% <ø> (ø)
src/libxrpl/basics/FileUtilities.cpp 69.2% <ø> (ø)
src/libxrpl/basics/Log.cpp 18.0% <ø> (ø)
src/libxrpl/basics/MallocTrim.cpp 92.3% <ø> (ø)
src/libxrpl/basics/Number.cpp 98.7% <ø> (ø)
src/libxrpl/basics/ResolverAsio.cpp 91.0% <ø> (ø)
src/libxrpl/basics/StringUtilities.cpp 95.2% <ø> (ø)
src/libxrpl/basics/contract.cpp 66.7% <ø> (ø)
src/libxrpl/basics/make_SSLContext.cpp 56.3% <ø> (ø)
... and 241 more

... and 163 files with indirect coverage changes

Impacted file tree graph

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@godexsoft godexsoft removed the DraftRunCI Normally CI does not run on draft PRs. This opts in. label Apr 15, 2026
@godexsoft
godexsoft marked this pull request as ready for review April 15, 2026 16:01
test.toplevel > test.jtx

Loop: test.jtx test.unit_test
test.unit_test == test.jtx

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: yes we have more includes now but at least no newly added loops

#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/objects.h> // IWYU pragma: keep

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need these IWYU pragmas?
Could you please check that they are actually neeeded?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes they are needed, without them clang-tidy would add obj_mac.h on mac etc. I also had to add the other one to ignores list

@mathbunnyru mathbunnyru left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea how to review this, but lgtm

Comment thread src/libxrpl/json/Writer.cpp
@a1q123456

Copy link
Copy Markdown
Contributor

Stripped out #include related changes and this PR looks good in general. Just left a small question, happy to approve once we try and see if removing IWYU pragma: keep works for standard library includes.

Attaching the script here:

#!/usr/bin/env python3
"""Strip #include-related changes from a unified diff file.
Identifies contiguous change blocks and drops them if they are include-related.
A block is include-related if ALL changes are #include/#pragma once, blanks, or comments.
Preprocessor guards (#if/#endif) are NOT considered include-related.
"""
import re, sys

def classify(text):
    s = text.strip()
    if s == '':
        return 'blank'
    if s.startswith('//'):
        return 'comment'
    if re.match(r'#\s*include\b', s):
        return 'include'
    if re.match(r'#\s*pragma\s+once', s):
        return 'include'
    return 'code'

def block_is_include_related(block):
    """A change block is include-related if:
    - it has at least one include/pragma line, AND
    - all other lines are blank/comment
    """
    classes = [classify(bl[1:]) for bl in block]
    has_include = 'include' in classes
    has_code = 'code' in classes
    if has_code:
        return False
    if has_include:
        return True
    # Only blanks and comments, no includes - still drop as trivial
    return True

def process_diff(input_path, output_path):
    with open(input_path, 'r') as f:
        lines = f.readlines()

    out = []
    i = 0
    while i < len(lines):
        line = lines[i]
        if line.startswith(('diff --git ', 'index ', '--- ', '+++ ', 'Binary files ')):
            out.append(line)
            i += 1
            continue

        m = re.match(r'^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)', line)
        if not m:
            out.append(line)
            i += 1
            continue

        old_start, new_start, trailing = int(m.group(1)), int(m.group(3)), m.group(5)
        i += 1

        hunk_lines = []
        while i < len(lines) and not lines[i].startswith(('diff --git ', '@@ ')):
            hunk_lines.append(lines[i])
            i += 1

        # Split into segments and filter change blocks
        filtered = []
        j = 0
        while j < len(hunk_lines):
            hl = hunk_lines[j]
            is_change = (hl.startswith('+') and not hl.startswith('+++')) or \
                        (hl.startswith('-') and not hl.startswith('---'))
            if not is_change:
                filtered.append(hl)
                j += 1
                continue

            block = []
            while j < len(hunk_lines):
                h = hunk_lines[j]
                ic = (h.startswith('+') and not h.startswith('+++')) or \
                     (h.startswith('-') and not h.startswith('---'))
                if not ic:
                    break
                block.append(h)
                j += 1

            if not block_is_include_related(block):
                filtered.extend(block)

        has_changes = any(
            (l.startswith('+') and not l.startswith('+++')) or
            (l.startswith('-') and not l.startswith('---'))
            for l in filtered
        )
        if not has_changes:
            continue

        old_count = sum(1 for l in filtered if l.startswith(' ') or (l.startswith('-') and not l.startswith('---')))
        new_count = sum(1 for l in filtered if l.startswith(' ') or (l.startswith('+') and not l.startswith('+++')))

        out.append(f'@@ -{old_start},{old_count} +{new_start},{new_count} @@{trailing}\n')
        out.extend(filtered)

    # Remove file entries with no hunks
    final = []
    i = 0
    while i < len(out):
        if out[i].startswith('diff --git '):
            file_block = [out[i]]
            i += 1
            while i < len(out) and not out[i].startswith(('diff --git ', '@@ ')):
                file_block.append(out[i])
                i += 1
            if i < len(out) and out[i].startswith('@@ '):
                final.extend(file_block)
        else:
            final.append(out[i])
            i += 1

    with open(output_path, 'w') as f:
        f.writelines(final)
    print(f"Written {len(final)} lines to {output_path}")

if __name__ == '__main__':
    process_diff(sys.argv[1], sys.argv[2])

@godexsoft godexsoft added the Ready to merge *PR author* thinks it's ready to merge. Has passed code review. Perf sign-off may still be required. label Apr 17, 2026
@ximinez
ximinez added this pull request to the merge queue Apr 17, 2026
Merged via the queue into XRPLF:develop with commit 653a383 Apr 17, 2026
2 of 3 checks passed
marek-foss-neti pushed a commit to marek-foss-neti/rippled that referenced this pull request May 5, 2026
beartec-jpg pushed a commit to beartec-jpg/FalconLedger that referenced this pull request Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready to merge *PR author* thinks it's ready to merge. Has passed code review. Perf sign-off may still be required.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants