def examine_fortran(self, subject: FortranSource): issues: List[Issue] = [] candidates: List[Fortran2003.StmtBase] = [] # Component variables candidates.extend(subject.find_all( Fortran2003.Data_Component_Def_Stmt)) # Variable declaration candidates.extend(subject.find_all(Fortran2003.Type_Declaration_Stmt)) for candidate in candidates: problem = 'Use of dimension attribute for {name}.' attributes = candidate.items[1] if attributes is None: continue cannon_attr = list( str(item).lower().replace(' ', '') for item in attributes.items) argument_def = 'intent(in)' in cannon_attr \ or 'intent(out)' in cannon_attr \ or 'intent(inout)' in cannon_attr if any(x.startswith('dimension') for x in cannon_attr): for variable in candidate.items[2].items: name = str(variable.items[0]) message = problem.format(name=name) line_number = candidate.item.span[0] issues.append(Issue(message, line=line_number)) issues.sort(key=lambda x: (x.filename, x.line, x.description)) return issues
def examine_fortran(self, subject: FortranSource) -> List[Issue]: issues = [] for exit in subject.find_all(Fortran2003.Exit_Stmt): if exit.items[1] is None: issues.append( Issue( 'Usage of "exit" without label indicating ' 'which "do" construct is being exited ' 'from.', line=exit.item.span[0])) # Above doesn't catch exits in inline if statements for statement in subject.find_all(Fortran2003.If_Stmt): action = statement.items[1] if type(action ) == Fortran2003.Exit_Stmt and action.items[1] is None: issues.append( Issue( 'Usage of "exit" without label indicating ' 'which "do" construct is being exited ' 'from.', line=statement.item.span[0])) return issues
def examine_fortran(self, subject: FortranSource) -> List[Issue]: issues = [] for statement in subject.find_all(Fortran2003.Use_Stmt): print ("statement = ", statement) for statement in subject.find_all(Fortran2003.Data_Component_Def_Stmt): print ("statement = ", statement) for statement in subject.find_all(Fortran2003.Proc_Component_Def_Stmt): print ("statement = ", statement) for statement in subject.find_all(Fortran2003.Procedure_Declaration_Stmt): print ("statement = ", statement) for statement in subject.find_all(Fortran2003.Type_Declaration_Stmt): print ("statement = ", statement) print ("text = ", subject.get_text()) return issues
def test_find_all(self) -> None: """ Checks that finding all occurrences of a source part works. """ reader = SourceStringReader(self._MULTI_PROC_MODULE) unit_under_test = FortranSource(reader) wanted = fparser.two.Fortran2003.Module_Subprogram result = unit_under_test.find_all(wanted) assert str(next(result).content[0].items[1]) == 'one' assert str(next(result).content[0].items[1]) == 'two' with pytest.raises(StopIteration): next(result)
def examine_fortran(self, subject: FortranSource) -> List[Issue]: issues: List[Issue] = [] candidates: List[Fortran2003.Base] = [] # Component variables candidates.extend(subject.find_all( Fortran2003.Data_Component_Def_Stmt)) # Component Procedure candidates.extend(subject.find_all( Fortran2003.Proc_Component_Def_Stmt)) # Procedure declaration candidates.extend( subject.find_all(Fortran2003.Procedure_Declaration_Stmt)) # Variable declaration candidates.extend(subject.find_all(Fortran2003.Type_Declaration_Stmt)) for candidate in candidates: if isinstance( candidate, # Is variable (Fortran2003.Data_Component_Def_Stmt, Fortran2003.Type_Declaration_Stmt)): type_spec: Fortran2003.Intrinsic_Type_Spec = candidate.items[0] kind_selector: Fortran2003.Kind_Selector = type_spec.items[1] if isinstance(kind_selector, Fortran2003.Kind_Selector): data_type: str = type_spec.items[0].lower() kind: str = kind_selector.string.strip('()') match = self._patterns[data_type].match(kind) if match is None: entity_declaration = candidate.items[2] message = self._ISSUE_TEMPLATE.format( type=data_type, kind=kind, name=entity_declaration, pattern=self._patterns[data_type].pattern) issues.append( Issue(message, line=candidate.item.span[0])) issues.sort(key=lambda x: (x.filename, x.line, x.description)) return issues
def examine_fortran(self, subject: FortranSource) -> List[Issue]: issues = [] for statement in subject.find_all(Fortran2003.Use_Stmt): module = statement.items[2] onlies = statement.items[4] if str(module).lower() not in self._ignore: if onlies is None: description = 'Usage of "{module}" without "only" clause.' issues.append(Issue(description.format(module=module), line=statement.item.span[0])) return issues
def examine_fortran(self, subject: FortranSource) -> List[Issue]: issues = [] for statement in subject.find_all(Fortran2003.Use_Stmt): module = statement.items[2] if str(module).lower() in self._INTRINSICS: nature = statement.items[0] if nature is None or nature.string.lower() != 'intrinsic': description = 'Usage of intrinsic module "{module}" ' \ 'without "intrinsic" clause.' issues.append( Issue(description.format(module=module), line=statement.item.span[0])) return issues
def examine_fortran(self, subject: FortranSource) -> List[Issue]: issues = [] # Collect all variable declarations declarations: List[Fortran2003.Type_Declaration_Stmt] = list( subject.find_all(Fortran2003.Type_Declaration_Stmt)) # keep only the ones in subroutines declarations = [ declaration for declaration in declarations if isinstance( declaration.parent.parent, Fortran2003.Subroutine_Subprogram) ] for declaration in declarations: type_spec = declaration.items[0] # If not a character, no concern if not type_spec.items[0] == "CHARACTER": continue param_value = type_spec.items[1] # This might be a length selector, if so get the param value if isinstance(param_value, Fortran2003.Length_Selector): param_value = param_value.items[1] # If not an auto length, no concern if not param_value.string == "*": continue attr_spec_list = declaration.items[1] # If no attributes specified, no concern if attr_spec_list is None: continue # Get intent attr and not other attributes intent_attr = None for item in attr_spec_list.items: if isinstance(item, Fortran2003.Intent_Attr_Spec): intent_attr = item break # If no intent, no conecern # Ensuring arguments specify intent should be enforced elsewhere if intent_attr is None: continue # Intent in, no conern if intent_attr.items[1].string == "IN": continue issues.append( Issue(self._message(declaration.items[2].string, intent_attr.items[1]), line=declaration.item.span[0])) return issues
def examine_fortran(self, subject: FortranSource): issues: List[Issue] = [] candidates: List[Fortran2003.StmtBase] = [] # Component variables candidates.extend(subject.find_all( Fortran2003.Data_Component_Def_Stmt)) # Component Procedure candidates.extend(subject.find_all( Fortran2003.Proc_Component_Def_Stmt)) # Procedure declaration candidates.extend( subject.find_all(Fortran2003.Procedure_Declaration_Stmt)) # Variable declaration candidates.extend(subject.find_all(Fortran2003.Type_Declaration_Stmt)) return_variable = '' for candidate in candidates: if isinstance( candidate, # Is variable (Fortran2003.Data_Component_Def_Stmt, Fortran2003.Type_Declaration_Stmt)): if isinstance(candidate.parent.parent, Fortran2003.Function_Subprogram): # Is contained in a function function_block: Fortran2003.Function_Subprogram \ = candidate.parent.parent statement = None for thing in function_block.children: if isinstance(thing, Fortran2003.Function_Stmt): statement = thing break if statement is None: message = "Malformed parse tree: Function subprogram" \ " without Function statement" raise Exception(message) suffix = statement.items[3] if isinstance(suffix, Fortran2003.Suffix): if isinstance(suffix.items[0], Fortran2003.Name): # Is return variable return_variable = str(suffix.items[0]) problem = 'Declaration of pointer "{name}" without initialisation.' attributes = candidate.items[1] if attributes is None: continue cannon_attr = list( str(item).lower().replace(' ', '') for item in attributes.items) argument_def = 'intent(in)' in cannon_attr \ or 'intent(out)' in cannon_attr \ or 'intent(inout)' in cannon_attr if 'pointer' in cannon_attr and not argument_def: for variable in candidate.items[2].items: if isinstance( candidate, # Is variable (Fortran2003.Data_Component_Def_Stmt, Fortran2003.Type_Declaration_Stmt)): name = str(variable.items[0]) if name == return_variable: continue # Return variables cannot be initialised. init = variable.items[3] if init is None: message = problem.format(name=name) line_number = candidate.item.span[0] issues.append(Issue(message, line=line_number)) elif isinstance( candidate, # Is procedure (Fortran2003.Proc_Component_Def_Stmt, Fortran2003.Procedure_Declaration_Stmt)): name = str(variable) if isinstance(variable, Fortran2003.Name): line_number = candidate.item.span[0] message = problem.format(name=name) issues.append(Issue(message, line=line_number)) else: message \ = f"Unexpected source element: {repr(candidate)}" raise Exception(message) issues.sort(key=lambda x: (x.filename, x.line, x.description)) return issues