<NME> SortModifiers.scala
<BEF> package org.scalafmt.rewrite

import org.scalafmt.config.RewriteSettings
import org.scalafmt.util.TreeOps

import scala.meta._

object SortModifiers extends RewriteFactory {

  override def hasChanged(v1: RewriteSettings, v2: RewriteSettings): Boolean =
    v2.sortModifiers ne v1.sortModifiers

  override def create(implicit ctx: RewriteCtx): RewriteSession =
    new SortModifiers
}

class SortModifiers(implicit ctx: RewriteCtx) extends RewriteSession {

  private implicit val order = ctx.style.rewrite.sortModifiers.order

  override def rewrite(tree: Tree): Unit =
    tree match {

      /*
       * in the case of Class, Object, and of class constructor parameters
       * some Mods are immovable, e.g. 'case' in "case class X".
       *
       * The case of parameters is a bit more curious because there the
       * "val" or "var" in, say:
       * {{{
       *   class Test(private final val x: Int)
       * }}}
       * are considered Mods, instead of being similar to `Defn.Val`, or `Defn.Var`.
       */
      case c: Defn.Class => sortMods(c.mods.filterNot(_.is[Mod.Case]))
      case o: Defn.Object => sortMods(o.mods.filterNot(_.is[Mod.Case]))
      case s: Stat.WithMods => sortMods(s.mods)
      case p: Term.Param =>
        val start = p.pos.start
        sortMods(p.mods.filterNot { m =>
          m.is[Mod.ValParam] || m.is[Mod.VarParam] ||
          TreeOps.isHiddenImplicit(start)(m)
        })
      case _ =>
    }

  private def sortMods(oldMods: Seq[Mod]): Unit = {

      ctx.addPatchSet(sortedMods.zip(sanitized).flatMap {
        case (next, old) =>
          val removeOld = old.tokens.map(TokenPatch.Remove)
          val addNext = TokenPatch.AddRight(old.tokens.head, next.syntax)
          removeOld :+ addNext
      }: _*)
    }
  }
        if (next eq old) Seq.empty
        else {
          val removeOld = old.tokens.tail.map(TokenPatch.Remove)
          val addNext = TokenPatch.Replace(old.tokens.head, next.toString())
          addNext +: removeOld
        }
      }: _*)
    }
  }

}

<MSG> SortModifiers: a few optimizations

In case the modifiers are already sorted, or a modifier would not change
its relative position, let's skip the unnecessary patch.

Also, use the Replace patch on the first token (likely the only), and
Remove the rest.

<DFF> @@ -48,9 +48,12 @@ object SortModifiers extends Rewrite {
 
       ctx.addPatchSet(sortedMods.zip(sanitized).flatMap {
         case (next, old) =>
-          val removeOld = old.tokens.map(TokenPatch.Remove)
-          val addNext = TokenPatch.AddRight(old.tokens.head, next.syntax)
-          removeOld :+ addNext
+          if (next eq old) Seq.empty
+          else {
+            val removeOld = old.tokens.tail.map(TokenPatch.Remove)
+            val addNext = TokenPatch.Replace(old.tokens.head, next.syntax)
+            removeOld :+ addNext
+          }
       }: _*)
     }
   }

{'addition_count': 6, 'commit_subject': 'SortModifiers: a few optimizations', 'deletion_count': 3, 'file_extension': '.scala', 'lang': 'scala', 'license': 'apache-2.0', 'repo_name': 'scalameta/scalafmt'}