14
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PSScriptAnalyzerを使ってPowerShellのコードをキレイに保とう

Last updated at Posted at 2019-07-27

はじめに

PSScriptAnalyzerとはPowerShellの静的コード解析ツールです。

バグになりやすい書き方や可読性を著しく低下させている箇所を警告してくれたり、
ベストプラクティスとされる書き方へ自動修整する機能を提供してくれたりしています。

MicrosoftのPowerShell公式チームが管理しているOSSで、
そこそこ有名なPowerShellのプロジェクトにはほぼ全てこちらのツールが利用されている印象です。

インストール方法

動作環境としては、Windows PowerShell 3.0以上、または、PowerShell 7.0.11以上(Linux, macOSも可)です。

PSScriptAnalyzerはVisual Studio CodeのPowerShell拡張機能(こちらもPowerShell公式チームより提供)に同梱されているため、
PowerShell Gallery等からインストールする必要はほぼ皆無です。

念のため、以下にインストールするコマンドだけ貼っておきます。

Install-Module PSScriptAnalyzer -Scope CurrentUser Force

PSScriptAnalyzer単体の機能だとコマンド経由で解析を実行します。
ただ、実際のところは既述の通り、Visual Studio Code経由で使用することがメジャーケースになるので、
この記事もそちらメインで使い方をまとめました。

コマンドでの操作方法を確認したい場合は、README.mdGet-Helpをご参照ください。

ルールについて

具体的な使い方を説明する前に、先にPSScriptAnalyzerの基本的な用語となる"ルール"について解説します。

ここでいう"ルール"とは、PSScriptAnalyzerが定義するPowerShellのベストプラクティスな書き方となる規約、のことです。

例えば、PowerShellスクリプト内でコマンドレットのエイリアスを使った場合、
コーディングしているときは便利ですが、使い過ぎると可読性が低下するという考えがあります。
※あくまで考えというだけで、「絶対にそうだ!」とここで言っているわけではありません。

PSScriptAnalyzerでは、このエイリアスを避ける規約をAvoidUsingCmdletAliasesというルール名で定義しています。
これが、ここでいう"ルール"の意味です。

また、一つ一つのルールにはSeverityが設定されており、警告の重さが決められています。
このSeverityはError、Warning、Informationの3段階で管理されています。

利用可能なルール一覧

PSScriptAnalyzerが提供しているルールは全部で59個あり、
PSScriptAnalyzer Rules - GitHubから確認することができます。

Errorが10個、Warningが43個、Informationが6個あり、そのうちルールごとに設定可能なものは10個あるようです。
READE.mdには載っていませんが、自動修整できる機能が利用できるルールは7つほどしかないようです。

Visual Studio Code上での使用法

まず、設定ファイル等を利用せずにPowerShellの拡張機能をインストールしたVisual Studio Codeで
どの程度の機能が利用できるのかを解説していきます。

警告内容の表示

以下のスクショにある通り、PSScriptAnalyzerの何らかのルールに違反している箇所がある場合、
波線で違反している箇所が示されます。
※波線の色はSeverityによって異なり、Errorは赤、Warningは黄、Informationは緑となります。
image.png

上のスクショでは、警告されているlsにカーソルを持っていき、Alt+F8で「問題を表示」している状態です。
今回はAvoidUsingCmdletAliasesというエイリアスの使用を禁止するルールに違反していると警告が出ています。

これらの警告している箇所はエディタペインに波線で表示されるほかに
開いているファイル内の警告であれば「問題」タブ内にも一覧で表示されます。

自動修正の適用

警告されている箇所と理由が把握できたら、コードを修正していきます。
下のスクショはlsカーソルがある状態から、Ctrl+.で「修正プログラムを利用する」を実施した結果です。

image.png

「Replace ls with Get-ChildItem」をクリックすることでlsのエイリアス元であるGet-ChildItemで修正されます。
「Show documentation for ...」はデフォルトのブラウザで該当のルールページが表示され、ルールの詳細を把握するのに便利です。

修正後は以下のように波線はなくなり、問題は検出されていないと表示されました。
image.png

検査するルールの無効/有効化

Ctrl+Shift+Pを押し、プロンプトにPowerShell: Select PSScと入力すると
PSScriptAnalyzerで検査するルール一覧が表示され、無効/有効に切り替えることができます。

image.png

上のスクショでは、まずデフォルトで有効になっている「AvoidUsingCmdletAliases」のチェックを外して「Confirm」をクリックし、
ファイルを一旦閉じて再度開く(Ctrl+w, Ctrl+Shift+t)とlsの警告が表示されなくなりました。

PSScriptAnalyzerSettings.psd1でプロジェクト固有の設定を定義する

Visual Studio Codeだと標準でPSScriptAnalyzerが有効になっているので、
設定ファイルなど作成しなくても利用すること自体はできます。

