Title: [137057] trunk/Tools
Revision
137057
Author
[email protected]
Date
2012-12-08 23:46:55 -0800 (Sat, 08 Dec 2012)

Log Message

[CMake] Add CMake style checker
https://bugs.webkit.org/show_bug.cgi?id=104240

Patch by Halton Huo <[email protected]> on 2012-12-08
Reviewed by Eric Seidel.

The CMake style checker is followed by existing style checkers like cpp, python.
Unit test is added as well.

* Scripts/webkitpy/style/checker.py: Use CMakeChecker CMAKE type files(.cmake or CMakeLists.txt)
(FileType):
(CheckerDispatcher._file_type):
(CheckerDispatcher._create_checker):
* Scripts/webkitpy/style/checkers/cmake.py: Added.
(CMakeChecker):
(CMakeChecker.__init__):
(CMakeChecker.check):
(CMakeChecker._process_line):
(CMakeChecker._check_trailing_whitespace):
(CMakeChecker._check_no_space_cmds):
(CMakeChecker._check_one_space_cmds):
(CMakeChecker._check_non_lowercase_cmd):
(CMakeChecker._check_indent):
* Scripts/webkitpy/style/checkers/cmake_unittest.py: Added.
(CMakeCheckerTest):
(CMakeCheckerTest.test_init):
(CMakeCheckerTest.test_init._mock_handle_style_error):
(CMakeCheckerTest.test_check):
(CMakeCheckerTest.test_check._mock_handle_style_error):

Modified Paths

Added Paths

Diff

Modified: trunk/Tools/ChangeLog (137056 => 137057)


--- trunk/Tools/ChangeLog	2012-12-09 05:48:26 UTC (rev 137056)
+++ trunk/Tools/ChangeLog	2012-12-09 07:46:55 UTC (rev 137057)
@@ -1,3 +1,34 @@
+2012-12-08  Halton Huo  <[email protected]>
+
+        [CMake] Add CMake style checker
+        https://bugs.webkit.org/show_bug.cgi?id=104240
+
+        Reviewed by Eric Seidel.
+
+        The CMake style checker is followed by existing style checkers like cpp, python.
+        Unit test is added as well.
+
+        * Scripts/webkitpy/style/checker.py: Use CMakeChecker CMAKE type files(.cmake or CMakeLists.txt)
+        (FileType):
+        (CheckerDispatcher._file_type):
+        (CheckerDispatcher._create_checker):
+        * Scripts/webkitpy/style/checkers/cmake.py: Added.
+        (CMakeChecker):
+        (CMakeChecker.__init__): 
+        (CMakeChecker.check):
+        (CMakeChecker._process_line):
+        (CMakeChecker._check_trailing_whitespace):
+        (CMakeChecker._check_no_space_cmds):
+        (CMakeChecker._check_one_space_cmds):
+        (CMakeChecker._check_non_lowercase_cmd):
+        (CMakeChecker._check_indent):
+        * Scripts/webkitpy/style/checkers/cmake_unittest.py: Added.
+        (CMakeCheckerTest):
+        (CMakeCheckerTest.test_init):
+        (CMakeCheckerTest.test_init._mock_handle_style_error):
+        (CMakeCheckerTest.test_check):
+        (CMakeCheckerTest.test_check._mock_handle_style_error):
+
 2012-12-08  Kondapally Kalyan  <[email protected]>
 
         [EFL] Enable WebGL by default.

Modified: trunk/Tools/Scripts/webkitpy/style/checker.py (137056 => 137057)


--- trunk/Tools/Scripts/webkitpy/style/checker.py	2012-12-09 05:48:26 UTC (rev 137056)
+++ trunk/Tools/Scripts/webkitpy/style/checker.py	2012-12-09 07:46:55 UTC (rev 137057)
@@ -39,6 +39,7 @@
 from checkers.common import CarriageReturnChecker
 from checkers.changelog import ChangeLogChecker
 from checkers.cpp import CppChecker
+from checkers.cmake import CMakeChecker
 from checkers.jsonchecker import JSONChecker
 from checkers.png import PNGChecker
 from checkers.python import PythonChecker
@@ -306,6 +307,8 @@
 
 _PNG_FILE_EXTENSION = 'png'
 
+_CMAKE_FILE_EXTENSION = 'cmake'
+
 # Files to skip that are less obvious.
 #
 # Some files should be skipped when checking style. For example,
@@ -496,6 +499,7 @@
     WATCHLIST = 7
     XML = 8
     XCODEPROJ = 9
+    CMAKE = 10
 
 
 class CheckerDispatcher(object):
@@ -574,6 +578,8 @@
             return FileType.XCODEPROJ
         elif file_extension == _PNG_FILE_EXTENSION:
             return FileType.PNG
+        elif ((file_extension == _CMAKE_FILE_EXTENSION) or os.path.basename(file_path) == 'CMakeLists.txt'):
+            return FileType.CMAKE
         elif ((not file_extension and os.path.join("Tools", "Scripts") in file_path) or
               file_extension in _TEXT_FILE_EXTENSIONS or os.path.basename(file_path) == 'TestExpectations'):
             return FileType.TEXT
