6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

coc.nvimでPHPStanやPHP_CodeSnifferを使う

Last updated at Posted at 2021-03-22

coc.nvimはVimのLSPクライアント・プラグインの一つです。

cocは自分自身がVimプラグインでありながら、拡張機能(エクステンション)の機構を持っており、LSPサーバをエクステンションをとしてインストールすることで機能を追加することができます。

PHPのLSPサーバのcocエクステンションもいくつかあります。例えばPHPのLSPサーバであるIntelephenseのcocエクステンションとしてcoc-phplsがあります。

coc-phplsをインストールするとcoc経由でPHPの自動補完・定義ジャンプ・ホバー(ヒント)表示・バグ検出などの機能を使えるようになります。

coc-phplsだけでもある程度のバグ検知は可能ですが、Intelephenseが提供するバグ検出は現時点ではPHPStanに比べると弱く、またPHP_CodeSnifferのようにコーディング規約違反を検出するものではありません。

こういうときに使えるのがdiagnostic-languageserverのcocエクステンションであるcoc-diagnosticです。

diagnostic-languageserverは各種linterと統合することで診断機能を提供する汎用言語サーバです。そのcocエクステンションであるcoc-diagnosticを使えば、PHPStanやPHP_CodeSnifferをcoc経由で使えるようになります。

インストール方法

  1. coc-diagnosticをインストールする。

    :CocInstall coc-diagnostic
    
  2. PHPStan、PHP_CodeSnifferをインストールする。

    composer require --dev phpstan/phpstan
    
    composer require squizlabs/php_codesniffer
    
  3. coc-settings.jsonに下記を設定する。

{~/.vim/coc-settings.json}
{
    "diagnostic-languageserver.filetypes": {
        "php": ["phpcs", "phpstan"]
    }
}

coc-diagnosticはデフォルトの設定./vendor/bin/phpstan./vendor/bin/phpcsを実行するようになっているので、Composerでローカルインストールしたのであればこれだけで使えるはずです。

こんな感じでcoc経由でPHPStanやPHP_CodeSnifferの出力が見れると思います。

スクリーンショット 2021-03-22 014726.png

linterの設定をカスタマイズする

coc-diagnosticはlinterの設定をカスタマイズすることもできます。下記に例を載せます。

{~/.vim/coc-settings.json}
{
    "diagnostic-languageserver.mergeConfig": true,
    "diagnostic-languageserver.linters": {
        "phpcs": {
            "command": "./tools/phpcs",
            "args": ["--report=emacs", "-s", "-"],
        },
        "phpstan": {
            "command": "./tools/phpstan"
        }
    }
}

diagnostic-languageserver.mergeConfigtrueに設定すると、追加した設定をデフォルトの設定とマージしてくれるので、差分だけを記載することができます。

上記の例ではcommandで実行ファイルのパスをComposerではなくPHIVEでローカルインストールした場合のパス(./tools/phpstan./tools/phpcs)に変更しています。また、PHP_CodeSnifferのデフォルトのargsから"--standard=PSR2"を削除することで、プロジェクトディレクトリ配下にあるphpcs.xmlを使うようにしています。

Dockerコンテナ上のPHPを使う

私はDocker(Laradock)を使って開発しており、ローカルにはPHPをインストールしていません。なので当然ですが、ローカルのPHPStanやPHP_CodeSnifferを実行できないため、上記の設定では動きません。こんな場合でも設定をひと工夫すれば、少し無理やりですがDockerコンテナ上のPHPを使って動かすことができます。

{~/.vim/coc-settings.json}
{
    "diagnostic-languageserver.mergeConfig": true,
    "diagnostic-languageserver.linters": {
        "ngmy.laradock.phive.phpcs": {
            "command": "docker",
            "debounce": 100,
            "rootPatterns": ["composer.json", "composer.lock", "vendor", ".git"],
            "args": ["exec", "-u", "laradock", "laradock_workspace_1", "php", "tools/phpcs", "--report=emacs"],
            "offsetLine": 0,
            "offsetColumn": 0,
            "sourceName": "phpcs",
            "formatLines": 1,
            "formatPattern": [
                "(^.*):(\\d+):(\\d+):\\s+(.*)\\s+-\\s+(.*)(\\r|\\n)*$",
                {
                    "sourceName": 1,
                    "sourceNameFilter": true,
                    "line": 2,
                    "column": 3,
                    "message": 5,
                    "security": 4
                }
            ],
            "securities": {
                "error": "error",
                "warning": "warning"
            }
        },
        "ngmy.laradock.phive.phpstan": {
            "command": "docker",
            "debounce": 100,
            "rootPatterns": ["composer.json", "composer.lock", "vendor", ".git"],
            "args": ["exec", "-u", "laradock", "laradock_workspace_1", "php", "tools/phpstan", "analyse", "--error-format", "raw", "--no-progress"],
            "offsetLine": 0,
            "offsetColumn": 0,
            "sourceName": "phpstan",
            "formatLines": 1,
            "formatPattern": [
                "^/var/www/([^:]+):(\\d+):(.*)(\\r|\\n)*$",
                {
                    "sourceName": 1,
                    "sourceNameFilter": true,
                    "line": 2,
                    "message": 3
                }
            ]
        }
    },
    "diagnostic-languageserver.filetypes": {
        "php": ["ngmy.laradock.phive.phpcs", "ngmy.laradock.phive.phpstan"]
    }
}

