ちゃなべの備忘録

ほぼ備忘録です。

TypeScriptとGolangにformatterを適用してみた【備忘録】

はじめに

実装してみたプロジェクトにCICDを導入しようとしたんだが、 そもそもCIにやってほしいことがformatterくらいしかしらん。 そしてまだ導入してなかった。 じゃあ導入しよう(いま)

ぼくの前提知識

  • TypeScriptがESLintでできることは知ってる、Prettierも。
  • Goはわからん。
  • VScodeとも連携できたらうれぴい
  • formatterの設定
    • import文の順序決め
    • 変数のケース決め
    • 関数のケース決め
    • ファイル名のケース決め

調査

なんか、自分のプロジェクト調べてみたら、TypeScriptはやってたらしい。。けどまとめる。とりあえず調査はGolangを中心にやってみよう。

zenn.dev

gofmtgoimportsgoreturnsgolinesのどれかが選択肢で、この人はgoreturnsを選択

github.com

→ うわ。Golangすげぇ、公式でこんなわかりやすいdocument出してるのか。これが、formatterの基礎となりそう。

blog.y-yuki.net

→ あ、gofmtって公式なのか。知らんかった。goreturnsの立ち位置が強くないな。

alenkacz.medium.com

→ 比較記事。gofmtgoimportsgoreturnsの比較。

gofmt = golang formatter
goimports = gofmt + fixing imports
goreturns = goimports + return statement syntactic sugar

この方はCLIではgofmtで、IDEではgoreturnsと言っているが、、goreturnsだけでいい気がする。

log.include.co.jp

goreturnsの実装を書いてくれてる。

github.com

→ いやこれ最終更新が2018年!?5年前から止まっとるんかい。やめよ。

実装

  • Golanggoimports
  • TypeScriptはESLintPrettierでいこう

TypeScript

じつはこっち作ってたので、共有。 てか、リンターとフォーマッターって意味が違うのか。

  • リンター:コードチェックをしてくれる。整形は基本しない。ESLintとか。
  • フォーマッター:コード整形をしてくれる。Prettierとか。
module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: ['plugin:react/recommended', 'standard-with-typescript'],
  overrides: [],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: './tsconfig.json',
  },
  plugins: ['react', '@typescript-eslint', 'unused-imports', 'import'],
  rules: {
    'comma-dangle': ['error', 'only-multiline'],
    '@typescript-eslint/comma-dangle': 0,
    'space-before-function-paren': 0,
    '@typescript-eslint/space-before-function-paren': 0,
    '@typescript-eslint/no-unused-vars': 'off', // or "no-unused-vars"
    'unused-imports/no-unused-imports': 'error',
    'unused-imports/no-unused-vars': [
      'warn',
      { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' },
    ],
    'import/order': [
      'error',
      {
        // グループごとの並び順
        groups: [
          'builtin', // 1. fsや path などの node "builtin" のモジュール
          'external', // 2. npm install したパッケージ
          'internal', // 3. webpack などでパス設定したモジュール
          ['parent', 'sibling'], // 4. 親階層と小階層のファイル
          'object', // object"-imports
          'type', // 型だけをインポートする type imports
          'index', // 同階層のファイル
        ],
        // グループごとに改行を入れる
        'newlines-between': 'always', // "never" を指定すると改行なし
        // FIXME: ちょっとよく分かってない
        // This defines import types that are not handled by configured pathGroups. This is mostly needed when you want to handle path groups that look like external imports.
        pathGroupsExcludedImportTypes: ['builtin'],
        // アルファベット順・大文字小文字を区別しない
        alphabetize: { order: 'asc', caseInsensitive: true },
        // パターンマッチしたものをグループにする
        // "newlines-between": "always" の場合は pathGroups  ごとに空行が入る
        pathGroups: [
          // react 関連を external より前にする
          // "pathGroupsExcludedImportTypes": ["react"], にしてみたが `react`, `react-dom` などが別グループになってしまったので pattern で無理やり同じグループにした
          {
            pattern: 'react**',
            group: 'external',
            position: 'before',
          },
          // `@/entity` の import をグルーピング
          {
            pattern: '@/entity/**',
            group: 'internal',
            position: 'before',
          },
          // `@/pages` の import をグルーピング
          {
            pattern: '@/pages/**',
            group: 'internal',
            position: 'before',
          },
          // `@/components` の import をグルーピング
          {
            pattern: '@/components/**',
            group: 'internal',
            position: 'before',
          },
          // CSS module を一番最後に
          {
            pattern: './**.module.css',
            group: 'index',
            position: 'after',
          },
        ],
      },
    ],
  },
}
module.exports = {
  printWidth: 120, //1行の文字列を120文字にする
  singleQuote: true, //ダブルに代わりシングルクオーテーションを使う
  trailingComma: 'es5', //複数行の場合は可能な限り末尾のカンマを表示
  semi: false,
};

基本的にやったことは以下

  • 1行の文字数設定
  • シングルクオートに統一
  • 配列が複数行の場合は末尾にカンマ
  • importsの順番を整形

参考は以下

chaika.hatenablog.com

Go

goimportsを使っていきます。

pkg.go.dev

nishinatoshiharu.com

goimportをCLI で実行できるように

じゃあinstall

$ go install golang.org/x/tools/cmd/goimports@latest
warning: GOPATH set to GOROOT (/usr/local/go) has no effect
go: downloading golang.org/x/tools v0.6.0
go: downloading golang.org/x/sys v0.5.0
go: downloading golang.org/x/mod v0.8.0
$ ls $GOPATH/bin
go         gofmt      goimports

入ったっぽいので、早速実行

$ go imports -w main.go

おーーー!修正された! goのimports文も修正されたし、インデントも整形された。 Goらしい書き方があんまりわかってないので、とりあえずdefault(gofmt)のままでいいかな。

だけど、これが保存のたびにされてほしいな。 それこそVSCodeのprettierのプラグインみたいに。

goimportsを保存のタイミングで実行できるように

こちらのVSCodeでの設定でやる方法をしてみたのだが、うまく行かなかった。 import文は保存のタイミングで整形されたのだが、インデントとかが治らなかった。

Go言語のためのVisual Studio Codeの設定方法 | Casual Developers Note

いーーろいろ探したけど、これででけた!たぶんベスト。

zenn.dev

まず、VScode拡張機能の"Run on Save"をinstallする。

そのあと、vscodeの設定jsonファイルに行ってこれを追記。

  "emeraldwalk.runonsave": {
    "commands": [
      {
        "cmd": "goimports -w ${file}",
        "match": "\\.go$"
      }
    ]
  },

いわゆる、保存のたびにCLIを回しましょってやつですね。 するとできた!! これで保存のたびにgoimportsが効きますね。