parameters: (self)
docstring: Finds the missing components for file nodes by parsing the Doxygen xml (which is
          just the ``doxygen_output_dir/node.refid``).  Additional items parsed include
          adding items whose ``refid`` tag are used in this file, the <programlisting> for
          the file, what it includes and what includes it, as well as the location of the
          file (with respsect to the *Doxygen* root).
  
          Care must be taken to only include a refid found with specific tags.  The
          parsing of the xml file was done by just looking at some example outputs.  It
          seems to be working correctly, but there may be some subtle use cases that break
          it.
  
          .. warning::
              Some enums, classes, variables, etc declared in the file will not have their
              associated refid in the declaration of the file, but will be present in the
              <programlisting>.  These are added to the files' list of children when they
              are found, but this parental relationship cannot be formed if you set
              ``XML_PROGRAMLISTING = NO`` with Doxygen.  An example of such an enum would
              be an enum declared inside of a namespace within this file.
docstring_summary: Finds the missing components for file nodes by parsing the Doxygen xml (which is
          just the ``doxygen_output_dir/node.refid``).  Additional items parsed include
          adding items whose ``refid`` tag are used in this file, the <programlisting> for
          the file, what it includes and what includes it, as well as the location of the
          file (with respsect to the *Doxygen* root).
docstring_tokens: Finds the missing components for file nodes by parsing the Doxygen xml ( which is just the doxygen_output_dir / node . refid ) . Additional items parsed include adding items whose refid tag are used in this file the <programlisting > for the file what it includes and what includes it as well as the location of the file ( with respsect to the * Doxygen * root ) .
function: def fileRefDiscovery(self):
          '''
          Finds the missing components for file nodes by parsing the Doxygen xml (which is
          just the ``doxygen_output_dir/node.refid``).  Additional items parsed include
          adding items whose ``refid`` tag are used in this file, the <programlisting> for
          the file, what it includes and what includes it, as well as the location of the
          file (with respsect to the *Doxygen* root).
  
          Care must be taken to only include a refid found with specific tags.  The
          parsing of the xml file was done by just looking at some example outputs.  It
          seems to be working correctly, but there may be some subtle use cases that break
          it.
  
          .. warning::
              Some enums, classes, variables, etc declared in the file will not have their
              associated refid in the declaration of the file, but will be present in the
              <programlisting>.  These are added to the files' list of children when they
              are found, but this parental relationship cannot be formed if you set
              ``XML_PROGRAMLISTING = NO`` with Doxygen.  An example of such an enum would
              be an enum declared inside of a namespace within this file.
          '''
          if EXHALE_API_DOXY_OUTPUT_DIR == "":
              exclaimError("The doxygen xml output directory was not specified!")
              return
          # parse the doxygen xml file and extract all refid's put in it
          # keys: file object, values: list of refid's
          doxygen_xml_file_ownerships = {}
          # innerclass, innernamespace, etc
          ref_regex    = re.compile(r'.*<inner.*refid="(\w+)".*')
          # what files this file includes
          inc_regex    = re.compile(r'.*<includes.*>(.+)</includes>')
          # what files include this file
          inc_by_regex = re.compile(r'.*<includedby refid="(\w+)".*>(.*)</includedby>')
          # the actual location of the file
          loc_regex    = re.compile(r'.*<location file="(.*)"/>')
  
          for f in self.files:
              doxygen_xml_file_ownerships[f] = []
              try:
                  doxy_xml_path = "{}{}.xml".format(EXHALE_API_DOXY_OUTPUT_DIR, f.refid)
                  with open(doxy_xml_path, "r") as doxy_file:
                      processing_code_listing = False # shows up at bottom of xml
                      for line in doxy_file:
                          # see if this line represents the location tag
                          match = loc_regex.match(line)
                          if match is not None:
                              f.location = match.groups()[0]
                              continue
  
                          if not processing_code_listing:
                              # gather included by references
                              match = inc_by_regex.match(line)
                              if match is not None:
                                  ref, name = match.groups()
                                  f.included_by.append((ref, name))
                                  continue
                              # gather includes lines
                              match = inc_regex.match(line)
                              if match is not None:
                                  inc = match.groups()[0]
                                  f.includes.append(inc)
                                  continue
                              # gather any classes, namespaces, etc declared in the file
                              match = ref_regex.match(line)
                              if match is not None:
                                  match_refid = match.groups()[0]
                                  if match_refid in self.node_by_refid:
                                      doxygen_xml_file_ownerships[f].append(match_refid)
                                  continue
                              # lastly, see if we are starting the code listing
                              if "<programlisting>" in line:
                                  processing_code_listing = True
                          elif processing_code_listing:
                              if "</programlisting>" in line:
                                  processing_code_listing = False
                              else:
                                  f.program_listing.append(line)
              except:
                  exclaimError("Unable to process doxygen xml for file [{}].\n".format(f.name))
  
          #
          # IMPORTANT: do not set the parent field of anything being added as a child to the file
          #
  
          # hack to make things work right on RTD
          if EXHALE_API_DOXYGEN_STRIP_FROM_PATH is not None:
              for f in self.files:
                  f.location = f.location.replace(EXHALE_API_DOXYGEN_STRIP_FROM_PATH, "")
                  if f.location[0] == "/":
                      f.location = f.location[1:]
  
          # now that we have parsed all the listed refid's in the doxygen xml, reparent
          # the nodes that we care about
          for f in self.files:
              for match_refid in doxygen_xml_file_ownerships[f]:
                  child = self.node_by_refid[match_refid]
                  if child.kind == "struct" or child.kind == "class" or child.kind == "function" or \
                     child.kind == "typedef" or child.kind == "define" or child.kind == "enum"   or \
                     child.kind == "union":
                      already_there = False
                      for fc in f.children:
                          if child.name == fc.name:
                              already_there = True
                              break
                      if not already_there:
                          # special treatment for unions: ignore if it is a class union
                          if child.kind == "union":
                              for u in self.unions:
                                  if child.name == u.name:
                                      f.children.append(child)
                                      break
                          else:
                              f.children.append(child)
                  elif child.kind == "namespace":
                      already_there = False
                      for fc in f.namespaces_used:
                          if child.name == fc.name:
                              already_there = True
                              break
                      if not already_there:
                          f.namespaces_used.append(child)
  
          # last but not least, some different kinds declared in the file that are scoped
          # in a namespace they will show up in the programlisting, but not at the toplevel.
          for f in self.files:
              potential_orphans = []
              for n in f.namespaces_used:
                  for child in n.children:
                      if child.kind == "enum"     or child.kind == "variable" or \
                         child.kind == "function" or child.kind == "typedef"  or \
                         child.kind == "union":
                          potential_orphans.append(child)
  
              # now that we have a list of potential orphans, see if this doxygen xml had
              # the refid of a given child present.
              for orphan in potential_orphans:
                  unresolved_name = orphan.name.split("::")[-1]
                  if f.refid in orphan.refid and any(unresolved_name in line for line in f.program_listing):
                      if orphan not in f.children:
                          f.children.append(orphan)