PHPStanとPHP_CodeSnifferの新しいlinter設定を追加しています。設定内容はデフォルトの設定をベースにしています。デフォルトの設定を上書きしていない理由は、Docker越しに使うという用途が特殊なので、デフォルトの設定を残しておきたいと思ったからです。設定名はなんでも良いのですが、デフォルトの設定と被らないようにしています。

commandargsを使ってdocker execを実行することで、Dockerコンテナ(私の場合はLaradockのworkspaceコンテナ)でPHPStanやPHP_CodeSnifferを実行するようにしています。

PHPStanのデフォルトのargsの最後にある"%file"を削除しています。%fileはdiagnostic-languageserverが用意しているargsで使える変数で、Vimで開いているファイルのフルパスに展開されます。他にもいくつかの変数が用意されています。削除する理由は、フルパスに展開されるとローカルのパスとDockerコンテナ上のパスが食い違ってしまい解析できないためです。削除すると、プロジェクトディレクトリ配下のphpstan.neonを使うようになるので、そこに記載されている全対象ファイルに対してPHPStanが実行されるようになります。

全対象ファイルに対して実行されたPHPStanの出力を今Vimで開いているファイルに対してだけ表示するために、formatPatternの正規表現を変更して相対パスを抽出してSourceNameとして使用しています。さらに複数ファイルを開いたときに出力が混ざらないように、sourceNameFiltertrueにしています。

もし相対パスに展開してくれる変数があればそれで済む話ですが、今のところないようなので、こんな設定をしています。

同じ理由で、PHP_CodeSnifferもargsから"-s", "-"を削除して、formatPatternを変更しています。

diagnostic-languageserver.mergeConfigtrueにしているのはコンテナ名を上書きできるようにするためです(後述)。

全対象ファイルに対して実行しているせいか少し処理が遅い気がしますが、数十ファイル程度の小さなプロジェクトであれば許容範囲内に感じています。

任意のDockerコンテナ上のPHPを使う

プロジェクトごとにLaradockをインストールしている場合、プロジェクトごとにコンテナ名が異なると思います。そういうときはプロジェクトディレクトリの配下に.vim/coc-settings.jsonを作ります。

cocは~/.vim/coc-settings.jsonとプロジェクトディレクトリ配下の.vim/coc-settings.jsonをマージしてくれます。この辺りの仕様についてはここに記載があります。

{some-project/.vim/coc-settings.json}
{
    "diagnostic-languageserver.linters": {
        "ngmy.laradock.phive.phpcs": {
            "args": ["exec", "-u", "laradock", "laradock-some-project_workspace_1", "php", "tools/phpcs", "--report=emacs"]
        },
        "ngmy.laradock.phive.phpstan": {
            "args": ["exec", "-u", "laradock", "laradock-some-project_workspace_1", "php", "tools/phpstan", "analyse", "--error-format", "raw", "--no-progress"],
        }
    }
}

argsでコンテナ名を変更しています。

こんな感じの設定を、cocを使いたい各プロジェクトに書いています。

以上です。

2021年5月7日追記

diagnostic-languageserverに相対パスに展開してくれる変数%relativepathが追加されたので、Dockerコンテナ上のPHPを使う場合、下記の設定で単一のファイルに対してのみlinterを実行できるようになりました。

{~/.vim/coc-settings.json}
{
    "diagnostic-languageserver.mergeConfig": true,
    "diagnostic-languageserver.linters": {
        "ngmy.laradock.phive.phpcs": {
            "command": "docker",
            "debounce": 100,
            "rootPatterns": ["composer.json", "composer.lock", "vendor", ".git"],
            "args": ["exec", "-u", "laradock", "laradock-workspace_1", "php", "tools/phpcs", "--report=emacs", "%relativepath"],
            "offsetLine": 0,
            "offsetColumn": 0,
            "sourceName": "phpcs",
            "formatLines": 1,
            "formatPattern": [
                "^.*:(\\d+):(\\d+):\\s+(.*)\\s+-\\s+(.*)(\\r|\\n)*$",
                {
                    "line": 1,
                    "column": 2,
                    "message": 4,
                    "security": 3
                }
            ],
            "securities": {
                "error": "error",
                "warning": "warning"
            }
        },
        "ngmy.laradock.phive.phpstan": {
            "command": "docker",
            "debounce": 100,
            "rootPatterns": ["composer.json", "composer.lock", "vendor", ".git"],
            "args": ["exec", "-u", "laradock", "laradock-workspace_1", "php", "tools/phpstan", "analyse", "--error-format", "raw", "--no-progress", "%relativepath"],
            "offsetLine": 0,
            "offsetColumn": 0,
            "sourceName": "phpstan",
            "formatLines": 1,
            "formatPattern": [
                "^[^:]+:(\\d+):(.*)(\\r|\\n)*$",
                {
                    "line": 1,
                    "message": 2
                }
            ]
        }
    },
    "diagnostic-languageserver.filetypes": {
        "php": ["ngmy.laradock.phive.phpcs", "ngmy.laradock.phive.phpstan"]
    }
}
{some-project/.vim/coc-settings.json}
{
    "diagnostic-languageserver.linters": {
        "ngmy.laradock.phive.phpcs": {
            "args": ["exec", "-u", "laradock", "laradock-some-project_workspace_1", "php", "tools/phpcs", "--report=emacs", "%relativepath"]
        },
        "ngmy.laradock.phive.phpstan": {
            "args": ["exec", "-u", "laradock", "laradock-some-project_workspace_1", "php", "tools/phpstan", "analyse", "--error-format", "raw", "--no-progress", "%relativepath"],
        }
    }
}
6
3
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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?