private def elementsForParameterInfo()

in scala/scala-impl/src/org/jetbrains/plugins/scala/lang/parameterInfo/ScalaFunctionParameterInfoHandler.scala [554:748]


  private def elementsForParameterInfo(args: Invocation): Seq[Object] = {
    implicit val project: ProjectContext = args.element.projectContext

    def elementsForConstructorInvocationParameterInfo(clazz: PsiClass,
                                                      subst: ScSubstitutor,
                                                      argumentLists: Seq[ScalaPsiElement],
                                                      maybeTypeArgs: Option[ScTypeArgs]): Seq[Object] = {
      val resultBuilder = ArraySeq.newBuilder[Object]
      val i = argumentLists.indexOf(args.element)

      clazz match {
        case constructorOwner: ScConstructorOwner =>
          constructorOwner.constructor match {
            case Some(constructor: ScPrimaryConstructor) if i < constructor.effectiveParameterClauses.length =>
              maybeTypeArgs match {
                case Some(typeArgs) =>
                  val substitutor = ScSubstitutor.bind(constructorOwner.typeParameters, typeArgs.typeArgs)(_.calcType)
                  resultBuilder += ((constructor, substitutor.followed(subst), i))
                case _ => resultBuilder += ((constructor, subst, i))
              }
            case Some(_) if i == 0 => resultBuilder += ""
            case None => resultBuilder += ""
            case _ =>
          }

          constructorOwner.functions.foreach { function =>
            if (function.isConstructor && function.clauses.fold(1)(_.clauses.length) > i) {
              resultBuilder += ((new PhysicalMethodSignature(function, subst), i))
            }
          }
        case annotation: PsiClass if annotation.annotationType =>
          val seq = annotation.getMethods.toSeq.collect {
            case method: PsiAnnotationMethod =>
              (method.name, method.getReturnType.toScType(), method.getDefaultValue)
          }
          resultBuilder += ((AnnotationParameters(seq), i))
        case psiClass: PsiClass if !psiClass.is[ScTypeDefinition] =>
          psiClass.getConstructors.foreach { constructor =>
            maybeTypeArgs match {
              case Some(typeArgs) =>
                val substitutor = ScSubstitutor.bind(psiClass.getTypeParameters, typeArgs.typeArgs)(_.calcType)
                val signature = new PhysicalMethodSignature(constructor, substitutor.followed(subst))
                resultBuilder += ((signature, i))
              case _ =>
                val signature = new PhysicalMethodSignature(constructor, subst)
                resultBuilder += ((signature, i))
            }
          }
        case _ =>
      }
      resultBuilder.result()
    }

    args.parent match {
      case UniversalApplyCall(UniversalApplyCallContext(constructor, substitutor, argumentLists, maybeTypeArgs)) =>
        val psiClass = constructor.containingClass
        elementsForConstructorInvocationParameterInfo(psiClass, substitutor, argumentLists, maybeTypeArgs)
      case constrInvocation: ScConstructorInvocation =>
        val typeElement = constrInvocation.typeElement
        typeElement.calcType.extractClassType match {
          case Some((psiClass: PsiClass, substitutor: ScSubstitutor)) =>
            val maybeTypeArgs = typeElement match {
              case gen: ScParameterizedTypeElement =>
                Some(gen.typeArgList)
              case _ => None
            }
            elementsForConstructorInvocationParameterInfo(psiClass, substitutor, constrInvocation.arguments, maybeTypeArgs)
          case _ => Seq.empty
        }
      case call@(_: MethodInvocation | _: ScReferenceExpression) =>
        val resultBuilder = ArraySeq.newBuilder[Object]
        def collectResult(): Unit = {
          val canBeUpdate = call.getParent match {
            case assignStmt: ScAssignment if call == assignStmt.leftExpression => true
            case notExpr if !notExpr.is[ScExpression] || notExpr.is[ScBlockExpr] => true
            case _ => false
          }
          val count = args.invocationCount
          val gen = args.callGeneric.getOrElse(null: ScGenericCall)
          def collectSubstitutor(element: PsiElement): ScSubstitutor = {
            if (gen == null) return ScSubstitutor.empty
            val typeParams = element match {
              case tpo: ScTypeParametersOwner => tpo.typeParameters.toArray
              case ptpo: PsiTypeParameterListOwner => ptpo.getTypeParameters
              case _ => return ScSubstitutor.empty
            }
            ScSubstitutor.bind(typeParams, gen.arguments)(_.calcType)
          }
          def collectForType(typez: ScType): Unit = {
            def process(functionName: String): Unit = {
              val i = if (functionName == "update") -1 else 0
              val processor: CompletionProcessor = new CompletionProcessor(StdKinds.refExprQualRef, call, withImplicitConversions = true) {

                override protected val forName: Option[String] = Some(functionName)
              }
              processor.processType(typez, call)
              val variants: Array[ScalaResolveResult] = processor.candidates
              for {
                variant <- variants
                if !variant.getElement.isInstanceOf[PsiMember] ||
                  ResolveUtils.isAccessible(variant.getElement.asInstanceOf[PsiMember], call)
              } {
                variant match {
                  case ScalaResolveResult(method: ScFunction, subst: ScSubstitutor) =>
                    val signature: PhysicalMethodSignature = new PhysicalMethodSignature(method, subst.followed(collectSubstitutor(method)))
                    resultBuilder += ((signature, i))
                    resultBuilder ++= ScalaParameterInfoEnhancer.enhance(signature, args.arguments).map((_, i))
                  case _ =>
                }
              }
            }

            process("apply")
            if (canBeUpdate) process("update")
          }
          args.callReference match {
            case Some(ref: ScReferenceExpression) =>
              if (count > 1) {
                //todo: missed case with last implicit call
                ref.bind() match {
                  case Some(ScalaResolveResult(function: ScFunction, subst: ScSubstitutor)) if function.
                    effectiveParameterClauses.length >= count =>
                    resultBuilder += ((new PhysicalMethodSignature(function, subst.followed(collectSubstitutor(function))), count - 1))
                  case Some(ScalaResolveResult(function: ScFunction, _)) if function.effectiveParameterClauses.isEmpty =>
                    function.`type`().foreach(collectForType)
                  case _ =>
                    call match {
                      case invocation: MethodInvocation =>
                        for (typez <- invocation.getEffectiveInvokedExpr.`type`()) //todo: implicit conversions
                        {collectForType(typez)}
                      case _ =>
                    }
                }
              } else {
                val variants = {
                  val sameName = ref.getSameNameVariants
                  if (sameName.isEmpty) ref.multiResolveScala(false)
                  else sameName
                }
                for {
                  variant <- variants
                  if !variant.getElement.isInstanceOf[PsiMember] ||
                    ResolveUtils.isAccessible(variant.getElement.asInstanceOf[PsiMember], ref)
                } {
                  variant match {
                    //todo: Synthetic function
                    case ScalaResolveResult(method: PsiMethod, subst: ScSubstitutor) =>
                      val signature: PhysicalMethodSignature = new PhysicalMethodSignature(method, subst.followed(collectSubstitutor(method)))
                      resultBuilder += ((signature, 0))
                      resultBuilder ++= ScalaParameterInfoEnhancer.enhance(signature, args.arguments).map((_, 0))
                    case ScalaResolveResult(typed: ScTypedDefinition, subst: ScSubstitutor) =>
                      val typez = subst(typed.`type`().getOrNothing) //todo: implicit conversions
                      collectForType(typez)
                    case _ =>
                  }
                }
              }
            case None =>
              call match {
                case call: ScMethodCall =>
                  for (typez <- call.getEffectiveInvokedExpr.`type`()) { //todo: implicit conversions
                    collectForType(typez)
                  }
              }
          }
        }
        collectResult()
        resultBuilder.result()
      case self: ScSelfInvocation =>
        val resultBuilder = ArraySeq.newBuilder[Object]
        val i = self.arguments.indexOf(args.element)

        self.parentOfType(classOf[ScClass]).foreach { clazz =>
          clazz.constructor match {
            case Some(constr: ScPrimaryConstructor) if i < constr.effectiveParameterClauses.length =>
              resultBuilder += ((constr, ScSubstitutor.empty, i))
            case Some(_) if i == 0 => resultBuilder += ""
            case None => resultBuilder += ""
            case _ =>
          }

          for {
            constr <- clazz.functions
            if constr.isConstructor &&
               constr.clauses.map(_.clauses.length).getOrElse(1) > i
          } {
            if (!PsiTreeUtil.isAncestor(constr, self, true) &&
              constr.getTextRange.getStartOffset < self.getTextRange.getStartOffset) {
              resultBuilder += ((new PhysicalMethodSignature(constr, ScSubstitutor.empty), i))
            }
          }
        }
        resultBuilder.result()
    }
  }