簡體   English   中英

有沒有辦法強制使用制表符而不是空格?

[英]Is there a way to enforce using tabs instead of spaces?

StyleCop提供檢查空間的一致使用,但遺憾的是缺乏相反的想法:強制源代碼使用選項卡。 有沒有辦法添加此功能? 它不一定是StyleCop,也歡迎其他工具。

雖然有很多理由可以使用其中任何一個,但我還有其他地方可以理解為什么你認為一個比另一個好。 :)

我實際上想要相同的東西 - 檢查制表符縮進的規則 - 所以我根據StyleCop的SpacingRules源編寫它。 雖然到目前為止我只在幾個項目上使用它,但它似乎工作得相當好。 它可能是優化的或任何......但它的工作原理。

using System;
using System.Text.RegularExpressions;
using Microsoft.StyleCop;
using Microsoft.StyleCop.CSharp;

namespace CustomRules.StyleCop.CSharp
{
  [SourceAnalyzer(typeof(CsParser))]
  public class SpacingRules : SourceAnalyzer
  {
    public SpacingRules()
    {
    }

    public override void AnalyzeDocument(CodeDocument document)
    {
      Param.RequireNotNull(document, "document");

      CsDocument csdocument = (CsDocument)document;
      if (csdocument.RootElement != null && !csdocument.RootElement.Generated)
      {
        this.CheckSpacing(csdocument.Tokens);
      }
    }

    private void CheckSpacing(MasterList<CsToken> tokens)
    {
      Param.AssertNotNull(tokens, "tokens");

      foreach (var token in tokens)
      {
        if (this.Cancel)
        {
          break;
        }

        if (token.Generated)
        {
          continue;
        }

        switch (token.CsTokenType)
        {
          case CsTokenType.WhiteSpace:
            this.CheckWhitespace(token as Whitespace);
            break;

          case CsTokenType.XmlHeader:
            XmlHeader header = (XmlHeader)token;
            foreach (var xmlChild in header.ChildTokens)
            {
              this.CheckTabsInComment(xmlChild);
            }
            break;

          case CsTokenType.SingleLineComment:
          case CsTokenType.MultiLineComment:
            this.CheckTabsInComment(token);
            break;
        }

        switch (token.CsTokenClass)
        {
          case CsTokenClass.ConstructorConstraint:
            this.CheckSpacing(((ConstructorConstraint)token).ChildTokens);
            break;

          case CsTokenClass.GenericType:
            this.CheckGenericSpacing((GenericType)token);
            this.CheckSpacing(((TypeToken)token).ChildTokens);
            break;

          case CsTokenClass.Type:
            this.CheckSpacing(((TypeToken)token).ChildTokens);
            break;
        }
      }
    }

    private void CheckGenericSpacing(GenericType generic)
    {
      Param.AssertNotNull(generic, "generic");
      if (generic.ChildTokens.Count == 0)
      {
        return;
      }

      foreach (var token in generic.ChildTokens)
      {
        if (this.Cancel)
        {
          break;
        }

        if (token.CsTokenClass == CsTokenClass.GenericType)
        {
          this.CheckGenericSpacing(token as GenericType);
        }

        if (!token.Generated && token.CsTokenType == CsTokenType.WhiteSpace)
        {
          this.CheckWhitespace(token as Whitespace);
        }
      }
    }

    private void CheckWhitespace(Whitespace whitespace)
    {
      Param.AssertNotNull(whitespace, "whitespace");

      if (whitespace.Location.StartPoint.IndexOnLine == 0 && Regex.IsMatch(whitespace.Text, "^ +"))
      {
        this.AddViolation(whitespace.FindParentElement(), whitespace.LineNumber, "TabsMustBeUsed");
      }
    }

    private void CheckTabsInComment(CsToken comment)
    {
      Param.AssertNotNull(comment, "comment");

      var lines = comment.Text.Split('\n');
      for (int i = 0; i < lines.Length; i++)
      {
        if (Regex.IsMatch(lines[i], "^ +"))
        {
          this.AddViolation(comment.FindParentElement(), comment.LineNumber + i, "TabsMustBeUsed");
        }
      }
    }
  }
}

