public static CheckTree Build(ClangTidyProperties Config)
        {
            // Since some check names contain dashes in them, it doesn't make sense to
            // simply split all check names by dash and construct a huge tree.  For
            // example, in the check called google-runtime-member-string-references,
            // we don't need each of those to be a different subgroup.  So instead we
            // explicitly specify the common breaking points at which a user might want
            // to use a -* and everything else falls as a leaf under one of these
            // categories.
            // FIXME: This should be configurable without recompilation
            CheckTree Root = new CheckTree();

            string[][] Groups = new string[][] {
                new string[] { "boost" },
                new string[] { "cert" },
                new string[] { "clang", "diagnostic" },
                new string[] { "cppcoreguidelines", "interfaces" },
                new string[] { "cppcoreguidelines", "pro", "bounds" },
                new string[] { "cppcoreguidelines", "pro", "type" },
                new string[] { "google", "build" },
                new string[] { "google", "readability" },
                new string[] { "google", "runtime" },
                new string[] { "llvm" },
                new string[] { "misc" },
            };

            foreach (string[] Group in Groups)
            {
                CheckTree Subgroup = Root;
                foreach (string Component in Group)
                {
                    Subgroup = Subgroup.AddOrCreateSubgroup(Component);
                }
            }

            var Props = Config.GetProperties()
                        .Cast <PropertyDescriptor>()
                        .OfType <DynamicPropertyDescriptor <bool> >()
                        .Where(x => x.Attributes.OfType <ClangTidyCheckAttribute>().Count() > 0)
                        .Select(x => new KeyValuePair <DynamicPropertyDescriptor <bool>, string>(
                                    x, x.Attributes.OfType <ClangTidyCheckAttribute>().First().CheckName));
            var PropArray = Props.ToArray();

            foreach (var CheckInfo in PropArray)
            {
                string    LeafName = null;
                CheckTree Tree     = Root.LocateCheckLeafGroup(CheckInfo.Value, out LeafName);
                Tree.AddLeaf(LeafName, CheckInfo.Key);
            }
            return(Root);
        }
        private CheckTree AddOrCreateSubgroup(string Name)
        {
            CheckTreeNode Subgroup = null;

            if (Children_.TryGetValue(Name, out Subgroup))
            {
                System.Diagnostics.Debug.Assert(Subgroup is CheckTree);
                return((CheckTree)Subgroup);
            }

            CheckTree SG = new CheckTree(Name, this);

            Children_[Name] = SG;
            return(SG);
        }
        private CheckTree LocateCheckLeafGroup(string Check, out string LeafName)
        {
            string[] Components     = Check.Split('-');
            string   FirstComponent = Components.FirstOrDefault();

            if (FirstComponent == null)
            {
                LeafName = Check;
                return(this);
            }

            CheckTreeNode Subgroup = null;

            if (!Children_.TryGetValue(FirstComponent, out Subgroup))
            {
                LeafName = Check;
                return(this);
            }
            System.Diagnostics.Debug.Assert(Subgroup is CheckTree);
            CheckTree Child     = (CheckTree)Subgroup;
            string    ChildName = Check.Substring(FirstComponent.Length + 1);

            return(Child.LocateCheckLeafGroup(ChildName, out LeafName));
        }
Exemplo n.º 4
0
 public ClangTidyProperties(DynamicPropertyComponent Parent)
     : base(Parent)
 {
     AddClangCheckProperties();
     CheckTree_ = CheckTree.Build(this);
 }
Exemplo n.º 5
0
 public ClangTidyProperties()
     : base(null)
 {
     AddClangCheckProperties();
     CheckTree_ = CheckTree.Build(this);
 }
 public ClangTidyProperties(DynamicPropertyComponent Parent)
     : base(Parent)
 {
     AddClangCheckProperties();
     CheckTree_ = CheckTree.Build(this);
 }
 public ClangTidyProperties()
     : base(null)
 {
     AddClangCheckProperties();
     CheckTree_ = CheckTree.Build(this);
 }
 public CheckLeaf(string Name, CheckTree Parent, DynamicPropertyDescriptor <bool> Property)
     : base(Name, Parent)
 {
     Property_ = Property;
 }
