def generate(generator_arguments_file: str) -> List[str]: mapping = { "_idl.pyi.em": "_%s.pyi", } generated_files: List[str] = generate_files(generator_arguments_file, mapping) args = read_generator_arguments(generator_arguments_file) package_name = args["package_name"] # For __init__.pyi, it is required to output the exact same contents as # rosidl_python does. modules: Dict[str, Set[str]] = {} idl_content = IdlContent() for idl_tuple in args.get("idl_tuples", []): idl_parts = idl_tuple.rsplit(":", 1) assert len(idl_parts) == 2 idl_rel_path = pathlib.Path(idl_parts[1]) idl_stems = modules.setdefault(str(idl_rel_path.parent), set()) idl_stems.add(idl_rel_path.stem) locator = IdlLocator(*idl_parts) idl_file = parse_idl_file(locator) idl_content.elements += idl_file.content.elements for subfolder in modules.keys(): with open(os.path.join(args["output_dir"], subfolder, "__init__.pyi"), "w") as f: for idl_stem in sorted(modules[subfolder]): module_name = "_{}".format( convert_camel_case_to_lower_case_underscore(idl_stem)) f.write( f"from {package_name}.{subfolder}.{module_name} import " f"{idl_stem} as {idl_stem} # noqa: F401\n") return generated_files
def generate_rs(generator_arguments_file, typesupport_impls): args = read_generator_arguments(generator_arguments_file) package_name = args['package_name'] # expand init modules for each directory modules = {} idl_content = IdlContent() for idl_tuple in args.get('idl_tuples', []): idl_parts = idl_tuple.rsplit(':', 1) assert len(idl_parts) == 2 idl_rel_path = pathlib.Path(idl_parts[1]) idl_stems = modules.setdefault(str(idl_rel_path.parent), set()) idl_stems.add(idl_rel_path.stem) locator = IdlLocator(*idl_parts) idl_file = parse_idl_file(locator) idl_content.elements += idl_file.content.elements typesupport_impls = typesupport_impls.split(';') template_dir = args['template_dir'] type_support_impl_by_filename = { '%s_rs.ep.{0}.c'.format(impl): impl for impl in typesupport_impls } mapping_msgs = { os.path.join(template_dir, 'msg.rs.em'): ['rust/src/%s.rs'], os.path.join(template_dir, 'msg.c.em'): type_support_impl_by_filename.keys(), } mapping_srvs = { os.path.join(template_dir, 'srv.rs.em'): ['rust/src/%s.rs'], os.path.join(template_dir, 'srv.c.em'): type_support_impl_by_filename.keys(), } # Ensure the required templates exist for template_file in mapping_msgs.keys(): assert os.path.exists(template_file), \ 'Messages template file %s not found' % template_file for template_file in mapping_srvs.keys(): assert os.path.exists(template_file), \ 'Services template file %s not found' % template_file data = { 'get_c_type': get_c_type, 'get_rs_type': get_rs_type, 'constant_value_to_rs': constant_value_to_rs, 'value_to_rs': value_to_rs, 'convert_camel_case_to_lower_case_underscore': convert_camel_case_to_lower_case_underscore, 'convert_lower_case_underscore_to_camel_case': convert_lower_case_underscore_to_camel_case, 'get_builtin_rs_type': get_builtin_rs_type, 'msg_specs': [], 'srv_specs': [], 'package_name': args['package_name'], 'typesupport_impls': typesupport_impls, } latest_target_timestamp = get_newest_modification_time( args['target_dependencies']) for message in idl_content.get_elements_of_type(Message): data['msg_specs'].append(('msg', message)) for service in idl_content.get_elements_of_type(Service): data['srv_specs'].append(('srv', service)) if data['msg_specs']: for template_file, generated_filenames in mapping_msgs.items(): for generated_filename in generated_filenames: generated_file = os.path.join(args['output_dir'], generated_filename % 'msg') expand_template( os.path.join(template_dir, template_file), data.copy(), generated_file, minimum_timestamp=latest_target_timestamp) if data['srv_specs']: for template_file, generated_filenames in mapping_srvs.items(): for generated_filename in generated_filenames: generated_file = os.path.join(args['output_dir'], generated_filename % 'srv') expand_template( os.path.join(template_dir, template_file), data.copy(), generated_file, minimum_timestamp=latest_target_timestamp) expand_template( os.path.join(template_dir, 'lib.rs.em'), data.copy(), os.path.join(args['output_dir'], 'rust/src/lib.rs'), minimum_timestamp=latest_target_timestamp) return 0
def extract_content_from_ast(tree): content = IdlContent() include_directives = tree.find_data('include_directive') for include_directive in include_directives: assert len(include_directive.children) == 1 child = include_directive.children[0] assert child.data in ('h_char_sequence', 'q_char_sequence') include_token = next(child.scan_values(_find_tokens(None))) content.elements.append(Include(include_token.value)) constants = {} const_dcls = tree.find_data('const_dcl') for const_dcl in const_dcls: const_type = next(const_dcl.find_data('const_type')) const_expr = next(const_dcl.find_data('const_expr')) module_identifiers = get_module_identifier_values(tree, const_dcl) module_comments = constants.setdefault(module_identifiers[-1], []) value = get_const_expr_value(const_expr) module_comments.append( Constant(get_first_identifier_value(const_dcl), get_abstract_type_from_const_expr(const_type, value), value)) typedefs = {} typedef_dcls = tree.find_data('typedef_dcl') for typedef_dcl in typedef_dcls: assert len(typedef_dcl.children) == 1 child = typedef_dcl.children[0] assert 'type_declarator' == child.data assert len(child.children) == 2 abstract_type = get_abstract_type(child.children[0]) child = child.children[1] assert 'any_declarators' == child.data assert len(child.children) == 1, 'Only support single typedefs atm' child = child.children[0] identifier = get_first_identifier_value(child) abstract_type = get_abstract_type_optionally_as_array( abstract_type, child) if identifier in typedefs: assert typedefs[identifier] == abstract_type else: typedefs[identifier] = abstract_type struct_defs = list(tree.find_data('struct_def')) if len(struct_defs) == 1: msg = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[0]), name=get_child_identifier_value( struct_defs[0])))) annotations = get_annotations(struct_defs[0]) msg.structure.annotations += annotations add_message_members(msg, struct_defs[0]) resolve_typedefed_names(msg.structure, typedefs) constant_module_name = msg.structure.namespaced_type.name + \ CONSTANT_MODULE_SUFFIX if constant_module_name in constants: msg.constants += constants[constant_module_name] content.elements.append(msg) elif len(struct_defs) == 2: request = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[0]), name=get_child_identifier_value( struct_defs[0])))) assert request.structure.namespaced_type.name.endswith( SERVICE_REQUEST_MESSAGE_SUFFIX) add_message_members(request, struct_defs[0]) resolve_typedefed_names(request.structure, typedefs) constant_module_name = \ request.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX if constant_module_name in constants: request.constants += constants[constant_module_name] response = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[1]), name=get_child_identifier_value( struct_defs[1])))) assert response.structure.namespaced_type.name.endswith( SERVICE_RESPONSE_MESSAGE_SUFFIX) add_message_members(response, struct_defs[1]) resolve_typedefed_names(response.structure, typedefs) constant_module_name = \ response.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX if constant_module_name in constants: response.constants += constants[constant_module_name] assert request.structure.namespaced_type.namespaces == \ response.structure.namespaced_type.namespaces request_basename = request.structure.namespaced_type.name[:-len( SERVICE_REQUEST_MESSAGE_SUFFIX)] response_basename = response.structure.namespaced_type.name[:-len( SERVICE_RESPONSE_MESSAGE_SUFFIX)] assert request_basename == response_basename srv = Service( NamespacedType( namespaces=request.structure.namespaced_type.namespaces, name=request_basename), request, response) content.elements.append(srv) elif len(struct_defs) == 3: goal = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[0]), name=get_child_identifier_value( struct_defs[0])))) assert goal.structure.namespaced_type.name.endswith(ACTION_GOAL_SUFFIX) add_message_members(goal, struct_defs[0]) resolve_typedefed_names(goal.structure, typedefs) constant_module_name = \ goal.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX if constant_module_name in constants: goal.constants += constants[constant_module_name] result = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[1]), name=get_child_identifier_value( struct_defs[1])))) assert result.structure.namespaced_type.name.endswith( ACTION_RESULT_SUFFIX) add_message_members(result, struct_defs[1]) resolve_typedefed_names(result.structure, typedefs) constant_module_name = \ result.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX if constant_module_name in constants: result.constants += constants[constant_module_name] assert goal.structure.namespaced_type.namespaces == \ result.structure.namespaced_type.namespaces goal_basename = goal.structure.namespaced_type.name[:-len( ACTION_GOAL_SUFFIX)] result_basename = result.structure.namespaced_type.name[:-len( ACTION_RESULT_SUFFIX)] assert goal_basename == result_basename feedback_message = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[2]), name=get_child_identifier_value( struct_defs[2])))) assert feedback_message.structure.namespaced_type.name.endswith( ACTION_FEEDBACK_SUFFIX) add_message_members(feedback_message, struct_defs[2]) resolve_typedefed_names(feedback_message.structure, typedefs) constant_module_name = \ feedback_message.structure.namespaced_type.name + \ CONSTANT_MODULE_SUFFIX if constant_module_name in constants: feedback_message.constants += constants[constant_module_name] action = Action( NamespacedType( namespaces=goal.structure.namespaced_type.namespaces, name=goal_basename), goal, result, feedback_message) all_includes = content.get_elements_of_type(Include) unique_include_locators = {include.locator for include in all_includes} content.elements += [ include for include in action.implicit_includes if include.locator not in unique_include_locators ] content.elements.append(action) else: assert False, \ 'Currently only .idl files with 1 (a message), 2 (a service) ' \ 'and 3 (an action) structures are supported' return content
def generate_py(generator_arguments_file, typesupport_impls): mapping = { '_idl.py.em': '_%s.py', '_idl_support.c.em': '_%s_s.c', } generate_files(generator_arguments_file, mapping) args = read_generator_arguments(generator_arguments_file) package_name = args['package_name'] # expand init modules for each directory modules = {} idl_content = IdlContent() for idl_tuple in args.get('idl_tuples', []): idl_parts = idl_tuple.rsplit(':', 1) assert len(idl_parts) == 2 idl_rel_path = pathlib.Path(idl_parts[1]) idl_stems = modules.setdefault(str(idl_rel_path.parent), set()) idl_stems.add(idl_rel_path.stem) locator = IdlLocator(*idl_parts) idl_file = parse_idl_file(locator) idl_content.elements += idl_file.content.elements # NOTE(sam): remove when a language specific name mangling is implemented def print_warning_if_reserved_keyword(member_name, interface_type, interface_name): if (keyword.iskeyword(member.name)): print("Member name '{}' in the {} '{}' is a " 'reserved keyword in Python and is not supported ' 'at the moment. Please use a different name.'.format( member_name, interface_type, interface_name), file=sys.stderr) for message in idl_content.get_elements_of_type(Message): for member in message.structure.members: print_warning_if_reserved_keyword( member.name, 'message', message.structure.namespaced_type.name) for service in idl_content.get_elements_of_type(Service): for member in service.request_message.structure.members: print_warning_if_reserved_keyword(member.name, 'service request', service.namespaced_type.name) for member in service.response_message.structure.members: print_warning_if_reserved_keyword(member.name, 'service response', service.namespaced_type.name) for action in idl_content.get_elements_of_type(Action): for member in action.goal.structure.members: print_warning_if_reserved_keyword(member.name, 'action goal', action.namespaced_type.name) for member in action.feedback.structure.members: print_warning_if_reserved_keyword(member.name, 'action feedback', action.namespaced_type.name) for member in action.result.structure.members: print_warning_if_reserved_keyword(member.name, 'action result', action.namespaced_type.name) for subfolder in modules.keys(): with open(os.path.join(args['output_dir'], subfolder, '__init__.py'), 'w') as f: for idl_stem in sorted(modules[subfolder]): module_name = '_' + \ convert_camel_case_to_lower_case_underscore(idl_stem) f.write( f'from {package_name}.{subfolder}.{module_name} import ' f'{idl_stem} # noqa: F401\n') # expand templates per available typesupport implementation template_dir = args['template_dir'] type_support_impl_by_filename = { '_%s_s.ep.{0}.c'.format(impl): impl for impl in typesupport_impls } mapping_msg_pkg_extension = { os.path.join(template_dir, '_idl_pkg_typesupport_entry_point.c.em'): type_support_impl_by_filename.keys(), } for template_file in mapping_msg_pkg_extension.keys(): assert os.path.exists( template_file), 'Could not find template: ' + template_file latest_target_timestamp = get_newest_modification_time( args['target_dependencies']) for template_file, generated_filenames in mapping_msg_pkg_extension.items( ): for generated_filename in generated_filenames: package_name = args['package_name'] data = { 'package_name': args['package_name'], 'content': idl_content, 'typesupport_impl': type_support_impl_by_filename.get(generated_filename, ''), } generated_file = os.path.join(args['output_dir'], generated_filename % package_name) expand_template(template_file, data, generated_file, minimum_timestamp=latest_target_timestamp) return 0
def extract_content_from_ast(tree): content = IdlContent() include_directives = tree.find_data('include_directive') for include_directive in include_directives: assert len(include_directive.children) == 1 child = include_directive.children[0] assert child.data in ('h_char_sequence', 'q_char_sequence') include_token = next(child.scan_values(_find_tokens(None))) content.elements.append(Include(include_token.value)) const_dcls = tree.find_data('const_dcl') for const_dcl in const_dcls: const_type = next(const_dcl.find_data('const_type')) const_expr = next(const_dcl.find_data('const_expr')) content.elements.append( Constant(get_first_identifier_value(const_dcl), get_abstract_type_from_const_expr(const_type), get_const_expr_value(const_expr))) typedefs = {} typedef_dcls = tree.find_data('typedef_dcl') for typedef_dcl in typedef_dcls: assert len(typedef_dcl.children) == 1 child = typedef_dcl.children[0] assert 'type_declarator' == child.data assert len(child.children) == 2 abstract_type = get_abstract_type(child.children[0]) child = child.children[1] assert 'any_declarators' == child.data assert len(child.children) == 1, 'Only support single typedefs atm' child = child.children[0] identifier = get_first_identifier_value(child) abstract_type = get_abstract_type_optionally_as_array( abstract_type, child) if identifier in typedefs: assert typedefs[identifier] == abstract_type else: typedefs[identifier] = abstract_type struct_defs = list(tree.find_data('struct_def')) if len(struct_defs) == 1: msg = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[0]), name=get_first_identifier_value( struct_defs[0])))) add_message_members(msg, struct_defs[0]) resolve_typedefed_names(msg.structure, typedefs) # TODO move "global" constants/enums within a "matching" namespace into the message msg.constants.update( {c.name: c for c in content.elements if isinstance(c, Constant)}) # msg.constants.update(constants) content.elements.append(msg) elif len(struct_defs) == 2: request = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[0]), name=get_first_identifier_value( struct_defs[0])))) assert request.structure.type.name.endswith( SERVICE_REQUEST_MESSAGE_SUFFIX) add_message_members(request, struct_defs[0]) resolve_typedefed_names(request.structure, typedefs) # TODO move "global" constants/enums within a "matching" namespace into the request message response = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[1]), name=get_first_identifier_value( struct_defs[1])))) assert response.structure.type.name.endswith( SERVICE_RESPONSE_MESSAGE_SUFFIX) add_message_members(response, struct_defs[1]) resolve_typedefed_names(response.structure, typedefs) # TODO move "global" constants/enums within a "matching" namespace into the response msg assert request.structure.type.namespaces == \ response.structure.type.namespaces request_basename = request.structure.type.name[:-len( SERVICE_REQUEST_MESSAGE_SUFFIX)] response_basename = response.structure.type.name[:-len( SERVICE_RESPONSE_MESSAGE_SUFFIX)] assert request_basename == response_basename srv = Service( NamespacedType(namespaces=request.structure.type.namespaces, name=request_basename), request, response) content.elements.append(srv) elif len(struct_defs) == 3: goal_request = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[0]), name=get_first_identifier_value( struct_defs[0])))) assert goal_request.structure.type.name.endswith( ACTION_GOAL_SERVICE_SUFFIX + SERVICE_REQUEST_MESSAGE_SUFFIX) add_message_members(goal_request, struct_defs[0]) resolve_typedefed_names(goal_request.structure, typedefs) # TODO move "global" constants/enums within a "matching" namespace into # the goal request message result_response = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[1]), name=get_first_identifier_value( struct_defs[1])))) assert result_response.structure.type.name.endswith( ACTION_RESULT_SERVICE_SUFFIX + SERVICE_RESPONSE_MESSAGE_SUFFIX) add_message_members(result_response, struct_defs[1]) resolve_typedefed_names(result_response.structure, typedefs) # TODO move "global" constants/enums within a "matching" namespace into # the result response message assert goal_request.structure.type.namespaces == \ result_response.structure.type.namespaces goal_request_basename = goal_request.structure.type.name[:-len( ACTION_GOAL_SERVICE_SUFFIX + SERVICE_REQUEST_MESSAGE_SUFFIX)] result_response_basename = result_response.structure.type.name[:-len( ACTION_RESULT_SERVICE_SUFFIX + SERVICE_RESPONSE_MESSAGE_SUFFIX)] assert goal_request_basename == result_response_basename feedback_message = Message( Structure( NamespacedType(namespaces=get_module_identifier_values( tree, struct_defs[2]), name=get_first_identifier_value( struct_defs[2])))) assert feedback_message.structure.type.name.endswith( ACTION_FEEDBACK_MESSAGE_SUFFIX) add_message_members(feedback_message, struct_defs[2]) resolve_typedefed_names(feedback_message.structure, typedefs) # TODO move "global" constants/enums within a "matching" namespace into # the feedback message action = Action( NamespacedType(namespaces=goal_request.structure.type.namespaces, name=goal_request_basename), goal_request, result_response, feedback_message) content.elements.append(action) else: assert False, \ 'Currently only .idl files with 1 (a message), 2 (a service) ' \ 'and 3 (an action) structures are supported' return content
def generate_rs(generator_arguments_file, typesupport_impls): args = read_generator_arguments(generator_arguments_file) package_name = args['package_name'] # expand init modules for each directory modules = {} idl_content = IdlContent() dependency_packages = set() (Path(args['output_dir']) / 'rust/src').mkdir(parents=True, exist_ok=True) for dep_tuple in args.get('ros_interface_dependencies', []): dep_parts = dep_tuple.rsplit(':', 1) assert len(dep_parts) == 2 if dep_parts[0] != package_name: dependency_packages.add(dep_parts[0]) for idl_tuple in args.get('idl_tuples', []): idl_parts = idl_tuple.rsplit(':', 1) assert len(idl_parts) == 2 idl_rel_path = pathlib.Path(idl_parts[1]) idl_stems = modules.setdefault(str(idl_rel_path.parent), set()) idl_stems.add(idl_rel_path.stem) locator = IdlLocator(*idl_parts) idl_file = parse_idl_file(locator) idl_content.elements += idl_file.content.elements typesupport_impls = typesupport_impls.split(';') template_dir = args['template_dir'] mapping_msgs = { os.path.join(template_dir, 'msg.rs.em'): ['rust/src/%s.rs'], } mapping_srvs = { os.path.join(template_dir, 'srv.rs.em'): ['rust/src/%s.rs'], } # Ensure the required templates exist for template_file in mapping_msgs.keys(): assert os.path.exists(template_file), \ 'Messages template file %s not found' % template_file for template_file in mapping_srvs.keys(): assert os.path.exists(template_file), \ 'Services template file %s not found' % template_file data = { 'get_rmw_rs_type': make_get_rmw_rs_type(args['package_name']), 'get_rs_name': get_rs_name, 'get_idiomatic_rs_type': make_get_idiomatic_rs_type(args['package_name']), 'constant_value_to_rs': constant_value_to_rs, 'value_to_rs': value_to_rs, 'convert_camel_case_to_lower_case_underscore': convert_camel_case_to_lower_case_underscore, 'convert_lower_case_underscore_to_camel_case': convert_lower_case_underscore_to_camel_case, 'msg_specs': [], 'srv_specs': [], 'package_name': args['package_name'], 'typesupport_impls': typesupport_impls, } latest_target_timestamp = get_newest_modification_time( args['target_dependencies']) for message in idl_content.get_elements_of_type(Message): data['msg_specs'].append(('msg', message)) for service in idl_content.get_elements_of_type(Service): data['srv_specs'].append(('srv', service)) if data['msg_specs']: for template_file, generated_filenames in mapping_msgs.items(): for generated_filename in generated_filenames: generated_file = os.path.join(args['output_dir'], generated_filename % 'msg') expand_template(os.path.join(template_dir, template_file), data.copy(), generated_file, minimum_timestamp=latest_target_timestamp) if data['srv_specs']: for template_file, generated_filenames in mapping_srvs.items(): for generated_filename in generated_filenames: generated_file = os.path.join(args['output_dir'], generated_filename % 'srv') expand_template(os.path.join(template_dir, template_file), data.copy(), generated_file, minimum_timestamp=latest_target_timestamp) expand_template(os.path.join(template_dir, 'lib.rs.em'), data.copy(), os.path.join(args['output_dir'], 'rust/src/lib.rs'), minimum_timestamp=latest_target_timestamp) cargo_toml_data = { 'dependency_packages': dependency_packages, 'package_name': args['package_name'], 'package_version': args['package_version'], } expand_template(os.path.join(template_dir, 'Cargo.toml.em'), cargo_toml_data, os.path.join(args['output_dir'], 'rust/Cargo.toml'), minimum_timestamp=latest_target_timestamp) expand_template(os.path.join(template_dir, 'build.rs.em'), {}, os.path.join(args['output_dir'], 'rust/build.rs'), minimum_timestamp=latest_target_timestamp) return 0
def generate_py(generator_arguments_file, typesupport_impls): mapping = { '_idl.py.em': '_%s.py', '_idl_support.c.em': '_%s_s.c', } generate_files(generator_arguments_file, mapping) args = read_generator_arguments(generator_arguments_file) package_name = args['package_name'] # expand init modules for each directory modules = {} idl_content = IdlContent() for idl_tuple in args.get('idl_tuples', []): idl_parts = idl_tuple.rsplit(':', 1) assert len(idl_parts) == 2 idl_rel_path = pathlib.Path(idl_parts[1]) idl_stems = modules.setdefault(str(idl_rel_path.parent), set()) idl_stems.add(idl_rel_path.stem) locator = IdlLocator(*idl_parts) idl_file = parse_idl_file(locator) idl_content.elements += idl_file.content.elements for subfolder in modules.keys(): with open(os.path.join(args['output_dir'], subfolder, '__init__.py'), 'w') as f: for idl_stem in sorted(modules[subfolder]): module_name = '_' + \ convert_camel_case_to_lower_case_underscore(idl_stem) f.write('from {package_name}.{subfolder}.{module_name} import ' '{idl_stem} # noqa: F401\n'.format_map(locals())) # expand templates per available typesupport implementation template_dir = args['template_dir'] type_support_impl_by_filename = { '_%s_s.ep.{0}.c'.format(impl): impl for impl in typesupport_impls } mapping_msg_pkg_extension = { os.path.join(template_dir, '_idl_pkg_typesupport_entry_point.c.em'): type_support_impl_by_filename.keys(), } for template_file in mapping_msg_pkg_extension.keys(): assert os.path.exists( template_file), 'Could not find template: ' + template_file latest_target_timestamp = get_newest_modification_time( args['target_dependencies']) for template_file, generated_filenames in mapping_msg_pkg_extension.items( ): for generated_filename in generated_filenames: package_name = args['package_name'] data = { 'package_name': args['package_name'], 'content': idl_content, 'typesupport_impl': type_support_impl_by_filename.get(generated_filename, ''), } generated_file = os.path.join(args['output_dir'], generated_filename % package_name) expand_template(template_file, data, generated_file, minimum_timestamp=latest_target_timestamp) return 0
def extract_content_from_ast(tree): content = IdlContent() include_directives = tree.find_data('include_directive') for include_directive in include_directives: assert len(include_directive.children) == 1 child = include_directive.children[0] assert child.data in ('h_char_sequence', 'q_char_sequence') include_token = next(child.scan_values(_find_tokens(None))) content.elements.append(Include(include_token.value)) constants = {} const_dcls = tree.find_data('const_dcl') for const_dcl in const_dcls: const_type = next(const_dcl.find_data('const_type')) const_expr = next(const_dcl.find_data('const_expr')) module_identifiers = get_module_identifier_values(tree, const_dcl) module_comments = constants.setdefault( module_identifiers[-1], []) value = get_const_expr_value(const_expr) module_comments.append(Constant( get_first_identifier_value(const_dcl), get_abstract_type_from_const_expr(const_type, value), value)) typedefs = {} typedef_dcls = tree.find_data('typedef_dcl') for typedef_dcl in typedef_dcls: assert len(typedef_dcl.children) == 1 child = typedef_dcl.children[0] assert 'type_declarator' == child.data assert len(child.children) == 2 abstract_type = get_abstract_type(child.children[0]) child = child.children[1] assert 'any_declarators' == child.data assert len(child.children) == 1, 'Only support single typedefs atm' child = child.children[0] identifier = get_first_identifier_value(child) abstract_type = get_abstract_type_optionally_as_array( abstract_type, child) if identifier in typedefs: assert typedefs[identifier] == abstract_type else: typedefs[identifier] = abstract_type struct_defs = list(tree.find_data('struct_def')) if len(struct_defs) == 1: msg = Message(Structure(NamespacedType( namespaces=get_module_identifier_values(tree, struct_defs[0]), name=get_child_identifier_value(struct_defs[0])))) annotations = get_annotations(struct_defs[0]) msg.structure.annotations += annotations add_message_members(msg, struct_defs[0]) resolve_typedefed_names(msg.structure, typedefs) constant_module_name = msg.structure.namespaced_type.name + \ CONSTANT_MODULE_SUFFIX if constant_module_name in constants: msg.constants += constants[constant_module_name] content.elements.append(msg) elif len(struct_defs) == 2: request = Message(Structure(NamespacedType( namespaces=get_module_identifier_values(tree, struct_defs[0]), name=get_child_identifier_value(struct_defs[0])))) assert request.structure.namespaced_type.name.endswith( SERVICE_REQUEST_MESSAGE_SUFFIX) add_message_members(request, struct_defs[0]) resolve_typedefed_names(request.structure, typedefs) constant_module_name = \ request.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX if constant_module_name in constants: request.constants += constants[constant_module_name] response = Message(Structure(NamespacedType( namespaces=get_module_identifier_values(tree, struct_defs[1]), name=get_child_identifier_value(struct_defs[1])))) assert response.structure.namespaced_type.name.endswith( SERVICE_RESPONSE_MESSAGE_SUFFIX) add_message_members(response, struct_defs[1]) resolve_typedefed_names(response.structure, typedefs) constant_module_name = \ response.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX if constant_module_name in constants: response.constants += constants[constant_module_name] assert request.structure.namespaced_type.namespaces == \ response.structure.namespaced_type.namespaces request_basename = request.structure.namespaced_type.name[ :-len(SERVICE_REQUEST_MESSAGE_SUFFIX)] response_basename = response.structure.namespaced_type.name[ :-len(SERVICE_RESPONSE_MESSAGE_SUFFIX)] assert request_basename == response_basename srv = Service( NamespacedType( namespaces=request.structure.namespaced_type.namespaces, name=request_basename), request, response) content.elements.append(srv) elif len(struct_defs) == 3: goal = Message(Structure(NamespacedType( namespaces=get_module_identifier_values(tree, struct_defs[0]), name=get_child_identifier_value(struct_defs[0])))) assert goal.structure.namespaced_type.name.endswith(ACTION_GOAL_SUFFIX) add_message_members(goal, struct_defs[0]) resolve_typedefed_names(goal.structure, typedefs) constant_module_name = \ goal.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX if constant_module_name in constants: goal.constants += constants[constant_module_name] result = Message(Structure(NamespacedType( namespaces=get_module_identifier_values(tree, struct_defs[1]), name=get_child_identifier_value(struct_defs[1])))) assert result.structure.namespaced_type.name.endswith( ACTION_RESULT_SUFFIX) add_message_members(result, struct_defs[1]) resolve_typedefed_names(result.structure, typedefs) constant_module_name = \ result.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX if constant_module_name in constants: result.constants += constants[constant_module_name] assert goal.structure.namespaced_type.namespaces == \ result.structure.namespaced_type.namespaces goal_basename = goal.structure.namespaced_type.name[ :-len(ACTION_GOAL_SUFFIX)] result_basename = result.structure.namespaced_type.name[ :-len(ACTION_RESULT_SUFFIX)] assert goal_basename == result_basename feedback_message = Message(Structure(NamespacedType( namespaces=get_module_identifier_values(tree, struct_defs[2]), name=get_child_identifier_value(struct_defs[2])))) assert feedback_message.structure.namespaced_type.name.endswith( ACTION_FEEDBACK_SUFFIX) add_message_members(feedback_message, struct_defs[2]) resolve_typedefed_names(feedback_message.structure, typedefs) constant_module_name = \ feedback_message.structure.namespaced_type.name + \ CONSTANT_MODULE_SUFFIX if constant_module_name in constants: feedback_message.constants += constants[constant_module_name] action = Action( NamespacedType( namespaces=goal.structure.namespaced_type.namespaces, name=goal_basename), goal, result, feedback_message) all_includes = content.get_elements_of_type(Include) unique_include_locators = { include.locator for include in all_includes} content.elements += [ include for include in action.implicit_includes if include.locator not in unique_include_locators] content.elements.append(action) else: assert False, \ 'Currently only .idl files with 1 (a message), 2 (a service) ' \ 'and 3 (an action) structures are supported' return content