Пример #1
0
        private int PrioritizeImports(HashSet <CdmDocumentDefinition> processedSet, ImportPriorities importPriorities, int sequence, bool skipMonikered)
        {
            // goal is to make a map from the reverse order of imports (breadth first) to the first (aka last) sequence number in that list.
            // This gives the semantic that the 'last/shallowest' definition for a duplicate symbol wins,
            // the lower in this list a document shows up, the higher priority its definitions are for resolving conflicts.
            // for 'moniker' imports, keep track of the 'last/shallowest' use of each moniker tag.

            // maps document to priority.
            IDictionary <CdmDocumentDefinition, int> priorityMap = importPriorities.ImportPriority;

            // maps moniker to document.
            IDictionary <string, CdmDocumentDefinition> monikerMap = importPriorities.MonikerPriorityMap;

            // if already in list, don't do this again
            if (processedSet.Contains(this))
            {
                // if the first document in the priority map is this then the document was the starting point of the recursion.
                // and if this document is present in the processedSet we know that there is a cicular list of imports.
                if (priorityMap.ContainsKey(this) && priorityMap[this] == 0)
                {
                    importPriorities.hasCircularImport = true;
                }

                return(sequence);
            }
            processedSet.Add(this);

            if (this.Imports != null)
            {
                var reversedImports = this.Imports.Reverse();

                // first add the imports done at this level only in reverse order.
                foreach (var imp in reversedImports)
                {
                    var  impDoc    = imp.Document;
                    bool isMoniker = !string.IsNullOrWhiteSpace(imp.Moniker);

                    // don't add the moniker imports to the priority list.
                    if (impDoc != null && !isMoniker && !priorityMap.ContainsKey(impDoc))
                    {
                        // add doc.
                        priorityMap.Add(impDoc, sequence);
                        sequence++;
                    }
                }

                // now add the imports of the imports.
                foreach (var imp in reversedImports)
                {
                    CdmDocumentDefinition impDoc = imp.Document;
                    bool isMoniker = !string.IsNullOrWhiteSpace(imp.Moniker);

                    // if the document has circular imports its order on the impDoc.ImportPriorities list is not correct.
                    // since the document itself will always be the first one on the list.
                    if (impDoc?.ImportPriorities != null && impDoc?.ImportPriorities.hasCircularImport == false)
                    {
                        // lucky, already done so avoid recursion and copy.
                        ImportPriorities impPriSub = impDoc.GetImportPriorities();
                        impPriSub.ImportPriority.Remove(impDoc); // because already added above.

                        foreach (var ip in impPriSub.ImportPriority)
                        {
                            if (priorityMap.ContainsKey(ip.Key) == false)
                            {
                                // add doc.
                                priorityMap.Add(ip.Key, sequence);
                                sequence++;
                            }
                        }

                        // if the import is not monikered then merge its monikerMap to this one.
                        if (!isMoniker)
                        {
                            foreach (var mp in impPriSub.MonikerPriorityMap)
                            {
                                monikerMap[mp.Key] = mp.Value;
                            }
                        }
                    }
                    else if (impDoc != null)
                    {
                        // skip the monikered imports from here if this is a monikered import itself and we are only collecting the dependencies.
                        sequence = impDoc.PrioritizeImports(processedSet, importPriorities, sequence, isMoniker);
                    }
                }

                // skip the monikered imports from here if this is a monikered import itself and we are only collecting the dependencies.
                if (!skipMonikered)
                {
                    // moniker imports are prioritized by the 'closest' use of the moniker to the starting doc. so last one found in this recursion.
                    foreach (var imp in this.Imports)
                    {
                        bool isMoniker = !string.IsNullOrWhiteSpace(imp.Moniker);
                        if (imp.Document != null && isMoniker)
                        {
                            monikerMap[imp.Moniker] = imp.Document;
                        }
                    }
                }
            }

            return(sequence);
        }
Пример #2
0
        private int PrioritizeImports(HashSet <CdmDocumentDefinition> processedSet, IDictionary <CdmDocumentDefinition, int> priorityMap, int sequence, IDictionary <string, CdmDocumentDefinition> monikerMap, bool skipMonikered = false)
        {
            // goal is to make a map from the reverse order of imports (breadth first) to the first (aka last) sequence number in that list.
            // This gives the semantic that the 'last/shallowest' definition for a duplicate symbol wins,
            // the lower in this list a document shows up, the higher priority its definitions are for resolving conflicts.
            // for 'moniker' imports, keep track of the 'last/shallowest' use of each moniker tag.

            // if already in list, don't do this again
            if (processedSet.Contains(this))
            {
                return(sequence);
            }
            processedSet.Add(this);

            if (this.Imports != null)
            {
                // first add the imports done at this level only
                int l = this.Imports.Count;
                // reverse order
                for (int i = l - 1; i >= 0; i--)
                {
                    CdmImport             imp    = this.Imports.AllItems[i];
                    CdmDocumentDefinition impDoc = imp.ResolvedDocument as CdmDocumentDefinition;
                    // don't add the moniker imports to the priority list
                    bool isMoniker = !string.IsNullOrWhiteSpace(imp.Moniker);
                    if (imp.ResolvedDocument != null && !isMoniker)
                    {
                        if (priorityMap.ContainsKey(impDoc) == false)
                        {
                            // add doc
                            priorityMap.Add(impDoc, sequence);
                            sequence++;
                        }
                    }
                }

                // now add the imports of the imports
                for (int i = l - 1; i >= 0; i--)
                {
                    CdmImport             imp    = this.Imports.AllItems[i];
                    CdmDocumentDefinition impDoc = imp.ResolvedDocument as CdmDocumentDefinition;
                    // don't add the moniker imports to the priority list
                    bool isMoniker = !string.IsNullOrWhiteSpace(imp.Moniker);
                    if (impDoc?.ImportPriorities != null)
                    {
                        // lucky, already done so avoid recursion and copy
                        ImportPriorities impPriSub = impDoc.GetImportPriorities();
                        impPriSub.ImportPriority.Remove(impDoc); // because already added above
                        foreach (var ip in impPriSub.ImportPriority)
                        {
                            if (priorityMap.ContainsKey(ip.Key) == false)
                            {
                                // add doc
                                priorityMap.Add(ip.Key, sequence);
                                sequence++;
                            }
                        }
                        if (!isMoniker)
                        {
                            foreach (var mp in impPriSub.MonikerPriorityMap)
                            {
                                monikerMap[mp.Key] = mp.Value;
                            }
                        }
                    }
                    else if (impDoc != null)
                    {
                        // skip the monikered imports from here if this is a monikered import itself and we are only collecting the dependencies
                        sequence = impDoc.PrioritizeImports(processedSet, priorityMap, sequence, monikerMap, isMoniker);
                    }
                }
                // skip the monikered imports from here if this is a monikered import itself and we are only collecting the dependencies
                if (!skipMonikered)
                {
                    // moniker imports are prioritized by the 'closest' use of the moniker to the starting doc. so last one found in this recursion
                    for (int i = 0; i < l; i++)
                    {
                        CdmImport imp = this.Imports.AllItems[i];
                        if (imp.ResolvedDocument != null && imp.Moniker != null)
                        {
                            monikerMap[imp.Moniker] = imp.ResolvedDocument as CdmDocumentDefinition;
                        }
                    }
                }
            }
            return(sequence);
        }