/// <summary> /// Add unique members from the PackageDatabase to this v1 AddReferenceDatabase. /// PackageDatabases should be added in ranked order (ex: descending download count) /// so that the highest ranked source will be shown for a given unique /// fully qualified type name. /// </summary> /// <param name="source">PackageDatabase to include unique public types from</param> /// <returns>DatabaseAddResult describing what was added</returns> /// <summary> public DatabaseAddResult AddUniqueMembers(PackageDatabase source) { // Merge namespaces into a common tree to find unique parts of this package DatabaseAddResult result = _mergedMembers.Add(source, this.DatabaseFormatVersion); if (this.DatabaseFormatVersion == ArdbVersion.V1) { // Import everything which was unique ImportPublics( source, sourceMemberIndex: 0, targetMemberIndex: 0, uniqueMembers: result.WasMemberAdded, ardbVersion: ArdbVersion.V1); } else { // Import everything which was unique. If we've got no // type information, nothing new was observed on merge if (result.TypeNameToTypeIndexMap.Count > 0) { int packageNodeIndex = ImportPackageNodes(source); ImportFrameworkTargets(source, packageNodeIndex, result); } } return(result); }
/// <summary> /// Add public types from the given source PackageDatabase to this one. /// Returns an array indicating which items were added. True means the /// member or a descendant were unique. False means nothing was new. /// Null means the type and descendants were excluded as non-public. /// </summary> /// <param name="source">PackageDatabase to add from</param> /// <returns>For each member, true if added, false if not unique, null if not a public type</returns> public DatabaseAddResult Add(PackageDatabase source, ArdbVersion ardbVersion) { // Merge namespaces into a common tree to find unique parts of this package DatabaseAddResult result = new DatabaseAddResult(source); AddUniqueMembers(source, 0, 0, result, ardbVersion); return(result); }
private bool AddUniqueMembers( PackageDatabase source, int sourceMemberIndex, int targetMemberIndex, DatabaseAddResult result, ArdbVersion version) { int pathLength = result.CurrentPath.Length; SymbolDetails memberDetails = source.DeclaredMemberDetails[sourceMemberIndex]; bool hasUniqueDescendants = false; int indexToAddChildrenUnder = targetMemberIndex; // Add public types and namespaces which contain either bool addMember = false; if (memberDetails.Type == SymbolType.FrameworkTarget) { String8 encodedFrameworkNames = source.StringStore[source.DeclaredMembers.GetNameIdentifier(sourceMemberIndex)]; result.CurrentFrameworkNames = new HashSet <string>(encodedFrameworkNames.ToString().ToFrameworkNames()); } else if (memberDetails.Type == SymbolType.Namespace) { addMember = ContainsPublics(source, sourceMemberIndex); } else if (memberDetails.Type == SymbolType.Assembly) { if (result.CurrentFrameworkNames != null) { result.CurrentFrameworkNames.Clear(); } } else if (memberDetails.Type.IsType()) { addMember = memberDetails.Modifiers.HasFlag(SymbolModifier.Public); } // Add the member if it is a public type or contains them [and set 'indexInTarget' to the added member] if (addMember) { result.PublicTypeCount++; // Remap name for target StringStore [all unique names will be added anyway] int memberName = source.DeclaredMembers.GetNameIdentifier(sourceMemberIndex); String8 memberNameText = source.StringStore[memberName]; result.CurrentPath.Append((result.CurrentPath.Length > 0 ? "." : "") + memberNameText.ToString()); memberName = this.StringStore.FindOrAddString(memberNameText); string fullTypeName; HashSet <string> frameworkTargets; // See if this name is already found in the merged namespace tree if (!this.MergedMembers.TryFindChildByName(targetMemberIndex, memberName, out indexToAddChildrenUnder)) { // If not, add it, and the tree is unique because this name is indexToAddChildrenUnder = this.MergedMembers.Add(targetMemberIndex, memberName); // Identify the package which added it int packageNameIdentifier = this.StringStore.FindOrAddString(source.Identity.PackageName); this.MergedMemberSourcePackageIdentifier.Add(packageNameIdentifier); this.MergedMemberDuplicateCount.Add(1); hasUniqueDescendants = true; result.MergedTypeCount++; if (version != ArdbVersion.V1 && memberDetails.Type.IsType()) { // We have encountered a fully-qualified type name for the // very first time. We will associate this name with the // current framework target. We will also remember this // sourceMemberIndex, in order to use it as the item // to add when populating the ARDB. fullTypeName = result.CurrentPath.ToString(); result.TypeToFrameworkTargetsMap.Add(fullTypeName, new HashSet <string>()); if (result.CurrentFrameworkNames != null) { result.TypeToFrameworkTargetsMap[fullTypeName].UnionWith(result.CurrentFrameworkNames); } result.TypeNameToTypeIndexMap.Add(fullTypeName, sourceMemberIndex); } } else { // Otherwise, if this is a duplicate with another entry in the same package, still include it (different framework targets) String8 sourcePackage = this.StringStore[this.MergedMemberSourcePackageIdentifier[indexToAddChildrenUnder]]; if (version != ArdbVersion.V1 && result.CurrentFrameworkNames != null && sourcePackage.Equals(source.Identity.PackageName)) { hasUniqueDescendants = true; result.MergedTypeCount++; if (version != ArdbVersion.V1 && memberDetails.Type.IsType()) { // We have encountered a fully-qualified type name that we've seen // before. We will record the current framework target but // will already have a source member index to use to add // to the ARDB later. fullTypeName = result.CurrentPath.ToString(); frameworkTargets = result.TypeToFrameworkTargetsMap[fullTypeName]; frameworkTargets.UnionWith(result.CurrentFrameworkNames); Debug.Assert(result.TypeNameToTypeIndexMap.ContainsKey(fullTypeName)); } } else { // If this isn't unique, increment the count of copies this.MergedMemberDuplicateCount[indexToAddChildrenUnder] += 1; } } } if (!memberDetails.Type.IsType()) { int childIndex = source.DeclaredMembers.GetFirstChild(sourceMemberIndex); while (childIndex > 0) { hasUniqueDescendants |= AddUniqueMembers(source, childIndex, indexToAddChildrenUnder, result, version); childIndex = source.DeclaredMembers.GetNextSibling(childIndex); } } // Add the package which had this member to results if it wasn't unique if (hasUniqueDescendants == false) { result.SourcePackageNames[sourceMemberIndex] = this.StringStore[this.MergedMemberSourcePackageIdentifier[indexToAddChildrenUnder]]; } // Record whether this member was unique (and added) result.WasMemberAdded[sourceMemberIndex] = hasUniqueDescendants; result.CurrentPath.Length = pathLength; return(hasUniqueDescendants); }
private void ImportFrameworkTargets(PackageDatabase source, int packageMemberIndex, DatabaseAddResult databaseAddResult) { Dictionary <string, HashSet <int> > frameworkTargetsToIncludedTypes = new Dictionary <string, HashSet <int> >(); HashSet <int> frameworkTargetTypes; foreach (string type in Sorted(databaseAddResult.TypeToFrameworkTargetsMap.Keys)) { HashSet <string> frameworkTargetsSet = databaseAddResult.TypeToFrameworkTargetsMap[type]; string[] frameworkTargets = new string[frameworkTargetsSet.Count]; frameworkTargetsSet.CopyTo(frameworkTargets, 0); Array.Sort(frameworkTargets); string sortedFrameworkTargets = StringExtensions.EncodeFrameworkNamesToXml(frameworkTargets); if (!frameworkTargetsToIncludedTypes.TryGetValue(sortedFrameworkTargets, out frameworkTargetTypes)) { frameworkTargetTypes = frameworkTargetsToIncludedTypes[sortedFrameworkTargets] = new HashSet <int>(); } frameworkTargetTypes.Add(databaseAddResult.TypeNameToTypeIndexMap[type]); } foreach (string sortedFrameworkTargets in frameworkTargetsToIncludedTypes.Keys) { int frameworkTargetsId = this.StringStore.FindOrAddString(sortedFrameworkTargets); int frameworkTargetIndex = this.DeclaredMembers.Add(packageMemberIndex, frameworkTargetsId); this.DeclaredMemberTypes.Add(SymbolType.FrameworkTarget); // Now we'll add all types associated with this framework target set // To do so, we grab a single example from the source that expresses // the fully-qualified name, walk its tree, and add it to the target frameworkTargetTypes = frameworkTargetsToIncludedTypes[sortedFrameworkTargets]; Stack <int> nodes = new Stack <int>(); foreach (int typeIndex in frameworkTargetTypes) { int sourceMemberIndex = typeIndex; SymbolDetails details = source.DeclaredMemberDetails[sourceMemberIndex]; while (details.Type == SymbolType.Namespace || details.Type.IsType()) { nodes.Push(sourceMemberIndex); sourceMemberIndex = source.DeclaredMembers.GetParent(sourceMemberIndex); details = source.DeclaredMemberDetails[sourceMemberIndex]; } int targetMemberIndex = frameworkTargetIndex; while (nodes.Count > 0) { sourceMemberIndex = nodes.Pop(); details = source.DeclaredMemberDetails[sourceMemberIndex]; int memberName = source.DeclaredMembers.GetNameIdentifier(sourceMemberIndex); memberName = this.StringStore.FindOrAddString(source.StringStore[memberName]); int indexInTarget; if (!this.DeclaredMembers.TryFindChildByName(targetMemberIndex, memberName, out indexInTarget)) { targetMemberIndex = this.DeclaredMembers.Add(targetMemberIndex, memberName); this.Index.AddItem(memberName, targetMemberIndex); this.DeclaredMemberTypes.Add(details.Type); } else { targetMemberIndex = indexInTarget; } } } } }