def analyze_unit(unit: lal.AnalysisUnit) -> None: """Computes and displays the static call graph of some unit.""" if unit.root: if DEBUG: ada_visitor = AdaPrintVisitor(max_depth=20) ada_visitor.visit(unit.root) static_call_graph_visitor = SCG.StaticCallGraphVisitor( context=context, caller_being_defined=None, edges=dict(), nodes=dict()) static_call_graph_visitor.visit(unit.root) analysis_output = make_empty_analysis_output() component_types = analysis_output["component_types"] component_types.add(ontology.SOURCE_FUNCTION) component_types.add(ontology.MODULE) formats = analysis_output["formats"] formats.add(ADA_FORMAT) components = analysis_output["components"] # register all components and the files they live in for component_key in static_call_graph_visitor.nodes: component_node = static_call_graph_visitor.nodes[component_key] component = register_component(analysis_output, component_node, ontology.SOURCE_FUNCTION) file_ = register_ada_file( analysis_output, as_optional_file_identifier(get_node_file(component_node))) component.defined_in = file_ # add "mentions" for caller_key in static_call_graph_visitor.edges: caller_node = static_call_graph_visitor.nodes[caller_key] caller_identifier = ontology.SoftwareComponentIdentifier( get_node_identifier(caller_node)) for callee_key in static_call_graph_visitor.edges[caller_key]: callee_node = static_call_graph_visitor.nodes[callee_key] callee_identifier = ontology.SoftwareComponentIdentifier( get_node_identifier(callee_node)) callee = components[callee_identifier] caller = components[caller_identifier] caller.add_mention(callee) if DEBUG_TURTLE: output_as_turtle(analysis_output) else: output_using_scrapingtoolkit(analysis_output) else: print("No root found, diagnostics:") print(unit.diagnostics)
def visit_PackageBody(self, node: lal.PackageBody) -> None: self.generic_visit(node) name = node.f_package_name for token in node.tokens: trace_id = self.match_trace_token(token) if trace_id is not None: self.traceability.setdefault(get_node_identifier(name), []).append(trace_id)
def visit_SubpBody(self, node: lal.SubpBody) -> None: self.generic_visit(node) spec = node.f_subp_spec name = spec.f_subp_name for token in node.tokens: trace_id = self.match_trace_token(token) if trace_id: self.traceability.setdefault(get_node_identifier(name), []).append(trace_id)
def analyze_structure(unit: lal.AnalysisUnit) -> None: """Extracts traceability identifiers from subprograms.""" if not unit.root: return visitor = PS.StructureExtractor() visitor.visit(unit.root) analysis_output = visitor.packages for package, components in analysis_output.items(): Evidence.Add.SWCOMPONENT( identifier=get_node_identifier(package), title=escape(package.doc_name), componentType_identifier=ontology.MODULE, ) for component in components: Evidence.Add.SWCOMPONENT( identifier=get_node_identifier(component), subcomponentOf_identifier=get_node_identifier(package), )
def register_component( analysis_output: AnalysisOutput, component: GraphNode, component_type: ontology.ComponentTypeIdentifier, ) -> ontology.SoftwareComponent: """ Makes sure that the component is already present in the components dictionary. Adds it if necessary. """ components = analysis_output["components"] component_identifier = ontology.SoftwareComponentIdentifier( get_node_identifier(component)) if component_identifier not in components: components[component_identifier] = ontology.SoftwareComponent( identifier=component_identifier, # does not work because display names may contain special characters # title=SCG.get_node_display_name(component), # using this instead even though less ideal: title=component.doc_name, component_type=ontology.SOURCE_FUNCTION, uri=SOFTWARE_COMPONENT_NS[component_identifier], ) return components[component_identifier]