Skip to content

Commit

Permalink
chore: Backport changes from Metals
Browse files Browse the repository at this point in the history
  • Loading branch information
tgodzik committed Jan 10, 2024
1 parent 91db06a commit 7240327
Show file tree
Hide file tree
Showing 16 changed files with 673 additions and 67 deletions.
6 changes: 2 additions & 4 deletions compiler/src/dotty/tools/dotc/interactive/Interactive.scala
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,10 @@ object Interactive {
case nested :: encl :: rest =>
val outer = contextOfPath(encl :: rest)
try encl match {
case tree @ PackageDef(pkg, stats) =>
assert(tree.symbol.exists)
case tree @ PackageDef(pkg, stats) if tree.symbol.exists =>
if (nested `eq` pkg) outer
else contextOfStat(stats, nested, pkg.symbol.moduleClass, outer.packageContext(tree, tree.symbol))
case tree: DefDef =>
assert(tree.symbol.exists)
case tree: DefDef if tree.symbol.exists =>
val localCtx = outer.localContext(tree, tree.symbol).setNewScope
for params <- tree.paramss; param <- params do localCtx.enter(param.symbol)
// Note: this overapproximates visibility a bit, since value parameters are only visible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class CompilerSearchVisitor(
.filter(denot => denot.exists)
.map(_.symbol)
.filter(isAccessible)
.filter(!_.is(Flags.Given))
}
loop(next, tl)
case Nil => owners
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import dotty.tools.dotc.util.Spans
import dotty.tools.pc.utils.MtagsEnrichments.*

import org.eclipse.lsp4j as l
import scala.annotation.tailrec

enum CompletionKind:
case Empty, Scope, Members
Expand Down Expand Up @@ -55,8 +56,10 @@ object CompletionPos:
val prevIsDot =
if start - 1 >= 0 then text.charAt(start - 1) == '.' else false
val kind =
if query.nn.isEmpty() && !prevIsDot then CompletionKind.Empty
else if prevIsDot then CompletionKind.Members
if prevIsDot then CompletionKind.Members
else if isImportOrExportSelect(cursorPos, treePath) then
CompletionKind.Members
else if query.nn.isEmpty then CompletionKind.Empty
else CompletionKind.Scope

CompletionPos(kind, start, end, query.nn, cursorPos, uri)
Expand Down Expand Up @@ -84,6 +87,21 @@ object CompletionPos:
(i, tabIndented)
end inferIndent

private def isImportOrExportSelect(
pos: SourcePosition,
path: List[Tree],
)(using Context): Boolean =
@tailrec
def loop(enclosing: List[Tree]): Boolean =
enclosing match
case head :: tl if !head.sourcePos.contains(pos) => loop(tl)
case (tree: (Import | Export)) :: _ =>
tree.selectors.exists(_.imported.sourcePos.contains(pos))
case _ => false

loop(path)


/**
* Returns the start offset of the identifier starting as the given offset position.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ class Completions(
case _ :: (withcursor @ Select(fun, name)) :: (appl: GenericApply) :: _
if appl.fun == withcursor && name.decoded == Cursor.value =>
false
case (_: Import) :: _ => false
case _ :: (_: Import) :: _ => false
case (_: (Import | Export)) :: _ => false
case _ :: (_: (Import | Export)) :: _ => false
case (_: Ident) :: (_: SeqLiteral) :: _ => false
case _ => true

Expand Down Expand Up @@ -140,7 +140,8 @@ class Completions(

val application = CompletionApplication.fromPath(path)
val ordering = completionOrdering(application)
val values = application.postProcess(all.sorted(ordering))
val sorted = all.sorted(ordering)
val values = application.postProcess(sorted)
(values, result)
end completions

Expand Down Expand Up @@ -441,6 +442,10 @@ class Completions(
true,
)

case (tree: (Import | Export)) :: _
if tree.selectors.exists(_.renamed.sourcePos.contains(pos)) =>
(List.empty, true)

// From Scala 3.1.3-RC3 (as far as I know), path contains
// `Literal(Constant(null))` on head for an incomplete program, in this case, just ignore the head.
case Literal(Constant(null)) :: tl =>
Expand Down Expand Up @@ -791,7 +796,8 @@ class Completions(
val fuzzyCache = mutable.Map.empty[CompletionValue, Int]

def compareLocalSymbols(s1: Symbol, s2: Symbol): Int =
if s1.isLocal && s2.isLocal then
if s1.isLocal && s2.isLocal && s1.sourcePos.exists && s2.sourcePos.exists
then
val firstIsAfter = s1.srcPos.isAfter(s2.srcPos)
if firstIsAfter then -1 else 1
else 0
Expand Down Expand Up @@ -833,6 +839,16 @@ class Completions(
priority(o1) - priority(o2)
end compareInApplyParams

def prioritizeKeywords(o1: CompletionValue, o2: CompletionValue): Int =
def priority(v: CompletionValue): Int =
v match
case _: CompletionValue.CaseKeyword => 0
case _: CompletionValue.NamedArg => 1
case _: CompletionValue.Keyword => 2
case _ => 3

priority(o1) - priority(o2)
end prioritizeKeywords
/**
* Some completion values should be shown first such as CaseKeyword and
* NamedArg
Expand Down Expand Up @@ -909,7 +925,10 @@ class Completions(
case _ =>
val byApplyParams = compareInApplyParams(o1, o2)
if byApplyParams != 0 then byApplyParams
else compareByRelevance(o1, o2)
else
val keywords = prioritizeKeywords(o1, o2)
if keywords != 0 then keywords
else compareByRelevance(o1, o2)
end compare

end Completions
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,13 @@ object InterpolatorCompletions:
case _: Select => true
case _ => false
} =>
val allLiterals = parent match
case SeqLiteral(elems, _) =>
elems
case _ => Nil
expr.elems.zip(allLiterals.tail).collectFirst {
case (i: (Ident | Select), literal) if literal == lit =>
i
}
parent match
case SeqLiteral(elems, _) if elems.size > 0 =>
expr.elems.zip(elems.tail).collectFirst {
case (i: (Ident | Select), literal) if literal == lit =>
i
}
case _ => None
end interpolatorMemberArg

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import dotty.tools.dotc.core.Names.Name
import dotty.tools.dotc.core.StdNames.*
import dotty.tools.dotc.core.SymDenotations.NoDenotation
import dotty.tools.dotc.core.Symbols
import dotty.tools.dotc.core.Symbols.defn
import dotty.tools.dotc.core.Symbols.NoSymbol
import dotty.tools.dotc.core.Symbols.Symbol
import dotty.tools.dotc.core.Types.AndType
Expand Down Expand Up @@ -309,15 +310,17 @@ object NamedArgCompletions:

val completionSymbols = indexedContext.scopeSymbols
def matchingTypesInScope(paramType: Type): List[String] =
completionSymbols
.collect {
case sym
if sym.info <:< paramType && sym.isTerm && !sym.info.isErroneous && !sym.info.isNullType && !sym.info.isNothingType && !sym
.is(Flags.Method) && !sym.is(Flags.Synthetic) =>
sym.decodedName
}
.filter(name => name != "Nil" && name != "None")
.sorted
if paramType != defn.AnyType then
completionSymbols
.collect {
case sym
if sym.info <:< paramType && sym.isTerm && !sym.info.isErroneous && !sym.info.isNullType && !sym.info.isNothingType && !sym
.is(Flags.Method) && !sym.is(Flags.Synthetic) =>
sym.decodedName
}
.filter(name => name != "Nil" && name != "None")
.sorted
else Nil

def findDefaultValue(param: ParamSymbol): String =
val matchingType = matchingTypesInScope(param.info)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@ class CompletionArgSuite extends BaseCompletionSuite:
| bbb = 123,
| aa@@
| )
|}
|}
|""".stripMargin,
"""|aaa = : Int
|""".stripMargin,
Expand All @@ -1063,7 +1063,7 @@ class CompletionArgSuite extends BaseCompletionSuite:
| ccc = 123,
| aa@@
| )
|}
|}
|""".stripMargin,
"""|aaa = : Int
|""".stripMargin,
Expand All @@ -1079,7 +1079,7 @@ class CompletionArgSuite extends BaseCompletionSuite:
| ccc = 123,
| aa@@
| )
|}
|}
|""".stripMargin,
"""|aaa = : Int
|""".stripMargin,
Expand All @@ -1105,4 +1105,18 @@ class CompletionArgSuite extends BaseCompletionSuite:
"""|str = : String
| """.stripMargin,
topLines = Some(1),
)

@Test def `comparison` =
check(
"""package a
|object w {
| abstract class T(x: Int) {
| def met(x: Int): Unit = {
| println(x@@)
| }
| }}
|""".stripMargin,
"""x: Int
|x = : Any""".stripMargin,
)
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
| // tr@@
|}
|""".stripMargin,
"",
"""|transient scala (commit: '')
|transparentTrait - scala.annotation (commit: '')""".stripMargin,
includeCommitCharacter = true
)

Expand All @@ -57,7 +58,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
| **/
|}
|""".stripMargin,
"",
"""|transient scala (commit: '')
|transparentTrait - scala.annotation (commit: '')""".stripMargin,
includeCommitCharacter = true
)

Expand Down Expand Up @@ -151,6 +153,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
"""|value: Int
|val
|var
|varargs(): varargs
|varargs - scala.annotation
|""".stripMargin
)

Expand All @@ -167,6 +171,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
|""".stripMargin,
"""|val
|var
|varargs(): varargs
|varargs - scala.annotation
|""".stripMargin
)

