Example #1
0
        /// <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);
        }
Example #4
0
        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;
                        }
                    }
                }
            }
        }