OLD | NEW |
1 # Copyright (C) 2009 Google Inc. All rights reserved. | 1 # Copyright (C) 2009 Google Inc. All rights reserved. |
2 # Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com) | 2 # Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com) |
3 # Copyright (C) 2010 ProFUSION embedded systems | 3 # Copyright (C) 2010 ProFUSION embedded systems |
4 # | 4 # |
5 # Redistribution and use in source and binary forms, with or without | 5 # Redistribution and use in source and binary forms, with or without |
6 # modification, are permitted provided that the following conditions are | 6 # modification, are permitted provided that the following conditions are |
7 # met: | 7 # met: |
8 # | 8 # |
9 # * Redistributions of source code must retain the above copyright | 9 # * Redistributions of source code must retain the above copyright |
10 # notice, this list of conditions and the following disclaimer. | 10 # notice, this list of conditions and the following disclaimer. |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 return ArgumentParser(all_categories=all_categories, | 267 return ArgumentParser(all_categories=all_categories, |
268 base_filter_rules=_BASE_FILTER_RULES, | 268 base_filter_rules=_BASE_FILTER_RULES, |
269 default_options=default_options) | 269 default_options=default_options) |
270 | 270 |
271 | 271 |
272 def check_webkit_style_configuration(options): | 272 def check_webkit_style_configuration(options): |
273 """Return a StyleProcessorConfiguration instance for check-webkit-style. | 273 """Return a StyleProcessorConfiguration instance for check-webkit-style. |
274 | 274 |
275 Args: | 275 Args: |
276 options: A CommandOptionValues instance. | 276 options: A CommandOptionValues instance. |
277 | |
278 """ | 277 """ |
279 filter_configuration = FilterConfiguration( | 278 filter_configuration = FilterConfiguration( |
280 base_rules=_BASE_FILTER_RULES, | 279 base_rules=_BASE_FILTER_RULES, |
281 path_specific=_PATH_RULES_SPECIFIER, | 280 path_specific=_PATH_RULES_SPECIFIER, |
282 user_rules=options.filter_rules) | 281 user_rules=options.filter_rules) |
283 | 282 |
284 return StyleProcessorConfiguration(filter_configuration=filter_configuration
, | 283 return StyleProcessorConfiguration(filter_configuration=filter_configuration
, |
285 max_reports_per_category=_MAX_REPORTS_PER
_CATEGORY, | 284 max_reports_per_category=_MAX_REPORTS_PER
_CATEGORY, |
286 min_confidence=options.min_confidence, | 285 min_confidence=options.min_confidence, |
287 output_format=options.output_format, | 286 output_format=options.output_format, |
288 stderr_write=sys.stderr.write) | 287 stderr_write=sys.stderr.write) |
289 | 288 |
290 | 289 |
291 def _create_log_handlers(stream): | 290 def _create_log_handlers(stream): |
292 """Create and return a default list of logging.Handler instances. | 291 """Create and return a default list of logging.Handler instances. |
293 | 292 |
294 Format WARNING messages and above to display the logging level, and | 293 Format WARNING messages and above to display the logging level, and |
295 messages strictly below WARNING not to display it. | 294 messages strictly below WARNING not to display it. |
296 | 295 |
297 Args: | 296 Args: |
298 stream: See the configure_logging() docstring. | 297 stream: See the configure_logging() docstring. |
299 | |
300 """ | 298 """ |
301 # Handles logging.WARNING and above. | 299 # Handles logging.WARNING and above. |
302 error_handler = logging.StreamHandler(stream) | 300 error_handler = logging.StreamHandler(stream) |
303 error_handler.setLevel(logging.WARNING) | 301 error_handler.setLevel(logging.WARNING) |
304 formatter = logging.Formatter("%(levelname)s: %(message)s") | 302 formatter = logging.Formatter("%(levelname)s: %(message)s") |
305 error_handler.setFormatter(formatter) | 303 error_handler.setFormatter(formatter) |
306 | 304 |
307 # Create a logging.Filter instance that only accepts messages | 305 # Create a logging.Filter instance that only accepts messages |
308 # below WARNING (i.e. filters out anything WARNING or above). | 306 # below WARNING (i.e. filters out anything WARNING or above). |
309 non_error_filter = logging.Filter() | 307 non_error_filter = logging.Filter() |
310 # The filter method accepts a logging.LogRecord instance. | 308 # The filter method accepts a logging.LogRecord instance. |
311 non_error_filter.filter = lambda record: record.levelno < logging.WARNING | 309 non_error_filter.filter = lambda record: record.levelno < logging.WARNING |
312 | 310 |
313 non_error_handler = logging.StreamHandler(stream) | 311 non_error_handler = logging.StreamHandler(stream) |
314 non_error_handler.addFilter(non_error_filter) | 312 non_error_handler.addFilter(non_error_filter) |
315 formatter = logging.Formatter("%(message)s") | 313 formatter = logging.Formatter("%(message)s") |
316 non_error_handler.setFormatter(formatter) | 314 non_error_handler.setFormatter(formatter) |
317 | 315 |
318 return [error_handler, non_error_handler] | 316 return [error_handler, non_error_handler] |
319 | 317 |
320 | 318 |
321 def _create_debug_log_handlers(stream): | 319 def _create_debug_log_handlers(stream): |
322 """Create and return a list of logging.Handler instances for debugging. | 320 """Create and return a list of logging.Handler instances for debugging. |
323 | 321 |
324 Args: | 322 Args: |
325 stream: See the configure_logging() docstring. | 323 stream: See the configure_logging() docstring. |
326 | |
327 """ | 324 """ |
328 handler = logging.StreamHandler(stream) | 325 handler = logging.StreamHandler(stream) |
329 formatter = logging.Formatter("%(name)s: %(levelname)-8s %(message)s") | 326 formatter = logging.Formatter("%(name)s: %(levelname)-8s %(message)s") |
330 handler.setFormatter(formatter) | 327 handler.setFormatter(formatter) |
331 | 328 |
332 return [handler] | 329 return [handler] |
333 | 330 |
334 | 331 |
335 def configure_logging(stream, logger=None, is_verbose=False): | 332 def configure_logging(stream, logger=None, is_verbose=False): |
336 """Configure logging, and return the list of handlers added. | 333 """Configure logging, and return the list of handlers added. |
337 | 334 |
338 Returns: | 335 Returns: |
339 A list of references to the logging handlers added to the root | 336 A list of references to the logging handlers added to the root |
340 logger. This allows the caller to later remove the handlers | 337 logger. This allows the caller to later remove the handlers |
341 using logger.removeHandler. This is useful primarily during unit | 338 using logger.removeHandler. This is useful primarily during unit |
342 testing where the caller may want to configure logging temporarily | 339 testing where the caller may want to configure logging temporarily |
343 and then undo the configuring. | 340 and then undo the configuring. |
344 | 341 |
345 Args: | 342 Args: |
346 stream: A file-like object to which to log. The stream must | 343 stream: A file-like object to which to log. The stream must |
347 define an "encoding" data attribute, or else logging | 344 define an "encoding" data attribute, or else logging |
348 raises an error. | 345 raises an error. |
349 logger: A logging.logger instance to configure. This parameter | 346 logger: A logging.logger instance to configure. This parameter |
350 should be used only in unit tests. Defaults to the | 347 should be used only in unit tests. Defaults to the |
351 root logger. | 348 root logger. |
352 is_verbose: A boolean value of whether logging should be verbose. | 349 is_verbose: A boolean value of whether logging should be verbose. |
353 | |
354 """ | 350 """ |
355 # If the stream does not define an "encoding" data attribute, the | 351 # If the stream does not define an "encoding" data attribute, the |
356 # logging module can throw an error like the following: | 352 # logging module can throw an error like the following: |
357 # | 353 # |
358 # Traceback (most recent call last): | 354 # Traceback (most recent call last): |
359 # File "/System/Library/Frameworks/Python.framework/Versions/2.6/... | 355 # File "/System/Library/Frameworks/Python.framework/Versions/2.6/... |
360 # lib/python2.6/logging/__init__.py", line 761, in emit | 356 # lib/python2.6/logging/__init__.py", line 761, in emit |
361 # self.stream.write(fs % msg.encode(self.stream.encoding)) | 357 # self.stream.write(fs % msg.encode(self.stream.encoding)) |
362 # LookupError: unknown encoding: unknown | 358 # LookupError: unknown encoding: unknown |
363 if logger is None: | 359 if logger is None: |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 | 516 |
521 Attributes: | 517 Attributes: |
522 min_confidence: An integer between 1 and 5 inclusive that is the | 518 min_confidence: An integer between 1 and 5 inclusive that is the |
523 minimum confidence level of style errors to report. | 519 minimum confidence level of style errors to report. |
524 | 520 |
525 max_reports_per_category: The maximum number of errors to report | 521 max_reports_per_category: The maximum number of errors to report |
526 per category, per file. | 522 per category, per file. |
527 | 523 |
528 stderr_write: A function that takes a string as a parameter and | 524 stderr_write: A function that takes a string as a parameter and |
529 serves as stderr.write. | 525 serves as stderr.write. |
530 | |
531 """ | 526 """ |
532 | 527 |
533 def __init__(self, | 528 def __init__(self, |
534 filter_configuration, | 529 filter_configuration, |
535 max_reports_per_category, | 530 max_reports_per_category, |
536 min_confidence, | 531 min_confidence, |
537 output_format, | 532 output_format, |
538 stderr_write): | 533 stderr_write): |
539 """Create a StyleProcessorConfiguration instance. | 534 """Create a StyleProcessorConfiguration instance. |
540 | 535 |
541 Args: | 536 Args: |
542 filter_configuration: A FilterConfiguration instance. The default | 537 filter_configuration: A FilterConfiguration instance. The default |
543 is the "empty" filter configuration, which | 538 is the "empty" filter configuration, which |
544 means that all errors should be checked. | 539 means that all errors should be checked. |
545 | 540 |
546 max_reports_per_category: The maximum number of errors to report | 541 max_reports_per_category: The maximum number of errors to report |
547 per category, per file. | 542 per category, per file. |
548 | 543 |
549 min_confidence: An integer between 1 and 5 inclusive that is the | 544 min_confidence: An integer between 1 and 5 inclusive that is the |
550 minimum confidence level of style errors to report. | 545 minimum confidence level of style errors to report. |
551 The default is 1, which reports all style errors. | 546 The default is 1, which reports all style errors. |
552 | 547 |
553 output_format: A string that is the output format. The supported | 548 output_format: A string that is the output format. The supported |
554 output formats are "emacs" which emacs can parse | 549 output formats are "emacs" which emacs can parse |
555 and "vs7" which Microsoft Visual Studio 7 can parse. | 550 and "vs7" which Microsoft Visual Studio 7 can parse. |
556 | 551 |
557 stderr_write: A function that takes a string as a parameter and | 552 stderr_write: A function that takes a string as a parameter and |
558 serves as stderr.write. | 553 serves as stderr.write. |
559 | |
560 """ | 554 """ |
561 self._filter_configuration = filter_configuration | 555 self._filter_configuration = filter_configuration |
562 self._output_format = output_format | 556 self._output_format = output_format |
563 | 557 |
564 self.max_reports_per_category = max_reports_per_category | 558 self.max_reports_per_category = max_reports_per_category |
565 self.min_confidence = min_confidence | 559 self.min_confidence = min_confidence |
566 self.stderr_write = stderr_write | 560 self.stderr_write = stderr_write |
567 | 561 |
568 def is_reportable(self, category, confidence_in_error, file_path): | 562 def is_reportable(self, category, confidence_in_error, file_path): |
569 """Return whether an error is reportable. | 563 """Return whether an error is reportable. |
570 | 564 |
571 An error is reportable if both the confidence in the error is | 565 An error is reportable if both the confidence in the error is |
572 at least the minimum confidence level and the current filter | 566 at least the minimum confidence level and the current filter |
573 says the category should be checked for the given path. | 567 says the category should be checked for the given path. |
574 | 568 |
575 Args: | 569 Args: |
576 category: A string that is a style category. | 570 category: A string that is a style category. |
577 confidence_in_error: An integer between 1 and 5 inclusive that is | 571 confidence_in_error: An integer between 1 and 5 inclusive that is |
578 the application's confidence in the error. | 572 the application's confidence in the error. |
579 A higher number means greater confidence. | 573 A higher number means greater confidence. |
580 file_path: The path of the file being checked | 574 file_path: The path of the file being checked |
581 | |
582 """ | 575 """ |
583 if confidence_in_error < self.min_confidence: | 576 if confidence_in_error < self.min_confidence: |
584 return False | 577 return False |
585 | 578 |
586 return self._filter_configuration.should_check(category, file_path) | 579 return self._filter_configuration.should_check(category, file_path) |
587 | 580 |
588 def write_style_error(self, | 581 def write_style_error(self, |
589 category, | 582 category, |
590 confidence_in_error, | 583 confidence_in_error, |
591 file_path, | 584 file_path, |
(...skipping 15 matching lines...) Expand all Loading... |
607 class ProcessorBase(object): | 600 class ProcessorBase(object): |
608 | 601 |
609 """The base class for processors of lists of lines.""" | 602 """The base class for processors of lists of lines.""" |
610 | 603 |
611 def should_process(self, file_path): | 604 def should_process(self, file_path): |
612 """Return whether the file at file_path should be processed. | 605 """Return whether the file at file_path should be processed. |
613 | 606 |
614 The TextFileReader class calls this method prior to reading in | 607 The TextFileReader class calls this method prior to reading in |
615 the lines of a file. Use this method, for example, to prevent | 608 the lines of a file. Use this method, for example, to prevent |
616 the style checker from reading binary files into memory. | 609 the style checker from reading binary files into memory. |
617 | |
618 """ | 610 """ |
619 raise NotImplementedError('Subclasses should implement.') | 611 raise NotImplementedError('Subclasses should implement.') |
620 | 612 |
621 def process(self, lines, file_path, **kwargs): | 613 def process(self, lines, file_path, **kwargs): |
622 """Process lines of text read from a file. | 614 """Process lines of text read from a file. |
623 | 615 |
624 Args: | 616 Args: |
625 lines: A list of lines of text to process. | 617 lines: A list of lines of text to process. |
626 file_path: The path from which the lines were read. | 618 file_path: The path from which the lines were read. |
627 **kwargs: This argument signifies that the process() method of | 619 **kwargs: This argument signifies that the process() method of |
628 subclasses of ProcessorBase may support additional | 620 subclasses of ProcessorBase may support additional |
629 keyword arguments. | 621 keyword arguments. |
630 For example, a style checker's check() method | 622 For example, a style checker's check() method |
631 may support a "reportable_lines" parameter that represents | 623 may support a "reportable_lines" parameter that represents |
632 the line numbers of the lines for which style errors | 624 the line numbers of the lines for which style errors |
633 should be reported. | 625 should be reported. |
634 | |
635 """ | 626 """ |
636 raise NotImplementedError('Subclasses should implement.') | 627 raise NotImplementedError('Subclasses should implement.') |
637 | 628 |
638 | 629 |
639 class StyleProcessor(ProcessorBase): | 630 class StyleProcessor(ProcessorBase): |
640 | 631 |
641 """A ProcessorBase for checking style. | 632 """A ProcessorBase for checking style. |
642 | 633 |
643 Attributes: | 634 Attributes: |
644 error_count: An integer that is the total number of reported | 635 error_count: An integer that is the total number of reported |
645 errors for the lifetime of this instance. | 636 errors for the lifetime of this instance. |
646 | |
647 """ | 637 """ |
648 | 638 |
649 def __init__(self, configuration, mock_dispatcher=None, | 639 def __init__(self, configuration, mock_dispatcher=None, |
650 mock_increment_error_count=None, | 640 mock_increment_error_count=None, |
651 mock_carriage_checker_class=None): | 641 mock_carriage_checker_class=None): |
652 """Create an instance. | 642 """Create an instance. |
653 | 643 |
654 Args: | 644 Args: |
655 configuration: A StyleProcessorConfiguration instance. | 645 configuration: A StyleProcessorConfiguration instance. |
656 mock_dispatcher: A mock CheckerDispatcher instance. This | 646 mock_dispatcher: A mock CheckerDispatcher instance. This |
657 parameter is for unit testing. Defaults to a | 647 parameter is for unit testing. Defaults to a |
658 CheckerDispatcher instance. | 648 CheckerDispatcher instance. |
659 mock_increment_error_count: A mock error-count incrementer. | 649 mock_increment_error_count: A mock error-count incrementer. |
660 mock_carriage_checker_class: A mock class for checking and | 650 mock_carriage_checker_class: A mock class for checking and |
661 transforming carriage returns. | 651 transforming carriage returns. |
662 This parameter is for unit testing. | 652 This parameter is for unit testing. |
663 Defaults to CarriageReturnChecker. | 653 Defaults to CarriageReturnChecker. |
664 | |
665 """ | 654 """ |
666 if mock_dispatcher is None: | 655 if mock_dispatcher is None: |
667 dispatcher = CheckerDispatcher() | 656 dispatcher = CheckerDispatcher() |
668 else: | 657 else: |
669 dispatcher = mock_dispatcher | 658 dispatcher = mock_dispatcher |
670 | 659 |
671 if mock_increment_error_count is None: | 660 if mock_increment_error_count is None: |
672 # The following blank line is present to avoid flagging by pep8.py. | 661 # The following blank line is present to avoid flagging by pep8.py. |
673 | 662 |
674 def increment_error_count(): | 663 def increment_error_count(): |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 Arguments: | 695 Arguments: |
707 lines: A list of all lines in the file to check. | 696 lines: A list of all lines in the file to check. |
708 file_path: The path of the file to process. If possible, the path | 697 file_path: The path of the file to process. If possible, the path |
709 should be relative to the source root. Otherwise, | 698 should be relative to the source root. Otherwise, |
710 path-specific logic may not behave as expected. | 699 path-specific logic may not behave as expected. |
711 line_numbers: A list of line numbers of the lines for which | 700 line_numbers: A list of line numbers of the lines for which |
712 style errors should be reported, or None if errors | 701 style errors should be reported, or None if errors |
713 for all lines should be reported. When not None, this | 702 for all lines should be reported. When not None, this |
714 list normally contains the line numbers corresponding | 703 list normally contains the line numbers corresponding |
715 to the modified lines of a patch. | 704 to the modified lines of a patch. |
716 | |
717 """ | 705 """ |
718 _log.debug("Checking style: " + file_path) | 706 _log.debug("Checking style: " + file_path) |
719 | 707 |
720 style_error_handler = DefaultStyleErrorHandler( | 708 style_error_handler = DefaultStyleErrorHandler( |
721 configuration=self._configuration, | 709 configuration=self._configuration, |
722 file_path=file_path, | 710 file_path=file_path, |
723 increment_error_count=self._increment_error_count, | 711 increment_error_count=self._increment_error_count, |
724 line_numbers=line_numbers) | 712 line_numbers=line_numbers) |
725 | 713 |
726 carriage_checker = self._carriage_checker_class(style_error_handler) | 714 carriage_checker = self._carriage_checker_class(style_error_handler) |
727 | 715 |
728 # Check for and remove trailing carriage returns ("\r"). | 716 # Check for and remove trailing carriage returns ("\r"). |
729 if self._dispatcher.should_check_and_strip_carriage_returns(file_path): | 717 if self._dispatcher.should_check_and_strip_carriage_returns(file_path): |
730 lines = carriage_checker.check(lines) | 718 lines = carriage_checker.check(lines) |
731 | 719 |
732 min_confidence = self._configuration.min_confidence | 720 min_confidence = self._configuration.min_confidence |
733 checker = self._dispatcher.dispatch(file_path, | 721 checker = self._dispatcher.dispatch(file_path, |
734 style_error_handler, | 722 style_error_handler, |
735 min_confidence) | 723 min_confidence) |
736 | 724 |
737 if checker is None: | 725 if checker is None: |
738 raise AssertionError("File should not be checked: '%s'" % file_path) | 726 raise AssertionError("File should not be checked: '%s'" % file_path) |
739 | 727 |
740 _log.debug("Using class: " + checker.__class__.__name__) | 728 _log.debug("Using class: " + checker.__class__.__name__) |
741 | 729 |
742 checker.check(lines) | 730 checker.check(lines) |
OLD | NEW |