[cfe-commits] [clang-tools-extra] r171994 - /clang-tools-extra/trunk/clang-format/clang-format-diff.py

Matt Beaumont-Gay matthewbg at google.com
Wed Jan 9 16:04:25 PST 2013


On Wed, Jan 9, 2013 at 12:20 PM, Daniel Jasper <djasper at google.com> wrote:
> Author: djasper
> Date: Wed Jan  9 14:20:11 2013
> New Revision: 171994
>
> URL: http://llvm.org/viewvc/llvm-project?rev=171994&view=rev
> Log:
> Initial version of diff/patch-reformat tool.
>
> Use at your own risk :-).
>
> Added:
>     clang-tools-extra/trunk/clang-format/clang-format-diff.py   (with props)
>
> Added: clang-tools-extra/trunk/clang-format/clang-format-diff.py
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-format/clang-format-diff.py?rev=171994&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/clang-format/clang-format-diff.py (added)
> +++ clang-tools-extra/trunk/clang-format/clang-format-diff.py Wed Jan  9 14:20:11 2013
> @@ -0,0 +1,117 @@
> +#!/usr/bin/python
> +#
> +#===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===#
> +#
> +#                     The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +#===------------------------------------------------------------------------===#
> +
> +r"""
> +ClangFormat Diff Reformatter
> +============================
> +
> +This script reads input from a unified diff and reformats all the changed
> +lines. This is useful to reformat all the lines touched by a specific patch.
> +Example usage for git users:
> +
> +  git diff -U0 HEAD^ | clang-format-diff.py -p1
> +
> +"""
> +
> +import argparse
> +import re
> +import subprocess
> +import sys
> +
> +
> +# Change this to the full path if clang-format is not on the path.
> +binary = 'clang-format'
> +
> +
> +def getOffsetLength(filename, line_number, line_count):
> +  """
> +  Calculates the field offset and length based on line number and count.
> +  """
> +  offset = 0
> +  length = 0
> +  with open(filename, 'r') as f:
> +    for line in f:
> +      if line_number > 1:
> +        offset += len(line)
> +        line_number -= 1
> +      elif line_count > 0:
> +        length += len(line)
> +        line_count -= 1
> +      else:
> +        break
> +  return offset, length
> +
> +
> +def formatRange(r, style):
> +  """
> +  Formats range 'r' according to style 'style'.
> +  """
> +  filename, line_number, line_count = r

Maybe define a namedtuple (collections.namedtuple) for this?

> +  # FIXME: Add other types containing C++/ObjC code.
> +  if not (filename.endswith(".cpp") or filename.endswith(".cc") or
> +          filename.endswith(".h")):

if os.path.splitext(filename)[1] not in ('cc', 'cpp', 'h'):

> +    return
> +
> +  offset, length = getOffsetLength(filename, line_number, line_count)
> +  with open(filename, 'r') as f:
> +    text = f.read()
> +  p = subprocess.Popen([binary, '-offset', str(offset), '-length', str(length),
> +                        '-style', style],
> +                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
> +                       stdin=subprocess.PIPE)
> +  stdout, stderr = p.communicate(input=text)
> +  if stderr:
> +    print stderr

print >>sys.stderr, stderr

Or just hook up the subprocess's stderr to our stderr?

