def process_wp(cls, wp): # Create lexer lexer = MATLAB_Lexer(wp.mh, wp.get_content(), wp.filename, wp.blockname) if wp.cfg.octave: lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False if len(lexer.text.strip()) == 0: return MH_Trace_Result(wp) # Create parse tree try: parser = MATLAB_Parser(wp.mh, lexer, wp.cfg) n_cu = parser.parse_file() n_ep = get_enclosing_ep(wp.filename) except Error: return MH_Trace_Result(wp) visitor = Function_Visitor(wp.in_test_dir, wp.mh, n_cu, n_ep) n_cu.visit(None, visitor, "Root") # Return results return MH_Trace_Result(wp, visitor.tracing)
def process_wp(cls, wp): # Create lexer lexer = MATLAB_Lexer(wp.mh, wp.get_content(), wp.filename, wp.blockname) if wp.cfg.octave: lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False if len(lexer.text.strip()) == 0: return MH_BMC_Result(wp) # Create parse tree and translate try: parser = MATLAB_Parser(wp.mh, lexer, wp.cfg) n_tree = parser.parse_file() gst = compile_file(wp.mh, n_tree) except Error: return MH_BMC_Result(wp) new_filename = wp.filename.replace(".m", ".json_symtab") with open(new_filename, "w") as fd: json.dump(gst.to_json(), fd, indent=2) # wp.mh.info(n_tree.loc(), # "wrote goto symbol table to %s" % new_filename) analyze(wp.mh, new_filename, lexer, n_tree) if not wp.options.keep: os.unlink(new_filename) return MH_BMC_Result(wp)
def process_wp(cls, wp): # Create lexer lexer = MATLAB_Lexer(wp.mh, wp.get_content(), wp.filename, wp.blockname) if wp.cfg.octave: lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False if len(lexer.text.strip()) == 0: return MH_Lint_Result(wp) # Create parse tree try: parser = MATLAB_Parser(wp.mh, lexer, wp.cfg) parser.parse_file() except Error: return MH_Lint_Result(wp) return MH_Lint_Result(wp)
def process_wp(cls, wp): # Create lexer lexer = MATLAB_Lexer(wp.mh, wp.get_content(), wp.filename, wp.blockname) if wp.cfg.octave: lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False if len(lexer.text.strip()) == 0: return MH_Lint_Result(wp) # Create parse tree try: parser = MATLAB_Parser(wp.mh, lexer, wp.cfg) n_cu = parser.parse_file() except Error: return MH_Lint_Result(wp) # Check compilation units for shadowing a built-in base_name = os.path.splitext(n_cu.name)[0] dir_name = os.path.basename( os.path.dirname(pathutil.abspath(wp.filename))) if wp.cfg.active("builtin_shadow") and \ base_name in BUILTIN_FUNCTIONS and \ not (dir_name.startswith("+") or dir_name.startswith("@")): wp.mh.check( n_cu.loc(), "this file shadows built-in %s which is very naughty" % base_name, "high") # Initial checks n_cu.visit(None, Stage_1_Linting(wp.mh), "Root") # First pass of semantic analysis entrypoint = cfg_tree.get_entry_point(wp.options.entry_point) sem = sem_pass_1(wp.mh, entrypoint, n_cu) return MH_Lint_Result(wp, sem)
def process_wp(cls, wp): if wp.blockname is None: full_name = wp.filename else: full_name = wp.filename + "/" + wp.blockname metrics = { full_name: { "errors" : False, "metrics" : {}, "functions" : {}, "disabled" : set(m for m in config.METRICS if not wp.cfg.metric_enabled(m)) } } justifications = {} # Create lexer lexer = MATLAB_Lexer(wp.mh, wp.get_content(), wp.filename, wp.blockname) if wp.cfg.octave: lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False # We're dealing with an empty file here. Lets just not do anything if len(lexer.text.strip()) == 0: return MH_Metric_Result(wp, metrics) # Create parse tree try: parser = MATLAB_Parser(wp.mh, lexer, wp.cfg) parse_tree = parser.parse_file() except Error: metrics[wp.filename]["errors"] = True return MH_Metric_Result(wp, metrics) # Collect file metrics if wp.cfg.metric_enabled("file_length"): metrics[full_name]["metrics"]["file_length"] = { "measure" : lexer.line_count(), "limit" : None, "reason" : None, "tickets" : set(), } # Check+justify file metrics justifications = {full_name : get_file_justifications(wp.mh, parse_tree)} for file_metric in config.FILE_METRICS: check_metric(wp.mh, wp.cfg, lexer.get_file_loc(), file_metric, metrics[full_name]["metrics"], justifications[full_name]) # Collect, check, and justify function metrics metrics[full_name]["functions"] = get_function_metrics(wp.mh, wp.cfg, parse_tree) # Complain about unused justifications warn_unused_justifications(wp.mh, parse_tree) return MH_Metric_Result(wp, metrics)
def process_wp(cls, wp): rule_set = wp.extra_options["rule_set"] autofix = wp.options.fix fd_tree = wp.extra_options["fd_tree"] debug_validate_links = wp.options.debug_validate_links # Build rule library rule_lib = build_library(wp.cfg, rule_set) # Load file content content = wp.get_content() # Create lexer lexer = MATLAB_Lexer(wp.mh, content, wp.filename, wp.blockname) if wp.cfg.octave: lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False # We're dealing with an empty file here. Lets just not do anything if len(lexer.text.strip()) == 0: return MH_Style_Result(wp) # Stage 1 - rules around the file itself for rule in rule_lib["on_file"]: rule.apply(wp.mh, wp.cfg, lexer.filename, lexer.text, lexer.context_line) # Stage 2 - rules around raw text lines for line_no, line in enumerate(lexer.context_line, 1): for rule in rule_lib["on_line"]: rule.apply(wp.mh, wp.cfg, lexer.filename, line_no, line) # Tabs are just super annoying, and they require special # treatment. There is a known but obscure bug here, in that tabs # in strings are replaced as if they were part of normal # text. This is probably not intentional. For example: # # "a<tab>b" # "a<tab>b" # # Will right now come out as # # "a b" # " a b" # # This is probably not correct. Fixing this is will require a very # different kind of lexing (which I am not in the mood for, I have # suffered enough to deal with ') or a 2-pass solution (which is # slow): first we lex and then fix up tabs inside tokens; and then # we do the global replacement and lex again before we proceed. if autofix: lexer.correct_tabs(wp.cfg.style_config["tab_width"]) # Create tokenbuffer try: tbuf = Token_Buffer(lexer, wp.cfg) except Error: # If there are lex errors, we can stop here return MH_Style_Result(wp) # Create parse tree try: parser = MATLAB_Parser(wp.mh, tbuf, wp.cfg) parse_tree = parser.parse_file() # Check naming (we do this after parsing, not during, # since we may need to re-write functions without end). parse_tree.sty_check_naming(wp.mh, wp.cfg) if debug_validate_links: tbuf.debug_validate_links() if fd_tree: fd_tree.write("-- Parse tree for %s\n" % wp.filename) parse_tree.pp_node(fd_tree) fd_tree.write("\n\n") except Error: parse_tree = None # Stage 3 - rules around individual tokens stage_3_analysis(mh=wp.mh, cfg=wp.cfg, tbuf=tbuf, is_embedded=isinstance( wp, work_package.Embedded_MATLAB_WP), fixed=parse_tree is not None) # Stage 4 - rules involving the parse tree # TODO # Possibly re-write the file, with issues fixed if autofix: if not parse_tree: wp.mh.error(lexer.get_file_loc(), "file is not auto-fixed because it contains" " parse errors", fatal=False) else: # TODO: call modify() wp.write_modified(tbuf.replay()) # Return results return MH_Style_Result(wp)
def process_wp(cls, wp): # Load file content content = wp.get_content() # Create lexer lexer = MATLAB_Lexer(wp.mh, content, wp.filename, wp.blockname) if wp.cfg.octave: lexer.set_octave_mode() if not wp.cfg.pragmas: # pragma: no cover lexer.process_pragmas = False # Deal with command-line options, setting up three variables: # * action - what to do # * primary_entity - main entity # * templates - how to write copyright notices templates = { "single": wp.options.template, "range": wp.options.template_range } primary_entity = get_primary_entity(wp.options, wp.cfg) if not primary_entity: wp.mh.warning( lexer.get_file_loc(), "unable to determine primary copyright entity," " skipping this file") return MH_Copyright_Result(wp, False) if wp.options.update_year: action = "update_year" elif wp.options.merge: action = "merge" elif wp.options.change_entity is not None: action = "change_entity" elif wp.options.add_notice: action = "add_notice" else: raise ICE("none of the action are set") allowed_entities = (wp.cfg.style_config["copyright_entity"] | set([primary_entity])) # We're dealing with an empty file here. Lets just not do anything if len(lexer.text.strip()) == 0: return MH_Copyright_Result(wp, False) # Parse try: tbuf = Token_Buffer(lexer, wp.cfg) parser = MATLAB_Parser(wp.mh, tbuf, wp.cfg) parse_tree = parser.parse_file() parse_docstrings(wp.mh, wp.cfg, parse_tree, tbuf) except Error: # pragma: no cover return MH_Copyright_Result(wp, False) # Determine the docstring of the primary entity. We use the # script/class docstring, if it exists and contains copyright # info. Otherwise we use the compilation unit's docstring # (i.e. file header). The style checker worries about the case # where we have copyright in more than one location. n_docstring = None if isinstance(parse_tree, Class_File): n_docstring = parse_tree.n_classdef.n_docstring elif isinstance(parse_tree, Function_File): n_docstring = parse_tree.l_functions[0].n_docstring if n_docstring is None or not n_docstring.copyright_info: n_docstring = parse_tree.n_docstring # Note that n_docstring could be None at this point, so we do # need to deal with that correctly. # Set up line -> Copyright_Info map cinfos = {} if n_docstring: for cinfo in n_docstring.copyright_info: if cinfo.t_comment.location.line in cinfos: raise ICE("docstring with duplicate line (%u)" % cinfo.t_comment.location.line) else: cinfos[cinfo.t_comment.location.line] = cinfo # The merge action requires the copyright notice to be # grouped. Enforce this now. if action == "merge" and \ not (n_docstring.all_copyright_in_one_block(allowed_entities) or n_docstring.all_copyright_in_one_block()): wp.mh.error(n_docstring.loc(), "cannot merge entries in this docstring as they" " are not all next to each other", fatal=False) return MH_Copyright_Result(wp, False) # Perform actions action_taken = False lines = copy(lexer.context_line) try: if action == "update_year": new_year = wp.options.year for line_no, cinfo in cinfos.items(): ystart, yend = cinfo.get_range() if cinfo.get_org() != primary_entity: continue if yend <= new_year: new_range = (ystart, new_year) replace_line(lines, line_no, cinfo.is_block_comment(), templates, cinfo.get_copy_notice(), primary_entity, new_range) action_taken = True else: wp.mh.error(cinfo.loc_yend(), "end year is later than %s" % new_year) elif action == "merge": merged_line = None merged_line_is_block = None killed_lines = [] new_range = None for line_no in sorted(cinfos): cinfo = cinfos[line_no] ystart, yend = cinfo.get_range() if cinfo.get_org() not in allowed_entities: continue if cinfo.get_org() != primary_entity or ystart == yend: action_taken = True if ystart > yend: wp.mh.error(cinfo.loc_ystart(), "initial year is later than end year") if new_range is None: merged_line = line_no merged_line_is_block = cinfo.is_block_comment() merged_line_copy_notice = cinfo.get_copy_notice() new_range = cinfo.get_range() else: new_range = (min(ystart, new_range[0]), max(yend, new_range[1])) killed_lines.append(line_no) action_taken = True if action_taken: replace_line(lines, merged_line, merged_line_is_block, templates, merged_line_copy_notice, primary_entity, new_range) for line_no in reversed(killed_lines): del lines[line_no - 1] elif action == "change_entity": for line_no, cinfo in cinfos.items(): if cinfo.get_org() == wp.options.change_entity: replace_line(lines, line_no, cinfo.is_block_comment(), templates, cinfo.get_copy_notice(), primary_entity, cinfo.get_range()) action_taken = True elif action == "add_notice": # Only add copyright notices to files without any # notice. if len(cinfos) == 0: # Find the right place to add the notice. Right # now we only do this for the file header; so we # need to find it and append at the end; or create # a new one. action_taken = True if parse_tree.n_docstring: is_block, line_no = parse_tree.n_docstring.final_line() off = parse_tree.n_docstring.guess_docstring_offset() # Duplicate the last line lines = \ lines[:line_no] + \ [lines[line_no - 1]] + \ lines[line_no:] else: is_block = False line_no = 0 off = 1 lines = ["% POTATO", ""] + lines if wp.options.style == "c_first" or \ (wp.options.style == "dynamic" and not wp.cfg.octave): copy_notice = "(c) Copyright" else: copy_notice = "Copyright (c)" # Then overwrite it replace_line(lines, line_no + 1, is_block, templates, copy_notice, primary_entity, (wp.options.year, wp.options.year), offset=off) else: raise ICE("Unexpected action '%s'" % action) except Error: return MH_Copyright_Result(wp, False) if action_taken: wp.write_modified("\n".join(lines) + "\n") return MH_Copyright_Result(wp, True)