Expand All @@ -181,9 +187,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
| }
|}
|""".stripMargin,
"""|given (commit: '')
|""".stripMargin,
includeCommitCharacter = true
"""given (commit: '')
|""".stripMargin,
includeCommitCharacter = true,
topLines = Some(5)
)

@Test def `val-arg` =
Expand All @@ -198,8 +205,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
|}
|""".stripMargin,
"""|value: Int
|""".stripMargin,
topLines = Some(1)
|varargs(): varargs
|varargs - scala.annotation""".stripMargin
)

@Test def `val-trailing-space` =
Expand Down Expand Up @@ -406,7 +413,13 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
| protected de@@
|}
""".stripMargin,
"def"
"""|def
|deprecated scala
|deprecatedInheritance scala
|deprecatedName scala
|deprecatedOverriding scala
|""".stripMargin,
topLines = Some(5)
)

@Test def `protected-val` =
Expand All @@ -418,9 +431,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
| protected va@@
|}
""".stripMargin,
"""val
|var
|""".stripMargin
"""|val
|var
|varargs - scala.annotation
|""".stripMargin
)

@Test def `topLevel` =
Expand Down Expand Up @@ -458,16 +472,26 @@ class CompletionKeywordSuite extends BaseCompletionSuite:
| def hello(u@@)
|}""".stripMargin,
"""|using (commit: '')
|unsafeExceptions scala (commit: '')
|unchecked scala (commit: '')
|unsafe - scala.caps (commit: '')
|unsafeNulls - scala.runtime.stdLibPatches.language (commit: '')
|""".stripMargin,
includeCommitCharacter = true
includeCommitCharacter = true,
topLines = Some(5)
)