Exemplo n.º 9
0
        /// <summary>
        /// Convert the given check tree into serialized list of commands that can be written to
        /// the Yaml.  The goal here is to determine the minimal sequence of check commands that
        /// will produce the exact configuration displayed in the UI.  This is complicated by the
        /// fact that an inherited True is not the same as an explicitly specified True.  If the
        /// user has chosen to inherit a setting in a .clang-tidy file, then changing it in the
        /// parent should show the reflected changes in the current file as well.  So we cannot
        /// simply -* everything and then add in the checks we need, because -* immediately marks
        /// every single check as explicitly false, thus disabling inheritance.
        /// </summary>
        /// <param name="CommandList">State passed through this recursive algorithm representing
        /// the sequence of commands we have determined so far.
        /// </param>
        /// <param name="Tree">The check tree to serialize.  This is the parameter that will be
        /// recursed on as successive subtrees get serialized to `CommandList`.
        /// </param>
        /// <param name="CurrentOp">The current state of the subtree.  For example, if the
        /// algorithm decides to -* an entire subtree and then add back one single check,
        /// after adding a -subtree-* command to CommandList, it would pass in a value of
        /// CurrentOp=TreeLevelOp.Disable when it recurses down.  This allows deeper iterations
        /// of the algorithm to know what kind of command (if any) needs to be added to CommandList
        /// in order to put a particular check into a particular state.
        /// </param>
        private static void SerializeCheckTree(List <string> CommandList, CheckTree Tree, TreeLevelOp CurrentOp)
        {
            int NumChecks    = Tree.CountChecks;
            int NumDisabled  = Tree.CountExplicitlyDisabledChecks;
            int NumEnabled   = Tree.CountExplicitlyEnabledChecks;
            int NumInherited = Tree.CountInheritedChecks;

            if (NumChecks == 0)
            {
                return;
            }

            if (NumInherited > 0)
            {
                System.Diagnostics.Debug.Assert(CurrentOp == TreeLevelOp.Inherit);
            }

            // If this entire tree is inherited, just exit, nothing about this needs to
            // go in the clang-tidy file.
            if (NumInherited == NumChecks)
            {
                return;
            }

            TreeLevelOp NewOp = CurrentOp;

            // If there are no inherited properties in this subtree, decide whether to
            // explicitly enable or disable this subtree.  Decide by looking at whether
            // there is a larger proportion of disabled or enabled descendants.  If
            // there are more disabled items in this subtree for example, disabling the
            // subtree will lead to a smaller configuration file.
            if (NumInherited == 0)
            {
                if (NumDisabled >= NumEnabled)
                {
                    NewOp = TreeLevelOp.Disable;
                }
                else
                {
                    NewOp = TreeLevelOp.Enable;
                }
            }

            if (NewOp == TreeLevelOp.Disable)
            {
                // Only add an explicit disable command if the tree was not already disabled
                // to begin with.
                if (CurrentOp != TreeLevelOp.Disable)
                {
                    string WildcardPath = "*";
                    if (Tree.Path != null)
                    {
                        WildcardPath = Tree.Path + "-" + WildcardPath;
                    }
                    CommandList.Add("-" + WildcardPath);
                }
                // If the entire subtree was disabled, there's no point descending.
                if (NumDisabled == NumChecks)
                {
                    return;
                }
            }
            else if (NewOp == TreeLevelOp.Enable)
            {
                // Only add an explicit enable command if the tree was not already enabled
                // to begin with.  Note that if we're at the root, all checks are already
                // enabled by default, so there's no need to explicitly include *
                if (CurrentOp != TreeLevelOp.Enable && Tree.Path != null)
                {
                    string WildcardPath = Tree.Path + "-*";
                    CommandList.Add(WildcardPath);
                }
                // If the entire subtree was enabled, there's no point descending.
                if (NumEnabled == NumChecks)
                {
                    return;
                }
            }

            foreach (var Child in Tree.Children)
            {
                if (Child.Value is CheckLeaf)
                {
                    CheckLeaf Leaf = (CheckLeaf)Child.Value;
                    if (Leaf.CountExplicitlyEnabledChecks == 1 && NewOp != TreeLevelOp.Enable)
                    {
                        CommandList.Add(Leaf.Path);
                    }
                    else if (Leaf.CountExplicitlyDisabledChecks == 1 && NewOp != TreeLevelOp.Disable)
                    {
                        CommandList.Add("-" + Leaf.Path);
                    }
                    continue;
                }

                System.Diagnostics.Debug.Assert(Child.Value is CheckTree);
                CheckTree ChildTree = (CheckTree)Child.Value;
                SerializeCheckTree(CommandList, ChildTree, NewOp);
            }
        }
 private CheckTree(string Name, CheckTree Parent)
     : base(Name, Parent)
 {
 }
        /// <summary>
        /// Convert the given check tree into serialized list of commands that can be written to
        /// the Yaml.  The goal here is to determine the minimal sequence of check commands that
        /// will produce the exact configuration displayed in the UI.  This is complicated by the
        /// fact that an inherited True is not the same as an explicitly specified True.  If the
        /// user has chosen to inherit a setting in a .clang-tidy file, then changing it in the
        /// parent should show the reflected changes in the current file as well.  So we cannot
        /// simply -* everything and then add in the checks we need, because -* immediately marks
        /// every single check as explicitly false, thus disabling inheritance.
        /// </summary>
        /// <param name="CommandList">State passed through this recursive algorithm representing
        /// the sequence of commands we have determined so far.
        /// </param>
        /// <param name="Tree">The check tree to serialize.  This is the parameter that will be
        /// recursed on as successive subtrees get serialized to `CommandList`.
        /// </param>
        /// <param name="CurrentOp">The current state of the subtree.  For example, if the
        /// algorithm decides to -* an entire subtree and then add back one single check,
        /// after adding a -subtree-* command to CommandList, it would pass in a value of
        /// CurrentOp=TreeLevelOp.Disable when it recurses down.  This allows deeper iterations
        /// of the algorithm to know what kind of command (if any) needs to be added to CommandList
        /// in order to put a particular check into a particular state.
        /// </param>
        private static void SerializeCheckTree(List<string> CommandList, CheckTree Tree, TreeLevelOp CurrentOp)
        {
            int NumChecks = Tree.CountChecks;
            int NumDisabled = Tree.CountExplicitlyDisabledChecks;
            int NumEnabled = Tree.CountExplicitlyEnabledChecks;
            int NumInherited = Tree.CountInheritedChecks;

            if (NumChecks == 0)
                return;

            if (NumInherited > 0)
                System.Diagnostics.Debug.Assert(CurrentOp == TreeLevelOp.Inherit);

            // If this entire tree is inherited, just exit, nothing about this needs to
            // go in the clang-tidy file.
            if (NumInherited == NumChecks)
                return;

            TreeLevelOp NewOp = CurrentOp;
            // If there are no inherited properties in this subtree, decide whether to
            // explicitly enable or disable this subtree.  Decide by looking at whether
            // there is a larger proportion of disabled or enabled descendants.  If
            // there are more disabled items in this subtree for example, disabling the
            // subtree will lead to a smaller configuration file.
            if (NumInherited == 0)
            {
                if (NumDisabled >= NumEnabled)
                    NewOp = TreeLevelOp.Disable;
                else
                    NewOp = TreeLevelOp.Enable;
            }

            if (NewOp == TreeLevelOp.Disable)
            {
                // Only add an explicit disable command if the tree was not already disabled
                // to begin with.
                if (CurrentOp != TreeLevelOp.Disable)
                {
                    string WildcardPath = "*";
                    if (Tree.Path != null)
                        WildcardPath = Tree.Path + "-" + WildcardPath;
                    CommandList.Add("-" + WildcardPath);
                }
                // If the entire subtree was disabled, there's no point descending.
                if (NumDisabled == NumChecks)
                    return;
            }
            else if (NewOp == TreeLevelOp.Enable)
            {
                // Only add an explicit enable command if the tree was not already enabled
                // to begin with.  Note that if we're at the root, all checks are already
                // enabled by default, so there's no need to explicitly include *
                if (CurrentOp != TreeLevelOp.Enable && Tree.Path != null)
                {
                    string WildcardPath = Tree.Path + "-*";
                    CommandList.Add(WildcardPath);
                }
                // If the entire subtree was enabled, there's no point descending.
                if (NumEnabled == NumChecks)
                    return;
            }

            foreach (var Child in Tree.Children)
            {
                if (Child.Value is CheckLeaf)
                {
                    CheckLeaf Leaf = (CheckLeaf)Child.Value;
                    if (Leaf.CountExplicitlyEnabledChecks == 1 && NewOp != TreeLevelOp.Enable)
                        CommandList.Add(Leaf.Path);
                    else if (Leaf.CountExplicitlyDisabledChecks == 1 && NewOp != TreeLevelOp.Disable)
                        CommandList.Add("-" + Leaf.Path);
                    continue;
                }

                System.Diagnostics.Debug.Assert(Child.Value is CheckTree);
                CheckTree ChildTree = (CheckTree)Child.Value;
                SerializeCheckTree(CommandList, ChildTree, NewOp);
            }
        }
Exemplo n.º 12
0
 private CheckTree(string Name, CheckTree Parent)
     : base(Name, Parent)
 {
 }
Exemplo n.º 13
0
        private CheckTree AddOrCreateSubgroup(string Name)
        {
            CheckTreeNode Subgroup = null;
            if (Children_.TryGetValue(Name, out Subgroup))
            {
                System.Diagnostics.Debug.Assert(Subgroup is CheckTree);
                return (CheckTree)Subgroup;
            }

            CheckTree SG = new CheckTree(Name, this);
            Children_[Name] = SG;
            return SG;
        }
Exemplo n.º 14
0
 public CheckLeaf(string Name, CheckTree Parent, DynamicPropertyDescriptor<bool> Property)
     : base(Name, Parent)
 {
     Property_ = Property;
 }
Exemplo n.º 15
0
        public static CheckTree Build(ClangTidyProperties Config)
        {
            // Since some check names contain dashes in them, it doesn't make sense to
            // simply split all check names by dash and construct a huge tree.  For
            // example, in the check called google-runtime-member-string-references,
            // we don't need each of those to be a different subgroup.  So instead we
            // explicitly specify the common breaking points at which a user might want
            // to use a -* and everything else falls as a leaf under one of these
            // categories.
            // FIXME: This should be configurable without recompilation
            CheckTree Root = new CheckTree();
            string[][] Groups = new string[][] {
                new string[] {"boost"},
                new string[] {"cert"},
                new string[] {"clang", "diagnostic"},
                new string[] {"cppcoreguidelines", "interfaces"},
                new string[] {"cppcoreguidelines", "pro", "bounds"},
                new string[] {"cppcoreguidelines", "pro", "type"},
                new string[] {"google", "build"},
                new string[] {"google", "readability"},
                new string[] {"google", "runtime"},
                new string[] {"llvm"},
                new string[] {"misc"},
            };

            foreach (string[] Group in Groups)
            {
                CheckTree Subgroup = Root;
                foreach (string Component in Group)
                    Subgroup = Subgroup.AddOrCreateSubgroup(Component);
            }

            var Props = Config.GetProperties()
                              .Cast<PropertyDescriptor>()
                              .OfType<DynamicPropertyDescriptor<bool>>()
                              .Where(x => x.Attributes.OfType<ClangTidyCheckAttribute>().Count() > 0)
                              .Select(x => new KeyValuePair<DynamicPropertyDescriptor<bool>, string>(
                                            x, x.Attributes.OfType<ClangTidyCheckAttribute>().First().CheckName));
            var PropArray = Props.ToArray();
            foreach (var CheckInfo in PropArray)
            {
                string LeafName = null;
                CheckTree Tree = Root.LocateCheckLeafGroup(CheckInfo.Value, out LeafName);
                Tree.AddLeaf(LeafName, CheckInfo.Key);
            }
            return Root;
        }