Skip to content

Commit d70418d

Browse files
Brooooooklynclaude
andcommitted
fix(angular): strip TS types from RawSource, add expression-body fallback, thread source_text through property decorators
Three reviewer fixes: 1. P1 - RawSource now strips TypeScript type annotations via parse-transform-codegen pipeline, preventing invalid JS output like `(dep: Dep) => { ... }` in generated code. 2. Medium - Expression-body arrows with unsupported inner expressions (e.g., `() => someUnsupportedExpr`) now fall back to RawSource instead of returning None. 3. P2 - Thread source_text through property_decorators.rs so @input({transform}), @ViewChild, @ContentChild arguments with complex expressions are preserved via RawSource fallback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 90ccab0 commit d70418d

File tree

7 files changed

+246
-107
lines changed

7 files changed

+246
-107
lines changed

crates/oxc_angular_compiler/src/component/decorator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ pub fn extract_component_metadata<'a>(
241241
extract_constructor_deps(allocator, class, import_map, has_superclass);
242242

243243
// Extract inputs from @Input decorators on class members
244-
metadata.inputs = extract_input_metadata(allocator, class);
244+
metadata.inputs = extract_input_metadata(allocator, class, source_text);
245245

246246
// Extract outputs from @Output decorators on class members
247247
metadata.outputs = extract_output_metadata(allocator, class);

crates/oxc_angular_compiler/src/component/transform.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,11 +1636,11 @@ pub fn transform_angular_file(
16361636
let template = allocator.alloc_str(&template_string);
16371637
// 4.5 Extract view queries from the class (for @ViewChild/@ViewChildren)
16381638
// These need to be passed to compile_component_full so predicates can be pooled
1639-
let view_queries = extract_view_queries(allocator, class);
1639+
let view_queries = extract_view_queries(allocator, class, Some(source));
16401640

16411641
// 4.6 Extract content queries from the class (for @ContentChild/@ContentChildren)
16421642
// Signal-based queries (contentChild(), contentChildren()) are also detected here
1643-
let content_queries = extract_content_queries(allocator, class);
1643+
let content_queries = extract_content_queries(allocator, class, Some(source));
16441644

16451645
// Collect content query property names for .d.ts generation
16461646
// (before content_queries is moved into compile_component_full)

crates/oxc_angular_compiler/src/directive/decorator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ pub fn extract_directive_metadata<'a>(
167167
}
168168

169169
// Extract @Input/@Output/@HostBinding/@HostListener from class members
170-
builder = builder.extract_from_class(allocator, class);
170+
builder = builder.extract_from_class(allocator, class, source_text);
171171

172172
// Detect if ngOnChanges lifecycle hook is implemented
173173
// Similar to Angular's: const usesOnChanges = members.some(member => ...)

crates/oxc_angular_compiler/src/directive/metadata.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,15 @@ impl<'a> R3DirectiveMetadataBuilder<'a> {
410410
///
411411
/// # Returns
412412
/// The builder with all extracted metadata added.
413-
pub fn extract_from_class(mut self, allocator: &'a Allocator, class: &'a Class<'a>) -> Self {
413+
pub fn extract_from_class(
414+
mut self,
415+
allocator: &'a Allocator,
416+
class: &'a Class<'a>,
417+
source_text: Option<&'a str>,
418+
) -> Self {
414419
// Extract inputs from @Input decorators
415-
let inputs = super::property_decorators::extract_input_metadata(allocator, class);
420+
let inputs =
421+
super::property_decorators::extract_input_metadata(allocator, class, source_text);
416422
for input in inputs {
417423
self = self.add_input(input);
418424
}
@@ -424,13 +430,15 @@ impl<'a> R3DirectiveMetadataBuilder<'a> {
424430
}
425431

426432
// Extract view queries from @ViewChild/@ViewChildren
427-
let view_queries = super::property_decorators::extract_view_queries(allocator, class);
433+
let view_queries =
434+
super::property_decorators::extract_view_queries(allocator, class, source_text);
428435
for query in view_queries {
429436
self = self.add_view_query(query);
430437
}
431438

432439
// Extract content queries from @ContentChild/@ContentChildren
433-
let content_queries = super::property_decorators::extract_content_queries(allocator, class);
440+
let content_queries =
441+
super::property_decorators::extract_content_queries(allocator, class, source_text);
434442
for query in content_queries {
435443
self = self.add_query(query);
436444
}
@@ -597,7 +605,7 @@ mod tests {
597605
let builder = R3DirectiveMetadataBuilder::new(&allocator)
598606
.name(Ident::from("TestDirective"))
599607
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("TestDirective")))
600-
.extract_from_class(&allocator, class.unwrap());
608+
.extract_from_class(&allocator, class.unwrap(), Some(code));
601609

602610
let metadata = builder.build();
603611
assert!(metadata.is_some());
@@ -635,7 +643,7 @@ mod tests {
635643
let builder = R3DirectiveMetadataBuilder::new(&allocator)
636644
.name(Ident::from("TestDirective"))
637645
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("TestDirective")))
638-
.extract_from_class(&allocator, class.unwrap());
646+
.extract_from_class(&allocator, class.unwrap(), Some(code));
639647

640648
let metadata = builder.build();
641649
assert!(metadata.is_some());
@@ -668,7 +676,7 @@ mod tests {
668676
let builder = R3DirectiveMetadataBuilder::new(&allocator)
669677
.name(Ident::from("TestComponent"))
670678
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("TestComponent")))
671-
.extract_from_class(&allocator, class.unwrap());
679+
.extract_from_class(&allocator, class.unwrap(), Some(code));
672680

