Ejemplo n.º 1
0
def sanity_test():
    # pylint: disable=import-outside-toplevel
    from argparse import ArgumentParser
    import traceback
    # pylint: enable=import-outside-toplevel

    ap = ArgumentParser()
    ap.add_argument("item", metavar="FILE|DIR")
    ap.add_argument("--no-tb",
                    action="store_true",
                    default=False,
                    help="Do not show debug-style backtrace")
    options = ap.parse_args()

    mh = Message_Handler("debug")
    mh.sort_messages = False
    mh.colour = False

    try:
        register_item(mh, options.item, options)

    except Error:
        if not options.no_tb:
            traceback.print_exc()

    except ICE as ice:
        if not options.no_tb:
            traceback.print_exc()
        print("ICE:", ice.reason)

    for dirname in sorted(tree):
        print("Showing config for %s" % dirname)

        node = tree[dirname]
        print("  Root: %s" % node.project_root)
        print("  File: %s" % ", ".join(node.config_files))

        cfg = node.config
        if cfg is None:
            print("  No config attached")
            continue

        print("  Enabled = %s" % cfg.enabled)
        print("  Octave  = %s" % cfg.octave)
        print("  Rules   = %u" % len(cfg.style_rules))
        print("  SConf   = %s" % cfg.style_config)
        print("  Metrics = %u" % len(cfg.enabled_metrics))
        print("  Limits  = %s" % cfg.metric_limits)
Ejemplo n.º 2
0
def main_handler():
    clp = command_line.create_basic_clp()

    # Extra output options
    clp["output_options"].add_argument(
        "--html", default=None, help="Write report to given file as HTML")
    clp["output_options"].add_argument("--json",
                                       default=None,
                                       help="Produce JSON report")

    options = command_line.parse_args(clp)

    if options.html:
        if options.json:
            clp["ap"].error("Cannot produce JSON and HTML at the same time")
        if os.path.exists(options.html) and not os.path.isfile(options.html):
            clp["ap"].error("Cannot write to %s: it is not a file" %
                            options.html)
        mh = HTML_Message_Handler("lint", options.html)
    elif options.json:
        if os.path.exists(options.json) and not os.path.isfile(options.json):
            clp["ap"].error("Cannot write to %s: it is not a file" %
                            options.json)
        mh = JSON_Message_Handler("lint", options.json)
    else:
        mh = Message_Handler("lint")

    mh.show_context = not options.brief
    mh.show_style = False
    mh.show_checks = True
    mh.autofix = False

    lint_backend = MH_Lint(options)
    command_line.execute(mh, options, {}, lint_backend)
Ejemplo n.º 3
0
def main_handler():
    clp = command_line.create_basic_clp()

    clp["output_options"].add_argument(
        "--json",
        default="mh_trace.json",
        help="name of the JSON report (by default mh_trace.json)")
    clp["output_options"].add_argument(
        "--by-tag",
        action="store_true",
        default=False,
        help=("group tracing information by tag; by default we group by"
              " unit name first"))

    options = command_line.parse_args(clp)

    mh = Message_Handler("trace")

    mh.show_context = not options.brief
    mh.show_style   = False
    mh.show_checks  = False
    mh.autofix      = False

    trace_backend = MH_Trace(options)
    command_line.execute(mh, options, {}, trace_backend,
                         process_tests=True)
Ejemplo n.º 4
0
def main():
    # pylint: disable=import-outside-toplevel
    from argparse import ArgumentParser
    # pylint: enable=import-outside-toplevel

    ap = ArgumentParser()
    ap.add_argument("name", metavar="FILE|DIR")
    options = ap.parse_args()

    mh = Message_Handler("debug")
    mh.sort_messages = False
    mh.colour = False

    if os.path.isfile(options.name):
        sanity_test(mh, options.name, options)
    elif os.path.isdir(options.name):
        for path, _, files in os.walk(options.name):
            for f in files:
                if f.endswith(".slx"):
                    sanity_test(mh, os.path.join(path, f), options)
    else:
        ap.error("%s is neither a file or directory" % options.name)

    print()
    print("=== Summary of misc. children ===")
    for block_type in sorted(anatomy):
        print("Children in %s" % block_type)
        for tag in sorted(anatomy[block_type]):
            print("   * %s" % tag)

    mh.summary_and_exit()
