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
This commit is contained in:
Zachary Turner 2016-09-07 18:28:55 +00:00
parent b7a619c1fa
commit 1122be8e15
38 changed files with 3309 additions and 0 deletions

View File

@ -4,6 +4,7 @@ add_subdirectory(clang-reorder-fields)
add_subdirectory(modularize)
if(CLANG_ENABLE_STATIC_ANALYZER)
add_subdirectory(clang-tidy)
add_subdirectory(clang-tidy-vs)
endif()
add_subdirectory(clang-query)

View File

@ -0,0 +1,7 @@
obj/
bin/
.vs/
Key.snk
clang-tidy.exe
packages/
*.csproj.user

View File

@ -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()

View File

@ -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

View File

@ -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
{
/// <summary>
/// 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.
/// </summary>
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);
}
}
}

View File

@ -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; }
}
/// <summary>
/// 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.
/// </summary>
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<CheckRoot>(Reader);
Checks_ = Root.Checks;
HashSet<string> Names = new HashSet<string>();
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<CheckInfo> Checks
{
get
{
return Checks_;
}
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,267 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BE261DA1-36C6-449A-95C5-4653A549170A}</ProjectGuid>
<ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LLVM.ClangTidy</RootNamespace>
<AssemblyName>ClangTidy</AssemblyName>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>4.0</OldToolsVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>0</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RunCodeAnalysis>true</RunCodeAnalysis>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualStudio.CoreUtility, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.Editor, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.OLE.Interop" />
<Reference Include="Microsoft.VisualStudio.Settings.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86" />
<Reference Include="Microsoft.VisualStudio.Shell.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop" />
<Reference Include="Microsoft.VisualStudio.TextManager.Interop" />
<Reference Include="Microsoft.VisualStudio.TextManager.Interop" />
<Reference Include="Microsoft.VisualStudio.Utilities, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Design" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="YamlDotNet, Version=3.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\YamlDotNet.3.3.0\lib\net35\YamlDotNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="YamlDotNet.Dynamic, Version=3.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\YamlDotNet.Dynamic.3.2.3\lib\net40\YamlDotNet.Dynamic.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<COMReference Include="EnvDTE">
<Guid>{80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}</Guid>
<VersionMajor>8</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="EnvDTE100">
<Guid>{26AD1324-4B7C-44BC-84F8-B86AED45729F}</Guid>
<VersionMajor>10</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="EnvDTE80">
<Guid>{1A31287A-4D7D-413E-8E32-3B374931BD89}</Guid>
<VersionMajor>8</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="EnvDTE90">
<Guid>{2CE2370E-D744-4936-A090-3FFFE667B0E1}</Guid>
<VersionMajor>9</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="Microsoft.VisualStudio.CommandBars">
<Guid>{1CBA492E-7263-47BB-87FE-639000619B15}</Guid>
<VersionMajor>8</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="stdole">
<Guid>{00020430-0000-0000-C000-000000000046}</Guid>
<VersionMajor>2</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<Compile Include="CategoryVerb.cs" />
<Compile Include="CheckDatabase.cs" />
<Compile Include="CheckTree.cs" />
<Compile Include="ClangTidyCheckAttribute.cs" />
<Compile Include="ClangTidyConfigurationPage.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ClangTidyProperties.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="DynamicPropertyConverter.cs" />
<Compile Include="DynamicPropertyDescriptor.cs" />
<Compile Include="ForwardingPropertyDescriptor.cs" />
<Compile Include="Guids.cs" />
<Compile Include="DynamicPropertyComponent.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="DynamicPropertyComponent.Designer.cs" />
<Compile Include="ClangTidyConfigParser.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="ClangTidyPackage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PkgCmdID.cs" />
<Compile Include="ClangTidyPropertyGrid.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="ClangTidyPropertyGrid.Designer.cs">
<DependentUpon>ClangTidyPropertyGrid.cs</DependentUpon>
</Compile>
<Compile Include="Utility.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="ClangTidyPropertyGrid.resx">
<DependentUpon>ClangTidyPropertyGrid.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="VSPackage.resx">
<MergeWithCTO>true</MergeWithCTO>
<ManifestResourceName>VSPackage</ManifestResourceName>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="Key.snk" />
<None Include="packages.config" />
<None Include="Resources\ClangTidyChecks.yaml" />
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<VSCTCompile Include="ClangTidy.vsct">
<ResourceName>Menus.ctmenu</ResourceName>
<SubType>Designer</SubType>
</VSCTCompile>
</ItemGroup>
<ItemGroup>
<None Include="Resources\Images_32bit.bmp" />
</ItemGroup>
<ItemGroup>
<Content Include="clang-tidy.exe">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="license.txt">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Resources\Package.ico" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
<Visible>False</Visible>
<ProductName>Windows Installer 4.5</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<PropertyGroup>
<UseCodebase>true</UseCodebase>
</PropertyGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\VSSDK\Microsoft.VsSDK.targets" Condition="false" />
<PropertyGroup>
<PreBuildEvent>if not exist $(ProjectDir)Key.snk ("$(SDKToolsPath)\sn.exe" -k $(ProjectDir)Key.snk)</PreBuildEvent>
</PropertyGroup>
<Target Name="BeforeBuild">
<Exec ContinueOnError="false" Command="&quot;..\packages\Brutal.Dev.StrongNameSigner.1.8.0\tools\StrongNameSigner.Console.exe&quot; -in &quot;..\packages&quot;" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This is the file that defines the actual layout and type of the commands.
It is divided in different sections (e.g. command definition, command
placement, ...), with each defining a specific set of properties.
See the comment before each section for more details about how to
use it. -->
<!-- The VSCT compiler (the tool that translates this file into the binary
format that VisualStudio will consume) has the ability to run a preprocessor
on the vsct file; this preprocessor is (usually) the C++ preprocessor, so
it is possible to define includes and macros with the same syntax used
in C++ files. Using this ability of the compiler here, we include some files
defining some of the constants that we will use inside the file. -->
<!--This is the file that defines the IDs for all the commands exposed by VisualStudio. -->
<Extern href="stdidcmd.h"/>
<!--This header contains the command ids for the menus provided by the shell. -->
<Extern href="vsshlids.h"/>
<!--The Commands section is where we the commands, menus and menu groups are defined.
This section uses a Guid to identify the package that provides the command defined inside it. -->
<Commands package="guidClangTidyPkg">
<!-- Inside this section we have different sub-sections: one for the menus, another
for the menu groups, one for the buttons (the actual commands), one for the combos
and the last one for the bitmaps used. Each element is identified by a command id that
is a unique pair of guid and numeric identifier; the guid part of the identifier is usually
called "command set" and is used to group different command inside a logically related
group; your package should define its own command set in order to avoid collisions
with command ids defined by other packages. -->
<!-- In this section you can define new menu groups. A menu group is a container for
other menus or buttons (commands); from a visual point of view you can see the
group as the part of a menu contained between two lines. The parent of a group
must be a menu. -->
<Groups>
<Group guid="guidClangTidyCmdSet" id="MyMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>
</Group>
</Groups>
<!--Buttons section. -->
<!--This section defines the elements the user can interact with, like a menu command or a button
or combo box in a toolbar. -->
<Buttons>
<!--To define a menu group you have to specify its ID, the parent menu and its display priority.
The command is visible and enabled by default. If you need to change the visibility, status, etc, you can use
the CommandFlag node.
You can add more than one CommandFlag node e.g.:
<CommandFlag>DefaultInvisible</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
If you do not want an image next to your command, remove the Icon node /> -->
<Button guid="guidClangTidyCmdSet" id="cmdidClangTidy" priority="0x0100" type="Button">
<Parent guid="guidClangTidyCmdSet" id="MyMenuGroup" />
<Icon guid="guidImages" id="bmpPic1" />
<Strings>
<ButtonText>ClangTidy</ButtonText>
</Strings>
</Button>
</Buttons>
<!--The bitmaps section is used to define the bitmaps that are used for the commands.-->
<Bitmaps>
<!-- The bitmap id is defined in a way that is a little bit different from the others:
the declaration starts with a guid for the bitmap strip, then there is the resource id of the
bitmap strip containing the bitmaps and then there are the numeric ids of the elements used
inside a button definition. An important aspect of this declaration is that the element id
must be the actual index (1-based) of the bitmap inside the bitmap strip. -->
<Bitmap guid="guidImages" href="Resources\Images_32bit.bmp" usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/>
</Bitmaps>
</Commands>
<KeyBindings>
<KeyBinding guid="guidClangTidyCmdSet" id="cmdidClangTidy" editor="guidTextEditor" key1="R" mod1="Control" key2="T" mod2="Control"/>
</KeyBindings>
<Symbols>
<!-- This is the package guid. -->
<GuidSymbol name="guidClangTidyPkg" value="{AE4956BE-3DB8-430E-BBAB-7E2E9A014E9C}" />
<!-- This is the guid used to group the menu commands together -->
<GuidSymbol name="guidClangTidyCmdSet" value="{9E0F0493-6493-46DE-AEE1-ACD8F60F265E}">
<IDSymbol name="MyMenuGroup" value="0x1020" />
<IDSymbol name="cmdidClangTidy" value="0x0100" />
</GuidSymbol>
<GuidSymbol name="guidTextEditor" value="{E10FAD35-7FB8-4991-A269-EF88F12166C9}" />
<GuidSymbol name="guidImages" value="{942F126F-942D-428A-84B4-4AC7C523D0B2}" >
<IDSymbol name="bmpPic1" value="1" />
<IDSymbol name="bmpPic2" value="2" />
<IDSymbol name="bmpPicSearch" value="3" />
<IDSymbol name="bmpPicX" value="4" />
<IDSymbol name="bmpPicArrows" value="5" />
</GuidSymbol>
</Symbols>
</CommandTable>

View File

@ -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_; }
}
}
}

View File

@ -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<CheckOption> CheckOptions { get; set; }
}
public static List<KeyValuePair<string, ClangTidyProperties>> ParseConfigurationChain(string ClangTidyFile)
{
List<KeyValuePair<string, ClangTidyProperties>> Result = new List<KeyValuePair<string, ClangTidyProperties>>();
Result.Add(new KeyValuePair<string, ClangTidyProperties>(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<ClangTidyYaml>(Reader);
ClangTidyProperties Parent = Result[Result.Count - 1].Value;
ClangTidyProperties NewProps = new ClangTidyProperties(Parent);
SetPropertiesFromYaml(Y, NewProps);
Result.Add(new KeyValuePair<string, ClangTidyProperties>(P, NewProps));
}
}
return Result;
}
enum TreeLevelOp
{
Enable,
Disable,
Inherit
}
public static void SerializeClangTidyFile(ClangTidyProperties Props, string ClangTidyFilePath)
{
List<string> CommandList = new List<string>();
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);
}
}
/// <summary>
/// Convert the given check tree into serialized list of commands that can be written to
/// the Yaml. The goal here is to determine the minimal sequence of check commands that
/// will produce the exact configuration displayed in the UI. This is complicated by the
/// fact that an inherited True is not the same as an explicitly specified True. If the
/// user has chosen to inherit a setting in a .clang-tidy file, then changing it in the
/// parent should show the reflected changes in the current file as well. So we cannot
/// simply -* everything and then add in the checks we need, because -* immediately marks
/// every single check as explicitly false, thus disabling inheritance.
/// </summary>
/// <param name="CommandList">State passed through this recursive algorithm representing
/// the sequence of commands we have determined so far.
/// </param>
/// <param name="Tree">The check tree to serialize. This is the parameter that will be
/// recursed on as successive subtrees get serialized to `CommandList`.
/// </param>
/// <param name="CurrentOp">The current state of the subtree. For example, if the
/// algorithm decides to -* an entire subtree and then add back one single check,
/// after adding a -subtree-* command to CommandList, it would pass in a value of
/// CurrentOp=TreeLevelOp.Disable when it recurses down. This allows deeper iterations
/// of the algorithm to know what kind of command (if any) needs to be added to CommandList
/// in order to put a particular check into a particular state.
/// </param>
private static void SerializeCheckTree(List<string> CommandList, CheckTree Tree, TreeLevelOp CurrentOp)
{
int NumChecks = Tree.CountChecks;
int NumDisabled = Tree.CountExplicitlyDisabledChecks;
int NumEnabled = Tree.CountExplicitlyEnabledChecks;
int NumInherited = Tree.CountInheritedChecks;
if (NumChecks == 0)
return;
if (NumInherited > 0)
System.Diagnostics.Debug.Assert(CurrentOp == TreeLevelOp.Inherit);
// If this entire tree is inherited, just exit, nothing about this needs to
// go in the clang-tidy file.
if (NumInherited == NumChecks)
return;
TreeLevelOp NewOp = CurrentOp;
// If there are no inherited properties in this subtree, decide whether to
// explicitly enable or disable this subtree. Decide by looking at whether
// there is a larger proportion of disabled or enabled descendants. If
// there are more disabled items in this subtree for example, disabling the
// subtree will lead to a smaller configuration file.
if (NumInherited == 0)
{
if (NumDisabled >= NumEnabled)
NewOp = TreeLevelOp.Disable;
else
NewOp = TreeLevelOp.Enable;
}
if (NewOp == TreeLevelOp.Disable)
{
// Only add an explicit disable command if the tree was not already disabled
// to begin with.
if (CurrentOp != TreeLevelOp.Disable)
{
string WildcardPath = "*";
if (Tree.Path != null)
WildcardPath = Tree.Path + "-" + WildcardPath;
CommandList.Add("-" + WildcardPath);
}
// If the entire subtree was disabled, there's no point descending.
if (NumDisabled == NumChecks)
return;
}
else if (NewOp == TreeLevelOp.Enable)
{
// Only add an explicit enable command if the tree was not already enabled
// to begin with. Note that if we're at the root, all checks are already
// enabled by default, so there's no need to explicitly include *
if (CurrentOp != TreeLevelOp.Enable && Tree.Path != null)
{
string WildcardPath = Tree.Path + "-*";
CommandList.Add(WildcardPath);
}
// If the entire subtree was enabled, there's no point descending.
if (NumEnabled == NumChecks)
return;
}
foreach (var Child in Tree.Children)
{
if (Child.Value is CheckLeaf)
{
CheckLeaf Leaf = (CheckLeaf)Child.Value;
if (Leaf.CountExplicitlyEnabledChecks == 1 && NewOp != TreeLevelOp.Enable)
CommandList.Add(Leaf.Path);
else if (Leaf.CountExplicitlyDisabledChecks == 1 && NewOp != TreeLevelOp.Disable)
CommandList.Add("-" + Leaf.Path);
continue;
}
System.Diagnostics.Debug.Assert(Child.Value is CheckTree);
CheckTree ChildTree = (CheckTree)Child.Value;
SerializeCheckTree(CommandList, ChildTree, NewOp);
}
}
private 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);
}
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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)
{
}
}
}

