Skip to content

Commit

Permalink
Weekly metals backport (#20542)
Browse files Browse the repository at this point in the history
  • Loading branch information
tgodzik authored Jun 13, 2024
2 parents 5cfcfa8 + d31aab8 commit 61a15b2
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import dotty.tools.dotc.ast.Trees.*
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.ast.tpd.DeepFolder
import dotty.tools.dotc.core.Contexts.*
import dotty.tools.dotc.core.Flags
import dotty.tools.dotc.core.Symbols.Symbol
import dotty.tools.dotc.core.Types.MethodType
import dotty.tools.dotc.core.Types.PolyType
Expand Down Expand Up @@ -116,9 +117,15 @@ final class ExtractMethodProvider(
typeParams.toList.sortBy(_.decodedName),
)
end localRefs
val optEnclosing =
path.dropWhile(src => !src.sourcePos.encloses(range)) match
case Nil => None
case _ :: (app @ Apply(fun, args)) :: _ if args.exists(ImplicitParameters.isSyntheticArg(_)) => Some(app)
case found :: _ => Some(found)

val edits =
for
enclosing <- path.find(src => src.sourcePos.encloses(range))
enclosing <- optEnclosing
extracted = extractFromBlock(enclosing)
head <- extracted.headOption
expr <- extracted.lastOption
Expand All @@ -131,11 +138,14 @@ final class ExtractMethodProvider(
val exprType = prettyPrint(expr.typeOpt.widen)
val name =
genName(indexedCtx.scopeSymbols.map(_.decodedName).toSet, "newMethod")
val (methodParams, typeParams) =
val (allMethodParams, typeParams) =
localRefs(extracted, stat.sourcePos, extractedPos)
val methodParamsText = methodParams
.map(sym => s"${sym.decodedName}: ${prettyPrint(sym.info)}")
.mkString(", ")
val (methodParams, implicitParams) = allMethodParams.partition(!_.isOneOf(Flags.GivenOrImplicit))
def toParamText(params: List[Symbol]) =
params.map(sym => s"${sym.decodedName}: ${prettyPrint(sym.info)}")
.mkString(", ")
val methodParamsText = toParamText(methodParams)
val implicitParamsText = if implicitParams.nonEmpty then s"(given ${toParamText(implicitParams)})" else ""
val typeParamsText = typeParams
.map(_.decodedName) match
case Nil => ""
Expand All @@ -155,7 +165,7 @@ final class ExtractMethodProvider(
if noIndent && extracted.length > 1 then (" {", s"$newIndent}")
else ("", "")
val defText =
s"def $name$typeParamsText($methodParamsText): $exprType =$obracket\n${toExtract}\n$cbracket\n$newIndent"
s"def $name$typeParamsText($methodParamsText)$implicitParamsText: $exprType =$obracket\n${toExtract}\n$cbracket\n$newIndent"
val replacedText = s"$name($exprParamsText)"
List(
new l.TextEdit(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ sealed trait IndexedContext:
Result.InScope
// when all the conflicting symbols came from an old version of the file
case Some(symbols) if symbols.nonEmpty && symbols.forall(_.isStale) => Result.Missing
case Some(_) => Result.Conflict
case None => Result.Missing
case Some(symbols) if symbols.exists(rename(_).isEmpty) => Result.Conflict
case _ => Result.Missing
end lookupSym

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package dotty.tools.pc

import java.nio.file.Paths

import scala.annotation.tailrec

import scala.meta.internal.metals.ReportContext
import dotty.tools.pc.utils.InteractiveEnrichments.*
import dotty.tools.pc.printer.ShortenedTypePrinter
Expand Down Expand Up @@ -194,10 +196,10 @@ object ImplicitConversion:
def unapply(tree: Tree)(using params: InlayHintsParams, ctx: Context) =
if (params.implicitConversions()) {
tree match
case Apply(fun: Ident, args) if isSynthetic(fun) =>
case Apply(fun: Ident, args) if isSynthetic(fun) && args.exists(!_.span.isZeroExtent) =>
implicitConversion(fun, args)
case Apply(Select(fun, name), args)
if name == nme.apply && isSynthetic(fun) =>
if name == nme.apply && isSynthetic(fun) && args.exists(!_.span.isZeroExtent) =>
implicitConversion(fun, args)
case _ => None
} else None
Expand All @@ -218,7 +220,7 @@ object ImplicitParameters:
if (params.implicitParameters()) {
tree match
case Apply(fun, args)
if args.exists(isSyntheticArg) && !tree.sourcePos.span.isZeroExtent =>
if args.exists(isSyntheticArg) && !tree.sourcePos.span.isZeroExtent && !args.exists(isQuotes(_)) =>
val (implicitArgs, providedArgs) = args.partition(isSyntheticArg)
val allImplicit = providedArgs.isEmpty || providedArgs.forall {
case Ident(name) => name == nme.MISSING
Expand All @@ -229,10 +231,12 @@ object ImplicitParameters:
case _ => None
} else None

private def isSyntheticArg(tree: Tree)(using Context) = tree match
@tailrec
def isSyntheticArg(tree: Tree)(using Context): Boolean = tree match
case tree: Ident =>
tree.span.isSynthetic && tree.symbol.isOneOf(Flags.GivenOrImplicit) &&
!isQuotes(tree)
tree.span.isSynthetic && tree.symbol.isOneOf(Flags.GivenOrImplicit)
case Apply(fun, _ ) if tree.span.isZeroExtent => isSyntheticArg(fun)
case TypeApply(fun, _ ) if tree.span.isZeroExtent => isSyntheticArg(fun)
case _ => false

// Decorations for Quotes are rarely useful
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,14 @@ object OverrideCompletions:
else ""
(indent, indent, lastIndent)
end calcIndent
val abstractMembers = defn.typeOpt.abstractTermMembers.map(_.symbol)
val abstractMembers =
defn.tpe.abstractTermMembers.map(_.symbol).groupBy(_.owner).map {
case (owner, members) => (owner, members.sortWith{ (sym1, sym2) =>
if(sym1.sourcePos.exists && sym2.sourcePos.exists)
sym1.sourcePos.start <= sym2.sourcePos.start
else !sym2.sourcePos.exists
})
}.toSeq.sortBy(_._1.name.decoded).flatMap(_._2)

val caseClassOwners = Set("Product", "Equals")
val overridables =
Expand Down Expand Up @@ -506,6 +513,8 @@ object OverrideCompletions:
defn match
case td: TypeDef if text.charAt(td.rhs.span.end) == ':' =>
Some(td.rhs.span.end)
case TypeDef(_, temp : Template) =>
temp.parentsOrDerived.lastOption.map(_.span.end).filter(text.charAt(_) == ':')
case _ => None

private def fallbackFromParent(parent: Tree, name: String)(using Context) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1952,3 +1952,34 @@ class CompletionSuite extends BaseCompletionSuite:
"""TestEnum test
|""".stripMargin,
)

@Test def `i6477-1` =
checkEdit(
"""|package a
|import a.b.SomeClass as SC
|
|package b {
| class SomeClass
|}
|package c {
| class SomeClass
|}
|
|val bar: SC = ???
|val foo: SomeClass@@
|""".stripMargin,
"""|package a
|import a.b.SomeClass as SC
|import a.c.SomeClass
|
|package b {
| class SomeClass
|}
|package c {
| class SomeClass
|}
|
|val bar: SC = ???
|val foo: SomeClass
|""".stripMargin,
)
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,10 @@ class AutoImplementAbstractMembersSuite extends BaseCodeActionSuite:
|object Main {
| class Baz extends Bar {
|
| override def foo: Int = ???
|
| override def bar: Int = ???
|
| override def foo: Int = ???
|
| }
|}
|""".stripMargin
Expand Down Expand Up @@ -1243,7 +1243,6 @@ class AutoImplementAbstractMembersSuite extends BaseCodeActionSuite:
|
|object A {
| trait Base:
| def foo(x: Int): Int
| def bar(x: String): String
|
| class <<Concrete>>(x: Int, y: String) extends Base:
Expand All @@ -1256,13 +1255,10 @@ class AutoImplementAbstractMembersSuite extends BaseCodeActionSuite:
|
|object A {
| trait Base:
| def foo(x: Int): Int
| def bar(x: String): String
|
| class Concrete(x: Int, y: String) extends Base:
|
| override def foo(x: Int): Int = ???
|
| override def bar(x: String): String = ???
|
|
Expand All @@ -1272,6 +1268,35 @@ class AutoImplementAbstractMembersSuite extends BaseCodeActionSuite:
|""".stripMargin,
)

@Test def `braceless-case-class` =
checkEdit(
"""|package a
|
|trait Base:
| def foo(x: Int): Int
| def bar(x: String): String
|
|case class <<Concrete>>() extends Base:
| def aaa = "aaa"
|end Concrete
|""".stripMargin,
"""|package a
|
|trait Base:
| def foo(x: Int): Int
| def bar(x: String): String
|
|case class Concrete() extends Base:
|
| override def foo(x: Int): Int = ???
|
| override def bar(x: String): String = ???
|
| def aaa = "aaa"
|end Concrete
|""".stripMargin
)

def checkEdit(
original: String,
expected: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,37 @@ class AutoImportsSuite extends BaseAutoImportsSuite:
|""".stripMargin,
)

@Test def `i6477` =
checkEdit(
"""|package a
|import a.b.SomeClass as SC
|
|package b {
| class SomeClass
|}
|package c {
| class SomeClass
|}
|
|val bar: SC = ???
|val foo: <<SomeClass>> = ???
|""".stripMargin,
"""|package a
|import a.b.SomeClass as SC
|import a.c.SomeClass
|
|package b {
| class SomeClass
|}
|package c {
| class SomeClass
|}
|
|val bar: SC = ???
|val foo: SomeClass = ???
|""".stripMargin
)

private def ammoniteWrapper(code: String): String =
// Vaguely looks like a scala file that Ammonite generates
// from a sc file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,95 @@ class ExtractMethodSuite extends BaseExtractMethodSuite:
| }
|}""".stripMargin
)

@Test def `i6476` =
checkEdit(
"""|object O {
| class C
| def foo(i: Int)(implicit o: C) = i
|
| @@val o = {
| implicit val c = new C
| <<foo(2)>>
| ???
| }
|}
|""".stripMargin,
"""|object O {
| class C
| def foo(i: Int)(implicit o: C) = i
|
| def newMethod()(given c: C): Int =
| foo(2)
|
| val o = {
| implicit val c = new C
| newMethod()
| ???
| }
|}
|""".stripMargin
)


@Test def `i6476-2` =
checkEdit(
"""|object O {
| class C
| def foo(i: Int)(implicit o: C) = i
|
| @@val o = {
| <<foo(2)(new C)>>
| ???
| }
|}
|""".stripMargin,
"""|object O {
| class C
| def foo(i: Int)(implicit o: C) = i
|
| def newMethod(): Int =
| foo(2)(new C)
|
| val o = {
| newMethod()
| ???
| }
|}
|""".stripMargin
)

@Test def `i6476-3` =
checkEdit(
"""|object O {
| class C
| class D
| def foo(i: Int)(using o: C)(x: Int)(using d: D) = i
|
| @@val o = {
| given C = new C
| given D = new D
| val w = 2
| <<foo(w)(w)>>
| ???
| }
|}
|""".stripMargin,
"""|object O {
| class C
| class D
| def foo(i: Int)(using o: C)(x: Int)(using d: D) = i
|
| def newMethod(w: Int)(given given_C: C, given_D: D): Int =
| foo(w)(w)
|
| val o = {
| given C = new C
| given D = new D
| val w = 2
| newMethod(w)
| ???
| }
|}
|""".stripMargin
)
Loading

0 comments on commit 61a15b2

Please sign in to comment.