Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: sky/tools/webkitpy/style/checker.py

Issue 675343003: Prune a bunch of webkitpy. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/tools/webkitpy/style/__init__.py ('k') | sky/tools/webkitpy/style/checker_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (C) 2009 Google Inc. All rights reserved.
2 # Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
3 # Copyright (C) 2010 ProFUSION embedded systems
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 """Front end of some style-checker modules."""
32
33 import logging
34 import os.path
35 import re
36 import sys
37
38 from checkers.common import categories as CommonCategories
39 from checkers.common import CarriageReturnChecker
40 from checkers.cpp import CppChecker
41 from checkers.jsonchecker import JSONChecker
42 from checkers.png import PNGChecker
43 from checkers.python import PythonChecker
44 from checkers.test_expectations import TestExpectationsChecker
45 from checkers.text import TextChecker
46 from checkers.xcodeproj import XcodeProjectFileChecker
47 from checkers.xml import XMLChecker
48 from error_handlers import DefaultStyleErrorHandler
49 from filter import FilterConfiguration
50 from optparser import ArgumentParser
51 from optparser import DefaultCommandOptionValues
52 from webkitpy.common.system.logutils import configure_logging as _configure_logg ing
53
54
55 _log = logging.getLogger(__name__)
56
57
58 # These are default option values for the command-line option parser.
59 _DEFAULT_MIN_CONFIDENCE = 1
60 _DEFAULT_OUTPUT_FORMAT = 'emacs'
61
62
63 # FIXME: For style categories we will never want to have, remove them.
64 # For categories for which we want to have similar functionality,
65 # modify the implementation and enable them.
66 #
67 # Throughout this module, we use "filter rule" rather than "filter"
68 # for an individual boolean filter flag like "+foo". This allows us to
69 # reserve "filter" for what one gets by collectively applying all of
70 # the filter rules.
71 #
72 # The base filter rules are the filter rules that begin the list of
73 # filter rules used to check style. For example, these rules precede
74 # any user-specified filter rules. Since by default all categories are
75 # checked, this list should normally include only rules that begin
76 # with a "-" sign.
77 _BASE_FILTER_RULES = [
78 '-build/endif_comment',
79 '-build/include_what_you_use', # <string> for std::string
80 '-build/storage_class', # const static
81 '-legal/copyright',
82 '-readability/multiline_comment',
83 '-readability/braces', # int foo() {};
84 '-readability/fn_size',
85 '-readability/casting',
86 '-readability/function',
87 '-runtime/arrays', # variable length array
88 '-runtime/casting',
89 '-runtime/sizeof',
90 '-runtime/explicit', # explicit
91 '-runtime/virtual', # virtual dtor
92 '-runtime/printf',
93 '-runtime/threadsafe_fn',
94 '-runtime/rtti',
95 '-whitespace/blank_line',
96 '-whitespace/end_of_line',
97 # List Python pep8 categories last.
98 #
99 # Because much of WebKit's Python code base does not abide by the
100 # PEP8 79 character limit, we ignore the 79-character-limit category
101 # pep8/E501 for now.
102 #
103 # FIXME: Consider bringing WebKit's Python code base into conformance
104 # with the 79 character limit, or some higher limit that is
105 # agreeable to the WebKit project.
106 '-pep8/E501',
107
108 # FIXME: Move the pylint rules from the pylintrc to here. This will
109 # also require us to re-work lint-webkitpy to produce the equivalent output.
110 ]
111
112
113 # The path-specific filter rules.
114 #
115 # This list is order sensitive. Only the first path substring match
116 # is used. See the FilterConfiguration documentation in filter.py
117 # for more information on this list.
118 #
119 # Each string appearing in this nested list should have at least
120 # one associated unit test assertion. These assertions are located,
121 # for example, in the test_path_rules_specifier() unit test method of
122 # checker_unittest.py.
123 _PATH_RULES_SPECIFIER = [
124 # Files in these directories are consumers of the WebKit
125 # API and therefore do not follow the same header including
126 # discipline as WebCore.
127
128 ([# There is no clean way to avoid "yy_*" names used by flex.
129 "Source/core/css/CSSParser-in.cpp"],
130 ["-readability/naming"]),
131
132 # For third-party Python code, keep only the following checks--
133 #
134 # No tabs: to avoid having to set the SVN allow-tabs property.
135 # No trailing white space: since this is easy to correct.
136 # No carriage-return line endings: since this is easy to correct.
137 #
138 (["webkitpy/thirdparty/"],
139 ["-",
140 "+pep8/W191", # Tabs
141 "+pep8/W291", # Trailing white space
142 "+whitespace/carriage_return"]),
143
144 ([# Jinja templates: files have .cpp or .h extensions, but contain
145 # template code, which can't be handled, so disable tests.
146 "Source/bindings/templates",
147 "Source/build/scripts/templates"],
148 ["-"]),
149
150 ([# IDL compiler reference output
151 # Conforming to style significantly increases the complexity of the code
152 # generator and decreases *its* readability, which is of more concern
153 # than style of the machine-generated code itself.
154 "Source/bindings/tests/results"],
155 ["-"]),
156 ]
157
158
159 _CPP_FILE_EXTENSIONS = [
160 'c',
161 'cpp',
162 'h',
163 ]
164
165 _JSON_FILE_EXTENSION = 'json'
166
167 _PYTHON_FILE_EXTENSION = 'py'
168
169 _TEXT_FILE_EXTENSIONS = [
170 'cc',
171 'cgi',
172 'css',
173 'gyp',
174 'gypi',
175 'html',
176 'idl',
177 'in',
178 'js',
179 'mm',
180 'php',
181 'pl',
182 'pm',
183 'rb',
184 'sh',
185 'txt',
186 'xhtml',
187 'y',
188 ]
189
190 _XCODEPROJ_FILE_EXTENSION = 'pbxproj'
191
192 _XML_FILE_EXTENSIONS = [
193 'vcproj',
194 'vsprops',
195 ]
196
197 _PNG_FILE_EXTENSION = 'png'
198
199 # Files to skip that are less obvious.
200 #
201 # Some files should be skipped when checking style. For example,
202 # WebKit maintains some files in Mozilla style on purpose to ease
203 # future merges.
204 _SKIPPED_FILES_WITH_WARNING = [
205 "Source/WebKit/gtk/tests/",
206 # All WebKit*.h files in Source/WebKit2/UIProcess/API/gtk,
207 # except those ending in ...Private.h are GTK+ API headers,
208 # which differ greatly from WebKit coding style.
209 re.compile(r'Source/WebKit2/UIProcess/API/gtk/WebKit(?!.*Private\.h).*\.h$') ,
210 re.compile(r'Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKit(?!.*Pri vate\.h).*\.h$'),
211 'Source/WebKit2/UIProcess/API/gtk/webkit2.h',
212 'Source/WebKit2/WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h']
213
214 # Files to skip that are more common or obvious.
215 #
216 # This list should be in addition to files with FileType.NONE. Files
217 # with FileType.NONE are automatically skipped without warning.
218 _SKIPPED_FILES_WITHOUT_WARNING = [
219 "tests" + os.path.sep,
220 "Source/ThirdParty/leveldb" + os.path.sep,
221 # Prevents this being recognized as a text file.
222 "Source/WebCore/GNUmakefile.features.am.in",
223 ]
224
225 # Extensions of files which are allowed to contain carriage returns.
226 _CARRIAGE_RETURN_ALLOWED_FILE_EXTENSIONS = [
227 'png',
228 'vcproj',
229 'vsprops',
230 ]
231
232 # The maximum number of errors to report per file, per category.
233 # If a category is not a key, then it has no maximum.
234 _MAX_REPORTS_PER_CATEGORY = {
235 "whitespace/carriage_return": 1
236 }
237
238
239 def _all_categories():
240 """Return the set of all categories used by check-webkit-style."""
241 # Take the union across all checkers.
242 categories = CommonCategories.union(CppChecker.categories)
243 categories = categories.union(JSONChecker.categories)
244 categories = categories.union(TestExpectationsChecker.categories)
245 categories = categories.union(PNGChecker.categories)
246
247 # FIXME: Consider adding all of the pep8 categories. Since they
248 # are not too meaningful for documentation purposes, for
249 # now we add only the categories needed for the unit tests
250 # (which validate the consistency of the configuration
251 # settings against the known categories, etc).
252 categories = categories.union(["pep8/W191", "pep8/W291", "pep8/E501"])
253
254 return categories
255
256
257 def _check_webkit_style_defaults():
258 """Return the default command-line options for check-webkit-style."""
259 return DefaultCommandOptionValues(min_confidence=_DEFAULT_MIN_CONFIDENCE,
260 output_format=_DEFAULT_OUTPUT_FORMAT)
261
262
263 # This function assists in optparser not having to import from checker.
264 def check_webkit_style_parser():
265 all_categories = _all_categories()
266 default_options = _check_webkit_style_defaults()
267 return ArgumentParser(all_categories=all_categories,
268 base_filter_rules=_BASE_FILTER_RULES,
269 default_options=default_options)
270
271
272 def check_webkit_style_configuration(options):
273 """Return a StyleProcessorConfiguration instance for check-webkit-style.
274
275 Args:
276 options: A CommandOptionValues instance.
277
278 """
279 filter_configuration = FilterConfiguration(
280 base_rules=_BASE_FILTER_RULES,
281 path_specific=_PATH_RULES_SPECIFIER,
282 user_rules=options.filter_rules)
283
284 return StyleProcessorConfiguration(filter_configuration=filter_configuration ,
285 max_reports_per_category=_MAX_REPORTS_PER_CATEGORY,
286 min_confidence=options.min_confidence,
287 output_format=options.output_format,
288 stderr_write=sys.stderr.write)
289
290
291 def _create_log_handlers(stream):
292 """Create and return a default list of logging.Handler instances.
293
294 Format WARNING messages and above to display the logging level, and
295 messages strictly below WARNING not to display it.
296
297 Args:
298 stream: See the configure_logging() docstring.
299
300 """
301 # Handles logging.WARNING and above.
302 error_handler = logging.StreamHandler(stream)
303 error_handler.setLevel(logging.WARNING)
304 formatter = logging.Formatter("%(levelname)s: %(message)s")
305 error_handler.setFormatter(formatter)
306
307 # Create a logging.Filter instance that only accepts messages
308 # below WARNING (i.e. filters out anything WARNING or above).
309 non_error_filter = logging.Filter()
310 # The filter method accepts a logging.LogRecord instance.
311 non_error_filter.filter = lambda record: record.levelno < logging.WARNING
312
313 non_error_handler = logging.StreamHandler(stream)
314 non_error_handler.addFilter(non_error_filter)
315 formatter = logging.Formatter("%(message)s")
316 non_error_handler.setFormatter(formatter)
317
318 return [error_handler, non_error_handler]
319
320
321 def _create_debug_log_handlers(stream):
322 """Create and return a list of logging.Handler instances for debugging.
323
324 Args:
325 stream: See the configure_logging() docstring.
326
327 """
328 handler = logging.StreamHandler(stream)
329 formatter = logging.Formatter("%(name)s: %(levelname)-8s %(message)s")
330 handler.setFormatter(formatter)
331
332 return [handler]
333
334
335 def configure_logging(stream, logger=None, is_verbose=False):
336 """Configure logging, and return the list of handlers added.
337
338 Returns:
339 A list of references to the logging handlers added to the root
340 logger. This allows the caller to later remove the handlers
341 using logger.removeHandler. This is useful primarily during unit
342 testing where the caller may want to configure logging temporarily
343 and then undo the configuring.
344
345 Args:
346 stream: A file-like object to which to log. The stream must
347 define an "encoding" data attribute, or else logging
348 raises an error.
349 logger: A logging.logger instance to configure. This parameter
350 should be used only in unit tests. Defaults to the
351 root logger.
352 is_verbose: A boolean value of whether logging should be verbose.
353
354 """
355 # If the stream does not define an "encoding" data attribute, the
356 # logging module can throw an error like the following:
357 #
358 # Traceback (most recent call last):
359 # File "/System/Library/Frameworks/Python.framework/Versions/2.6/...
360 # lib/python2.6/logging/__init__.py", line 761, in emit
361 # self.stream.write(fs % msg.encode(self.stream.encoding))
362 # LookupError: unknown encoding: unknown
363 if logger is None:
364 logger = logging.getLogger()
365
366 if is_verbose:
367 logging_level = logging.DEBUG
368 handlers = _create_debug_log_handlers(stream)
369 else:
370 logging_level = logging.INFO
371 handlers = _create_log_handlers(stream)
372
373 handlers = _configure_logging(logging_level=logging_level, logger=logger,
374 handlers=handlers)
375
376 return handlers
377
378
379 # Enum-like idiom
380 class FileType:
381
382 NONE = 0 # FileType.NONE evaluates to False.
383 # Alphabetize remaining types
384 # CHANGELOG = 1
385 CPP = 2
386 JSON = 3
387 PNG = 4
388 PYTHON = 5
389 TEXT = 6
390 # WATCHLIST = 7
391 XML = 8
392 XCODEPROJ = 9
393
394
395 class CheckerDispatcher(object):
396
397 """Supports determining whether and how to check style, based on path."""
398
399 def _file_extension(self, file_path):
400 """Return the file extension without the leading dot."""
401 return os.path.splitext(file_path)[1].lstrip(".")
402
403 def _should_skip_file_path(self, file_path, skip_array_entry):
404 match = re.search("\s*png$", file_path)
405 if match:
406 return False
407 if isinstance(skip_array_entry, str):
408 if file_path.find(skip_array_entry) >= 0:
409 return True
410 elif skip_array_entry.match(file_path):
411 return True
412 return False
413
414 def should_skip_with_warning(self, file_path):
415 """Return whether the given file should be skipped with a warning."""
416 for skipped_file in _SKIPPED_FILES_WITH_WARNING:
417 if self._should_skip_file_path(file_path, skipped_file):
418 return True
419 return False
420
421 def should_skip_without_warning(self, file_path):
422 """Return whether the given file should be skipped without a warning."""
423 if not self._file_type(file_path): # FileType.NONE.
424 return True
425 # Since "tests" is in _SKIPPED_FILES_WITHOUT_WARNING, make
426 # an exception to prevent files like 'TestExpectations' from being skipp ed.
427 #
428 # FIXME: Figure out a good way to avoid having to add special logic
429 # for this special case.
430 basename = os.path.basename(file_path)
431 if basename == 'TestExpectations':
432 return False
433 for skipped_file in _SKIPPED_FILES_WITHOUT_WARNING:
434 if self._should_skip_file_path(file_path, skipped_file):
435 return True
436 return False
437
438 def should_check_and_strip_carriage_returns(self, file_path):
439 return self._file_extension(file_path) not in _CARRIAGE_RETURN_ALLOWED_F ILE_EXTENSIONS
440
441 def _file_type(self, file_path):
442 """Return the file type corresponding to the given file."""
443 file_extension = self._file_extension(file_path)
444
445 if (file_extension in _CPP_FILE_EXTENSIONS) or (file_path == '-'):
446 # FIXME: Do something about the comment below and the issue it
447 # raises since cpp_style already relies on the extension.
448 #
449 # Treat stdin as C++. Since the extension is unknown when
450 # reading from stdin, cpp_style tests should not rely on
451 # the extension.
452 return FileType.CPP
453 elif file_extension == _JSON_FILE_EXTENSION:
454 return FileType.JSON
455 elif file_extension == _PYTHON_FILE_EXTENSION:
456 return FileType.PYTHON
457 elif file_extension in _XML_FILE_EXTENSIONS:
458 return FileType.XML
459 elif file_extension == _XCODEPROJ_FILE_EXTENSION:
460 return FileType.XCODEPROJ
461 elif file_extension == _PNG_FILE_EXTENSION:
462 return FileType.PNG
463 elif ((not file_extension and os.path.join("Tools", "Scripts") in file_p ath) or
464 file_extension in _TEXT_FILE_EXTENSIONS or os.path.basename(file_p ath) == 'TestExpectations'):
465 return FileType.TEXT
466 else:
467 return FileType.NONE
468
469 def _create_checker(self, file_type, file_path, handle_style_error,
470 min_confidence):
471 """Instantiate and return a style checker based on file type."""
472 if file_type == FileType.NONE:
473 checker = None
474 elif file_type == FileType.CPP:
475 file_extension = self._file_extension(file_path)
476 checker = CppChecker(file_path, file_extension,
477 handle_style_error, min_confidence)
478 elif file_type == FileType.JSON:
479 checker = JSONChecker(file_path, handle_style_error)
480 elif file_type == FileType.PYTHON:
481 checker = PythonChecker(file_path, handle_style_error)
482 elif file_type == FileType.XML:
483 checker = XMLChecker(file_path, handle_style_error)
484 elif file_type == FileType.XCODEPROJ:
485 checker = XcodeProjectFileChecker(file_path, handle_style_error)
486 elif file_type == FileType.PNG:
487 checker = PNGChecker(file_path, handle_style_error)
488 elif file_type == FileType.TEXT:
489 basename = os.path.basename(file_path)
490 if basename == 'TestExpectations':
491 checker = TestExpectationsChecker(file_path, handle_style_error)
492 else:
493 checker = TextChecker(file_path, handle_style_error)
494 else:
495 raise ValueError('Invalid file type "%(file_type)s": the only valid file types '
496 "are %(NONE)s, %(CPP)s, and %(TEXT)s."
497 % {"file_type": file_type,
498 "NONE": FileType.NONE,
499 "CPP": FileType.CPP,
500 "TEXT": FileType.TEXT})
501
502 return checker
503
504 def dispatch(self, file_path, handle_style_error, min_confidence):
505 """Instantiate and return a style checker based on file path."""
506 file_type = self._file_type(file_path)
507
508 checker = self._create_checker(file_type,
509 file_path,
510 handle_style_error,
511 min_confidence)
512 return checker
513
514
515 # FIXME: Remove the stderr_write attribute from this class and replace
516 # its use with calls to a logging module logger.
517 class StyleProcessorConfiguration(object):
518
519 """Stores configuration values for the StyleProcessor class.
520
521 Attributes:
522 min_confidence: An integer between 1 and 5 inclusive that is the
523 minimum confidence level of style errors to report.
524
525 max_reports_per_category: The maximum number of errors to report
526 per category, per file.
527
528 stderr_write: A function that takes a string as a parameter and
529 serves as stderr.write.
530
531 """
532
533 def __init__(self,
534 filter_configuration,
535 max_reports_per_category,
536 min_confidence,
537 output_format,
538 stderr_write):
539 """Create a StyleProcessorConfiguration instance.
540
541 Args:
542 filter_configuration: A FilterConfiguration instance. The default
543 is the "empty" filter configuration, which
544 means that all errors should be checked.
545
546 max_reports_per_category: The maximum number of errors to report
547 per category, per file.
548
549 min_confidence: An integer between 1 and 5 inclusive that is the
550 minimum confidence level of style errors to report.
551 The default is 1, which reports all style errors.
552
553 output_format: A string that is the output format. The supported
554 output formats are "emacs" which emacs can parse
555 and "vs7" which Microsoft Visual Studio 7 can parse.
556
557 stderr_write: A function that takes a string as a parameter and
558 serves as stderr.write.
559
560 """
561 self._filter_configuration = filter_configuration
562 self._output_format = output_format
563
564 self.max_reports_per_category = max_reports_per_category
565 self.min_confidence = min_confidence
566 self.stderr_write = stderr_write
567
568 def is_reportable(self, category, confidence_in_error, file_path):
569 """Return whether an error is reportable.
570
571 An error is reportable if both the confidence in the error is
572 at least the minimum confidence level and the current filter
573 says the category should be checked for the given path.
574
575 Args:
576 category: A string that is a style category.
577 confidence_in_error: An integer between 1 and 5 inclusive that is
578 the application's confidence in the error.
579 A higher number means greater confidence.
580 file_path: The path of the file being checked
581
582 """
583 if confidence_in_error < self.min_confidence:
584 return False
585
586 return self._filter_configuration.should_check(category, file_path)
587
588 def write_style_error(self,
589 category,
590 confidence_in_error,
591 file_path,
592 line_number,
593 message):
594 """Write a style error to the configured stderr."""
595 if self._output_format == 'vs7':
596 format_string = "%s(%s): %s [%s] [%d]\n"
597 else:
598 format_string = "%s:%s: %s [%s] [%d]\n"
599
600 self.stderr_write(format_string % (file_path,
601 line_number,
602 message,
603 category,
604 confidence_in_error))
605
606
607 class ProcessorBase(object):
608
609 """The base class for processors of lists of lines."""
610
611 def should_process(self, file_path):
612 """Return whether the file at file_path should be processed.
613
614 The TextFileReader class calls this method prior to reading in
615 the lines of a file. Use this method, for example, to prevent
616 the style checker from reading binary files into memory.
617
618 """
619 raise NotImplementedError('Subclasses should implement.')
620
621 def process(self, lines, file_path, **kwargs):
622 """Process lines of text read from a file.
623
624 Args:
625 lines: A list of lines of text to process.
626 file_path: The path from which the lines were read.
627 **kwargs: This argument signifies that the process() method of
628 subclasses of ProcessorBase may support additional
629 keyword arguments.
630 For example, a style checker's check() method
631 may support a "reportable_lines" parameter that represents
632 the line numbers of the lines for which style errors
633 should be reported.
634
635 """
636 raise NotImplementedError('Subclasses should implement.')
637
638
639 class StyleProcessor(ProcessorBase):
640
641 """A ProcessorBase for checking style.
642
643 Attributes:
644 error_count: An integer that is the total number of reported
645 errors for the lifetime of this instance.
646
647 """
648
649 def __init__(self, configuration, mock_dispatcher=None,
650 mock_increment_error_count=None,
651 mock_carriage_checker_class=None):
652 """Create an instance.
653
654 Args:
655 configuration: A StyleProcessorConfiguration instance.
656 mock_dispatcher: A mock CheckerDispatcher instance. This
657 parameter is for unit testing. Defaults to a
658 CheckerDispatcher instance.
659 mock_increment_error_count: A mock error-count incrementer.
660 mock_carriage_checker_class: A mock class for checking and
661 transforming carriage returns.
662 This parameter is for unit testing.
663 Defaults to CarriageReturnChecker.
664
665 """
666 if mock_dispatcher is None:
667 dispatcher = CheckerDispatcher()
668 else:
669 dispatcher = mock_dispatcher
670
671 if mock_increment_error_count is None:
672 # The following blank line is present to avoid flagging by pep8.py.
673
674 def increment_error_count():
675 """Increment the total count of reported errors."""
676 self.error_count += 1
677 else:
678 increment_error_count = mock_increment_error_count
679
680 if mock_carriage_checker_class is None:
681 # This needs to be a class rather than an instance since the
682 # process() method instantiates one using parameters.
683 carriage_checker_class = CarriageReturnChecker
684 else:
685 carriage_checker_class = mock_carriage_checker_class
686
687 self.error_count = 0
688
689 self._carriage_checker_class = carriage_checker_class
690 self._configuration = configuration
691 self._dispatcher = dispatcher
692 self._increment_error_count = increment_error_count
693
694 def should_process(self, file_path):
695 """Return whether the file should be checked for style."""
696 if self._dispatcher.should_skip_without_warning(file_path):
697 return False
698 if self._dispatcher.should_skip_with_warning(file_path):
699 _log.warn('File exempt from style guide. Skipping: "%s"'
700 % file_path)
701 return False
702 return True
703
704 def process(self, lines, file_path, line_numbers=None):
705 """Check the given lines for style.
706
707 Arguments:
708 lines: A list of all lines in the file to check.
709 file_path: The path of the file to process. If possible, the path
710 should be relative to the source root. Otherwise,
711 path-specific logic may not behave as expected.
712 line_numbers: A list of line numbers of the lines for which
713 style errors should be reported, or None if errors
714 for all lines should be reported. When not None, this
715 list normally contains the line numbers corresponding
716 to the modified lines of a patch.
717
718 """
719 _log.debug("Checking style: " + file_path)
720
721 style_error_handler = DefaultStyleErrorHandler(
722 configuration=self._configuration,
723 file_path=file_path,
724 increment_error_count=self._increment_error_count,
725 line_numbers=line_numbers)
726
727 carriage_checker = self._carriage_checker_class(style_error_handler)
728
729 # Check for and remove trailing carriage returns ("\r").
730 if self._dispatcher.should_check_and_strip_carriage_returns(file_path):
731 lines = carriage_checker.check(lines)
732
733 min_confidence = self._configuration.min_confidence
734 checker = self._dispatcher.dispatch(file_path,
735 style_error_handler,
736 min_confidence)
737
738 if checker is None:
739 raise AssertionError("File should not be checked: '%s'" % file_path)
740
741 _log.debug("Using class: " + checker.__class__.__name__)
742
743 checker.check(lines)
OLDNEW
« no previous file with comments | « sky/tools/webkitpy/style/__init__.py ('k') | sky/tools/webkitpy/style/checker_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698