| #!/usr/bin/env python |
| # -*- coding: utf-8 -*- |
| # Copyright 2014 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import argparse |
| import os |
| import re |
| import subprocess |
| import sys |
| |
| SKY_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__)) |
| SKY_ROOT = os.path.dirname(SKY_TOOLS_DIR) |
| SRC_ROOT = os.path.dirname(SKY_ROOT) |
| |
| WORKBENCH = os.path.join(SRC_ROOT, 'sky', 'packages', 'workbench') |
| DART_SDK = os.path.join(SRC_ROOT, 'third_party', 'dart-sdk', 'dart-sdk', 'bin') |
| DARTANALYZER = os.path.join(DART_SDK, 'dartanalyzer') |
| SKY_UNIT_TESTS = os.path.join(SKY_ROOT, 'unit', 'test') |
| |
| _IGNORED_PATTERNS = [ |
| # Ignored because they're not indicative of specific errors. |
| re.compile(r'^$'), |
| re.compile(r'^Analyzing \['), |
| re.compile(r'^No issues found'), |
| re.compile(r'^[0-9]+ (error|warning|hint).*found[.]'), |
| |
| # Disable the Strong checks that we don't care about. |
| re.compile(r'^\[error\] Invalid override\. The type of [^ ]+ \(.+\) is not a subtype of [^ ]+ \(.+\)\.'), # we allow type narrowing |
| re.compile(r'^\[(warning|hint)\] .+ will need runtime check to cast to type .+'), # https://github.com/dart-lang/sdk/issues/24542 |
| re.compile(r'^\[hint\] .+ requires dynamic invoke'), # too many false positives, e.g. https://github.com/dart-lang/sdk/issues/24564 |
| re.compile(r'^\[hint\] Runtime check on non-ground type .+ may throw StrongModeError'), # https://github.com/dart-lang/sdk/issues/24565 |
| re.compile(r'^\[hint] \([_, ]+\) .+ has inferred type '), # ignore underscore-only arguments |
| re.compile(r'^\[error\] Type check failed: .*\(dynamic\) is not of type'), # allow unchecked casts from dynamic |
| |
| # Disable the lint checks that will be caught by code review |
| re.compile(r'^\[lint\] Avoid defining a one-member abstract class when a simple function will do'), |
| re.compile(r'^\[lint\] Prefer using lowerCamelCase for constant names.'), |
| re.compile(r'^\[lint\] Name non-constant identifiers using lowerCamelCase.'), |
| |
| # TODO: Fix all the warnings in the mojo packages |
| re.compile(r'.*pub-cache.*\.mojom\.dart'), |
| |
| # It'd be nice if the other packages we used didn't have warnings, too... |
| re.compile(r'.*pub-cache/hosted/pub.dartlang.org/'), |
| ] |
| |
| def main(): |
| parser = argparse.ArgumentParser(description='Sky Analyzer') |
| parser.add_argument('--congratulate', action="store_true") |
| parser.add_argument('app_path', type=str, nargs="?") |
| args = parser.parse_args() |
| |
| if args.app_path is not None: |
| app_paths = [args.app_path] |
| else: |
| # If no app_path is provided, then run the analyzer on any Dart file |
| # within the unit tests. |
| app_paths = [] |
| for root, _, files in os.walk(SKY_UNIT_TESTS): |
| app_paths.extend(os.path.join(root, f) |
| for f in files if f.endswith(".dart")) |
| |
| try: |
| subprocess.check_output([ |
| DARTANALYZER, "--package-warnings", |
| "--package-root", os.path.join(WORKBENCH, "packages"), |
| "--ignore-unrecognized-flags", |
| "--fatal-hints", |
| "--fatal-warnings", |
| "--lints", |
| "--strong", |
| "--strong-hints", |
| "--enable-strict-call-checks", |
| "--enable_type_checks", |
| "--supermixin", |
| ] + app_paths, stderr=subprocess.STDOUT) |
| except subprocess.CalledProcessError as e: |
| errors = [l for l in e.output.split('\n') |
| if not any(p.match(l) for p in _IGNORED_PATTERNS)] |
| if len(errors) > 0: |
| for error in errors: |
| print >> sys.stderr, error |
| # Propagate analyzer error code. |
| return e.returncode |
| # If we do not have any errors left after filtering, return 0. |
| if args.congratulate: |
| print >> sys.stdout, "No analyzer warnings!" |
| return 0 |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |