private def convertPsiToIntermediate()

in scala/conversion/src/org/jetbrains/plugins/scala/conversion/JavaToScala.scala [146:618]


  private def convertPsiToIntermediate(
    element: PsiElement,
    externalProperties: ExternalProperties
  )(implicit conversionContext: ConversionContext): IntermediateNode = {
    if (element == null || conversionContext.dropElements.contains(element))
      return EmptyConstruction()
    if (element.getLanguage != JavaLanguage.INSTANCE)
      return EmptyConstruction()

    //NOTE: we need to calculate the comments before calculating IntermediateNode result
    //because some comments can be attached to different nodes and we would like them to occur in the most top-level parent nodes
    val comments = CommentsCollector.allCommentsForElement(element)(conversionContext.usedComments)

    val result: IntermediateNode = element match {
      case f: PsiFile =>
        val children = f.getChildren.map(convertPsiToIntermediate(_, externalProperties)).toSeq
        MainConstruction(children)
      case unnamedClass: PsiImplicitClass =>
        val children = unnamedClass.getChildren.map(convertPsiToIntermediate(_, externalProperties)).toSeq
        MainConstruction(children)
      case e: PsiExpressionStatement => convertPsiToIntermediate(e.getExpression, externalProperties)
      case l: PsiLiteralExpression => LiteralExpression(l.getText)
      case n: PsiIdentifier =>
        convertToIdentifier(n)
      case t: PsiTypeElement =>
        convertTypePsiToIntermediate(t)
      case w: PsiWhiteSpace => LiteralExpression(w.getText)
      case r: PsiReturnStatement => ReturnStatement(convertPsiToIntermediate(r.getReturnValue, externalProperties))
      case t: PsiThrowStatement => ThrowStatement(convertPsiToIntermediate(t.getException, externalProperties))
      case i: PsiImportStatement => handleImport(i)
      case i: PsiImportStaticStatement => handleImport(i)
      case i: PsiImportList => ImportStatementList(i.getAllImportStatements.map(handleImport).distinct.toIndexedSeq)
      case a: PsiAssignmentExpression =>
        BinaryExpressionConstruction(convertPsiToIntermediate(a.getLExpression, externalProperties),
          convertPsiToIntermediate(a.getRExpression, externalProperties), a.getOperationSign.getText, inExpression = false)
      case e: PsiExpressionListStatement =>
        ExpressionListStatement(e.getExpressionList.getExpressions.map(convertPsiToIntermediate(_, externalProperties)).toIndexedSeq)
      case d: PsiDeclarationStatement => ExpressionListStatement(d.getDeclaredElements.map(convertPsiToIntermediate(_, externalProperties)).toIndexedSeq)
      case b: PsiBlockStatement =>
        convertToBlockConstruction(b.getCodeBlock, externalProperties)
      case s: PsiSynchronizedStatement =>
        val lock = Option(s.getLockExpression).map(convertPsiToIntermediate(_, externalProperties))
        val body = Option(s.getBody).map(convertPsiToIntermediate(_, externalProperties))
        SynchronizedStatement(lock, body)
      case b: PsiCodeBlock =>
        convertToBlockConstruction(b, externalProperties)
      case t: PsiTypeParameter =>
        convertToTypeParameterConstruction(t, externalProperties)
      case i: PsiIfStatement =>
        val condition = Option(i.getCondition).map(convertPsiToIntermediate(_, externalProperties))
        val thenBranch = Option(i.getThenBranch).map(convertPsiToIntermediate(_, externalProperties))
        val elseBranch = Option(i.getElseBranch).map(convertPsiToIntermediate(_, externalProperties))
        IfStatement(condition, thenBranch, elseBranch)
      case c: PsiConditionalExpression =>
        val condition = Option(c.getCondition).map(convertPsiToIntermediate(_, externalProperties))
        val thenBranch = Option(c.getThenExpression).map(convertPsiToIntermediate(_, externalProperties))
        val elseBranch = Option(c.getElseExpression).map(convertPsiToIntermediate(_, externalProperties))
        IfStatement(condition, thenBranch, elseBranch)
      case w: PsiWhileStatement =>
        //noinspection DuplicatedCode
        val condition = Option(w.getCondition).map(convertPsiToIntermediate(_, externalProperties))
        val body = Option(w.getBody).map(convertPsiToIntermediate(_, externalProperties))
        WhileStatement(None, condition, body, None, WhileStatement.PRE_TEST_LOOP)
      case w: PsiDoWhileStatement =>
        //noinspection DuplicatedCode
        val condition = Option(w.getCondition).map(convertPsiToIntermediate(_, externalProperties))
        val body = Option(w.getBody).map(convertPsiToIntermediate(_, externalProperties))
        WhileStatement(None, condition, body, None, WhileStatement.POST_TEST_LOOP)
      case f: PsiForStatement =>
        val countingLoop = CountingLoop.from(f)
        val body = Option(f.getBody).map(convertPsiToIntermediate(_, externalProperties))
        if (countingLoop != null) {
          val name = convertPsiToIntermediate(countingLoop.getCounter.getNameIdentifier, externalProperties)

          val iteratedValue = RangeExpression(
            convertPsiToIntermediate(countingLoop.getInitializer, externalProperties),
            convertPsiToIntermediate(countingLoop.getBound, externalProperties),
            countingLoop.isIncluding, countingLoop.isDescending)
          ForeachStatement(name, Some(iteratedValue), body, isJavaCollection = false)
        } else {
          val initialization = Option(f.getInitialization).map(convertPsiToIntermediate(_, externalProperties))
          val condition = Some(f.getCondition match {
            case _: PsiEmptyStatement => LiteralExpression("true")
            case null => LiteralExpression("true")
            case _ => convertPsiToIntermediate(f.getCondition, externalProperties)
          })
          val update = Option(f.getUpdate).map(convertPsiToIntermediate(_, externalProperties))
          WhileStatement(initialization, condition, body, update, WhileStatement.PRE_TEST_LOOP)
        }
      case a: PsiAssertStatement =>
        val condition = Option(a.getAssertCondition).map(convertPsiToIntermediate(_, externalProperties))
        val description = Option(a.getAssertDescription).map(convertPsiToIntermediate(_, externalProperties))
        AssertStatement(condition, description)
      case s: PsiSwitchLabelStatementBase =>
        val caseValues = if (s.isDefaultCase)
          Seq(LiteralExpression("_"))
        else
          Option(s.getCaseLabelElementList)
            .map(it => it.getElements.iterator.map(convertPsiToIntermediate(_, externalProperties)).toSeq)
            .getOrElse(Seq.empty)
        val body : Option[PsiStatement] = s match {
          case rs: PsiSwitchLabeledRuleStatement => Option(rs.getBody)
          case _ => None
        }
        val guardExpression = s.getGuardExpression.toOption
        SwitchLabelStatement(
          caseValues,
          guardExpression.map(convertPsiToIntermediate(_, externalProperties)),
          ScalaPsiUtil.functionArrow(s.getProject),
          body.map(convertPsiToIntermediate(_, externalProperties))
        )
      case s: PsiSwitchBlock =>
        val statements: Option[Array[PsiStatement]] =
          Option(s.getBody).map(_.getStatements)

        def defaultStatement: SwitchLabelStatement =
          SwitchLabelStatement(Seq(LiteralExpression("_")), None, ScalaPsiUtil.functionArrow(s.getProject))

        val expr = Option(s.getExpression).map(convertPsiToIntermediate(_, externalProperties))
        val body = Option(s.getBody).map(convertPsiToIntermediate(_, externalProperties))
        val hasEmptyStatement = statements.exists(_.isEmpty)
        val body2 = if (hasEmptyStatement) Some(defaultStatement) else body
        SwitchBlock(expr, body2)
      case p: PsiPackageStatement => PackageStatement(convertPsiToIntermediate(p.getPackageReference, externalProperties))
      case f: PsiForeachStatementBase =>
        val tp = Option(f.getIteratedValue).flatMap((e: PsiExpression) => Option(e.getType))
        val isJavaCollection = if (tp.isEmpty) true else !tp.get.isInstanceOf[PsiArrayType]

        val iteratedValue = Option(f.getIteratedValue).map(convertPsiToIntermediate(_, externalProperties))
        val body = Option(f.getBody).map(convertPsiToIntermediate(_, externalProperties))
        val nameIdentifier = f match {
          case statement: PsiForeachStatement => statement.getIterationParameter.getNameIdentifier
          case patternStatement: PsiForeachPatternStatement =>
            val pattern = patternStatement.getIterationPattern
            val variable = JavaPsiPatternUtil.getPatternVariable(pattern)
            if (variable != null) variable.getNameIdentifier else null
          case _ => null
        }
        val name = convertPsiToIntermediate(nameIdentifier, externalProperties)
        ForeachStatement(name, iteratedValue, body, isJavaCollection)
      case r: PsiReferenceExpression =>
        val args = Option(r.getParameterList).map(convertPsiToIntermediate(_, externalProperties))

        val refName: Option[String] = {
          val nameWithPrefix: String = if (conversionContext.textMode && r.getQualifier == null) r.resolve() match {
            case clazz: PsiClass => ScalaPsiUtil.nameWithPrefixIfNeeded(clazz)
            case _ => r.getReferenceName
          } else r.getReferenceName

          val name: String = if (externalProperties.isInstanceOf[WithReferenceExpression]) {
            fieldParameterMap.getOrElse(r.getReferenceName, nameWithPrefix)
          } else {
            nameWithPrefix
          }
          Option(name)
        }

        var iResult = JavaCodeReferenceStatement(None, args, refName)
        if (r.getQualifierExpression != null) {
          val t = Option(r.getQualifierExpression).map(convertPsiToIntermediate(_, externalProperties))
          iResult = JavaCodeReferenceStatement(t, args, refName)
        } else {
          r.resolve() match {
            case f: PsiMember
              if f.hasModifierProperty("static") =>
              val clazz = f.containingClass
              if (clazz != null && context.value.contains((false, clazz.qualifiedName))) {
                val name = Option(clazz.getNameIdentifier).map(convertPsiToIntermediate(_, externalProperties))
                iResult = JavaCodeReferenceStatement(name, args, refName)
              }

            case _ =>
          }
        }

        handleAssociations(r, iResult)
        iResult
      case p: PsiJavaCodeReferenceElement =>
        val qualifier = Option(p.getQualifier).map(convertPsiToIntermediate(_, externalProperties))
        val args = Option(p.getParameterList).map(convertPsiToIntermediate(_, externalProperties))
        JavaCodeReferenceStatement(qualifier, args, Option(p.getReferenceName))
      case be: PsiBinaryExpression =>
        def isOk: Boolean = {
          if (be.getLOperand.getType.isInstanceOf[PsiPrimitiveType]) return false
          be.getROperand match {
            case l: PsiLiteralExpression if l.textMatches("null") => return false
            case _ =>
          }
          true
        }

        def inExpression: Boolean = Option(be.getParent) match {
          case Some(_: PsiExpression) => true
          case _ => false
        }

        val operation = be.getOperationSign.getText match {
          case "==" if isOk => "eq"
          case "!=" if isOk => "ne"
          case x => x
        }

        BinaryExpressionConstruction(
          convertPsiToIntermediate(be.getLOperand, externalProperties),
          convertPsiToIntermediate(be.getROperand, externalProperties),
          operation, inExpression)
      case c: PsiTypeCastExpression =>
        ClassCast(
          convertPsiToIntermediate(c.getOperand, externalProperties),
          convertTypePsiToIntermediate(c.getCastType),
          isPrimitive = c.getCastType.getType.isInstanceOf[PsiPrimitiveType] && c.getOperand.getType.isInstanceOf[PsiPrimitiveType]
        )
      case a: PsiArrayAccessExpression =>
        ArrayAccess(
          convertPsiToIntermediate(a.getArrayExpression, externalProperties),
          convertPsiToIntermediate(a.getIndexExpression, externalProperties))
      case a: PsiArrayInitializerExpression =>
        ArrayInitializer(a.getInitializers.map(convertPsiToIntermediate(_, externalProperties)).toIndexedSeq)
      case c: PsiClassObjectAccessExpression => ClassObjectAccess(convertPsiToIntermediate(c.getOperand, externalProperties))
      case typeTest: PsiTypeTestPattern =>
        //TODO support Java pattern matching truly, see SCL-21510
        LiteralExpression(typeTest.getText)
      case i: PsiInstanceOfExpression =>
        val checkType = i.getCheckType match {
          case null =>
            //type can be null since Java 15/16 when there is a variable: `obj instanceof String str`
            //NOTE: this is a fast workaround just to avoid NPE (see SCL-21509)
            //TODO support Java pattern matching truly, see SCL-21510
            i.getPattern match {
              case typeTest: PsiTypeTestPattern => typeTest.getCheckType
              case _ => null
            }
          case t => t
        }
        val checkTypeNode = if (checkType != null) convertTypePsiToIntermediate(checkType) else EmptyTypeNode()
        InstanceOfConstruction(
          convertPsiToIntermediate(i.getOperand, externalProperties),
          checkTypeNode
        )
      case m: PsiMethodCallExpression =>
        def isSuper: Boolean = m.getMethodExpression.getQualifierExpression.isInstanceOf[PsiSuperExpression]

        m.getMethodExpression.resolve() match {
          case method: PsiMethod if method.getName == "parseInt" && m.getArgumentList.getExpressions.length == 1 &&
            method.getContainingClass != null && method.getContainingClass.qualifiedName == "java.lang.Integer" =>
            ClassCast(convertPsiToIntermediate(m.getArgumentList.getExpressions.apply(0), externalProperties),
              TypeConstruction("Int"), isPrimitive = true)
          case method: PsiMethod if method.getName == "parseDouble" && m.getArgumentList.getExpressions.length == 1 &&
            method.getContainingClass != null && method.getContainingClass.qualifiedName == "java.lang.Double" =>
            ClassCast(convertPsiToIntermediate(m.getArgumentList.getExpressions.apply(0), externalProperties),
              TypeConstruction("Double"), isPrimitive = true)
          case method: PsiMethod if method.getName == "round" && m.getArgumentList.getExpressions.length == 1 &&
            method.getContainingClass != null && method.getContainingClass.qualifiedName == "java.lang.Math" =>
            MethodCallExpression.build(
              convertPsiToIntermediate(m.getArgumentList.getExpressions.apply(0), externalProperties), ".round", null)
          case method: PsiMethod if method.getName == "equals" && m.getTypeArguments.isEmpty && !isSuper
            && m.getArgumentList.getExpressions.length == 1 =>
            val receiver = Option(m.getMethodExpression.getQualifierExpression).map(convertPsiToIntermediate(_, externalProperties)).getOrElse(LiteralExpression("this"))
            MethodCallExpression.build(
              receiver,
              " == ",
              ExpressionList(Seq(convertPsiToIntermediate(m.getArgumentList.getExpressions.apply(0), externalProperties)))
            )
          case _ =>
            MethodCallExpression(
              convertPsiToIntermediate(m.getMethodExpression, externalProperties),
              convertToExpressionList(m.getArgumentList, externalProperties),
              (m.getType == PsiTypeConstants.Void) && m.getArgumentList.getExpressions.isEmpty
            )
        }
      case t: PsiThisExpression =>
        ThisExpression(Option(t.getQualifier).map(convertPsiToIntermediate(_, externalProperties)))
      case s: PsiSuperExpression =>
        SuperExpression(Option(s.getQualifier).map(convertPsiToIntermediate(_, externalProperties)))
      case e: PsiExpressionList =>
        convertToExpressionList(e, externalProperties)
      case lambda: PsiLambdaExpression =>
        FunctionalExpression(
          convertToParameterListConstruction(lambda.getParameterList),
          convertPsiToIntermediate(lambda.getBody, externalProperties)
        )
      case l: PsiLocalVariable =>
        val parent = Option(PsiTreeUtil.getParentOfType(l, classOf[PsiCodeBlock], classOf[PsiBlockStatement]))
        val needVar = if (parent.isEmpty) false else isVar(l, parent)
        val initializer = Option(l.getInitializer).map(convertPsiToIntermediate(_, externalProperties))
        val name = convertToIdentifier(l.getNameIdentifier)
        LocalVariable(
          handleModifierList(l),
          name,
          convertTypePsiToIntermediate(l.getType, l.getTypeElement, l.getProject),
          needVar,
          initializer
        )
      case enumConstant: PsiEnumConstant =>
        EnumConstruction(convertToIdentifier(enumConstant.getNameIdentifier))
      case f: PsiField =>
        val modifiers = handleModifierList(f)
        val needVar = isVar(f, Option(f.getContainingClass))
        val initializer = Option(f.getInitializer).map(convertPsiToIntermediate(_, externalProperties))
        val name = convertToIdentifier(f.getNameIdentifier)
        FieldConstruction(
          modifiers,
          name,
          convertTypePsiToIntermediate(f.getType, f.getTypeElement, f.getProject),
          needVar,
          initializer
        )
      case p: PsiParameterList =>
        convertToParameterListConstruction(p)
      case m: PsiMethod =>
        def body: Option[IntermediateNode] = {
          if (m.isConstructor) {
            getFirstStatement(m).map(_.getExpression).flatMap {
              case mc: PsiMethodCallExpression if mc.getMethodExpression.getQualifiedName == "this" =>
                Some(convertPsiToIntermediate(m.getBody, externalProperties))
              case _ =>
                getStatements(m).map(statements => {
                  val statementsUpdated = LiteralExpression("this()") +: statements.map(convertPsiToIntermediate(_, externalProperties)).toIndexedSeq
                  BlockConstruction(statementsUpdated)
                })
            }
          } else {
            Option(m.getBody).map(convertPsiToIntermediate(_, externalProperties))
          }
        }

        def convertMethodReturnType: Option[TypeNode] =
          if (m.getReturnType != PsiTypeConstants.Void || ScalaCodeStyleSettings.getInstance(m.getProject).ENFORCE_FUNCTIONAL_SYNTAX_FOR_UNIT)
            Some(convertTypePsiToIntermediate(m.getReturnTypeElement))
          else None

        if (m.isConstructor) {
          ConstructorSimply(
            handleModifierList(m),
            m.getTypeParameters.map(convertToTypeParameterConstruction(_, externalProperties)).toIndexedSeq,
            m.parameters.map(convertToParameterConstruction),
            body
          )
        } else {
          val name = convertToIdentifier(m.getNameIdentifier)
          MethodConstruction(
            handleModifierList(m),
            name,
            m.getTypeParameters.map(convertToTypeParameterConstruction(_, externalProperties)).toIndexedSeq,
            m.parameters.map(convertToParameterConstruction),
            body,
            convertMethodReturnType
          )
        }
      case c: PsiClass =>
        createClass(c, externalProperties)
      case p: PsiParenthesizedExpression =>
        val expr = Option(p.getExpression).map(convertPsiToIntermediate(_, externalProperties))
        ParenthesizedExpression(expr)
      case v: PsiArrayInitializerMemberValue =>
        ArrayInitializer(v.getInitializers.map(convertPsiToIntermediate(_, externalProperties)).toSeq)
      case annot: PsiAnnotation =>
        def isArrayAnnotationParameter(pair: PsiNameValuePair): Boolean = {
          AnnotationUtil.getAnnotationMethod(pair) match {
            case method: PsiMethod =>
              val returnType = method.getReturnType
              returnType != null && returnType.isInstanceOf[PsiArrayType]
            case _ => false
          }
        }

        val attributes = annot.getParameterList.getAttributes
        val attrResult = mutable.ArrayBuffer[(Option[IntermediateNode], Option[IntermediateNode])]()
        for (attribute <- attributes) {
          val value = Option(attribute.getValue) match {
            case Some(v: PsiAnnotationMemberValue) if isArrayAnnotationParameter(attribute) =>
              ArrayInitializer(Seq(convertPsiToIntermediate(v, externalProperties)))
            case Some(_) => convertPsiToIntermediate(attribute.getValue, externalProperties)
            case _ => null
          }
          attrResult += ((Option(attribute.getNameIdentifier).map(convertPsiToIntermediate(_, externalProperties)), Option(value)))
        }

        val inAnnotation = PsiTreeUtil.getParentOfType(annot, classOf[PsiAnnotation]) != null

        val name = Option(annot.getNameReferenceElement).map(convertPsiToIntermediate(_, externalProperties))
        AnnotationConstruction(inAnnotation, attrResult.toSeq, name)
      case p: PsiParameter =>
        convertToParameterConstruction(p)

      case n: PsiNewExpression =>
        val anonymousClass = n.getAnonymousClass
        if (anonymousClass != null) {
          val node = convertPsiToIntermediate(anonymousClass, externalProperties)
          node match {
            case ac: AnonymousClass =>
              return AnonymousClassExpression(ac)
            case other =>
              return other
          }
        }

        val iType = convertTypePsiToIntermediate(n.getType, n.getClassReference, n.getProject)
        val withArrayInitializer = n.getArrayInitializer != null
        val argList: Seq[IntermediateNode] =
          if (n.getArrayInitializer != null)
            n.getArrayInitializer.getInitializers.map(convertPsiToIntermediate(_, externalProperties)).toIndexedSeq
          else if (n.getArrayDimensions.nonEmpty)
            n.getArrayDimensions.map(convertPsiToIntermediate(_, externalProperties)).toIndexedSeq
          else if (n.getArgumentList != null) {
            if (n.getArgumentList.getExpressions.isEmpty)
              n.getParent match {
                case r: PsiJavaCodeReferenceElement if n == r.getQualifier =>
                  Seq(LiteralExpression("()"))
                case _ => null
              }
            else
              Seq(convertPsiToIntermediate(n.getArgumentList, externalProperties))
          }
          else null

        NewExpression(iType, argList, withArrayInitializer)
      case t: PsiTryStatement =>
        val resourcesVariables = mutable.ArrayBuffer[(String, IntermediateNode)]()
        Option(t.getResourceList).foreach { resourceList =>
          val it = resourceList.iterator
          while (it.hasNext) {
            val next = it.next()
            next match {
              case variable: PsiResourceVariable =>
                resourcesVariables += ((variable.getName, convertPsiToIntermediate(variable, externalProperties)))
              case _ =>
            }
          }
        }
        val tryBlock = Option(t.getTryBlock).map(convertToBlockConstruction(_, externalProperties))
        val catches: Seq[(ParameterConstruction, IntermediateNode)] = t.getCatchSections.map { (cb: PsiCatchSection) =>
          (convertToParameterConstruction(cb.getParameter),
            convertPsiToIntermediate(cb.getCatchBlock, externalProperties))
        }.toIndexedSeq
        val finallyBlockStatements = Option(t.getFinallyBlock).map(_.getStatements.map(convertPsiToIntermediate(_, externalProperties)).toSeq)
        TryCatchStatement(resourcesVariables.toSeq, tryBlock, catches, finallyBlockStatements, ScalaPsiUtil.functionArrow(t.getProject))
      case p: PsiPrefixExpression =>
        PrefixExpression(convertPsiToIntermediate(p.getOperand, externalProperties), p.getOperationSign.getText, ExpressionUtils.isVoidContext(p))
      case p: PsiPostfixExpression =>
        PostfixExpression(convertPsiToIntermediate(p.getOperand, externalProperties), p.getOperationSign.getText, ExpressionUtils.isVoidContext(p))
      case p: PsiPolyadicExpression =>
        val tokenValue = if (p.getOperands.nonEmpty) {
          p.getTokenBeforeOperand(p.getOperands.apply(1)).getText
        } else ""
        PolyadicExpression(p.getOperands.map(convertPsiToIntermediate(_, externalProperties)).toIndexedSeq, tokenValue)
      case r: PsiReferenceParameterList => TypeParameters(r.getTypeParameterElements.map(convertPsiToIntermediate(_, externalProperties)).toIndexedSeq)
      case b: PsiBreakStatement =>
        if (isBreakRemovable(b)) EmptyConstruction()
        else if (b.getLabelIdentifier != null)
          NotSupported(None, "break " + b.getLabelIdentifier.getText + "// todo: label break is not supported")
        else NotSupported(None, "break //todo: break is not supported")
      case y: PsiYieldStatement =>
        if (isYieldRemovable(y)) convertPsiToIntermediate(y.getExpression, externalProperties)
        else NotSupported(None, "`yield` " + Option(y.getExpression).map(_.getText).mkString + "// todo: Java's yield is not supported")
      case c: PsiContinueStatement =>
        if (c.getLabelIdentifier != null)
          NotSupported(None, "continue " + c.getLabelIdentifier.getText + " //todo: continue is not supported")
        else NotSupported(None, "continue //todo: continue is not supported")
      case s: PsiLabeledStatement =>
        val statements = Option(s.getStatement).map(convertPsiToIntermediate(_, externalProperties))
        NotSupported(statements, s.getLabelIdentifier.getText + " //todo: labels are not supported")
      case _: PsiEmptyStatement => EmptyConstruction()
      case _: PsiErrorElement => EmptyConstruction()
      case c: PsiComment if conversionContext.usedComments.contains(c) =>
        EmptyConstruction()
      case e =>
        LiteralExpression(e.getText)
    }

    result.setComments(comments)
    result
  }