Repair-Command.ps1

function Repair-Command
{
    <#
    .Synopsis
        Repair-Command attempts to fix your scripts.
    .Description
        Repair-Command will use a set of repair scripts to attempt to automatically
        resolve an issue uncovered with ScriptCop.
 
        Repair-Command will take all issues thru the pipeline, and will output
        an object with the Rule, Problem, ItemWithProblem, and WasFixed.
    .Link
        Test-Command
    .Example
        Get-Module MyModule | Test-Command | Repair-Command
    #>

    [OutputType([Nullable])]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "holdup", Justification="PSScriptAnalyzer false positive.")]
    param(
    # The Rule that flagged the problem
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [ValidateScript({
        if ($_ -is [Management.Automation.CommandInfo]) {
            return $true
        }
        if ($_ -is [Management.Automation.PSModuleInfo]) {
            return $true
        }

        throw 'Must be a CommandInfo or a PSModuleInfo'
    })]
    [PSObject]$Rule,

    # The Problem
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [Management.Automation.ErrorRecord]
    $Problem,

    # The Item with the Problem
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [ValidateScript({
        if ($_ -is [Management.Automation.CommandInfo]) {
            return $true
        }
        if ($_ -is [Management.Automation.PSModuleInfo]) {
            return $true
        }

        throw 'Must be a CommandInfo or a PSModuleInfo'
    })]
    [PSObject]$ItemWithProblem,

    # If set, only fixers which have indicated they will not require user interaction will be run.
    [Switch]$NotInteractive
    )

    #region Initialize The List of Problems
    begin {

        # Make a quick pair of functions to help people output the right thing
        function CouldNotFixProblem
        {
            param([string]$ErrorId)

            $info = @{
                WasIdentified=$false
                CouldFix=$false
                WasFixed=$false
                ErrorId = $errorID
                Problem=$Problem
                ItemWithProblem=$ItemWithProblem
                Rule=$Rule
                FixRequiresRescan=$false
            }

            New-Object PSObject -Property $Info
        }

        function TriedToFixProblem
        {
            param([string]$ErrorId,
            [Switch]$FixRequiresRescan)

            $stillHasThisProblem = $ItemWithProblem |
                Test-Command -Rule "$Rule" |
                Where-Object {
                    $_.Problem.FullyQualifiedErrorId -like "$ErrorId*"
                }

            New-Object PSObject -Property @{
                WasIdentified = $true
                CouldFix = $true
                WasFixed = -not ($stillHasThisProblem -as [bool])
                ErrorId = $errorId
                Problem=$Problem
                ItemWithProblem=$ItemWithProblem
                Rule=$Rule
                FixRequiresRescan=$FixRequiresRescan
            }
        }


        # Declare a list to hold the problems (for speed)
        $problems = New-Object Collections.ArrayList


    }
    #endregion

    #region Add Each Problem to the List
    process {
        $null = $problems.Add((New-Object PSObject -Property $psBoundParameters))
        Write-Verbose "Processing
$($_ | Out-String)
"

    }
    #endregion


    end {
        try {
            #region Fix the Problems That You Can
            $script:ScriptCopFixers |
                ForEach-Object -Begin {
                    $holdUp = $false
                } {
                    $fixer = $_

                    $problems |
                        & $fixer |
                        ForEach-Object {
                            $fix = $_
                            if ($fix.FixRequiresRescan) {
                                $holdUp = $true
                            }
                            throw $holdup
                        }

                    trap
                    {
                        if (-not (Get-Variable -Scope 1 -Name holdUp -ErrorAction SilentlyContinue)) {
                            throw $_
                        } else { break }
                    }
                }
        } catch {
            if ($_.InvocationInfo.Line -like '*throw $holdup*') {
                Write-Warning "Fixed $($fix.Problem) on $($Fix.ItemWithProblem), but that fix changed files, so you must rescan"
                return
            } else {
                Write-Error -ErrorRecord $_
                return
            }
        }
        #endregion
    }
}