@@ -615,47 +615,113 @@ function createAirshipProperty(
615615 return prop ;
616616}
617617
618- export function getClassDecorators ( state : TransformState , classNode : ts . ClassLikeDeclaration ) {
619- const decorators = ts . hasDecorators ( classNode ) ? ts . getDecorators ( classNode ) : undefined ;
620- if ( decorators ) {
621- const items = new Array < AirshipBehaviourClassDecorator > ( ) ;
618+ function processRequireComponentDecorator (
619+ state : TransformState ,
620+ classNode : ts . ClassLikeDeclaration ,
621+ expression : ts . CallExpression ,
622+ ) : AirshipBehaviourClassDecorator | undefined {
623+ const typeChecker = state . typeChecker ;
624+ const typeArguments = expression . typeArguments ;
625+
626+ if ( ! typeArguments || typeArguments . length === 0 ) {
627+ DiagnosticService . addDiagnostic ( errors . requiredComponentTypeParameterRequired ( classNode , classNode . name ?. text || "<anonymous>" ) ) ;
628+ return undefined ;
629+ }
622630
623- for ( const decorator of decorators ) {
624- const expression = decorator . expression ;
625- if ( ! ts . isCallExpression ( expression ) ) continue ;
631+ const componentParameters = new Array < AirshipBehaviourFieldDecoratorParameter > ( ) ;
632+ for ( const typeArgument of typeArguments ) {
633+ const type = typeChecker . getTypeFromTypeNode ( typeArgument ) ;
626634
627- const aliasSymbol = state . typeChecker . getTypeAtLocation ( expression ) . aliasSymbol ;
628- if ( ! aliasSymbol ) continue ;
635+ if ( isAirshipBehaviourType ( state , type ) ) {
636+ const typeString = typeChecker . typeToString ( type ) ;
637+ componentParameters . push ( {
638+ type : "AirshipBehaviour" ,
639+ value : typeString ,
640+ } ) ;
641+ } else if ( isUnityObjectType ( state , type ) ) {
642+ const nonNullableType = typeChecker . getNonNullableType ( type ) ;
643+ const nonNullableTypeString = typeChecker . typeToString ( nonNullableType ) ;
644+ componentParameters . push ( {
645+ type : "object" ,
646+ value : nonNullableTypeString ,
647+ } ) ;
648+ } else {
649+ const typeString = typeChecker . typeToString ( type ) ;
650+ DiagnosticService . addDiagnostic ( errors . requiredComponentInvalidType ( classNode , classNode . name ?. text ?? "<anonymous>" , typeString ) ) ;
651+ }
652+ }
629653
630- const airshipFieldSymbol = state . services . airshipSymbolManager . getSymbolOrThrow ( "AirshipDecorator" ) ;
654+ if ( componentParameters . length === 0 ) {
655+ return undefined ;
656+ }
631657
632- if ( aliasSymbol === airshipFieldSymbol ) {
633- items . push ( {
634- name : expression . expression . getText ( ) ,
635- typeParameters : expression . typeArguments ?. map ( typeNode => {
636- return state . typeChecker . typeToString ( state . typeChecker . getTypeFromTypeNode ( typeNode ) ) ;
637- } ) ,
638- parameters : expression . arguments . map ( ( argument , i ) : AirshipBehaviourFieldDecoratorParameter => {
639- const value = getLiteralFromNode ( state , argument ) ;
658+ return {
659+ name : "RequireComponent" ,
660+ typeParameters : expression . typeArguments ?. map ( typeNode => {
661+ return state . typeChecker . typeToString ( state . typeChecker . getTypeFromTypeNode ( typeNode ) ) ;
662+ } ) ,
663+ parameters : componentParameters ,
664+ } ;
665+ }
640666
641- if ( value ) {
642- return value ;
643- } else {
644- DiagnosticService . addDiagnostic (
645- errors . decoratorParamsLiteralsOnly ( expression . arguments [ i ] ) ,
646- ) ;
667+ function processGenericDecorator (
668+ state : TransformState ,
669+ expression : ts . CallExpression ,
670+ decoratorName : string ,
671+ ) : AirshipBehaviourClassDecorator {
672+ return {
673+ name : decoratorName ,
674+ typeParameters : expression . typeArguments ?. map ( typeNode => {
675+ return state . typeChecker . typeToString ( state . typeChecker . getTypeFromTypeNode ( typeNode ) ) ;
676+ } ) ,
677+ parameters : expression . arguments . map ( ( argument , i ) : AirshipBehaviourFieldDecoratorParameter => {
678+ const value = getLiteralFromNode ( state , argument ) ;
647679
648- return { type : "invalid" , value : undefined } ;
649- }
650- } ) ,
651- } ) ;
680+ if ( value ) {
681+ return value ;
682+ } else {
683+ DiagnosticService . addDiagnostic (
684+ errors . decoratorParamsLiteralsOnly ( expression . arguments [ i ] ) ,
685+ ) ;
686+
687+ return { type : "invalid" , value : undefined } ;
652688 }
653- }
689+ } ) ,
690+ } ;
691+ }
654692
655- return items ;
656- } else {
693+ export function getClassDecorators ( state : TransformState , classNode : ts . ClassLikeDeclaration ) {
694+ const decorators = ts . hasDecorators ( classNode ) ? ts . getDecorators ( classNode ) : undefined ;
695+ if ( ! decorators ) {
657696 return [ ] ;
658697 }
698+
699+ const items = new Array < AirshipBehaviourClassDecorator > ( ) ;
700+
701+ for ( const decorator of decorators ) {
702+ const expression = decorator . expression ;
703+ if ( ! ts . isCallExpression ( expression ) ) continue ;
704+
705+ const aliasSymbol = state . typeChecker . getTypeAtLocation ( expression ) . aliasSymbol ;
706+ if ( ! aliasSymbol ) continue ;
707+
708+ const airshipFieldSymbol = state . services . airshipSymbolManager . getSymbolOrThrow ( "AirshipDecorator" ) ;
709+ if ( aliasSymbol !== airshipFieldSymbol ) continue ;
710+
711+ const decoratorName = expression . expression . getText ( ) ;
712+
713+ if ( decoratorName === "RequireComponent" ) {
714+ const processedDecorator = processRequireComponentDecorator ( state , classNode , expression ) ;
715+ if ( processedDecorator ) {
716+ items . push ( processedDecorator ) ;
717+ }
718+ } else {
719+ const processedDecorator = processGenericDecorator ( state , expression , decoratorName ) ;
720+ items . push ( processedDecorator ) ;
721+ }
722+ }
723+
724+ return items ;
659725}
660726
661727function getPropertyDecorators (
@@ -1056,3 +1122,4 @@ export function transformClassLikeDeclaration(state: TransformState, node: ts.Cl
10561122
10571123 return { statements, name : returnVar } ;
10581124}
1125+
0 commit comments