summaryrefslogtreecommitdiffstats
path: root/tools/clang
diff options
context:
space:
mode:
authorDaniel Cheng <dcheng@chromium.org>2015-12-17 17:15:09 -0800
committerDaniel Cheng <dcheng@chromium.org>2015-12-18 01:17:04 +0000
commitb82e8ec46f4b1fd53a8f62ac5bb4c6395b920c37 (patch)
treefe3b967c51acace6d8e0e36942e20e61e0bcd7a3 /tools/clang
parentd2aa19d6109954ad1ac499b3e0be7c9295a3606e (diff)
downloadchromium_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-xtools/clang/scripts/apply_fixits.py88
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())