ただ、Visual Studio Code自体を一旦閉じてしまうと無効・有効にしているルールは標準設定に戻り、
その他細かいルールの表示設定はできません。

そのため、プロジェクトでいつも同じルールの無効/有効化を常にしたい場合や
ほかに利用できるPSScriptAnalyzerの設定項目を利用したい場合は
PSScriptAnalyzerSettings.psd1というファイルを作成し、そのファイル内に設定内容を追加する必要があります。

配置の仕方

PSScriptAnalyzerを使用する際はだいたいプロジェクトのルートディレクトリ直下に
PSScriptAnalyzerSettings.psd1を配置します。

Visual Studio CodeのPowerShell拡張機能の場合、「フォルダを開く」で指定されたディレクトリ直下に
こちらのファイルがあった場合、自動で設定内容を反映してくれるようです。

なお、プロジェクトのルートディレクトリ直下以外、または、明示的にどの設定ファイルを利用するか指定したい場合は、
.vscode\settings.jsonに以下のような設定をすることで反映できます。

.vscode\settings.json
{
  // プロジェクトルートからの相対パスで指定可能です。
  "powershell.scriptAnalysis.settingsPath": "rules/PSScriptAnalyzerSettings_Strict.psd1",
  // 他にもリアルタイムの静的解析のON/OFFも設定可能です。デフォルトはtrueです。
  "powershell.scriptAnalysis.enable": false
}

検査するSeverityの指定

では、PSScriptAnalyzerSettings.psd1の中身について解説していきます。

SeverityはErrorWarningInformationの3段階ありますが、
その中から検査するSeverityを絞ることができます。

PSScriptAnalyzerSettings.psd1
@{
    # 'Error'と'Warning'しか表示しない。
    Severity = @('Error', 'Warning')
}

検査するルールを指定

必要最小限しか警告されたくない場合はIncludeRulesで限られたルールのみ指定することが可能です。

PSScriptAnalyzerSettings.psd1
@{
    # 4つのルールのみを警告する。
    IncludeRules = @('PSAvoidDefaultValueSwitchParameter',
                     'PSMisleadingBacktick',
                     'PSMissingModuleManifestField',
                     'PSReservedCmdletChar')
}

検査を除外するルールの指定

反対に必要最小限のルールを除外したい場合はExcludeRulesで指定します。
GitHubを見ると、こちらの方がよく使われている印象でした。

PSScriptAnalyzerSettings.psd1
@{
    ExcludeRules = @(
        # 色付きのメッセージをWrite-Hostで行っているため。
        'PSAvoidUsingWriteHost',
        # 現状`Invoke-Expression`を使わざるを得ないため。
        'PSAvoidUsingInvokeExpression'
    )
}

ちなみに同じルールをIncludeRulesでもExcludeRulesでも指定した場合は、
ExcludeRulesが優先的に適応されるため、そのルールは除外となります。

ルールごとに詳細な設定値を指定

一つ一つのルールにおいても、設定ファイルでカスタマイズすることができます。
GitHubを見ると、だいたいPSAvoidUsingCmdletAliasesPSUseCompatibleCmdletsが多い印象でした。

PSScriptAnalyzerSettings.psd1
@{
    Rules = @{
        # 以下のエイリアスについては使用可能とする。
        PSAvoidUsingCmdletAliases = @{
            # (gal -d "*-Object").Name
            Whitelist = @(
                '%',
                '?',
                'compare',
                'diff',
                'foreach',
                'group',
                'measure',
                'select',
                'sort',
                'tee',
                'where'
            )
        }

        # スクリプト内のコマンドレットがPowerShell Coreと互換性があるか確認する。
        PSUseCompatibleCmdlets = @{Compatibility = @("core-6.0.0-alpha-linux")}
}

Pesterとの連携

PowerShellのテスティングツールとしてお馴染みのPesterと連携し、
全てのルールを守れているかをテスト結果に含めることも可能です。

やり方としてはPSScriptAnalyzer.Tests.ps1のようなテストファイルを作っておいて、
中でInvoke-ScriptAnalyzerコマンドの実行結果をアサーションするテストケースを書くことで可能となります。

LabilityというHyper-Vのプロビジョニングツールで実装されていたので、
試したい方はこちらを参考にしてみるとよさそうです。

この記事で紹介しなかったこと

他にもPowerShellのASTを使って独自でルールを追加することや自動修正を作成することも可能となっています。

その他の詳しい使い方についてはこちらのドキュメントをご参照ください。
https://github.com/PowerShell/PSScriptAnalyzer/blob/master/ScriptRuleDocumentation.md

ただ、ほとんどのプロジェクトはこの記事で解説していないような複雑なことは行っていなかったので、
無理にカスタマイズする必要はないと思います。

まとめ

GitHubのfilename検索オプションは便利。

14
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?