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 not os.path.isdir(configs._doxygen_xml_output_directory):
            utils.fancyError("The doxygen xml output directory [{0}] is not valid!".format(
                configs._doxygen_xml_output_directory
            ))

        # 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 = os.path.join(configs._doxygen_xml_output_directory, "{0}.xml".format(f.refid))
                with codecs.open(doxy_xml_path, "r", "utf-8") 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 = os.path.normpath(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:
                utils.fancyError(
                    "Unable to process doxygen xml for file [{0}].\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
        # TODO: do this at construction rather than as a post process!
        if configs.doxygenStripFromPath is not None:
            for node in itertools.chain(self.files, self.dirs):
                if node.kind == "file":
                    manip = node.location
                else:  # node.kind == "dir"
                    manip = node.name

                abs_strip_path = os.path.normpath(os.path.abspath(
                    configs.doxygenStripFromPath
                ))
                if manip.startswith(abs_strip_path):
                    manip = os.path.relpath(manip, abs_strip_path)

                manip = os.path.normpath(manip)
                if node.kind == "file":
                    node.location = manip
                else:  # node.kind == "dir"
                    node.name = manip

        # now that we have parsed all the listed refid's in the doxygen xml, reparent
        # the nodes that we care about
        allowable_child_kinds = ["struct", "class", "function", "typedef", "define", "enum", "union"]
        for f in self.files:
            for match_refid in doxygen_xml_file_ownerships[f]:
                child = self.node_by_refid[match_refid]
                if child.kind in allowable_child_kinds:
                    if child not in f.children:
                        f.children.append(child)
                elif child.kind == "namespace":
                    if child not in f.namespaces_used:
                        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)

        # Last but not least, make sure all children know where they were defined.
        for f in self.files:
            for child in f.children:
                if child.def_in_file is None:
                    child.def_in_file = f
                elif child.def_in_file != f:
                    # << verboseBuild
                    utils.verbose_log(
                        "Conflicting file definition for [{0}]: both [{1}] and [{2}] found.".format(
                            child.name, child.def_in_file.name, f.name
                        ),
                        utils.AnsiColors.BOLD_RED
                    )
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.