@@ -1221,6 +1221,7 @@ fn link_class_metadata_async(
12211221/// Declaration format (`ɵɵngDeclareDirective`):
12221222/// - `propertyName: "publicName"` (simple)
12231223/// - `propertyName: ["publicName", "classPropertyName"]` (aliased)
1224+ /// - `propertyName: ["publicName", "classPropertyName", transformFn]` (aliased with transform)
12241225/// - `propertyName: { classPropertyName: "...", publicName: "...", isRequired: bool,
12251226/// isSignal: bool, transformFunction: expr }` (Angular 16+ object format)
12261227///
@@ -1256,28 +1257,27 @@ fn convert_inputs_to_definition_format(inputs_obj: &ObjectExpression<'_>, source
12561257 // Array: check if it's declaration format [publicName, classPropertyName]
12571258 // and convert to definition format [InputFlags, publicName, classPropertyName]
12581259 Expression :: ArrayExpression ( arr) => {
1259- if arr. elements . len ( ) == 2 {
1260- // Check if first element is a string (declaration format)
1261- let first_is_string = matches ! (
1262- arr. elements. first( ) ,
1263- Some ( ArrayExpressionElement :: StringLiteral ( _) )
1264- ) ;
1265- if first_is_string {
1266- // Declaration format: ["publicName", "classPropertyName"]
1267- // Convert to: [0, "publicName", "classPropertyName"]
1268- let arr_source =
1269- & source[ arr. span . start as usize + 1 ..arr. span . end as usize - 1 ] ;
1270- entries. push ( format ! ( "{quoted_key}: [0, {arr_source}]" ) ) ;
1271- } else {
1272- // Already in definition format or unknown, keep as is
1273- let val =
1274- & source[ p. value . span ( ) . start as usize ..p. value . span ( ) . end as usize ] ;
1275- entries. push ( format ! ( "{quoted_key}: {val}" ) ) ;
1276- }
1277- } else {
1278- // 3+ elements likely already in definition format, keep as is
1279- let val = & source[ p. value . span ( ) . start as usize ..p. value . span ( ) . end as usize ] ;
1260+ let val = & source[ p. value . span ( ) . start as usize ..p. value . span ( ) . end as usize ] ;
1261+ let first_is_string =
1262+ matches ! ( arr. elements. first( ) , Some ( ArrayExpressionElement :: StringLiteral ( _) ) ) ;
1263+
1264+ if !first_is_string {
1265+ // Already in definition format or unknown, keep as is.
12801266 entries. push ( format ! ( "{quoted_key}: {val}" ) ) ;
1267+ continue ;
1268+ }
1269+
1270+ let arr_source = & source[ arr. span . start as usize + 1 ..arr. span . end as usize - 1 ] ;
1271+ match arr. elements . len ( ) {
1272+ // Declaration format: ["publicName", "classPropertyName"]
1273+ // Convert to: [0, "publicName", "classPropertyName"]
1274+ 2 => entries. push ( format ! ( "{quoted_key}: [0, {arr_source}]" ) ) ,
1275+ // Since Angular 16.1, support multi-directive inputs, so we need to convert to the definition format.
1276+ // Declaration format: ["publicName", "classPropertyName", transformFn]
1277+ // Convert to: [2, "publicName", "classPropertyName", transformFn]
1278+ 3 => entries. push ( format ! ( "{quoted_key}: [2, {arr_source}]" ) ) ,
1279+ // 4+ elements likely already in definition format, keep as is.
1280+ _ => entries. push ( format ! ( "{quoted_key}: {val}" ) ) ,
12811281 }
12821282 }
12831283 // Object: Angular 16+ format with classPropertyName, publicName, isRequired, etc.
@@ -2439,6 +2439,26 @@ RxFor.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.1
24392439 ) ;
24402440 }
24412441
2442+ #[ test]
2443+ fn test_link_directive_input_array_with_transform ( ) {
2444+ let allocator = Allocator :: default ( ) ;
2445+ let code = r#"
2446+ import * as i0 from "@angular/core";
2447+ class MyDirective {
2448+ }
2449+ MyDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.0.0", ngImport: i0, type: MyDirective, selector: "[myDir]", inputs: { push: ["cdkConnectedOverlayPush", "push", i0.booleanAttribute] } });
2450+ "# ;
2451+ let result = link ( & allocator, code, "test.mjs" ) ;
2452+ assert ! ( result. linked) ;
2453+ assert ! (
2454+ result
2455+ . code
2456+ . contains( r#"push: [2, "cdkConnectedOverlayPush", "push", i0.booleanAttribute]"# ) ,
2457+ "Expected transform input array to be converted with InputFlags.HasDecoratorInputTransform. Got: {}" ,
2458+ result. code
2459+ ) ;
2460+ }
2461+
24422462 #[ test]
24432463 fn test_link_component_basic ( ) {
24442464 let allocator = Allocator :: default ( ) ;
0 commit comments