diff options
author | Daniel Cheng <dcheng@chromium.org> | 2015-12-17 17:15:09 -0800 |
---|---|---|
committer | Daniel Cheng <dcheng@chromium.org> | 2015-12-18 01:17:04 +0000 |
commit | b82e8ec46f4b1fd53a8f62ac5bb4c6395b920c37 (patch) | |
tree | fe3b967c51acace6d8e0e36942e20e61e0bcd7a3 /tools/clang | |
parent | d2aa19d6109954ad1ac499b3e0be7c9295a3606e (diff) | |
download | chromium_src-b82e8ec46f4b1fd53a8f62ac5bb4c6395b920c37.zip chromium_src-b82e8ec46f4b1fd53a8f62ac5bb4c6395b920c37.tar.gz chromium_src-b82e8ec46f4b1fd53a8f62ac5bb4c6395b920c37.tar.bz2 |
Script to apply fixits generated by Clang.
Though clang has a mode to automatically apply fixits and recompile with
the -Xclang -fixit-recompile flag, this doesn't work well with parallel
invocations of clang.
BUG=557422
R=thakis@chromium.org
Review URL: https://codereview.chromium.org/1538703002 .
Cr-Commit-Position: refs/heads/master@{#365957}
Diffstat (limited to 'tools/clang')
-rwxr-xr-x | tools/clang/scripts/apply_fixits.py | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/tools/clang/scripts/apply_fixits.py b/tools/clang/scripts/apply_fixits.py new file mode 100755 index 0000000..6387f2d --- /dev/null +++ b/tools/clang/scripts/apply_fixits.py @@ -0,0 +1,88 @@ +#!/usr/bin/env/python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Script to apply fixits generated by clang. This is to work around the fact +# that clang's -Xclang -fixit-recompile flag, which automatically applies fixits +# and recompiles, doesn't work well with parallel invocations of clang. +# +# Usage: +# 1. Enable parseable fixits and disable warnings as errors. Instructions for +# doing this vary based on the build environment, but for GN, warnings as +# errors can be disabled by setting treat_warnings_as_errors = false +# Enabling parseable fixits requires editing build/config/compiler/BUILD.gn +# and adding `-fdiagnostics-parseable-fixits` to cflags. +# 2. Build everything and capture the output: +# ninja -C <build_directory> &> generated-fixits +# 3. Apply the fixits with this script: +# python apply_fixits.py[ <build_directory>] < generated-fixits +# <build_directory> is optional and only required if your build directory is +# a non-standard location. + +import argparse +import collections +import fileinput +import os +import re +import sys + +# fix-it:"../../base/threading/sequenced_worker_pool.h":{341:3-341:11}:"" +# Note that the file path is relative to the build directory. +_FIXIT_RE = re.compile(r'^fix-it:"(?P<file>.+?)":' + r'{(?P<start_line>\d+?):(?P<start_col>\d+?)-' + r'(?P<end_line>\d+?):(?P<end_col>\d+?)}:' + r'"(?P<text>.*?)"$') + +FixIt = collections.namedtuple( + 'FixIt', ('start_line', 'start_col', 'end_line', 'end_col', 'text')) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + 'build_directory', + nargs='?', + default='out/Debug', + help='path to the build directory to complete relative paths in fixits') + args = parser.parse_args() + + fixits = collections.defaultdict(list) + for line in fileinput.input(): + if not line.startswith('fix-it:'): + continue + m = _FIXIT_RE.match(line) + if not m: + continue + # The negative line numbers are a cheap hack so we can sort things in line + # order but reverse column order. Applying the fixits in reverse order makes + # things simpler, since offsets won't have to be adjusted as the text is + # changed. + fixits[m.group('file')].append(FixIt( + int(m.group('start_line')), -int(m.group('start_col')), int(m.group( + 'end_line')), -int(m.group('end_col')), m.group('text'))) + for k, v in fixits.iteritems(): + v.sort() + with open(os.path.join(args.build_directory, k), 'rb+') as f: + lines = f.readlines() + last_fixit = None + for fixit in v: + if fixit.start_line != fixit.end_line: + print 'error: multiline fixits not supported! file: %s, fixit: %s' % ( + k, fixit) + sys.exit(1) + if fixit == last_fixit: + continue + last_fixit = fixit + # The line/column numbers emitted in fixit hints start at 1, so offset + # is appropriately. + line = lines[fixit.start_line - 1] + lines[fixit.start_line - 1] = (line[:-fixit.start_col - 1] + fixit.text + + line[-fixit.end_col - 1:]) + f.seek(0) + f.truncate() + f.writelines(lines) + + +if __name__ == '__main__': + sys.exit(main()) |