5

我被要求将 StyleCop 以如下方式集成到我们的 CI 构建过程中:

  • 我们(大)解决方案中的单个项目文件不受影响
  • 我不必使用任何 3rd 方工具

第一个要求(我还没有完全理解)是因为我们不想直接在整个解决方案上运行 StyleCop。显然,当 StyleCop 在 VS 中运行时,它会忽略某些指定要忽略的文件的属性。正因为如此,如果我们让它在开发机器上运行,我们将不断受到数千个我们尚未准备好处理的违规行为的打击。所以底线是我们希望能够只在构建服务器上运行它。

我们的构建环境目前包括:

巡航控制 > 执行 msbuild 的 nant 任务(通过 exec)

南特任务如下:

<target name="buildSolution">       
    <echo message="Building solution..." />
    <exec program="C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe"                     
        commandline="${Project.SolutionFile} /t:Rebuild /p:Configuration=${Project.SolutionBuildConfiguration} /v:q" workingdir="." />      
</target>  

当我第一次看到这个时,我认为这将是一个以类似于执行 msbuild 的方式执行 StyleCop 的简单案例。

然而,StyleCop 是作为一组 dll 提供的......

所以这意味着我不能做我想做的事......我想......

我今天用谷歌搜索的所有文章都说“使用 StyleCopCmd”,由于 3rd 方工具限制,我也不能这样做。

我查看了该工具,它似乎实现了一个自定义的 nant 任务,该任务启动 StyleCopConsole,挂钩到几个事件并输出格式良好的报告。但是为了能够证明在内部创建任何工具的合理性,我需要能够充分解释为什么我不能在 nant 配置文件中实现我想要的。或以任何其他不涉及创建或使用工具的方式。理想情况下,如果我不必编写或使用工具,它会更快。

所以我的问题是,这可能吗?

4

1 回答 1

5

我们已经成功地做到了这一点。只需按照以下步骤操作:

  • 在您的项目中创建一个目录并将所有 StyleCop 文件复制到那里(Microsoft.StyleCop.CSharp.dll、Microsoft.StyleCop.Targets 等)

  • 编辑 Microsoft.StyleCop.Targets 使其看起来像这样:

