Repository: scalameta/scalameta (scala)

Issue:
Failure on previously formatted macro code
Pulled out from https://github.com/scalameta/munit/pull/518#issuecomment-1096576523

## Configuration (required) ##
```
version = "3.5.1"
runner.dialect = scala3
```


## Command-line parameters (required) ##

When I run scalafmt via CLI like this: `-c .scalafmt.conf test.scala`


## Steps

Given code like this:
```scala
package munit.internal

import munit.Clue
import scala.quoted._
import scala.language.experimental.macros

object MacroCompat {

  trait ClueMacro {
    inline implicit def generate[T](value: T): Clue[T] = ${ clueImpl('value) }
    implicit def generate[T](value: T): Clue[T] = macro MacroCompatScala2.clueImpl
  }

}
```

## Problem

Scalafmt formats code like this:
```scala
package munit.internal

import munit.Clue
import scala.quoted._
import scala.language.experimental.macros

object MacroCompat {

  trait ClueMacro {
    inline implicit def generate[T](value: T): Clue[T] = ${ clueImpl('value) }
    implicit def generate[T](value: T): Clue[T] =
      macro MacroCompatScala2.clueImpl
  }

}
```
Note the `macro MacroCompatScala2.clueImpl` on a new line.

Once formatted, rerunning scalafmt yields the following error:
```
org.scalafmt.dynamic.exceptions.PositionExceptionImpl:
  /home/andrew/src/scalafmttest/test.scala:12: error: [dialect scala3] illegal start of statement
      macro MacroCompatScala2.clueImpl
      ^: /home/andrew/src/scalafmttest/test.scala
```

## Expectation

The output format should be able to parsed/formatted again

Pull request:
From what I understand macros must exist as the only statement in a definition, which is way we can't have a block there and indentation should not be tried.

Fixes https://github.com/scalameta/scalameta/issues/2727

Patch:
diff --git a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
index 91e5d018ab..5b26d29f32 100644
--- a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
+++ b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
@@ -329,9 +329,14 @@ class ScannerTokens(tokens: Tokens, input: Input)(implicit dialect: Dialect) {
     trait CanStartIndent {
       def unapply(token: Token): Boolean = token match {
         case _: KwYield | _: KwTry | _: KwCatch | _: KwFinally | _: KwMatch | _: KwDo | _: KwFor |
-            _: KwThen | _: KwElse | _: Equals | _: KwWhile | _: KwIf | _: RightArrow | _: KwReturn |
+            _: KwThen | _: KwElse | _: KwWhile | _: KwIf | _: RightArrow | _: KwReturn |
             _: LeftArrow | _: ContextArrow =>
           true
+        case _: Equals =>
+          token.next match {
+            case _: KwMacro => false
+            case _ => true
+          }
         case _: KwWith =>
           token.next match {
             case _: KwImport | _: KwExport | DefIntro() => true


Test patch:
diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MinorDottySuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MinorDottySuite.scala
index e94220561d..0441b2734d 100644
--- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MinorDottySuite.scala
+++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MinorDottySuite.scala
@@ -1300,4 +1300,23 @@ class MinorDottySuite extends BaseDottySuite {
     )
   }
 
+  test("#2727-newline-macro") {
+
+    runTestAssert[Stat](
+      """|implicit def generate[T](value: T): Clue[T] =
+         |  macro MacroCompatScala2.clueImpl""".stripMargin,
+      assertLayout =
+        Some("implicit def generate[T](value: T): Clue[T] = macro MacroCompatScala2.clueImpl")
+    )(
+      Defn.Macro(
+        List(Mod.Implicit()),
+        Term.Name("generate"),
+        List(Type.Param(Nil, Type.Name("T"), Nil, Type.Bounds(None, None), Nil, Nil)),
+        List(List(Term.Param(Nil, Term.Name("value"), Some(Type.Name("T")), None))),
+        Some(Type.Apply(Type.Name("Clue"), List(Type.Name("T")))),
+        Term.Select(Term.Name("MacroCompatScala2"), Term.Name("clueImpl"))
+      )
+    )
+  }
+
 }