function_tokens: def fileRefDiscovery ( self ) : if EXHALE_API_DOXY_OUTPUT_DIR == "" : exclaimError ( "The doxygen xml output directory was not specified!" ) return # parse the doxygen xml file and extract all refid's put in it # keys: file object, values: list of refid's doxygen_xml_file_ownerships = { } # innerclass, innernamespace, etc ref_regex = re . compile ( r'.*<inner.*refid="(\w+)".*' ) # what files this file includes inc_regex = re . compile ( r'.*<includes.*>(.+)</includes>' ) # what files include this file inc_by_regex = re . compile ( r'.*<includedby refid="(\w+)".*>(.*)</includedby>' ) # the actual location of the file loc_regex = re . compile ( r'.*<location file="(.*)"/>' ) for f in self . files : doxygen_xml_file_ownerships [ f ] = [ ] try : doxy_xml_path = "{}{}.xml" . format ( EXHALE_API_DOXY_OUTPUT_DIR , f . refid ) with open ( doxy_xml_path , "r" ) as doxy_file : processing_code_listing = False # shows up at bottom of xml for line in doxy_file : # see if this line represents the location tag match = loc_regex . match ( line ) if match is not None : f . location = match . groups ( ) [ 0 ] continue if not processing_code_listing : # gather included by references match = inc_by_regex . match ( line ) if match is not None : ref , name = match . groups ( ) f . included_by . append ( ( ref , name ) ) continue # gather includes lines match = inc_regex . match ( line ) if match is not None : inc = match . groups ( ) [ 0 ] f . includes . append ( inc ) continue # gather any classes, namespaces, etc declared in the file match = ref_regex . match ( line ) if match is not None : match_refid = match . groups ( ) [ 0 ] if match_refid in self . node_by_refid : doxygen_xml_file_ownerships [ f ] . append ( match_refid ) continue # lastly, see if we are starting the code listing if "<programlisting>" in line : processing_code_listing = True elif processing_code_listing : if "</programlisting>" in line : processing_code_listing = False else : f . program_listing . append ( line ) except : exclaimError ( "Unable to process doxygen xml for file [{}].\n" . format ( f . name ) ) # # IMPORTANT: do not set the parent field of anything being added as a child to the file # # hack to make things work right on RTD if EXHALE_API_DOXYGEN_STRIP_FROM_PATH is not None : for f in self . files : f . location = f . location . replace ( EXHALE_API_DOXYGEN_STRIP_FROM_PATH , "" ) if f . location [ 0 ] == "/" : f . location = f . location [ 1 : ] # now that we have parsed all the listed refid's in the doxygen xml, reparent # the nodes that we care about for f in self . files : for match_refid in doxygen_xml_file_ownerships [ f ] : child = self . node_by_refid [ match_refid ] if child . kind == "struct" or child . kind == "class" or child . kind == "function" or child . kind == "typedef" or child . kind == "define" or child . kind == "enum" or child . kind == "union" : already_there = False for fc in f . children : if child . name == fc . name : already_there = True break if not already_there : # special treatment for unions: ignore if it is a class union if child . kind == "union" : for u in self . unions : if child . name == u . name : f . children . append ( child ) break else : f . children . append ( child ) elif child . kind == "namespace" : already_there = False for fc in f . namespaces_used : if child . name == fc . name : already_there = True break if not already_there : f . namespaces_used . append ( child ) # last but not least, some different kinds declared in the file that are scoped # in a namespace they will show up in the programlisting, but not at the toplevel. for f in self . files : potential_orphans = [ ] for n in f . namespaces_used : for child in n . children : if child . kind == "enum" or child . kind == "variable" or child . kind == "function" or child . kind == "typedef" or child . kind == "union" : potential_orphans . append ( child ) # now that we have a list of potential orphans, see if this doxygen xml had # the refid of a given child present. for orphan in potential_orphans : unresolved_name = orphan . name . split ( "::" ) [ - 1 ] if f . refid in orphan . refid and any ( unresolved_name in line for line in f . program_listing ) : if orphan not in f . children : f . children . append ( orphan )