| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- #!/usr/bin/env python3
- #
- # Copyright (c) 2022 Project CHIP Authors
- #
- # Licensed 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.
- #
- """Check #include files.
- Reads from standard input the output of a `grep -n` for `#include`s;
- see `check_includes.sh`.
- Uses the conditions defined in `check_includes_config.py`.
- """
- import re
- import sys
- from typing import Iterable, Pattern
- import check_includes_config as config
- # The input comes from `grep -n` and has the form
- # filename:line:include-directive
- #
- # This RE does not handle C-style comments before the file name.
- # So don't do that.
- _MATCH_SPLIT_RE = re.compile(r"""
- (?P<file>.+)
- : (?P<line>\d+)
- : (?P<directive>
- \s* \# \s* include \s* (?P<type>[<"]) (?P<include>[^">]+) [">])
- (?P<trailing> .*)
- """, re.VERBOSE)
- # Allow a temporary override so that a PR will not be blocked
- # on first updating `check_includes_config.py`.
- OVERRIDE = 'T' + 'ODO: update check_includes_config.py'
- def any_re(res: Iterable[str]) -> Pattern:
- """Given a list of RE strings, return an RE to match any of them."""
- return re.compile('|'.join((f'({i})' for i in res)))
- def main():
- ignore_re = any_re(config.IGNORE)
- n = 0
- for line in sys.stdin:
- s = line.strip()
- m = _MATCH_SPLIT_RE.fullmatch(s)
- if not m:
- print(f"Unrecognized input '{s}'", file=sys.stderr)
- return 2
- if OVERRIDE in m.group('trailing'):
- continue
- filename, include = m.group('file', 'include')
- if ignore_re.search(filename):
- continue
- if include not in config.DENY:
- continue
- if include in config.ALLOW.get(filename, []):
- continue
- n += 1
- if n == 1:
- print('Disallowed:\n')
- line_number, directive = m.group('line', 'directive')
- print(f' {filename}:{line_number}: {directive}')
- if n > 0:
- print('\nIf a disallowed #include is legitimate, add an ALLOW rule to')
- print(f' {config.__file__}')
- print('and/or temporarily suppress this error by adding exactly')
- print(f' {OVERRIDE}')
- print('in a comment at the end of the #include.')
- return 1
- return 0
- if __name__ == '__main__':
- sys.exit(main())
|