Ejemplo n.º 5
0
def main_handler():
    clp = command_line.create_basic_clp()
    clp["debug_options"].add_argument(
        "--keep",
        help="do not delete intermediate files",
        action="store_true",
        default=False)

    options = command_line.parse_args(clp)

    try:
        subprocess.run(["cbmc", "--version"],
                       check=True,
                       capture_output=True,
                       encoding="utf-8")
    except FileNotFoundError:
        clp["ap"].error("MH BMC needs 'cbmc' from the CPROVER tools on "
                        "your PATH")

    mh = Message_Handler("bmc")
    mh.show_context = not options.brief
    mh.show_style   = False
    mh.show_checks  = True
    mh.autofix      = False

    bmc_backend = MH_BMC(options)
    command_line.execute(mh, options, {}, bmc_backend)
Ejemplo n.º 6
0
def cfg_parser_main():
    # pylint: disable=import-outside-toplevel
    from argparse import ArgumentParser
    # pylint: enable=import-outside-toplevel

    ap = ArgumentParser()
    ap.add_argument("file")
    ap.add_argument("--no-tb",
                    action="store_true",
                    default=False,
                    help="Do not show debug-style backtrace")
    options = ap.parse_args()

    mh = Message_Handler("debug")
    mh.sort_messages = False
    mh.colour = False

    sanity_test(mh, options.file, not options.no_tb)

    mh.summary_and_exit()
Ejemplo n.º 7
0
def main_handler():
    clp = command_line.create_basic_clp()

    clp["output_options"].add_argument(
        "--worst-offenders",
        default=10,
        type=int,
        help=("Produce a table of the worst offenders for each metric."
              " By default this is 10; setting it to 0 disables this"
              " feature."))

    clp["output_options"].add_argument(
        "--ci",
        default=False,
        action="store_true",
        help=("Do not print any metrics report, only notify about violations."
              "This is the intended way to run in a CI environment."))

    clp["output_options"].add_argument(
        "--text",
        default=None,
        metavar="FILE",
        help=("Print plain-text metrics summary to the given file. By"
              " default we print the summary to standard output."))

    clp["output_options"].add_argument(
        "--html",
        default=None,
        metavar="FILE",
        help=("Write HTML metrics report to the file."))

    clp["output_options"].add_argument(
        "--portable-html",
        default=False,
        action="store_true",
        help=("Use assets/stylesheets from the web instead of "
              "the local MISS_HIT install."))

    clp["output_options"].add_argument(
        "--json",
        default=None,
        metavar="FILE",
        help=("Create JSON metrics report in the given file."))

    options = command_line.parse_args(clp)

    if options.text:
        if os.path.exists(options.text) and not os.path.isfile(options.text):
            clp["ap"].error("cannot write metrics to %s, it exists and is"
                            " not a file" % options.text)
        if options.html or options.json:
            clp["ap"].error("the text option is mutually exclusive with other"
                            " output options")

    if options.html:
        if os.path.exists(options.html) and not os.path.isfile(options.html):
            clp["ap"].error("cannot write metrics to %s, it exists and is"
                            " not a file" % options.text)
        if options.text or options.json:
            clp["ap"].error("the html option is mutually exclusive with other"
                            " output options")

    if options.json:
        if os.path.exists(options.json) and not os.path.isfile(options.json):
            clp["ap"].error("cannot write metrics to %s, it exists and is"
                            " not a file" % options.text)
        if options.text or options.html:
            clp["ap"].error("the json option is mutually exclusive with other"
                            " output options")

    if options.ci and (options.text or options.html or options.json):
        clp["ap"].error("the CI mode and and text/html/json options are"
                        "mutually exclusive")

    if options.worst_offenders < 0:
        clp["ap"].error("the worst-offender option cannot be negative")

    mh = Message_Handler("metric")
    mh.show_context = not options.brief
    mh.show_style   = False
    mh.autofix      = False

    metric_backend = MH_Metric(options)
    command_line.execute(mh, options, {}, metric_backend)
