11using NUnit . Framework ;
2+ using System ;
3+ using System . Collections . Generic ;
4+ using System . IO ;
25
36namespace CppAst . Tests
47{
@@ -224,7 +227,7 @@ public void TestFunctionExport()
224227 Assert . True ( cppFunction . IsPublicExport ( ) ) ;
225228 }
226229 } ,
227- new CppParserOptions ( ) { }
230+ new CppParserOptions ( ) { }
228231 ) ;
229232
230233 ParseAssert ( text ,
@@ -353,7 +356,356 @@ public void TestFunctionPointersByParam()
353356 ) ;
354357 }
355358
359+ [ Test ]
360+ public void TestFunctionBody ( )
361+ {
362+ var options = new CppParserOptions ( ) ;
363+ options . ParseFunctionBodies = true ;
364+ var headerFilename = "test_function_body.h" ;
365+
366+ var text = @"
367+ void function0();
368+ int function1(int a, float b) {
369+ return a + (int)b;
370+ }
371+ float function2(int x);
372+ " ;
373+
374+ var currentDirectory = Environment . CurrentDirectory ;
375+ var headerFile = Path . Combine ( currentDirectory , headerFilename ) ;
376+ File . WriteAllText ( headerFile , text ) ;
377+
378+ var compilation = CppParser . ParseFile ( headerFile , options ) ;
379+
380+ Assert . False ( compilation . HasErrors ) ;
381+ Assert . AreEqual ( 3 , compilation . Functions . Count ) ;
382+
383+ {
384+ var cppFunction = compilation . Functions [ 0 ] ;
385+ Assert . AreEqual ( "function0" , cppFunction . Name ) ;
386+ Assert . IsNull ( cppFunction . BodySpan ) ;
387+ }
388+
389+ {
390+ var cppFunction = compilation . Functions [ 1 ] ;
391+ Assert . AreEqual ( "function1" , cppFunction . Name ) ;
392+ Assert . IsNotNull ( cppFunction . BodySpan ) ;
393+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
394+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
395+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
396+ }
397+
398+ {
399+ var cppFunction = compilation . Functions [ 2 ] ;
400+ Assert . AreEqual ( "function2" , cppFunction . Name ) ;
401+ Assert . IsNull ( cppFunction . BodySpan ) ;
402+ }
403+ }
404+
405+ [ Test ]
406+ public void TestInlineMethodBody ( )
407+ {
408+ var options = new CppParserOptions ( ) ;
409+ options . ParseFunctionBodies = true ;
410+ var headerFilename = "test_inline_method_body.h" ;
411+
412+ var text = @"
413+ typedef unsigned int ImWchar;
414+
415+ class ImFont {
416+ public:
417+ bool IsGlyphInFont(ImWchar c)
418+ {
419+ return false;
420+ }
421+
422+ bool AnotherMethod(ImWchar c) {
423+ if (c == 0) return true;
424+ return false;
425+ }
426+ };
427+ " ;
428+
429+ var currentDirectory = Environment . CurrentDirectory ;
430+ var headerFile = Path . Combine ( currentDirectory , headerFilename ) ;
431+ File . WriteAllText ( headerFile , text ) ;
432+
433+ var compilation = CppParser . ParseFile ( headerFile , options ) ;
434+
435+ Assert . False ( compilation . HasErrors ) ;
436+ Assert . AreEqual ( 1 , compilation . Classes . Count ) ;
437+
438+ var cls = compilation . Classes [ 0 ] ;
439+ Assert . AreEqual ( "ImFont" , cls . Name ) ;
440+ Assert . AreEqual ( 2 , cls . Functions . Count ) ;
441+
442+ {
443+ var cppFunction = cls . Functions [ 0 ] ;
444+ Assert . AreEqual ( "IsGlyphInFont" , cppFunction . Name ) ;
445+ Assert . IsNotNull ( cppFunction . BodySpan , "IsGlyphInFont should have BodySpan - this is the bug reported" ) ;
446+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
447+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
448+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
449+ }
450+
451+ {
452+ var cppFunction = cls . Functions [ 1 ] ;
453+ Assert . AreEqual ( "AnotherMethod" , cppFunction . Name ) ;
454+ Assert . IsNotNull ( cppFunction . BodySpan , "AnotherMethod should have BodySpan" ) ;
455+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
456+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
457+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
458+ }
459+ }
460+
461+ [ Test ]
462+ public void TestFunctionOverloadBodySpan ( )
463+ {
464+ var options = new CppParserOptions ( ) ;
465+ options . ParseFunctionBodies = true ;
466+ var headerFilename = "test_function_overload_body.h" ;
467+
468+ var text = @"
469+ int process(int x)
470+ {
471+ return x * 2;
472+ }
356473
474+ int process(float y)
475+ {
476+ return (int)(y * 3.0f);
477+ }
478+
479+ int process(int x, int y)
480+ {
481+ return x + y;
482+ }
483+ " ;
484+
485+ var currentDirectory = Environment . CurrentDirectory ;
486+ var headerFile = Path . Combine ( currentDirectory , headerFilename ) ;
487+ File . WriteAllText ( headerFile , text ) ;
488+
489+ var compilation = CppParser . ParseFile ( headerFile , options ) ;
490+
491+ Assert . False ( compilation . HasErrors ) ;
492+ Assert . AreEqual ( 3 , compilation . Functions . Count ) ;
493+
494+ {
495+ var cppFunction = compilation . Functions [ 0 ] ;
496+ Assert . AreEqual ( "process" , cppFunction . Name ) ;
497+ Assert . AreEqual ( 1 , cppFunction . Parameters . Count ) ;
498+ Assert . IsNotNull ( cppFunction . BodySpan , "process(int) should have BodySpan" ) ;
499+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
500+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
501+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
502+ }
503+
504+ {
505+ var cppFunction = compilation . Functions [ 1 ] ;
506+ Assert . AreEqual ( "process" , cppFunction . Name ) ;
507+ Assert . AreEqual ( 1 , cppFunction . Parameters . Count ) ;
508+ Assert . IsNotNull ( cppFunction . BodySpan , "process(float) should have BodySpan" ) ;
509+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
510+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
511+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
512+ }
513+
514+ {
515+ var cppFunction = compilation . Functions [ 2 ] ;
516+ Assert . AreEqual ( "process" , cppFunction . Name ) ;
517+ Assert . AreEqual ( 2 , cppFunction . Parameters . Count ) ;
518+ Assert . IsNotNull ( cppFunction . BodySpan , "process(int, int) should have BodySpan" ) ;
519+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
520+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
521+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
522+ }
523+ HashSet < int > startLines = new HashSet < int > ( ) ;
524+ foreach ( var function in compilation . Functions )
525+ {
526+ Assert . True ( startLines . Add ( function . BodySpan . Value . Start . Line ) ) ;
527+ }
528+ }
529+
530+ [ Test ]
531+ public void TestMethodOverloadBodySpan ( )
532+ {
533+ var options = new CppParserOptions ( ) ;
534+ options . ParseFunctionBodies = true ;
535+ var headerFilename = "test_method_overload_body.h" ;
536+
537+ var text = @"
538+ class Calculator {
539+ public:
540+ int calculate(int x) {
541+ return x * 2;
542+ }
543+
544+ int calculate(float y) {
545+ return (int)(y * 3.0f);
546+ }
547+
548+ int calculate(int x, int y) {
549+ return x + y;
550+ }
551+ };
552+ " ;
553+
554+ var currentDirectory = Environment . CurrentDirectory ;
555+ var headerFile = Path . Combine ( currentDirectory , headerFilename ) ;
556+ File . WriteAllText ( headerFile , text ) ;
557+
558+ var compilation = CppParser . ParseFile ( headerFile , options ) ;
559+
560+ Assert . False ( compilation . HasErrors ) ;
561+ Assert . AreEqual ( 1 , compilation . Classes . Count ) ;
562+
563+ var cls = compilation . Classes [ 0 ] ;
564+ Assert . AreEqual ( "Calculator" , cls . Name ) ;
565+ Assert . AreEqual ( 3 , cls . Functions . Count ) ;
566+
567+ {
568+ var cppFunction = cls . Functions [ 0 ] ;
569+ Assert . AreEqual ( "calculate" , cppFunction . Name ) ;
570+ Assert . AreEqual ( 1 , cppFunction . Parameters . Count ) ;
571+ Assert . IsNotNull ( cppFunction . BodySpan , "calculate(int) should have BodySpan" ) ;
572+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
573+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
574+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
575+ }
576+
577+ {
578+ var cppFunction = cls . Functions [ 1 ] ;
579+ Assert . AreEqual ( "calculate" , cppFunction . Name ) ;
580+ Assert . AreEqual ( 1 , cppFunction . Parameters . Count ) ;
581+ Assert . IsNotNull ( cppFunction . BodySpan , "calculate(float) should have BodySpan" ) ;
582+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
583+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
584+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
585+ }
586+
587+ {
588+ var cppFunction = cls . Functions [ 2 ] ;
589+ Assert . AreEqual ( "calculate" , cppFunction . Name ) ;
590+ Assert . AreEqual ( 2 , cppFunction . Parameters . Count ) ;
591+ Assert . IsNotNull ( cppFunction . BodySpan , "calculate(int, int) should have BodySpan" ) ;
592+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
593+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
594+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
595+ }
596+
597+ HashSet < int > startLines = new HashSet < int > ( ) ;
598+ foreach ( var function in cls . Functions )
599+ {
600+ Assert . True ( startLines . Add ( function . BodySpan . Value . Start . Line ) ) ;
601+ }
602+ }
603+
604+ [ Test ]
605+ public void TestMethodOverloadDefinitionOutsideClassBodySpan ( )
606+ {
607+ var options = new CppParserOptions ( ) ;
608+ options . ParseFunctionBodies = true ;
609+ var headerFilename = "test_method_overload_outside_class_body.h" ;
610+
611+ var text = @"
612+ class Calculator {
613+ public:
614+ int calculate(int x);
615+ int calculate(float y);
616+ int calculate(int x, int y);
617+ };
618+
619+ int Calculator::calculate(int x)
620+ {
621+ return x * 2;
622+ }
623+
624+ int Calculator::calculate(float y)
625+ {
626+ return (int)(y * 3.0f);
627+ }
628+
629+ int Calculator::calculate(int x, int y)
630+ {
631+ return x + y;
632+ }
633+
634+ class Calculator2 {
635+ public:
636+ int calculate(int x);
637+ int calculate(float y);
638+ int calculate(int x, int y);
639+ };
640+
641+ int Calculator2::calculate(int x)
642+ {
643+ return x * 2;
644+ }
645+
646+ int Calculator2::calculate(float y)
647+ {
648+ return (int)(y * 3.0f);
649+ }
650+
651+ int Calculator2::calculate(int x, int y)
652+ {
653+ return x + y;
654+ }
655+ " ;
656+
657+ var currentDirectory = Environment . CurrentDirectory ;
658+ var headerFile = Path . Combine ( currentDirectory , headerFilename ) ;
659+ File . WriteAllText ( headerFile , text ) ;
660+
661+ var compilation = CppParser . ParseFile ( headerFile , options ) ;
662+
663+ Assert . False ( compilation . HasErrors ) ;
664+ Assert . AreEqual ( 2 , compilation . Classes . Count ) ;
665+
666+ var cls = compilation . Classes [ 0 ] ;
667+ Assert . AreEqual ( "Calculator" , cls . Name ) ;
668+ Assert . AreEqual ( 3 , cls . Functions . Count ) ;
669+
670+ {
671+ var cppFunction = cls . Functions [ 0 ] ;
672+ Assert . AreEqual ( "calculate" , cppFunction . Name ) ;
673+ Assert . AreEqual ( 1 , cppFunction . Parameters . Count ) ;
674+ Assert . IsNotNull ( cppFunction . BodySpan , "calculate(int) should have BodySpan" ) ;
675+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
676+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
677+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
678+ }
679+
680+ {
681+ var cppFunction = cls . Functions [ 1 ] ;
682+ Assert . AreEqual ( "calculate" , cppFunction . Name ) ;
683+ Assert . AreEqual ( 1 , cppFunction . Parameters . Count ) ;
684+ Assert . IsNotNull ( cppFunction . BodySpan , "calculate(float) should have BodySpan" ) ;
685+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
686+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
687+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
688+ }
689+
690+ {
691+ var cppFunction = cls . Functions [ 2 ] ;
692+ Assert . AreEqual ( "calculate" , cppFunction . Name ) ;
693+ Assert . AreEqual ( 2 , cppFunction . Parameters . Count ) ;
694+ Assert . IsNotNull ( cppFunction . BodySpan , "calculate(int, int) should have BodySpan" ) ;
695+ Assert . Greater ( cppFunction . BodySpan . Value . Start . Line , 0 ) ;
696+ Assert . Greater ( cppFunction . BodySpan . Value . End . Line , 0 ) ;
697+ Assert . GreaterOrEqual ( cppFunction . BodySpan . Value . End . Offset , cppFunction . BodySpan . Value . Start . Offset ) ;
698+ }
699+
700+ HashSet < int > startLines = new HashSet < int > ( ) ;
701+ foreach ( var cls2 in compilation . Classes )
702+ {
703+ foreach ( var function in cls2 . Functions )
704+ {
705+ Assert . True ( startLines . Add ( function . BodySpan . Value . Start . Line ) ) ;
706+ }
707+ }
708+ }
357709
358710 }
359711}
0 commit comments