diff --git a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala index d9ed4b115d..81fee45e10 100644 --- a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala +++ b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala @@ -849,6 +849,23 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser => }).getOrElse(t) } + def typeBlock(): Type = + // TypeBlock, https://dotty.epfl.ch/docs/internals/syntax.html#expressions-3 + if (dialect.allowQuotedTypeVariables && token.is[KwType]) autoPos { + val typeDefs = listBy[Stat.TypeDef] { buf => + @tailrec def iter(): Unit = { + buf += typeDefOrDcl(Nil) + if (StatSep(token)) { + next() + if (token.is[KwType]) iter() + } + } + iter() + } + Type.Block(typeDefs, typ()) + } + else typ() + private def typeFuncOnArrow( paramPos: Int, params: List[Type], @@ -2297,7 +2314,7 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser => next() token match { case _: LeftBrace => Term.QuotedMacroExpr(autoPos(inBracesOnOpen(blockWithinDelims()))) - case _: LeftBracket => Term.QuotedMacroType(inBracketsOnOpen(typ())) + case _: LeftBracket => Term.QuotedMacroType(inBracketsOnOpen(typeBlock())) case t => syntaxError("Quotation only works for expressions and types", at = t) } }) @@ -2982,6 +2999,7 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser => * initiated from non-pattern context. */ def typ() = outPattern.typ() + private def typeBlock() = outPattern.typeBlock() def typeIndentedOpt() = outPattern.typeIndentedOpt() def quasiquoteType() = outPattern.quasiquoteType() def entrypointType() = outPattern.entrypointType() diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MacroSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MacroSuite.scala index 58ca540d6e..a9eddb30db 100644 --- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MacroSuite.scala +++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MacroSuite.scala @@ -449,19 +449,23 @@ class MacroSuite extends BaseDottySuite { test("#3610 2") { val code = "'[ type t = Int; List[t] ]" - val error = - """|:1: error: identifier expected but type found - |'[ type t = Int; List[t] ] - | ^""".stripMargin - runTestError[Stat](code, error) + val tree = Term.QuotedMacroType( + Type.Block( + List(Defn.Type(Nil, pname("t"), Nil, pname("Int"), noBounds)), + Type.Apply(pname("List"), List(pname("t"))) + ) + ) + runTestAssert[Stat](code)(tree) } test("#3610 3") { val code = "'[ type tail <: Tuple; *:[Int, tail] ]" - val error = - """|:1: error: identifier expected but type found - |'[ type tail <: Tuple; *:[Int, tail] ] - | ^""".stripMargin - runTestError[Stat](code, error) + val tree = Term.QuotedMacroType( + Type.Block( + List(Decl.Type(Nil, pname("tail"), Nil, bounds(hi = "Tuple"))), + Type.Apply(pname("*:"), List(pname("Int"), pname("tail"))) + ) + ) + runTestAssert[Stat](code)(tree) } }