請注意,您還必須在程序集中包含嵌入式XML文件“SpacingRules.xml”。 (有關詳細信息,請閱讀StyleCop SDK文檔。)

<?xml version="1.0" encoding="utf-8" ?>
<SourceAnalyzer Name="Custom Spacing Rules">
  <Description>
    Rules which verify the spacing placed between keywords and symbols in the code.
  </Description>
  <Rules>
    <Rule Name="TabsMustBeUsed" CheckId="MY1027">
      <Context>Spaces are not allowed. Use tabs instead.</Context>
      <Description>Verifies that the code does not contain spaces.</Description>
    </Rule>
  </Rules>
</SourceAnalyzer>

您可以使用StyleCop +插件來強制使用選項卡。

下載后StyleCopPlus.dll放置在Custom Rules文件夾中的主了StyleCop文件夾C:\\Program Files (x86)\\StyleCop 4.7\\Custom Rules或直接在主文件夾。

現在,當使用StyleCopSettingsEditor打開Settings.StyleCop ,您將能夠設置規則SP2001: CheckAllowedIndentationCharacters

此規則可在StyleCop+選項卡下的“ More Custom Rules子選項卡下的“ Formatting標題下找到:

規則選項

假設您使用Visual Studio作為IDE,並且您的隊友支持這個想法,那么您可以做的一件事就是將VS設置為使用制表符而不是空格,導出和共享設置文件。

可以在工具>選項>文本編輯器>所有語言(或您要使用的語言)>選項卡下找到該設置,然后在右側可以選擇“插入空格”或“保留選項卡”。

從Visual Studio導出設置:工具>導入和導出設置>導出所選環境設置>選擇'選項'

只是一個想法 - 但說實話,真正的問題似乎是你的隊友的支持。 否則,他們總是可以恢復到他們的設置。 或者,在辦理登機手續時,正如Sam建議的那樣,您可以進行一些自動重新格式化。

HTH

包方式:

目前的趨勢似乎是通過nuget包來實現這一點(並且經典的StyleCop可能會在某些時候逐步淘汰)。 因此,要對包執行此操作,請執行以下操作:

通過nuget:

Install-Package Microsoft.CodeAnalysis.FxCopAnalyzers
Install-Package StyleCop.Analyzers -Version 1.1.0-beta006

請注意對pre-releaset的引用(此時),選項卡的設置僅在測試版中可用。

將以下代碼添加到您的項目中作為ca.ruleset:

