Sunday, January 22, 2012

Adding the missing pieces to the Standalone StyleCop script

Rather than post the whole ~200 lines, just the salient bits so that the original can be tidied up (but without obscuring everything with obsessive error handling). Start by giving it parameters like

<# 
.SYNOPSIS 
    Stand-alone stylecop runner. 
    
.DESCRIPTION 
    Runs StyleCop over a project or a solution
        
.NOTES 
    File Name  : Run-StyleCop.ps1 
    Requires   : PowerShell Version 2.0

.PARAMETER FilesToScan

Project or Solution file

.PARAMETER StyleCopFolder

To override the heuristic looking in $env:ProgramFiles for the latest version
e.g. for StyleCop in source control

.PARAMETER OnlyBuildIntegrated

Only scan project files which include <Import Project="something with 'stylecop' in it" />
#>
param ( 
    [Parameter(Mandatory = $true)] [string] $FilesToScan,
    [string] $StyleCopFolder,
    [switch] $OnlyBuildIntegrated)

Find StyleCop in the default install location by


if (-not $StyleCopFolder) {
    $styleCopFolder =  (dir "$($env:programFiles)*\stylecop*" | Sort-object LastWriteTimeUtc | Select-Object -Last 1).FullName
}

Get the list of projects by either just the project, or using a regex on the project file from here: http://bytes.com/topic/c-sharp/answers/483959-enumerate-projects-solution


if ($FilesToScan -like "*.csproj") {
    $projectList = ,$FilesToScan
} else {
    if ($FilesToScan -like "*.sln") {
        $solutionDir = Split-Path $FilesToScan
        $matchProjectNameRegex =
            '^Project\("(?<PROJECTTYPEGUID>.*)"\)\s*=\s* "(?<PROJECTNAME>.*)"\s*,\s*"(?<PROJECTRELATIVEPATH>.*)"\s*,\s*"(?<PROJECTGUID>.*)"$'
        # or we could filter on project guid being {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
        $projectList = @(Get-Content $FilesToScan | % { 
                        $matches = $null; $_ -match $matchProjectNameRegex | Out-Null; $matches.PROJECTRELATIVEPATH } | ? {
                        $_ -like "*.csproj" } | % { Join-Path $solutionDir $_ } )
    } else {
        Write-Error "$FilesToScan isn't a solution file or a C# project"
    }
}

# Check if required for a StyleCop target
if ($OnlyBuildIntegrated) {
    $projectList = @($projectList | ? {
        [xml]$content = Get-Content $_
        $imports = @($content.Project.Import)
        $flagged = (@($imports | % { $_.Project } | ? { $_ -like "*stylecop*" })).Length
        if ($flagged -eq 0) { Write-Host "Skipping project $_" }
        ($flagged -gt 0)
})}

Find a Settings.StyleCop file by looking at the project folder and up, defaulting to one in the StyleCop folder; and then scan the C# files of interest by


[xml]$content = Get-Content $projectFile
        # All C# files
        $cs = @($content.Project.ItemGroup | % { $_.Compile } | ? {$_})
        
        # Filter excluded files; get absolute paths
        $projectDir = Split-Path $_
        $cs = @($cs | ? { -not (($cs[0].ExcludeFromStyleCop -like "true") -or ($cs[0].ExcludeFromSourceAnalysis -like "true")) 
            } | % { Join-Path $projectDir $_.Include })
        
        $cs | % { $console.Core.Environment.AddSourceCode($codeproject, $_, $null) | Out-Null }

and customise the output file as


$name = (Split-Path $projectFile -Leaf).Replace(".csproj", ".StyleCop.xml")
    $outputXml = Join-Path (Get-Location) $name

0 comments: