dprint-plugin-typescript icon indicating copy to clipboard operation
dprint-plugin-typescript copied to clipboard

Formatting is unstable (not idempotent)

Open adrian-gierakowski opened this issue 1 year ago • 5 comments

Describe the bug

Running dprint fmt on the on some code twice, leads to different output each time.

Input Code

const createTestData = () =>
  function*() {
    const startingFrom = yield* Effect.map(DateTime.now, now =>
      DateTime.startOf(now, 'day'))

    return HashSet.make(DateTime.toEpochMillis(startingFrom))
  }

Expected Output

const createTestData = () =>
  function*() {
    const startingFrom = yield* Effect.map(DateTime.now, now =>
      DateTime.startOf(now, 'day'))

    return HashSet.make(DateTime.toEpochMillis(startingFrom))
  }

Actual Output

first time:

const createTestData = () =>
  function*() {
    const startingFrom = yield* Effect.map(DateTime.now, now =>
      DateTime.startOf(now, 'day'))

    return HashSet
      .make(DateTime.toEpochMillis(startingFrom))
  }

second time:

const createTestData = () =>
  function*() {
    const startingFrom = yield* Effect.map(DateTime.now, now =>
      DateTime.startOf(now, 'day'))

    return HashSet
      .make(DateTime
        .toEpochMillis(startingFrom))
  }

adrian-gierakowski avatar Nov 25 '24 14:11 adrian-gierakowski

note that following remains unchanged (with the same config)

const createTestData = () =>
  function*() {
    return HashSet.make(DateTime.toEpochMillis(startingFrom))
  }

and the following:

const createTestData = function*() {
  const startingFrom = yield* Effect.map(DateTime.now, now =>
    DateTime.startOf(now, 'day'))

  return HashSet.make(DateTime.toEpochMillis(startingFrom))
}

gets formatted to:

const createTestData = function*() {
  const startingFrom = yield* Effect.map(
    DateTime.now,
    now => DateTime.startOf(now, 'day'),
  )

  return HashSet.make(DateTime.toEpochMillis(startingFrom))
}

adrian-gierakowski avatar Nov 25 '24 14:11 adrian-gierakowski

Tested with:

  • dprint 0.47.5
  • dprin-plugin-typescript 0.93.2
  • following config
{
  "typescript": {
    "arrowFunction.useParentheses": "preferNone",
    "binaryExpression.linePerExpression": true,
    "enumDeclaration.memberSpacing": "newLine",
    "jsx.quoteStyle": "preferSingle",
    "lineWidth": 80,
    "memberExpression.linePerExpression": true,
    "nextControlFlowPosition": "sameLine",
    "quoteProps": "asNeeded",
    "quoteStyle": "preferSingle",
    "semiColons": "asi"
  }
}

adrian-gierakowski avatar Nov 25 '24 14:11 adrian-gierakowski

Yes I have the same problem even with the latest versions

SorooshGb avatar Jun 21 '25 13:06 SorooshGb

I believe I got it fixed here

adrian-gierakowski avatar Nov 20 '25 11:11 adrian-gierakowski

adding braces around the arrow-function argument prevents the problem, this is unchanged after formatting:

const createTestData = () =>
  function*() {
    const startingFrom = yield* Effect.map(DateTime.now, now => {
      DateTime.startOf(now, "day");
    });

    return HashSet.make(DateTime.toEpochMillis(startingFrom));
  };

also adding braces around the top level arrow function:

const createTestData = () => {
  return function*() {
    const startingFrom = yield* Effect.map(DateTime.now, now =>
      DateTime.startOf(now, "day"));

    return HashSet.make(DateTime.toEpochMillis(startingFrom));
  };
}

gets formatted t:

const createTestData = () => {
  return function*() {
    const startingFrom = yield* Effect.map(
      DateTime.now,
      now => DateTime.startOf(now, "day"),
    );

    return HashSet.make(DateTime.toEpochMillis(startingFrom));
  };
};

adrian-gierakowski avatar Nov 21 '25 09:11 adrian-gierakowski