> +    return
> +  if not stdout:
> +    print 'Segfault occurred while formatting', filename
> +    print 'Please report a bug on llvm.org/bugs.'
> +    return
> +  with open(filename, 'w') as f:
> +    f.write(stdout)
> +
> +
> +def main():
> +  parser = argparse.ArgumentParser(description=
> +                                   'Reformat changed lines in diff')
> +  parser.add_argument('-p', default=1,
> +                      help='strip the smallest prefix containing P slashes')
> +  parser.add_argument('-style', default='LLVM',
> +                      help='formatting style to apply (LLVM, Google)')
> +  args = parser.parse_args()
> +
> +  filename = None
> +  ranges = []
> +
> +  for line in sys.stdin:
> +    match = re.search('^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)

I like to have a comment with an example along with nontrivial regular
expressions.

Also, here and below, you can use re.match instead of anchoring the
regex with '^'.

> +    if match:
> +      filename = match.group(2)
> +    if filename == None:

if filename is None:

> +      continue
> +
> +    match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
> +    if match:
> +      line_count = 1
> +      if match.group(3):
> +        line_count = int(match.group(3))
> +      ranges.append((filename, int(match.group(1)), line_count))
> +
> +  # Reverse the ranges so that the reformatting does not influence file offsets.
> +  ranges.reverse()
> +
> +  # Do the actual formatting.
> +  for r in ranges:
> +    formatRange(r, args.style)
> +
> +
> +if __name__ == '__main__':
> +  main()
>
> Propchange: clang-tools-extra/trunk/clang-format/clang-format-diff.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


On Wed, Jan 9, 2013 at 12:20 PM, Daniel Jasper <djasper at google.com> wrote:
> Author: djasper
> Date: Wed Jan  9 14:20:11 2013
> New Revision: 171994
>
> URL: http://llvm.org/viewvc/llvm-project?rev=171994&view=rev
> Log:
> Initial version of diff/patch-reformat tool.
>
> Use at your own risk :-).
>
> Added:
>     clang-tools-extra/trunk/clang-format/clang-format-diff.py   (with props)
>
> Added: clang-tools-extra/trunk/clang-format/clang-format-diff.py
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-format/clang-format-diff.py?rev=171994&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/clang-format/clang-format-diff.py (added)
> +++ clang-tools-extra/trunk/clang-format/clang-format-diff.py Wed Jan  9 14:20:11 2013
> @@ -0,0 +1,117 @@
> +#!/usr/bin/python
> +#
> +#===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===#
> +#
> +#                     The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +#===------------------------------------------------------------------------===#
> +
> +r"""
> +ClangFormat Diff Reformatter
> +============================
> +
> +This script reads input from a unified diff and reformats all the changed
> +lines. This is useful to reformat all the lines touched by a specific patch.
> +Example usage for git users:
> +
> +  git diff -U0 HEAD^ | clang-format-diff.py -p1
> +
> +"""
> +
> +import argparse
> +import re
> +import subprocess
> +import sys
> +
> +
> +# Change this to the full path if clang-format is not on the path.
> +binary = 'clang-format'
> +
> +
> +def getOffsetLength(filename, line_number, line_count):
> +  """
> +  Calculates the field offset and length based on line number and count.
> +  """
> +  offset = 0
> +  length = 0
> +  with open(filename, 'r') as f:
> +    for line in f:
> +      if line_number > 1:
> +        offset += len(line)
> +        line_number -= 1
> +      elif line_count > 0:
> +        length += len(line)
> +        line_count -= 1
> +      else:
> +        break
> +  return offset, length
> +
> +
> +def formatRange(r, style):
> +  """
> +  Formats range 'r' according to style 'style'.
> +  """
> +  filename, line_number, line_count = r
> +  # FIXME: Add other types containing C++/ObjC code.
> +  if not (filename.endswith(".cpp") or filename.endswith(".cc") or
> +          filename.endswith(".h")):
> +    return
> +
> +  offset, length = getOffsetLength(filename, line_number, line_count)
> +  with open(filename, 'r') as f:
> +    text = f.read()
> +  p = subprocess.Popen([binary, '-offset', str(offset), '-length', str(length),
> +                        '-style', style],
> +                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
> +                       stdin=subprocess.PIPE)
> +  stdout, stderr = p.communicate(input=text)
> +  if stderr:
> +    print stderr
> +    return
> +  if not stdout:
> +    print 'Segfault occurred while formatting', filename
> +    print 'Please report a bug on llvm.org/bugs.'
> +    return
> +  with open(filename, 'w') as f:
> +    f.write(stdout)
> +
> +
> +def main():
> +  parser = argparse.ArgumentParser(description=
> +                                   'Reformat changed lines in diff')
> +  parser.add_argument('-p', default=1,
> +                      help='strip the smallest prefix containing P slashes')
> +  parser.add_argument('-style', default='LLVM',
> +                      help='formatting style to apply (LLVM, Google)')
> +  args = parser.parse_args()
> +
> +  filename = None
> +  ranges = []
> +
> +  for line in sys.stdin:
> +    match = re.search('^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
> +    if match:
> +      filename = match.group(2)
> +    if filename == None:
> +      continue
> +
> +    match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
> +    if match:
> +      line_count = 1
> +      if match.group(3):
> +        line_count = int(match.group(3))
> +      ranges.append((filename, int(match.group(1)), line_count))
> +
> +  # Reverse the ranges so that the reformatting does not influence file offsets.
> +  ranges.reverse()
> +
> +  # Do the actual formatting.
> +  for r in ranges:
> +    formatRange(r, args.style)
> +
> +
> +if __name__ == '__main__':
> +  main()
>
> Propchange: clang-tools-extra/trunk/clang-format/clang-format-diff.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list