View File

@ -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<string> Categories = new HashSet<string>();
foreach (var Check in CheckDatabase.Checks)
{
string Name = Check.Name.Replace('-', '_');
List<Attribute> Attrs = new List<Attribute>();
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<bool>(Check.Name, Attrs.ToArray());
}
// Add a category verb for each unique category.
foreach (string Cat in Categories)
{
List<Attribute> Attrs = new List<Attribute>();
Attrs.Add(new CategoryAttribute(Cat));
Attrs.Add(new DisplayNameAttribute("(Category Verbs)"));
Attrs.Add(new TypeConverterAttribute(typeof(CategoryVerbConverter)));
Attrs.Add(new DefaultValueAttribute(CategoryVerb.None));
AddDynamicProperty<CategoryVerb>(Cat + "Verb", Attrs.ToArray());
}
}
public CheckTree GetCheckTree() { return CheckTree_; }
public bool GetHasUnsavedChanges() { return HasUnsavedChanges_; }
public void SetHasUnsavedChanges(bool Value) { HasUnsavedChanges_ = Value; }
}
}

View File

@ -0,0 +1,119 @@
namespace LLVM.ClangTidy
{
partial class ClangTidyPropertyGrid
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// 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).
/// </summary>
public partial class ClangTidyPropertyGrid : UserControl
{
/// <summary>
/// The sequence of .clang-tidy configuration files, starting from the root
/// of the filesystem, down to the selected file.
/// </summary>
List<KeyValuePair<string, ClangTidyProperties>> PropertyChain_ = null;
/// <summary>
/// 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.
/// </summary>
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<KeyValuePair<string, ClangTidyProperties>>();
PropertyChain_.Add(new KeyValuePair<string, ClangTidyProperties>(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";
/// <summary>
/// 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.
/// </summary>
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<CategoryAttribute>().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;
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="clangTidyConfigurationPage1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>183, 17</value>
</metadata>
</root>

View File

@ -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
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -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
{
/// <summary>
/// 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.
/// </summary>
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<PropertyDescriptor>();
var Filtered = Props.Where(x => x.Attributes.Contains(attributes)).ToArray();
return new PropertyDescriptorCollection(Filtered);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
public void SetDynamicValue<T>(string Name, T Value)
{
Name = Name.Replace('-', '_');
DynamicPropertyDescriptor<T> Descriptor = (DynamicPropertyDescriptor<T>)DynamicProperties_.Find(Name, false);
Descriptor.SetValue(this, Value);
}
public T GetDynamicValue<T>(string Name)
{
Name = Name.Replace('-', '_');
DynamicPropertyDescriptor<T> Descriptor = (DynamicPropertyDescriptor<T>)DynamicProperties_.Find(Name, false);
return (T)Descriptor.GetValue(this);
}
protected void AddDynamicProperty<T>(string Name, Attribute[] Attributes)
{
Name = Name.Replace('-', '_');
// If we have a parent, find the corresponding PropertyDescriptor with the same
// name from the parent.
DynamicPropertyDescriptor<T> ParentDescriptor = null;
if (Parent_ != null)
ParentDescriptor = (DynamicPropertyDescriptor<T>)Parent_.GetProperties().Find(Name, false);
DynamicProperties_.Add(new DynamicPropertyDescriptor<T>(Name, ParentDescriptor, Name, Attributes));
}
}
}

View File

@ -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 = "<Inherit from project or parent>";
}
class DynamicPropertyConverter<T> : TypeConverter
{
private DynamicPropertyDescriptor<T> Descriptor_;
private TypeConverter Root_;
public DynamicPropertyConverter(DynamicPropertyDescriptor<T> Descriptor, TypeConverter Root)
{
Descriptor_ = Descriptor;
Root_ = Root;
}
/// <summary>
/// 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.
/// </summary>
/// <returns>true</returns>
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
/// <summary>
/// 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.
/// </summary>
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
List<object> Values = new List<object>();
if (Root_.GetStandardValuesSupported(context))
{
StandardValuesCollection RootValues = Root_.GetStandardValues(context);
Values.AddRange(RootValues.Cast<object>());
}
if (!Descriptor_.IsInheriting)
Values.Add(MagicInheritance.Value);
StandardValuesCollection Result = new StandardValuesCollection(Values);
return Result;
}
/// <summary>
/// Determines whether this property can accept values other than those specified
/// in the dropdown (for example by manually typing into the field).
/// </summary>
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();
}
}
}

