@@ -528,10 +528,12 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this:
528528 clazz.columnNumber
529529 )
530530
531- val annotationAst = createClassAnnotationAst(clazz, classIdNode)
532- if (annotationAst.root.isDefined) {
531+ val classAnnotationAst = createClassAnnotationAst(clazz, classIdNode)
532+ val propertyAnnotationAsts = createPropertyAnnotationAsts(clazz, classIdNode)
533+ val methodAnnotationAsts = createMethodAnnotationAsts(clazz, classIdNode)
534+ if (classAnnotationAst.root.isDefined || propertyAnnotationAsts.nonEmpty || methodAnnotationAsts.nonEmpty) {
533535 val blockNode_ = blockNode(clazz)
534- val childrenAsts = List (assignmentAst, annotationAst)
536+ val childrenAsts = List (assignmentAst, classAnnotationAst) ++ propertyAnnotationAsts ++ methodAnnotationAsts
535537 setArgumentIndices(childrenAsts)
536538 Ast (blockNode_).withChildren(childrenAsts)
537539 } else assignmentAst
@@ -555,7 +557,7 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this:
555557
556558 val receiverNode = identifierNode(classNodeInfo, " __decorate" )
557559 scope.addVariableReference(receiverNode.name, receiverNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
558- val thisNode = identifierNode(classNodeInfo, " this" ).dynamicTypeHintFullName(typeHintForThisExpression() )
560+ val thisNode = identifierNode(classNodeInfo, " this" ).dynamicTypeHintFullName(rootTypeDecl.map(_.fullName).toSeq )
559561 scope.addVariableReference(thisNode.name, thisNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
560562
561563 val decorateCallNode =
@@ -590,6 +592,311 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this:
590592 } else Ast ()
591593 }
592594
595+ private def createMetadataCallTypeAst (tsMethodNodeInfo : BabelNodeInfo ): Ast = {
596+ val metadataCallRecNode = identifierNode(tsMethodNodeInfo, " __metadata" )
597+ scope.addVariableReference(
598+ metadataCallRecNode.name,
599+ metadataCallRecNode,
600+ Defines .Any ,
601+ EvaluationStrategies .BY_REFERENCE
602+ )
603+ val metadataCallRecThisNode =
604+ identifierNode(tsMethodNodeInfo, " this" ).dynamicTypeHintFullName(rootTypeDecl.map(_.fullName).toSeq)
605+ scope.addVariableReference(
606+ metadataCallRecThisNode.name,
607+ metadataCallRecThisNode,
608+ Defines .Any ,
609+ EvaluationStrategies .BY_REFERENCE
610+ )
611+
612+ val designTypeLiteralNode = literalNode(tsMethodNodeInfo, " 'design:type'" , Defines .String )
613+ val functionLiteralNode = literalNode(tsMethodNodeInfo, " Function" , Defines .Any )
614+ val metadataCallType =
615+ callNode(
616+ tsMethodNodeInfo,
617+ s """ __metadata("design:type", Function) """ ,
618+ " __metadata" ,
619+ DispatchTypes .DYNAMIC_DISPATCH
620+ )
621+ val metadataTypeArgAsts = Seq (Ast (designTypeLiteralNode), Ast (functionLiteralNode))
622+ callAst(
623+ metadataCallType,
624+ metadataTypeArgAsts,
625+ receiver = Option (Ast (metadataCallRecNode)),
626+ base = Option (Ast (metadataCallRecThisNode))
627+ )
628+ }
629+
630+ private def createMetadataCallParamTypesAst (tsMethodNodeInfo : BabelNodeInfo , numParams : Int ): Ast = {
631+ val metadataCallRecNode = identifierNode(tsMethodNodeInfo, " __metadata" )
632+ scope.addVariableReference(
633+ metadataCallRecNode.name,
634+ metadataCallRecNode,
635+ Defines .Any ,
636+ EvaluationStrategies .BY_REFERENCE
637+ )
638+ val metadataCallThisNode =
639+ identifierNode(tsMethodNodeInfo, " this" ).dynamicTypeHintFullName(rootTypeDecl.map(_.fullName).toSeq)
640+ scope.addVariableReference(
641+ metadataCallThisNode.name,
642+ metadataCallThisNode,
643+ Defines .Any ,
644+ EvaluationStrategies .BY_REFERENCE
645+ )
646+
647+ val designParamTypeLiteralNode = literalNode(tsMethodNodeInfo, " 'design:paramtypes'" , Defines .String )
648+
649+ val objectLiteralNode = literalNode(tsMethodNodeInfo, " Object" , Defines .Object )
650+
651+ val blockNode_ = blockNode(tsMethodNodeInfo)
652+ scope.pushNewBlockScope(blockNode_)
653+ localAstParentStack.push(blockNode_)
654+
655+ val tmpName = generateUnusedVariableName(usedVariableNames, " _tmp" )
656+ val localTmpNode = localNode(tsMethodNodeInfo, tmpName, tmpName, Defines .Any ).order(0 )
657+ val tmpArrayNode = identifierNode(tsMethodNodeInfo, tmpName)
658+ diffGraph.addEdge(localAstParentStack.head, localTmpNode, EdgeTypes .AST )
659+ scope.addVariableReference(tmpName, tmpArrayNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
660+
661+ val arrayCallNode =
662+ callNode(
663+ tsMethodNodeInfo,
664+ s " ${EcmaBuiltins .arrayFactory}() " ,
665+ EcmaBuiltins .arrayFactory,
666+ DispatchTypes .STATIC_DISPATCH
667+ )
668+
669+ val lineNumber = tsMethodNodeInfo.lineNumber
670+ val columnNumber = tsMethodNodeInfo.columnNumber
671+ val assignmentCode = s " ${localTmpNode.code} = ${arrayCallNode.code}"
672+ val assignmentTmpArrayCallNode =
673+ createAssignmentCallAst(tmpArrayNode, arrayCallNode, assignmentCode, lineNumber, columnNumber)
674+
675+ val elementAsts = (0 until numParams).toList.map { _ =>
676+ val objectLiteralNode = literalNode(tsMethodNodeInfo, " Object" , Defines .Object )
677+ val pushCallNode = callNode(tsMethodNodeInfo, s " $tmpName.push(Object) " , " " , DispatchTypes .DYNAMIC_DISPATCH )
678+
679+ val baseNode = identifierNode(tsMethodNodeInfo, tmpName)
680+ val memberNode = fieldIdentifierNode(tsMethodNodeInfo, " push" , " push" )
681+ val receiverNode =
682+ createFieldAccessCallAst(baseNode, memberNode, tsMethodNodeInfo.lineNumber, tsMethodNodeInfo.columnNumber)
683+ val thisPushNode = identifierNode(tsMethodNodeInfo, tmpName)
684+ callAst(
685+ pushCallNode,
686+ List (Ast (objectLiteralNode)),
687+ receiver = Option (receiverNode),
688+ base = Option (Ast (thisPushNode))
689+ )
690+ }
691+
692+ val tmpArrayReturnNode = identifierNode(tsMethodNodeInfo, tmpName)
693+
694+ scope.popScope()
695+ localAstParentStack.pop()
696+
697+ val blockChildrenAsts = assignmentTmpArrayCallNode +: elementAsts :+ Ast (tmpArrayReturnNode)
698+ setArgumentIndices(blockChildrenAsts)
699+ val blockAst_ = blockAst(blockNode_, blockChildrenAsts)
700+
701+ val metadataParamTypeCall =
702+ callNode(
703+ tsMethodNodeInfo,
704+ s """ __metadata("design:paramtypes", [ ${List .fill(numParams)(" Object" ).mkString(" ," )}]) """ ,
705+ " __metadata" ,
706+ DispatchTypes .DYNAMIC_DISPATCH
707+ )
708+ val metadataTypeArgAsts = Seq (Ast (designParamTypeLiteralNode), blockAst_)
709+ callAst(
710+ metadataParamTypeCall,
711+ metadataTypeArgAsts,
712+ receiver = Option (Ast (metadataCallRecNode)),
713+ base = Option (Ast (metadataCallThisNode))
714+ )
715+ }
716+
717+ private def createMetadataCallReturnTypeAst (tsMethodNodeInfo : BabelNodeInfo , tpe : String ): Ast = {
718+ val metadataCallRecNode = identifierNode(tsMethodNodeInfo, " __metadata" )
719+ scope.addVariableReference(
720+ metadataCallRecNode.name,
721+ metadataCallRecNode,
722+ Defines .Any ,
723+ EvaluationStrategies .BY_REFERENCE
724+ )
725+ val metadataCallTypeRecThisNode =
726+ identifierNode(tsMethodNodeInfo, " this" ).dynamicTypeHintFullName(rootTypeDecl.map(_.fullName).toSeq)
727+ scope.addVariableReference(
728+ metadataCallTypeRecThisNode.name,
729+ metadataCallTypeRecThisNode,
730+ Defines .Any ,
731+ EvaluationStrategies .BY_REFERENCE
732+ )
733+
734+ val designTypeLiteralNode = literalNode(tsMethodNodeInfo, " 'design:returntype'" , Defines .String )
735+ val tpeLiteralNode = literalNode(tsMethodNodeInfo, tpe, Defines .Any )
736+ val metadataCallType =
737+ callNode(tsMethodNodeInfo, s """ __metadata("design:type", $tpe) """ , " __metadata" , DispatchTypes .DYNAMIC_DISPATCH )
738+ val metadataTypeArgAsts = Seq (Ast (designTypeLiteralNode), Ast (tpeLiteralNode))
739+ callAst(
740+ metadataCallType,
741+ metadataTypeArgAsts,
742+ receiver = Option (Ast (metadataCallRecNode)),
743+ base = Option (Ast (metadataCallTypeRecThisNode))
744+ )
745+ }
746+
747+ private def createPropertyAnnotationAsts (classNodeInfo : BabelNodeInfo , classIdNode : NewIdentifier ): Seq [Ast ] = {
748+ val tsProperties = classMembers(classNodeInfo).flatMap { member =>
749+ val memberNodeInfo = createBabelNodeInfo(member)
750+ if (
751+ memberNodeInfo.node == ClassProperty ||
752+ memberNodeInfo.node == ClassPrivateProperty
753+ ) {
754+ Some (memberNodeInfo)
755+ } else {
756+ None
757+ }
758+ }
759+
760+ tsProperties.map { tsPropertyNodeInfo =>
761+ val decoratorAsts =
762+ decoratorExpressionElements(tsPropertyNodeInfo).map(e => astForNodeWithFunctionReference(e.json))
763+ if (decoratorAsts.nonEmpty) {
764+ val name = tsPropertyNodeInfo.node match {
765+ case ClassProperty => code(tsPropertyNodeInfo.json(" key" ))
766+ case ClassPrivateProperty => code(tsPropertyNodeInfo.json(" key" )(" id" ))
767+ case _ => tsPropertyNodeInfo.code
768+ }
769+ val propertyTpe = typeFor(tsPropertyNodeInfo)
770+
771+ val receiverNode = identifierNode(classNodeInfo, " __decorate" )
772+ scope.addVariableReference(receiverNode.name, receiverNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
773+ val thisNode = identifierNode(classNodeInfo, " this" ).dynamicTypeHintFullName(rootTypeDecl.map(_.fullName).toSeq)
774+ scope.addVariableReference(thisNode.name, thisNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
775+
776+ val classPrototypeAccessAst = createFieldAccessCallAst(
777+ identifierNode(classNodeInfo, classIdNode.name),
778+ fieldIdentifierNode(classNodeInfo, " prototype" , " prototype" ),
779+ classNodeInfo.lineNumber,
780+ classNodeInfo.columnNumber
781+ )
782+ val propertyNameNode = literalNode(tsPropertyNodeInfo, s " ' $name' " , Defines .String )
783+ val voidCallNode_ = voidCallNode(line(tsPropertyNodeInfo), column(tsPropertyNodeInfo))
784+
785+ val arg1Code = decoratorAsts.flatMap(_.root.map(codeOf)).mkString(" ," )
786+ val decorateCallCode =
787+ s " __decorate([ $arg1Code], ${codeOf(classPrototypeAccessAst.nodes.head)}, ${propertyNameNode.code}, ${voidCallNode_.code}) "
788+
789+ val decorateCallNode = callNode(classNodeInfo, decorateCallCode, " __decorate" , DispatchTypes .DYNAMIC_DISPATCH )
790+ val subAst = astForDecorateArray(classNodeInfo, decoratorAsts)
791+ callAst(
792+ decorateCallNode,
793+ subAst +: Seq (classPrototypeAccessAst, Ast (propertyNameNode), Ast (voidCallNode_)),
794+ receiver = Option (Ast (receiverNode)),
795+ base = Option (Ast (thisNode))
796+ )
797+ } else {
798+ Ast ()
799+ }
800+ }
801+ }
802+
803+ private def createMethodAnnotationAsts (classNodeInfo : BabelNodeInfo , classIdNode : NewIdentifier ): Seq [Ast ] = {
804+ val tsMethods = classMembers(classNodeInfo).flatMap { member =>
805+ val memberNodeInfo = createBabelNodeInfo(member)
806+ if (memberNodeInfo.node == ClassMethod ) {
807+ Some (memberNodeInfo)
808+ } else {
809+ None
810+ }
811+ }
812+
813+ tsMethods.map { tsMethodNodeInfo =>
814+ val decoratorAsts =
815+ decoratorExpressionElements(tsMethodNodeInfo).map(e => astForNodeWithFunctionReference(e.json))
816+ val (name, fullName) = calcMethodNameAndFullName(tsMethodNodeInfo)
817+ val methodTpe = typeFor(tsMethodNodeInfo)
818+ val paramNodeInfos = if (hasKey(tsMethodNodeInfo.json, " parameters" )) {
819+ tsMethodNodeInfo.json(" parameters" ).arr.toSeq
820+ } else {
821+ tsMethodNodeInfo.json(" params" ).arr.toSeq
822+ }
823+ val paramDecoratorAsts = paramNodeInfos.zipWithIndex.flatMap { case (value, idx) =>
824+ val paramAsts =
825+ decoratorExpressionElements(createBabelNodeInfo(value)).map(e => astForNodeWithFunctionReference(e.json))
826+
827+ if (paramAsts.isEmpty) {
828+ Seq .empty
829+ } else {
830+ val paramNodeInfo = createBabelNodeInfo(value)
831+ val receiverNode = identifierNode(paramNodeInfo, " __param" )
832+ scope.addVariableReference(receiverNode.name, receiverNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
833+ val thisNode =
834+ identifierNode(paramNodeInfo, " this" ).dynamicTypeHintFullName(rootTypeDecl.map(_.fullName).toSeq)
835+ scope.addVariableReference(thisNode.name, thisNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
836+
837+ paramAsts.map { p =>
838+ val callNode_ = callNode(
839+ paramNodeInfo,
840+ s " __param( $idx, ${codeOf(p.nodes.head)}) " ,
841+ " __param" ,
842+ DispatchTypes .DYNAMIC_DISPATCH
843+ )
844+ val idxNode = literalNode(paramNodeInfo, s " $idx" , Defines .Number )
845+ val argAsts = Seq (Ast (idxNode), p)
846+ val paramDecorateCallAst =
847+ callAst(callNode_, argAsts, receiver = Option (Ast (receiverNode)), base = Option (Ast (thisNode)))
848+ paramDecorateCallAst
849+ }
850+ }
851+ }
852+
853+ if (decoratorAsts.nonEmpty || paramDecoratorAsts.nonEmpty) {
854+ val receiverNode = identifierNode(classNodeInfo, " __decorate" )
855+ scope.addVariableReference(receiverNode.name, receiverNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
856+ val thisNode = identifierNode(classNodeInfo, " this" ).dynamicTypeHintFullName(rootTypeDecl.map(_.fullName).toSeq)
857+ scope.addVariableReference(thisNode.name, thisNode, Defines .Any , EvaluationStrategies .BY_REFERENCE )
858+
859+ val classPrototypeAccessAst = createFieldAccessCallAst(
860+ identifierNode(classNodeInfo, classIdNode.name),
861+ fieldIdentifierNode(classNodeInfo, " prototype" , " prototype" ),
862+ classNodeInfo.lineNumber,
863+ classNodeInfo.columnNumber
864+ )
865+ val functionNameNode = literalNode(tsMethodNodeInfo, s " ' $name' " , Defines .String )
866+ val nullNode = literalNode(tsMethodNodeInfo, " null" , Defines .Null )
867+ val metadataCallTypeAst = createMetadataCallTypeAst(tsMethodNodeInfo)
868+ val metadataCallParamTypesAst = createMetadataCallParamTypesAst(tsMethodNodeInfo, paramNodeInfos.size)
869+ val metadataCallReturnTypeAst = createMetadataCallReturnTypeAst(tsMethodNodeInfo, methodTpe)
870+
871+ val arg1Code = decoratorAsts.flatMap(_.root.map(codeOf)).mkString(" ," )
872+ val arg2Code = paramDecoratorAsts.flatMap(_.root.map(codeOf)).mkString(" ," )
873+ val arg3Code = codeOf(metadataCallTypeAst.root.get)
874+ val arg4Code = codeOf(metadataCallParamTypesAst.root.get)
875+ val arg5Code = codeOf(metadataCallReturnTypeAst.root.get)
876+ val decorateCallCode =
877+ s " __decorate([ $arg1Code, $arg2Code, $arg3Code, $arg4Code, $arg5Code], ${codeOf(classPrototypeAccessAst.nodes.head)}, ${functionNameNode.code}, null) "
878+
879+ val decorateCallNode = callNode(classNodeInfo, decorateCallCode, " __decorate" , DispatchTypes .DYNAMIC_DISPATCH )
880+ val subAst = astForDecorateArray(
881+ classNodeInfo,
882+ decoratorAsts ++ paramDecoratorAsts ++ Seq (
883+ metadataCallTypeAst,
884+ metadataCallParamTypesAst,
885+ metadataCallReturnTypeAst
886+ )
887+ )
888+ callAst(
889+ decorateCallNode,
890+ subAst +: Seq (classPrototypeAccessAst, Ast (functionNameNode), Ast (nullNode)),
891+ receiver = Option (Ast (receiverNode)),
892+ base = Option (Ast (thisNode))
893+ )
894+ } else {
895+ Ast ()
896+ }
897+ }
898+ }
899+
593900 private def astForDecorateArray (classNodeInfo : BabelNodeInfo , decoratorAsts : List [Ast ]): Ast = {
594901 val blockNode_ = blockNode(classNodeInfo)
595902 scope.pushNewBlockScope(blockNode_)
0 commit comments