1*cc02d7e2SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*cc02d7e2SAndroid Build Coastguard Worker 3*cc02d7e2SAndroid Build Coastguard Worker# Copyright 2022 gRPC authors. 4*cc02d7e2SAndroid Build Coastguard Worker# 5*cc02d7e2SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*cc02d7e2SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*cc02d7e2SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*cc02d7e2SAndroid Build Coastguard Worker# 9*cc02d7e2SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*cc02d7e2SAndroid Build Coastguard Worker# 11*cc02d7e2SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*cc02d7e2SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*cc02d7e2SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*cc02d7e2SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*cc02d7e2SAndroid Build Coastguard Worker# limitations under the License. 16*cc02d7e2SAndroid Build Coastguard Worker 17*cc02d7e2SAndroid Build Coastguard Worker# Check for includes of the form `#include "bar.h"` - i.e. not including the subdirectory. We require instead `#include "foo/bar.h"`. 18*cc02d7e2SAndroid Build Coastguard Worker 19*cc02d7e2SAndroid Build Coastguard Workerimport argparse 20*cc02d7e2SAndroid Build Coastguard Workerimport os 21*cc02d7e2SAndroid Build Coastguard Workerimport re 22*cc02d7e2SAndroid Build Coastguard Workerimport sys 23*cc02d7e2SAndroid Build Coastguard Worker 24*cc02d7e2SAndroid Build Coastguard Worker# find our home 25*cc02d7e2SAndroid Build Coastguard WorkerROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../..")) 26*cc02d7e2SAndroid Build Coastguard Workeros.chdir(ROOT) 27*cc02d7e2SAndroid Build Coastguard Worker 28*cc02d7e2SAndroid Build Coastguard Worker# parse command line 29*cc02d7e2SAndroid Build Coastguard Workerargp = argparse.ArgumentParser(description="include guard checker") 30*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("-f", "--fix", default=False, action="store_true") 31*cc02d7e2SAndroid Build Coastguard Workerargs = argp.parse_args() 32*cc02d7e2SAndroid Build Coastguard Worker 33*cc02d7e2SAndroid Build Coastguard Worker# error count 34*cc02d7e2SAndroid Build Coastguard Workererrors = 0 35*cc02d7e2SAndroid Build Coastguard Worker 36*cc02d7e2SAndroid Build Coastguard WorkerCHECK_SUBDIRS = [ 37*cc02d7e2SAndroid Build Coastguard Worker "src/core", 38*cc02d7e2SAndroid Build Coastguard Worker "src/cpp", 39*cc02d7e2SAndroid Build Coastguard Worker "test/core", 40*cc02d7e2SAndroid Build Coastguard Worker "test/cpp", 41*cc02d7e2SAndroid Build Coastguard Worker "fuzztest", 42*cc02d7e2SAndroid Build Coastguard Worker] 43*cc02d7e2SAndroid Build Coastguard Worker 44*cc02d7e2SAndroid Build Coastguard Workerfor subdir in CHECK_SUBDIRS: 45*cc02d7e2SAndroid Build Coastguard Worker for root, dirs, files in os.walk(subdir): 46*cc02d7e2SAndroid Build Coastguard Worker for f in files: 47*cc02d7e2SAndroid Build Coastguard Worker if f.endswith(".h") or f.endswith(".cc"): 48*cc02d7e2SAndroid Build Coastguard Worker fpath = os.path.join(root, f) 49*cc02d7e2SAndroid Build Coastguard Worker output = open(fpath, "r").readlines() 50*cc02d7e2SAndroid Build Coastguard Worker changed = False 51*cc02d7e2SAndroid Build Coastguard Worker for i, line in enumerate(output): 52*cc02d7e2SAndroid Build Coastguard Worker m = re.match(r'^#include "([^"]*)"(.*)', line) 53*cc02d7e2SAndroid Build Coastguard Worker if not m: 54*cc02d7e2SAndroid Build Coastguard Worker continue 55*cc02d7e2SAndroid Build Coastguard Worker include = m.group(1) 56*cc02d7e2SAndroid Build Coastguard Worker if "/" in include: 57*cc02d7e2SAndroid Build Coastguard Worker continue 58*cc02d7e2SAndroid Build Coastguard Worker expect_path = os.path.join(root, include) 59*cc02d7e2SAndroid Build Coastguard Worker trailing = m.group(2) 60*cc02d7e2SAndroid Build Coastguard Worker if not os.path.exists(expect_path): 61*cc02d7e2SAndroid Build Coastguard Worker continue 62*cc02d7e2SAndroid Build Coastguard Worker changed = True 63*cc02d7e2SAndroid Build Coastguard Worker errors += 1 64*cc02d7e2SAndroid Build Coastguard Worker output[i] = '#include "{0}"{1}\n'.format( 65*cc02d7e2SAndroid Build Coastguard Worker expect_path, trailing 66*cc02d7e2SAndroid Build Coastguard Worker ) 67*cc02d7e2SAndroid Build Coastguard Worker print( 68*cc02d7e2SAndroid Build Coastguard Worker "Found naked include '{0}' in {1}".format( 69*cc02d7e2SAndroid Build Coastguard Worker include, fpath 70*cc02d7e2SAndroid Build Coastguard Worker ) 71*cc02d7e2SAndroid Build Coastguard Worker ) 72*cc02d7e2SAndroid Build Coastguard Worker if changed and args.fix: 73*cc02d7e2SAndroid Build Coastguard Worker open(fpath, "w").writelines(output) 74*cc02d7e2SAndroid Build Coastguard Worker 75*cc02d7e2SAndroid Build Coastguard Workerif errors > 0: 76*cc02d7e2SAndroid Build Coastguard Worker print("{} errors found.".format(errors)) 77*cc02d7e2SAndroid Build Coastguard Worker sys.exit(1) 78