Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7d27633

Browse files
authored
Improve symbol order in completions provided by the presentation compiler (#23888)
Extension methods that are not in the same file are placed after all Product methods and even after extension methods like "ensuring". This PR penalizes the following methods, so that they are no longer at the top of the suggestions: - scala.Product.* - scala.Equals.* - scala.Predef.ArrowAssoc.* - scala.Predef.Ensuring.* - scala.Predef.StringFormat.* - scala.Predef.nn - scala.Predef.runtimeChecked Resolves scalameta/metals#7642
1 parent e2018c2 commit 7d27633

File tree

3 files changed

+71
-11
lines changed

3 files changed

+71
-11
lines changed

‎presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import dotty.tools.dotc.ast.untpd
1515
import dotty.tools.dotc.core.Comments.Comment
1616
import dotty.tools.dotc.core.Constants.Constant
1717
import dotty.tools.dotc.core.Contexts.*
18+
import dotty.tools.dotc.core.Decorators.toTermName
1819
import dotty.tools.dotc.core.Denotations.SingleDenotation
1920
import dotty.tools.dotc.core.Flags
2021
import dotty.tools.dotc.core.Flags.*
@@ -766,6 +767,13 @@ class Completions(
766767
).flatMap(_.alternatives.map(_.symbol)).toSet
767768
)
768769

770+
private lazy val EqualsClass: ClassSymbol = requiredClass("scala.Equals")
771+
private lazy val ArrowAssocClass: ClassSymbol = requiredClass("scala.Predef.ArrowAssoc")
772+
private lazy val EnsuringClass: ClassSymbol = requiredClass("scala.Predef.Ensuring")
773+
private lazy val StringFormatClass: ClassSymbol = requiredClass("scala.Predef.StringFormat")
774+
private lazy val nnMethod: Symbol = defn.ScalaPredefModule.info.member("nn".toTermName).symbol
775+
private lazy val runtimeCheckedMethod: Symbol = defn.ScalaPredefModule.info.member("runtimeChecked".toTermName).symbol
776+
769777
private def isNotLocalForwardReference(sym: Symbol)(using Context): Boolean =
770778
!sym.isLocalToBlock ||
771779
!sym.srcPos.isAfter(completionPos.originalCursorPosition) ||
@@ -784,6 +792,17 @@ class Completions(
784792
(sym.isField && !isJavaClass && !isModuleOrClass) || sym.getter != NoSymbol
785793
catch case _ => false
786794

795+
def isInheritedFromScalaLibrary(sym: Symbol) =
796+
sym.owner == defn.AnyClass ||
797+
sym.owner == defn.ObjectClass ||
798+
sym.owner == defn.ProductClass ||
799+
sym.owner == EqualsClass ||
800+
sym.owner == ArrowAssocClass ||
801+
sym.owner == EnsuringClass ||
802+
sym.owner == StringFormatClass ||
803+
sym == nnMethod ||
804+
sym == runtimeCheckedMethod
805+
787806
def symbolRelevance(sym: Symbol): Int =
788807
var relevance = 0
789808
// symbols defined in this file are more relevant
@@ -801,7 +820,7 @@ class Completions(
801820
case _ =>
802821

803822
// symbols whose owner is a base class are less relevant
804-
if sym.owner == defn.AnyClass|| sym.owner == defn.ObjectClass
823+
if isInheritedFromScalaLibrary(sym)
805824
then relevance |= IsInheritedBaseMethod
806825
// symbols not provided via an implicit are more relevant
807826
if sym.is(Implicit) ||
@@ -813,7 +832,7 @@ class Completions(
813832
// accessors of case class members are more relevant
814833
if !sym.is(CaseAccessor) then relevance |= IsNotCaseAccessor
815834
// public symbols are more relevant
816-
if !sym.isPublic then relevance |= IsNotCaseAccessor
835+
if !sym.isPublic then relevance |= IsNotPublic
817836
// synthetic symbols are less relevant (e.g. `copy` on case classes)
818837
if sym.is(Synthetic) && !sym.isAllOf(EnumCase) then
819838
relevance |= IsSynthetic

‎presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,3 +437,44 @@ class CompletionExtensionSuite extends BaseCompletionSuite:
437437
|""".stripMargin,
438438
assertSingleItem = false
439439
)
440+
441+
@Test def `extension-for-case-class` =
442+
check(
443+
"""|case class Bar():
444+
| def baz(): Unit = ???
445+
|
446+
|object Bar:
447+
| extension (f: Bar)
448+
| def qux: Unit = ???
449+
|
450+
|object Main:
451+
| val _ = Bar().@@
452+
|""".stripMargin,
453+
"""|baz(): Unit
454+
|copy(): Bar
455+
|qux: Unit
456+
|asInstanceOf[X0]: X0
457+
|canEqual(that: Any): Boolean
458+
|equals(x0ドル: Any): Boolean
459+
|getClass[X0 >: Bar](): Class[? <: X0]
460+
|hashCode(): Int
461+
|isInstanceOf[X0]: Boolean
462+
|productArity: Int
463+
|productElement(n: Int): Any
464+
|productElementName(n: Int): String
465+
|productElementNames: Iterator[String]
466+
|productIterator: Iterator[Any]
467+
|productPrefix: String
468+
|synchronized[X0](x0ドル: X0): X0
469+
|toString(): String
470+
|->[B](y: B): (Bar, B)
471+
|ensuring(cond: Boolean): Bar
472+
|ensuring(cond: Bar => Boolean): Bar
473+
|ensuring(cond: Boolean, msg: => Any): Bar
474+
|ensuring(cond: Bar => Boolean, msg: => Any): Bar
475+
|nn: `?1`.type
476+
|runtimeChecked: `?2`.type
477+
|formatted(fmtstr: String): String
478+
|→[B](y: B): (Bar, B)
479+
| """.stripMargin
480+
)

‎presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,9 @@ class CompletionSuite extends BaseCompletionSuite:
109109
|tabulate[A](n: Int)(f: Int => A): List[A]
110110
|unapplySeq[A](x: List[A] @uncheckedVariance): UnapplySeqWrapper[A]
111111
|unfold[A, S](init: S)(f: S => Option[(A, S)]): List[A]
112-
|->[B](y: B): (List.type, B)
113-
|ensuring(cond: Boolean): List.type
114-
|ensuring(cond: List.type => Boolean): List.type
115-
|ensuring(cond: Boolean, msg: => Any): List.type
116-
|ensuring(cond: List.type => Boolean, msg: => Any): List.type
117112
|fromSpecific(from: Any)(it: IterableOnce[Nothing]): List[Nothing]
118113
|fromSpecific(it: IterableOnce[Nothing]): List[Nothing]
119-
|nn: List.type
120-
|runtimeChecked scala.collection.immutable
121114
|toFactory(from: Any): Factory[Nothing, List[Nothing]]
122-
|formatted(fmtstr: String): String
123-
|→[B](y: B): (List.type, B)
124115
|iterableFactory[A]: Factory[A, List[A]]
125116
|asInstanceOf[X0]: X0
126117
|equals(x0ドル: Any): Boolean
@@ -129,6 +120,15 @@ class CompletionSuite extends BaseCompletionSuite:
129120
|isInstanceOf[X0]: Boolean
130121
|synchronized[X0](x0ドル: X0): X0
131122
|toString(): String
123+
|->[B](y: B): (List.type, B)
124+
|ensuring(cond: Boolean): List.type
125+
|ensuring(cond: List.type => Boolean): List.type
126+
|ensuring(cond: Boolean, msg: => Any): List.type
127+
|ensuring(cond: List.type => Boolean, msg: => Any): List.type
128+
|nn: List.type
129+
|runtimeChecked scala.collection.immutable
130+
|formatted(fmtstr: String): String
131+
|→[B](y: B): (List.type, B)
132132
|""".stripMargin
133133
)
134134

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /