summaryrefslogtreecommitdiffstats
path: root/ppapi/generators
diff options
context:
space:
mode:
authornoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-27 18:03:05 +0000
committernoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-27 18:03:05 +0000
commit03fcdb90f3c64f5a755d9c61b7a7468e1cffcae8 (patch)
tree2639153dbe50ecd98d6deace044b2fedd89f060b /ppapi/generators
parent2e57eb0408cb0f2f5e4c8f546cd4fd9126267632 (diff)
downloadchromium_src-03fcdb90f3c64f5a755d9c61b7a7468e1cffcae8.zip
chromium_src-03fcdb90f3c64f5a755d9c61b7a7468e1cffcae8.tar.gz
chromium_src-03fcdb90f3c64f5a755d9c61b7a7468e1cffcae8.tar.bz2
Add diff tool for IDL
This CL adds a diff tool which will take all generated headers found, and diff them against the matching original headers while ignoring common difference that are not real issues such as blank lines, changes in whitespace, etc... BUG= http://code.google.com/p/chromium/issues/detail?id=76271 TEST= python idl_diff.py --src=../c --gen=hdir ---Paths modified but not in any changelist: Review URL: http://codereview.chromium.org/7242020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90609 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/generators')
-rw-r--r--ppapi/generators/idl_diff.py191
1 files changed, 191 insertions, 0 deletions
diff --git a/ppapi/generators/idl_diff.py b/ppapi/generators/idl_diff.py
new file mode 100644
index 0000000..d005a20
--- /dev/null
+++ b/ppapi/generators/idl_diff.py
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2011 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.
+
+import glob
+import os
+import subprocess
+import sys
+
+from idl_option import GetOption, Option, ParseOptions
+
+#
+# IDLDiff
+#
+# IDLDiff is a tool for comparing sets of IDL generated header files
+# with the standard checked in headers. It does this by capturing the
+# output of the standard diff tool, parsing it into separate changes, then
+# ignoring changes that are know to be safe, such as adding or removing
+# blank lines, etc...
+#
+
+Option('gen', 'IDL generated files', default='hdir')
+Option('src', 'Original ".h" files', default='../c')
+
+# Change
+#
+# A Change object contains the previous lines, new news and change type.
+#
+class Change(object):
+ def __init__(self, change):
+ self.mode = str(change['mode'])
+ self.was = list(change['was'])
+ self.now = list(change['now'])
+
+ def Dump(self):
+ if not self.was:
+ print 'Adding %s' % self.mode
+ elif not self.now:
+ print 'Missing %s' % self.mode
+ else:
+ print 'Modifying %s' % self.mode
+
+ for line in self.was:
+ print 'src: %s' % line
+ for line in self.now:
+ print 'gen: %s' % line
+ print
+
+#
+# IsCopyright
+#
+# Return True if this change is only a one line change in the copyright notice
+# such as non-matching years.
+#
+def IsCopyright(change):
+ if len(change['now']) != 1 or len(change['was']) != 1: return False
+ if 'Copyright (c)' not in change['now'][0]: return False
+ if 'Copyright (c)' not in change['was'][0]: return False
+ return True
+
+#
+# IsBlank
+#
+# Return True if this change only adds or removes blank lines
+#
+def IsBlank(change):
+ for line in change['now']:
+ if line: return False
+ for line in change['was']:
+ if line: return False
+ return True
+
+
+#
+# IsSpacing
+#
+# Return True if this change is only different in the way 'words' are spaced
+# such as in an enum:
+# ENUM_XXX = 1,
+# ENUM_XYY_Y = 2,
+# vs
+# ENUM_XXX = 1,
+# ENUM_XYY_Y = 2,
+#
+def IsSpacing(change):
+ if len(change['now']) != len(change['was']): return False
+ for i in range(len(change['now'])):
+ # Also ignore right side comments
+ line = change['was'][i]
+ offs = line.find('//')
+ if offs == -1:
+ offs = line.find('/*')
+ if offs >-1:
+ line = line[:offs-1]
+
+ words1 = change['now'][i].split()
+ words2 = line.split()
+ if words1 != words2: return False
+ return True
+
+#
+# IsInclude
+#
+# Return True if change has extra includes
+#
+def IsInclude(change):
+ if len(change['was']): return False
+ for line in change['now']:
+ if line and '#include' not in line: return False
+ return True
+
+#
+# IsCppComment
+#
+# Return True if the change is only missing C++ comments
+#
+def IsCppComment(change):
+ if len(change['now']): return False
+ for line in change['was']:
+ line = line.strip()
+ if line[:2] != '//': return False
+ return True
+#
+# ValidChange
+#
+# Return True if none of the changes does not patch an above "bogus" change.
+#
+def ValidChange(change):
+ if IsCopyright(change): return False
+ if IsBlank(change): return False
+ if IsSpacing(change): return False
+ if IsInclude(change): return False
+ if IsCppComment(change): return False
+ return True
+
+
+
+#
+# GetChanges
+#
+# Parse the output into discrete change blocks.
+#
+def GetChanges(output):
+ lines = output.split('\n')
+ changes = []
+ change = { 'mode' : None,
+ 'was': [],
+ 'now': []
+ }
+ for line in lines:
+ if not line: continue
+ elif line[0] == '<':
+ change['was'].append(line[2:])
+ elif line[0] == '>':
+ change['now'].append(line[2:])
+ elif line[0] == '-':
+ continue
+ else:
+ if ValidChange(change): changes.append(Change(change))
+ change['mode'] = line
+ change['now'] = []
+ change['was'] = []
+ if ValidChange(change): changes.append(Change(change))
+ return changes
+
+def Main(args):
+ filenames = ParseOptions(args)
+ if not filenames:
+ gendir = os.path.join(GetOption('gen'), '*.h')
+ filenames = glob.glob(gendir)
+
+ for filename in filenames:
+ gen = filename
+ filename = filename[len(GetOption('gen')) + 1:]
+ src = os.path.join(GetOption('src'), filename)
+ p = subprocess.Popen(['diff', src, gen], stdout=subprocess.PIPE)
+ output, errors = p.communicate()
+
+ changes = GetChanges(output)
+ if changes:
+ print "\n\nDelta between:\n src=%s\n gen=%s\n" % (src, gen)
+ for change in GetChanges(output):
+ change.Dump()
+ else:
+ print "\nSAME:\n src=%s\n gen=%s\n" % (src, gen)
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
+