--

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask AssemblyFile="Microsoft.StyleCop.dll" TaskName="StyleCopTask" />
    <PropertyGroup>
        <BuildDependsOn>StyleCop</BuildDependsOn>
        <RebuildDependsOn>StyleCopForceFullAnalysis;StyleCop</RebuildDependsOn>
    </PropertyGroup>
    <PropertyGroup Condition="('$(SourceAnalysisForceFullAnalysis)' != '') and ('$(StyleCopForceFullAnalysis)' == '')">
        <StyleCopForceFullAnalysis>$(SourceAnalysisForceFullAnalysis)</StyleCopForceFullAnalysis>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopForceFullAnalysis)' == ''">
        <StyleCopForceFullAnalysis>false</StyleCopForceFullAnalysis>
    </PropertyGroup>
    <PropertyGroup Condition="('$(SourceAnalysisCacheResults)' != '') and ('$(StyleCopCacheResults)' == '')">
        <StyleCopCacheResults>$(SourceAnalysisCacheResults)</StyleCopCacheResults>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopCacheResults)' == ''">
        <StyleCopCacheResults>true</StyleCopCacheResults>
    </PropertyGroup>

    <!-- Define StyleCopTreatErrorsAsWarnings property. -->
    <PropertyGroup Condition="('$(SourceAnalysisTreatErrorsAsWarnings)' != '') and ('$(StyleCopTreatErrorsAsWarnings)' == '')">
        <StyleCopTreatErrorsAsWarnings>$(SourceAnalysisTreatErrorsAsWarnings)</StyleCopTreatErrorsAsWarnings>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopTreatErrorsAsWarnings)' == ''">
        <StyleCopTreatErrorsAsWarnings>true</StyleCopTreatErrorsAsWarnings>
    </PropertyGroup>

    <PropertyGroup Condition="('$(SourceAnalysisEnabled)' != '') and ('$(StyleCopEnabled)' == '')">
        <StyleCopEnabled>$(SourceAnalysisEnabled)</StyleCopEnabled>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopEnabled)' == ''">
        <StyleCopEnabled>true</StyleCopEnabled>
    </PropertyGroup>

    <!-- Define StyleCopOverrideSettingsFile property. -->
    <PropertyGroup Condition="('$(SourceAnalysisOverrideSettingsFile)' != '') and ('$(StyleCopOverrideSettingsFile)' == '')">
        <StyleCopOverrideSettingsFile>$(SourceAnalysisOverrideSettingsFile)</StyleCopOverrideSettingsFile>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopOverrideSettingsFile)' == ''">
        <StyleCopOverrideSettingsFile> </StyleCopOverrideSettingsFile>
    </PropertyGroup>

    <!-- Define StyleCopOutputFile property. -->
    <PropertyGroup Condition="('$(StyleCopOutputPath)' == '')">
        <StyleCopOutputPath>$(IntermediateOutputPath)</StyleCopOutputPath>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopOutputFile)' == ''">
        <StyleCopOutputFile Condition="!HasTrailingSlash('$(StyleCopOutputPath)')">$(StyleCopOutputPath)\$(AssemblyName).StyleCopViolations.xml</StyleCopOutputFile>
        <StyleCopOutputFile Condition="HasTrailingSlash('$(StyleCopOutputPath)')">$(StyleCopOutputPath)$(AssemblyName).StyleCopViolations.xml</StyleCopOutputFile>
    </PropertyGroup>

    <!-- Define all new properties which do not need to have both StyleCop and SourceAnalysis variations. -->
    <PropertyGroup>
        <!-- Specifying 0 will cause StyleCop to use the default violation count limit.
         Specifying any positive number will cause StyleCop to use that number as the violation count limit.
         Specifying any negative number will cause StyleCop to allow any number of violations without limit. -->
        <StyleCopMaxViolationCount Condition="'$(StyleCopMaxViolationCount)' == ''">100</StyleCopMaxViolationCount>
    </PropertyGroup>

    <!-- Define target: StyleCopForceFullAnalysis -->
    <Target Name="StyleCopForceFullAnalysis">
        <CreateProperty Value="true">
            <Output TaskParameter="Value" PropertyName="StyleCopForceFullAnalysis" />
        </CreateProperty>
    </Target>

    <!-- Define target: StyleCop -->
    <Target Name="StyleCop" Condition="'$(StyleCopEnabled)' != 'false'">
        <!-- Determine what files should be checked. Take all Compile items, but exclude those that have set ExcludeFromStyleCop=true or ExcludeFromSourceAnalysis=true. -->
        <CreateItem Include="@(Compile)" Condition="('%(Compile.ExcludeFromStyleCop)' != 'true') and ('%(Compile.ExcludeFromSourceAnalysis)' != 'true')">
            <Output TaskParameter="Include" ItemName="StyleCopFiles"/>
        </CreateItem>

        <Message Text="Forcing full StyleCop reanalysis." Condition="'$(StyleCopForceFullAnalysis)' == 'true'" Importance="Low" />

        <Message Text="Analyzing @(StyleCopFiles)" Importance="Low" />

        <!-- Run the StyleCop MSBuild task. -->
        <StyleCopTask
            ProjectFullPath="$(MSBuildProjectFile)"
            SourceFiles="@(StyleCopFiles)"
            AdditionalAddinPaths="@(StyleCopAdditionalAddinPaths)"
            ForceFullAnalysis="$(StyleCopForceFullAnalysis)"
            DefineConstants="$(DefineConstants)"
            TreatErrorsAsWarnings="$(StyleCopTreatErrorsAsWarnings)"
            CacheResults="$(StyleCopCacheResults)"
            OverrideSettingsFile="$(StyleCopOverrideSettingsFile)"
            OutputFile="$(StyleCopOutputFile)"
            MaxViolationCount="$(StyleCopMaxViolationCount)"
            />

        <!-- Make output files cleanable -->
        <CreateItem Include="$(StyleCopOutputFile)">
            <Output TaskParameter="Include" ItemName="FileWrites"/>
        </CreateItem>

        <!-- Add the StyleCop.cache file to the list of files we've written - so they can be cleaned up on a Build Clean. -->
        <CreateItem Include="StyleCop.Cache" Condition="'$(StyleCopCacheResults)' == 'true'">
            <Output TaskParameter="Include" ItemName="FileWrites"/>
        </CreateItem>
    </Target>
</Project>
  • 将以下任务添加到要运行 StyleCop 的 NAnt 脚本中。只需将 NAnt 属性替换为对您的构建脚本有意义的属性或值。

        <msbuild project="${solutionfile}" target="ReBuild" verbosity="Quiet">
           <property name="CustomAfterMicrosoftCommonTargets" value="${path::combine(project:get-base-directory(), relative-path-to-Microsoft.StyleCop.Targets)}"/>
           <property name="Configuration" value="Release"/>
           <property name="StyleCopEnabled" value="true" />
           <property name="StyleCopOutputPath" value="${directory-to-dump-output-report-to}" />
           <arg value="/noconsolelogger" />
        </msbuild>
    
于 2009-08-19T09:31:44.467 回答