@@ -604,6 +610,8 @@
             checker = XcodeProjectFileChecker(file_path, handle_style_error)
         elif file_type == FileType.PNG:
             checker = PNGChecker(file_path, handle_style_error)
+        elif file_type == FileType.CMAKE:
+            checker = CMakeChecker(file_path, handle_style_error)
         elif file_type == FileType.TEXT:
             basename = os.path.basename(file_path)
             if basename == 'TestExpectations':

Added: trunk/Tools/Scripts/webkitpy/style/checkers/cmake.py (0 => 137057)


--- trunk/Tools/Scripts/webkitpy/style/checkers/cmake.py	                        (rev 0)
+++ trunk/Tools/Scripts/webkitpy/style/checkers/cmake.py	2012-12-09 07:46:55 UTC (rev 137057)
@@ -0,0 +1,150 @@
+# Copyright (C) 2012 Intel Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Supports checking WebKit style in cmake files.(.cmake, CMakeLists.txt)"""
+
+import re
+
+from common import TabChecker
+
+
+class CMakeChecker(object):
+
+    """Processes CMake lines for checking style."""
+
+    # NO_SPACE_CMDS list are based on commands section of CMake document.
+    # Now it is generated from
+    # http://www.cmake.org/cmake/help/v2.8.10/cmake.html#section_Commands.
+    # Some commands are from default CMake modules such as pkg_check_modules.
+    # Please keep list in alphabet order.
+    #
+    # For commands in this list, spaces should not be added it and its
+    # parentheses. For eg, message("testing"), not message ("testing")
+    #
+    # The conditional commands like if, else, endif, foreach, endforeach,
+    # while, endwhile and break are listed in ONE_SPACE_CMDS
+    NO_SPACE_CMDS = [
+        'add_custom_command', 'add_custom_target', 'add_definitions',
+        'add_dependencies', 'add_executable', 'add_library',
+        'add_subdirectory', 'add_test', 'aux_source_directory',
+        'build_command',
+        'cmake_minimum_required', 'cmake_policy', 'configure_file',
+        'create_test_sourcelist',
+        'define_property',
+        'enable_language', 'enable_testing', 'endfunction', 'endmacro',
+        'execute_process', 'export',
+        'file', 'find_file', 'find_library', 'find_package', 'find_path',
+        'find_program', 'fltk_wrap_ui', 'function',
+        'get_cmake_property', 'get_directory_property',
+        'get_filename_component', 'get_property', 'get_source_file_property',
+        'get_target_property', 'get_test_property',
+        'include', 'include_directories', 'include_external_msproject',
+        'include_regular_expression', 'install',
+        'link_directories', 'list', 'load_cache', 'load_command',
+        'macro', 'mark_as_advanced', 'math', 'message',
+        'option',
+        #From FindPkgConfig.cmake
+        'pkg_check_modules',
+        'project',
+        'qt_wrap_cpp', 'qt_wrap_ui',
+        'remove_definitions', 'return',
+        'separate_arguments', 'set', 'set_directory_properties', 'set_property',
+        'set_source_files_properties', 'set_target_properties',
+        'set_tests_properties', 'site_name', 'source_group', 'string',
+        'target_link_libraries', 'try_compile', 'try_run',
+        'unset',
+        'variable_watch',
+    ]
+
+    # CMake conditional commands, require one space between command and
+    # its parentheses, such as "if (", "foreach (", etc.
+    _ONE_SPACE_CMDS_ = [
+        'if', 'else', 'elseif', 'endif',
+        'foreach', 'endforeach',
+        'while', 'endwhile',
+        'break',
+    ]
+
+    def __init__(self, file_path, handle_style_error):
+        self._handle_style_error = handle_style_error
+        self._tab_checker = TabChecker(file_path, handle_style_error)
+
+    def check(self, lines):
+        self._tab_checker.check(lines)
+        self._num_lines = len(lines)
+        for l in xrange(self._num_lines):
+            self._process_line(l + 1, lines[l])
+
+    def _process_line(self, line_number, line_content):
+        if re.match('(^|\ +)#', line_content):
+            # ignore comment line
+            return
+        l = line_content.expandtabs(4)
+        # check command like message( "testing")
+        if re.search('\(\ +', l):
+            self._handle_style_error(line_number, 'whitespace/parentheses', 5,
+                                     'No space after "("')
+        # check command like message("testing" )
+        if re.search('\ +\)', l) and not re.search('^\ +\)$', l):
+            self._handle_style_error(line_number, 'whitespace/parentheses', 5,
+                                     'No space before ")"')
+        self._check_trailing_whitespace(line_number, l)
+        self._check_no_space_cmds(line_number, l)
+        self._check_one_space_cmds(line_number, l)
+        self._check_indent(line_number, line_content)
+
+    def _check_trailing_whitespace(self, line_number, line_content):
+        line_content = line_content.rstrip('\n')    # chr(10), newline
+        line_content = line_content.rstrip('\r')    # chr(13), carriage return
+        line_content = line_content.rstrip('\x0c')  # chr(12), form feed, ^L
+        stripped = line_content.rstrip()
+        if line_content != stripped:
+            self._handle_style_error(line_number, 'whitespace/trailing', 5,
+                                     'No trailing spaces')
+
+    def _check_no_space_cmds(self, line_number, line_content):
+        # check command like "SET    (" or "Set("
+        for t in self.NO_SPACE_CMDS:
+            self._check_non_lowercase_cmd(line_number, line_content, t)
+            if re.search('(^|\ +)' + t.lower() + '\ +\(', line_content):
+                msg = 'No space between command "' + t.lower() + '" and its parentheses, should be "' + t + '("'
+                self._handle_style_error(line_number, 'whitespace/parentheses', 5, msg)
+
+    def _check_one_space_cmds(self, line_number, line_content):
+        # check command like "IF (" or "if(" or "if   (" or "If ()"
+        for t in self.ONE_SPACE_CMDS:
+            self._check_non_lowercase_cmd(line_number, line_content, t)
+            if re.search('(^|\ +)' + t.lower() + '(\(|\ \ +\()', line_content):
+                msg = 'One space between command "' + t.lower() + '" and its parentheses, should be "' + t + ' ("'
+                self._handle_style_error(line_number, 'whitespace/parentheses', 5, msg)
+
+    def _check_non_lowercase_cmd(self, line_number, line_content, cmd):
+        if re.search('(^|\ +)' + cmd + '\ *\(', line_content, flags=re.IGNORECASE) and \
+           (not re.search('(^|\ +)' + cmd.lower() + '\ *\(', line_content)):
+            msg = 'Use lowercase command "' + cmd.lower() + '"'
+            self._handle_style_error(line_number, 'command/lowercase', 5, msg)
+
+    def _check_indent(self, line_number, line_content):
+        #TODO (halton): add indent checking
+        pass

