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
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
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
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.
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.
31 """Front end of some style-checker modules."""
37 from checkers.common import categories as CommonCategories
38 from checkers.common import CarriageReturnChecker
39 from checkers.changelog import ChangeLogChecker
40 from checkers.cpp import CppChecker
41 from checkers.python import PythonChecker
42 from checkers.test_expectations import TestExpectationsChecker
43 from checkers.text import TextChecker
44 from checkers.xcodeproj import XcodeProjectFileChecker
45 from checkers.xml import XMLChecker
46 from error_handlers import DefaultStyleErrorHandler
47 from filter import FilterConfiguration
48 from optparser import ArgumentParser
49 from optparser import DefaultCommandOptionValues
50 from webkitpy.common.system.logutils import configure_logging as _configure_logging
53 _log = logging.getLogger(__name__)
56 # These are default option values for the command-line option parser.
57 _DEFAULT_MIN_CONFIDENCE = 1
58 _DEFAULT_OUTPUT_FORMAT = 'emacs'
61 # FIXME: For style categories we will never want to have, remove them.
62 # For categories for which we want to have similar functionality,
63 # modify the implementation and enable them.
65 # Throughout this module, we use "filter rule" rather than "filter"
66 # for an individual boolean filter flag like "+foo". This allows us to
67 # reserve "filter" for what one gets by collectively applying all of
70 # The base filter rules are the filter rules that begin the list of
71 # filter rules used to check style. For example, these rules precede
72 # any user-specified filter rules. Since by default all categories are
73 # checked, this list should normally include only rules that begin
75 _BASE_FILTER_RULES = [
76 '-build/endif_comment',
77 '-build/include_what_you_use', # <string> for std::string
78 '-build/storage_class', # const static
80 '-readability/multiline_comment',
81 '-readability/braces', # int foo() {};
82 '-readability/fn_size',
83 '-readability/casting',
84 '-readability/function',
85 '-runtime/arrays', # variable length array
88 '-runtime/explicit', # explicit
89 '-runtime/virtual', # virtual dtor
91 '-runtime/threadsafe_fn',
93 '-whitespace/blank_line',
94 '-whitespace/end_of_line',
96 # List Python pep8 categories last.
98 # Because much of WebKit's Python code base does not abide by the
99 # PEP8 79 character limit, we ignore the 79-character-limit category
102 # FIXME: Consider bringing WebKit's Python code base into conformance
103 # with the 79 character limit, or some higher limit that is
104 # agreeable to the WebKit project.
109 # The path-specific filter rules.
111 # This list is order sensitive. Only the first path substring match
112 # is used. See the FilterConfiguration documentation in filter.py
113 # for more information on this list.
115 # Each string appearing in this nested list should have at least
116 # one associated unit test assertion. These assertions are located,
117 # for example, in the test_path_rules_specifier() unit test method of
118 # checker_unittest.py.
119 _PATH_RULES_SPECIFIER = [
120 # Files in these directories are consumers of the WebKit
121 # API and therefore do not follow the same header including
122 # discipline as WebCore.
124 ([# TestNetscapePlugIn has no config.h and uses funny names like
126 "Tools/DumpRenderTree/TestNetscapePlugIn/",
127 # The API test harnesses have no config.h and use funny macros like
129 "Tools/WebKitAPITest/",
130 "Tools/TestWebKitAPI/",
131 "Source/WebKit/qt/tests/qdeclarativewebview"],
133 "-readability/naming"]),
134 ([# There is no clean way to avoid "yy_*" names used by flex.
135 "Source/WebCore/css/CSSParser.cpp",
136 # Qt code uses '_' in some places (such as private slots
137 # and on test xxx_data methos on tests)
138 "Source/JavaScriptCore/qt/",
139 "Source/WebKit/qt/Api/",
140 "Source/WebKit/qt/tests/",
141 "Source/WebKit/qt/declarative/",
142 "Source/WebKit/qt/examples/"],
143 ["-readability/naming"]),
144 ([# Qt's MiniBrowser has no config.h
145 "Tools/MiniBrowser/qt"],
147 ([# The GTK+ APIs use GTK+ naming style, which includes
148 # lower-cased, underscore-separated values, whitespace before
149 # parens for function calls, and always having variable names.
150 # Also, GTK+ allows the use of NULL.
151 "Source/WebCore/bindings/scripts/test/GObject",
152 "Source/WebKit/gtk/webkit/",
153 "Tools/DumpRenderTree/gtk/"],
154 ["-readability/naming",
155 "-readability/parameter_name",
157 "-whitespace/parens"]),
158 ([# Header files in ForwardingHeaders have no header guards or
159 # exceptional header guards (e.g., WebCore_FWD_Debugger_h).
160 "/ForwardingHeaders/"],
161 ["-build/header_guard"]),
162 ([# assembler has lots of opcodes that use underscores, so
163 # we don't check for underscores in that directory.
164 "/Source/JavaScriptCore/assembler/"],
165 ["-readability/naming"]),
166 ([# JITStubs has an usual syntax which causes false alarms for a few checks.
167 "JavaScriptCore/jit/JITStubs.cpp"],
168 ["-readability/parameter_name",
169 "-whitespace/parens"]),
171 ([# The EFL APIs use EFL naming style, which includes
172 # both lower-cased and camel-cased, underscore-sparated
174 "Source/WebKit/efl/ewk/",
175 "Source/WebKit2/UIProcess/API/efl/",
176 "Tools/EWebLauncher/",
177 "Tools/MiniBrowser/efl/"],
178 ["-readability/naming",
179 "-readability/parameter_name",
180 "-whitespace/declaration"]),
183 # WebKit2 and certain directories have idiosyncracies.
184 ([# NPAPI has function names with underscores.
185 "Source/WebKit2/WebProcess/Plugins/Netscape"],
186 ["-readability/naming"]),
187 ([# The WebKit2 C API has names with underscores and whitespace-aligned
188 # struct members. Also, we allow unnecessary parameter names in
189 # WebKit2 APIs because we're matching CF's header style.
190 "Source/WebKit2/UIProcess/API/C/",
191 "Source/WebKit2/Shared/API/c/",
192 "Source/WebKit2/WebProcess/InjectedBundle/API/c/"],
193 ["-readability/naming",
194 "-readability/parameter_name",
195 "-whitespace/declaration"]),
197 # For third-party Python code, keep only the following checks--
199 # No tabs: to avoid having to set the SVN allow-tabs property.
200 # No trailing white space: since this is easy to correct.
201 # No carriage-return line endings: since this is easy to correct.
203 (["webkitpy/thirdparty/"],
206 "+pep8/W291", # Trailing white space
207 "+whitespace/carriage_return"]),
209 ([# Qt Symbian platform plugin has no config.h or header guard.
210 # Qt code uses '_' in some places (such as private slots
211 # and on test xxx_data methos on tests).
212 "Source/WebKit/qt/symbian/platformplugin/"],
213 ["-readability/naming",
214 "-build/header_guard",
215 "-build/include_order"]),
217 ([# glu's libtess is third-party code, and doesn't follow WebKit style.
218 "Source/ThirdParty/glu"],
221 "-build/header_guard",
222 "-build/include_order"]),
226 _CPP_FILE_EXTENSIONS = [
232 _PYTHON_FILE_EXTENSION = 'py'
234 _TEXT_FILE_EXTENSIONS = [
261 _XCODEPROJ_FILE_EXTENSION = 'pbxproj'
263 _XML_FILE_EXTENSIONS = [
268 # Files to skip that are less obvious.
270 # Some files should be skipped when checking style. For example,
271 # WebKit maintains some files in Mozilla style on purpose to ease
273 _SKIPPED_FILES_WITH_WARNING = [
274 "gtk2drawing.c", # WebCore/platform/gtk/gtk2drawing.c
275 "gtkdrawing.h", # WebCore/platform/gtk/gtkdrawing.h
276 "Source/WebKit/gtk/tests/",
277 # Soup API that is still being cooked, will be removed from WebKit
278 # in a few months when it is merged into soup proper. The style
279 # follows the libsoup style completely.
280 "Source/WebCore/platform/network/soup/cache/",
284 # Files to skip that are more common or obvious.
286 # This list should be in addition to files with FileType.NONE. Files
287 # with FileType.NONE are automatically skipped without warning.
288 _SKIPPED_FILES_WITHOUT_WARNING = [
289 "LayoutTests" + os.path.sep,
292 # Extensions of files which are allowed to contain carriage returns.
293 _CARRIAGE_RETURN_ALLOWED_FILE_EXTENSIONS = [
298 # The maximum number of errors to report per file, per category.
299 # If a category is not a key, then it has no maximum.
300 _MAX_REPORTS_PER_CATEGORY = {
301 "whitespace/carriage_return": 1
305 def _all_categories():
306 """Return the set of all categories used by check-webkit-style."""
307 # Take the union across all checkers.
308 categories = CommonCategories.union(CppChecker.categories)
309 categories = categories.union(TestExpectationsChecker.categories)
311 # FIXME: Consider adding all of the pep8 categories. Since they
312 # are not too meaningful for documentation purposes, for
313 # now we add only the categories needed for the unit tests
314 # (which validate the consistency of the configuration
315 # settings against the known categories, etc).
316 categories = categories.union(["pep8/W191", "pep8/W291", "pep8/E501"])
321 def _check_webkit_style_defaults():
322 """Return the default command-line options for check-webkit-style."""
323 return DefaultCommandOptionValues(min_confidence=_DEFAULT_MIN_CONFIDENCE,
324 output_format=_DEFAULT_OUTPUT_FORMAT)
327 # This function assists in optparser not having to import from checker.
328 def check_webkit_style_parser():
329 all_categories = _all_categories()
330 default_options = _check_webkit_style_defaults()
331 return ArgumentParser(all_categories=all_categories,
332 base_filter_rules=_BASE_FILTER_RULES,
333 default_options=default_options)
336 def check_webkit_style_configuration(options):
337 """Return a StyleProcessorConfiguration instance for check-webkit-style.
340 options: A CommandOptionValues instance.
343 filter_configuration = FilterConfiguration(
344 base_rules=_BASE_FILTER_RULES,
345 path_specific=_PATH_RULES_SPECIFIER,
346 user_rules=options.filter_rules)
348 return StyleProcessorConfiguration(filter_configuration=filter_configuration,
349 max_reports_per_category=_MAX_REPORTS_PER_CATEGORY,
350 min_confidence=options.min_confidence,
351 output_format=options.output_format,
352 stderr_write=sys.stderr.write)
355 def _create_log_handlers(stream):
356 """Create and return a default list of logging.Handler instances.
358 Format WARNING messages and above to display the logging level, and
359 messages strictly below WARNING not to display it.
362 stream: See the configure_logging() docstring.
365 # Handles logging.WARNING and above.
366 error_handler = logging.StreamHandler(stream)
367 error_handler.setLevel(logging.WARNING)
368 formatter = logging.Formatter("%(levelname)s: %(message)s")
369 error_handler.setFormatter(formatter)
371 # Create a logging.Filter instance that only accepts messages
372 # below WARNING (i.e. filters out anything WARNING or above).
373 non_error_filter = logging.Filter()
374 # The filter method accepts a logging.LogRecord instance.
375 non_error_filter.filter = lambda record: record.levelno < logging.WARNING
377 non_error_handler = logging.StreamHandler(stream)
378 non_error_handler.addFilter(non_error_filter)
379 formatter = logging.Formatter("%(message)s")
380 non_error_handler.setFormatter(formatter)
382 return [error_handler, non_error_handler]
385 def _create_debug_log_handlers(stream):
386 """Create and return a list of logging.Handler instances for debugging.
389 stream: See the configure_logging() docstring.
392 handler = logging.StreamHandler(stream)
393 formatter = logging.Formatter("%(name)s: %(levelname)-8s %(message)s")
394 handler.setFormatter(formatter)
399 def configure_logging(stream, logger=None, is_verbose=False):
400 """Configure logging, and return the list of handlers added.
403 A list of references to the logging handlers added to the root
404 logger. This allows the caller to later remove the handlers
405 using logger.removeHandler. This is useful primarily during unit
406 testing where the caller may want to configure logging temporarily
407 and then undo the configuring.
410 stream: A file-like object to which to log. The stream must
411 define an "encoding" data attribute, or else logging
413 logger: A logging.logger instance to configure. This parameter
414 should be used only in unit tests. Defaults to the
416 is_verbose: A boolean value of whether logging should be verbose.
419 # If the stream does not define an "encoding" data attribute, the
420 # logging module can throw an error like the following:
422 # Traceback (most recent call last):
423 # File "/System/Library/Frameworks/Python.framework/Versions/2.6/...
424 # lib/python2.6/logging/__init__.py", line 761, in emit
425 # self.stream.write(fs % msg.encode(self.stream.encoding))
426 # LookupError: unknown encoding: unknown
428 logger = logging.getLogger()
431 logging_level = logging.DEBUG
432 handlers = _create_debug_log_handlers(stream)
434 logging_level = logging.INFO
435 handlers = _create_log_handlers(stream)
437 handlers = _configure_logging(logging_level=logging_level, logger=logger,
446 NONE = 0 # FileType.NONE evaluates to False.
447 # Alphabetize remaining types
456 class CheckerDispatcher(object):
458 """Supports determining whether and how to check style, based on path."""
460 def _file_extension(self, file_path):
461 """Return the file extension without the leading dot."""
462 return os.path.splitext(file_path)[1].lstrip(".")
464 def should_skip_with_warning(self, file_path):
465 """Return whether the given file should be skipped with a warning."""
466 for skipped_file in _SKIPPED_FILES_WITH_WARNING:
467 if file_path.find(skipped_file) >= 0:
471 def should_skip_without_warning(self, file_path):
472 """Return whether the given file should be skipped without a warning."""
473 if not self._file_type(file_path): # FileType.NONE.
475 # Since "LayoutTests" is in _SKIPPED_FILES_WITHOUT_WARNING, make
476 # an exception to prevent files like "LayoutTests/ChangeLog" and
477 # "LayoutTests/ChangeLog-2009-06-16" from being skipped.
478 # Files like 'test_expectations.txt' and 'drt_expectations.txt'
479 # are also should not be skipped.
481 # FIXME: Figure out a good way to avoid having to add special logic
482 # for this special case.
483 basename = os.path.basename(file_path)
484 if basename.startswith('ChangeLog'):
486 elif basename == 'test_expectations.txt' or basename == 'drt_expectations.txt':
488 for skipped_file in _SKIPPED_FILES_WITHOUT_WARNING:
489 if file_path.find(skipped_file) >= 0:
493 def should_check_and_strip_carriage_returns(self, file_path):
494 return self._file_extension(file_path) not in _CARRIAGE_RETURN_ALLOWED_FILE_EXTENSIONS
496 def _file_type(self, file_path):
497 """Return the file type corresponding to the given file."""
498 file_extension = self._file_extension(file_path)
500 if (file_extension in _CPP_FILE_EXTENSIONS) or (file_path == '-'):
501 # FIXME: Do something about the comment below and the issue it
502 # raises since cpp_style already relies on the extension.
504 # Treat stdin as C++. Since the extension is unknown when
505 # reading from stdin, cpp_style tests should not rely on
508 elif file_extension == _PYTHON_FILE_EXTENSION:
509 return FileType.PYTHON
510 elif file_extension in _XML_FILE_EXTENSIONS:
512 elif os.path.basename(file_path).startswith('ChangeLog'):
513 return FileType.CHANGELOG
514 elif file_extension == _XCODEPROJ_FILE_EXTENSION:
515 return FileType.XCODEPROJ
516 elif ((not file_extension and os.path.join("Tools", "Scripts") in file_path) or
517 file_extension in _TEXT_FILE_EXTENSIONS):
522 def _create_checker(self, file_type, file_path, handle_style_error,
524 """Instantiate and return a style checker based on file type."""
525 if file_type == FileType.NONE:
527 elif file_type == FileType.CHANGELOG:
528 should_line_be_checked = None
529 if handle_style_error:
530 should_line_be_checked = handle_style_error.should_line_be_checked
531 checker = ChangeLogChecker(file_path, handle_style_error, should_line_be_checked)
532 elif file_type == FileType.CPP:
533 file_extension = self._file_extension(file_path)
534 checker = CppChecker(file_path, file_extension,
535 handle_style_error, min_confidence)
536 elif file_type == FileType.PYTHON:
537 checker = PythonChecker(file_path, handle_style_error)
538 elif file_type == FileType.XML:
539 checker = XMLChecker(file_path, handle_style_error)
540 elif file_type == FileType.XCODEPROJ:
541 checker = XcodeProjectFileChecker(file_path, handle_style_error)
542 elif file_type == FileType.TEXT:
543 basename = os.path.basename(file_path)
544 if basename == 'test_expectations.txt' or basename == 'drt_expectations.txt':
545 checker = TestExpectationsChecker(file_path, handle_style_error)
547 checker = TextChecker(file_path, handle_style_error)
549 raise ValueError('Invalid file type "%(file_type)s": the only valid file types '
550 "are %(NONE)s, %(CPP)s, and %(TEXT)s."
551 % {"file_type": file_type,
552 "NONE": FileType.NONE,
554 "TEXT": FileType.TEXT})
558 def dispatch(self, file_path, handle_style_error, min_confidence):
559 """Instantiate and return a style checker based on file path."""
560 file_type = self._file_type(file_path)
562 checker = self._create_checker(file_type,
569 # FIXME: Remove the stderr_write attribute from this class and replace
570 # its use with calls to a logging module logger.
571 class StyleProcessorConfiguration(object):
573 """Stores configuration values for the StyleProcessor class.
576 min_confidence: An integer between 1 and 5 inclusive that is the
577 minimum confidence level of style errors to report.
579 max_reports_per_category: The maximum number of errors to report
580 per category, per file.
582 stderr_write: A function that takes a string as a parameter and
583 serves as stderr.write.
588 filter_configuration,
589 max_reports_per_category,
593 """Create a StyleProcessorConfiguration instance.
596 filter_configuration: A FilterConfiguration instance. The default
597 is the "empty" filter configuration, which
598 means that all errors should be checked.
600 max_reports_per_category: The maximum number of errors to report
601 per category, per file.
603 min_confidence: An integer between 1 and 5 inclusive that is the
604 minimum confidence level of style errors to report.
605 The default is 1, which reports all style errors.
607 output_format: A string that is the output format. The supported
608 output formats are "emacs" which emacs can parse
609 and "vs7" which Microsoft Visual Studio 7 can parse.
611 stderr_write: A function that takes a string as a parameter and
612 serves as stderr.write.
615 self._filter_configuration = filter_configuration
616 self._output_format = output_format
618 self.max_reports_per_category = max_reports_per_category
619 self.min_confidence = min_confidence
620 self.stderr_write = stderr_write
622 def is_reportable(self, category, confidence_in_error, file_path):
623 """Return whether an error is reportable.
625 An error is reportable if both the confidence in the error is
626 at least the minimum confidence level and the current filter
627 says the category should be checked for the given path.
630 category: A string that is a style category.
631 confidence_in_error: An integer between 1 and 5 inclusive that is
632 the application's confidence in the error.
633 A higher number means greater confidence.
634 file_path: The path of the file being checked
637 if confidence_in_error < self.min_confidence:
640 return self._filter_configuration.should_check(category, file_path)
642 def write_style_error(self,
648 """Write a style error to the configured stderr."""
649 if self._output_format == 'vs7':
650 format_string = "%s(%s): %s [%s] [%d]\n"
652 format_string = "%s:%s: %s [%s] [%d]\n"
654 self.stderr_write(format_string % (file_path,
658 confidence_in_error))
661 class ProcessorBase(object):
663 """The base class for processors of lists of lines."""
665 def should_process(self, file_path):
666 """Return whether the file at file_path should be processed.
668 The TextFileReader class calls this method prior to reading in
669 the lines of a file. Use this method, for example, to prevent
670 the style checker from reading binary files into memory.
673 raise NotImplementedError('Subclasses should implement.')
675 def process(self, lines, file_path, **kwargs):
676 """Process lines of text read from a file.
679 lines: A list of lines of text to process.
680 file_path: The path from which the lines were read.
681 **kwargs: This argument signifies that the process() method of
682 subclasses of ProcessorBase may support additional
684 For example, a style checker's check() method
685 may support a "reportable_lines" parameter that represents
686 the line numbers of the lines for which style errors
690 raise NotImplementedError('Subclasses should implement.')
693 class StyleProcessor(ProcessorBase):
695 """A ProcessorBase for checking style.
698 error_count: An integer that is the total number of reported
699 errors for the lifetime of this instance.
703 def __init__(self, configuration, mock_dispatcher=None,
704 mock_increment_error_count=None,
705 mock_carriage_checker_class=None):
706 """Create an instance.
709 configuration: A StyleProcessorConfiguration instance.
710 mock_dispatcher: A mock CheckerDispatcher instance. This
711 parameter is for unit testing. Defaults to a
712 CheckerDispatcher instance.
713 mock_increment_error_count: A mock error-count incrementer.
714 mock_carriage_checker_class: A mock class for checking and
715 transforming carriage returns.
716 This parameter is for unit testing.
717 Defaults to CarriageReturnChecker.
720 if mock_dispatcher is None:
721 dispatcher = CheckerDispatcher()
723 dispatcher = mock_dispatcher
725 if mock_increment_error_count is None:
726 # The following blank line is present to avoid flagging by pep8.py.
728 def increment_error_count():
729 """Increment the total count of reported errors."""
730 self.error_count += 1
732 increment_error_count = mock_increment_error_count
734 if mock_carriage_checker_class is None:
735 # This needs to be a class rather than an instance since the
736 # process() method instantiates one using parameters.
737 carriage_checker_class = CarriageReturnChecker
739 carriage_checker_class = mock_carriage_checker_class
743 self._carriage_checker_class = carriage_checker_class
744 self._configuration = configuration
745 self._dispatcher = dispatcher
746 self._increment_error_count = increment_error_count
748 def should_process(self, file_path):
749 """Return whether the file should be checked for style."""
750 if self._dispatcher.should_skip_without_warning(file_path):
752 if self._dispatcher.should_skip_with_warning(file_path):
753 _log.warn('File exempt from style guide. Skipping: "%s"'
758 def process(self, lines, file_path, line_numbers=None):
759 """Check the given lines for style.
762 lines: A list of all lines in the file to check.
763 file_path: The path of the file to process. If possible, the path
764 should be relative to the source root. Otherwise,
765 path-specific logic may not behave as expected.
766 line_numbers: A list of line numbers of the lines for which
767 style errors should be reported, or None if errors
768 for all lines should be reported. When not None, this
769 list normally contains the line numbers corresponding
770 to the modified lines of a patch.
773 _log.debug("Checking style: " + file_path)
775 style_error_handler = DefaultStyleErrorHandler(
776 configuration=self._configuration,
778 increment_error_count=self._increment_error_count,
779 line_numbers=line_numbers)
781 carriage_checker = self._carriage_checker_class(style_error_handler)
783 # Check for and remove trailing carriage returns ("\r").
784 if self._dispatcher.should_check_and_strip_carriage_returns(file_path):
785 lines = carriage_checker.check(lines)
787 min_confidence = self._configuration.min_confidence
788 checker = self._dispatcher.dispatch(file_path,
793 raise AssertionError("File should not be checked: '%s'" % file_path)
795 _log.debug("Using class: " + checker.__class__.__name__)