Ejemplo n.º 8
0
def main_handler():
    rule_set = get_rules()
    clp = command_line.create_basic_clp()

    clp["ap"].add_argument("--fix",
                           action="store_true",
                           default=False,
                           help=("Automatically fix issues where the fix"
                                 " is obvious"))

    clp["ap"].add_argument("--process-slx",
                           action="store_true",
                           default=False,
                           help=("Style-check (but not yet auto-fix) code"
                                 " inside SIMULINK models. This option is"
                                 " temporary, and will be removed in"
                                 " future once the feature is good enough"
                                 " to be enabled by default."))

    # Extra output options
    clp["output_options"].add_argument(
        "--html", default=None, help="Write report to given file as HTML")
    clp["output_options"].add_argument("--json",
                                       default=None,
                                       help="Produce JSON report")
    clp["output_options"].add_argument(
        "--no-style",
        action="store_true",
        default=False,
        help="Don't show any style message, only show warnings and errors.")

    # Debug options
    clp["debug_options"].add_argument(
        "--debug-dump-tree",
        default=None,
        metavar="FILE",
        help="Dump text-based parse tree to given file")
    clp["debug_options"].add_argument("--debug-validate-links",
                                      action="store_true",
                                      default=False,
                                      help="Debug option to check AST links")

    style_option = clp["ap"].add_argument_group("rule options")

    # Add any parameters from rules
    for rule_kind in rule_set:
        for rule in rule_set[rule_kind]:
            rule_params = getattr(rule, "parameters", None)
            if not rule_params:
                continue
            for p_name in rule_params:
                style_option.add_argument("--" + p_name, **rule_params[p_name])

    style_option.add_argument("--copyright-entity",
                              metavar="STR",
                              default=[],
                              nargs="+",
                              help=("Add (company) name to check for in "
                                    "Copyright notices. Can be specified "
                                    "multiple times."))

    options = command_line.parse_args(clp)

    if options.html:
        if options.json:
            clp["ap"].error("Cannot produce JSON and HTML at the same time")
        if os.path.exists(options.html) and not os.path.isfile(options.html):
            clp["ap"].error("Cannot write to %s: it is not a file" %
                            options.html)
        mh = HTML_Message_Handler("style", options.html)
    elif options.json:
        if os.path.exists(options.json) and not os.path.isfile(options.json):
            clp["ap"].error("Cannot write to %s: it is not a file" %
                            options.json)
        mh = JSON_Message_Handler("style", options.json)
    else:
        mh = Message_Handler("style")

    mh.show_context = not options.brief
    mh.show_style = not options.no_style
    mh.autofix = options.fix

    extra_options = {
        "fd_tree": None,
        "rule_set": rule_set,
    }

    if options.debug_dump_tree:
        extra_options["fd_tree"] = open(options.debug_dump_tree, "w")

    style_backend = MH_Style()
    command_line.execute(mh, options, extra_options, style_backend,
                         options.process_slx)

    if options.debug_dump_tree:
        extra_options["fd_tree"].close()
Ejemplo n.º 9
0
def main_handler():
    clp = command_line.create_basic_clp(
        epilog=("Remember to carefully review any code changes this tool"
                " makes, as copyright notices are generally considered to"
                " be quite important."))

    clp["ap"].add_argument("--process-slx",
                           action="store_true",
                           default=False,
                           help=("Update copyright notices inside Simulink"
                                 " models. This option is temporary, and"
                                 " will be removed in future once the"
                                 " feature is good enough to be enabled"
                                 " by default."))

    c_actions = clp["ap"].add_argument_group("copyright action")
    c_actions = c_actions.add_mutually_exclusive_group(required=True)
    c_actions.add_argument("--update-year",
                           action="store_true",
                           default=False,
                           help=("Update the end year in copyright notices for"
                                 " the primary copyright holder to the current"
                                 " year."))
    c_actions.add_argument("--merge",
                           action="store_true",
                           default=False,
                           help=("Merge all non-3rd party copyright notices"
                                 " into one for the primary copyright holder"))
    c_actions.add_argument("--change-entity",
                           default=None,
                           metavar="OLD_COPYRIGHT_HOLDER",
                           help=("Change notices from the specified copyright"
                                 " holder into the primary copyright holder."))
    c_actions.add_argument("--add-notice",
                           action="store_true",
                           default=False,
                           help=("Add a copyright notice to files that do not"
                                 " have one yet."))

    c_data = clp["ap"].add_argument_group("copyright data")
    c_data.add_argument("--year",
                        default=datetime.datetime.now().year,
                        type=int,
                        help=("The current year (by default this is"
                              " %(default)s)"))
    c_data.add_argument("--primary-entity",
                        default=None,
                        metavar="COPYRIGHT_HOLDER",
                        help=("The primary copyright entity."))
    c_data.add_argument("--template-range",
                        default="(c) Copyright %(ystart)u-%(yend)u %(org)s",
                        metavar="TEMPLATE_TEXT",
                        help=("Text template to use for a copyright notice"
                              " with a year range. default: '%(default)s'"))
    c_data.add_argument("--template",
                        default="(c) Copyright %(yend)u %(org)s",
                        metavar="TEMPLATE_TEXT",
                        help=("Text template to use for a copyright notice"
                              " with a single year. default: '%(default)s'"))

    options = command_line.parse_args(clp)

    # Sanity check year
    if options.year < 1900:  # pragma: no cover
        clp["ap"].error("year must be at lest 1900")
    elif options.year >= 10000:  # pragma: no cover
        clp["ap"].error("I am extremely concerned that this tool is still"
                        " useful after 8000 years, stop what you're doing"
                        " and change programming language NOW.")

    mh = Message_Handler("copyright")

    mh.show_context = not options.brief
    mh.show_style   = False
    mh.show_checks  = False
    mh.autofix      = True

    copyright_backend = MH_Copyright()
    command_line.execute(mh, options, {},
                         copyright_backend,
                         options.process_slx)
