@@ -42,6 +42,7 @@ class PcInlayHintsProvider(
42
42
val source =
43
43
SourceFile .virtual(filePath.toString, sourceText)
44
44
driver.run(uri, source)
45
+ given InlayHintsParams = params
45
46
46
47
given InferredType .Text = InferredType .Text (text)
47
48
given ctx : Context = driver.currentCtx
@@ -65,7 +66,7 @@ class PcInlayHintsProvider(
65
66
tree : Tree ,
66
67
): InlayHints =
67
68
tree match
68
- case ImplicitConversion (symbol, range) if params.implicitConversions() =>
69
+ case ImplicitConversion (symbol, range) =>
69
70
val adjusted = adjustPos(range)
70
71
inlayHints
71
72
.add(
@@ -78,8 +79,7 @@ class PcInlayHintsProvider(
78
79
LabelPart (" )" ) :: Nil ,
79
80
InlayHintKind .Parameter ,
80
81
)
81
- case ImplicitParameters (symbols, pos, allImplicit)
82
- if params.implicitParameters() =>
82
+ case ImplicitParameters (symbols, pos, allImplicit) =>
83
83
val labelParts = symbols.map(s => List (labelPart(s, s.decodedName)))
84
84
val label =
85
85
if allImplicit then labelParts.separated(" (using " , " , " , " )" )
@@ -89,22 +89,22 @@ class PcInlayHintsProvider(
89
89
label,
90
90
InlayHintKind .Parameter ,
91
91
)
92
- case ValueOf (label, pos) if params.implicitParameters() =>
92
+ case ValueOf (label, pos) =>
93
93
inlayHints.add(
94
94
adjustPos(pos).toLsp,
95
95
LabelPart (" (" ) :: LabelPart (label) :: List (LabelPart (" )" )),
96
96
InlayHintKind .Parameter ,
97
97
)
98
98
case TypeParameters (tpes, pos, sel)
99
- if params.typeParameters() && ! syntheticTupleApply(sel) =>
99
+ if ! syntheticTupleApply(sel) =>
100
100
val label = tpes.map(toLabelParts(_, pos)).separated(" [" , " , " , " ]" )
101
101
inlayHints.add(
102
102
adjustPos(pos).endPos.toLsp,
103
103
label,
104
104
InlayHintKind .Type ,
105
105
)
106
106
case InferredType (tpe, pos, defTree)
107
- if params.inferredTypes() && ! isErrorTpe(tpe) =>
107
+ if ! isErrorTpe(tpe) =>
108
108
val adjustedPos = adjustPos(pos).endPos
109
109
if inlayHints.containsDef(adjustedPos.start) then inlayHints
110
110
else
@@ -191,14 +191,16 @@ class PcInlayHintsProvider(
191
191
end PcInlayHintsProvider
192
192
193
193
object ImplicitConversion :
194
- def unapply (tree : Tree )(using Context ) =
195
- tree match
196
- case Apply (fun : Ident , args) if isSynthetic(fun) =>
197
- implicitConversion(fun, args)
198
- case Apply (Select (fun, name), args)
199
- if name == nme.apply && isSynthetic(fun) =>
200
- implicitConversion(fun, args)
201
- case _ => None
194
+ def unapply (tree : Tree )(using params : InlayHintsParams , ctx : Context ) =
195
+ if (params.implicitConversions()) {
196
+ tree match
197
+ case Apply (fun : Ident , args) if isSynthetic(fun) =>
198
+ implicitConversion(fun, args)
199
+ case Apply (Select (fun, name), args)
200
+ if name == nme.apply && isSynthetic(fun) =>
201
+ implicitConversion(fun, args)
202
+ case _ => None
203
+ } else None
202
204
private def isSynthetic (tree : Tree )(using Context ) =
203
205
tree.span.isSynthetic && tree.symbol.isOneOf(Flags .GivenOrImplicit )
204
206
@@ -212,52 +214,64 @@ object ImplicitConversion:
212
214
end ImplicitConversion
213
215
214
216
object ImplicitParameters :
215
- def unapply (tree : Tree )(using Context ) =
216
- tree match
217
- case Apply (fun, args)
218
- if args.exists(isSyntheticArg) && ! tree.sourcePos.span.isZeroExtent =>
219
- val (implicitArgs, providedArgs) = args.partition(isSyntheticArg)
220
- val allImplicit = providedArgs.isEmpty || providedArgs.forall {
221
- case Ident (name) => name == nme.MISSING
222
- case _ => false
223
- }
224
- val pos = implicitArgs.head.sourcePos
225
- Some (implicitArgs.map(_.symbol), pos, allImplicit)
226
- case _ => None
217
+ def unapply (tree : Tree )(using params : InlayHintsParams , ctx : Context ) =
218
+ if (params.implicitParameters()) {
219
+ tree match
220
+ case Apply (fun, args)
221
+ if args.exists(isSyntheticArg) && ! tree.sourcePos.span.isZeroExtent =>
222
+ val (implicitArgs, providedArgs) = args.partition(isSyntheticArg)
223
+ val allImplicit = providedArgs.isEmpty || providedArgs.forall {
224
+ case Ident (name) => name == nme.MISSING
225
+ case _ => false
226
+ }
227
+ val pos = implicitArgs.head.sourcePos
228
+ Some (implicitArgs.map(_.symbol), pos, allImplicit)
229
+ case _ => None
230
+ } else None
227
231
228
232
private def isSyntheticArg (tree : Tree )(using Context ) = tree match
229
233
case tree : Ident =>
230
- tree.span.isSynthetic && tree.symbol.isOneOf(Flags .GivenOrImplicit )
234
+ tree.span.isSynthetic && tree.symbol.isOneOf(Flags .GivenOrImplicit ) &&
235
+ ! isQuotes(tree)
231
236
case _ => false
237
+
238
+ // Decorations for Quotes are rarely useful
239
+ private def isQuotes (tree : Tree )(using Context ) =
240
+ tree.tpe.typeSymbol == defn.QuotesClass
241
+
232
242
end ImplicitParameters
233
243
234
244
object ValueOf :
235
- def unapply (tree : Tree )(using Context ) =
236
- tree match
237
- case Apply (ta @ TypeApply (fun, _), _)
238
- if fun.span.isSynthetic && isValueOf(fun) =>
239
- Some (
240
- " new " + tpnme.valueOf.decoded.capitalize + " (...)" ,
241
- fun.sourcePos,
242
- )
243
- case _ => None
245
+ def unapply (tree : Tree )(using params : InlayHintsParams , ctx : Context ) =
246
+ if (params.implicitParameters()) {
247
+ tree match
248
+ case Apply (ta @ TypeApply (fun, _), _)
249
+ if fun.span.isSynthetic && isValueOf(fun) =>
250
+ Some (
251
+ " new " + tpnme.valueOf.decoded.capitalize + " (...)" ,
252
+ fun.sourcePos,
253
+ )
254
+ case _ => None
255
+ } else None
244
256
private def isValueOf (tree : Tree )(using Context ) =
245
257
val symbol = tree.symbol.maybeOwner
246
258
symbol.name.decoded == tpnme.valueOf.decoded.capitalize
247
259
end ValueOf
248
260
249
261
object TypeParameters :
250
- def unapply (tree : Tree )(using Context ) =
251
- tree match
252
- case TypeApply (sel : Select , _) if sel.isForComprehensionMethod => None
253
- case TypeApply (fun, args) if inferredTypeArgs(args) =>
254
- val pos = fun match
255
- case sel : Select if sel.isInfix =>
256
- sel.sourcePos.withEnd(sel.nameSpan.end)
257
- case _ => fun.sourcePos
258
- val tpes = args.map(_.typeOpt.stripTypeVar.widen.finalResultType)
259
- Some ((tpes, pos.endPos, fun))
260
- case _ => None
262
+ def unapply (tree : Tree )(using params : InlayHintsParams , ctx : Context ) =
263
+ if (params.typeParameters()) {
264
+ tree match
265
+ case TypeApply (sel : Select , _)
266
+ if sel.isForComprehensionMethod || sel.isInfix ||
267
+ sel.symbol.name == nme.unapply =>
268
+ None
269
+ case TypeApply (fun, args) if inferredTypeArgs(args) =>
270
+ val tpes = args.map(_.tpe.stripTypeVar.widen.finalResultType)
271
+ Some ((tpes, fun.sourcePos.endPos, fun))
272
+ case _ => None
273
+ } else None
274
+
261
275
private def inferredTypeArgs (args : List [Tree ]): Boolean =
262
276
args.forall {
263
277
case tt : TypeTree if tt.span.exists && ! tt.span.isZeroExtent => true
@@ -270,29 +284,35 @@ object InferredType:
270
284
object Text :
271
285
def apply (text : Array [Char ]): Text = text
272
286
273
- def unapply (tree : Tree )(using text : Text , cxt : Context ) =
274
- tree match
275
- case vd @ ValDef (_, tpe, _)
276
- if isValidSpan(tpe.span, vd.nameSpan) &&
277
- ! vd.symbol.is(Flags .Enum ) &&
278
- ! isValDefBind(text, vd) =>
279
- if vd.symbol == vd.symbol.sourceSymbol then
280
- Some (tpe.typeOpt, tpe.sourcePos.withSpan(vd.nameSpan), vd)
281
- else None
282
- case vd @ DefDef (_, _, tpe, _)
283
- if isValidSpan(tpe.span, vd.nameSpan) &&
284
- tpe.span.start >= vd.nameSpan.end &&
285
- ! vd.symbol.isConstructor &&
286
- ! vd.symbol.is(Flags .Mutable ) =>
287
- if vd.symbol == vd.symbol.sourceSymbol then
288
- Some (tpe.typeOpt, tpe.sourcePos, vd)
289
- else None
290
- case bd @ Bind (
291
- name,
292
- Ident (nme.WILDCARD ),
293
- ) =>
294
- Some (bd.symbol.info, bd.namePos, bd)
295
- case _ => None
287
+ def unapply (tree : Tree )(using params : InlayHintsParams , text : Text , ctx : Context ) =
288
+ if (params.inferredTypes()) {
289
+ tree match
290
+ case vd @ ValDef (_, tpe, _)
291
+ if isValidSpan(tpe.span, vd.nameSpan) &&
292
+ ! vd.symbol.is(Flags .Enum ) &&
293
+ (isNotInUnapply(vd) || params.hintsInPatternMatch()) &&
294
+ ! isValDefBind(text, vd) =>
295
+ if vd.symbol == vd.symbol.sourceSymbol then
296
+ Some (tpe.tpe, tpe.sourcePos.withSpan(vd.nameSpan), vd)
297
+ else None
298
+ case vd @ DefDef (_, _, tpe, _)
299
+ if isValidSpan(tpe.span, vd.nameSpan) &&
300
+ tpe.span.start >= vd.nameSpan.end &&
301
+ ! vd.symbol.isConstructor &&
302
+ ! vd.symbol.is(Flags .Mutable ) =>
303
+ if vd.symbol == vd.symbol.sourceSymbol then
304
+ Some (tpe.tpe, tpe.sourcePos, vd)
305
+ else None
306
+ case bd @ Bind (
307
+ name,
308
+ Ident (nme.WILDCARD ),
309
+ ) if ! bd.span.isZeroExtent && bd.symbol.isTerm && params.hintsInPatternMatch() =>
310
+ Some (bd.symbol.info, bd.namePos, bd)
311
+ case _ => None
312
+ } else None
313
+
314
+ private def isNotInUnapply (vd : ValDef )(using Context ) =
315
+ vd.rhs.span.exists && vd.rhs.span.start > vd.nameSpan.end
296
316
297
317
private def isValidSpan (tpeSpan : Span , nameSpan : Span ): Boolean =
298
318
tpeSpan.isZeroExtent &&
0 commit comments