@Test def `not-using` =
check(
"""|object A{
| def hello(a: String, u@@)
|}""".stripMargin,
""
"""|unsafeExceptions scala
|unchecked scala
|unsafe - scala.caps
|unsafeNulls - scala.runtime.stdLibPatches.language
|unused - scala.annotation """.stripMargin,
topLines = Some(5)
)

@Test def `extends-class` =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ class CompletionPatternSuite extends BaseCompletionSuite:
| case ma@@
| }
|}""".stripMargin,
""
"""|main scala
|macros - scala.languageFeature.experimental
|macroImpl - scala.reflect.macros.internal
|""".stripMargin
)

@Test def `bind2` =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,8 @@ class CompletionSnippetSuite extends BaseCompletionSuite:
|Widget($0) - (age: Int): Widget
|Widget($0) - (name: String, age: Int): Widget
|""".stripMargin,
includeDetail = true
includeDetail = true,
topLines = Some(4)
)

@Test def `no-apply` =
Expand All @@ -335,8 +336,13 @@ class CompletionSnippetSuite extends BaseCompletionSuite:
| Wi@@
|}
|""".stripMargin,
"Widget - example",
includeDetail = true
"""|Widget - example
|Window - java.awt
|WindowPeer - java.awt.peer
|WithFilter - scala.collection
|""".stripMargin,
includeDetail = true,
topLines = Some(4)
)

// https://github.com/scalameta/metals/issues/4004
Expand Down
Loading

0 comments on commit 7240327

Please sign in to comment.