fun resolveS4GenericOrMethods()

in psi/src/com/intellij/r/psi/classes/s4/RS4Resolver.kt [76:118]


  fun resolveS4GenericOrMethods(element: PsiElement,
                                name: String,
                                result: MutableList<ResolveResult>,
                                globalSearchScope: GlobalSearchScope) {
    val call = element.parent as? RCallExpression ?: return
    RS4GenericIndex.findDefinitionsByName(name, element.project, globalSearchScope).map { generic ->
      val genericInfo = generic.associatedS4GenericInfo ?: return@map generic
      val argumentInfo = RArgumentInfo.getArgumentInfo(call.argumentList, genericInfo.signature.parameters)
      val types = argumentInfo.toS4MethodParameters(false)

      val methodName = generic.methodName ?: return@map generic
      val methodsWithDistance = RS4MethodsIndex.findDefinitionsByName(methodName, generic.project, globalSearchScope)
        .mapNotNull { def ->
          val info = def.associatedS4MethodInfo?.getParameters(globalSearchScope)
                       ?.sortedBy { it.name }
                       ?.takeIf { it.isNotEmpty() }
                     ?: return@mapNotNull null
          if (info.size != types.size || info.zip(types).any { (a, b) -> a.name != b.name }) return@mapNotNull null
          def to info.zip(types).map { (a, b) ->
            RS4ClassInfoUtil.lookupDistanceBetweenClasses(b.type, a.type, element.project, globalSearchScope)
          }
        }
      val anyDistance = methodsWithDistance.maxOfOrNull { methodWithDistance ->
        methodWithDistance.second.maxOfOrNull { if (it is RS4OrdDistance) it.distance else 0 } ?: 0
      } ?: 0 + 1
      methodsWithDistance.map { methodWithDistance ->
        methodWithDistance.first to methodWithDistance.second.sumOf {
          when (it) {
            RS4DistanceToANY -> anyDistance
            RS4InfDistance -> 100_000
            is RS4OrdDistance -> it.distance
          }
        }
      }.minByOrNull { it.second }?.first ?: generic
    }.forEach {
      val target = when (val methodNameIdentifier = it.methodNameIdentifier) {
        null -> it
        is RStringLiteralExpression -> RPomTarget.createStringLiteralTarget(methodNameIdentifier)
        else -> methodNameIdentifier
      }
      result.add(PsiElementResolveResult(target))
    }
  }