@@ -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,113 +79,41 @@ 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
- def hasSyntheticCursorSuffix : Boolean =
79
- if ! sym.name.endsWith(Cursor .value) then false
80
- else
81
- val realNameLength = sym.decodedName.length - Cursor .value.length
82
- sym.source == pos.source &&
83
- sym.span.start + realNameLength == pos.span.end
84
-
85
- val generalExclude =
86
- isUninterestingSymbol(sym) ||
87
- ! isNotLocalForwardReference(sym) ||
88
- sym.isPackageObject ||
89
- hasSyntheticCursorSuffix
90
-
91
- def isWildcardParam (sym : Symbol ) =
92
- if sym.isTerm && sym.owner.isAnonymousFunction then
93
- sym.name match
94
- case DerivedName (under, _) =>
95
- under.isEmpty
96
- case _ => false
97
- else false
82
+ private lazy val allowTemplateSuffix : Boolean =
83
+ path match
84
+ case _ :: New (selectOrIdent : (Select | Ident )) :: _ => true
85
+ case _ => false
98
86
99
- if generalExclude then false
87
+ def includeSymbol (sym : Symbol )(using Context ): Boolean =
88
+ def hasSyntheticCursorSuffix : Boolean =
89
+ if ! sym.name.endsWith(Cursor .value) then false
100
90
else
101
- this match
102
- case Type (_, _) => true
103
- case Term if isWildcardParam(sym) => false
104
- case Term if sym.isTerm || sym.is(Package ) => true
105
- case Import => true
91
+ val realNameLength = sym.decodedName.length - Cursor .value.length
92
+ sym.source == pos.source &&
93
+ sym.span.start + realNameLength == pos.span.end
94
+
95
+ val generalExclude =
96
+ isUninterestingSymbol(sym) ||
97
+ ! isNotLocalForwardReference(sym) ||
98
+ sym.isPackageObject ||
99
+ hasSyntheticCursorSuffix
100
+
101
+ def isWildcardParam (sym : Symbol ) =
102
+ if sym.isTerm && sym.owner.isAnonymousFunction then
103
+ sym.name match
104
+ case DerivedName (under, _) =>
105
+ under.isEmpty
106
106
case _ => false
107
- end if
108
- end include
109
-
110
- def allowBracketSuffix : Boolean =
111
- this match
112
- case Type (hasTypeParams, _) => ! hasTypeParams
113
- case _ => false
114
-
115
- def allowTemplateSuffix : Boolean =
116
- this match
117
- case Type (_, hasNewKw) => hasNewKw
118
- case _ => false
107
+ else false
119
108
120
- def allowApplicationSuffix : Boolean =
121
- this match
122
- case Term => true
123
- case _ => false
109
+ if generalExclude then false
110
+ else if completionMode.is(Mode .ImportOrExport ) then true
111
+ else if completionMode.is(Mode .Term ) && isWildcardParam(sym) then false
112
+ else if completionMode.is(Mode .Term ) && (sym.isTerm || sym.is(Package )) then true
113
+ else ! completionMode.is(Mode .Term )
114
+ end if
115
+ end includeSymbol
124
116
125
- end CursorPos
126
-
127
- private lazy val cursorPos =
128
- calculateTypeInstanceAndNewPositions(Completion .pathBeforeDesugaring(path, pos))
129
-
130
- private def calculateTypeInstanceAndNewPositions (
131
- path : List [Tree ]
132
- ): CursorPos =
133
- path match
134
- case (_ : Import ) :: _ => CursorPos .Import
135
- case _ :: (_ : Import ) :: _ => CursorPos .Import
136
- case (head : (Select | Ident )) :: tail =>
137
- // https://github.com/lampepfl/dotty/issues/15750
138
- // due to this issue in dotty, because of which trees after typer lose information,
139
- // we have to calculate hasNoSquareBracket manually:
140
- val hasSquareBracket =
141
- val span : Span = head.srcPos.span
142
- if span.exists then
143
- var i = span.end
144
- while i < (text.length() - 1 ) && text(i).isWhitespace do i = i + 1
145
-
146
- if i < text.length() then text(i) == '['
147
- else false
148
- else false
149
-
150
- def typePos = CursorPos .Type (hasSquareBracket, hasNewKw = false )
151
- def newTypePos =
152
- CursorPos .Type (hasSquareBracket, hasNewKw = true )
153
-
154
- tail match
155
- case (v : ValOrDefDef ) :: _ if v.tpt.sourcePos.contains(pos) =>
156
- typePos
157
- case New (selectOrIdent : (Select | Ident )) :: _
158
- if selectOrIdent.sourcePos.contains(pos) =>
159
- newTypePos
160
- case (a @ AppliedTypeTree (_, args)) :: _
161
- if args.exists(_.sourcePos.contains(pos)) =>
162
- typePos
163
- case (templ @ Template (constr, _, self, _)) :: _
164
- if (constr :: self :: templ.parents).exists(
165
- _.sourcePos.contains(pos)
166
- ) =>
167
- typePos
168
- case _ =>
169
- CursorPos .Term
170
- end match
171
-
172
- case (_ : TypeTree ) :: TypeApply (Select (newQualifier : New , _), _) :: _
173
- if newQualifier.sourcePos.contains(pos) =>
174
- CursorPos .Type (hasTypeParams = false , hasNewKw = true )
175
-
176
- case _ => CursorPos .Term
177
- end match
178
- end calculateTypeInstanceAndNewPositions
179
117
180
118
def completions (): (List [CompletionValue ], SymbolSearch .Result ) =
181
119
val (advanced, exclusive) = advancedCompletions(path, pos, completionPos)
@@ -206,7 +144,7 @@ class Completions(
206
144
end match
207
145
208
146
val application = CompletionApplication .fromPath(path)
209
- val ordering = completionOrdering(application, cursorPos )
147
+ val ordering = completionOrdering(application)
210
148
val values = application.postProcess(all.sorted(ordering))
211
149
(values, result)
212
150
end completions
@@ -256,8 +194,7 @@ class Completions(
256
194
private def findSuffix (symbol : Symbol ): CompletionSuffix =
257
195
CompletionSuffix .empty
258
196
.chain { suffix => // for [] suffix
259
- if shouldAddSnippet &&
260
- cursorPos.allowBracketSuffix && symbol.info.typeParams.nonEmpty
197
+ if shouldAddSnippet && symbol.info.typeParams.nonEmpty
261
198
then suffix.withNewSuffixSnippet(SuffixKind .Bracket )
262
199
else suffix
263
200
}
@@ -285,7 +222,7 @@ class Completions(
285
222
else suffix
286
223
}
287
224
.chain { suffix => // for {} suffix
288
- if shouldAddSnippet && cursorPos. allowTemplateSuffix
225
+ if shouldAddSnippet && allowTemplateSuffix
289
226
&& isAbstractType(symbol)
290
227
then
291
228
if suffix.hasSnippet then suffix.withNewSuffix(SuffixKind .Template )
@@ -307,7 +244,7 @@ class Completions(
307
244
val methodSymbols =
308
245
if shouldAddSnippet &&
309
246
(sym.is(Flags .Module ) || sym.isClass && ! sym.is(Flags .Trait )) &&
310
- ! sym.is(Flags .JavaDefined ) && cursorPos.allowApplicationSuffix
247
+ ! sym.is(Flags .JavaDefined ) && completionMode.is( Mode . Term )
311
248
then
312
249
val info =
313
250
/* Companion will be added even for normal classes now,
@@ -635,7 +572,7 @@ class Completions(
635
572
val suffix =
636
573
if symOnly.snippetSuffix.addLabelSnippet then " []" else " "
637
574
val id = nameId + suffix
638
- val include = cursorPos.include (sym)
575
+ val include = includeSymbol (sym)
639
576
(id, include)
640
577
case kw : CompletionValue .Keyword => (kw.label, true )
641
578
case mc : CompletionValue .MatchCompletion => (mc.label, true )
@@ -695,7 +632,6 @@ class Completions(
695
632
private def computeRelevancePenalty (
696
633
completion : CompletionValue ,
697
634
application : CompletionApplication ,
698
- cursorPos : CursorPos ,
699
635
): Int =
700
636
import scala .meta .internal .pc .MemberOrdering .*
701
637
@@ -741,10 +677,8 @@ class Completions(
741
677
relevance |= IsSynthetic
742
678
if sym.isDeprecated then relevance |= IsDeprecated
743
679
if isEvilMethod(sym.name) then relevance |= IsEvilMethod
744
- cursorPos match
745
- case CursorPos .Type (_, _) if ! sym.isType =>
746
- relevance |= IsNotTypeInTypePos
747
- case _ =>
680
+ if ! completionMode.is(Mode .ImportOrExport ) &&
681
+ completionMode.is(Mode .Type ) && ! sym.isType then relevance |= IsNotTypeInTypePos
748
682
relevance
749
683
end symbolRelevance
750
684
@@ -822,8 +756,7 @@ class Completions(
822
756
end CompletionApplication
823
757
824
758
private def completionOrdering (
825
- application : CompletionApplication ,
826
- cursorPos : CursorPos ,
759
+ application : CompletionApplication
827
760
): Ordering [CompletionValue ] =
828
761
new Ordering [CompletionValue ]:
829
762
val queryLower = completionPos.query.toLowerCase()
@@ -838,8 +771,8 @@ class Completions(
838
771
839
772
def compareByRelevance (o1 : CompletionValue , o2 : CompletionValue ): Int =
840
773
Integer .compare(
841
- computeRelevancePenalty(o1, application, cursorPos ),
842
- computeRelevancePenalty(o2, application, cursorPos ),
774
+ computeRelevancePenalty(o1, application),
775
+ computeRelevancePenalty(o2, application),
843
776
)
844
777
845
778
def fuzzyScore (o : CompletionValue .Symbolic ): Int =
0 commit comments