鈴木颯介のブログ

Prettier にコントリビュートした(10)

解決した Issue

https://github.com/prettier/prettier/issues/6269

TS/Flow でReact.useEffect(のような形をした)関数の特定の位置にコメントを入れるとフォーマットが崩れ、複数のコメントを入れた場合、冪等性も崩れてしまうというバグです。

// Input
function Component() {
  useEffect(
    () => {
      console.log("foo");
    }),

    // comment01
    // comment02
    // comment03
    []
  );
}

// Output(first)
function Component() {
  useEffect(
    () => {
      console.log("foo");
    }), // comment01
    // comment02
    // comment03
    []
  );
}

// Output(second)
function Component() {
  useEffect(
    () => {
      console.log("foo");
    }), // comment02 // comment01
    // comment03
    []
  );
}

// Output(third)
function Component() {
  useEffect(
    () => {
      console.log("foo");
    }), // comment03 // comment02 // comment01
    []
  );
}

// Output(forth)
function Component() {
  useEffect(
    () => {
      console.log("foo");
    }),
    []
  ); // comment03 // comment02 // comment01
}

これはおもしろいですね。見事に冪等性が壊れています。

出した PR

https://github.com/prettier/prettier/pull/6270

これはわかっていればすごく簡単な問題で、@babel/parser でパースした場合、コメントがノードに対してtrailingCommentsもしくはleadingCommentsとして含まれるんですが、TS や Flow の場合はパースの段階でそのようにはならず、Prettier 側でcommentsとして AST の中のそのノードに追加されます。(@babel/parser でパースした場合も Prettier 側でcommentsの追加は行われる)

なので、trailingCommentsおよびleadingCommentsでコメント有無を判定していたのを、commentsで判定するように変更しました。