Skip to content

Commit 87dc30e

Browse files
authored
Merge pull request #217 from scala/backport-lts-3.3-22426
Backport "Backport from Metals" to 3.3 LTS
2 parents 0e872c4 + 174b497 commit 87dc30e

11 files changed

+451
-33
lines changed

Diff for: presentation-compiler/src/main/dotty/tools/pc/CompletionItemResolver.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ object CompletionItemResolver extends ItemResolver:
7575
else gsymDoc
7676
else
7777
val companionDoc = docs(companion)
78-
if companionDoc.isEmpty() then gsymDoc
78+
if companionDoc.isEmpty() || companionDoc == gsymDoc then gsymDoc
7979
else if gsymDoc.isEmpty() then companionDoc
8080
else
8181
List(

Diff for: presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala

+69-12
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ class PcInlayHintsProvider(
8080
LabelPart(")") :: Nil,
8181
InlayHintKind.Parameter,
8282
)
83-
case ImplicitParameters(symbols, pos, allImplicit) =>
84-
val labelParts = symbols.map(s => List(labelPart(s, s.decodedName)))
85-
val label =
86-
if allImplicit then labelParts.separated("(using ", ", ", ")")
87-
else labelParts.separated(", ")
83+
case ImplicitParameters(trees, pos) =>
8884
inlayHints.add(
8985
adjustPos(pos).toLsp,
90-
label,
91-
InlayHintKind.Parameter,
86+
ImplicitParameters.partsFromImplicitArgs(trees).map((label, maybeSymbol) =>
87+
maybeSymbol match
88+
case Some(symbol) => labelPart(symbol, label)
89+
case None => LabelPart(label)
90+
),
91+
InlayHintKind.Parameter
9292
)
9393
case ValueOf(label, pos) =>
9494
inlayHints.add(
@@ -221,12 +221,8 @@ object ImplicitParameters:
221221
case Apply(fun, args)
222222
if args.exists(isSyntheticArg) && !tree.sourcePos.span.isZeroExtent && !args.exists(isQuotes(_)) =>
223223
val (implicitArgs, providedArgs) = args.partition(isSyntheticArg)
224-
val allImplicit = providedArgs.isEmpty || providedArgs.forall {
225-
case Ident(name) => name == nme.MISSING
226-
case _ => false
227-
}
228224
val pos = implicitArgs.head.sourcePos
229-
Some(implicitArgs.map(_.symbol), pos, allImplicit)
225+
Some(implicitArgs, pos)
230226
case _ => None
231227
} else None
232228

@@ -242,6 +238,67 @@ object ImplicitParameters:
242238
private def isQuotes(tree: Tree)(using Context) =
243239
tree.tpe.typeSymbol == defn.QuotesClass
244240

241+
def partsFromImplicitArgs(trees: List[Tree])(using Context): List[(String, Option[Symbol])] = {
242+
@tailrec
243+
def recurseImplicitArgs(
244+
currentArgs: List[Tree],
245+
remainingArgsLists: List[List[Tree]],
246+
parts: List[(String, Option[Symbol])]
247+
): List[(String, Option[Symbol])] =
248+
(currentArgs, remainingArgsLists) match {
249+
case (Nil, Nil) => parts
250+
case (Nil, headArgsList :: tailArgsList) =>
251+
if (headArgsList.isEmpty) {
252+
recurseImplicitArgs(
253+
headArgsList,
254+
tailArgsList,
255+
(")", None) :: parts
256+
)
257+
} else {
258+
recurseImplicitArgs(
259+
headArgsList,
260+
tailArgsList,
261+
(", ", None) :: (")", None) :: parts
262+
)
263+
}
264+
case (arg :: remainingArgs, remainingArgsLists) =>
265+
arg match {
266+
case Apply(fun, args) =>
267+
val applyLabel = (fun.symbol.decodedName, Some(fun.symbol))
268+
recurseImplicitArgs(
269+
args,
270+
remainingArgs :: remainingArgsLists,
271+
("(", None) :: applyLabel :: parts
272+
)
273+
case t if t.isTerm =>
274+
val termLabel = (t.symbol.decodedName, Some(t.symbol))
275+
if (remainingArgs.isEmpty)
276+
recurseImplicitArgs(
277+
remainingArgs,
278+
remainingArgsLists,
279+
termLabel :: parts
280+
)
281+
else
282+
recurseImplicitArgs(
283+
remainingArgs,
284+
remainingArgsLists,
285+
(", ", None) :: termLabel :: parts
286+
)
287+
case _ =>
288+
recurseImplicitArgs(
289+
remainingArgs,
290+
remainingArgsLists,
291+
parts
292+
)
293+
}
294+
}
295+
((")", None) :: recurseImplicitArgs(
296+
trees,
297+
Nil,
298+
List(("(using ", None))
299+
)).reverse
300+
}
301+
245302
end ImplicitParameters
246303

247304
object ValueOf:

Diff for: presentation-compiler/src/main/dotty/tools/pc/PcInlineValueProviderImpl.scala

+12-11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import dotty.tools.dotc.interactive.Interactive
1818
import dotty.tools.dotc.interactive.InteractiveDriver
1919
import dotty.tools.dotc.util.SourcePosition
2020
import dotty.tools.pc.utils.InteractiveEnrichments.*
21+
import dotty.tools.pc.IndexedContext.Result
2122

2223
import org.eclipse.lsp4j as l
2324

@@ -49,7 +50,9 @@ final class PcInlineValueProviderImpl(
4950
DefinitionTree(defn, pos)
5051
}
5152
.toRight(Errors.didNotFindDefinition)
52-
symbols = symbolsUsedInDefn(definition.tree.rhs)
53+
path = Interactive.pathTo(unit.tpdTree, definition.tree.rhs.span)(using newctx)
54+
indexedContext = IndexedContext(Interactive.contextOfPath(path)(using newctx))
55+
symbols = symbolsUsedInDefn(definition.tree.rhs).filter(indexedContext.lookupSym(_) == Result.InScope)
5356
references <- getReferencesToInline(definition, allOccurences, symbols)
5457
yield
5558
val (deleteDefinition, refsEdits) = references
@@ -111,27 +114,25 @@ final class PcInlineValueProviderImpl(
111114
val adjustedEnd = extend(pos.end - 1, ')', 1) + 1
112115
text.slice(adjustedStart, adjustedEnd).mkString
113116

114-
private def symbolsUsedInDefn(
115-
rhs: Tree
116-
): List[Symbol] =
117+
private def symbolsUsedInDefn(rhs: Tree): Set[Symbol] =
117118
def collectNames(
118-
symbols: List[Symbol],
119+
symbols: Set[Symbol],
119120
tree: Tree
120-
): List[Symbol] =
121+
): Set[Symbol] =
121122
tree match
122123
case id: (Ident | Select)
123124
if !id.symbol.is(Synthetic) && !id.symbol.is(Implicit) =>
124-
tree.symbol :: symbols
125+
symbols + tree.symbol
125126
case _ => symbols
126127

127-
val traverser = new DeepFolder[List[Symbol]](collectNames)
128-
traverser(List(), rhs)
128+
val traverser = new DeepFolder[Set[Symbol]](collectNames)
129+
traverser(Set(), rhs)
129130
end symbolsUsedInDefn
130131

131132
private def getReferencesToInline(
132133
definition: DefinitionTree,
133134
allOccurences: List[Occurence],
134-
symbols: List[Symbol]
135+
symbols: Set[Symbol]
135136
): Either[String, (Boolean, List[Reference])] =
136137
val defIsLocal = definition.tree.symbol.ownersIterator
137138
.drop(1)
@@ -156,7 +157,7 @@ final class PcInlineValueProviderImpl(
156157

157158
private def makeRefsEdits(
158159
refs: List[Occurence],
159-
symbols: List[Symbol]
160+
symbols: Set[Symbol]
160161
): Either[String, List[Reference]] =
161162
val newctx = driver.currentCtx.fresh.setCompilationUnit(unit)
162163
def buildRef(occurrence: Occurence): Either[String, Reference] =

Diff for: presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala

+47-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ case class ScalaPresentationCompiler(
5555
completionItemPriority: CompletionItemPriority = (_: String) => 0,
5656
) extends PresentationCompiler:
5757

58+
override def supportedCodeActions(): ju.List[String] = List(
59+
CodeActionId.ConvertToNamedArguments,
60+
CodeActionId.ImplementAbstractMembers,
61+
CodeActionId.ExtractMethod,
62+
CodeActionId.InlineValue,
63+
CodeActionId.InsertInferredType
64+
).asJava
65+
5866
def this() = this("", None, Nil, Nil)
5967

6068
val scalaVersion = BuildInfo.scalaVersion
@@ -67,6 +75,38 @@ case class ScalaPresentationCompiler(
6775
.map(StdReportContext(_, _ => buildTargetName, reportsLevel))
6876
.getOrElse(EmptyReportContext)
6977

78+
override def codeAction[T](
79+
params: OffsetParams,
80+
codeActionId: String,
81+
codeActionPayload: Optional[T]
82+
): CompletableFuture[ju.List[TextEdit]] =
83+
(codeActionId, codeActionPayload.asScala) match
84+
case (
85+
CodeActionId.ConvertToNamedArguments,
86+
Some(argIndices: ju.List[_])
87+
) =>
88+
val payload =
89+
argIndices.asScala.collect { case i: Integer => i.toInt }.toSet
90+
convertToNamedArguments(params, payload)
91+
case (CodeActionId.ImplementAbstractMembers, _) =>
92+
implementAbstractMembers(params)
93+
case (CodeActionId.InsertInferredType, _) =>
94+
insertInferredType(params)
95+
case (CodeActionId.InlineValue, _) =>
96+
inlineValue(params)
97+
case (CodeActionId.ExtractMethod, Some(extractionPos: OffsetParams)) =>
98+
params match {
99+
case range: RangeParams =>
100+
extractMethod(range, extractionPos)
101+
case _ => failedFuture(new IllegalArgumentException(s"Expected range parameters"))
102+
}
103+
case (id, _) => failedFuture(new IllegalArgumentException(s"Unsupported action id $id"))
104+
105+
private def failedFuture[T](e: Throwable): CompletableFuture[T] =
106+
val f = new CompletableFuture[T]()
107+
f.completeExceptionally(e)
108+
f
109+
70110
override def withCompletionItemPriority(
71111
priority: CompletionItemPriority
72112
): PresentationCompiler =
@@ -348,14 +388,20 @@ case class ScalaPresentationCompiler(
348388
override def convertToNamedArguments(
349389
params: OffsetParams,
350390
argIndices: ju.List[Integer]
391+
): CompletableFuture[ju.List[l.TextEdit]] =
392+
convertToNamedArguments(params, argIndices.asScala.toSet.map(_.toInt))
393+
394+
def convertToNamedArguments(
395+
params: OffsetParams,
396+
argIndices: Set[Int]
351397
): CompletableFuture[ju.List[l.TextEdit]] =
352398
val empty: Either[String, List[l.TextEdit]] = Right(List())
353399
(compilerAccess
354400
.withNonInterruptableCompiler(Some(params))(empty, params.token()) { pc =>
355401
new ConvertToNamedArgumentsProvider(
356402
pc.compiler(),
357403
params,
358-
argIndices.asScala.map(_.toInt).toSet
404+
argIndices
359405
).convertToNamedArguments
360406
})
361407
.thenApplyAsync {

Diff for: presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,9 @@ class CompletionProvider(
218218
// related issue https://github.com/lampepfl/scala3/issues/11941
219219
lazy val kind: CompletionItemKind = underlyingCompletion.completionItemKind
220220
val description = underlyingCompletion.description(printer)
221-
val label = underlyingCompletion.labelWithDescription(printer)
221+
val label =
222+
if config.isDetailIncludedInLabel then completion.labelWithDescription(printer)
223+
else completion.label
222224
val ident = underlyingCompletion.insertText.getOrElse(underlyingCompletion.label)
223225

224226
lazy val isInStringInterpolation =

Diff for: presentation-compiler/src/main/dotty/tools/pc/utils/InteractiveEnrichments.scala

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package dotty.tools.pc.utils
22

3+
import java.util.Optional
4+
35
import scala.annotation.tailrec
46
import scala.meta.internal.jdk.CollectionConverters.*
57
import scala.meta.internal.mtags.CommonMtagsEnrichments
@@ -272,11 +274,14 @@ object InteractiveEnrichments extends CommonMtagsEnrichments:
272274
symbol.maybeOwner.companion,
273275
).filter(_ != NoSymbol) ++ symbol.allOverriddenSymbols
274276
else symbol.allOverriddenSymbols
275-
val documentation = search.documentation(
276-
sym,
277-
() => parentSymbols.iterator.map(toSemanticdbSymbol).toList.asJava,
278-
contentType,
279-
)
277+
val documentation =
278+
if symbol.isLocal then Optional.empty
279+
else
280+
search.documentation(
281+
sym,
282+
() => parentSymbols.iterator.map(toSemanticdbSymbol).toList.asJava,
283+
contentType,
284+
)
280285
documentation.nn.toScala
281286
end symbolDocumentation
282287
end extension

0 commit comments

Comments
 (0)