From ebd1ee08300c1b6a3040100192f82874f29eac1f Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Mon, 8 Jul 2024 19:25:26 +0200 Subject: [PATCH] Fix handling of right associative extension methods across scaladoc and printers (#20467) Fixes #19925 The same issue with handling right associative extension methods was also present in RefinedPrinter and ShortenedTypePrinter, so I fixed those as well [Cherry-picked d3df8cacc78be93ab5b8b9eaf7fe073fad27010e][modified] --- .../dotty/tools/dotc/printing/RefinedPrinter.scala | 4 +++- .../dotty/tools/pc/printer/ShortenedTypePrinter.scala | 4 +++- .../dotty/tools/pc/tests/hover/HoverTermSuite.scala | 11 +++++++++++ .../src/tests/rightAssocExtension.scala | 7 +++++++ .../dotty/tools/scaladoc/tasty/ClassLikeSupport.scala | 4 +++- .../signatures/TranslatableSignaturesTestCases.scala | 2 ++ 6 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 scaladoc-testcases/src/tests/rightAssocExtension.scala diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index e1f831072c92..e81052537018 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -936,7 +936,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { // - trailingUsing = List(`(using D)`) // - rest = List(`(g: G)`, `(using H)`) // we need to swap (rightTyParams ++ rightParam) with (leftParam ++ trailingUsing) - val (leftTyParams, rest1) = tree.paramss.span(isTypeParamClause) + val (leftTyParams, rest1) = tree.paramss match + case fst :: tail if isTypeParamClause(fst) => (List(fst), tail) + case other => (List(), other) val (leadingUsing, rest2) = rest1.span(isUsingClause) val (rightTyParams, rest3) = rest2.span(isTypeParamClause) val (rightParam, rest4) = rest3.splitAt(1) diff --git a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala index 559e199f3449..19d603fcbb3b 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala @@ -419,7 +419,9 @@ class ShortenedTypePrinter( if gsym.is(Flags.ExtensionMethod) then val filteredParams = if gsym.name.isRightAssocOperatorName then - val (leadingTyParamss, rest1) = paramss.span(isTypeParamClause) + val (leadingTyParamss, rest1) = paramss match + case fst :: tail if isTypeParamClause(fst) => (List(fst), tail) + case other => (List(), other) val (leadingUsing, rest2) = rest1.span(isUsingClause) val (rightTyParamss, rest3) = rest2.span(isTypeParamClause) val (rightParamss, rest4) = rest3.splitAt(1) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index 12013366181b..65b2fb20734f 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -683,3 +683,14 @@ class HoverTermSuite extends BaseHoverSuite: |""".stripMargin, """yy: A{type T = Int}""".stripMargin.hover ) + + @Test def `right-assoc-extension`: Unit = + check( + """ + |case class Wrap[+T](x: T) + | + |extension [T](a: T) + | def <<*@@:>>[U <: Tuple](b: Wrap[U]): Wrap[T *: U] = Wrap(a *: b.x) + |""".stripMargin, + "extension [T](a: T) def *:[U <: Tuple](b: Wrap[U]): Wrap[T *: U]".hover + ) diff --git a/scaladoc-testcases/src/tests/rightAssocExtension.scala b/scaladoc-testcases/src/tests/rightAssocExtension.scala new file mode 100644 index 000000000000..a065ee765caf --- /dev/null +++ b/scaladoc-testcases/src/tests/rightAssocExtension.scala @@ -0,0 +1,7 @@ +package tests.rightAssocExtension + +case class Wrap[+T](x: T) + +extension [T](a: T) + def *:[U <: Tuple](b: Wrap[U]): Wrap[T *: U] + = Wrap(a *: b.x) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index 1598accf4f40..880979852ef6 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -359,7 +359,9 @@ trait ClassLikeSupport: if methodSymbol.isExtensionMethod && methodSymbol.isRightAssoc then // Taken from RefinedPrinter.scala // If you change the names of the clauses below, also change them in right-associative-extension-methods.md - val (leftTyParams, rest1) = memberInfo.paramLists.span(_.isType) + val (leftTyParams, rest1) = memberInfo.paramLists match + case fst :: tail if fst.isType => (List(fst), tail) + case other => (List(), other) val (leadingUsing, rest2) = rest1.span(_.isUsing) val (rightTyParams, rest3) = rest2.span(_.isType) val (rightParam, rest4) = rest3.splitAt(1) diff --git a/scaladoc/test/dotty/tools/scaladoc/signatures/TranslatableSignaturesTestCases.scala b/scaladoc/test/dotty/tools/scaladoc/signatures/TranslatableSignaturesTestCases.scala index 2b654d186aef..b658bfcdedc0 100644 --- a/scaladoc/test/dotty/tools/scaladoc/signatures/TranslatableSignaturesTestCases.scala +++ b/scaladoc/test/dotty/tools/scaladoc/signatures/TranslatableSignaturesTestCases.scala @@ -120,3 +120,5 @@ class MatchTypeTuple extends SignatureTest("matchTypeTuple", SignatureTest.all) class InfixTypes extends SignatureTest("infixTypes", SignatureTest.all) class ExtendsCall extends SignatureTest("extendsCall", SignatureTest.all) + +class RightAssocExtension extends SignatureTest("rightAssocExtension", SignatureTest.all)