673681
let metadata = builder.build();
674682
assert!(metadata.is_some());
@@ -701,7 +709,7 @@ mod tests {
701709
let builder = R3DirectiveMetadataBuilder::new(&allocator)
702710
.name(Ident::from("TestComponent"))
703711
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("TestComponent")))
704-
.extract_from_class(&allocator, class.unwrap());
712+
.extract_from_class(&allocator, class.unwrap(), Some(code));
705713

706714
let metadata = builder.build();
707715
assert!(metadata.is_some());
@@ -734,7 +742,7 @@ mod tests {
734742
let builder = R3DirectiveMetadataBuilder::new(&allocator)
735743
.name(Ident::from("TestDirective"))
736744
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("TestDirective")))
737-
.extract_from_class(&allocator, class.unwrap());
745+
.extract_from_class(&allocator, class.unwrap(), Some(code));
738746

739747
let metadata = builder.build();
740748
assert!(metadata.is_some());
@@ -769,7 +777,7 @@ mod tests {
769777
let builder = R3DirectiveMetadataBuilder::new(&allocator)
770778
.name(Ident::from("TestDirective"))
771779
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("TestDirective")))
772-
.extract_from_class(&allocator, class.unwrap());
780+
.extract_from_class(&allocator, class.unwrap(), Some(code));
773781

774782
let metadata = builder.build();
775783
assert!(metadata.is_some());
@@ -807,7 +815,7 @@ mod tests {
807815
let builder = R3DirectiveMetadataBuilder::new(&allocator)
808816
.name(Ident::from("TestComponent"))
809817
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("TestComponent")))
810-
.extract_from_class(&allocator, class.unwrap());
818+
.extract_from_class(&allocator, class.unwrap(), Some(code));
811819

812820
let metadata = builder.build();
813821
assert!(metadata.is_some());
@@ -837,7 +845,7 @@ mod tests {
837845
let builder = R3DirectiveMetadataBuilder::new(&allocator)
838846
.name(Ident::from("EmptyDirective"))
839847
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("EmptyDirective")))
840-
.extract_from_class(&allocator, class.unwrap());
848+
.extract_from_class(&allocator, class.unwrap(), Some(code));
841849

842850
let metadata = builder.build();
843851
assert!(metadata.is_some());
@@ -870,7 +878,7 @@ mod tests {
870878
.name(Ident::from("TestDirective"))
871879
.r#type(OutputAstBuilder::variable(&allocator, Ident::from("TestDirective")))
872880
.add_input(R3InputMetadata::simple(Ident::from("existingInput")))
873-
.extract_from_class(&allocator, class.unwrap());
881+
.extract_from_class(&allocator, class.unwrap(), Some(code));
874882

875883
let metadata = builder.build();
876884
assert!(metadata.is_some());

0 commit comments

Comments
 (0)