Skip to content

Commit ac21093

Browse files
committed
Fix BodySpan matching for overloaded functions and methods
1 parent 492dc8c commit ac21093

2 files changed

Lines changed: 262 additions & 27 deletions

File tree

src/CppAst.Tests/TestFunctions.cs

Lines changed: 226 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using NUnit.Framework;
22
using System;
3+
using System.Collections.Generic;
34
using System.IO;
45

56
namespace CppAst.Tests
@@ -226,7 +227,7 @@ public void TestFunctionExport()
226227
Assert.True(cppFunction.IsPublicExport());
227228
}
228229
},
229-
new CppParserOptions() { }
230+
new CppParserOptions() { }
230231
);
231232

232233
ParseAssert(text,
@@ -361,7 +362,7 @@ public void TestFunctionBody()
361362
var options = new CppParserOptions();
362363
options.ParseFunctionBodies = true;
363364
var headerFilename = "test_function_body.h";
364-
365+
365366
var text = @"
366367
void function0();
367368
int function1(int a, float b) {
@@ -373,7 +374,7 @@ int function1(int a, float b) {
373374
var currentDirectory = Environment.CurrentDirectory;
374375
var headerFile = Path.Combine(currentDirectory, headerFilename);
375376
File.WriteAllText(headerFile, text);
376-
377+
377378
var compilation = CppParser.ParseFile(headerFile, options);
378379

379380
Assert.False(compilation.HasErrors);
@@ -407,7 +408,7 @@ public void TestInlineMethodBody()
407408
var options = new CppParserOptions();
408409
options.ParseFunctionBodies = true;
409410
var headerFilename = "test_inline_method_body.h";
410-
411+
411412
var text = @"
412413
typedef unsigned int ImWchar;
413414
@@ -428,12 +429,12 @@ bool AnotherMethod(ImWchar c) {
428429
var currentDirectory = Environment.CurrentDirectory;
429430
var headerFile = Path.Combine(currentDirectory, headerFilename);
430431
File.WriteAllText(headerFile, text);
431-
432+
432433
var compilation = CppParser.ParseFile(headerFile, options);
433434

434435
Assert.False(compilation.HasErrors);
435436
Assert.AreEqual(1, compilation.Classes.Count);
436-
437+
437438
var cls = compilation.Classes[0];
438439
Assert.AreEqual("ImFont", cls.Name);
439440
Assert.AreEqual(2, cls.Functions.Count);
@@ -458,52 +459,253 @@ bool AnotherMethod(ImWchar c) {
458459
}
459460

460461
[Test]
461-
public void TestMethodDefinitionOutsideClass()
462+
public void TestFunctionOverloadBodySpan()
462463
{
463464
var options = new CppParserOptions();
464465
options.ParseFunctionBodies = true;
465-
var headerFilename = "test_method_outside_class.h";
466-
466+
var headerFilename = "test_function_overload_body.h";
467+
467468
var text = @"
468-
typedef unsigned int ImWchar;
469+
int process(int x)
470+
{
471+
return x * 2;
472+
}
469473
470-
class ImFont {
471-
public:
472-
bool IsGlyphInFont(ImWchar c);
473-
};
474+
int process(float y)
475+
{
476+
return (int)(y * 3.0f);
477+
}
474478
475-
bool ImFont::IsGlyphInFont(ImWchar c)
479+
int process(int x, int y)
476480
{
477-
return false;
481+
return x + y;
478482
}
479483
";
480484

481485
var currentDirectory = Environment.CurrentDirectory;
482486
var headerFile = Path.Combine(currentDirectory, headerFilename);
483487
File.WriteAllText(headerFile, text);
484-
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+
485558
var compilation = CppParser.ParseFile(headerFile, options);
486559

487560
Assert.False(compilation.HasErrors);
488561
Assert.AreEqual(1, compilation.Classes.Count);
489-
490-
var cls = compilation.Classes[0];
491-
Assert.AreEqual("ImFont", cls.Name);
492-
493562

494-
Assert.AreEqual(1, cls.Functions.Count);
563+
var cls = compilation.Classes[0];
564+
Assert.AreEqual("Calculator", cls.Name);
565+
Assert.AreEqual(3, cls.Functions.Count);
495566

496567
{
497568
var cppFunction = cls.Functions[0];
498-
Assert.AreEqual("IsGlyphInFont", cppFunction.Name);
499-
Assert.IsNotNull(cppFunction.BodySpan, "IsGlyphInFont should have BodySpan - this is the bug reported (method defined outside class)");
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");
500582
Assert.Greater(cppFunction.BodySpan.Value.Start.Line, 0);
501583
Assert.Greater(cppFunction.BodySpan.Value.End.Line, 0);
502584
Assert.GreaterOrEqual(cppFunction.BodySpan.Value.End.Offset, cppFunction.BodySpan.Value.Start.Offset);
503585
}
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+
}
504602
}
505603

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+
}
506679

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+
}
507709

508710
}
509711
}

0 commit comments

Comments
 (0)