private def makeUParentAndPin[U <: UElement]()

in scala/uast/src/org/jetbrains/plugins/scala/lang/psi/uast/converter/Scala2UastConverter.scala [76:337]


  private def makeUParentAndPin[U <: UElement](sourcePsi: PsiElement,
                                               converted: Free[U]): U =
    converted.pinTo(
      LazyUElement.fromThunk(() => makeUParent(sourcePsi, converted).orNull)
    )

  private def convertToFree[U <: UElement: ClassTag: NotNothing](
    sourcePsi: PsiElement,
    convertLambdas: Boolean = true
  ): Option[Free[U]] = {
    import ConverterUtils._

    val requiredType = implicitly[ClassTag[U]].runtimeClass.asInstanceOf[Class[U]]

    //performance optimization
    if (!isUnitTestMode && !isPossibleToConvert(requiredType, sourcePsi)) {
      return None
    }

    //noinspection GetOrElseNull,ConvertibleToMethodValue
    val elementOpt: Option[Free[UElement]] =
      Option((sourcePsi match {

        // ========================= DECLARATIONS ===============================

        case file: ScalaFile =>
          (_: LazyUElement) =>
            new ScUFile(
              file,
              UastFacade.INSTANCE.findPlugin(file).asInstanceOf[ScalaUastLanguagePlugin]
            )
        case e: ScImportStmt => new ScUImportStatement(e, _)

        case e: ScTypeDefinition            => new ScUClass(e, _)
        case ScUVariable(parent2UField)     => parent2UField(_)
        case e: ScMethodLike if !e.isLocal  => new ScUMethod(e, _)
        case e: ScPrimaryConstructorWrapper => new ScUMethod(e.delegate, _)
        case e: ScFunctionWrapper           => new ScUMethod(e.delegate, _)
        case e: ScParameter                 => new ScUParameter(e, _)
        case e: ScValueOrVariable           => new ScUValOrVarDeclarationsExpression(e, _)

        case e: ScFunctionDefinition if e.isLocal =>
          new ScULocalFunctionDeclarationExpression(e, _)

        //Handle case with anonymous class: new SomeClass() { ... }
        //NOTE: we attach `ScUAnonymousClass` UAST element to `ScExtendsBlock` PSI element and not to `ScTemplateBody` because here:
        //com.intellij.codeInspection.NonExtendableApiUsageInspection.NonExtendableApiUsageProcessor.processReference
        //it's assumed that `USimpleNameReferenceExpression` (representing `SomeClass` identifier) will have UClass as it's parent
        case eb: ScExtendsBlock if eb.isAnonymousClass =>
          //noinspection ScalaUnusedSymbol
          (for {
            nt @ (td: ScNewTemplateDefinition) <- Option(eb.getParent)
          } yield new ScUAnonymousClass(nt, eb, _: LazyUElement)).orNull

        case e: ScNewTemplateDefinition if e.extendsBlock.isAnonymousClass =>
          new ScUObjectLiteralExpression(e, _)

        case constructorInvocation: ScConstructorInvocation =>
          val isAnnotationConstructorCall = constructorInvocation.getParent.is[ScAnnotationExpr]
          if (isAnnotationConstructorCall)
            null
          else
            new ScUConstructorCallExpression(constructorInvocation, _)

        case e: ScAnnotation =>
          new ScUAnnotation(e, _)

        // ========================= LAMBDAS ====================================

        case lambdaExpr: ScFunctionExpr =>
          new ScULambdaExpression(lambdaExpr, _)

        case block: ScBlock if block.isPartialFunction =>
          new ScUPartialLambdaExpression(block, _)

        case us: ScUnderscoreSection if us.bindingExpr.collect {
              case ScReference(_: PsiMethod) =>
            }.isDefined =>
          us.bindingExpr match {
            case Some(binding: ScReference) =>
              new ScUCallableReferenceExpression(binding, _)
            case _ => null
          }

        case us: ScExpression if isUnderscoreFunction(us) && convertLambdas =>
          new ScUUnderscoreLambdaExpression(us, _)

        case mv: ScExpression if isMethodValue(mv, convertLambdas) =>
          mv match {
            case ref: ScReference =>
              new ScUCallableReferenceExpression(ref, _)
            case _ => new ScUMethodValueLambdaExpression(mv, _)
          }

        // ========================= CONTROL STRUCTURES =========================

        case e: ScIf     => new ScUIfExpression(e, _)
        case e: ScWhile  => new ScUWhileExpression(e, _)
        case e: ScDo     => new ScUDoWhileExpression(e, _)
        case e: ScTry    => new ScUTryExpression(e, _)
        case e: ScThrow  => new ScUThrowExpression(e, _)
        case e: ScReturn => new ScUReturnExpression(e, _)
        case e: ScMatch  => new ScUSwitchExpression(e, _)
        case e: ScCaseClauses =>
          e.getParent match {
            case bl: ScBlock if bl.isInCatchBlock => null
            case _                                => new ScUCaseClausesList(e, _)
          }
        case e: ScCaseClause =>
          if (isInsideCatchBlock(e)) new ScUCatchExpression(e, _)
          else new ScUCaseClause(e, _)
        case e: ScBlock if e.getParent.is[ScCaseClause] =>
          e.getParent match {
            case clause: ScCaseClause if !isInsideCatchBlock(clause) =>
              new ScUCaseClauseBodyList(e, _)
            case _ => new ScUBlockExpression(e, _)
          }

        // ========================= EXPRESSION GROUPS ==========================

        case e: ScInfixExpr   if requiredType != classOf[UCallExpression] => new ScUBinaryExpression(e, _)
        case e: ScPostfixExpr if requiredType != classOf[UCallExpression] => new ScUPostfixExpression(e, _)

        case e: ScBlock             => new ScUBlockExpression(e, _)
        case e: ScTypedExpression   => new ScUBinaryExpressionWithType(e, _)
        case e: ScPrefixExpr        => new ScUPrefixExpression(e, _)
        case e: ScParenthesisedExpr => new ScUParenthesizedExpression(e, _)
        case e: ScAssignment =>
          if (e.isNamedParameter) new ScUNamedExpression(e, _)
          else new ScUAssignment(e, _)

        // ======================== CALLS =======================================

        //region Special section that converts PSI call elements to
        // UAST call expressions if the required type is a call expression.
        // Otherwise PSI visitor won't be able to find some UAST calls
        // because they will be converted to UQualifiedExpression's
        case e: ScMethodCall if requiredType == classOf[UCallExpression] =>
          new ScUMethodCallExpression(e, _)

        case e: ScGenericCall
            if !e.getParent.is[ScMethodCall] &&
              requiredType == classOf[UCallExpression] =>
          new ScUGenericCallExpression(e, _)

        case p@ScPostfixExpr(_, ref@ScReferenceExpression(_: PsiMethod | _: ScSyntheticFunction)) if ref.qualifier.isEmpty && requiredType == classOf[UCallExpression] =>
          new ScUPostfixExpressionCall(p, _)

        case i@ScInfixExpr(_, ref@ScReferenceExpression(_: PsiMethod | _: ScSyntheticFunction), _) if ref.qualifier.isEmpty && requiredType == classOf[UCallExpression] =>
          new ScUBinaryExpressionCall(i, _)

        case funRef: ScReferenceExpression
            if !funRef.getParent.is[ScMethodCall, ScGenericCall] &&
              requiredType == classOf[UCallExpression] &&
              funRef.resolve().is[PsiMethod, ScSyntheticFunction] =>
          functionReferenceCall(funRef, _)
        //endregion

        case e: ScNewTemplateDefinition =>
          //noinspection ScalaUnnecessaryParentheses
          e.firstConstructorInvocation
            .map(c => new ScUConstructorCallExpression(c, _: LazyUElement))
            .getOrElse(null)

        case e: ScMethodCall =>
          /** NOTE: see related code in [[org.jetbrains.plugins.scala.lang.psi.uast.expressions.ScUQualifiedReferenceExpression.getExpressionType]] */
          e.getInvokedExpr match {
            case ref: ScReferenceExpression if ref.isQualified =>
              new ScUQualifiedReferenceExpression(ref, sourcePsi = e, _)
            case gc: ScGenericCall =>
              gc.referencedExpr match {
                case ref: ScReferenceExpression if ref.isQualified =>
                  new ScUQualifiedReferenceExpression(ref, sourcePsi = e, _)
                case _ =>
                  new ScUMethodCallExpression(e, _)
              }
            case _ => new ScUMethodCallExpression(e, _)
          }

        case e: ScGenericCall if !e.getParent.is[ScMethodCall] =>
          e.referencedExpr match {
            case ref: ScReferenceExpression if ref.isQualified =>
              new ScUQualifiedReferenceExpression(ref, sourcePsi = e, _)
            case _ =>
              new ScUGenericCallExpression(e, _)
          }

        // ========================= REFERENCES =================================

        case e: ScReferenceExpression if e.isQualified =>
          e.getParent match {
            case mc: ScMethodCall =>
              new ScUQualifiedReferenceExpression(e, sourcePsi = mc, _)
            case gc: ScGenericCall =>
              gc.getParent match {
                case mc: ScMethodCall =>
                  new ScUQualifiedReferenceExpression(e, sourcePsi = mc, _)
                case _ =>
                  new ScUQualifiedReferenceExpression(e, sourcePsi = gc, _)
              }
            case _ =>
              new ScUQualifiedReferenceExpression(e, _)
          }

        case funRef: ScReferenceExpression
          if !funRef.getParent.is[ScMethodCall, ScGenericCall, ScUnderscoreSection] &&
            funRef.resolve().is[PsiMethod, ScSyntheticFunction] =>
          functionReferenceCall(funRef, _)

        case ref @ ScUReferenceExpression(parent2ScURef) if !ref.isInstanceOf[ScTypeElement] =>
          parent2ScURef(_)

        case e: ScExistentialTypeElement =>
          // Unsupported element type.
          // Needs to be ordered before ScTypeElement because ScExistentialTypeElement <: ScTypeElement.
          new UnknownScalaElement(e, _)

        case e: ScTypeElement if e.getFirstChild.is[ScReference] =>
          new ScUTypeReferenceExpression(
            e.getFirstChild.asInstanceOf[ScReference],
            typeProvider = Some(e),
            sourcePsi = e,
            _
          )
        case e: ScThisReference  => new ScUThisExpression(e, _)
        case e: ScSuperReference => new ScUSuperExpression(e, _)

        // ========================= LEAF ELEMENTS ==============================

        case e: ScLiteral => ScULiteral(e, _)
        case e: ScUnderscoreSection if e.bindingExpr.isEmpty =>
          new ScUUnderscoreExpression(e, _)

        /**
          * Some 3-rd party UAST based inspections try to
          * convert [[LeafPsiElement]] representing identifier to [[UIdentifier]]
          */
        case e: LeafPsiElement
            if e.getElementType == ScalaTokenTypes.tIDENTIFIER =>
          (_: LazyUElement) =>
            new LazyAnyUParentUIdentifier(e)

        // ========================= UNSUPPORTED ================================

        case e: ScFor                    => new ScUEmptyExpressionWithGivenType(e, _)
        case _                           => null
      }): LazyUElement => UElement)
        .map(Free.fromLazyConstructor[UElement](_))

    elementOpt.flatMap { element =>
      element.standalone match {
        case standalone: U =>

          if (isUnitTestMode && !possibleSourceTypesCheckIsActive && !isPossibleToConvert(requiredType, sourcePsi)) {
            throw new AssertionError(s"${requiredType.getName} is not expected from ${sourcePsi.getClass.getName}, got ${standalone.getClass.getName}")
          }

          Some(element.asInstanceOf[Free[U]])
        case _ => None
      }
    }
  }