def processType()

in scala/scala-impl/src/org/jetbrains/plugins/scala/lang/resolve/processor/BaseProcessor.scala [142:317]


  def processType(
    t:                        ScType,
    place:                    PsiElement,
    state:                    ResolveState = ScalaResolveState.empty,
    updateWithProjectionType: Boolean      = true
  ): Boolean = processTypeImpl(t, place, state, updateWithProjectionType)(RecursionState.empty)

  private def processTypeImpl(
    t:                         ScType,
    place:                     PsiElement,
    state:                     ResolveState = ScalaResolveState.empty,
    updateWithProjectionSubst: Boolean = true
  )(implicit
    recState: RecursionState
  ): Boolean = {
    implicit val context: Context = Context(place)

    ProgressManager.checkCanceled()

    t match {
      case ScDesignatorType(clazz: PsiClass) if clazz.qualifiedName == "java.lang.String" =>
        val plusMethod: ScType => ScSyntheticFunction = SyntheticClasses.get(place.getProject).stringPlusMethod
        if (plusMethod != null) execute(plusMethod(t), state) //add + method
      case _ =>
    }

    if (place.isInScala3File && kinds.contains(ResolveTargets.METHOD)) {
      if (!processSelectable(t, place, state, execute)) {
        return false
      }
    }

    t match {
      case ScThisType(clazz) =>
        clazz.selfType match {
          case None =>
            processElement(clazz, ScSubstitutor.empty, place, state)
          case Some(ScThisType(`clazz`)) =>
            //to prevent SOE, let's process Element
            processElement(clazz, ScSubstitutor.empty, place, state)
          case Some(ScProjectionType(_, element)) if recState.visitedProjections.contains(element) =>
            //recursion detected
            true
          case Some(selfType) =>
            val clazzType = clazz.getTypeWithProjections().getOrElse(return true)

            if (selfType.conforms(clazzType)) {
              val newState =
                state
                  .withCompoundOrSelfType(t)
                  .withSubstitutor(ScSubstitutor(ScThisType(clazz)))

              processTypeImpl(selfType, place, newState)
            } else if (clazzType.conforms(selfType)) {
              processElement(clazz, ScSubstitutor.empty, place, state)
            } else {
              //@TODO: temporary fix, should be removed once lub/glb is implemented in a version specific manner
              val glb =
                if (place.isInScala3File) ScAndType(clazzType, selfType)
                else                      selfType.glb(clazzType)

              val newState = state.withCompoundOrSelfType(t)
              processTypeImpl(glb, place, newState)
            }
        }
      case d@ScDesignatorType(e: PsiClass) if d.isStatic && !e.is[ScTemplateDefinition] =>
        //not scala from scala
        var break = true
        for (method <- e.getMethods if break && method.hasModifierProperty("static")) {
          if (!execute(method, state)) break = false
        }
        for (cl <- e.getInnerClasses if break && cl.hasModifierProperty("static")) {
          if (!execute(cl, state)) break = false
        }
        for (field <- e.getFields if break && field.hasModifierProperty("static")) {
          if (!execute(field, state)) break = false
        }
        if (!break) return false
        processEnum(e, execute(_, state))
      case ScDesignatorType(o: ScObject) =>
        processElement(o, ScSubstitutor.empty, place, state)
      case ScDesignatorType(e: ScTypedDefinition) if place.is[ScTypeProjection] =>
        val result: TypeResult =
          e match {
            case p: ScParameter => p.insideParamType
            case _ => e.`type`()
          }
        result match {
          case Right(tp) => processTypeImpl(tp, place, state)
          case _ => true
        }
      case ScDesignatorType(e)    => processElement(e, ScSubstitutor.empty, place, state)
      case tpt: TypeParameterType => processTypeImpl(tpt.upperType, place, state, updateWithProjectionSubst = false)
      case j: JavaArrayType =>
        implicit val elementScope: ElementScope = place.elementScope
        processTypeImpl(j.getParameterizedType.getOrElse(return true), place, state)
      case p@ParameterizedType(designator, typeArgs) =>
        val cont = designator match {
          case tpt: TypeParameterType =>
            if (recState.visitedTypeParameter.contains(tpt)) return true
            val newState = state.withSubstitutor(ScSubstitutor(p))
            val upper    = tpt.upperType

            val substedType =
              if (upper.isAny || upper.isAnyRef) upper
              else                               p.substitutor(ParameterizedType(tpt.upperType, typeArgs))

            processTypeImpl(substedType, place, newState)(recState.add(tpt))
          case _ =>
            p.extractDesignatedType(expandAliases = false) match {
              case Some((des, subst)) =>
                processElement(des, subst, place, state)
              case None =>
                true
            }
        }

        cont && processNamedTuple(p, state, execute) && processScala3Tuple(p, execute(_, state))
      case proj: ScProjectionType =>
        val withActual = new ScProjectionType.withActual(updateWithProjectionSubst)

        proj match {
          case withActual(elem, s) =>
            if (recState.visitedProjections.contains(elem))
              return true

            elem match {
              case alias: ScTypeAlias =>
                val upper = alias.upperBound.getOrElse(return true)
                processTypeImpl(s(upper), place, state.withSubstitutor(ScSubstitutor.empty))(recState.add(alias))
              case elem =>
                val subst =
                  if (updateWithProjectionSubst) ScSubstitutor(proj) followed s
                  else                           s

                processElement(elem, subst, place, state)(recState.add(elem))
            }
        }
      case lit: ScLiteralType => processType(lit.wideType, place, state, updateWithProjectionSubst)
      case StdType(name, tSuper) =>
        SyntheticClasses.get(place.getProject).byName(name) match {
          case Some(c) =>
            if (!c.processDeclarations(this, state, null, place) ||
              !(tSuper match {
                case Some(ts) => processTypeImpl(ts, place)
                case _ => true
              })) return false
          case None => //nothing to do
        }

        val scope = place.resolveScope
        val obj: PsiClass = ScalaPsiManager.instance(place.getProject).getCachedClass(scope, "java.lang.Object").orNull
        if (obj != null) {
          val namesSet = Set("hashCode", "toString", "equals", "getClass")
          val methods = obj.getMethods.iterator
          while (methods.hasNext) {
            val method = methods.next()
            if (name == "AnyRef" || namesSet.contains(method.name)) {
              if (!execute(method, state)) return false
            }
          }
        }
        true
      case comp: ScCompoundType   => processDeclarations(comp, this, state, null, place)
      case and: ScAndType         => processDeclarations(and, this, state, null, place)
      case or: ScOrType           => processTypeImpl(or.join, place, state, updateWithProjectionSubst)
      case matchType: ScMatchType =>
        val redex = matchType.reduce.getOrElse(matchType.upperBound.getOrElse(Any))
        processTypeImpl(redex, place, state)
      case ex: ScExistentialType  =>
        processTypeImpl(ex.quantified, place, state.withSubstitutor(ScSubstitutor.empty))
      case ScExistentialArgument(_, _, _, upper) =>
        processTypeImpl(upper, place, state)
      case _ => true
    }
  }