def _find_nodes(self, settings): pkgs = {pkg.name: pkg for pkg in self.project.packages} ws = settings.workspace if settings else None extractor = NodeExtractor(pkgs, self.environment, ws=ws, node_cache=self.node_cache, parse_nodes=self.parse_nodes) if self.parse_nodes and not CppAstParser is None: if settings is None: CppAstParser.set_library_path() db_dir = os.path.join(extractor.workspace, "build") if os.path.isfile(os.path.join(db_dir, "compile_commands.json")): CppAstParser.set_database(db_dir) else: CppAstParser.set_library_path(settings.cpp_parser_lib) CppAstParser.set_standard_includes(settings.cpp_includes) db_dir = settings.cpp_compile_db if (db_dir and os.path.isfile( os.path.join(db_dir, "compile_commands.json"))): CppAstParser.set_database(settings.cpp_compile_db) for pkg in self.project.packages: if not pkg.name in self.package_cache: extractor.find_nodes(pkg)
def _roscpp_analysis(self, node): self.log.debug("Parsing C++ files for node %s", node.id) parser = CppAstParser(workspace = self.workspace) for sf in node.source_files: self.log.debug("Parsing C++ file %s", sf.path) if parser.parse(sf.path) is None: self.log.warning("no compile commands for " + sf.path) node.source_tree = parser.global_scope # ----- queries after parsing, since global scope is reused --------------- self._query_comm_primitives(node, parser.global_scope) self._query_nh_param_primitives(node, parser.global_scope) self._query_param_primitives(node, parser.global_scope)
def extract_node(self, name, node_name, pkg_name, ns, ws, rossystem): pkg = Package(pkg_name) rospack = rospkg.RosPack() pkg.path = rospack.get_path(pkg_name) roscomponent = None #HAROS NODE EXTRACTOR node = Node(node_name, pkg, rosname=RosName(node_name)) srcdir = pkg.path[len(ws):] srcdir = os.path.join(ws, srcdir.split(os.sep, 1)[0]) bindir = os.path.join(ws, "build") #HAROS CMAKE PARSER parser = RosCMakeParser(srcdir, bindir, pkgs=[pkg]) model_str = "" if os.path.isfile(os.path.join(pkg.path, "CMakeLists.txt")): parser.parse(os.path.join(pkg.path, "CMakeLists.txt")) for target in parser.executables.itervalues(): if target.output_name == node_name: for file_in in target.files: full_path = file_in relative_path = full_path.replace( pkg.path + "/", "").rpartition("/")[0] file_name = full_path.rsplit('/', 1)[-1] source_file = SourceFile(file_name, relative_path, pkg) node.source_files.append(source_file) if node.language == "cpp": parser = CppAstParser(workspace=ws) analysis = RoscppExtractor(pkg, ws) if node.language == "py": parser = PyAstParser(workspace=ws) analysis = RospyExtractor(pkg, ws) #node.source_tree = parser.global_scope for sf in node.source_files: try: if parser.parse(sf.path) is not None: # ROS MODEL EXTRACT PRIMITIVES if node.language == "py": node_name = node_name.replace(".py", "") rosmodel = ros_model(pkg.name, node_name, node_name) roscomponent = ros_component(name, ns) try: self.extract_primitives(node, parser, analysis, rosmodel, roscomponent, pkg_name, node_name, node_name) # SAVE ROS MODEL model_str = rosmodel.save_model( self.args.model_path) except: pass except: pass if rossystem is not None and roscomponent is not None: rossystem.add_component(roscomponent) if self.args.output: print model_str
def launch(self): self.parse_arg() #FIND WORKSPACE: #Fixme: the env variable ROS_PACKAGE_PATH is not the best way to extract the workspace path ros_pkg_path = os.environ.get("ROS_PACKAGE_PATH") ws = ros_pkg_path[:ros_pkg_path.find("/src:")] #BONSAI PARSER parser = CppAstParser(workspace=ws) parser.set_library_path("/usr/lib/llvm-4.0/lib") parser.set_standard_includes( "/usr/lib/llvm-4.0/lib/clang/4.0.0/include") db_dir = os.path.join(ws, "build") if os.path.isfile(os.path.join(db_dir, "compile_commands.json")): parser.set_database(db_dir) if (self.args.node): self.extract_node(self.args.name, self.args.name, self.args.package_name, None, ws, None) if (self.args.launch): pkg = Package(self.args.package_name) rospack = rospkg.RosPack() pkg.path = rospack.get_path(self.args.package_name) relative_path = "launch/" for root, dirs, files in os.walk(pkg.path): for file in files: if file.endswith(self.args.name): relative_path = root.replace("/" + pkg.path, "") source = SourceFile(self.args.name, relative_path, pkg) pkgs = {pkg.id: pkg} launch_parser = LaunchParser(pkgs=pkgs) rossystem = ros_system(self.args.name.replace(".launch", "")) try: source.tree = launch_parser.parse(source.path) for node in source.tree.children: if isinstance(node, NodeTag): name = node.attributes["name"] node_name = node.attributes["type"] node_pkg = node.attributes["pkg"] try: ns = node.attributes["ns"] except: ns = None self.extract_node(name, node_name, node_pkg, ns, ws, rossystem) except LaunchParserError as e: print("Parsing error in %s:\n%s", source.path, str(e)) system_str = rossystem.save_model(self.args.model_path) if self.args.output: print system_str
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #THE SOFTWARE. import sys from bonsai.analysis import * from bonsai.cpp.clang_parser import CppAstParser # ----- Setup ------------------------------------------------------------------ if len(sys.argv) < 2: print "Please provide a file to be analysed." sys.exit(1) CppAstParser.set_library_path() parser = CppAstParser(workspace="examples/cpp") for i in xrange(1, len(sys.argv)): if parser.parse(sys.argv[i]) is None: print "No compile commands for file", sys.argv[i] sys.exit(1) # ----- Printing Program ------------------------------------------------------- print parser.global_scope.pretty_str() print "\n----------------------------------\n" # ----- Performing Queries ----------------------------------------------------- print "# QUERY FOR VARIABLE 'a'" for cppobj in (CodeQuery( parser.global_scope).all_references.where_name("a").get()): print "[{}:{}]".format(cppobj.line, cppobj.column), cppobj.pretty_str() print "[type]", cppobj.result print "[canon. type]", cppobj.canonical_type
def launch(self): self.parse_arg() if self.args.node: #FIND WORKSPACE: #Fixme: the env variable ROS_PACKAGE_PATH is not the best way to extract the workspace path ros_pkg_path = os.environ.get("ROS_PACKAGE_PATH") ws = ros_pkg_path[:ros_pkg_path.find("/src:")] #FIND PACKAGE PATH pkg = Package(self.args.package_name) rospack = rospkg.RosPack() pkg.path = rospack.get_path(self.args.package_name) #BONSAI PARSER parser = CppAstParser(workspace=ws) parser.set_library_path("/usr/lib/llvm-3.8/lib") parser.set_standard_includes( "/usr/lib/llvm-3.8/lib/clang/3.8.0/include") db_dir = os.path.join(ws, "build") if os.path.isfile(os.path.join(db_dir, "compile_commands.json")): parser.set_database(db_dir) #HAROS NODE EXTRACTOR analysis = NodeExtractor(pkg, env=dict(os.environ), ws=ws, node_cache=False, parse_nodes=True) node = Node(self.args.name, pkg, rosname=RosName(self.args.name)) srcdir = pkg.path[len(ws):] srcdir = os.path.join(ws, srcdir.split(os.sep, 1)[0]) bindir = os.path.join(ws, "build") #HAROS CMAKE PARSER parser = RosCMakeParser(srcdir, bindir, pkgs=[pkg]) parser.parse(os.path.join(pkg.path, "CMakeLists.txt")) for target in parser.executables.itervalues(): if target.output_name == self.args.name: for file_in in target.files: full_path = file_in relative_path = full_path.replace( pkg.path + "/", "").rpartition("/")[0] file_name = full_path.rsplit('/', 1)[-1] source_file = SourceFile(file_name, relative_path, pkg) node.source_files.append(source_file) parser = CppAstParser(workspace=ws) node.source_tree = parser.global_scope model_str = "" for sf in node.source_files: if parser.parse(sf.path) is None: print "File not found" else: # ROS MODEL EXTRACT PRIMITIVES rosmodel = ros_model(self.args.package_name, self.args.name, self.args.name) self.extract_primitives(node, parser.global_scope, analysis, rosmodel) # SAVE ROS MODEL model_str = rosmodel.save_model() if self.args.output: print model_str else: text_file = open(self.args.name + ".ros", "w") text_file.write(model_str) text_file.close()
from bonsai.analysis import * from bonsai.cpp.clang_parser import CppAstParser # ----- Setup ------------------------------------------------------------------ if len(sys.argv) < 2: print "Please provide a file to be analysed." sys.exit(1) v = "3.8" argi = 1 if sys.argv[1] == "-v": if len(sys.argv) < 4: print "Please provide a file to be analysed." sys.exit(1) v = sys.argv[2] argi = 3 CppAstParser.set_library_path(lib_path="/usr/lib/llvm-{v}/lib".format(v=v)) CppAstParser.set_standard_includes( "/usr/lib/llvm-{v}/lib/clang/{v}.0/include".format(v=v)) parser = CppAstParser(workspace = "examples/cpp") for i in xrange(argi, len(sys.argv)): if parser.parse(sys.argv[i]) is None: print "No compile commands for file", sys.argv[i] sys.exit(1) # ----- Printing Program ------------------------------------------------------- print parser.global_scope.pretty_str() print "\n----------------------------------\n" # ----- Performing Queries ----------------------------------------------------- print "# QUERY FOR VARIABLE 'a'" for cppobj in (CodeQuery(parser.global_scope).all_references .where_name("a").get()): print "[{}:{}]".format(cppobj.line, cppobj.column), cppobj.pretty_str()
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #THE SOFTWARE. import sys from bonsai.analysis import * from bonsai.cpp.clang_parser import CppAstParser # ----- Setup ------------------------------------------------------------------ files = [ "examples/cpp/multi_def/file1.cpp", "examples/cpp/multi_def/file2.cpp" ] CppAstParser.set_library_path() parser = CppAstParser() for filename in files: if parser.parse(filename) is None: print "No compile commands for file", filename sys.exit(1) # ----- Printing Program ------------------------------------------------------- print parser.global_scope.pretty_str() print "\n----------------------------------\n" # ----- Performing Queries ----------------------------------------------------- print "# QUERY FOR CALL 'add_ints'" for cppobj in (CodeQuery( parser.global_scope).all_calls.where_name("add_ints").get()): print "[{}:{}]".format(cppobj.line, cppobj.column), cppobj.pretty_str() print "[type]", cppobj.result print "[reference]", cppobj.reference or "unknown"