@@ -8,7 +8,7 @@ import scala.collection.mutable
8
8
import scala .meta .internal .metals .Fuzzy
9
9
import scala .meta .internal .metals .ReportContext
10
10
import scala .meta .internal .mtags .CoursierComplete
11
- import scala .meta .internal .pc .{IdentifierComparator , MemberOrdering }
11
+ import scala .meta .internal .pc .{IdentifierComparator , MemberOrdering , CompletionFuzzy }
12
12
import scala .meta .pc .*
13
13
14
14
import dotty .tools .dotc .ast .tpd .*
@@ -232,16 +232,18 @@ class Completions(
232
232
val hasNonSyntheticConstructor = sym.name.isTypeName && sym.isClass
233
233
&& ! sym.is(ModuleClass ) && ! sym.is(Trait ) && ! sym.is(Abstract ) && ! sym.is(Flags .JavaDefined )
234
234
235
- val methodDenots : List [SingleDenotation ] =
235
+ val (extraMethodDenots, skipOriginalDenot) : ( List [SingleDenotation ], Boolean ) =
236
236
if shouldAddSnippet && isNew && hasNonSyntheticConstructor then
237
- sym.info.member(nme.CONSTRUCTOR ).allSymbols.map(_.asSingleDenotation)
237
+ val constructors = sym.info.member(nme.CONSTRUCTOR ).allSymbols.map(_.asSingleDenotation)
238
238
.filter(_.symbol.isAccessibleFrom(denot.info))
239
+ constructors -> true
240
+
239
241
else if shouldAddSnippet && completionMode.is(Mode .Term ) && sym.name.isTermName && ! sym.is(Flags .Method ) && ! sym.is(Flags .JavaDefined ) then
240
242
val constructors = if sym.isAllOf(ConstructorProxyModule ) then
241
243
sym.companionClass.info.member(nme.CONSTRUCTOR ).allSymbols
242
244
else
243
245
val companionApplies = denot.info.member(nme.apply).allSymbols
244
- val classConstructors = if sym.companionClass.exists then
246
+ val classConstructors = if sym.companionClass.exists && ! sym.companionClass.isOneOf( AbstractOrTrait ) then
245
247
sym.companionClass.info.member(nme.CONSTRUCTOR ).allSymbols
246
248
else Nil
247
249
@@ -250,33 +252,44 @@ class Completions(
250
252
else
251
253
companionApplies ++ classConstructors
252
254
253
- val extraDenots = constructors.map(_.asSeenFrom(denot.info).asSingleDenotation)
255
+ val result = constructors.map(_.asSeenFrom(denot.info).asSingleDenotation)
254
256
.filter(_.symbol.isAccessibleFrom(denot.info))
255
257
256
- if sym.isAllOf(ConstructorProxyModule ) || sym.is(Trait ) then extraDenots
257
- else denot :: extraDenots
258
+ result -> ( sym.isAllOf(ConstructorProxyModule ) || sym.is(Trait ))
259
+ else Nil -> false
258
260
259
- else denot :: Nil
261
+ val extraCompletionValues =
262
+ val existsApply = extraMethodDenots.exists(_.symbol.name == nme.apply)
260
263
261
- val existsApply = methodDenots.exists(_.symbol.name == nme.apply)
264
+ extraMethodDenots.map { methodDenot =>
265
+ val suffix = findSuffix(methodDenot.symbol)
266
+ val affix = if methodDenot.symbol.isConstructor && existsApply then
267
+ adjustedPath match
268
+ case (select @ Select (qual, _)) :: _ =>
269
+ val start = qual.span.start
270
+ val insertRange = select.sourcePos.startPos.withEnd(completionPos.queryEnd).toLsp
262
271
263
- methodDenots.map { methodDenot =>
264
- val suffix = findSuffix(methodDenot.symbol )
265
- val affix = if methodDenot.symbol.isConstructor && existsApply then
266
- adjustedPath match
267
- case (select @ Select (qual, _)) :: _ =>
268
- val start = qual.span.start
269
- val insertRange = select.sourcePos.startPos.withEnd(completionPos.queryEnd).toLsp
272
+ suffix
273
+ .withCurrentPrefix(qual.show + " . " )
274
+ .withNewPrefix( Affix ( PrefixKind . New , insertRange = Some (insertRange)))
275
+ case _ =>
276
+ suffix.withNewPrefix( Affix ( PrefixKind . New ))
277
+ else suffix
278
+ val name = undoBacktick(label)
270
279
271
- suffix
272
- .withCurrentPrefix(qual.show + " ." )
273
- .withNewPrefix(Affix (PrefixKind .New , insertRange = Some (insertRange)))
274
- case _ =>
275
- suffix.withNewPrefix(Affix (PrefixKind .New ))
276
- else suffix
280
+ CompletionValue .ExtraMethod (
281
+ owner = denot,
282
+ extraMethod = toCompletionValue(name, methodDenot, affix)
283
+ )
284
+ }
285
+
286
+ if skipOriginalDenot then extraCompletionValues
287
+ else
288
+ val suffix = findSuffix(denot.symbol)
277
289
val name = undoBacktick(label)
278
- toCompletionValue(name, methodDenot, affix)
279
- }
290
+ val denotCompletionValue = toCompletionValue(name, denot, suffix)
291
+ denotCompletionValue :: extraCompletionValues
292
+
280
293
end completionsWithAffix
281
294
282
295
/**
@@ -638,7 +651,10 @@ class Completions(
638
651
case ck : CompletionValue .CaseKeyword => (ck.label, true )
639
652
case symOnly : CompletionValue .Symbolic =>
640
653
val sym = symOnly.symbol
641
- val name = SemanticdbSymbols .symbolName(sym)
654
+ val name = symOnly match
655
+ case CompletionValue .ExtraMethod (owner, extraMethod) =>
656
+ SemanticdbSymbols .symbolName(owner.symbol) + SemanticdbSymbols .symbolName(extraMethod.symbol)
657
+ case _ => SemanticdbSymbols .symbolName(sym)
642
658
val suffix =
643
659
if symOnly.snippetAffix.addLabelSnippet then " []" else " "
644
660
val id = name + suffix
@@ -749,18 +765,24 @@ class Completions(
749
765
relevance
750
766
end symbolRelevance
751
767
768
+ def computeRelevance (sym : Symbol , completionValue : CompletionValue .Symbolic ) =
769
+ completionValue match
770
+ case _ : CompletionValue .Override =>
771
+ var penalty = symbolRelevance(sym)
772
+ // show the abstract members first
773
+ if ! sym.is(Deferred ) then penalty |= MemberOrdering .IsNotAbstract
774
+ penalty
775
+ case _ : CompletionValue .Workspace =>
776
+ symbolRelevance(sym) | (IsWorkspaceSymbol + sym.name.show.length())
777
+ case _ => symbolRelevance(sym)
778
+
752
779
completion match
753
- case ov : CompletionValue .Override =>
754
- var penalty = symbolRelevance(ov.symbol)
755
- // show the abstract members first
756
- if ! ov.symbol.is(Deferred ) then penalty |= MemberOrdering .IsNotAbstract
757
- penalty
758
- case CompletionValue .Workspace (_, denot, _, _) =>
759
- symbolRelevance(denot.symbol) | (IsWorkspaceSymbol + denot.name.show.length())
780
+ case CompletionValue .ExtraMethod (owner, extraMethod) =>
781
+ computeRelevance(owner.symbol, extraMethod)
760
782
case sym : CompletionValue .Symbolic =>
761
- symbolRelevance (sym.symbol)
762
- case _ =>
763
- Int . MaxValue
783
+ computeRelevance (sym.symbol, sym )
784
+ case _ => Int . MaxValue
785
+
764
786
end computeRelevancePenalty
765
787
766
788
private lazy val isEvilMethod : Set [Name ] = Set [Name ](
@@ -868,6 +890,7 @@ class Completions(
868
890
def priority (v : CompletionValue ): Int =
869
891
v match
870
892
case _ : CompletionValue .Compiler => 0
893
+ case CompletionValue .ExtraMethod (_, _ : CompletionValue .Compiler ) => 0
871
894
case _ => 1
872
895
873
896
priority(o1) - priority(o2)
@@ -909,12 +932,19 @@ class Completions(
909
932
910
933
def methodScore (v : CompletionValue .Symbolic )(using Context ): Int =
911
934
val sym = v.symbol
912
- val workspacePenalty = if v.isInstanceOf [CompletionValue .Workspace ] then 3 else 0
935
+ val workspacePenalty = v match
936
+ case CompletionValue .ExtraMethod (_, _ : CompletionValue .Workspace ) => 5
937
+ case _ : CompletionValue .Workspace => 5
938
+ case _ => 0
939
+
940
+ val isExtraMethod = v.isInstanceOf [CompletionValue .ExtraMethod ]
913
941
val methodPenalty =
914
942
if isNew && sym.isConstructor then - 1
915
- else if ! completionMode.is(Mode .Member ) && sym.name == nme.apply then 1
916
- else if sym.isConstructor then 2
917
- else 0
943
+ else if isExtraMethod && ! sym.isConstructor then 1
944
+ else if isExtraMethod then 2
945
+ else if ! sym.isAllOf(SyntheticModule ) then 3
946
+ else 4
947
+
918
948
workspacePenalty + methodPenalty
919
949
920
950
override def compare (o1 : CompletionValue , o2 : CompletionValue ): Int =
@@ -942,14 +972,14 @@ class Completions(
942
972
)
943
973
if byFuzzy != 0 then byFuzzy
944
974
else
945
- val byMethodScore = Integer .compare(
946
- methodScore(sym1),
947
- methodScore(sym2)
948
- )
949
- if byMethodScore != 0 then byMethodScore
975
+ val byRelevance = compareByRelevance(o1, o2)
976
+ if byRelevance != 0 then byRelevance
950
977
else
951
- val byRelevance = compareByRelevance(o1, o2)
952
- if byRelevance != 0 then byRelevance
978
+ val byMethodScore = Integer .compare(
979
+ methodScore(sym1),
980
+ methodScore(sym2)
981
+ )
982
+ if byMethodScore != 0 then byMethodScore
953
983
else
954
984
val byIdentifier = IdentifierComparator .compare(
955
985
s1.name.show,
0 commit comments