<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Custom Rulset" Description="Custom Rulset" ToolsVersion="14.0">
    <Rules AnalyzerId="AsyncUsageAnalyzers" RuleNamespace="AsyncUsageAnalyzers">
        <Rule Id="UseConfigureAwait" Action="Warning" />
    </Rules>
    <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
        <Rule Id="CA1001" Action="Warning" />
        <Rule Id="CA1009" Action="Warning" />
        <Rule Id="CA1016" Action="Warning" />
        <Rule Id="CA1033" Action="Warning" />
        <Rule Id="CA1049" Action="Warning" />
        <Rule Id="CA1060" Action="Warning" />
        <Rule Id="CA1061" Action="Warning" />
        <Rule Id="CA1063" Action="Warning" />
        <Rule Id="CA1065" Action="Warning" />
        <Rule Id="CA1301" Action="Warning" />
        <Rule Id="CA1400" Action="Warning" />
        <Rule Id="CA1401" Action="Warning" />
        <Rule Id="CA1403" Action="Warning" />
        <Rule Id="CA1404" Action="Warning" />
        <Rule Id="CA1405" Action="Warning" />
        <Rule Id="CA1410" Action="Warning" />
        <Rule Id="CA1415" Action="Warning" />
        <Rule Id="CA1821" Action="Warning" />
        <Rule Id="CA1900" Action="Warning" />
        <Rule Id="CA1901" Action="Warning" />
        <Rule Id="CA2002" Action="Warning" />
        <Rule Id="CA2100" Action="Warning" />
        <Rule Id="CA2101" Action="Warning" />
        <Rule Id="CA2108" Action="Warning" />
        <Rule Id="CA2111" Action="Warning" />
        <Rule Id="CA2112" Action="Warning" />
        <Rule Id="CA2114" Action="Warning" />
        <Rule Id="CA2116" Action="Warning" />
        <Rule Id="CA2117" Action="Warning" />
        <Rule Id="CA2122" Action="Warning" />
        <Rule Id="CA2123" Action="Warning" />
        <Rule Id="CA2124" Action="Warning" />
        <Rule Id="CA2126" Action="Warning" />
        <Rule Id="CA2131" Action="Warning" />
        <Rule Id="CA2132" Action="Warning" />
        <Rule Id="CA2133" Action="Warning" />
        <Rule Id="CA2134" Action="Warning" />
        <Rule Id="CA2137" Action="Warning" />
        <Rule Id="CA2138" Action="Warning" />
        <Rule Id="CA2140" Action="Warning" />
        <Rule Id="CA2141" Action="Warning" />
        <Rule Id="CA2146" Action="Warning" />
        <Rule Id="CA2147" Action="Warning" />
        <Rule Id="CA2149" Action="Warning" />
        <Rule Id="CA2200" Action="Warning" />
        <Rule Id="CA2202" Action="Warning" />
        <Rule Id="CA2207" Action="Warning" />
        <Rule Id="CA2212" Action="Warning" />
        <Rule Id="CA2213" Action="Warning" />
        <Rule Id="CA2214" Action="Warning" />
        <Rule Id="CA2216" Action="Warning" />
        <Rule Id="CA2220" Action="Warning" />
        <Rule Id="CA2229" Action="Warning" />
        <Rule Id="CA2231" Action="Warning" />
        <Rule Id="CA2232" Action="Warning" />
        <Rule Id="CA2235" Action="Warning" />
        <Rule Id="CA2236" Action="Warning" />
        <Rule Id="CA2237" Action="Warning" />
        <Rule Id="CA2238" Action="Warning" />
        <Rule Id="CA2240" Action="Warning" />
        <Rule Id="CA2241" Action="Warning" />
        <Rule Id="CA2242" Action="Warning" />
        <Rule Id="CA1012" Action="Warning" />
    </Rules>
    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
        <Rule Id="SA1305" Action="Warning" />
        <Rule Id="SA1412" Action="Warning" />
        <Rule Id="SA1600" Action="None" />
        <Rule Id="SA1609" Action="Warning" />
    </Rules>
</RuleSet>

通過編輯.csproj文件並添加以下內容將其添加到項目文件中:

<PropertyGroup>
    <CodeAnalysisRuleSet>ca.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>

要覆蓋選項卡(和其他)設置,您需要將stylecop.json文件添加到項目中。 在文件屬性中,將Build Action設置為'(analyzer)additional file'。 根據項目類型,可能不存在實際的“分析器”字樣。

將stylecop.json文件編輯為以下內容:

{
  "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
  "settings": {
    "documentationRules": {
      "companyName": "YourCompanyName",
      "copyrightText": "Copyright (c) {companyName}. All Rights Reserved.\r\nLicensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.",
      "xmlHeader": false,
      "fileNamingConvention": "metadata"
    },
    "indentation": {
      "useTabs": true
    }
  }
}

至少對於.NET標准項目,您需要確保以下內容位於csproj文件中(並且沒有其他對文件的引用):

<ItemGroup>
  <AdditionalFiles Include="stylecop.json" />
</ItemGroup>

您可能必須重新加載項目和包以使它們識別stylecop.json文件。

參考文獻:

DotNetAnalyzers / StyleCopAnalyzers

.NET核心,代碼分析和StyleCop

StyleCop支持創建自定義規則,因此您可以添加自己的“使用前導選項卡而不是空格”規則。 如果您不想嘗試開發自己的規則,可以在http://stylecopcontrib.codeplex.com/http://github.com/AArnott/nerdbank.stylecop.rules獲取現有規則。

好的,我設法找出問題,因為出現此警告的原因,看起來是因為開發人員有時會復制並粘貼代碼

如果您正在使用VS2010請轉到解決方案資源管理器檢入設置樣式警察然后修改樣式警察內部的設置,例如禁用或取消選中設置[間距.....]

在源代碼管理服務器中執行此操作。 使用預提交腳本檢查文件以查找以多個空格開頭的行並阻止提交。

我同意標簽比空格更好。 這是個人偏好,但團隊的一致性非常重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM