internal ImportPriorities GetImportPriorities()
 {
     if (this.ImportPriorities == null)
     {
         this.ImportPriorities = new ImportPriorities();
         this.ImportPriorities.ImportPriority.Add(this, 0);
         this.PrioritizeImports(new HashSet <CdmDocumentDefinition>(), this.ImportPriorities.ImportPriority, 1, this.ImportPriorities.MonikerPriorityMap, false);
     }
     // make a copy so the caller doesn't mess these up
     return(this.ImportPriorities.Copy());
 }
Beispiel #2
0
 internal ImportPriorities GetImportPriorities()
 {
     if (this.ImportPriorities == null)
     {
         var importPriorities = new ImportPriorities();
         importPriorities.ImportPriority.Add(this, new ImportInfo(0, false));
         this.PrioritizeImports(new HashSet <CdmDocumentDefinition>(), importPriorities, 1, false);
         this.ImportPriorities = importPriorities;
     }
     // make a copy so the caller doesn't mess these up
     return(this.ImportPriorities.Copy());
 }
        internal ImportPriorities Copy()
        {
            ImportPriorities copy = new ImportPriorities();

            if (this.ImportPriority != null)
            {
                foreach (KeyValuePair <CdmDocumentDefinition, int> pair in this.ImportPriority)
                {
                    copy.ImportPriority[pair.Key] = pair.Value;
                }
                foreach (KeyValuePair <string, CdmDocumentDefinition> pair in this.MonikerPriorityMap)
                {
                    copy.MonikerPriorityMap[pair.Key] = pair.Value;
                }
            }
            return(copy);
        }
Beispiel #4
0
        internal ImportPriorities Copy()
        {
            ImportPriorities copy = new ImportPriorities();

            if (this.ImportPriority != null)
            {
                foreach (KeyValuePair <CdmDocumentDefinition, ImportInfo> pair in this.ImportPriority)
                {
                    copy.ImportPriority[pair.Key] = pair.Value;
                }
            }
            if (this.MonikerPriorityMap != null)
            {
                foreach (KeyValuePair <string, CdmDocumentDefinition> pair in this.MonikerPriorityMap)
                {
                    copy.MonikerPriorityMap[pair.Key] = pair.Value;
                }
            }
            copy.hasCircularImport = this.hasCircularImport;
            return(copy);
        }
Beispiel #5
0
        /// <summary>
        /// Clear all document's internal caches and update the declared path of every object contained by this document.
        /// </summary>
        /// <param name="objects"></param>
        /// <returns>A list containing all the objects inside this document.</returns>
        internal void ClearCaches()
        {
            // Clean all internal caches and flags
            this.InternalObjects      = new List <CdmObjectBase>();
            this.DeclarationsIndexed  = false;
            this.InternalDeclarations = new ConcurrentDictionary <string, CdmObjectBase>();
            this.ImportsIndexed       = false;
            this.ImportPriorities     = null;

            // Collects all the objects contained by this document and updates their DeclaredPath.
            this.Visit("", new VisitCallback
            {
                Invoke = (obj, objPath) =>
                {
                    CdmObjectBase objectBase = obj as CdmObjectBase;
                    // Update the DeclaredPath property.
                    objectBase.DeclaredPath = objPath;
                    this.InternalObjects.Add(objectBase);
                    return(false);
                }
            }, null);
        }
Beispiel #6
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);
        }
        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);
        }