Skip to content

Commit

Permalink
add tool
Browse files Browse the repository at this point in the history
  • Loading branch information
acelyc111 committed Aug 5, 2024
1 parent d3754b3 commit 70aeaee
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 6 deletions.
24 changes: 18 additions & 6 deletions .github/workflows/lint_and_test_cpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ jobs:
build_Release:
name: Build Release
needs: cpp_clang_format_linter
needs:
- cpp_clang_format_linter
- cpp_clang_tidy_linter
runs-on: ubuntu-latest
env:
USE_JEMALLOC: OFF
Expand Down Expand Up @@ -191,7 +193,9 @@ jobs:

build_ASAN:
name: Build ASAN
needs: cpp_clang_format_linter
needs:
- cpp_clang_format_linter
- cpp_clang_tidy_linter
runs-on: ubuntu-latest
env:
USE_JEMALLOC: OFF
Expand Down Expand Up @@ -278,7 +282,9 @@ jobs:
# before we find any way to reduce the time cost.
# build_UBSAN:
# name: Build UBSAN
# needs: cpp_clang_format_linter
# needs:
# - cpp_clang_format_linter
# - cpp_clang_tidy_linter
# runs-on: ubuntu-latest
# env:
# USE_JEMALLOC: OFF
Expand Down Expand Up @@ -358,7 +364,9 @@ jobs:

build_with_jemalloc:
name: Build with jemalloc
needs: cpp_clang_format_linter
needs:
- cpp_clang_format_linter
- cpp_clang_tidy_linter
runs-on: ubuntu-latest
env:
USE_JEMALLOC: ON
Expand Down Expand Up @@ -399,7 +407,9 @@ jobs:

build_release_on_macos:
name: Build Release on macOS
needs: cpp_clang_format_linter
needs:
- cpp_clang_format_linter
- cpp_clang_tidy_linter
runs-on: macos-12
steps:
- name: Install Softwares
Expand Down Expand Up @@ -433,7 +443,9 @@ jobs:
build_debug_on_centos7:
name: Build Debug on CentOS 7
needs: cpp_clang_format_linter
needs:
- cpp_clang_format_linter
- cpp_clang_tidy_linter
runs-on: ubuntu-latest
env:
USE_JEMALLOC: OFF
Expand Down
123 changes: 123 additions & 0 deletions build-support/clang_tidy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

import argparse
import collections
import json
import logging
import multiprocessing
from multiprocessing.pool import ThreadPool
import os
import re
import subprocess
import sys
import tempfile

from kudu_util import init_logging

ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))

BUILD_PATH = os.path.join(ROOT, "build", "latest")

def run_tidy(sha="HEAD", is_rev_range=False):
diff_cmdline = ["git", "diff" if is_rev_range else "show", sha]

# Figure out which paths changed in the given diff.
changed_paths = subprocess.check_output(diff_cmdline + ["--name-only", "--pretty=format:"]).splitlines()
changed_paths = [p for p in changed_paths if p]

# Produce a separate diff for each file and run clang-tidy-diff on it
# in parallel.
#
# Note: this will incorporate any configuration from .clang-tidy.
def tidy_on_path(path):
patch_file = tempfile.NamedTemporaryFile()
cmd = diff_cmdline + [
"--src-prefix=%s/" % ROOT,
"--dst-prefix=%s/" % ROOT,
"--",
path]
subprocess.check_call(cmd, stdout=patch_file, cwd=ROOT)
cmdline = [CLANG_TIDY_DIFF,
"-clang-tidy-binary", CLANG_TIDY,
"-p0",
"-path", BUILD_PATH,
"-extra-arg=-DCLANG_TIDY"]
return subprocess.check_output(
cmdline,
stdin=open(patch_file.name),
cwd=ROOT).decode()
pool = ThreadPool(multiprocessing.cpu_count())
try:
return "".join(pool.imap(tidy_on_path, changed_paths))
except KeyboardInterrupt as ki:
sys.exit(1)
finally:
pool.terminate()
pool.join()


def split_warnings(clang_output):
accumulated = ""
for l in clang_output.splitlines():
if l == "" or l == "No relevant changes found.":
continue
if l.startswith(ROOT) and re.search(r'(warning|error): ', l):
if accumulated:
yield accumulated
accumulated = ""
accumulated += l + "\n"
if accumulated:
yield accumulated


def parse_clang_output(clang_output):
ret = []
for w in split_warnings(clang_output):
m = re.match(r"^(.+?):(\d+):\d+: ((?:warning|error): .+)$", w, re.MULTILINE | re.DOTALL)
if not m:
raise Exception("bad warning: " + w)
path, line, warning = m.groups()
ret.append(dict(
path=os.path.relpath(path, ROOT),
line=int(line),
warning=warning.strip()))
return ret


if __name__ == "__main__":
# Basic setup and argument parsing.
parser = argparse.ArgumentParser(description="Run clang-tidy on a patch")
parser.add_argument("--rev-range", action="store_true",
default=False,
help="Whether the revision specifies the 'rev..' range")
parser.add_argument('rev', help="The git revision (or range of revisions) to process")
args = parser.parse_args()

# Run clang-tidy and parse the output.
clang_output = run_tidy(args.rev, args.rev_range)
logging.info("Clang output")
logging.info(clang_output)
logging.info("=" * 80)
parsed = parse_clang_output(clang_output)
if not parsed:
print("No warnings", file=sys.stderr)
sys.exit(0)
print("Parsed clang warnings:")
print(json.dumps(parsed, indent=4))

0 comments on commit 70aeaee

Please sign in to comment.