def _extract_interface(interface_node, file_name):
    interface_name = IdentifierString(file_name, interface_node.name)
    extended_classifiers = []
    if interface_node.extends:
        for super_interface in interface_node.extends:
            extended_classifiers.append(IdentifierString(file_name, super_interface.name))
    inner_classifiers = _extract_inner_classifier(interface_node, file_name)
    interface_object = Classifier(interface_name, IdentifierString(file_name, ""), inner_classifiers=inner_classifiers,
                                  extended_classifiers=extended_classifiers)
    
    return _extract_attributes_and_methods_and_doc(interface_object, interface_node, file_name)
def _extract_attributes(attribute_nodes, file_name):
    """Return an attribute object list."""
    attr_list = []
    for attr in attribute_nodes:
        if not(ONLY_PUBLIC_ATTRIBUTES) or attr.modifiers.contains("public"):  # logical Implication
            attr_init_value, left_side_identifier = _extract_children_strings(attr.declarators[0].initializer, file_name)
            attr_obj = Attribute(IdentifierString(file_name, attr.type.name),
                                 IdentifierString(file_name, attr.declarators[0].name), attr_init_value, IdentifierString(file_name, ""))
            if attr.documentation:
                attr_obj.comment = _extract_comment(attr.documentation, file_name)
            attr_list.append(attr_obj)
    return attr_list
def _extract_enum(enum_node, file_name):
    enum_name = IdentifierString(file_name, enum_node.name)
    implemented_classifiers = []
    if enum_node.implements:
        for super_interface in enum_node.implements:
            implemented_classifiers.append(IdentifierString(file_name, super_interface.name))
            
    constants = []
    for con in enum_node.body.constants:
        constants.append(IdentifierString(file_name, con.name))

    enum_object = Enum_(enum_name, IdentifierString(file_name, ""), constants=constants, implemented_classifiers=implemented_classifiers)
    return _extract_attributes_and_methods_and_doc(enum_object, enum_node, file_name)
def _extract_class(class_node, file_name):
    class_name = IdentifierString(file_name, class_node.name)
    implemented_classifiers = []
    extended_classifiers = []
    if class_node.extends:
        extended_classifiers.append(IdentifierString(file_name, class_node.extends.name))
    if class_node.implements:
        for super_classifier in class_node.implements:
            implemented_classifiers.append(IdentifierString(file_name, super_classifier.name))
    
    inner_classifiers = _extract_inner_classifier(class_node, file_name)
    class_object = Classifier(class_name, IdentifierString(file_name, ""), inner_classifiers=inner_classifiers,
                              implemented_classifiers=implemented_classifiers, extended_classifiers=extended_classifiers)

    return _extract_attributes_and_methods_and_doc(class_object, class_node, file_name)
def _extract_methods(method_nodes, file_name):
    """Returns a method object list. """
    meth_list = []
    for meth in method_nodes:
        if not(ONLY_PUBLIC_METHODS) or "public" in meth.modifiers:  # logical Implication
            meth_obj = Method(IdentifierString(file_name, ""), IdentifierString(file_name, meth.name), IdentifierString(file_name, ""),
                              IdentifierString(file_name, ""), IdentifierString(file_name, ""))
            if meth.return_type:
                meth_obj.return_type = IdentifierString(file_name, meth.return_type.name)
            if meth.documentation:
                meth_obj.comment = _extract_comment(meth.documentation, file_name)
            meth_obj.set_params(_extract_parameters(meth.parameters, file_name))
            meth_obj.body, meth_obj.left_side_identifiers = _extract_children_strings(meth.body, file_name)
            meth_list.append(meth_obj)
    return meth_list
def _extract_parameters(parameter_nodes, file_name):
    """Returns a parameter object list."""
    param_list = []
    for param in parameter_nodes:
        type_suffix = ""
        if len(param.type.dimensions) == param.type.dimensions.count(None):  # it's an array type
            type_suffix = "[]" * len(param.type.dimensions)
        param_list.append(Parameter(IdentifierString(file_name, param.type.name + type_suffix), IdentifierString(file_name, param.name)))
    return param_list
def _extract_comment(comment: str, file_name):
    return IdentifierString(file_name, *(COMMENT_TOKENIZER.tokenize_to_string_list(comment)))
def _extract_children_strings(body_node, file_name) -> IdentifierString:
    """Returns an IdentifierString that contains all identifiers in the given body node"""
    
    strings_in_body, left_side_identifiers = _traverse_node(body_node, file_name)
    return IdentifierString(file_name, *strings_in_body), IdentifierString(file_name, *left_side_identifiers)