| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| /// 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; | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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=""..\packages\Brutal.Dev.StrongNameSigner.1.8.0\tools\StrongNameSigner.Console.exe" -in "..\packages"" /> | ||
| </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> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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_; } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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(); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) | ||
| { | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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)); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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(); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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(); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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")] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| namespace LLVM.ClangTidy | ||
| { | ||
| static class PkgCmdIDList | ||
| { | ||
| public const uint cmdidClangTidy = 0x100; | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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")] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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> |