Skip to content

Commit

Permalink
infer system includes
Browse files Browse the repository at this point in the history
  • Loading branch information
esquires committed Sep 4, 2017
1 parent 35470c0 commit fc4bb20
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 14 deletions.
37 changes: 28 additions & 9 deletions cpp/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from __future__ import print_function
from __future__ import unicode_literals

import os

from . import keywords
from . import tokenize

Expand Down Expand Up @@ -613,11 +615,14 @@ def get_template_indices(self, names):

class ASTBuilder(object):

def __init__(self, token_stream, filename, in_class=None,
def __init__(self, token_stream, filename, system_includes=[],
nonsystem_includes=[], in_class=None,
namespace_stack=None, quiet=False):
if namespace_stack is None:
namespace_stack = []

self.system_includes = system_includes
self.nonsystem_includes = nonsystem_includes
self.tokens = token_stream
self.filename = filename
self.token_queue = []
Expand Down Expand Up @@ -742,13 +747,22 @@ def _generate_one(self, token):
if name.startswith('\\'):
name = name[1:].strip()

system = True
filename = name
if name[0] in '<"':
assert_parse(name[-1] in '>"', token)
filename = name.strip('<>"')
def is_file(prefix):
return os.path.isfile(os.path.join(prefix, filename))

if filter(is_file, self.system_includes):
system = True
elif filter(is_file, self.nonsystem_includes):
system = False
else:
system = True
filename = name

if name[0] in '<"':
assert_parse(name[-1] in '>"', token)

system = name[0] == '<'
filename = name[1:-1]
system = name[0] == '<'
return Include(token.start, token.end, filename, system)
if name.startswith('define'):
# Remove "define".
Expand Down Expand Up @@ -1481,7 +1495,9 @@ def _get_class(self, class_type, templated_types):
body = None
if token.token_type == tokenize.SYNTAX and token.name == '{':
name = class_name or '__unamed__'
ast = ASTBuilder(self.get_scope(), self.filename, name,
ast = ASTBuilder(self.get_scope(), self.filename,
self.system_includes, self.nonsystem_includes,
name,
self.namespace_stack,
quiet=self.quiet)
body = list(ast.generate())
Expand Down Expand Up @@ -1548,7 +1564,8 @@ def handle_operator(self):
pass


def builder_from_source(source, filename, quiet=False):
def builder_from_source(source, filename, system_includes,
nonsystem_includes, quiet=False):
"""Utility method that returns an ASTBuilder from source code.
Args:
Expand All @@ -1561,6 +1578,8 @@ def builder_from_source(source, filename, quiet=False):
"""
return ASTBuilder(tokenize.get_tokens(source),
filename,
system_includes,
nonsystem_includes,
quiet=quiet)


Expand Down
13 changes: 11 additions & 2 deletions cpp/find_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,15 @@ class WarningHunter(object):
# Cache filename: ast_list
_module_cache = {}

def __init__(self, filename, source, ast_list, include_paths, quiet=False):
def __init__(self, filename, source, ast_list, include_paths,
system_include_paths, nonsystem_include_paths,
quiet=False):
self.filename = filename
self.source = source
self.ast_list = ast_list
self.include_paths = include_paths[:]
self.system_include_paths = system_include_paths
self.nonsystem_include_paths = nonsystem_include_paths
self.quiet = quiet
self.symbol_table = symbols.SymbolTable()

Expand Down Expand Up @@ -147,6 +151,8 @@ def _get_module(self, node):
ast_list = None
try:
builder = ast.builder_from_source(source, filename,
self.system_include_paths,
self.nonsystem_include_paths,
quiet=self.quiet)
ast_list = [_f for _f in builder.generate() if _f]
except tokenize.TokenError:
Expand Down Expand Up @@ -587,9 +593,12 @@ def get_correct_include_filename(filename, candidate_filenames):
return None


def run(filename, source, entire_ast, include_paths, quiet):
def run(filename, source, entire_ast, include_paths,
system_include_paths, nonsystem_include_paths, quiet):
hunter = WarningHunter(filename, source, entire_ast,
include_paths=include_paths,
system_include_paths=system_include_paths,
nonsystem_include_paths=nonsystem_include_paths,
quiet=quiet)
hunter.find_warnings()
hunter.show_warnings()
Expand Down
3 changes: 2 additions & 1 deletion cpp/nonvirtual_dtors.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@ def _find_warnings(filename, source, ast_list):
return count


def run(filename, source, entire_ast, include_paths, quiet):
def run(filename, source, entire_ast, include_paths,
system_include_paths, nonsystem_include_paths, quiet):
return _find_warnings(filename, source, entire_ast)
3 changes: 2 additions & 1 deletion cpp/static_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ def find_variables_use(body):
return count


def run(filename, source, entire_ast, include_paths, quiet):
def run(filename, source, entire_ast, include_paths,
system_include_paths, nonsystem_include_paths, quiet):
lines = metrics.Metrics(source)

return (
Expand Down
21 changes: 20 additions & 1 deletion cppclean
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ def main():
help='add a header include path; '
'specify this multiple times for multiple '
'include paths')
parser.add_argument('--include-path-system', '-is', '-Is', action='append',
dest='include_system_paths', default=[],
help=('same as --include-path but explicitly '
'designates all header files found in these'
'directories as "system" includes'))
parser.add_argument('--include-path-non-system', '-in', '-In',
action='append', dest='include_nonsystem_paths',
default=[],
help=('same as --include-path but explicitly '
'designates all header files found in these'
'directories as "non-system" includes'))
parser.add_argument('--verbose', action='store_true',
help='print verbose messages')
parser.add_argument('--version', action='version',
Expand All @@ -101,6 +112,10 @@ def main():
if hasattr(filename, 'decode') else filename
for filename in args.files]

all_includes = list(set(
args.include_paths + args.include_system_paths +
args.include_nonsystem_paths))

status = 0
for filename in (
sorted(find_files(args.files,
Expand All @@ -116,6 +131,8 @@ def main():

builder = ast.builder_from_source(source,
filename,
args.include_system_paths,
args.include_nonsystem_paths,
quiet=args.quiet)
entire_ast = list([_f for _f in builder.generate() if _f])
except tokenize.TokenError as exception:
Expand All @@ -134,7 +151,9 @@ def main():
nonvirtual_dtors,
static_data]:
if module.run(filename, source, entire_ast,
include_paths=args.include_paths,
include_paths=all_includes,
system_include_paths=args.include_system_paths,
nonsystem_include_paths=args.include_nonsystem_paths,
quiet=args.quiet):
status = 1

Expand Down

0 comments on commit fc4bb20

Please sign in to comment.