Skip to content

Commit

Permalink
Merge pull request #9 from CognexVisionSoftware/feature/fix_using
Browse files Browse the repository at this point in the history
'using' is not recognized
  • Loading branch information
harsszegi authored Nov 29, 2023
2 parents 224a3aa + 1ef651d commit 9395218
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 9 deletions.
41 changes: 41 additions & 0 deletions src/CppAst.Tests/TestMisc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using NUnit.Framework;

namespace CppAst.Tests
{
public class TestMisc : InlineTestBase
{
[Test]
public void TestMiscFeatures()
{
ParseAssert(@"
class Foo
{
public:
Foo(int x) : x_{x} {}
private:
int x_{0};
};
class Bar : public Foo
{
public:
using Foo::Foo;
};
",
compilation =>
{
Assert.False(compilation.HasErrors);
Assert.AreEqual(2, compilation.Classes.Count);
Assert.AreEqual(1, compilation.Classes[0].Constructors.Count);
// Bar will get 3 constructors
Assert.AreEqual(3, compilation.Classes[1].Constructors.Count);
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[0].Visibility);
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[1].Visibility);
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[2].Visibility);
}
);
}
}
}
55 changes: 46 additions & 9 deletions src/CppAst/CppModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,44 @@ private CppClass VisitClassDecl(CXCursor cursor, void* data)
return cppStruct;
}

private CppFunction VisitUsing(CXCursor cursor, CXCursor parent, void* data)
{
var contextContainer = GetOrCreateDeclarationContainer(cursor.SemanticParent, data);
var container = contextContainer.DeclarationContainer;

if (container == null)
{
WarningUnhandled(cursor, parent);
return null;
}

cursor.VisitChildren((childCursor, funcCursor, clientData) =>
{
// Please note that this is not the complete using implementation,
// it only works with constructors
if (childCursor.Kind == CXCursorKind.CXCursor_OverloadedDeclRef)
{
// We simply copy the overloaded functions into the current class
for (uint i=0;i< childCursor.NumOverloadedDecls; i++)
{
VisitFunctionDecl(cursor, childCursor.GetOverloadedDecl(i), parent, clientData);
}
return CXChildVisitResult.CXChildVisit_Break;
}
return CXChildVisitResult.CXChildVisit_Continue;
}, new CXClientData((IntPtr)data));

return null;
}

private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* data)
{
CppElement element = null;
switch (cursor.Kind)
{
case CXCursorKind.CXCursor_UsingDeclaration:
element = VisitUsing(cursor, parent, data);
break;
case CXCursorKind.CXCursor_FieldDecl:
case CXCursorKind.CXCursor_VarDecl:
{
Expand Down Expand Up @@ -390,7 +423,7 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
case CXCursorKind.CXCursor_FunctionDecl:
case CXCursorKind.CXCursor_Constructor:
case CXCursorKind.CXCursor_CXXMethod:
element = VisitFunctionDecl(cursor, parent, data);
element = VisitFunctionDecl(cursor, cursor, parent, data);
break;

case CXCursorKind.CXCursor_UsingDirective:
Expand Down Expand Up @@ -1227,43 +1260,47 @@ private static CppStorageQualifier GetStorageQualifier(CXCursor cursor)
return CppStorageQualifier.None;
}

private CppFunction VisitFunctionDecl(CXCursor cursor, CXCursor parent, void* data)
private CppFunction VisitFunctionDecl(CXCursor destinationCursor, CXCursor cursor, CXCursor parent, void* data)
{
var destinationContextContainer = GetOrCreateDeclarationContainer(destinationCursor.SemanticParent, data);
var destinationContainer = destinationContextContainer.DeclarationContainer;
var contextContainer = GetOrCreateDeclarationContainer(cursor.SemanticParent, data);
var container = contextContainer.DeclarationContainer;

if (container == null)
if (destinationContainer == null || container == null)
{
WarningUnhandled(cursor, parent);
return null;
}

var functionName = GetCursorSpelling(cursor);
// This (not using 'cursor', but 'destinationCursor') is only used when we pulling in constructors from Foo, into Bar
// We are renaming effectively the pulled in 'Foo' constructor into 'Bar'
var functionName = GetCursorSpelling(destinationCursor);

//We need ignore the function define out in the class definition here(Otherwise it will has two same functions here~)!
var semKind = cursor.SemanticParent.Kind;
var semKind = destinationCursor.SemanticParent.Kind;
if ((semKind == CXCursorKind.CXCursor_StructDecl || semKind == CXCursorKind.CXCursor_ClassDecl)
&& cursor.LexicalParent != cursor.SemanticParent)
&& destinationCursor.LexicalParent != destinationCursor.SemanticParent)
{
return null;
}

var cppFunction = new CppFunction(functionName)
{
Visibility = contextContainer.CurrentVisibility,
Visibility = destinationContextContainer.CurrentVisibility,
StorageQualifier = GetStorageQualifier(cursor),
LinkageKind = GetLinkage(cursor.Linkage),
};

if (cursor.Kind == CXCursorKind.CXCursor_Constructor)
{
var cppClass = (CppClass)container;
var cppClass = (CppClass)destinationContainer;
cppFunction.IsConstructor = true;
cppClass.Constructors.Add(cppFunction);
}
else
{
container.Functions.Add(cppFunction);
destinationContainer.Functions.Add(cppFunction);
}

if (cursor.kind == CXCursorKind.CXCursor_FunctionTemplate)
Expand Down

0 comments on commit 9395218

Please sign in to comment.