Exemple #1
0
        private void ResolveCircularTypes(List <IRTypeNode> circle)
        {
            // All unique types within the given list are moved together into a seperate
            // namespace, because that's the only way to solve these kind of circular dependancies.
            // This list will NEVER contain enums!
            var distincttypes = circle.Distinct().Cast <IRClass>();

            // TODO: Better naming algorithm?! (Longest commong substring)
            // The longest substring between the fullnames of each type's namespace.
            var allTypeNamespaceNames = circle.Select(type => _TypeNSMapper[type].FullName).ToList();
            var newNSName             = DependancyUtil.LongestmatchingSubstring(allTypeNamespaceNames).Trim('.');
            // Also construct a shortname from the new namespace fullname
            var newNSShortName = newNSName.Substring(newNSName.LastIndexOf('.') + 1);

            // Append the suffix to lower chances of collision
            newNSName      = newNSName + EXTRACTED_NS_SUFFIX;
            newNSShortName = newNSShortName + EXTRACTED_NS_SUFFIX;

            // There still might already be a namespace with that name, so a test is necessary anyway!
            var newNS = _program.GetCreateNamespace(newNSName);

            // And copy over all types to this namespace.
            foreach (var irClass in distincttypes)
            {
                var oldNS = _TypeNSMapper[irClass];
                MoveType(irClass, oldNS, newNS);
            }

            // No need to add the namespace to the program anymore!
        }
Exemple #2
0
        // Compares the heights of both namespaces in a mental NON-CIRCULAR TREE.
        // The tree has the limitation that references are only allowed towards the root.
        // This method returns -1 if nsOne is closer to the root.
        // This method returns +1 is nsTwo is closer to the root.
        private int CompareNSHeights(IRNamespace nsOne, IRNamespace nsTwo)
        {
            List <string> nsNames = new List <string>();

            nsNames.Add(nsOne.FullName);
            nsNames.Add(nsTwo.FullName);
            var commonSubstr = DependancyUtil.LongestmatchingSubstring(nsNames);

            // Both namespaces share a hypothetical parent namespace.
            if (commonSubstr.Count() > 0)
            {
                return(nsOne.FullName.CompareTo(nsTwo.FullName));
            }

            // If there is no shared namespace, resort to amount of imports both types do.
            var depsNSOne = _NSDependancies[nsOne].Count();
            var depsNSTwo = _NSDependancies[nsTwo].Count();

            // NSTwo has less dependancies, so it's considered closer to the root.
            // This is a vague heuristic, ideally the one closer to the root has NO dependancies.
            if (depsNSTwo < depsNSOne)
            {
                return(1);
            }
            // Per default, nsOne is higher up the tree than nsTwo.
            return(-1);
        }
        private void ResolveCircularTypes(List <IRTypeNode> circle)
        {
            // All unique types within the given list are moved together into a seperate
            // namespace, because that's the only way to solve these kind of circular dependancies.
            // This list will NEVER contain enums!
            IEnumerable <IRClass> distincttypes = circle.Distinct().Cast <IRClass>();

            // TODO: Better naming algorithm?! (Longest commong substring)
            // The longest substring between the fullnames of each type's namespace.
            var    allTypeNamespaceNames = circle.Select(type => _TypeNSMapper[type].FullName).ToList();
            string newNSName             = DependancyUtil.LongestmatchingSubstring(allTypeNamespaceNames).Trim('.');
            // Also construct a shortname from the new namespace fullname
            string newNSShortName = newNSName.Substring(newNSName.LastIndexOf('.') + 1);

            // NOTE; A suffix is appended here in order to not increase the degree count
            // for the subject namespace (vertex).
            // Pulling types into a seperate namespace helps flattening the graph into a spanning,
            // while the alternative would increase the length of circular namespace chains.
            newNSName      += EXTRACTED_NS_SUFFIX;
            newNSShortName += EXTRACTED_NS_SUFFIX;

            // There still might already be a namespace with that name, so a test is necessary anyway!
            IRNamespace newNS = _program.GetCreateNamespace(newNSName);

            // And copy over all types to this namespace.
            foreach (IRClass irClass in distincttypes)
            {
                IRNamespace oldNS = _TypeNSMapper[irClass];
                MoveType(irClass, oldNS, newNS);
            }

            // No need to add the namespace to the program anymore!
        }