[clang-tools-extra] r211698 - Add clang-tidy-diff.py script to run clang-tidy and display warnings on changed lines only.
NAKAMURA Takumi
geek4civic at gmail.com
Thu Jun 26 09:37:56 PDT 2014
LGTM.
2014-06-27 1:36 GMT+09:00 Alexander Kornienko <alexfh at google.com>:
> On Thu, Jun 26, 2014 at 6:09 PM, NAKAMURA Takumi <geek4civic at gmail.com>
> wrote:
>>
>> Since clang-tidy-diff.py is not a test script but a tool, it's fine to
>> require modern version of python for it.
>>
>> Note, your test script invokes python as "python", but lit might not
>> run with "python".
>
>
> Yep, this wasn't very reliable.
>
>>
>> For example in CMake build, PYTHON_EXECUTABLE is used.
>> Consider that it is out of $PATH, or it is like "python32".
>>
>> Then you should import config.python_executable from llvm/test.
>
>
> I'm don't know to import it (if you know, please enlighten me), but I know
> how to generate from the lit.site.cfg.in. Here's the updated patch:
>
> Index: test/Makefile
> ===================================================================
> --- test/Makefile (revision 211769)
> +++ test/Makefile (working copy)
> @@ -52,6 +52,7 @@
> @$(ECHOPATH) s=@CLANG_TOOLS_SOURCE_DIR@=$(PROJ_SRC_DIR)/..=g >>
> lit.tmp
> @$(ECHOPATH) s=@CLANG_TOOLS_BINARY_DIR@=$(PROJ_OBJ_DIR)/..=g >>
> lit.tmp
> @$(ECHOPATH) s=@CLANG_TOOLS_DIR@=$(ToolDir)=g >> lit.tmp
> + @$(ECHOPATH) s=@PYTHON_EXECUTABLE@=$(PYTHON)=g >> lit.tmp
> @$(ECHOPATH) s=@TARGET_TRIPLE@=$(TARGET_TRIPLE)=g >> lit.tmp
> @sed -f lit.tmp $(PROJ_SRC_DIR)/lit.site.cfg.in > $@
> @-rm -f lit.tmp
> Index: test/clang-tidy/clang-tidy-diff.cpp
> ===================================================================
> --- test/clang-tidy/clang-tidy-diff.cpp (revision 211769)
> +++ test/clang-tidy/clang-tidy-diff.cpp (working copy)
> @@ -1,6 +1,7 @@
> +// REQUIRES: python27
> // RUN: sed 's/placeholder_for_f/f/' %s > %t.cpp
> // RUN: clang-tidy -checks=-*,misc-use-override %t.cpp -- -std=c++11 |
> FileCheck -check-prefix=CHECK-SANITY %s
> -// R_U_N: not diff -U0 %s %t.cpp | python
> %S/../../clang-tidy/tool/clang-tidy-diff.py -checks=-*,misc-use-override --
> -std=c++11 2>&1 | FileCheck %s
> +// RUN: not diff -U0 %s %t.cpp | %python
> %S/../../clang-tidy/tool/clang-tidy-diff.py -checks=-*,misc-use-override --
> -std=c++11 2>&1 | FileCheck %s
> struct A {
> virtual void f() {}
> virtual void g() {}
> Index: test/lit.cfg
> ===================================================================
> --- test/lit.cfg (revision 211769)
> +++ test/lit.cfg (working copy)
> @@ -174,3 +174,10 @@
> # ANSI escape sequences in non-dumb terminal
> if platform.system() not in ['Windows']:
> config.available_features.add('ansi-escape-sequences')
> +
> +config.substitutions.append( ('%python', config.python_executable) )
> +
> +import sys
> +# Scripts using argparse need Python 2.7.
> +if sys.version_info >= (2, 7):
> + config.available_features.add('python27')
> Index: test/lit.site.cfg.in
> ===================================================================
> --- test/lit.site.cfg.in (revision 211769)
> +++ test/lit.site.cfg.in (working copy)
> @@ -7,6 +7,7 @@
> config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
> config.clang_tools_binary_dir = "@CLANG_TOOLS_BINARY_DIR@"
> config.clang_tools_dir = "@CLANG_TOOLS_DIR@"
> +config.python_executable = "@PYTHON_EXECUTABLE@"
> config.target_triple = "@TARGET_TRIPLE@"
>
> # Support substitution of the tools and libs dirs with user parameters.
> This is
>
>
>>
>>
>> 2014-06-26 23:46 GMT+09:00 Alexander Kornienko <alexfh at google.com>:
>> > It seems like we can't require Python 2.7 for running tests, but I'm
>> > also
>> > against rewriting the script using deprecated APIs. I'd better make this
>> > test conditional on the availability of Python 2.7. What do you think?
>> >
>> > Here's the patch which implements this:
>> >
>> > Index: test/clang-tidy/clang-tidy-diff.cpp
>> > ===================================================================
>> > --- test/clang-tidy/clang-tidy-diff.cpp (revision 211769)
>> > +++ test/clang-tidy/clang-tidy-diff.cpp (working copy)
>> > @@ -1,6 +1,7 @@
>> > +// REQUIRES: python27
>> > // RUN: sed 's/placeholder_for_f/f/' %s > %t.cpp
>> > // RUN: clang-tidy -checks=-*,misc-use-override %t.cpp -- -std=c++11 |
>> > FileCheck -check-prefix=CHECK-SANITY %s
>> > -// R_U_N: not diff -U0 %s %t.cpp | python
>> > %S/../../clang-tidy/tool/clang-tidy-diff.py -checks=-*,misc-use-override
>> > --
>> > -std=c++11 2>&1 | FileCheck %s
>> > +// RUN: not diff -U0 %s %t.cpp | python
>> > %S/../../clang-tidy/tool/clang-tidy-diff.py -checks=-*,misc-use-override
>> > --
>> > -std=c++11 2>&1 | FileCheck %s
>> > struct A {
>> > virtual void f() {}
>> > virtual void g() {}
>> > Index: test/lit.cfg
>> > ===================================================================
>> > --- test/lit.cfg (revision 211769)
>> > +++ test/lit.cfg (working copy)
>> > @@ -174,3 +174,8 @@
>> > # ANSI escape sequences in non-dumb terminal
>> > if platform.system() not in ['Windows']:
>> > config.available_features.add('ansi-escape-sequences')
>> > +
>> > +import sys
>> > +# Scripts using argparse need Python 2.7.
>> > +if sys.version_info >= (2, 7):
>> > + config.available_features.add('python27')
>> >
>> >
>> >
>> > On Thu, Jun 26, 2014 at 1:45 AM, Alexander Kornienko <alexfh at google.com>
>> > wrote:
>> >>
>> >> On Thu, Jun 26, 2014 at 1:24 AM, NAKAMURA Takumi <geek4civic at gmail.com>
>> >> wrote:
>> >>>
>> >>> 2014-06-25 23:09 GMT+09:00 Alexander Kornienko <alexfh at google.com>:
>> >>> > Author: alexfh
>> >>> > Date: Wed Jun 25 09:09:52 2014
>> >>> > New Revision: 211698
>> >>> >
>> >>> > URL: http://llvm.org/viewvc/llvm-project?rev=211698&view=rev
>> >>> > Log:
>> >>> > Add clang-tidy-diff.py script to run clang-tidy and display warnings
>> >>> > on
>> >>> > changed lines only.
>> >>> >
>> >>> > Reviewers: djasper
>> >>> >
>> >>> > Reviewed By: djasper
>> >>> >
>> >>> > Subscribers: cfe-commits
>> >>> >
>> >>> > Differential Revision: http://reviews.llvm.org/D4288
>> >>> >
>> >>> > Added:
>> >>> > clang-tools-extra/trunk/clang-tidy/tool/clang-tidy-diff.py
>> >>> > (with
>> >>> > props)
>> >>> > clang-tools-extra/trunk/test/clang-tidy/clang-tidy-diff.cpp
>> >>> >
>> >>> > Added: clang-tools-extra/trunk/clang-tidy/tool/clang-tidy-diff.py
>> >>> > URL:
>> >>> >
>> >>> > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/clang-tidy-diff.py?rev=211698&view=auto
>> >>> >
>> >>> >
>> >>> > ==============================================================================
>> >>> > --- clang-tools-extra/trunk/clang-tidy/tool/clang-tidy-diff.py
>> >>> > (added)
>> >>> > +++ clang-tools-extra/trunk/clang-tidy/tool/clang-tidy-diff.py Wed
>> >>> > Jun
>> >>> > 25 09:09:52 2014
>> >>> > @@ -0,0 +1,115 @@
>> >>> > +#!/usr/bin/python
>> >>> > +#
>> >>> > +#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*-
>> >>> > python -*--===#
>> >>> > +#
>> >>> > +# The LLVM Compiler Infrastructure
>> >>> > +#
>> >>> > +# This file is distributed under the University of Illinois Open
>> >>> > Source
>> >>> > +# License. See LICENSE.TXT for details.
>> >>> > +#
>> >>> >
>> >>> >
>> >>> > +#===------------------------------------------------------------------------===#
>> >>> > +
>> >>> > +r"""
>> >>> > +ClangTidy Diff Checker
>> >>> > +======================
>> >>> > +
>> >>> > +This script reads input from a unified diff, runs clang-tidy on all
>> >>> > changed
>> >>> > +files and outputs clang-tidy warnings in changed lines only. This
>> >>> > is
>> >>> > useful to
>> >>> > +detect clang-tidy regressions in the lines touched by a specific
>> >>> > patch.
>> >>> > +Example usage for git/svn users:
>> >>> > +
>> >>> > + git diff -U0 HEAD^ | clang-tidy-diff.py -p1
>> >>> > + svn diff --diff-cmd=diff -x-U0 | \
>> >>> > + clang-tidy-diff.py -fix -checks=-*,misc-use-override
>> >>> > +
>> >>> > +"""
>> >>> > +
>> >>> > +import argparse
>> >>>
>> >>> argparse has been introduced since 2.7. I suppose we can still use
>> >>> 2.6.
>> >>
>> >>
>> >> Python 2.7 has been available since 2010, and it should be available
>> >> virtually everywhere. I've not seen any python-related buildbot
>> >> failures
>> >> after this patch, so I suppose they all use up-to-date python. Can you
>> >> provide more details: where is python 2.6 still used and why do we need
>> >> to
>> >> support it?
>> >>
>> >>>
>> >>> Suppressed in r211741. Could you rewrite to avoid argparse?
>> >>
>> >>
>> >> Python 2.6 had optparse, which has been deprecated since 2.7. I don't
>> >> think it's a good idea to rewrite the script using deprecated api.
>> >>
>> >>>
>> >>> > +import json
>> >>> > +import re
>> >>> > +import subprocess
>> >>> > +import sys
>> >>> > +
>> >>> > +
>> >>> > +def main():
>> >>> > + parser = argparse.ArgumentParser(description=
>> >>> > + 'Reformat changed lines in diff.
>> >>> > Without -i '
>> >>> > + 'option just output the diff
>> >>> > that
>> >>> > would be '
>> >>> > + 'introduced.')
>> >>> > + parser.add_argument('-clang-tidy-binary', metavar='PATH',
>> >>> > + default='clang-tidy',
>> >>> > + help='path to clang-tidy binary')
>> >>> > + parser.add_argument('-p', metavar='NUM', default=0,
>> >>> > + help='strip the smallest prefix containing P
>> >>> > slashes')
>> >>> > + parser.add_argument('-regex', metavar='PATTERN', default=None,
>> >>> > + help='custom pattern selecting file paths to
>> >>> > reformat '
>> >>> > + '(case sensitive, overrides -iregex)')
>> >>> > + parser.add_argument('-iregex', metavar='PATTERN', default=
>> >>> > +
>> >>> > r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)',
>> >>> > + help='custom pattern selecting file paths to
>> >>> > reformat '
>> >>> > + '(case insensitive, overridden by -regex)')
>> >>> > +
>> >>> > + parser.add_argument('-fix', action='store_true', default=False,
>> >>> > + help='apply suggested fixes')
>> >>> > + parser.add_argument('-checks',
>> >>> > + help='checks filter, when not specified, use
>> >>> > clang-tidy '
>> >>> > + 'default',
>> >>> > + default='')
>> >>> > + clang_tidy_args = []
>> >>> > + argv = sys.argv[1:]
>> >>> > + if '--' in argv:
>> >>> > + clang_tidy_args.extend(argv[argv.index('--'):])
>> >>> > + argv = argv[:argv.index('--')]
>> >>> > +
>> >>> > + args = parser.parse_args(argv)
>> >>> > +
>> >>> > + # Extract changed lines for each file.
>> >>> > + filename = None
>> >>> > + lines_by_file = {}
>> >>> > + for line in sys.stdin:
>> >>> > + match = re.search('^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
>> >>> > + if match:
>> >>> > + filename = match.group(2)
>> >>> > + if filename == None:
>> >>> > + continue
>> >>> > +
>> >>> > + if args.regex is not None:
>> >>> > + if not re.match('^%s$' % args.regex, filename):
>> >>> > + continue
>> >>> > + else:
>> >>> > + if not re.match('^%s$' % args.iregex, filename,
>> >>> > re.IGNORECASE):
>> >>> > + continue
>> >>> > +
>> >>> > + match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
>> >>> > + if match:
>> >>> > + start_line = int(match.group(1))
>> >>> > + line_count = 1
>> >>> > + if match.group(3):
>> >>> > + line_count = int(match.group(3))
>> >>> > + if line_count == 0:
>> >>> > + continue
>> >>> > + end_line = start_line + line_count - 1;
>> >>> > + lines_by_file.setdefault(filename, []).append([start_line,
>> >>> > end_line])
>> >>> > +
>> >>> > + if len(lines_by_file) == 0:
>> >>> > + print "No relevant changes found."
>> >>> > + sys.exit(0)
>> >>> > +
>> >>> > + line_filter_json = json.dumps(
>> >>> > + [{"name" : name, "lines" : lines_by_file[name]} for name in
>> >>> > lines_by_file],
>> >>> > + separators = (',', ':'))
>> >>> > +
>> >>> > + # Run clang-tidy on files containing changes.
>> >>> > + command = [args.clang_tidy_binary]
>> >>> > + command.append('-line-filter=\'' + line_filter_json + '\'')
>> >>> > + if args.fix:
>> >>> > + command.append('-fix')
>> >>> > + if args.checks != '':
>> >>> > + command.append('-checks=\'' + args.checks + '\'')
>> >>> > + command.extend(lines_by_file.keys())
>> >>> > + command.extend(clang_tidy_args)
>> >>> > +
>> >>> > + sys.exit(subprocess.call(' '.join(command), shell=True))
>> >>> > +
>> >>> > +if __name__ == '__main__':
>> >>> > + main()
>> >>> >
>> >>> > Propchange:
>> >>> > clang-tools-extra/trunk/clang-tidy/tool/clang-tidy-diff.py
>> >>> >
>> >>> >
>> >>> > ------------------------------------------------------------------------------
>> >>> > svn:executable = *
>> >>> >
>> >>> > Added: clang-tools-extra/trunk/test/clang-tidy/clang-tidy-diff.cpp
>> >>> > URL:
>> >>> >
>> >>> > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/clang-tidy-diff.cpp?rev=211698&view=auto
>> >>> >
>> >>> >
>> >>> > ==============================================================================
>> >>> > --- clang-tools-extra/trunk/test/clang-tidy/clang-tidy-diff.cpp
>> >>> > (added)
>> >>> > +++ clang-tools-extra/trunk/test/clang-tidy/clang-tidy-diff.cpp Wed
>> >>> > Jun
>> >>> > 25 09:09:52 2014
>> >>> > @@ -0,0 +1,18 @@
>> >>> > +// RUN: sed 's/placeholder_for_f/f/' %s > %t.cpp
>> >>> > +// RUN: clang-tidy -checks=-*,misc-use-override %t.cpp --
>> >>> > -std=c++11 |
>> >>> > FileCheck -check-prefix=CHECK-SANITY %s
>> >>> > +// RUN: not diff -u0 %s %t.cpp | python
>> >>> > %S/../../clang-tidy/tool/clang-tidy-diff.py
>> >>> > -checks=-*,misc-use-override --
>> >>> > -std=c++11 2>&1 | FileCheck %s
>> >>> > +struct A {
>> >>> > + virtual void f() {}
>> >>> > + virtual void g() {}
>> >>> > +};
>> >>> > +// CHECK-NOT: warning
>> >>> > +struct B : public A {
>> >>> > + void placeholder_for_f() {}
>> >>> > +// CHECK-SANITY: [[@LINE-1]]:8: warning: Use exactly
>> >>> > +// CHECK: [[@LINE-2]]:8: warning: Use exactly
>> >>> > + void g() {}
>> >>> > +// CHECK-SANITY: [[@LINE-1]]:8: warning: Use exactly
>> >>> > +// CHECK-NOT: warning:
>> >>> > +};
>> >>> > +// CHECK-SANITY-NOT: Suppressed
>> >>> > +// CHECK: Suppressed 1 warnings (1 due to line filter).
>> >
>> >
More information about the cfe-commits
mailing list