@@ -23,6 +23,7 @@ package com.demonwav.mcdev.util
23
23
import com.demonwav.mcdev.facet.MinecraftFacet
24
24
import com.demonwav.mcdev.platform.mcp.McpModule
25
25
import com.demonwav.mcdev.platform.mcp.McpModuleType
26
+ import com.demonwav.mcdev.platform.mixin.handlers.desugar.DesugarUtil
26
27
import com.intellij.codeInsight.lookup.LookupElementBuilder
27
28
import com.intellij.debugger.impl.DebuggerUtilsEx
28
29
import com.intellij.ide.highlighter.JavaClassFileType
@@ -42,16 +43,21 @@ import com.intellij.openapi.util.text.StringUtil
42
43
import com.intellij.psi.ElementManipulator
43
44
import com.intellij.psi.ElementManipulators
44
45
import com.intellij.psi.JavaPsiFacade
46
+ import com.intellij.psi.LambdaUtil
45
47
import com.intellij.psi.PsiAnnotation
48
+ import com.intellij.psi.PsiArrayType
46
49
import com.intellij.psi.PsiClass
50
+ import com.intellij.psi.PsiClassType
47
51
import com.intellij.psi.PsiDirectory
52
+ import com.intellij.psi.PsiDisjunctionType
48
53
import com.intellij.psi.PsiDocumentManager
49
54
import com.intellij.psi.PsiElement
50
55
import com.intellij.psi.PsiElementFactory
51
56
import com.intellij.psi.PsiElementResolveResult
52
57
import com.intellij.psi.PsiEllipsisType
53
58
import com.intellij.psi.PsiExpression
54
59
import com.intellij.psi.PsiFile
60
+ import com.intellij.psi.PsiIntersectionType
55
61
import com.intellij.psi.PsiKeyword
56
62
import com.intellij.psi.PsiLanguageInjectionHost
57
63
import com.intellij.psi.PsiManager
@@ -67,7 +73,10 @@ import com.intellij.psi.PsiParameterList
67
73
import com.intellij.psi.PsiPrimitiveType
68
74
import com.intellij.psi.PsiReference
69
75
import com.intellij.psi.PsiReferenceExpression
76
+ import com.intellij.psi.PsiSuperExpression
70
77
import com.intellij.psi.PsiType
78
+ import com.intellij.psi.PsiTypeElement
79
+ import com.intellij.psi.PsiTypeParameter
71
80
import com.intellij.psi.ResolveResult
72
81
import com.intellij.psi.filters.ElementFilter
73
82
import com.intellij.psi.search.GlobalSearchScope
@@ -76,6 +85,7 @@ import com.intellij.psi.util.CachedValueProvider
76
85
import com.intellij.psi.util.CachedValuesManager
77
86
import com.intellij.psi.util.PsiTreeUtil
78
87
import com.intellij.psi.util.PsiTypesUtil
88
+ import com.intellij.psi.util.PsiUtil
79
89
import com.intellij.psi.util.TypeConversionUtil
80
90
import com.intellij.psi.util.parentOfType
81
91
import com.intellij.refactoring.changeSignature.ChangeSignatureUtil
@@ -371,20 +381,103 @@ val PsiElement.mcVersion: SemanticVersion?
371
381
}
372
382
}
373
383
374
- @Suppress(" PrivatePropertyName" )
375
384
private val REAL_NAME_KEY = Key <String >(" mcdev.real_name" )
376
385
377
386
var PsiMember .realName: String?
378
387
get() = getUserData(REAL_NAME_KEY )
379
388
set(value) = putUserData(REAL_NAME_KEY , value)
380
389
381
- val PsiMethodReferenceExpression .hasSyntheticMethod: Boolean
390
+ // see com.sun.tools.javac.comp.TransTypes.needsConversionToLambda
391
+ fun PsiMethodReferenceExpression.hasSyntheticMethod (classVersion : Int ): Boolean {
392
+ val qualifier = this .qualifier ? : return true
393
+
394
+ if (qualifier is PsiTypeElement && qualifier.type is PsiArrayType ) {
395
+ return true
396
+ }
397
+
398
+ if (qualifier is PsiSuperExpression ) {
399
+ return true
400
+ }
401
+
402
+ val referencedClass = when (qualifier) {
403
+ is PsiTypeElement -> (qualifier.type as ? PsiClassType )?.resolve()
404
+ is PsiReferenceExpression -> qualifier.resolve() as ? PsiClass
405
+ else -> null
406
+ }
407
+
408
+ if (isConstructor) {
409
+ if (referencedClass?.containingClass != null && ! referencedClass.hasModifierProperty(PsiModifier .STATIC )) {
410
+ return true
411
+ }
412
+ if (referencedClass != null && PsiUtil .isLocalOrAnonymousClass(referencedClass)) {
413
+ return true
414
+ }
415
+ }
416
+
417
+ if (isVarArgsCall) {
418
+ return true
419
+ }
420
+
421
+ if (DesugarUtil .needsBridgeMethod(this , classVersion)) {
422
+ return true
423
+ }
424
+
425
+ // even if a bridge method isn't required, if the method is protected in a different package, a synthetic method is
426
+ // still required, because otherwise the synthetic class that LambdaMetafactory creates won't be able to access it
427
+ val resolved = resolve() ? : return true
428
+ when (resolved) {
429
+ is PsiClass -> return ! isConstructor
430
+ !is PsiMethod -> return true
431
+ }
432
+ if (resolved.hasModifierProperty(PsiModifier .PROTECTED ) && findContainingClass()?.packageName != referencedClass?.packageName) {
433
+ return true
434
+ }
435
+
436
+ val functionalInterfaceType = this .functionalInterfaceType ? : return true
437
+ val interfaceMethod = LambdaUtil .getFunctionalInterfaceMethod(functionalInterfaceType) ? : return true
438
+
439
+ return interfaceMethod.parameterList.parameters.any { param ->
440
+ var paramType = param.type
441
+ while (paramType is PsiClassType ) {
442
+ val resolved = paramType.resolve()
443
+ if (resolved is PsiTypeParameter ) {
444
+ val extendsList = resolved.extendsList.referencedTypes
445
+ when (extendsList.size) {
446
+ 0 -> break
447
+ 1 -> paramType = extendsList.single()
448
+ else -> return @any true
449
+ }
450
+ }
451
+ }
452
+ paramType is PsiIntersectionType || paramType is PsiDisjunctionType
453
+ }
454
+ }
455
+
456
+ private val PsiMethodReferenceExpression .isVarArgsCall: Boolean
382
457
get() {
383
- // the only method reference that doesn't have a synthetic method is a direct reference to a method
384
- if (referenceName == " new" ) return true
385
- val qualifier = this .qualifier
386
- if (qualifier !is PsiReferenceExpression ) return true
387
- return qualifier.resolve() !is PsiClass
458
+ val resolveResult = advancedResolve(false )
459
+ val resolvedMethod = resolveResult.element as ? PsiMethod ? : return false
460
+ if (! resolvedMethod.isVarArgs) {
461
+ return false
462
+ }
463
+
464
+ val functionalInterfaceType = this .functionalInterfaceType ? : return true
465
+ val functionalResolveResult = PsiUtil .resolveGenericsClassInType(functionalInterfaceType)
466
+ val interfaceMethod = LambdaUtil .getFunctionalInterfaceMethod(functionalResolveResult) ? : return true
467
+
468
+ val interfaceSignature = interfaceMethod.getSignature(LambdaUtil .getSubstitutor(interfaceMethod, functionalResolveResult))
469
+ val interfaceParamTypes = interfaceSignature.parameterTypes
470
+
471
+ val resolvedParams = resolvedMethod.parameterList.parameters
472
+ val isStatic = resolvedMethod.hasModifierProperty(PsiModifier .STATIC )
473
+ val effectiveNumParams = if (isStatic) resolvedParams.size else resolvedParams.size + 1
474
+ if (effectiveNumParams != interfaceParamTypes.size) {
475
+ return true
476
+ }
477
+
478
+ val varArgsType = resolvedParams.lastOrNull()?.type as ? PsiEllipsisType ? : return true
479
+ val arrayType = resolveResult.substitutor.substitute(varArgsType.toArrayType())
480
+ return ! arrayType.isAssignableFrom(interfaceParamTypes.last())
388
481
}
389
482
390
483
val PsiClass .psiType: PsiType
0 commit comments