From 2753bb4a4362d7c8cce8f452320ee5e2f5dee0c4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 03:46:40 +0000 Subject: [PATCH 1/3] Initial plan From e67ab4d0b1fda0a1fea9001865a32007d470d4d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 03:52:08 +0000 Subject: [PATCH 2/3] Add @extends annotation support for single-file components Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com> --- models/EmptySingleFileComponent.bx | 2 +- models/EmptySingleFileComponent.cfc | 2 +- models/SingleFileComponentBuilder.cfc | 20 ++++++++++++++++++- test-harness/tests/specs/CBWIRESpec.cfc | 10 ++++++++++ ...ire_from_single_file_boxlang_component.bxm | 12 +++++++++++ ...om_basewire_from_single_file_component.cfm | 12 +++++++++++ 6 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 test-harness/wires/test/should_extend_custom_basewire_from_single_file_boxlang_component.bxm create mode 100644 test-harness/wires/test/should_extend_custom_basewire_from_single_file_component.cfm diff --git a/models/EmptySingleFileComponent.bx b/models/EmptySingleFileComponent.bx index ac22dc0c..676d96ab 100644 --- a/models/EmptySingleFileComponent.bx +++ b/models/EmptySingleFileComponent.bx @@ -1,4 +1,4 @@ -class extends="cbwire.models.Component" { +class extends="{{ EXTENDS_PATH }}" { {{ CFC_CONTENTS }} diff --git a/models/EmptySingleFileComponent.cfc b/models/EmptySingleFileComponent.cfc index 4f95e6d0..a6877a69 100644 --- a/models/EmptySingleFileComponent.cfc +++ b/models/EmptySingleFileComponent.cfc @@ -1,4 +1,4 @@ -component extends="cbwire.models.Component" { +component extends="{{ EXTENDS_PATH }}" { {{ CFC_CONTENTS }} diff --git a/models/SingleFileComponentBuilder.cfc b/models/SingleFileComponentBuilder.cfc index b4c1e983..b2f1dbeb 100644 --- a/models/SingleFileComponentBuilder.cfc +++ b/models/SingleFileComponentBuilder.cfc @@ -46,6 +46,7 @@ component accessors="true" singleton { local.fileContents = fileRead( arguments.cfmPath ); local.singleFileContents = ""; local.remainingContents = ""; + local.extendsPath = "cbwire.models.Component"; local.startedWire = false; local.endedWire = false; @@ -64,6 +65,15 @@ component accessors="true" singleton { local.insideScriptTag = false; } + // Parse @extends annotation + if ( local.insideScriptTag && local.line contains "@extends" ) { + local.extendsMatch = reFindNoCase( "@extends\s*\(\s*['""]?([^'"")\s]+)['""]?\s*\)", local.line, 1, true ); + if ( arrayLen( local.extendsMatch.match ) >= 2 && len( local.extendsMatch.match[ 2 ] ) ) { + local.extendsPath = local.extendsMatch.match[ 2 ]; + } + continue; + } + if ( local.insideScriptTag && local.line contains "@startWire" ) { local.startedWire = true; continue; @@ -82,7 +92,8 @@ component accessors="true" singleton { return { "singleFileContents" : local.singleFileContents, - "remainingContents" : local.remainingContents + "remainingContents" : local.remainingContents, + "extendsPath" : local.extendsPath }; } @@ -151,6 +162,13 @@ component accessors="true" singleton { "one" ); + local.emptySingleFileComponent = replaceNoCase( + local.emptySingleFileComponent, + "{{ EXTENDS_PATH }}", + local.parsedContents.extendsPath, + "one" + ); + local.uuid = createUUID(); fileWrite( local.tmpClassPath, local.emptySingleFileComponent ); diff --git a/test-harness/tests/specs/CBWIRESpec.cfc b/test-harness/tests/specs/CBWIRESpec.cfc index b21a2916..2cd6dddc 100644 --- a/test-harness/tests/specs/CBWIRESpec.cfc +++ b/test-harness/tests/specs/CBWIRESpec.cfc @@ -303,6 +303,16 @@ component extends="coldbox.system.testing.BaseTestCase" { expect( result ).toInclude( "
Result: Hello World!
" ); } ); + it( "should extend custom basewire from single file component", function() { + var result = CBWIREController.wire( "test.should_extend_custom_basewire_from_single_file_component" ); + expect( result ).toInclude( "Result: Hello World!
" ); + } ); + + it( title="should extend custom basewire from single file boxlang component", body=function() { + var result = CBWIREController.wire( "test.should_extend_custom_basewire_from_single_file_boxlang_component" ); + expect( result ).toInclude( "Result: Hello World!
" ); + }, skip=!isBoxLang() ); + it( "should be able to access event from template", function() { var result = CBWIREController.wire( "test.should_be_able_to_access_event_from_template" ); expect( result ).toInclude( "Event is object: true
" ); diff --git a/test-harness/wires/test/should_extend_custom_basewire_from_single_file_boxlang_component.bxm b/test-harness/wires/test/should_extend_custom_basewire_from_single_file_boxlang_component.bxm new file mode 100644 index 00000000..7ec9cdff --- /dev/null +++ b/test-harness/wires/test/should_extend_custom_basewire_from_single_file_boxlang_component.bxm @@ -0,0 +1,12 @@ +Result: #sayHello()#
+Result: #sayHello()#
+