Ejemplo n.º 10
0
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("file_before")
    ap.add_argument("file_after")

    ap.add_argument("--kdiff3",
                    help="Use KDiff3 to show a visual diff",
                    action="store_true",
                    default=False)

    ap.add_argument("--allow-weird-names",
                    help=("Permit file names not ending in .slx (use at "
                          "your own risk)"),
                    action="store_true",
                    default=False)

    options = ap.parse_args()

    for item in (options.file_before, options.file_after):
        if not os.path.isfile(item):
            ap.error("%s is not a file" % item)
        elif not item.endswith(".slx") and not options.allow_weird_names:
            ap.error("%s is not a modern (slx) Simulink model")

    mh = Message_Handler("diff")

    n_before = load_file(mh, options.file_before)
    n_after = load_file(mh, options.file_after)

    code_blocks = {}

    for side in ("before", "after"):
        n_root = n_before if side == "before" else n_after
        for n_block in n_root.iter_all_blocks():
            if not isinstance(n_block, s_ast.Matlab_Function):
                continue
            name = n_block.local_name()
            if name not in code_blocks:
                code_blocks[name] = {"before": None, "after": None}
            code_blocks[name][side] = n_block.get_text()

    first = True

    for name in sorted(code_blocks):
        before = code_blocks[name]["before"]
        after = code_blocks[name]["after"]

        if before == after:
            continue

        if first:
            first = False
        else:
            print()

        print("Difference in MATLAB Code block '%s'" % name)
        if before is None:
            if options.kdiff3:
                with tempfile.TemporaryDirectory() as dirname:
                    with open(os.path.join(dirname, "before"), "w") as fd:
                        pass
                    with open(os.path.join(dirname, "after"), "w") as fd:
                        fd.write(after)
                    cmd = "kdiff3 %s %s" % (os.path.join(
                        dirname, "before"), os.path.join(dirname, "after"))
                    os.system(cmd)
            else:
                print("NEW block containing:")
                print("=" * 78)
                print(before)
                print("=" * 78)
        elif after is None:
            print("DELETED block")
        else:
            if options.kdiff3:
                with tempfile.TemporaryDirectory() as dirname:
                    with open(os.path.join(dirname, "before"), "w") as fd:
                        fd.write(before)
                    with open(os.path.join(dirname, "after"), "w") as fd:
                        fd.write(after)
                    cmd = "kdiff3 %s %s" % (os.path.join(
                        dirname, "before"), os.path.join(dirname, "after"))
                    os.system(cmd)
            else:
                print("CHANGED block:")
                print("=" * 78)
                print("\n".join(
                    difflib.unified_diff(before.splitlines(),
                                         after.splitlines(),
                                         fromfile=options.file_before,
                                         tofile=options.file_after)))
                print("=" * 78)

    return 0