From 3575180dfe1a897e97bb8052ebd2c01cc7509484 Mon Sep 17 00:00:00 2001 From: Brice Jaglin Date: Thu, 9 Nov 2023 16:54:44 +0100 Subject: [PATCH] rules capturing leading tokens can be suppressed with scalafix:ok --- .../scalafix/internal/patch/EscapeHatch.scala | 40 ++++++++++++++++--- .../disableSyntax/DisableSyntaxBase.scala | 3 ++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/scalafix-core/src/main/scala/scalafix/internal/patch/EscapeHatch.scala b/scalafix-core/src/main/scala/scalafix/internal/patch/EscapeHatch.scala index 85429664b4..b198f7a4bc 100644 --- a/scalafix-core/src/main/scala/scalafix/internal/patch/EscapeHatch.scala +++ b/scalafix-core/src/main/scala/scalafix/internal/patch/EscapeHatch.scala @@ -365,7 +365,8 @@ object EscapeHatch { associatedComments: LazyValue[AssociatedComments] ): AnchoredEscapes = { val enable = TreeMap.newBuilder[EscapeOffset, List[EscapeFilter]] - val disable = TreeMap.newBuilder[EscapeOffset, List[EscapeFilter]] + val disableList = + ListBuffer.newBuilder[(EscapeOffset, List[EscapeFilter])] val visitedFilterExpression = mutable.Set.empty[Position] val onOffTracker = new OnOffTracker @@ -422,9 +423,11 @@ object EscapeHatch { case comment @ Token.Comment(ScalafixOkRgx(rules)) => if (!visitedFilterExpression.contains(comment.pos)) { val rulesPos = rulesWithPosition(rules, comment) - val start = EscapeOffset(t.pos.start) + // include line start in case the rule captures leading tokens + val start = EscapeOffset(t.pos.start - t.pos.startColumn) val end = Some(EscapeOffset(t.pos.end)) - disable += (start -> makeFilters(rulesPos, start, end, comment)) + disableList += + (start -> makeFilters(rulesPos, start, end, comment)) visitedFilterExpression += comment.pos } @@ -444,7 +447,12 @@ object EscapeHatch { case ScalafixOffRgx(rules) => val rulesPos = rulesWithPosition(rules, comment) val start = EscapeOffset(comment.pos.start) - disable += (start -> makeFilters(rulesPos, start, None, comment)) + disableList += (start -> makeFilters( + rulesPos, + start, + None, + comment + )) onOffTracker.trackOff(rulesPos, comment) // matches on anchors @@ -470,7 +478,8 @@ object EscapeHatch { val start = EscapeOffset(comment.pos.start - comment.pos.startColumn) val end = Some(EscapeOffset(comment.pos.end)) - disable += (start -> makeFilters(rulesPos, start, end, comment)) + disableList += + (start -> makeFilters(rulesPos, start, end, comment)) } case _ => () @@ -479,10 +488,29 @@ object EscapeHatch { case _ => () } + val disable = TreeMap.newBuilder[EscapeOffset, List[EscapeFilter]] + val unused = ListBuffer.from(onOffTracker.allUnused) + + // for filters starting on the same offset, pick the one with the wider range + // and mark the others as unused + disableList.result().groupBy(_._1).valuesIterator.foreach { + filtersForOffset => + val sorted = filtersForOffset.sortBy { case (_, filters) => + filters.headOption.flatMap(_.endOffset.map(-_.offset)) + } + + sorted.result() match { + case head :: tail => + disable += head + unused ++= tail.flatMap(_._2).map(_.cause) + case _ => + } + } + new AnchoredEscapes( enable.result(), disable.result(), - onOffTracker.allUnused + unused.result() ) } } diff --git a/scalafix-tests/input/src/main/scala/test/disableSyntax/DisableSyntaxBase.scala b/scalafix-tests/input/src/main/scala/test/disableSyntax/DisableSyntaxBase.scala index 873dfc1793..1c821abd65 100644 --- a/scalafix-tests/input/src/main/scala/test/disableSyntax/DisableSyntaxBase.scala +++ b/scalafix-tests/input/src/main/scala/test/disableSyntax/DisableSyntaxBase.scala @@ -22,6 +22,7 @@ DisableSyntax.regex = [ message = "Numbers ({$1} in this instance) should always have a named parameter attached, or be assigned to a val." } "Await\\.result" + ".*bar\\s" ] */ package test.disableSyntax @@ -61,6 +62,8 @@ Numbers (5 in this instance) should always have a named parameter attached, or b // actually 7.5 million years Await.result(Future(fortyTwo), someDays) // assert: DisableSyntax.Await\.result + val bar = 1 // scalafix:ok + override def finalize(): Unit = println("exit") // assert: DisableSyntax.noFinalize val Right(notFound) = 1.asInstanceOf[Either[String, String]]