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()); }
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); }
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); }
/// <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); }
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); }