Add JavaScript style checker and teach checker.py about .js files

https://bugs.webkit.org/show_bug.cgi?id=125049

Patch by Brian J. Burg <burg@cs.washington.edu> on 2013-12-02
Reviewed by Joseph Pecoraro.

Add a JavaScript file type, extension, and checker (JSChecker).
Use TextChecker for JavaScript tests, libraries, website resources,
etc. and use JSChecker for files within WebInspectorUI/UserInterface.

Amended tests for TextChecker to reflect the rule above.

* Scripts/webkitpy/style/checker.py:
(_all_categories): Add categories defined by JSChecker.
(FileType): Add file type for JS and re-number the enum.
(CheckerDispatcher._file_type): Detect .js files as JavaScript.
(CheckerDispatcher._create_checker):
Create a JSChecker or TextChecker depending on the file's path.

* Scripts/webkitpy/style/checker_unittest.py:
(CheckerDispatcherDispatchTest.assert_checker_js): Added.
(CheckerDispatcherDispatchTest.test_js_paths): Added.
(CheckerDispatcherDispatchTest.test_text_paths): Add new test paths
that end in .js but should be checked with TextChecker.
* Scripts/webkitpy/style/checkers/js.py: Added.
(JSChecker):
(JSChecker.__init__):
(JSChecker.check):
* Scripts/webkitpy/style/checkers/js_unittest.py: Added.
(JSTestCase):
(JSTestCase.assertNoError):
(JSTestCase.assertNoError.error_for_test):
(JSTestCase.assertError):
(JSTestCase.assertError.error_for_test):
(JSTestCase.test_no_error):
(JSTestCase.test_error):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@159969 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 37a9256b
2013-12-02 Brian J. Burg <burg@cs.washington.edu>
Add JavaScript style checker and teach checker.py about .js files
https://bugs.webkit.org/show_bug.cgi?id=125049
Reviewed by Joseph Pecoraro.
Add a JavaScript file type, extension, and checker (JSChecker).
Use TextChecker for JavaScript tests, libraries, website resources,
etc. and use JSChecker for files within WebInspectorUI/UserInterface.
Amended tests for TextChecker to reflect the rule above.
* Scripts/webkitpy/style/checker.py:
(_all_categories): Add categories defined by JSChecker.
(FileType): Add file type for JS and re-number the enum.
(CheckerDispatcher._file_type): Detect .js files as JavaScript.
(CheckerDispatcher._create_checker):
Create a JSChecker or TextChecker depending on the file's path.
* Scripts/webkitpy/style/checker_unittest.py:
(CheckerDispatcherDispatchTest.assert_checker_js): Added.
(CheckerDispatcherDispatchTest.test_js_paths): Added.
(CheckerDispatcherDispatchTest.test_text_paths): Add new test paths
that end in .js but should be checked with TextChecker.
* Scripts/webkitpy/style/checkers/js.py: Added.
(JSChecker):
(JSChecker.__init__):
(JSChecker.check):
* Scripts/webkitpy/style/checkers/js_unittest.py: Added.
(JSTestCase):
(JSTestCase.assertNoError):
(JSTestCase.assertNoError.error_for_test):
(JSTestCase.assertError):
(JSTestCase.assertError.error_for_test):
(JSTestCase.test_no_error):
(JSTestCase.test_error):
2013-12-02 Mark Hahnenberg <mhahnenberg@apple.com>
run-jsc-stress-tests always copies the VM
......
......@@ -41,6 +41,7 @@ from checkers.common import CarriageReturnChecker
from checkers.changelog import ChangeLogChecker
from checkers.cpp import CppChecker
from checkers.cmake import CMakeChecker
from checkers.js import JSChecker
from checkers.jsonchecker import JSONChecker
from checkers.png import PNGChecker
from checkers.python import PythonChecker
......@@ -263,6 +264,8 @@ _CPP_FILE_EXTENSIONS = [
'h',
]
_JS_FILE_EXTENSION = 'js'
_JSON_FILE_EXTENSION = 'json'
_PYTHON_FILE_EXTENSION = 'py'
......@@ -279,7 +282,6 @@ _TEXT_FILE_EXTENSIONS = [
'html',
'idl',
'in',
'js',
'mm',
'php',
'pl',
......@@ -350,6 +352,7 @@ def _all_categories():
"""Return the set of all categories used by check-webkit-style."""
# Take the union across all checkers.
categories = CommonCategories.union(CppChecker.categories)
categories = categories.union(JSChecker.categories)
categories = categories.union(JSONChecker.categories)
categories = categories.union(TestExpectationsChecker.categories)
categories = categories.union(ChangeLogChecker.categories)
......@@ -494,15 +497,15 @@ class FileType:
# Alphabetize remaining types
CHANGELOG = 1
CPP = 2
JSON = 3
PNG = 4
PYTHON = 5
TEXT = 6
WATCHLIST = 7
XML = 8
XCODEPROJ = 9
CMAKE = 10
JS = 3
JSON = 4
PNG = 5
PYTHON = 6
TEXT = 7
WATCHLIST = 8
XML = 9
XCODEPROJ = 10
CMAKE = 11
class CheckerDispatcher(object):
......@@ -566,6 +569,8 @@ class CheckerDispatcher(object):
# reading from stdin, cpp_style tests should not rely on
# the extension.
return FileType.CPP
elif file_extension == _JS_FILE_EXTENSION:
return FileType.JS
elif file_extension == _JSON_FILE_EXTENSION:
return FileType.JSON
elif file_extension == _PYTHON_FILE_EXTENSION:
......@@ -602,6 +607,12 @@ class CheckerDispatcher(object):
file_extension = self._file_extension(file_path)
checker = CppChecker(file_path, file_extension,
handle_style_error, min_confidence)
elif file_type == FileType.JS:
# Do not attempt to check non-Inspector or 3rd-party JavaScript files as JS.
if os.path.join('WebInspectorUI', 'UserInterface') in file_path and (not 'External' in file_path):
checker = JSChecker(file_path, handle_style_error)
else:
checker = TextChecker(file_path, handle_style_error)
elif file_type == FileType.JSON:
checker = JSONChecker(file_path, handle_style_error)
elif file_type == FileType.PYTHON:
......
......@@ -52,6 +52,7 @@ from checker import StyleProcessor
from checker import StyleProcessorConfiguration
from checkers.changelog import ChangeLogChecker
from checkers.cpp import CppChecker
from checkers.js import JSChecker
from checkers.jsonchecker import JSONChecker
from checkers.python import PythonChecker
from checkers.text import TextChecker
......@@ -393,6 +394,10 @@ class CheckerDispatcherDispatchTest(unittest.TestCase):
"""Assert that the dispatched checker is a CppChecker."""
self.assert_checker(file_path, CppChecker)
def assert_checker_js(self, file_path):
"""Assert that the dispatched checker is a JSChecker."""
self.assert_checker(file_path, JSChecker)
def assert_checker_json(self, file_path):
"""Assert that the dispatched checker is a JSONChecker."""
self.assert_checker(file_path, JSONChecker)
......@@ -459,6 +464,24 @@ class CheckerDispatcherDispatchTest(unittest.TestCase):
self.assertEqual(checker.file_extension, file_extension)
self.assertEqual(checker.file_path, file_path)
def test_js_paths(self):
"""Test paths that should be checked as JavaScript."""
paths = [
"Source/WebInspectorUI/UserInterface/dummy.js",
]
for path in paths:
self.assert_checker_js(path)
# Check checker attributes on a typical input.
file_base = "foo"
file_extension = "css"
file_path = file_base + "." + file_extension
self.assert_checker_text(file_path)
checker = self.dispatch(file_path)
self.assertEqual(checker.handle_style_error,
self.mock_handle_style_error)
def test_json_paths(self):
"""Test paths that should be checked as JSON."""
paths = [
......@@ -512,7 +535,6 @@ class CheckerDispatcherDispatchTest(unittest.TestCase):
"foo.html",
"foo.idl",
"foo.in",
"foo.js",
"foo.mm",
"foo.php",
"foo.pl",
......@@ -525,7 +547,9 @@ class CheckerDispatcherDispatchTest(unittest.TestCase):
"foo.wm",
"foo.xhtml",
"foo.y",
os.path.join("Source", "WebCore", "inspector", "front-end", "inspector.js"),
"Source/WebInspectorUI/External/codemirror.js",
"LayoutTests/fast/foo.js",
"Websites/webkit.org/foo.js",
os.path.join("Tools", "Scripts", "check-webkit-style"),
]
......
# Copyright (C) 2013 University of Washington. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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 JavaScript files"""
from common import TabChecker
class JSChecker(object):
"""Processes JavaScript lines for checking style."""
# FIXME: plug in a JavaScript parser to find syntax errors.
categories = set(('js/syntax',))
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)
# Copyright (C) 2009 Google Inc. All rights reserved.
# Copyright (C) 2013 University of Washington. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# 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.
"""Unit test for js.py."""
import unittest2 as unittest
from js import JSChecker
class JSTestCase(unittest.TestCase):
"""TestCase for js.py"""
def assertNoError(self, lines):
"""Asserts that the specified lines has no errors."""
self.had_error = False
def error_for_test(line_number, category, confidence, message):
"""Records if an error occurs."""
self.had_error = True
checker = JSChecker('', error_for_test)
checker.check(lines)
self.assertFalse(self.had_error, '%s should not have any errors.' % lines)
def assertError(self, lines, expected_line_number):
"""Asserts that the specified lines has an error."""
self.had_error = False
def error_for_test(line_number, category, confidence, message):
"""Checks if the expected error occurs."""
self.assertEqual(expected_line_number, line_number)
self.assertEqual('whitespace/tab', category)
self.had_error = True
checker = JSChecker('', error_for_test)
checker.check(lines)
self.assertTrue(self.had_error, '%s should have an error [whitespace/tab].' % lines)
def test_no_error(self):
"""Tests for no error cases."""
self.assertNoError([''])
self.assertNoError(['abc def', 'ggg'])
def test_error(self):
"""Tests for error cases."""
self.assertError(['\tvar foo = window;\n'], 1)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment