@@ -7,11 +7,10 @@ import java.lang.ref.WeakReference
7
7
import com .intellij .codeInsight .PsiEquivalenceUtil
8
8
import com .intellij .lang .java .JavaLanguage
9
9
import com .intellij .openapi .diagnostic .Logger
10
- import com .intellij .openapi .module .{JavaModuleType , ModuleUtil , ModuleUtilCore , Module }
10
+ import com .intellij .openapi .module .{JavaModuleType , Module , ModuleUtil }
11
11
import com .intellij .openapi .progress .ProgressManager
12
12
import com .intellij .openapi .project .Project
13
13
import com .intellij .openapi .roots .{ProjectFileIndex , ProjectRootManager }
14
- import com .intellij .openapi .updateSettings .impl .pluginsAdvertisement .PluginsAdvertiser .Plugin
15
14
import com .intellij .openapi .util .TextRange
16
15
import com .intellij .psi ._
17
16
import com .intellij .psi .codeStyle .CodeStyleSettingsManager
@@ -61,7 +60,7 @@ import org.jetbrains.plugins.scala.lang.resolve.{ResolvableReferenceExpression,
61
60
import org .jetbrains .plugins .scala .lang .structureView .ScalaElementPresentation
62
61
import org .jetbrains .plugins .scala .project .ScalaLanguageLevel .Scala_2_11
63
62
import org .jetbrains .plugins .scala .project .settings .ScalaCompilerConfiguration
64
- import org .jetbrains .plugins .scala .project .{Version , ModuleExt , ProjectPsiElementExt }
63
+ import org .jetbrains .plugins .scala .project .{ModuleExt , ProjectPsiElementExt }
65
64
import org .jetbrains .plugins .scala .settings .ScalaProjectSettings
66
65
import org .jetbrains .plugins .scala .util .ScEquivalenceUtil
67
66
@@ -2316,7 +2315,7 @@ object ScalaPsiUtil {
2316
2315
* @see SCL-6140
2317
2316
* @see https://github.com/scala/scala/pull/3018/
2318
2317
*/
2319
- def toSAMType (expected : ScType , scope : GlobalSearchScope ): Option [ScType ] = {
2318
+ def toSAMType (expected : ScType , scalaScope : GlobalSearchScope ): Option [ScType ] = {
2320
2319
2321
2320
def constructorValidForSAM (constructors : Array [PsiMethod ]): Boolean = {
2322
2321
// primary constructor (if any) must be public, no-args, not overloaded
@@ -2346,8 +2345,14 @@ object ScalaPsiUtil {
2346
2345
! abst.head.hasTypeParameters
2347
2346
2348
2347
if (valid) {
2349
- abst.head.getType() match {
2350
- case Success (tp, _) => Some (sub.subst(tp))
2348
+ val fun = abst.head
2349
+ fun.getType() match {
2350
+ case Success (tp, _) =>
2351
+ val subbed = sub.subst(tp)
2352
+ extrapolateWildcardBounds(subbed, expected, fun.getProject, scalaScope) match {
2353
+ case s@ Some (_) => s
2354
+ case _ => Some (subbed)
2355
+ }
2351
2356
case _ => None
2352
2357
}
2353
2358
} else None
@@ -2359,15 +2364,63 @@ object ScalaPsiUtil {
2359
2364
// need to generate ScType for Java method
2360
2365
val method = abst.head
2361
2366
val project = method.getProject
2362
- val returnType : ScType = ScType .create(method.getReturnType, project, scope )
2367
+ val returnType : ScType = ScType .create(method.getReturnType, project, scalaScope )
2363
2368
val params : Array [ScType ] = method.getParameterList.getParameters.map {
2364
- param : PsiParameter => ScType .create(param.getTypeElement.getType, project, scope)
2369
+ param : PsiParameter => ScType .create(param.getTypeElement.getType, project, scalaScope)
2370
+ }
2371
+ val fun = ScFunctionType (returnType, params)(project, scalaScope)
2372
+ val subbed = sub.subst(fun)
2373
+ extrapolateWildcardBounds(subbed, expected, project, scalaScope) match {
2374
+ case s@ Some (_) => s
2375
+ case _ => Some (subbed)
2365
2376
}
2366
- val result = ScFunctionType (returnType, params)(project, scope)
2367
- Some (sub.subst(result))
2368
2377
} else None
2369
2378
}
2370
2379
case None => None
2371
2380
}
2372
2381
}
2382
+
2383
+ /**
2384
+ * In some cases existential bounds can be simplified without losing precision
2385
+ *
2386
+ * trait Comparinator[T] { def compare(a: T, b: T): Int }
2387
+ *
2388
+ * trait Test {
2389
+ * def foo(a: Comparinator[_ >: String]): Int
2390
+ * }
2391
+ *
2392
+ * can be simplified to:
2393
+ *
2394
+ * trait Test {
2395
+ * def foo(a: Comparinator[String]): Int
2396
+ * }
2397
+ *
2398
+ * @see https://github.com/scala/scala/pull/4101
2399
+ * @see SCL-8956
2400
+ */
2401
+ private def extrapolateWildcardBounds (tp : ScType , expected : ScType , proj : Project , scope : GlobalSearchScope ): Option [ScType ] = {
2402
+ expected match {
2403
+ case ScExistentialType (ScParameterizedType (expectedDesignator, _), wildcards) =>
2404
+ tp match {
2405
+ case ScFunctionType (retTp, params) =>
2406
+ def convertParameter (tpArg : ScType , variance : Int ): ScType = {
2407
+ wildcards.find(_.name == tpArg.canonicalText) match {
2408
+ case Some (wildcard) =>
2409
+ (wildcard.lowerBound, wildcard.upperBound) match {
2410
+ case (lo, Any ) if variance == ScTypeParam .Contravariant => lo
2411
+ case (Nothing , hi) if variance == ScTypeParam .Covariant => hi
2412
+ case _ => tpArg
2413
+ }
2414
+ case _ => tpArg
2415
+ }
2416
+ }
2417
+ // parameter clauses are contravariant positions, return types are covariant positions
2418
+ val newParams = params.map(convertParameter(_, ScTypeParam .Contravariant ))
2419
+ val newRetTp = convertParameter(retTp, ScTypeParam .Covariant )
2420
+ Some (ScFunctionType (newRetTp, newParams)(proj, scope))
2421
+ case _ => None
2422
+ }
2423
+ case _ => None
2424
+ }
2425
+ }
2373
2426
}
0 commit comments