Added: trunk/Tools/Scripts/webkitpy/style/checkers/cmake_unittest.py (0 => 137057)


--- trunk/Tools/Scripts/webkitpy/style/checkers/cmake_unittest.py	                        (rev 0)
+++ trunk/Tools/Scripts/webkitpy/style/checkers/cmake_unittest.py	2012-12-09 07:46:55 UTC (rev 137057)
@@ -0,0 +1,90 @@
+# Copyright (C) 2012 Intel Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for cmake.py."""
+
+import unittest
+
+from cmake import CMakeChecker
+
+
+class CMakeCheckerTest(unittest.TestCase):
+
+    """Tests CMakeChecker class."""
+
+    def test_init(self):
+        """Test __init__() method."""
+        def _mock_handle_style_error(self):
+            pass
+
+        checker = CMakeChecker("foo.cmake", _mock_handle_style_error)
+        self.assertEqual(checker._handle_style_error, _mock_handle_style_error)
+
+    def test_check(self):
+        """Test check() method."""
+        errors = []
+
+        def _mock_handle_style_error(line_number, category, confidence,
+                                     message):
+            error = (line_number, category, confidence, message)
+            errors.append(error)
+
+        checker = CMakeChecker("foo.cmake", _mock_handle_style_error)
+
+        lines = [
+            '# This file is sample input for cmake_unittest.py and includes below problems:\n',
+            'IF ()',
+            '\tmessage("Error line with Tab")\n',
+            '    message("Error line with endding spaces")    \n',
+            '    message( "Error line with space after (")\n',
+            '    message("Error line with space before (" )\n',
+            '    MESSAGE("Error line with upper case non-condtional command")\n',
+            '    MESSage("Error line with upper case non-condtional command")\n',
+            '    message("correct message line")\n',
+            'ENDif ()\n',
+            '\n',
+            'if()\n',
+            'endif ()\n',
+            '\n',
+            'macro ()\n',
+            'ENDMacro()\n',
+            '\n',
+            'function    ()\n',
+            'endfunction()\n',
+            ]
+        checker.check(lines)
+
+        self.maxDiff = None
+        self.assertEqual(errors, [
+            (3, 'whitespace/tab', 5, 'Line contains tab character.'),
+            (2, 'command/lowercase', 5, 'Use lowercase command "if"'),
+            (4, 'whitespace/trailing', 5, 'No trailing spaces'),
+            (5, 'whitespace/parentheses', 5, 'No space after "("'),
+            (6, 'whitespace/parentheses', 5, 'No space before ")"'),
+            (7, 'command/lowercase', 5, 'Use lowercase command "message"'),
+            (8, 'command/lowercase', 5, 'Use lowercase command "message"'),
+            (10, 'command/lowercase', 5, 'Use lowercase command "endif"'),
+            (12, 'whitespace/parentheses', 5, 'One space between command "if" and its parentheses, should be "if ("'),
+            (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("'),
+            ])
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to