View File

@ -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<T> : PropertyDescriptor
{
T Value_;
DynamicPropertyDescriptor<T> Parent_;
bool IsInheriting_;
object Component_;
public DynamicPropertyDescriptor(object Component, DynamicPropertyDescriptor<T> Parent, string Name, Attribute[] Attrs)
: base(Name, Attrs)
{
foreach (DefaultValueAttribute Attr in Attrs.OfType<DefaultValueAttribute>())
{
Value_ = (T)Attr.Value;
}
Parent_ = Parent;
IsInheriting_ = true;
Component_ = Component;
}
public bool IsInheriting { get { return IsInheriting_; } set { IsInheriting_ = value; } }
public DynamicPropertyDescriptor<T> Parent { get { return Parent_; } }
/// <summary>
/// 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.
/// </summary>
/// <param name="component"></param>
/// <returns></returns>
public override bool ShouldSerializeValue(object component)
{
return (Parent_ != null) && !IsInheriting;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="component"></param>
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<TypeConverterAttribute>().LastOrDefault();
if (ConverterAttr != null)
{
Type ConverterType = Type.GetType(ConverterAttr.ConverterTypeName);
UnderlyingConverter = (TypeConverter)Activator.CreateInstance(ConverterType);
}
else
UnderlyingConverter = TypeDescriptor.GetConverter(typeof(T));
return new DynamicPropertyConverter<T>(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);
}
}
}
}

