@@ -372,6 +372,52 @@ TEST(extract_cfml_tag_issue38) {
372372 PASS ();
373373}
374374
375+ /* --- CFML tag dialect: script functions inside a <cfscript> block of a tag
376+ * component. The HTML-derived cfml grammar keeps the <cfscript> body as an
377+ * opaque cf_script_content token, so these functions only surface once the
378+ * block is re-parsed with the cfscript grammar through the shared
379+ * included-ranges machinery (parse_one_embedded_block, #1852).
380+ * Also asserts the block-relative line numbers are remapped back to host-file
381+ * lines, and that a leading <cfsetting> void tag (which cascades ERROR nodes in
382+ * the cfml grammar) does not prevent recovery of the functions. --- */
383+ TEST (extract_cfml_embedded_cfscript_defs ) {
384+ /* Source layout (1-based lines): 1 <cfcomponent>, 2 <cfsetting>, 3 <cfscript>,
385+ * 4 greet(), 7 addTwo(), 10 </cfscript>, 11 <cffunction tagPing>, 14 close. */
386+ CBMFileResult * r = extract ("<cfcomponent>\n"
387+ "<cfsetting requesttimeout=\"10\">\n"
388+ "<cfscript>\n"
389+ " public string function greet(string who) {\n"
390+ " return \"hi \" & who;\n"
391+ " }\n"
392+ " private numeric function addTwo(numeric a) {\n"
393+ " return a + 2;\n"
394+ " }\n"
395+ "</cfscript>\n"
396+ "<cffunction name=\"tagPing\" returntype=\"string\">\n"
397+ " <cfreturn \"pong\">\n"
398+ "</cffunction>\n"
399+ "</cfcomponent>\n" ,
400+ CBM_LANG_CFML , "app" , "Service.cfc" );
401+ ASSERT_NOT_NULL (r );
402+ /* Script functions inside <cfscript> are recovered ... */
403+ ASSERT (has_def (r , "Function" , "greet" ));
404+ ASSERT (has_def (r , "Function" , "addTwo" ));
405+ /* ... alongside the tag-dialect <cffunction> in the same component. */
406+ ASSERT (has_def (r , "Function" , "tagPing" ));
407+ /* Line numbers are remapped from block-relative back to host-file lines. */
408+ for (int i = 0 ; i < r -> defs .count ; i ++ ) {
409+ const CBMDefinition * d = & r -> defs .items [i ];
410+ if (strcmp (d -> label , "Function" ) == 0 && strcmp (d -> name , "greet" ) == 0 ) {
411+ ASSERT (d -> start_line == 4 );
412+ }
413+ if (strcmp (d -> label , "Function" ) == 0 && strcmp (d -> name , "addTwo" ) == 0 ) {
414+ ASSERT (d -> start_line == 7 );
415+ }
416+ }
417+ cbm_free_result (r );
418+ PASS ();
419+ }
420+
375421/* --- Helm / Go template: named templates + include calls (#338) --- */
376422TEST (extract_helm_templates_issue338 ) {
377423 CBMFileResult * r = extract ("{{- define \"chart.fullname\" -}}\n"
@@ -1689,14 +1735,13 @@ TEST(cpp_function) {
16891735 * node when multiple tests share a file. Each must mint a distinct Function
16901736 * node whose name encodes the suite and case arguments. */
16911737TEST (cpp_gtest_same_name_collision_issue1266 ) {
1692- CBMFileResult * r = extract (
1693- "namespace demo { int assembleWidget(int s) { return s * 2; } }\n"
1694- "TEST(WidgetSuite, DoublesSmallSize) { demo::assembleWidget(1); }\n"
1695- "TEST(WidgetSuite, DoublesZero) { demo::assembleWidget(0); }\n"
1696- "TEST(WidgetSuite, DoublesLargeSize) {\n"
1697- " demo::assembleWidget(1000);\n"
1698- "}\n" ,
1699- CBM_LANG_CPP , "t" , "direct_test.cpp" );
1738+ CBMFileResult * r = extract ("namespace demo { int assembleWidget(int s) { return s * 2; } }\n"
1739+ "TEST(WidgetSuite, DoublesSmallSize) { demo::assembleWidget(1); }\n"
1740+ "TEST(WidgetSuite, DoublesZero) { demo::assembleWidget(0); }\n"
1741+ "TEST(WidgetSuite, DoublesLargeSize) {\n"
1742+ " demo::assembleWidget(1000);\n"
1743+ "}\n" ,
1744+ CBM_LANG_CPP , "t" , "direct_test.cpp" );
17001745 ASSERT_NOT_NULL (r );
17011746 ASSERT (has_def (r , "Function" , "TEST_WidgetSuite_DoublesSmallSize" ));
17021747 ASSERT (has_def (r , "Function" , "TEST_WidgetSuite_DoublesZero" ));
@@ -1708,10 +1753,9 @@ TEST(cpp_gtest_same_name_collision_issue1266) {
17081753
17091754/* #1266: TEST_F fixture macro also produces unique names. */
17101755TEST (cpp_gtest_f_unique_name_issue1266 ) {
1711- CBMFileResult * r = extract (
1712- "TEST_F(MyFixture, FirstTest) { doStuff(); }\n"
1713- "TEST_F(MyFixture, SecondTest) { doOtherStuff(); }\n" ,
1714- CBM_LANG_CPP , "t" , "fixture_test.cpp" );
1756+ CBMFileResult * r = extract ("TEST_F(MyFixture, FirstTest) { doStuff(); }\n"
1757+ "TEST_F(MyFixture, SecondTest) { doOtherStuff(); }\n" ,
1758+ CBM_LANG_CPP , "t" , "fixture_test.cpp" );
17151759 ASSERT_NOT_NULL (r );
17161760 ASSERT (has_def (r , "Function" , "TEST_F_MyFixture_FirstTest" ));
17171761 ASSERT (has_def (r , "Function" , "TEST_F_MyFixture_SecondTest" ));
@@ -3676,9 +3720,9 @@ TEST(extract_ts_decorators_survive_interleaved_comment) {
36763720 ASSERT_FALSE (r -> has_error );
36773721 const CBMDefinition * m = find_def_by_name (r , "login" );
36783722 ASSERT_NOT_NULL (m );
3679- ASSERT (decorators_contain (m , "Throttle" )); /* below the comment — always worked */
3680- ASSERT (decorators_contain (m , "HttpCode" )); /* above the comment — was dropped */
3681- ASSERT (decorators_contain (m , "Post" )); /* above the comment — was dropped */
3723+ ASSERT (decorators_contain (m , "Throttle" )); /* below the comment — always worked */
3724+ ASSERT (decorators_contain (m , "HttpCode" )); /* above the comment — was dropped */
3725+ ASSERT (decorators_contain (m , "Post" )); /* above the comment — was dropped */
36823726 cbm_free_result (r );
36833727 PASS ();
36843728}
@@ -3937,7 +3981,6 @@ TEST(extract_go_binary_concat_url_no_literal_suffix_issue1249) {
39373981 PASS ();
39383982}
39393983
3940-
39413984/* Reproduce-first: Java module QN must derive from the CONTAINING DIRECTORY, not
39423985 * the filename stem, so a top-level class `Outer` in `Outer.java` is `t.Outer`,
39433986 * NOT the doubled `t.Outer.Outer`. The nested method def QN must also equal the
@@ -6037,6 +6080,7 @@ SUITE(extraction) {
60376080 RUN_TEST (extract_qml_issue42 );
60386081 RUN_TEST (extract_cfscript_issue38 );
60396082 RUN_TEST (extract_cfml_tag_issue38 );
6083+ RUN_TEST (extract_cfml_embedded_cfscript_defs );
60406084 RUN_TEST (extract_helm_templates_issue338 );
60416085 RUN_TEST (extract_helm_values_toplevel_issue338 );
60426086
0 commit comments