Add style checker for CMake lists
authorparoga@webkit.org <paroga@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Sep 2013 18:00:18 +0000 (18:00 +0000)
committerparoga@webkit.org <paroga@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Sep 2013 18:00:18 +0000 (18:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=121764

Reviewed by Ryosuke Niwa.

Add an additional check to make sure that list of files are sorted.
Exclude lists of include directories for now, since the order
can be importent for compilation of some files.

* Scripts/webkitpy/style/checkers/cmake.py:
(CMakeChecker.check):
(CMakeChecker._check_indent):
(CMakeChecker):
(CMakeChecker._check_list_order):
(CMakeChecker._list_item_path):
* Scripts/webkitpy/style/checkers/cmake_unittest.py:
(CMakeCheckerTest.test_check):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@156405 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/webkitpy/style/checkers/cmake.py
Tools/Scripts/webkitpy/style/checkers/cmake_unittest.py

index a117429..72e1ad7 100644 (file)
@@ -1,5 +1,25 @@
 2013-09-25  Patrick Gansterer  <paroga@webkit.org>
 
+        Add style checker for CMake lists
+        https://bugs.webkit.org/show_bug.cgi?id=121764
+
+        Reviewed by Ryosuke Niwa.
+
+        Add an additional check to make sure that list of files are sorted.
+        Exclude lists of include directories for now, since the order
+        can be importent for compilation of some files.
+
+        * Scripts/webkitpy/style/checkers/cmake.py:
+        (CMakeChecker.check):
+        (CMakeChecker._check_indent):
+        (CMakeChecker):
+        (CMakeChecker._check_list_order):
+        (CMakeChecker._list_item_path):
+        * Scripts/webkitpy/style/checkers/cmake_unittest.py:
+        (CMakeCheckerTest.test_check):
+
+2013-09-25  Patrick Gansterer  <paroga@webkit.org>
+
         CMakeChecker takes unusually long time to run
         https://bugs.webkit.org/show_bug.cgi?id=105662
 
index a004629..85c446f 100644 (file)
@@ -93,6 +93,7 @@ class CMakeChecker(object):
         self._num_lines = len(lines)
         for l in xrange(self._num_lines):
             self._process_line(l + 1, lines[l])
+        self._check_list_order(lines)
 
     def _process_line(self, line_number, line_content):
         if match('(^|\ +)#', line_content):
@@ -146,3 +147,59 @@ class CMakeChecker(object):
     def _check_indent(self, line_number, line_content):
         #TODO (halton): add indent checking
         pass
+
+    def _check_list_order(self, lines):
+        last_line = None
+
+        line_number = 0
+        for line in lines:
+            line_number += 1
+            line = line.strip()
+
+            if last_line == None:
+                matched = match('(set\(|list\((APPEND|REMOVE_ITEM) )(?P<name>\w+)(?P<item>\s+\w+)?$', line)
+                if matched:
+                    # FIXME: Add handling for include directories.
+                    if 'INCLUDE_DIRECTORIES' in matched.group('name'):
+                        continue
+                    empty_lines_count = 0
+                    last_line = ''
+                    if matched.group('item'):
+                        msg = 'First listitem "%s" should be in a new line.' % matched.group('item').strip()
+                        self._handle_style_error(line_number, 'list/parentheses', 5, msg)
+            else:
+                matched = match('(?P<item>.+)?\)$', line)
+                if matched:
+                    last_line = None
+                    if matched.group('item'):
+                        msg = 'The parentheses after the last listitem "%s" should be in a new line.' % matched.group('item').strip()
+                        self._handle_style_error(line_number, 'list/parentheses', 5, msg)
+                elif line == '':
+                    empty_lines_count += 1
+                else:
+                    last_line_path = self._list_item_path(last_line)
+                    line_path = self._list_item_path(line)
+
+                    if line == last_line:
+                        msg = 'The item "%s" should be added only once to the list.' % line
+                        self._handle_style_error(line_number, 'list/duplicate', 5, msg)
+                    elif line_path < last_line_path or line_path == last_line_path and line < last_line:
+                        msg = 'Alphabetical sorting problem. "%s" should be before "%s".' % (line, last_line)
+                        self._handle_style_error(line_number, 'list/order', 5, msg)
+                    elif last_line != '':
+                        if line_path != last_line_path:
+                            if empty_lines_count != 1:
+                                msg = 'There should be exactly one empty line instead of %d between "%s" and "%s".' % (empty_lines_count, last_line, line)
+                                self._handle_style_error(line_number, 'list/emptyline', 5, msg)
+                        elif empty_lines_count != 0:
+                            msg = 'There should be no empty line between "%s" and "%s".' % (last_line, line)
+                            self._handle_style_error(line_number, 'list/emptyline', 5, msg)
+
+                    last_line = line
+                    empty_lines_count = 0
+
+    def _list_item_path(self, item):
+        token = item.split('/')
+        if len(token) < 2:
+            return ''
+        return '/'.join(token[:-1])
index 7b2cdaf..90cb77b 100644 (file)
@@ -70,6 +70,45 @@ class CMakeCheckerTest(unittest.TestCase):
             '\n',
             'function    ()\n',
             'endfunction()\n',
+            '\n',
+            'set(name a)\n',
+            'set(name a b c)\n',
+            'set(name a\n',
+            'b)\n',
+            'set(name',
+            'abc\n',
+            ')\n',
+            'list(APPEND name a)\n',
+            'list(APPEND name\n',
+            'a\n',
+            'a\n',
+            ')\n',
+            'list(APPEND name\n',
+            'b\n',
+            'a\n',
+            '\n',
+            'c/a.a\n',
+            '\n',
+            'c/b/a.a\n',
+            '\n',
+            'c/c.c\n',
+            '\n',
+            'c/b/a.a\n',
+            ')\n',
+            'list(REMOVE_ITEM name a)\n',
+            'list(REMOVE_ITEM name\n',
+            'a\n',
+            '\n',
+            'b\n',
+            ')\n',
+            'list(REMOVE_ITEM name\n',
+            'a/a.a\n',
+            'a/b.b\n',
+            'b/a.a\n',
+            '\n',
+            '\n',
+            'c/a.a\n',
+            ')\n',
             ]
         checker.check(lines)
 
@@ -87,4 +126,12 @@ class CMakeCheckerTest(unittest.TestCase):
             (15, 'whitespace/parentheses', 5, 'No space between command "macro" and its parentheses, should be "macro("'),
             (16, 'command/lowercase', 5, 'Use lowercase command "endmacro"'),
             (18, 'whitespace/parentheses', 5, 'No space between command "function" and its parentheses, should be "function("'),
+            (23, 'list/parentheses', 5, 'First listitem "a" should be in a new line.'),
+            (24, 'list/parentheses', 5, 'The parentheses after the last listitem "b" should be in a new line.'),
+            (31,  'list/duplicate', 5, 'The item "a" should be added only once to the list.'),
+            (35, 'list/order', 5, 'Alphabetical sorting problem. "a" should be before "b".'),
+            (41, 'list/order', 5, 'Alphabetical sorting problem. "c/c.c" should be before "c/b/a.a".'),
+            (49, 'list/emptyline', 5, 'There should be no empty line between "a" and "b".'),
+            (54, 'list/emptyline', 5, 'There should be exactly one empty line instead of 0 between "a/b.b" and "b/a.a".'),
+            (57, 'list/emptyline', 5, 'There should be exactly one empty line instead of 2 between "b/a.a" and "c/a.a".'),
             ])