def _cache_file(self, src_path): """ Load the data from `self._xml_roots` for `src_path`, if it hasn't been already. """ # If we have not yet loaded this source file if src_path not in self._info_cache: # We only want to keep violations that show up in each xml source. # Thus, each time, we take the intersection. However, to do this # we must treat the first time as a special case and just add all # the violations from the first xml report. violations = None # A line is measured if it is measured in any of the reports, so # we take set union each time and can just start with the empty set measured = set() # Loop through the files that contain the xml roots for xml_document in self._xml_roots: line_nodes = self._get_src_path_line_nodes(xml_document, src_path) if line_nodes is None: continue # First case, need to define violations initially if violations is None: violations = set( Violation(int(line.get('number')), None) for line in line_nodes if int(line.get('hits', 0)) == 0) # If we already have a violations set, # take the intersection of the new # violations set and its old self else: violations = violations & set( Violation(int(line.get('number')), None) for line in line_nodes if int(line.get('hits', 0)) == 0 ) # Measured is the union of itself and the new measured measured = measured | set( int(line.get('number')) for line in line_nodes ) # If we don't have any information about the source file, # don't report any violations if violations is None: violations = set() self._info_cache[src_path] = (violations, measured)
def parse_reports(self, reports): """ Args: reports: list[str] - output from the report Return: A dict[Str:Violation] Violation is a simple named tuple Defined above """ violations_dict = defaultdict(list) for report in reports: xml_document = etree.fromstring("".join(report)) bugs = xml_document.findall(".//BugInstance") for bug in bugs: category = bug.get('category') short_message = bug.find('ShortMessage').text line = bug.find('SourceLine') if line.get('start') is None or line.get('end') is None: continue start = int(line.get('start')) end = int(line.get('end')) for line_number in range(start, end + 1): error_str = "{}: {}".format(category, short_message) violation = Violation(line_number, error_str) filename = GitPathTool.relative_path( line.get('sourcepath')) violations_dict[filename].append(violation) return violations_dict
def parse_reports(self, reports): """ Args: reports: list[str] - output from the report Return: A dict[Str:Violation] Violation is a simple named tuple Defined above """ violations_dict = defaultdict(list) for report in reports: output_lines = report.splitlines() for line in output_lines: match = self.cppcheck_expression.match(line) # Ignore any line that isn't matched # (for example, snippets from the source code) if match is not None: (cppcheck_src_path, line_number, message) = match.groups() violation = Violation(int(line_number), message) violations_dict[cppcheck_src_path].append(violation) return violations_dict
def parse_reports(self, reports): """ Args: reports: list[str] - output from the report Return: A dict[Str:Violation] Violation is a simple named tuple Defined above """ violations_dict = defaultdict(list) for report in reports: output_lines = report.split("\n") for output_line_number, line in enumerate(output_lines): match = self.pylint_expression.match(line) # Ignore any line that isn't matched # (for example, snippets from the source code) if match is not None: ( pylint_src_path, line_number, pylint_code, function_name, message, ) = match.groups() if pylint_code == self.dupe_code_violation: files_involved = self._process_dupe_code_violation( output_lines, output_line_number, message ) else: files_involved = [(pylint_src_path, line_number)] for violation in files_involved: pylint_src_path, line_number = violation # If we're looking for a particular source file, # ignore any other source files. if function_name: error_str = "{}: {}: {}".format( pylint_code, function_name, message ) else: error_str = f"{pylint_code}: {message}" violation = Violation(int(line_number), error_str) violations_dict[pylint_src_path].append(violation) return violations_dict
def violations(src_path: str) -> List[Violation]: """Return list of violations. Given the path to a .sql file, analyze it and return a list of violations (i.e. formatting or style issues). """ linter = Linter(config=FluffConfig.from_root()) linted_path = linter.lint_path(src_path, ignore_non_existent_files=True) result = [] for violation in linted_path.get_violations(): try: # Normal SQLFluff warnings message = f"{violation.rule_code()}: {violation.description}" except AttributeError: # Parse errors message = str(violation) result.append(Violation(violation.line_no, message)) return result
def parse_reports(self, reports): """ Args: reports: list[str] - output from the report Return: A dict[Str:Violation] Violation is a simple named tuple Defined above """ violations_dict = defaultdict(list) for report in reports: xml_document = etree.fromstring("".join(report)) files = xml_document.findall(".//file") for file_tree in files: for error in file_tree.findall('error'): line_number = error.get('line') error_str = "{}: {}".format(error.get('severity'), error.get('message')) violation = Violation(int(line_number), error_str) filename = GitPathTool.relative_path(file_tree.get('name')) violations_dict[filename].append(violation) return violations_dict
def violations(src_path): """Return list of violations. Given the path to a .sql file, analyze it and return a list of violations (i.e. formatting or style issues). :param src_path: :return: list of Violation """ linter = Linter(config=FluffConfig()) linted_path = linter.lint_path(src_path, ignore_non_existent_files=True) result = [] for violation in linted_path.get_violations(): try: # Normal SQLFluff warnings message = violation.description except AttributeError: # Parse errors message = str(violation) result.append(Violation(violation.line_no(), message)) return result
def parse_reports(self, reports): """ Args: reports: list[str] - output from the report Return: A dict[Str:Violation] Violation is a simple named tuple Defined above """ violations_dict = defaultdict(list) for report in reports: xml_document = etree.fromstring("".join(report)) node_files = xml_document.findall(".//file") for node_file in node_files: for error in node_file.findall("violation"): line_number = error.get("beginline") error_str = "{}: {}".format(error.get("rule"), error.text.strip()) violation = Violation(int(line_number), error_str) filename = GitPathTool.relative_path(node_file.get("name")) filename = filename.replace(os.sep, "/") violations_dict[filename].append(violation) return violations_dict
def violations(self, src_path): """Return list of violations. Given the path to a .sql file, analyze it and return a list of violations (i.e. formatting or style issues). :param src_path: :return: list of Violation """ linter = get_linter(get_config()) linter.output_func = None linted_path = linter.lint_path(src_path) result = [] for violation in linted_path.files[0].violations: try: # Normal SQLFluff warnings message = violation.description except AttributeError: # Parse errors message = str(violation) result.append(Violation(violation.line_no(), message)) return result
def _cache_file(self, src_path): """ Load the data from `self._xml_roots` for `src_path`, if it hasn't been already. """ # If we have not yet loaded this source file if src_path not in self._info_cache: # We only want to keep violations that show up in each xml source. # Thus, each time, we take the intersection. However, to do this # we must treat the first time as a special case and just add all # the violations from the first xml report. violations = None # A line is measured if it is measured in any of the reports, so # we take set union each time and can just start with the empty set measured = set() # Loop through the files that contain the xml roots for xml_document in self._xml_roots: if xml_document.findall(".[@clover]"): # see etc/schema/clover.xsd at https://bitbucket.org/atlassian/clover/src line_nodes = self._get_src_path_line_nodes_clover( xml_document, src_path) _number = "num" _hits = "count" elif xml_document.findall(".[@name]"): # https://github.com/jacoco/jacoco/blob/master/org.jacoco.report/src/org/jacoco/report/xml/report.dtd line_nodes = self._get_src_path_line_nodes_jacoco( xml_document, src_path) _number = "nr" _hits = "ci" else: # https://github.com/cobertura/web/blob/master/htdocs/xml/coverage-04.dtd line_nodes = self._get_src_path_line_nodes_cobertura( xml_document, src_path) _number = "number" _hits = "hits" if line_nodes is None: continue # First case, need to define violations initially if violations is None: violations = { Violation(int(line.get(_number)), None) for line in line_nodes if int(line.get(_hits, 0)) == 0 } # If we already have a violations set, # take the intersection of the new # violations set and its old self else: violations = violations & { Violation(int(line.get(_number)), None) for line in line_nodes if int(line.get(_hits, 0)) == 0 } # Measured is the union of itself and the new measured measured = measured | { int(line.get(_number)) for line in line_nodes } # If we don't have any information about the source file, # don't report any violations if violations is None: violations = set() self._info_cache[src_path] = (violations, measured)