02 January 2022

Perl・Python・PHPのコード整形ツール設定メモ(perltidy, perlcritic, autopep8, flake8, phpcs/phpcbf)

コード整形ツールをインストール、初期設定をするためのメモ

(Perlコード整形) perltidy

公式Webページとドキュメントはこちら(https://metacpan.org/pod/perltidy)。 VS Codeでは、ソースコードを保存するときに、perltidyを実行することができる

インストールはlinuxのパッケージマネージャで行う

$ sudo apt-get install perltidy

~/.perltidyrc に毎回指定するオプションをあらかじめ設定しておく。私が常に使っているオプションは次のようなもの

~/.perltidyrc
# Perltidy 設定ファイル
# 設定詳細は https://metacpan.org/pod/perltidy

##### Basic Options
-enc=utf8       # (--character-encoding)
-ole=unix       # (--output-line-ending) 改行は LF
-i=4            # (--indent-columns) タブを空白4とする
-l=100          # (--maximum-line-length) 1行の長さが150文字以内に収まるようにする

##### Code Indentation Control
-cti=1          # (--closing-token-indentation) 配列などの対応する「括弧閉じる」を開始位置までインデント

##### Blank Line Control
-kbl=0          # (--keep-old-blank-lines) 空白行をすべて最適化する

##### I/O control
-b              # (--backup-and-modify-in-place) 整形後にファイルを上書きし、整形前のものは .bak とする(defaultは整形後を .tdy)

コマンドラインでの使い方

-b スイッチをつけることで、整形後の結果で上書きし、元のファイルを拡張子 .bak として保存する

$ perltidy -b test.pl

Visual Studio Codeで利用する場合

デバッグのための必須ツールのLanguage Server and Debugger for Perlを導入すれば、その機能の一部としてperltidyも使えるようになる。

20220102-vscode-perltidy01.jpg
Language Server and Debugger for Perl

コード整形が必要になれば、エディタ画面で F1 キーを押し、検索ボックスに Format と入力すれば、整形ツール(Formatter)メニューが表示される。

20220102-vscode-perltidy02.jpg

なお、ショートカットキーはWindowsとLinuxでは違う(私の環境では違う)ので、キーコンビネーションで覚えると弊害があるかもしれない

(Perl 文法チェック)perlcritic

コードの文法チェックしてくれるツール。公式Webページとドキュメントはこちら(https://metacpan.org/dist/Perl-Critic/view/bin/perlcritic)。表示されるエラーの説明は、Damian Conway 著 Perl Best Practicesというオライリー出版の書籍のページ番号で表示される。

perlcriticの出力例で、黄色で着色した部分が書籍でのページ番号。書籍を持っていない場合は、公式ページの Perl::Critic::Policy 配下にあるモジュールのページを参照すればよい

Useless interpolation of literal string at line 10, column 11.  See page 51 of PBP.

インストールはcpanで行うか、

$ sudo cpan Perl::Critic

linuxのパッケージマネージャで行える

$ sudo apt install libperl-critic-perl

~/.perlcriticrc に検出してほしくないチェック項目などを書き込んでおくと、警告だらけにならない。

~/.perlcriticrc
# perlcritic 設定
# ( perlcritic --profile-proto で標準設定をテキストに出力し、編集する )
# ( 実際に出力したテキストを参考までに「こちら」に掲載 ) 

# Globals
# severity = 5
severity = 2
# force = 0
# only = 0
only = 0
# allow-unsafe = 0
# profile-strictness = warn
# color = 0
# pager =
# top = 0
# verbose = 4
# include =
# exclude =
# single-policy =
# theme =
# color-severity-highest = bold red
# color-severity-high = magenta
# color-severity-medium =
# color-severity-low =
# color-severity-lowest =
# program-extensions =

### 以下、警告を抑止したり、停止したりするサンプル例
# perlcritic --profile-proto の出力をコピペし、必要な箇所を修正

# C言語のような for(i=0; i<10; i++) 記法を警告するのを抑制する
# (公式Webページの解説 Perl::Critic::Policy)

# Write `for(0..20)' instead of `for($i=0; $i<=20; $i++)'.
[ControlStructures::ProhibitCStyleForLoops]
# set_themes                         = core maintenance pbp
# add_themes                         =
# severity                           = 2
severity                           = 1
# maximum_violations_per_document    = no_limit


# スクリプトにはバージョン番号を書くべし(例  our $VERSION = 1.0)警告を無効化
# (公式Webページの解説 Perl::Critic::Policy)
# 設定のセクション先頭に - (マイナス記号)を入れると、そのルールは無効化出来る

# Give every module a `$VERSION' number.
[-Modules::RequireVersionVar]
# set_themes                         = core pbp readability
# add_themes                         =
# severity                           = 2
# severity                           = 1
# maximum_violations_per_document    = no_limit


# 文字列をシングルクォート'...'ではなく、ダブルクォート"..."で
#   囲むなという「Useless interpolation of literal string」警告を
#   より低いSeverityでも出るようにすることが出来る
# ※エスケープや変数展開が必要なければ、シングルクォートが安全なため
# (公式Webページの解説 Perl::Critic::Policy)

# Always use single quotes for literal strings.
[ValuesAndExpressions::ProhibitInterpolationOfLiterals]
# set_themes                         = core cosmetic pbp
# add_themes                         =
# severity                           = 1
severity                           = 2
# maximum_violations_per_document    = no_limit

# Kinds of delimiters to permit, e.g. "qq{", "qq(", "qq[", "qq/".
# allow =

# If the string contains ' characters, allow "" to quote it.
# allow_if_string_contains_single_quote = 0


# スクリプト中に直接、定数を書くな(constant変数を介せ)警告
#  「Unnamed numeric literals make code less maintainable」は、
#   最も厳しい Severity=1 だけに限定する
# (公式Webページの解説 Perl::Critic::Policy)

# Don't use values that don't explain themselves.
[ValuesAndExpressions::ProhibitMagicNumbers]
# set_themes                         = certrec core maintenance
# add_themes                         =
# severity                           = 2
severity                           = 1
# maximum_violations_per_document    = 10

# Individual and ranges of values to allow, and/or "all_integers".
# allowed_values = 0 1 2

# Kind of literals to allow.
# Valid values: Binary, Exp, Float, Hex, Octal.
# allowed_types = Float

# Should anything to the right of a "=>" be allowed?.
# allow_to_the_right_of_a_fat_comma = 1

# Names of subroutines that create constants.
# Values that are always included: Readonly, Readonly::Array, Readonly::Hash, Readonly::Scalar, const.
# constant_creator_subroutines = 

コマンドラインでの使い方

チェックレベルは5段階あり、1が最も厳しいチェックが入り、5は最低限のチェックしか行われない。

チェックレベル(公式Webページからの転載)
    SEVERITY NAME   ...is equivalent to...   SEVERITY NUMBER
    --------------------------------------------------------
    --severity gentle                           --severity 5
    --severity stern                            --severity 4
    --severity harsh                            --severity 3
    --severity cruel                            --severity 2
    --severity brutal                           --severity 1

実際に、チェックを行った場合の表示例

$ perlcritic --severity 1 test.pl
エラー: No word lists can be found for the language "ja_JP".
Code is not tidy at line 1, column 1.  See page 33 of PBP.  (Severity: 1)
No package-scoped "$VERSION" variable found at line 1, column 1.  See page 404 of PBP.  (Severity: 2)
Useless interpolation of literal string at line 10, column 11.  See page 51 of PBP.  (Severity: 1)
Useless interpolation of literal string at line 14, column 7.  See page 51 of PBP.  (Severity: 1)
Return value of flagged function ignored - print at line 16, column 1.  See pages 208,278 of PBP.  (Severity: 1)
Builtin function called with parentheses at line 21, column 5.  See page 13 of PBP.  (Severity: 1)
Return value of flagged function ignored - print at line 21, column 5.  See pages 208,278 of PBP.  (Severity: 1)
Useless interpolation of literal string at line 21, column 12.  See page 51 of PBP.  (Severity: 1)
Builtin function called with parentheses at line 22, column 5.  See page 13 of PBP.  (Severity: 1)
Return value of flagged function ignored - print at line 34, column 1.  See pages 208,278 of PBP.  (Severity: 1)
Useless interpolation of literal string at line 34, column 7.  See page 51 of PBP.  (Severity: 1)

$ perlcritic --severity 2 test.pl
No package-scoped "$VERSION" variable found at line 1, column 1.  See page 404 of PBP.  (Severity: 2)

$ perlcritic --severity 3 test.pl
test.pl source OK

Visual Studio Codeで利用する場合

20220102-vscode-perlcritic01.jpg
Perl Toolbox拡張機能を導入するとperlcriticが使えるようになる

設定画面では...

20220102-vscode-perlcritic02.jpg

実行ファイル設定(Lint:Exec perlcritic library)に、perlcritic コマンドがデフォルトで設定されている

20220102-vscode-perlcritic03.jpg

また、チェックレベル設定(Lint:Severity)はデフォルトでは brutal(レベル 1) となっているが、警告が出すぎるので、cruel(レベル 2)あたりが妥当なレベル。なお、このチェックレベル設定は、~/.perlcriticrc 内の設定より優先される

無効化したい警告は、~/.perlcriticrc に書くのではなく、VS Codeのsettings.jsonに書く (~/.perlcriticrc を読み込んでくれないのは、バグなのか、そういう仕様なのか、私が設定箇所を間違っているのか...)

ソースコード
{
    "workbench.colorTheme": "Visual Studio Dark",
    "[perl]": {
        "editor.defaultFormatter": "Kaktus.perltidy-more"
    },
    "editor.formatOnType": true,
    "editor.fontSize": 15,
    "editor.renderWhitespace": "boundary",
    "editor.renderLineHighlight": "all",
    "files.eol": "\n",
    "workbench.editorAssociations": {
        "*.ipynb": "jupyter.notebook.ipynb"
    },
    "perl-toolbox.lint.severity": "cruel",
    "perl-toolbox.lint.excludedPolicies": [
        "ControlStructures::ProhibitCStyleForLoops",
        "Modules::RequireVersionVar",
    ]
}

(Pythonコード整形)autopep8

公式Webページとドキュメントはこちら(https://github.com/hhatto/autopep8)。

インストールはlinuxのパッケージマネージャで行う

$ sudo apt-get install python3-autopep8

コマンドラインでの使い方

$ autopep8 --in-place --aggressive --aggressive test.py

--in-place スイッチは、整形結果を上書き保存する。--aggressive スイッチは複数つけることができ、つけるほどに最適化レベルが上がる。

Visual Studio Codeで利用する場合

MicrosoftのPython拡張機能を導入すれば、autopep8の機能が使えるようになる。※2022年4月追記 : autopep8機能はMicrosaoft Python拡張機能から独立した単体の拡張機能となったため、autopep8拡張機能を導入すること。

20220102-vscode-autopep801.jpg

コード整形が必要になれば、エディタ画面で F1 キーを押し、検索ボックスに Format と入力すれば、整形ツール(Formatter)メニューが表示される。

20220102-vscode-perltidy02.jpg

autopep8 実施時のオプション(プログラム起動時の引数)は、 settings.json に書き込んでおけばよい

ソースコード
{
    "workbench.colorTheme": "Visual Studio Dark",
    "[perl]": {
        "editor.defaultFormatter": "Kaktus.perltidy-more"
    },
    "editor.formatOnType": true,
    "editor.fontSize": 15,
    "editor.renderWhitespace": "boundary",
    "editor.renderLineHighlight": "all",
    "files.eol": "\n",
    "workbench.editorAssociations": {
        "*.ipynb": "jupyter.notebook.ipynb"
    },
    "perl-toolbox.lint.severity": "cruel",
    "perl-toolbox.lint.excludedPolicies": [
        "ControlStructures::ProhibitCStyleForLoops",
        "Modules::RequireVersionVar",
    ],
    "python.formatting.autopep8Args": [
        "--aggressive",
        "--aggressive",
        "--max-line-length", "80",
    ],
}

※autopep8拡張機能の設定例は次の通り

    "autopep8.args": [
        "--aggressive",
        "--aggressive",
        "--max-line-length",
        "100"
    ],

(Python 文法チェック)flake8

公式Webページとドキュメントはこちら(https://pypi.org/project/flake8/

インストールはpipで行うことも出来るし、

$ sudo apt-get install python-flake8
$ sudo apt-get install python3-flake8

あるいはpipコマンドで行える

$ pip install flake8
$ python3 -m pip install flake8

上で上げたインストールコマンドは、それぞれ上段はPython2、下段はPython3用で、両方がインストールされているシステムでは必要な方(あるいは両方)をインストールする

コマンドラインでの使い方

$ flake8 --statistics --show-source test.py

Visual Studio Codeで利用する場合

設定の Linting: Flake8 Enabled にチェックを入れて有効化する (私の環境では、デフォルトで無効となっていた)。

また、flake8の設定項目の少し上に Linting: Enabled というチェック項目もあるため、こちらも有効となっているか念のため確認

20220103-vscode-flake801.jpg

文法チェックが必要になれば、エディタ画面で F1 キーを押し、検索ボックスに Lint と入力すれば、文法チェック(Run Lint)メニューが表示される。

20220103-vscode-flake802.jpg

(PHPコード整形)phpcbf

phpcbf(コード整形) と phpcs(文法チェック)は、GitHubのリポジトリPHP_CodeSnifferで配布されている。

PHPのライブラリ管理ツールComposerや、一昔前のライブラリ管理ツールPEARでもセットアップできるようだが、自分の目で見てセットアップするには、GitHubから直接ダウンロードして展開するのがいちばんかんたん。

GitHubからダウンロードしたパッケージのディレクトリを、まるごと/opt 以下にコピーする。そして、PATHの通っているディレクトリ(/usr/local/bin/)に、phpcbfとphpcsコマンドのシンボリックリンクを作る。

$ git clone https://github.com/squizlabs/PHP_CodeSniffer.git
$ sudo cp -r ./PHP_CodeSniffer /opt
$ sudo ln -s /opt/PHP_CodeSniffer/bin/phpcbf /usr/local/bin/
$ sudo ln -s /opt/PHP_CodeSniffer/bin/phpcs /usr/local/bin/

コマンドラインでの使い方

$ phpcbf --standard=PSR12 test.php

対象ファイルはバックアップ無しで上書きされる。

上の例では PSR-12コーディング規約に準拠するコード整形を行っているが、サポートする規格一覧は次のコマンドで出力できる。引数 --standard でコーディング規約を指定しなければ、PEARコーディング規約が用いられる(phpcbf -v で利用されるコーディング規約を表示できる)

$ phpcbf -i
The installed coding standards are PSR2, Zend, PEAR, PSR1, PSR12, MySource and Squiz

(PHP文法チェック)phpcs

phpcbf と同時にインストールされるので、インストール方法は cppcbf の項目を参照

コマンドラインでの使い方

$ phpcs --standard=PSR12 test.php
FILE: /home/user/test/test.php
---------------------------------------------------------------------------
FOUND 4 ERRORS AND 1 WARNING AFFECTING 4 LINES
---------------------------------------------------------------------------
  5 | ERROR   | [x] Whitespace found at end of line
  6 | ERROR   | [x] Whitespace found at end of line
 13 | ERROR   | [x] Expected 1 space(s) after IF keyword; 0 found
 13 | ERROR   | [x] Expected 1 space(s) after closing parenthesis; found 0
 15 | WARNING | [ ] Line exceeds 120 characters; contains 164 characters
---------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
---------------------------------------------------------------------------

チエック( [x] )が入ったエラー/警告は、phpcbfで修正できる項目

同じファイルをPEARコーディング規約でチェックすると、全く違う結果となる

$ phpcs -v test.php 
Registering sniffs in the PEAR standard... DONE (28 sniffs registered)
Processing test.php [PHP => 56 tokens in 18 lines]... DONE in 1ms (9 errors, 2 warnings)
FILE: /home/user/test/test.php

--------------------------------------------------------------------------------
FOUND 9 ERRORS AND 2 WARNINGS AFFECTING 4 LINES
--------------------------------------------------------------------------------
  4 | ERROR   | [ ] Doc comment short description must start with a capital
    |         |     letter
  7 | WARNING | [ ] PHP version not specified
  7 | ERROR   | [ ] Missing @category tag in file comment
  7 | ERROR   | [ ] Missing @package tag in file comment
  7 | ERROR   | [ ] Missing @author tag in file comment
  7 | ERROR   | [ ] Missing @license tag in file comment
  7 | ERROR   | [ ] Missing @link tag in file comment
  7 | ERROR   | [x] Additional blank lines found at end of doc comment
 13 | ERROR   | [ ] Expected "if (...) {\n"; found "if(...){\n"
 13 | ERROR   | [x] There must be a single space between the closing
    |         |     parenthesis and the opening brace of a multi-line IF
    |         |     statement; found 0 spaces
 15 | WARNING | [ ] Line exceeds 85 characters; contains 164 characters
--------------------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
--------------------------------------------------------------------------------