View File

@ -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
{
/// <summary>
/// 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.
/// </summary>
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();
}
}
}

View File

@ -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")]

View File

@ -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);
};
}

View File

@ -0,0 +1,7 @@
namespace LLVM.ClangTidy
{
static class PkgCmdIDList
{
public const uint cmdidClangTidy = 0x100;
};
}

View File

@ -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")]

View File

@ -0,0 +1,81 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace LLVM.ClangTidy {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 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]&quot;;.
/// </summary>
internal static string ClangTidyChecks {
get {
return ResourceManager.GetString("ClangTidyChecks", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="ClangTidyChecks" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\ClangTidyChecks.yaml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View File

@ -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
...

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -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<string> 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);
}
}
}

View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="110" xml:space="preserve">
<value>ClangTidy</value>
</data>
<data name="112" xml:space="preserve">
<value>Analyzes code by calling the clang-tidy executable.</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="400" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -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
------- ---------
<none yet>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Brutal.Dev.StrongNameSigner" version="1.8.0" targetFramework="net45" />
<package id="YamlDotNet" version="3.3.0" targetFramework="net45" />
<package id="YamlDotNet.Dynamic" version="3.2.3" targetFramework="net45" />
</packages>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Vsix Version="1.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">
<Identifier Id="405594C3-042A-4155-B9A6-E25DAB8B1924">
<Name>ClangFormat</Name>
<Author>LLVM</Author>
<Version>4.0.0</Version>
<Description xml:space="preserve">A static analysis tool for C/C++ code.</Description>
<Locale>1033</Locale>
<MoreInfoUrl>http://clang.llvm.org/extra/clang-tidy/</MoreInfoUrl>
<License>license.txt</License>
<InstalledByMsi>false</InstalledByMsi>
<SupportedProducts>
<VisualStudio Version="10.0">
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="11.0">
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="12.0">
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="14.0">
<Edition>Pro</Edition>
</VisualStudio>
</SupportedProducts>
<SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.0" />
</Identifier>
<References>
<Reference Id="Microsoft.VisualStudio.MPF" MinVersion="10.0">
<Name>Visual Studio MPF</Name>
</Reference>
</References>
<Content>
<VsPackage>|%CurrentProject%;PkgdefProjectOutputGroup|</VsPackage>
</Content>
</Vsix>

View File

@ -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.

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Vsix Version="1.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">
<Identifier Id="405594C3-042A-4155-B9A6-E25DAB8B1924">
<Name>ClangFormat</Name>
<Author>LLVM</Author>
<Version>@CLANG_TIDY_VS_VERSION@</Version>
<Description xml:space="preserve">A static analysis tool for C/C++ code.</Description>
<Locale>1033</Locale>
<MoreInfoUrl>http://clang.llvm.org/extra/clang-tidy/</MoreInfoUrl>
<License>license.txt</License>
<InstalledByMsi>false</InstalledByMsi>
<SupportedProducts>
<VisualStudio Version="10.0">
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="11.0">
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="12.0">
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="14.0">
<Edition>Pro</Edition>
</VisualStudio>
</SupportedProducts>
<SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.0" />
</Identifier>
<References>
<Reference Id="Microsoft.VisualStudio.MPF" MinVersion="10.0">
<Name>Visual Studio MPF</Name>
</Reference>
</References>
<Content>
<VsPackage>|%CurrentProject%;PkgdefProjectOutputGroup|</VsPackage>
</Content>
</Vsix>