Есть ли способ принудительного использования табуляции вместо пробелов? - PullRequest
18 голосов
/ 17 февраля 2010

StyleCop предлагает проверить согласованное использование пробелов, но, к сожалению, отсутствует противоположная идея: заставить исходный код использовать вкладки. Есть ли способ добавить эту функциональность? Это не обязательно должен быть StyleCop, приветствуются и другие инструменты.

Ответы [ 7 ]

12 голосов
/ 08 апреля 2011

Я тоже человек с табуляцией, хотя есть много причин использовать любое из них, и есть другие места, чтобы попасть в , почему вы думаете, что одно лучше другого. :)

Я на самом деле хотел то же самое - правило для проверки отступов табуляции - поэтому я написал его на основе источника SpacingRules из StyleCop. Кажется, это работает достаточно хорошо, хотя я пока использовал его только в нескольких проектах. Возможно, он может быть оптимизирован или что-то еще ... но это работает.

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>
8 голосов
/ 16 мая 2012

Вы можете использовать плагин StyleCop + для принудительного использования вкладок.

После загрузки StyleCopPlus.dll поместите его в папку Custom Rules внутри основной папки StyleCop C:\Program Files (x86)\StyleCop 4.7\Custom Rules или непосредственно в основную папку.

Теперь при открытии Settings.StyleCop с помощью StyleCopSettingsEditor вы сможете установить правило SP2001: CheckAllowedIndentationCharacters.

Это правило можно найти на вкладке StyleCop+, во вложенной вкладке More Custom Rules, под заголовком Formatting:

Rule Options

3 голосов
/ 17 февраля 2010

Одна вещь, которую вы могли бы сделать, предполагая, что вы используете Visual Studio в качестве IDE, и что ваши товарищи по команде поддерживают эту идею, это настроить VS на использование вкладок вместо пробелов, экспортировать и поделиться файлом настроек. .

Настройку можно найти в меню «Инструменты»> «Параметры»> «Текстовый редактор»> «Все языки» (или на языке, который вы хотите использовать)> «Вкладки», а затем справа выберите «Вставить пробелы» или «Сохранить вкладки».

Чтобы экспортировать настройки из вашей Visual Studio: Инструменты> Параметры импорта и экспорта> Экспорт выбранных настроек среды> выберите «Параметры»

Просто мысль - но, честно говоря, реальная проблема, похоже, заключается в бай-ине от ваших товарищей по команде. В противном случае они всегда могут вернуться к своим настройкам. В качестве альтернативы, после регистрации, как предложил Сэм, вы можете выполнить автоматическое переформатирование.

НТН

2 голосов
/ 05 марта 2018

Пакетный подход:

Кажется, что текущая тенденция состоит в том, чтобы сделать это через пакеты nuget (и что классический StyleCop может быть постепенно прекращен). Итак, чтобы сделать это с пакетами, сделайте следующее:

через nuget:

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

Обратите внимание на ссылку на предварительный релиз (в настоящее время), настройки для вкладок доступны только в бета-версии.

добавить следующий код в ваш проект как 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 на «(анализатор) дополнительный файл». В зависимости от типа проекта фактическое слово «анализатор» может отсутствовать.

Измените файл 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 Core, анализ кода и StyleCop

2 голосов
/ 01 июня 2011

Хорошо, мне удалось выяснить проблему, потому что причина, по которой это предупреждение появляется, появляется, потому что разработчик иногда копирует и вставляет код

если вы используете VS2010 Перейти к обозревателю решений Отметьте в настройке Style Cop затем измените настройку внутри стиля Cop, например, отключите или снимите флажок настройки [Spacing .....]

2 голосов
/ 17 февраля 2010

StyleCop поддерживает создание пользовательских правил, поэтому вы можете добавить свое собственное правило «использовать начальные табуляции вместо пробелов». Если вы не хотите разрабатывать свои собственные правила, вы можете получить существующее правило на http://stylecopcontrib.codeplex.com/ или http://github.com/AArnott/nerdbank.stylecop.rules.

1 голос
/ 17 февраля 2010

Сделайте это на вашем сервере контроля версий. Используйте скрипт предварительной фиксации, чтобы проверить файл на наличие строк, начинающихся с нескольких пробелов, и предотвратить фиксацию.

Я согласен, что вкладки лучше пробелов. Это личное предпочтение, но последовательность команды очень важна.

...