@@ -12,6 +12,7 @@ import scala.meta.internal.pc.{IdentifierComparator, MemberOrdering}
12
12
import scala .meta .pc .*
13
13
14
14
import dotty .tools .dotc .ast .tpd .*
15
+ import dotty .tools .dotc .ast .NavigateAST
15
16
import dotty .tools .dotc .core .Comments .Comment
16
17
import dotty .tools .dotc .core .Constants .Constant
17
18
import dotty .tools .dotc .core .Contexts .*
@@ -24,6 +25,7 @@ import dotty.tools.dotc.core.StdNames.*
24
25
import dotty .tools .dotc .core .Symbols .*
25
26
import dotty .tools .dotc .core .Types .*
26
27
import dotty .tools .dotc .interactive .Completion
28
+ import dotty .tools .dotc .interactive .Completion .Mode
27
29
import dotty .tools .dotc .transform .SymUtils .*
28
30
import dotty .tools .dotc .util .SourcePosition
29
31
import dotty .tools .dotc .util .Spans
@@ -54,6 +56,14 @@ class Completions(
54
56
55
57
val coursierComplete = new CoursierComplete (BuildInfo .scalaVersion)
56
58
59
+ private lazy val completionMode =
60
+ val adjustedPath = Completion .pathBeforeDesugaring(path, pos)
61
+ val mode = Completion .completionMode(adjustedPath, pos)
62
+ path match
63
+ case Literal (Constant (_ : String )) :: _ => Mode .Term // literal completions
64
+ case _ => mode
65
+
66
+
57
67
private lazy val shouldAddSnippet =
58
68
path match
59
69
/* In case of `method@@()` we should not add snippets and the path
@@ -69,105 +79,33 @@ class Completions(
69
79
case (_ : Ident ) :: (_ : SeqLiteral ) :: _ => false
70
80
case _ => true
71
81
72
- enum CursorPos :
73
- case Type (hasTypeParams : Boolean , hasNewKw : Boolean )
74
- case Term
75
- case Import
76
-
77
- def include (sym : Symbol )(using Context ): Boolean =
78
- val generalExclude =
79
- isUninterestingSymbol(sym) ||
80
- ! isNotLocalForwardReference(sym) ||
81
- sym.isPackageObject
82
-
83
- def isWildcardParam (sym : Symbol ) =
84
- if sym.isTerm && sym.owner.isAnonymousFunction then
85
- sym.name match
86
- case DerivedName (under, _) =>
87
- under.isEmpty
88
- case _ => false
89
- else false
82
+ private lazy val allowTemplateSuffix : Boolean =
83
+ path match
84
+ case _ :: New (selectOrIdent : (Select | Ident )) :: _ => true
85
+ case _ => false
90
86
91
- if generalExclude then false
92
- else
93
- this match
94
- case Type (_, _) => true
95
- case Term if isWildcardParam(sym) => false
96
- case Term if sym.isTerm || sym.is(Package ) => true
97
- case Import => true
87
+ def includeSymbol (sym : Symbol )(using Context ): Boolean =
88
+ val generalExclude =
89
+ isUninterestingSymbol(sym) ||
90
+ ! isNotLocalForwardReference(sym) ||
91
+ sym.isPackageObject
92
+
93
+ def isWildcardParam (sym : Symbol ) =
94
+ if sym.isTerm && sym.owner.isAnonymousFunction then
95
+ sym.name match
96
+ case DerivedName (under, _) =>
97
+ under.isEmpty
98
98
case _ => false
99
- end if
100
- end include
101
-
102
- def allowBracketSuffix : Boolean =
103
- this match
104
- case Type (hasTypeParams, _) => ! hasTypeParams
105
- case _ => false
106
-
107
- def allowTemplateSuffix : Boolean =
108
- this match
109
- case Type (_, hasNewKw) => hasNewKw
110
- case _ => false
111
-
112
- def allowApplicationSuffix : Boolean =
113
- this match
114
- case Term => true
115
- case _ => false
99
+ else false
116
100
117
- end CursorPos
101
+ if generalExclude then false
102
+ else if completionMode.is(Mode .ImportOrExport ) then true
103
+ else if completionMode.is(Mode .Term ) && isWildcardParam(sym) then false
104
+ else if completionMode.is(Mode .Term ) && (sym.isTerm || sym.is(Package )) then true
105
+ else ! completionMode.is(Mode .Term )
106
+ end if
107
+ end includeSymbol
118
108
119
- private lazy val cursorPos =
120
- calculateTypeInstanceAndNewPositions(Completion .pathBeforeDesugaring(path, pos))
121
-
122
- private def calculateTypeInstanceAndNewPositions (
123
- path : List [Tree ]
124
- ): CursorPos =
125
- path match
126
- case (_ : Import ) :: _ => CursorPos .Import
127
- case _ :: (_ : Import ) :: _ => CursorPos .Import
128
- case (head : (Select | Ident )) :: tail =>
129
- // https://github.com/lampepfl/dotty/issues/15750
130
- // due to this issue in dotty, because of which trees after typer lose information,
131
- // we have to calculate hasNoSquareBracket manually:
132
- val hasSquareBracket =
133
- val span : Span = head.srcPos.span
134
- if span.exists then
135
- var i = span.end
136
- while i < (text.length() - 1 ) && text(i).isWhitespace do i = i + 1
137
-
138
- if i < text.length() then text(i) == '['
139
- else false
140
- else false
141
-
142
- def typePos = CursorPos .Type (hasSquareBracket, hasNewKw = false )
143
- def newTypePos =
144
- CursorPos .Type (hasSquareBracket, hasNewKw = true )
145
-
146
- tail match
147
- case (v : ValOrDefDef ) :: _ if v.tpt.sourcePos.contains(pos) =>
148
- typePos
149
- case New (selectOrIdent : (Select | Ident )) :: _
150
- if selectOrIdent.sourcePos.contains(pos) =>
151
- newTypePos
152
- case (a @ AppliedTypeTree (_, args)) :: _
153
- if args.exists(_.sourcePos.contains(pos)) =>
154
- typePos
155
- case (templ @ Template (constr, _, self, _)) :: _
156
- if (constr :: self :: templ.parents).exists(
157
- _.sourcePos.contains(pos)
158
- ) =>
159
- typePos
160
- case _ =>
161
- CursorPos .Term
162
- end match
163
-
164
- case (_ : TypeTree ) :: TypeApply (Select (newQualifier : New , _), _) :: _
165
- if newQualifier.sourcePos.contains(pos) =>
166
- CursorPos .Type (hasTypeParams = false , hasNewKw = true )
167
-
168
- case _ => CursorPos .Term
169
- end match
170
- end calculateTypeInstanceAndNewPositions
171
109
172
110
def completions (): (List [CompletionValue ], SymbolSearch .Result ) =
173
111
val (advanced, exclusive) = advancedCompletions(path, pos, completionPos)
@@ -198,7 +136,7 @@ class Completions(
198
136
end match
199
137
200
138
val application = CompletionApplication .fromPath(path)
201
- val ordering = completionOrdering(application, cursorPos )
139
+ val ordering = completionOrdering(application)
202
140
val values = application.postProcess(all.sorted(ordering))
203
141
(values, result)
204
142
end completions
@@ -248,8 +186,7 @@ class Completions(
248
186
private def findSuffix (symbol : Symbol ): CompletionSuffix =
249
187
CompletionSuffix .empty
250
188
.chain { suffix => // for [] suffix
251
- if shouldAddSnippet &&
252
- cursorPos.allowBracketSuffix && symbol.info.typeParams.nonEmpty
189
+ if shouldAddSnippet && symbol.info.typeParams.nonEmpty
253
190
then
254
191
val typeParamsCount = symbol.info.typeParams.length
255
192
suffix.withNewSuffixSnippet(SuffixKind .Bracket (typeParamsCount))
@@ -279,7 +216,7 @@ class Completions(
279
216
else suffix
280
217
}
281
218
.chain { suffix => // for {} suffix
282
- if shouldAddSnippet && cursorPos. allowTemplateSuffix
219
+ if shouldAddSnippet && allowTemplateSuffix
283
220
&& isAbstractType(symbol)
284
221
then
285
222
if suffix.hasSnippet then suffix.withNewSuffix(SuffixKind .Template )
@@ -301,7 +238,7 @@ class Completions(
301
238
val methodSymbols =
302
239
if shouldAddSnippet &&
303
240
(sym.is(Flags .Module ) || sym.isClass && ! sym.is(Flags .Trait )) &&
304
- ! sym.is(Flags .JavaDefined ) && cursorPos.allowApplicationSuffix
241
+ ! sym.is(Flags .JavaDefined ) && completionMode.is( Mode . Term )
305
242
then
306
243
val info =
307
244
/* Companion will be added even for normal classes now,
@@ -627,7 +564,7 @@ class Completions(
627
564
name.substring(0 , name.length - 1 )
628
565
else name
629
566
val id = nameId + symOnly.snippetSuffix.labelSnippet.getOrElse(" " )
630
- val include = cursorPos.include (sym)
567
+ val include = includeSymbol (sym)
631
568
(id, include)
632
569
case kw : CompletionValue .Keyword => (kw.label, true )
633
570
case mc : CompletionValue .MatchCompletion => (mc.label, true )
@@ -687,7 +624,6 @@ class Completions(
687
624
private def computeRelevancePenalty (
688
625
completion : CompletionValue ,
689
626
application : CompletionApplication ,
690
- cursorPos : CursorPos ,
691
627
): Int =
692
628
import scala .meta .internal .pc .MemberOrdering .*
693
629
@@ -733,10 +669,8 @@ class Completions(
733
669
relevance |= IsSynthetic
734
670
if sym.isDeprecated then relevance |= IsDeprecated
735
671
if isEvilMethod(sym.name) then relevance |= IsEvilMethod
736
- cursorPos match
737
- case CursorPos .Type (_, _) if ! sym.isType =>
738
- relevance |= IsNotTypeInTypePos
739
- case _ =>
672
+ if ! completionMode.is(Mode .ImportOrExport ) &&
673
+ completionMode.is(Mode .Type ) && ! sym.isType then relevance |= IsNotTypeInTypePos
740
674
relevance
741
675
end symbolRelevance
742
676
@@ -814,8 +748,7 @@ class Completions(
814
748
end CompletionApplication
815
749
816
750
private def completionOrdering (
817
- application : CompletionApplication ,
818
- cursorPos : CursorPos ,
751
+ application : CompletionApplication
819
752
): Ordering [CompletionValue ] =
820
753
new Ordering [CompletionValue ]:
821
754
val queryLower = completionPos.query.toLowerCase()
@@ -830,8 +763,8 @@ class Completions(
830
763
831
764
def compareByRelevance (o1 : CompletionValue , o2 : CompletionValue ): Int =
832
765
Integer .compare(
833
- computeRelevancePenalty(o1, application, cursorPos ),
834
- computeRelevancePenalty(o2, application, cursorPos ),
766
+ computeRelevancePenalty(o1, application),
767
+ computeRelevancePenalty(o2, application),
835
768
)
836
769
837
770
def fuzzyScore (o : CompletionValue .Symbolic ): Int =
0 commit comments