summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-09-07 18:28:55 +0000
committerZachary Turner <zturner@google.com>2016-09-07 18:28:55 +0000
commit1122be8e15b8244afeae5d38383f2410ba7fa102 (patch)
treedba6fa12ffd5174ce8a6702ec60bf2fc1a431251 /clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs
parentb7a619c1fa7a244d3fe88a8cf63eccd1a360bf33 (diff)
downloadbcm5719-llvm-1122be8e15b8244afeae5d38383f2410ba7fa102.tar.gz
bcm5719-llvm-1122be8e15b8244afeae5d38383f2410ba7fa102.zip
Add a clang-tidy visual studio extension.
For now this only adds the UI necessary to configure clang-tidy settings graphically, and it enables reading in and saving out of .clang-tidy files. It does not actually run clang-tidy on any source files yet. Differential Revision: https://reviews.llvm.org/D23848 llvm-svn: 280840
Diffstat (limited to 'clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs')
-rw-r--r--clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs272
1 files changed, 272 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs b/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs
new file mode 100644
index 00000000000..ab746fe32b7
--- /dev/null
+++ b/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs
@@ -0,0 +1,272 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Text;
+
+namespace LLVM.ClangTidy
+{
+ /// <summary>
+ /// CheckTree is used to group checks into categories and subcategories. For
+ /// example, given the following list of checks:
+ ///
+ /// llvm-include-order
+ /// llvm-namespace-comment
+ /// llvm-twine-local
+ /// llvm-header-guard
+ /// google-runtime-member-string-references
+ /// google-runtime-int
+ /// google-readability-namespace-comments
+ ///
+ /// the corresponding CheckTree would look like this:
+ ///
+ /// llvm
+ /// include-order
+ /// namespace-comment
+ /// twine-local
+ /// header-guard
+ /// google
+ /// runtime
+ /// member-string-references
+ /// int
+ /// readability
+ /// namespace-comments
+ /// redundant-smartptr-get
+ ///
+ /// This is useful when serializing a set of options out to a .clang-tidy file,
+ /// because we need to decide the most efficient way to serialize the sequence
+ /// of check commands, when to use wildcards, etc. For example, if everything
+ /// under google is inherited, we can simply leave that entry out entirely from
+ /// the .clang-tidy file. On the other hand, if anything is inherited, we *must
+ /// not* add or remove google-* by wildcard because that, by definition, means
+ /// the property is no longer inherited. When we can categorize the checks into
+ /// groups and subgroups like this, it is possible to efficiently serialize to
+ /// a minimal representative .clang-tidy file.
+ /// </summary>
+
+ public abstract class CheckTreeNode
+ {
+ private string Name_;
+ private CheckTreeNode Parent_;
+
+ protected CheckTreeNode(string Name, CheckTreeNode Parent)
+ {
+ Name_ = Name;
+ Parent_ = Parent;
+ }
+
+ public string Path
+ {
+ get
+ {
+ if (Parent_ == null)
+ return null;
+ string ParentPath = Parent_.Path;
+ if (ParentPath == null)
+ return Name_;
+ return ParentPath + "-" + Name_;
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return Name_;
+ }
+ }
+
+
+ public abstract int CountChecks { get; }
+ public abstract int CountExplicitlyDisabledChecks { get; }
+ public abstract int CountExplicitlyEnabledChecks { get; }
+ public abstract int CountInheritedChecks { get; }
+ }
+
+ public class CheckTree : CheckTreeNode
+ {
+ private Dictionary<string, CheckTreeNode> Children_ = new Dictionary<string, CheckTreeNode>();
+ public CheckTree()
+ : base(null, null)
+ {
+
+ }
+
+ private CheckTree(string Name, CheckTree Parent)
+ : base(Name, Parent)
+ {
+ }
+
+ private void AddLeaf(string Name, DynamicPropertyDescriptor<bool> Property)
+ {
+ Children_[Name] = new CheckLeaf(Name, this, Property);
+ }
+
+ 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;
+ }
+
+ 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 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);
+ }
+
+ public override int CountChecks
+ {
+ get
+ {
+ return Children_.Aggregate(0, (X, V) => { return X + V.Value.CountChecks; });
+ }
+ }
+
+ public override int CountExplicitlyDisabledChecks
+ {
+ get
+ {
+ return Children_.Aggregate(0, (X, V) => { return X + V.Value.CountExplicitlyDisabledChecks; });
+ }
+ }
+
+ public override int CountExplicitlyEnabledChecks
+ {
+ get
+ {
+ return Children_.Aggregate(0, (X, V) => { return X + V.Value.CountExplicitlyEnabledChecks; });
+ }
+ }
+ public override int CountInheritedChecks
+ {
+ get
+ {
+ return Children_.Aggregate(0, (X, V) => { return X + V.Value.CountInheritedChecks; });
+ }
+ }
+
+ public IDictionary<string, CheckTreeNode> Children
+ {
+ get { return Children_; }
+ }
+ }
+
+ public class CheckLeaf : CheckTreeNode
+ {
+ private DynamicPropertyDescriptor<bool> Property_;
+
+ public CheckLeaf(string Name, CheckTree Parent, DynamicPropertyDescriptor<bool> Property)
+ : base(Name, Parent)
+ {
+ Property_ = Property;
+ }
+
+ public override int CountChecks
+ {
+ get
+ {
+ return 1;
+ }
+ }
+
+ public override int CountExplicitlyDisabledChecks
+ {
+ get
+ {
+ if (Property_.IsInheriting)
+ return 0;
+ return (bool)Property_.GetValue(null) ? 0 : 1;
+ }
+ }
+
+ public override int CountExplicitlyEnabledChecks
+ {
+ get
+ {
+ if (Property_.IsInheriting)
+ return 0;
+ return (bool)Property_.GetValue(null) ? 1 : 0;
+ }
+ }
+
+ public override int CountInheritedChecks
+ {
+ get
+ {
+ return (Property_.IsInheriting) ? 1 : 0;
+ }
+ }
+
+ }
+}
OpenPOWER on IntegriCloud