Index: clang-tools-extra/trunk/CMakeLists.txt =================================================================== --- clang-tools-extra/trunk/CMakeLists.txt +++ clang-tools-extra/trunk/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(modularize) if(CLANG_ENABLE_STATIC_ANALYZER) add_subdirectory(clang-tidy) +add_subdirectory(clang-tidy-vs) endif() add_subdirectory(clang-query) Index: clang-tools-extra/trunk/clang-tidy-vs/.gitignore =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/.gitignore +++ clang-tools-extra/trunk/clang-tidy-vs/.gitignore @@ -0,0 +1,7 @@ +obj/ +bin/ +.vs/ +Key.snk +clang-tidy.exe +packages/ +*.csproj.user Index: clang-tools-extra/trunk/clang-tidy-vs/CMakeLists.txt =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/CMakeLists.txt +++ clang-tools-extra/trunk/clang-tidy-vs/CMakeLists.txt @@ -0,0 +1,28 @@ +option(BUILD_CLANG_TIDY_VS_PLUGIN "Build clang-tidy VS plugin" OFF) +if (BUILD_CLANG_TIDY_VS_PLUGIN) + add_custom_target(clang_tidy_exe_for_vsix + ${CMAKE_COMMAND} -E copy_if_different + "${LLVM_TOOLS_BINARY_DIR}/clang-tidy.exe" + "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/clang-tidy.exe" + DEPENDS clang-tidy) + + add_custom_target(clang_tidy_license + ${CMAKE_COMMAND} -E copy_if_different + "${CLANG_SOURCE_DIR}/LICENSE.TXT" + "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/license.txt") + + if (NOT CLANG_TIDY_VS_VERSION) + set(CLANG_TIDY_VS_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") + endif() + + configure_file("source.extension.vsixmanifest.in" + "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/source.extension.vsixmanifest") + + add_custom_target(clang_tidy_vsix ALL + devenv "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy.sln" /Build Release + DEPENDS clang_tidy_exe_for_vsix "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/source.extension.vsixmanifest" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/bin/Release/ClangTidy.vsix" + "${LLVM_TOOLS_BINARY_DIR}/ClangTidy.vsix" + DEPENDS clang_tidy_exe_for_vsix clang_tidy_license) +endif() Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy.sln =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy.sln +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClangTidy", "ClangTidy\ClangTidy.csproj", "{BE261DA1-36C6-449A-95C5-4653A549170A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BE261DA1-36C6-449A-95C5-4653A549170A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE261DA1-36C6-449A-95C5-4653A549170A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE261DA1-36C6-449A-95C5-4653A549170A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE261DA1-36C6-449A-95C5-4653A549170A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/CategoryVerb.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/CategoryVerb.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/CategoryVerb.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + /// + /// Allows entire categories of properties to be enabled, disabled, or inherited + /// in one fell swoop. We add properties to each category with the value being + /// this enum, and when the value is selected, we use reflection to find all other + /// properties in the same category and perform the corresponding action. + /// + public enum CategoryVerb + { + None, + Disable, + Enable, + Inherit + } + + public class CategoryVerbConverter : EnumConverter + { + public CategoryVerbConverter() : base(typeof(CategoryVerb)) + { + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string) + { + switch ((string)value) + { + case "Disable Category": + return CategoryVerb.Disable; + case "Enable Category": + return CategoryVerb.Enable; + case "Inherit Category": + return CategoryVerb.Inherit; + case "": + return CategoryVerb.None; + } + } + return base.ConvertFrom(context, culture, value); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (value is CategoryVerb && destinationType == typeof(string)) + { + switch ((CategoryVerb)value) + { + case CategoryVerb.Disable: + return "Disable Category"; + case CategoryVerb.Enable: + return "Enable Category"; + case CategoryVerb.Inherit: + return "Inherit Category"; + case CategoryVerb.None: + return String.Empty; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/CheckDatabase.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/CheckDatabase.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/CheckDatabase.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +namespace LLVM.ClangTidy +{ + public class CheckInfo + { + [YamlAlias("Name")] + public string Name { get; set; } + + [YamlAlias("Label")] + public string Label { get; set; } + + [YamlAlias("Description")] + public string Desc { get; set; } + + [YamlAlias("Category")] + public string Category { get; set; } + } + + /// + /// Reads the list of checks from Yaml and builds a description of each one. + /// This list of checks is then used by the PropertyGrid to determine what + /// items to display. + /// + public static class CheckDatabase + { + static CheckInfo[] Checks_ = null; + + class CheckRoot + { + [YamlAlias("Checks")] + public CheckInfo[] Checks { get; set; } + } + + static CheckDatabase() + { + using (StringReader Reader = new StringReader(Resources.ClangTidyChecks)) + { + Deserializer D = new Deserializer(namingConvention: new PascalCaseNamingConvention()); + var Root = D.Deserialize(Reader); + Checks_ = Root.Checks; + + HashSet Names = new HashSet(); + foreach (var Check in Checks_) + { + if (Names.Contains(Check.Name)) + throw new ArgumentException(String.Format("Check {0} exists more than once!", Check.Name)); + Names.Add(Check.Name); + } + } + } + + public static IEnumerable Checks + { + get + { + return Checks_; + } + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/CheckTree.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/CheckTree.cs +++ clang-tools-extra/trunk/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 +{ + /// + /// 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. + /// + + 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 Children_ = new Dictionary(); + public CheckTree() + : base(null, null) + { + + } + + private CheckTree(string Name, CheckTree Parent) + : base(Name, Parent) + { + } + + private void AddLeaf(string Name, DynamicPropertyDescriptor 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() + .OfType>() + .Where(x => x.Attributes.OfType().Count() > 0) + .Select(x => new KeyValuePair, string>( + x, x.Attributes.OfType().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 Children + { + get { return Children_; } + } + } + + public class CheckLeaf : CheckTreeNode + { + private DynamicPropertyDescriptor Property_; + + public CheckLeaf(string Name, CheckTree Parent, DynamicPropertyDescriptor 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; + } + } + + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidy.csproj =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidy.csproj +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidy.csproj @@ -0,0 +1,267 @@ + + + + + Debug + AnyCPU + 2.0 + {BE261DA1-36C6-449A-95C5-4653A549170A} + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + LLVM.ClangTidy + ClangTidy + true + Key.snk + v4.5 + 14.0 + + + + + 4.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 0 + false + AnyCPU + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + false + + + + + + + + + + + + + + + + + + + + + + + + ..\packages\YamlDotNet.3.3.0\lib\net35\YamlDotNet.dll + True + + + ..\packages\YamlDotNet.Dynamic.3.2.3\lib\net40\YamlDotNet.Dynamic.dll + True + + + + + {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2} + 8 + 0 + 0 + primary + False + False + + + {26AD1324-4B7C-44BC-84F8-B86AED45729F} + 10 + 0 + 0 + primary + False + False + + + {1A31287A-4D7D-413E-8E32-3B374931BD89} + 8 + 0 + 0 + primary + False + False + + + {2CE2370E-D744-4936-A090-3FFFE667B0E1} + 9 + 0 + 0 + primary + False + False + + + {1CBA492E-7263-47BB-87FE-639000619B15} + 8 + 0 + 0 + primary + False + False + + + {00020430-0000-0000-C000-000000000046} + 2 + 0 + 0 + primary + False + False + + + + + + + + + Component + + + Component + + + + + + + Component + + + + + True + True + Resources.resx + + + + + + + UserControl + + + ClangTidyPropertyGrid.cs + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + ClangTidyPropertyGrid.cs + + + true + VSPackage + + + + + + + + Designer + + + + + Menus.ctmenu + Designer + + + + + + + + true + + + true + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 4.5 + true + + + + true + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + if not exist $(ProjectDir)Key.snk ("$(SDKToolsPath)\sn.exe" -k $(ProjectDir)Key.snk) + + + + + + \ No newline at end of file Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidy.vsct =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidy.vsct +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidy.vsct @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyCheckAttribute.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyCheckAttribute.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyCheckAttribute.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + public class ClangTidyCheckAttribute : Attribute + { + private string CheckName_; + public ClangTidyCheckAttribute(string CheckName) + { + this.CheckName_ = CheckName; + } + + public string CheckName + { + get { return CheckName_; } + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyConfigParser.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyConfigParser.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyConfigParser.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +namespace LLVM.ClangTidy +{ + static class ClangTidyConfigParser + { + public class CheckOption + { + [YamlAlias("key")] + public string Key { get; set; } + + [YamlAlias("value")] + public string Value { get; set; } + } + public class ClangTidyYaml + { + [YamlAlias("Checks")] + public string Checks { get; set; } + + [YamlAlias("CheckOptions")] + public List CheckOptions { get; set; } + } + + public static List> ParseConfigurationChain(string ClangTidyFile) + { + List> Result = new List>(); + Result.Add(new KeyValuePair(null, ClangTidyProperties.RootProperties)); + + foreach (string P in Utility.SplitPath(ClangTidyFile).Reverse()) + { + if (!Utility.HasClangTidyFile(P)) + continue; + + string ConfigFile = Path.Combine(P, ".clang-tidy"); + + using (StreamReader Reader = new StreamReader(ConfigFile)) + { + Deserializer D = new Deserializer(namingConvention: new PascalCaseNamingConvention()); + ClangTidyYaml Y = D.Deserialize(Reader); + ClangTidyProperties Parent = Result[Result.Count - 1].Value; + ClangTidyProperties NewProps = new ClangTidyProperties(Parent); + SetPropertiesFromYaml(Y, NewProps); + Result.Add(new KeyValuePair(P, NewProps)); + } + } + return Result; + } + + enum TreeLevelOp + { + Enable, + Disable, + Inherit + } + + public static void SerializeClangTidyFile(ClangTidyProperties Props, string ClangTidyFilePath) + { + List CommandList = new List(); + SerializeCheckTree(CommandList, Props.GetCheckTree(), TreeLevelOp.Inherit); + + CommandList.Sort((x, y) => + { + bool LeftSub = x.StartsWith("-"); + bool RightSub = y.StartsWith("-"); + if (LeftSub && !RightSub) + return -1; + if (RightSub && !LeftSub) + return 1; + return StringComparer.CurrentCulture.Compare(x, y); + }); + + string ConfigFile = Path.Combine(ClangTidyFilePath, ".clang-tidy"); + using (StreamWriter Writer = new StreamWriter(ConfigFile)) + { + Serializer S = new Serializer(namingConvention: new PascalCaseNamingConvention()); + ClangTidyYaml Yaml = new ClangTidyYaml(); + Yaml.Checks = String.Join(",", CommandList.ToArray()); + S.Serialize(Writer, Yaml); + } + } + + /// + /// 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. + /// + /// State passed through this recursive algorithm representing + /// the sequence of commands we have determined so far. + /// + /// The check tree to serialize. This is the parameter that will be + /// recursed on as successive subtrees get serialized to `CommandList`. + /// + /// 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. + /// + private static void SerializeCheckTree(List 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 static void SetPropertiesFromYaml(ClangTidyYaml Yaml, ClangTidyProperties Props) + { + string[] CheckCommands = Yaml.Checks.Split(','); + foreach (string Command in CheckCommands) + { + if (Command == null || Command.Length == 0) + continue; + bool Add = true; + string Pattern = Command; + if (Pattern[0] == '-') + { + Pattern = Pattern.Substring(1); + Add = false; + } + + foreach (var Match in CheckDatabase.Checks.Where(x => Utility.MatchWildcardString(x.Name, Pattern))) + { + Props.SetDynamicValue(Match.Name, Add); + } + } + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyConfigurationPage.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyConfigurationPage.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyConfigurationPage.cs @@ -0,0 +1,61 @@ +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace LLVM.ClangTidy +{ + [ClassInterface(ClassInterfaceType.AutoDual)] + [CLSCompliant(false), ComVisible(true)] + public class ClangTidyConfigurationPage : DialogPage + { + ClangTidyPropertyGrid Grid = null; + protected override IWin32Window Window + { + get + { + if (Grid == null) + Grid = new ClangTidyPropertyGrid(); + return Grid; + } + } + + protected override void SaveSetting(PropertyDescriptor property) + { + base.SaveSetting(property); + } + + public override void SaveSettingsToStorage() + { + if (Grid != null) + Grid.SaveSettingsToStorage(); + + base.SaveSettingsToStorage(); + } + + public override void ResetSettings() + { + base.ResetSettings(); + } + + protected override void LoadSettingFromStorage(PropertyDescriptor prop) + { + base.LoadSettingFromStorage(prop); + } + + public override void LoadSettingsFromStorage() + { + if (Grid != null) + Grid.InitializeSettings(); + base.LoadSettingsFromStorage(); + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs @@ -0,0 +1,56 @@ +//===-- ClangTidyPackages.cs - VSPackage for clang-tidy ----------*- C# -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class contains a VS extension package that runs clang-tidy over a +// file in a VS text editor. +// +//===----------------------------------------------------------------------===// + +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using System.Xml.Linq; + +namespace LLVM.ClangTidy +{ + [PackageRegistration(UseManagedResourcesOnly = true)] + [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] + [ProvideMenuResource("Menus.ctmenu", 1)] + [Guid(GuidList.guidClangTidyPkgString)] + [ProvideOptionPage(typeof(ClangTidyConfigurationPage), "LLVM/Clang", "ClangTidy", 0, 0, true)] + public sealed class ClangTidyPackage : Package + { + #region Package Members + protected override void Initialize() + { + base.Initialize(); + + var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; + if (commandService != null) + { + var menuCommandID = new CommandID(GuidList.guidClangTidyCmdSet, (int)PkgCmdIDList.cmdidClangTidy); + var menuItem = new MenuCommand(MenuItemCallback, menuCommandID); + commandService.AddCommand(menuItem); + } + } + #endregion + + private void MenuItemCallback(object sender, EventArgs args) + { + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyProperties.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyProperties.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyProperties.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + + public class ClangTidyProperties : DynamicPropertyComponent + { + private static ClangTidyProperties RootProperties_ = null; + private CheckTree CheckTree_; + private bool HasUnsavedChanges_ = false; + + public struct CheckMapping + { + public string CheckName; + public string Property; + } + + public ClangTidyProperties() + : base(null) + { + AddClangCheckProperties(); + CheckTree_ = CheckTree.Build(this); + } + + public ClangTidyProperties(DynamicPropertyComponent Parent) + : base(Parent) + { + AddClangCheckProperties(); + CheckTree_ = CheckTree.Build(this); + } + + static ClangTidyProperties() + { + RootProperties_ = new ClangTidyProperties(null); + PropertyDescriptor D; + } + + public static ClangTidyProperties RootProperties + { + get { return RootProperties_; } + } + + private void AddClangCheckProperties() + { + // Add each check in the check database + HashSet Categories = new HashSet(); + foreach (var Check in CheckDatabase.Checks) + { + string Name = Check.Name.Replace('-', '_'); + List Attrs = new List(); + Attrs.Add(new CategoryAttribute(Check.Category)); + Attrs.Add(new DisplayNameAttribute(Check.Label)); + Attrs.Add(new DefaultValueAttribute(true)); + Attrs.Add(new DescriptionAttribute(Check.Desc)); + Attrs.Add(new ClangTidyCheckAttribute(Check.Name)); + Categories.Add(Check.Category); + AddDynamicProperty(Check.Name, Attrs.ToArray()); + } + + // Add a category verb for each unique category. + foreach (string Cat in Categories) + { + List Attrs = new List(); + Attrs.Add(new CategoryAttribute(Cat)); + Attrs.Add(new DisplayNameAttribute("(Category Verbs)")); + Attrs.Add(new TypeConverterAttribute(typeof(CategoryVerbConverter))); + Attrs.Add(new DefaultValueAttribute(CategoryVerb.None)); + AddDynamicProperty(Cat + "Verb", Attrs.ToArray()); + } + } + + public CheckTree GetCheckTree() { return CheckTree_; } + public bool GetHasUnsavedChanges() { return HasUnsavedChanges_; } + public void SetHasUnsavedChanges(bool Value) { HasUnsavedChanges_ = Value; } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.Designer.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.Designer.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.Designer.cs @@ -0,0 +1,119 @@ +namespace LLVM.ClangTidy +{ + partial class ClangTidyPropertyGrid + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.propertyGrid1 = new System.Windows.Forms.PropertyGrid(); + this.clangTidyProperties1 = new LLVM.ClangTidy.ClangTidyProperties(); + this.clangTidyConfigurationPage1 = new LLVM.ClangTidy.ClangTidyConfigurationPage(); + this.linkLabelPath = new System.Windows.Forms.LinkLabel(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(14, 17); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(88, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Configuration File"; + // + // textBox1 + // + this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox1.Location = new System.Drawing.Point(108, 14); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(222, 20); + this.textBox1.TabIndex = 1; + // + // button1 + // + this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.button1.Location = new System.Drawing.Point(336, 14); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(78, 20); + this.button1.TabIndex = 2; + this.button1.Text = "Browse"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // propertyGrid1 + // + this.propertyGrid1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.propertyGrid1.Location = new System.Drawing.Point(20, 73); + this.propertyGrid1.Name = "propertyGrid1"; + this.propertyGrid1.SelectedObject = this.clangTidyProperties1; + this.propertyGrid1.Size = new System.Drawing.Size(391, 384); + this.propertyGrid1.TabIndex = 6; + this.propertyGrid1.ViewBorderColor = System.Drawing.SystemColors.ControlDarkDark; + this.propertyGrid1.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid1_PropertyValueChanged); + // + // linkLabelPath + // + this.linkLabelPath.AutoSize = true; + this.linkLabelPath.Location = new System.Drawing.Point(29, 50); + this.linkLabelPath.Name = "linkLabelPath"; + this.linkLabelPath.Size = new System.Drawing.Size(55, 13); + this.linkLabelPath.TabIndex = 7; + this.linkLabelPath.TabStop = true; + this.linkLabelPath.Text = "linkLabel1"; + this.linkLabelPath.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelPath_LinkClicked); + // + // ClangTidyPropertyGrid + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.linkLabelPath); + this.Controls.Add(this.propertyGrid1); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.Name = "ClangTidyPropertyGrid"; + this.Size = new System.Drawing.Size(444, 469); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.PropertyGrid propertyGrid1; + private ClangTidyProperties clangTidyProperties1; + private ClangTidyConfigurationPage clangTidyConfigurationPage1; + private System.Windows.Forms.LinkLabel linkLabelPath; + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs @@ -0,0 +1,215 @@ +//===-- ClangTidyPropertyGrid.cs - UI for configuring clang-tidy -*- C# -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class contains a UserControl consisting of a .NET PropertyGrid control +// allowing configuration of checks and check options for ClangTidy. +// +//===----------------------------------------------------------------------===// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.IO; +using Microsoft.VisualStudio.Shell; + +namespace LLVM.ClangTidy +{ + /// + /// A UserControl displaying a PropertyGrid allowing configuration of clang-tidy + /// checks and check options, as well as serialization and deserialization of + /// clang-tidy configuration files. When a configuration file is loaded, the + /// entire chain of configuration files is analyzed based on the file path, + /// and quick access is provided to edit or view any of the files in the + /// configuration chain, allowing easy visualization of where values come from + /// (similar in spirit to the -explain-config option of clang-tidy). + /// + public partial class ClangTidyPropertyGrid : UserControl + { + /// + /// The sequence of .clang-tidy configuration files, starting from the root + /// of the filesystem, down to the selected file. + /// + List> PropertyChain_ = null; + + /// + /// A tree representing all the checks that the extension knows about, used + /// when serializing a file to intelligently determine when to use wildcard + /// include / exclude rules. + /// + CheckTree Checks_; + + public ClangTidyPropertyGrid() + { + InitializeComponent(); + InitializeSettings(); + } + + private enum ShouldCancel + { + Yes, + No, + } + + public void SaveSettingsToStorage() + { + PersistUnsavedChanges(false); + } + + private ShouldCancel PersistUnsavedChanges(bool PromptFirst) + { + var UnsavedResults = PropertyChain_.Where(x => x.Key != null && x.Value.GetHasUnsavedChanges()); + if (UnsavedResults.Count() == 0) + return ShouldCancel.No; + + bool ShouldSave = false; + if (PromptFirst) + { + var Response = MessageBox.Show( + "You have unsaved changes! Do you want to save before loading a new file?", + "clang-tidy", + MessageBoxButtons.YesNoCancel); + + ShouldSave = (Response == DialogResult.Yes); + if (Response == DialogResult.Cancel) + return ShouldCancel.Yes; + } + else + ShouldSave = true; + + if (ShouldSave) + { + foreach (var Result in UnsavedResults) + { + ClangTidyConfigParser.SerializeClangTidyFile(Result.Value, Result.Key); + Result.Value.SetHasUnsavedChanges(false); + } + } + return ShouldCancel.No; + } + + public void InitializeSettings() + { + PropertyChain_ = new List>(); + PropertyChain_.Add(new KeyValuePair(null, ClangTidyProperties.RootProperties)); + reloadPropertyChain(); + } + + private void button1_Click(object sender, EventArgs e) + { + ShouldCancel Cancel = PersistUnsavedChanges(true); + if (Cancel == ShouldCancel.Yes) + return; + + using (OpenFileDialog D = new OpenFileDialog()) + { + D.Filter = "Clang Tidy files|.clang-tidy"; + D.CheckPathExists = true; + D.CheckFileExists = true; + + if (D.ShowDialog() == DialogResult.OK) + { + PropertyChain_.Clear(); + PropertyChain_ = ClangTidyConfigParser.ParseConfigurationChain(D.FileName); + textBox1.Text = D.FileName; + reloadPropertyChain(); + } + } + } + + private static readonly string DefaultText = "(Default)"; + private static readonly string BrowseText = "Browse for a file to edit its properties"; + + /// + /// After a new configuration file is chosen, analyzes the directory hierarchy + /// and finds all .clang-tidy files in the path, parses them and updates the + /// PropertyGrid and quick-access LinkLabel control to reflect the new property + /// chain. + /// + private void reloadPropertyChain() + { + StringBuilder LinkBuilder = new StringBuilder(); + LinkBuilder.Append(DefaultText); + LinkBuilder.Append(" > "); + int PrefixLength = LinkBuilder.Length; + + if (PropertyChain_.Count == 1) + LinkBuilder.Append(BrowseText); + else + LinkBuilder.Append(PropertyChain_[PropertyChain_.Count - 1].Key); + + linkLabelPath.Text = LinkBuilder.ToString(); + + // Given a path like D:\Foo\Bar\Baz, construct a LinkLabel where individual + // components of the path are clickable iff they contain a .clang-tidy file. + // Clicking one of the links then updates the PropertyGrid to display the + // selected .clang-tidy file. + ClangTidyProperties LastProps = ClangTidyProperties.RootProperties; + linkLabelPath.Links.Clear(); + linkLabelPath.Links.Add(0, DefaultText.Length, LastProps); + foreach (var Prop in PropertyChain_.Skip(1)) + { + LastProps = Prop.Value; + string ClangTidyFolder = Path.GetFileName(Prop.Key); + int ClangTidyFolderOffset = Prop.Key.Length - ClangTidyFolder.Length; + linkLabelPath.Links.Add(PrefixLength + ClangTidyFolderOffset, ClangTidyFolder.Length, LastProps); + } + propertyGrid1.SelectedObject = LastProps; + } + + private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) + { + ClangTidyProperties Props = (ClangTidyProperties)propertyGrid1.SelectedObject; + Props.SetHasUnsavedChanges(true); + + // When a CategoryVerb is selected, perform the corresponding action. + PropertyDescriptor Property = e.ChangedItem.PropertyDescriptor; + if (!(e.ChangedItem.Value is CategoryVerb)) + return; + + CategoryVerb Action = (CategoryVerb)e.ChangedItem.Value; + if (Action == CategoryVerb.None) + return; + + var Category = Property.Attributes.OfType().FirstOrDefault(); + if (Category == null) + return; + var SameCategoryProps = Props.GetProperties(new Attribute[] { Category }); + foreach (PropertyDescriptor P in SameCategoryProps) + { + if (P == Property) + continue; + switch (Action) + { + case CategoryVerb.Disable: + P.SetValue(propertyGrid1.SelectedObject, false); + break; + case CategoryVerb.Enable: + P.SetValue(propertyGrid1.SelectedObject, true); + break; + case CategoryVerb.Inherit: + P.ResetValue(propertyGrid1.SelectedObject); + break; + } + } + Property.ResetValue(propertyGrid1.SelectedObject); + propertyGrid1.Invalidate(); + } + + private void linkLabelPath_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + ClangTidyProperties Props = (ClangTidyProperties)e.Link.LinkData; + propertyGrid1.SelectedObject = Props; + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.resx =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.resx +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 183, 17 + + \ No newline at end of file Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.Designer.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.Designer.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.Designer.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + partial class DynamicPropertyComponent + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + /// + /// The goal of this class is to enable displaying of a PropertyGrid in much the + /// same way that Visual Studio's C++ project system does. A project or file can + /// have properties which might inherit from their parent, or be overridden. + /// It turns out this is somewhat non-trivial. The .NET PropertyGrid is good makes + /// displaying simple properties with a static notion of what constitutes a + /// "default" value very easy. You simply apply an Attribute to the class that says + /// what the default value is and you're done. But when you try to introduce the idea + /// that a property's default value depends on some other factor, things get much more + /// complicated due to the static nature of Attributes. + /// + /// The solution to this is to inherit from ICustomTypeDescriptor. This is the mechanism + /// by which you can inject or modify attributes or properties at runtime. The .NET + /// PropertyGrid is designed in such a way that instead of using simple .NET Reflection to + /// look for the properties and attributes on a class, it will invoke the methods of + /// ICustomTypeDescriptor (if your type inherits from it), and ask those methods. Our + /// implementation of ICustomTypeDescriptor works by waiting until the PropertyGrid requests + /// PropertyDescriptors for each of the properties, and then "decorating" them with our + /// own custom PropertyDescriptor implementation which understands the proeprty inheritance + /// model we wish to implement. + /// + public partial class DynamicPropertyComponent : Component, ICustomTypeDescriptor + { + PropertyDescriptorCollection DynamicProperties_ = new PropertyDescriptorCollection(null); + private DynamicPropertyComponent Parent_; + + public DynamicPropertyComponent(DynamicPropertyComponent Parent) + { + Parent_ = Parent; + } + + public DynamicPropertyComponent(DynamicPropertyComponent Parent, IContainer container) + { + Parent_ = Parent; + + container.Add(this); + InitializeComponent(); + } + + public AttributeCollection GetAttributes() + { + return TypeDescriptor.GetAttributes(GetType()); + } + + public string GetClassName() + { + return TypeDescriptor.GetClassName(GetType()); + } + + public string GetComponentName() + { + return TypeDescriptor.GetComponentName(GetType()); + } + + public TypeConverter GetConverter() + { + return TypeDescriptor.GetConverter(GetType()); + } + + public EventDescriptor GetDefaultEvent() + { + return TypeDescriptor.GetDefaultEvent(GetType()); + } + + public PropertyDescriptor GetDefaultProperty() + { + return TypeDescriptor.GetDefaultProperty(GetType()); + } + + public object GetEditor(Type editorBaseType) + { + return TypeDescriptor.GetEditor(GetType(), editorBaseType); + } + + public EventDescriptorCollection GetEvents() + { + return TypeDescriptor.GetEvents(GetType()); + } + + public EventDescriptorCollection GetEvents(Attribute[] attributes) + { + return TypeDescriptor.GetEvents(GetType(), attributes); + } + + public PropertyDescriptorCollection GetProperties() + { + return DynamicProperties_; + } + + public PropertyDescriptorCollection GetProperties(Attribute[] attributes) + { + var Props = DynamicProperties_.OfType(); + var Filtered = Props.Where(x => x.Attributes.Contains(attributes)).ToArray(); + return new PropertyDescriptorCollection(Filtered); + } + + public object GetPropertyOwner(PropertyDescriptor pd) + { + return this; + } + + public void SetDynamicValue(string Name, T Value) + { + Name = Name.Replace('-', '_'); + DynamicPropertyDescriptor Descriptor = (DynamicPropertyDescriptor)DynamicProperties_.Find(Name, false); + Descriptor.SetValue(this, Value); + } + + public T GetDynamicValue(string Name) + { + Name = Name.Replace('-', '_'); + DynamicPropertyDescriptor Descriptor = (DynamicPropertyDescriptor)DynamicProperties_.Find(Name, false); + return (T)Descriptor.GetValue(this); + } + + protected void AddDynamicProperty(string Name, Attribute[] Attributes) + { + Name = Name.Replace('-', '_'); + + // If we have a parent, find the corresponding PropertyDescriptor with the same + // name from the parent. + DynamicPropertyDescriptor ParentDescriptor = null; + if (Parent_ != null) + ParentDescriptor = (DynamicPropertyDescriptor)Parent_.GetProperties().Find(Name, false); + + DynamicProperties_.Add(new DynamicPropertyDescriptor(Name, ParentDescriptor, Name, Attributes)); + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyConverter.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyConverter.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyConverter.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + class MagicInheritance + { + public static readonly string Value = "{3A27184D-1774-489B-9BB7-7191B8E8E622}"; + public static readonly string Text = ""; + } + + + class DynamicPropertyConverter : TypeConverter + { + private DynamicPropertyDescriptor Descriptor_; + private TypeConverter Root_; + + public DynamicPropertyConverter(DynamicPropertyDescriptor Descriptor, TypeConverter Root) + { + Descriptor_ = Descriptor; + Root_ = Root; + } + + /// + /// Returns true if there are specific values that can be chosen from a dropdown + /// for this property. Regardless of whether standard values are supported for + /// the underlying type, we always support standard values because we need to + /// display the inheritance option. + /// + /// true + public override bool GetStandardValuesSupported(ITypeDescriptorContext context) + { + return true; + } + + /// + /// Get the set of all standard values that can be chosen from a dropdown for this + /// property. If the underlying type supports standard values, we want to include + /// all those. Additionally, we want to display the option to inherit the value, + /// but only if the value is not already inheriting. + /// + public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) + { + List Values = new List(); + if (Root_.GetStandardValuesSupported(context)) + { + StandardValuesCollection RootValues = Root_.GetStandardValues(context); + Values.AddRange(RootValues.Cast()); + } + if (!Descriptor_.IsInheriting) + Values.Add(MagicInheritance.Value); + StandardValuesCollection Result = new StandardValuesCollection(Values); + return Result; + } + + /// + /// Determines whether this property can accept values other than those specified + /// in the dropdown (for example by manually typing into the field). + /// + public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) + { + // Although we add items to the dropdown list, we do not change whether or not + // the set of values are exclusive. If the user could type into the field before + // they still can. And if they couldn't before, they still can't. + return Root_.GetStandardValuesExclusive(context); + } + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return Root_.CanConvertFrom(context, sourceType); + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return Root_.CanConvertTo(context, destinationType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value.Equals(MagicInheritance.Value)) + return MagicInheritance.Text; + return Root_.ConvertFrom(context, culture, value); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (value.GetType() == destinationType) + return value; + + return Root_.ConvertTo(context, culture, value, destinationType); + } + + public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) + { + return Root_.CreateInstance(context, propertyValues); + } + + public override bool Equals(object obj) + { + return Root_.Equals(obj); + } + + public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) + { + return Root_.GetCreateInstanceSupported(context); + } + + public override int GetHashCode() + { + return Root_.GetHashCode(); + } + + public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) + { + return Root_.GetProperties(context, value, attributes); + } + + public override bool GetPropertiesSupported(ITypeDescriptorContext context) + { + return Root_.GetPropertiesSupported(context); + } + + public override bool IsValid(ITypeDescriptorContext context, object value) + { + return Root_.IsValid(context, value); + } + + public override string ToString() + { + return Root_.ToString(); + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyDescriptor.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyDescriptor.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/DynamicPropertyDescriptor.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + public class DynamicPropertyDescriptor : PropertyDescriptor + { + T Value_; + DynamicPropertyDescriptor Parent_; + bool IsInheriting_; + object Component_; + + public DynamicPropertyDescriptor(object Component, DynamicPropertyDescriptor Parent, string Name, Attribute[] Attrs) + : base(Name, Attrs) + { + foreach (DefaultValueAttribute Attr in Attrs.OfType()) + { + Value_ = (T)Attr.Value; + } + Parent_ = Parent; + IsInheriting_ = true; + Component_ = Component; + } + + public bool IsInheriting { get { return IsInheriting_; } set { IsInheriting_ = value; } } + public DynamicPropertyDescriptor Parent { get { return Parent_; } } + + /// + /// Determines whether this property's value should be considered "default" (e.g. + /// displayed in bold in the property grid). Root properties are unmodifiable and + /// always default. Non-root properties are default iff they are inheriting. + /// That is to say, if a property is explicitly set to False, the property should + /// be serialized even if the parent is also False. It would only not be serialized + /// if the user had explicitly chosen to inherit it. + /// + /// + /// + public override bool ShouldSerializeValue(object component) + { + return (Parent_ != null) && !IsInheriting; + } + + /// + /// Set the value back to the default. For root properties, this essentially does + /// nothing as they are read-only anyway. For non-root properties, this only means + /// that the property is now inheriting. + /// + /// + public override void ResetValue(object component) + { + IsInheriting_ = true; + } + + public override void SetValue(object component, object value) + { + // This is a bit of a trick. If the user chose the inheritance option from the + // dropdown, we will try to set the value to that string. So look for that and + // then just reset the value. + if (value.Equals(MagicInheritance.Text)) + ResetValue(component); + else + { + // By explicitly setting the value, this property is no longer inheriting, + // even if the value the property is being set to is the same as that of + // the parent. + IsInheriting_ = false; + Value_ = (T)value; + } + } + + public override TypeConverter Converter + { + get + { + // We need to return a DynamicPropertyConverter<> that can deal with our requirement + // to inject the inherit property option into the dropdown. But we still need to use + // the "real" converter to do the actual work for the underlying type. Therefore, + // we need to look for a TypeConverter<> attribute on the property, and if it is present + // forward an instance of that converter to the DynamicPropertyConverter<>. Otherwise, + // forward an instance of the default converter for type T to the DynamicPropertyConverter<>. + TypeConverter UnderlyingConverter = null; + var ConverterAttr = this.Attributes.OfType().LastOrDefault(); + if (ConverterAttr != null) + { + Type ConverterType = Type.GetType(ConverterAttr.ConverterTypeName); + UnderlyingConverter = (TypeConverter)Activator.CreateInstance(ConverterType); + } + else + UnderlyingConverter = TypeDescriptor.GetConverter(typeof(T)); + + return new DynamicPropertyConverter(this, UnderlyingConverter); + } + } + + public override bool IsReadOnly + { + get + { + return (Parent_ == null); + } + } + + public override Type ComponentType + { + get + { + return Component_.GetType(); + } + } + + public override object GetValue(object component) + { + // Return either this property's value or the parents value, depending on + // whether or not this property is inheriting. + if (IsInheriting_ && Parent != null) + return Parent.GetValue(component); + return Value_; + } + + public override bool CanResetValue(object component) + { + return !IsReadOnly; + } + + public override Type PropertyType + { + get + { + return typeof(T); + } + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ForwardingPropertyDescriptor.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ForwardingPropertyDescriptor.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/ForwardingPropertyDescriptor.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + /// + /// A decorator of sorts. Accepts a PropertyDescriptor to its constructor + /// and forwards all calls to the underlying PropertyDescriptor. In this way + /// we can inherit from ForwardingPropertyDescriptor and override only the + /// few methods we need to customize the behavior of, while allowing the + /// underlying PropertyDescriptor to do the real work. + /// + public abstract class ForwardingPropertyDescriptor : PropertyDescriptor + { + private readonly PropertyDescriptor root; + protected PropertyDescriptor Root { get { return root; } } + protected ForwardingPropertyDescriptor(PropertyDescriptor root) + : base(root) + { + this.root = root; + } + + public override void AddValueChanged(object component, EventHandler handler) + { + root.AddValueChanged(component, handler); + } + + public override AttributeCollection Attributes + { + get + { + return root.Attributes; + } + } + + public override bool CanResetValue(object component) + { + return root.CanResetValue(component); + } + + public override string Category + { + get + { + return root.Category; + } + } + + public override Type ComponentType + { + get + { + return root.ComponentType; + } + } + + public override TypeConverter Converter + { + get + { + return root.Converter; + } + } + + public override string Description + { + get + { + return root.Description; + } + } + + public override bool DesignTimeOnly + { + get + { + return root.DesignTimeOnly; + } + } + + public override string DisplayName + { + get + { + return root.DisplayName; + } + } + + public override bool Equals(object obj) + { + return root.Equals(obj); + } + + public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter) + { + return root.GetChildProperties(instance, filter); + } + + public override object GetEditor(Type editorBaseType) + { + return root.GetEditor(editorBaseType); + } + + public override int GetHashCode() + { + return root.GetHashCode(); + } + + public override object GetValue(object component) + { + return root.GetValue(component); + } + + public override bool IsBrowsable + { + get + { + return root.IsBrowsable; + } + } + + public override bool IsLocalizable + { + get + { + return root.IsLocalizable; + } + } + + public override bool IsReadOnly + { + get + { + return root.IsReadOnly; + } + } + + public override string Name + { + get + { + return root.Name; + } + } + + public override Type PropertyType + { + get + { + return root.PropertyType; + } + } + + public override void RemoveValueChanged(object component, EventHandler handler) + { + root.RemoveValueChanged(component, handler); + } + + public override void ResetValue(object component) + { + root.ResetValue(component); + } + + public override void SetValue(object component, object value) + { + root.SetValue(component, value); + } + + public override bool ShouldSerializeValue(object component) + { + return root.ShouldSerializeValue(component); + } + + public override bool SupportsChangeEvents + { + get + { + return root.SupportsChangeEvents; + } + } + + public override string ToString() + { + return root.ToString(); + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/GlobalSuppressions.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/GlobalSuppressions.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/GlobalSuppressions.cs @@ -0,0 +1,11 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. Project-level +// suppressions either have no target or are given a specific target +// and scoped to a namespace, type, member, etc. +// +// To add a suppression to this file, right-click the message in the +// Error List, point to "Suppress Message(s)", and click "In Project +// Suppression File". You do not need to add suppressions to this +// file manually. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")] Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Guids.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Guids.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Guids.cs @@ -0,0 +1,12 @@ +using System; + +namespace LLVM.ClangTidy +{ + static class GuidList + { + public const string guidClangTidyPkgString = "AE4956BE-3DB8-430E-BBAB-7E2E9A014E9C"; + public const string guidClangTidyCmdSetString = "9E0F0493-6493-46DE-AEE1-ACD8F60F265E"; + + public static readonly Guid guidClangTidyCmdSet = new Guid(guidClangTidyCmdSetString); + }; +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/PkgCmdID.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/PkgCmdID.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/PkgCmdID.cs @@ -0,0 +1,7 @@ +namespace LLVM.ClangTidy +{ + static class PkgCmdIDList + { + public const uint cmdidClangTidy = 0x100; + }; +} \ No newline at end of file Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Properties/AssemblyInfo.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Properties/AssemblyInfo.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ClangFormat")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("LLVM")] +[assembly: AssemblyProduct("ClangFormat")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +[assembly: NeutralResourcesLanguage("en-US")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +// FIXME: Add a way to have this generated automatically by CMake +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources.Designer.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources.Designer.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace LLVM.ClangTidy { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LLVM.ClangTidy.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to --- + ///Checks: + ///Checks: + /// - Name: cert-dcl54-cpp + /// Label: Overloaded allocation function pairs + /// Description: Checks for violations of CERT DCL54-CPP - Overload allocation and deallocation functions as a pair in the same scope + /// Category: CERT Secure Coding Standards + /// - Name: cppcoreguidelines-interfaces-global-init + /// Label: I.22 - Complex Global Initializers + /// Description: Checks for violations of Core Guideline I.22 - Avoid complex initializers of global object [rest of string was truncated]";. + /// + internal static string ClangTidyChecks { + get { + return ResourceManager.GetString("ClangTidyChecks", resourceCulture); + } + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources.resx =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources.resx +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Resources\ClangTidyChecks.yaml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + \ No newline at end of file Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources/ClangTidyChecks.yaml =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources/ClangTidyChecks.yaml +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Resources/ClangTidyChecks.yaml @@ -0,0 +1,325 @@ +--- +Checks: + # This file should be updated when new checks are added, and eventually we should + # generate this file automatically from the .rst files in clang-tidy. + - Category: CERT Secure Coding Standards + Label: Overloaded allocation function pairs + Description: Checks for violations of CERT DCL54-CPP - Overload allocation and deallocation functions as a pair in the same scope + Name: cert-dcl54-cpp + - Category: C++ Core Guidelines + Label: I.22 - Complex Global Initializers + Description: Checks for violations of Core Guideline I.22 - Avoid complex initializers of global objects + Name: cppcoreguidelines-interfaces-global-init + - Category: CERT Secure Coding Standards + Label: DCL50-CPP + Description: Checks for violations of CERT DCL50-CPP - Do not define a C-style variadic function + Name: cert-dcl50-cpp + - Category: C++ Core Guidelines + Label: Bounds.1 - No pointer arithmetic + Description: Checks for violations of Core Guideline Bounds.3 - Don't use pointer arithmetic. Use span<> instead. + Name: cppcoreguidelines-pro-bounds-pointer-arithmetic + - Category: C++ Core Guidelines + Label: Bounds.2 - Constant array indices + Description: Checks for violations of Core Bounds.2 - Only index into arrays using constant expressions. + Name: cppcoreguidelines-pro-bounds-constant-array-index + - Category: C++ Core Guidelines + Label: Bounds.3 - Array to Pointer Decay + Description: Checks for violations of Core Guideline Bounds.3 - No array-to-pointer decay + Name: cppcoreguidelines-pro-bounds-array-to-pointer-decay + - Category: C++ Core Guidelines + Label: const_cast (Type.3) + Description: Checks for violations of Core Guideline Type.3 - Don't use const_cast to cast away const + Name: cppcoreguidelines-pro-type-const-cast + - Category: C++ Core Guidelines + Label: C style casts (Type.4) + Description: Checks for violations of Core Guideline Type.3 - Don't use C-style (T)expression casts that would perform a static downcast, const_cast, or reinterpret_cast + Name: cppcoreguidelines-pro-type-cstyle-cast + - Category: C++ Core Guidelines + Label: reinterpret_cast (Type.1) + Description: Checks for violations of Core Guideline Type.1 - Don't use reinterpret_cast. + Name: cppcoreguidelines-pro-type-reinterpret-cast + - Category: C++ Core Guidelines + Label: Prefer dynamic_cast (Type.2) + Description: Checks for violations of Core Guideline Type.2 - Don't use static_cast downcasts. Use dynamic_cast instead. + Name: cppcoreguidelines-pro-type-static-cast-downcast + - Category: C++ Core Guidelines + Label: Member variable initialization (Type.6) + Description: Checks for violations of Core Guideline Type.6 - Always initialize a member variable. + Name: cppcoreguidelines-pro-type-member-init + - Category: C++ Core Guidelines + Label: Avoid unions (Type.7) + Description: Checks for violations of Core Guideline Type.7 - Avoid accessing members of raw unions. Use variant instead. + Name: cppcoreguidelines-pro-type-union-access + - Category: C++ Core Guidelines + Label: Don't use varargs (Type.8) + Description: Checks for violations of Core Guideline Type.8 - Avoid reading varargs or passing vararg arguments. Prefer variadic templates instead. + Name: cppcoreguidelines-pro-type-vararg + - Category: C++ Core Guidelines + Label: Don't slice (ES.63 & C.145) + Description: Checks for violations of Core Guidelines ES.63 (Don't slice) and C.145 (Access polymorphic objects through pointers and references) + Name: cppcoreguidelines-slicing + - Category: C++ Core Guidelines + Label: Detect unsafe special functions (C.21) + Description: Checks for violations of Core Guidelines C.21 - If you define or =delete any default operation, define or =delete them all. + Name: cppcoreguidelines-special-member-functions + - Category: Google Style Guide + Label: Forbid explicitly parameterized make_pair + Description: + Name: google-build-explicit-make-pair + - Category: Google Style Guide + Label: Anonymous namespace in headers + Description: + Name: google-build-namespaces + - Category: Google Style Guide + Label: Find using namespace directives + Description: + Name: google-build-using-namespace + - Category: Google Style Guide + Label: Default arguments in virtual methods + Description: + Name: google-default-arguments + - Category: Google Style Guide + Label: explicit constructors + Description: + Name: google-explicit-constructor + - Category: Google Style Guide + Label: Global namespace pollution in headers + Description: + Name: google-global-names-in-headers + - Category: Google Style Guide + Label: Braces around statements + Description: + Name: google-readability-braces-around-statements + - Category: Google Style Guide + Label: No C-style casts + Description: + Name: google-readability-casting + - Category: Google Style Guide + Label: Find large functions + Description: + Name: google-readability-function-size + - Category: Google Style Guide + Label: Namespace closing comments + Description: + Name: google-readability-namespace-comments + - Category: Google Style Guide + Label: Find unnecessary calls to .get() + Description: + Name: google-readability-redundant-smartptr-get + - Category: Google Style Guide + Label: Find noncomformant TODO comments + Description: + Name: google-readability-todo + - Category: Google Style Guide + Label: Find implementation-specific integral types + Description: + Name: google-runtime-int + - Category: Google Style Guide + Label: Find const string references + Description: + Name: google-runtime-member-string-references + - Category: Google Style Guide + Label: Find zero-length memsets + Description: + Name: google-runtime-memset + - Category: Google Style Guide + Label: Find overloads of operator& + Description: + Name: google-runtime-operator + - Category: Google Style Guide + Label: Check usage of non-const references + Description: + Name: google-runtime-references + - Category: LLVM Style Guide + Label: LLVM header guards + Description: + Name: llvm-header-guard + - Category: LLVM Style Guide + Label: LLVM include order + Description: + Name: llvm-include-order + - Category: LLVM Style Guide + Label: LLVM namespace comments + Description: + Name: llvm-namespace-comment + - Category: LLVM Style Guide + Label: Find local twines + Description: + Name: llvm-twine-local + - Category: Clang Diagnostics + Label: Warnings + Description: + Name: clang-diagnostic-warning + - Category: Clang Diagnostics + Label: Errors + Description: + Name: clang-diagnostic-error + - Category: Clang Diagnostics + Label: Unknown + Description: + Name: clang-diagnostic-unknown + - Category: Miscellaneous + Label: Validate argument comments + Description: + Name: misc-argument-comment + - Category: Miscellaneous + Label: Side effects in assert() + Description: + Name: misc-assert-side-effect + - Category: Miscellaneous + Label: bool / pointer implicit conversions + Description: + Name: misc-bool-pointer-implicit-conversion + - Category: Miscellaneous + Label: Dangling handles + Description: + Name: misc-dangling-handle + - Category: Miscellaneous + Label: Definitions in headers + Description: + Name: misc-definitions-in-headers + - Category: Miscellaneous + Label: Type mismatch in fold operations + Description: + Name: misc-fold-init-type + - Category: Miscellaneous + Label: Forward declaration namespace + Description: + Name: misc-forward-declaration-namespace + - Category: Miscellaneous + Label: Inaccurate erase + Description: + Name: misc-inaccurate-erase + - Category: Miscellaneous + Label: Incorrect rounding + Description: + Name: misc-incorrect-roundings + - Category: Miscellaneous + Label: Inefficient STL algorithms + Description: + Name: misc-inefficient-algorithm + - Category: Miscellaneous + Label: Macro parentheses + Description: + Name: misc-macro-parentheses + - Category: Miscellaneous + Label: Macro repeated side effects + Description: + Name: misc-macro-repeated-side-effects + - Category: Miscellaneous + Label: Misplaced const + Description: + Name: misc-misplaced-const + - Category: Miscellaneous + Label: Misplaced widening casts + Description: + Name: misc-misplaced-widening-cast + - Category: Miscellaneous + Label: Move constructor const arguments + Description: + Name: misc-move-const-arg + - Category: Miscellaneous + Label: Move constructor initialization + Description: + Name: misc-move-constructor-init + - Category: Miscellaneous + Label: Multi-statement macros + Description: + Name: misc-multiple-statement-macro + - Category: Miscellaneous + Label: Verify new / delete overloads + Description: + Name: misc-new-delete-overloads + - Category: Miscellaneous + Label: Ensure move constructors are noexcept + Description: + Name: misc-noexcept-move-constructor + - Category: Miscellaneous + Label: Copying of non-copyable objects + Description: + Name: misc-non-copyable-objects + - Category: Miscellaneous + Label: Suspicious pointer / integer operations + Description: + Name: misc-pointer-and-integral-operation + - Category: Miscellaneous + Label: Find redundant expressions + Description: + Name: misc-redundant-expression + - Category: Miscellaneous + Label: sizeof() on stl containers + Description: + Name: misc-sizeof-container + - Category: Miscellaneous + Label: Suspicious sizeof() usage + Description: + Name: misc-sizeof-expression + - Category: Miscellaneous + Label: Replace assert with static_assert + Description: + Name: misc-static-assert + - Category: Miscellaneous + Label: Suspicious string constructor + Description: + Name: misc-string-constructor + - Category: Miscellaneous + Label: String integer assignment + Description: + Name: misc-string-integer-assignment + - Category: Miscellaneous + Label: String literal with embedded null + Description: + Name: misc-string-literal-with-embedded-nul + - Category: Miscellaneous + Label: Suspicious missing comma + Description: + Name: misc-suspicious-missing-comma + - Category: Miscellaneous + Label: Suspicious semicolon + Description: + Name: misc-suspicious-semicolon + - Category: Miscellaneous + Label: Suspicious string compare + Description: + Name: misc-suspicious-string-compare + - Category: Miscellaneous + Label: Swapped arguments + Description: + Name: misc-swapped-arguments + - Category: Miscellaneous + Label: Throw by value / catch by reference + Description: + Name: misc-throw-by-value-catch-by-reference + - Category: Miscellaneous + Label: Unconventional operator=() + Description: + Name: misc-unconventional-assign-operator + - Category: Miscellaneous + Label: Undelegated constructor + Description: + Name: misc-undelegated-constructor + - Category: Miscellaneous + Label: unique_ptr<> reset / release + Description: + Name: misc-uniqueptr-reset-release + - Category: Miscellaneous + Label: Unused Alias Decls + Description: + Name: misc-unused-alias-decls + - Category: Miscellaneous + Label: Unused Params + Description: + Name: misc-unused-parameters + - Category: Miscellaneous + Label: Unused Raii + Description: + Name: misc-unused-raii + - Category: Miscellaneous + Label: Unused Using Decls + Description: + Name: misc-unused-using-decls + - Category: Miscellaneous + Label: Virtual Near Miss + Description: + Name: misc-virtual-near-miss +... Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Utility.cs =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Utility.cs +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/Utility.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace LLVM.ClangTidy +{ + static class Utility + { + public static IEnumerable SplitPath(string FileOrDir) + { + string P = Path.GetDirectoryName(FileOrDir); + do + { + yield return P; + P = Path.GetDirectoryName(P); + } while (P != null); + } + + public static bool HasClangTidyFile(string Folder) + { + string ClangTidy = Path.Combine(Folder, ".clang-tidy"); + return File.Exists(ClangTidy); + } + + public static bool MatchWildcardString(string Value, string Pattern) + { + string RE = Regex.Escape(Pattern).Replace(@"\*", ".*"); + return Regex.IsMatch(Value, RE); + } + } +} Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/VSPackage.resx =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/VSPackage.resx +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/VSPackage.resx @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ClangTidy + + + Analyzes code by calling the clang-tidy executable. + + + + Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/license.txt =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/license.txt +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/license.txt @@ -0,0 +1,63 @@ +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2007-2016 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- + + Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/packages.config =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/packages.config +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file Index: clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/source.extension.vsixmanifest =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/source.extension.vsixmanifest +++ clang-tools-extra/trunk/clang-tidy-vs/ClangTidy/source.extension.vsixmanifest @@ -0,0 +1,36 @@ + + + + ClangFormat + LLVM + 4.0.0 + A static analysis tool for C/C++ code. + 1033 + http://clang.llvm.org/extra/clang-tidy/ + license.txt + false + + + Pro + + + Pro + + + Pro + + + Pro + + + + + + + Visual Studio MPF + + + + |%CurrentProject%;PkgdefProjectOutputGroup| + + Index: clang-tools-extra/trunk/clang-tidy-vs/README.txt =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/README.txt +++ clang-tools-extra/trunk/clang-tidy-vs/README.txt @@ -0,0 +1,17 @@ +This directory contains a VSPackage project to generate a Visual Studio extension +for clang-tidy. + +Build prerequisites are: +- Visual Studio 2013 Professional +- Visual Studio 2013 SDK +- Visual Studio 2010 Professional (?) +- Visual Studio 2010 SDK (?) + +The extension is built using CMake by setting BUILD_CLANG_TIDY_VS_PLUGIN=ON +when configuring a Clang build, and building the clang_tidy_vsix target. + +The CMake build will copy clang-tidy.exe and LICENSE.TXT into the ClangTidy/ +directory so they can be bundled with the plug-in, as well as creating +ClangTidy/source.extension.vsixmanifest. Once the plug-in has been built with +CMake once, it can be built manually from the ClangTidy.sln solution in Visual +Studio. Index: clang-tools-extra/trunk/clang-tidy-vs/source.extension.vsixmanifest.in =================================================================== --- clang-tools-extra/trunk/clang-tidy-vs/source.extension.vsixmanifest.in +++ clang-tools-extra/trunk/clang-tidy-vs/source.extension.vsixmanifest.in @@ -0,0 +1,36 @@ + + + + ClangFormat + LLVM + @CLANG_TIDY_VS_VERSION@ + A static analysis tool for C/C++ code. + 1033 + http://clang.llvm.org/extra/clang-tidy/ + license.txt + false + + + Pro + + + Pro + + + Pro + + + Pro + + + + + + + Visual Studio MPF + + + + |%CurrentProject%;PkgdefProjectOutputGroup| + +