Browse Source

Merge pull request #237 from azeno/minor-improvements

Minor improvements
pull/238/head
João Matos 11 years ago
parent
commit
d79d5e7a2d
  1. 27
      src/AST/Class.cs
  2. 12
      src/AST/Function.cs
  3. 5
      src/AST/Method.cs
  4. 43
      src/AST/Namespace.cs
  5. 1
      src/Core/Parser/ASTConverter.cs
  6. 1
      src/CppParser/AST.h
  7. 10
      src/CppParser/Bindings/CLI/AST.cpp
  8. 6
      src/CppParser/Bindings/CLI/AST.h
  9. 22
      src/CppParser/Bindings/CSharp/AST.cs
  10. 1
      src/CppParser/Parser.cpp
  11. 164
      src/Generator.Tests/AST/TestAST.cs
  12. 17
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  13. 17
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  14. 1
      src/Parser/Parser.cpp
  15. 6
      tests/CLITemp/CLITemp.cs
  16. 9
      tests/CLITemp/CLITemp.h
  17. 22
      tests/Native/AST.h

27
src/AST/Class.cs

@ -133,6 +133,28 @@ namespace CppSharp.AST @@ -133,6 +133,28 @@ namespace CppSharp.AST
Layout = new ClassLayout();
}
public Class(Class @class)
: base(@class)
{
Bases = new List<BaseClassSpecifier>(@class.Bases);
Fields = new List<Field>(@class.Fields);
Properties = new List<Property>(@class.Properties);
Methods = new List<Method>(@class.Methods);
Specifiers = new List<AccessSpecifierDecl>(@class.Specifiers);
IsPOD = @class.IsPOD;
Type = @class.Type;
Layout = new ClassLayout(@class.Layout);
IsAbstract = @class.IsAbstract;
IsUnion = @class.IsUnion;
IsOpaque = @class.IsOpaque;
IsDynamic = @class.IsDynamic;
IsPolymorphic = @class.IsPolymorphic;
HasNonTrivialDefaultConstructor = @class.HasNonTrivialDefaultConstructor;
HasNonTrivialCopyConstructor = @class.HasNonTrivialCopyConstructor;
HasNonTrivialDestructor = @class.HasNonTrivialDestructor;
IsStatic = @class.IsStatic;
}
public bool HasBase
{
get { return Bases.Count > 0; }
@ -199,6 +221,11 @@ namespace CppSharp.AST @@ -199,6 +221,11 @@ namespace CppSharp.AST
}
}
public override IEnumerable<Function> FindOperator(CXXOperatorKind kind)
{
return Methods.Where(m => m.OperatorKind == kind);
}
public override IEnumerable<Function> GetOverloads(Function function)
{
if (function.IsOperator)

12
src/AST/Function.cs

@ -37,9 +37,21 @@ namespace CppSharp.AST @@ -37,9 +37,21 @@ namespace CppSharp.AST
HasDefaultValue = false;
}
public Parameter(Parameter p)
: base(p)
{
HasDefaultValue = p.HasDefaultValue;
Index = p.Index;
IsIndirect = p.IsIndirect;
Kind = p.Kind;
QualifiedType = p.QualifiedType;
Usage = p.Usage;
}
public Type Type { get { return QualifiedType.Type; } }
public QualifiedType QualifiedType { get; set; }
public bool IsIndirect { get; set; }
public uint Index { get; set; }
public ParameterKind Kind { get; set; }
public ParameterUsage Usage { get; set; }

5
src/AST/Method.cs

@ -148,6 +148,11 @@ namespace CppSharp.AST @@ -148,6 +148,11 @@ namespace CppSharp.AST
public Class ExplicitInterfaceImpl { get; set; }
public override T Visit<T>(IDeclVisitor<T> visitor)
{
return visitor.VisitMethodDecl(this);
}
public override QualifiedType GetFunctionType()
{
var qualifiedType = base.GetFunctionType();

43
src/AST/Namespace.cs

@ -51,6 +51,22 @@ namespace CppSharp.AST @@ -51,6 +51,22 @@ namespace CppSharp.AST
Anonymous = new Dictionary<ulong, Declaration>();
}
protected DeclarationContext(DeclarationContext dc)
: base(dc)
{
Namespaces = new List<Namespace>(dc.Namespaces);
Enums = new List<Enumeration>(dc.Enums);
Functions = new List<Function>(dc.Functions);
Classes = new List<Class>(dc.Classes);
Templates = new List<Template>(dc.Templates);
Typedefs = new List<TypedefDecl>(dc.Typedefs);
Variables = new List<Variable>(dc.Variables);
Events = new List<Event>(dc.Events);
TypeReferences = new List<TypeReference>(dc.TypeReferences);
Anonymous = new Dictionary<ulong, Declaration>(dc.Anonymous);
IsAnonymous = dc.IsAnonymous;
}
public IEnumerable<DeclarationContext> GatherParentNamespaces()
{
var children = new List<DeclarationContext>();
@ -294,15 +310,30 @@ namespace CppSharp.AST @@ -294,15 +310,30 @@ namespace CppSharp.AST
public TypedefDecl FindTypedef(string name, bool createDecl = false)
{
var typedef = Typedefs.Find(e => e.Name.Equals(name));
var entries = name.Split(new string[] { "::" },
StringSplitOptions.RemoveEmptyEntries).ToList();
if (typedef == null && createDecl)
if (entries.Count <= 1)
{
typedef = new TypedefDecl { Name = name, Namespace = this };
Typedefs.Add(typedef);
var typeDef = Typedefs.Find(e => e.Name.Equals(name));
if (typeDef == null && createDecl)
{
typeDef = new TypedefDecl() { Name = name, Namespace = this };
Typedefs.Add(typeDef);
}
return typeDef;
}
return typedef;
var typeDefName = entries[entries.Count - 1];
var namespaces = entries.Take(entries.Count - 1);
var @namespace = FindNamespace(namespaces);
if (@namespace == null)
return null;
return @namespace.FindTypedef(typeDefName, createDecl);
}
public T FindType<T>(string name) where T : Declaration
@ -320,7 +351,7 @@ namespace CppSharp.AST @@ -320,7 +351,7 @@ namespace CppSharp.AST
return Enums.Find(e => e.ItemsByName.ContainsKey(name));
}
public IEnumerable<Function> FindOperator(CXXOperatorKind kind)
public virtual IEnumerable<Function> FindOperator(CXXOperatorKind kind)
{
return Functions.Where(fn => fn.OperatorKind == kind);
}

1
src/Core/Parser/ASTConverter.cs

@ -803,6 +803,7 @@ namespace CppSharp @@ -803,6 +803,7 @@ namespace CppSharp
_param.QualifiedType = typeConverter.VisitQualified(decl.QualifiedType);
_param.IsIndirect = decl.IsIndirect;
_param.HasDefaultValue = decl.HasDefaultValue;
_param.Index = decl.Index;
return _param;
}

1
src/CppParser/AST.h

@ -433,6 +433,7 @@ struct CS_API Parameter : public Declaration @@ -433,6 +433,7 @@ struct CS_API Parameter : public Declaration
CppSharp::CppParser::AST::QualifiedType QualifiedType;
bool IsIndirect;
bool HasDefaultValue;
unsigned int Index;
};
enum struct CXXMethodKind

10
src/CppParser/Bindings/CLI/AST.cpp

@ -1459,6 +1459,16 @@ void CppSharp::Parser::AST::Parameter::HasDefaultValue::set(bool value) @@ -1459,6 +1459,16 @@ void CppSharp::Parser::AST::Parameter::HasDefaultValue::set(bool value)
((::CppSharp::CppParser::AST::Parameter*)NativePtr)->HasDefaultValue = value;
}
unsigned int CppSharp::Parser::AST::Parameter::Index::get()
{
return ((::CppSharp::CppParser::AST::Parameter*)NativePtr)->Index;
}
void CppSharp::Parser::AST::Parameter::Index::set(unsigned int value)
{
((::CppSharp::CppParser::AST::Parameter*)NativePtr)->Index = value;
}
CppSharp::Parser::AST::Function::Function(::CppSharp::CppParser::AST::Function* native)
: CppSharp::Parser::AST::Declaration((::CppSharp::CppParser::AST::Declaration*)native)
{

6
src/CppParser/Bindings/CLI/AST.h

@ -1120,6 +1120,12 @@ namespace CppSharp @@ -1120,6 +1120,12 @@ namespace CppSharp
bool get();
void set(bool);
}
property unsigned int Index
{
unsigned int get();
void set(unsigned int);
}
};
public ref class Function : CppSharp::Parser::AST::Declaration

22
src/CppParser/Bindings/CSharp/AST.cs

@ -3389,7 +3389,7 @@ namespace CppSharp @@ -3389,7 +3389,7 @@ namespace CppSharp
public unsafe partial class Parameter : CppSharp.Parser.AST.Declaration, IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 104)]
[StructLayout(LayoutKind.Explicit, Size = 108)]
public new struct Internal
{
[FieldOffset(0)]
@ -3437,6 +3437,9 @@ namespace CppSharp @@ -3437,6 +3437,9 @@ namespace CppSharp
[FieldOffset(101)]
internal bool HasDefaultValue;
[FieldOffset(104)]
internal uint Index;
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0Parameter@AST@CppParser@CppSharp@@QAE@XZ")]
@ -3471,7 +3474,7 @@ namespace CppSharp @@ -3471,7 +3474,7 @@ namespace CppSharp
public Parameter()
: this(IntPtr.Zero)
{
__Instance = Marshal.AllocHGlobal(104);
__Instance = Marshal.AllocHGlobal(108);
Internal.ctor_0(__Instance);
}
@ -3526,6 +3529,21 @@ namespace CppSharp @@ -3526,6 +3529,21 @@ namespace CppSharp
__ptr->HasDefaultValue = value;
}
}
public uint Index
{
get
{
var __ptr = (Internal*)__Instance.ToPointer();
return __ptr->Index;
}
set
{
var __ptr = (Internal*)__Instance.ToPointer();
__ptr->Index = value;
}
}
}
public unsafe partial class Function : CppSharp.Parser.AST.Declaration, IDisposable

1
src/CppParser/Parser.cpp

@ -1885,6 +1885,7 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, Function* F, @@ -1885,6 +1885,7 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, Function* F,
P->QualifiedType = GetQualifiedType(VD->getType(), WalkType(VD->getType(), &PTL));
P->HasDefaultValue = VD->hasDefaultArg();
P->_Namespace = NS;
P->Index = VD->getFunctionScopeIndex();
HandleDeclaration(VD, P);
F->Parameters.push_back(P);

164
src/Generator.Tests/AST/TestAST.cs

@ -0,0 +1,164 @@ @@ -0,0 +1,164 @@
using System.Linq;
using CppSharp.Passes;
using CppSharp.AST;
using CppSharp.AST.Extensions;
using NUnit.Framework;
namespace CppSharp.Generator.Tests.AST
{
[TestFixture]
public class TestAST : ASTTestFixture
{
private PassBuilder<TranslationUnitPass> passBuilder;
[TestFixtureSetUp]
public void Init()
{
}
[SetUp]
public void Setup()
{
ParseLibrary("AST.h");
passBuilder = new PassBuilder<TranslationUnitPass>(Driver);
}
[Test]
public void TestASTParameter()
{
var func = AstContext.FindFunction("TestParameterProperties").FirstOrDefault();
Assert.IsNotNull(func);
var paramNames = new [] { "a", "b", "c" };
var paramTypes = new []
{
new QualifiedType(new BuiltinType(PrimitiveType.Bool)),
new QualifiedType(
new PointerType()
{
Modifier = PointerType.TypeModifier.LVReference,
QualifiedPointee = new QualifiedType(
new BuiltinType(PrimitiveType.Int16),
new TypeQualifiers() { IsConst = true })
}),
new QualifiedType(
new PointerType()
{
Modifier = PointerType.TypeModifier.Pointer,
QualifiedPointee = new QualifiedType(new BuiltinType(PrimitiveType.Int32))
})
};
for (int i = 0; i < func.Parameters.Count; i++)
{
var param = func.Parameters[i];
Assert.AreEqual(paramNames[i], param.Name, "Parameter.Name");
Assert.AreEqual(paramTypes[i], param.QualifiedType, "Parameter.QualifiedType");
Assert.AreEqual(i, param.Index, "Parameter.Index");
}
Assert.IsTrue(func.Parameters[2].HasDefaultValue, "Parameter.HasDefaultValue");
}
[Test]
public void TestASTHelperMethods()
{
var @class = AstContext.FindClass("Math::Complex").FirstOrDefault();
Assert.IsNotNull(@class, "Couldn't find Math::Complex class.");
var plusOperator = @class.FindOperator(CXXOperatorKind.Plus).FirstOrDefault();
Assert.IsNotNull(plusOperator, "Couldn't find operator+ in Math::Complex class.");
var typedef = AstContext.FindTypedef("Math::Single").FirstOrDefault();
Assert.IsNotNull(typedef);
}
#region TestVisitor
class TestVisitor : IDeclVisitor<bool>
{
public bool VisitDeclaration(Declaration decl)
{
throw new System.NotImplementedException();
}
public bool VisitClassDecl(Class @class)
{
throw new System.NotImplementedException();
}
public bool VisitFieldDecl(Field field)
{
throw new System.NotImplementedException();
}
public bool VisitFunctionDecl(Function function)
{
throw new System.NotImplementedException();
}
public bool VisitMethodDecl(Method method)
{
return true;
}
public bool VisitParameterDecl(Parameter parameter)
{
throw new System.NotImplementedException();
}
public bool VisitTypedefDecl(TypedefDecl typedef)
{
throw new System.NotImplementedException();
}
public bool VisitEnumDecl(Enumeration @enum)
{
throw new System.NotImplementedException();
}
public bool VisitVariableDecl(Variable variable)
{
throw new System.NotImplementedException();
}
public bool VisitClassTemplateDecl(ClassTemplate template)
{
throw new System.NotImplementedException();
}
public bool VisitFunctionTemplateDecl(FunctionTemplate template)
{
throw new System.NotImplementedException();
}
public bool VisitMacroDefinition(MacroDefinition macro)
{
throw new System.NotImplementedException();
}
public bool VisitNamespace(Namespace @namespace)
{
throw new System.NotImplementedException();
}
public bool VisitEvent(Event @event)
{
throw new System.NotImplementedException();
}
public bool VisitProperty(Property property)
{
throw new System.NotImplementedException();
}
}
#endregion
[Test]
public void TestASTVisitor()
{
var testVisitor = new TestVisitor();
var plusOperator = AstContext.TranslationUnits
.SelectMany(u => u.Namespaces.Where(n => n.Name == "Math"))
.SelectMany(n => n.Classes.Where(c => c.Name == "Complex"))
.SelectMany(c => c.Methods.Where(m => m.OperatorKind == CXXOperatorKind.Plus))
.First();
Assert.IsTrue(plusOperator.Visit(testVisitor));
}
}
}

17
src/Generator/Generators/CLI/CLIHeadersTemplate.cs

@ -382,10 +382,15 @@ namespace CppSharp.Generators.CLI @@ -382,10 +382,15 @@ namespace CppSharp.Generators.CLI
GenerateMethod(ctor);
}
if (@class.IsRefType)
if (Options.GenerateFinalizers && @class.IsRefType)
{
GenerateClassDestructor(@class);
GenerateClassFinalizer(@class);
var destructor = @class.Destructors
.FirstOrDefault(d => d.Parameters.Count == 0 && d.Access == AccessSpecifier.Public);
if (destructor != null)
{
GenerateClassDestructor(@class);
GenerateClassFinalizer(@class);
}
}
PopIndent();
@ -393,9 +398,6 @@ namespace CppSharp.Generators.CLI @@ -393,9 +398,6 @@ namespace CppSharp.Generators.CLI
private void GenerateClassDestructor(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Destructor);
WriteLine("~{0}();", @class.Name);
PopBlock(NewLineKind.BeforeNextBlock);
@ -403,9 +405,6 @@ namespace CppSharp.Generators.CLI @@ -403,9 +405,6 @@ namespace CppSharp.Generators.CLI
private void GenerateClassFinalizer(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Finalizer);
WriteLine("!{0}();", @class.Name);
PopBlock(NewLineKind.BeforeNextBlock);

17
src/Generator/Generators/CLI/CLISourcesTemplate.cs

@ -205,10 +205,15 @@ namespace CppSharp.Generators.CLI @@ -205,10 +205,15 @@ namespace CppSharp.Generators.CLI
GenerateClassConstructor(@class, isIntPtr: false);
GenerateClassConstructor(@class, isIntPtr: true);
if (@class.IsRefType)
if (Options.GenerateFinalizers && @class.IsRefType)
{
GenerateClassDestructor(@class);
GenerateClassFinalizer(@class);
var destructor = @class.Destructors
.FirstOrDefault(d => d.Parameters.Count == 0 && d.Access == AccessSpecifier.Public);
if (destructor != null)
{
GenerateClassDestructor(@class);
GenerateClassFinalizer(@class);
}
}
}
@ -229,9 +234,6 @@ namespace CppSharp.Generators.CLI @@ -229,9 +234,6 @@ namespace CppSharp.Generators.CLI
private void GenerateClassDestructor(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Destructor);
WriteLine("{0}::~{1}()", QualifiedIdentifier(@class), @class.Name);
@ -247,9 +249,6 @@ namespace CppSharp.Generators.CLI @@ -247,9 +249,6 @@ namespace CppSharp.Generators.CLI
private void GenerateClassFinalizer(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Finalizer);
WriteLine("{0}::!{1}()", QualifiedIdentifier(@class), @class.Name);

1
src/Parser/Parser.cpp

@ -1900,6 +1900,7 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, CppSharp::AST::Function^ F, @@ -1900,6 +1900,7 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, CppSharp::AST::Function^ F,
P->QualifiedType = GetQualifiedType(VD->getType(), WalkType(VD->getType(), &PTL));
P->HasDefaultValue = VD->hasDefaultArg();
P->Namespace = NS;
P->Index = VD->getFunctionScopeIndex();
HandleDeclaration(VD, P);
F->Parameters->Add(P);

6
tests/CLITemp/CLITemp.cs

@ -11,6 +11,12 @@ namespace CppSharp.Tests @@ -11,6 +11,12 @@ namespace CppSharp.Tests
{
}
public override void Setup(Driver driver)
{
driver.Options.GenerateFinalizers = true;
base.Setup(driver);
}
public override void Preprocess(Driver driver, ASTContext ctx)
{
}

9
tests/CLITemp/CLITemp.h

@ -15,3 +15,12 @@ struct DLL_API Types @@ -15,3 +15,12 @@ struct DLL_API Types
typedef int AttributedFuncType(int, int) ATTR;
AttributedFuncType AttributedSum;
};
// Tests code generator to not generate a destructor/finalizer pair
// if the destructor of the C++ class is not public.
class DLL_API TestProtectedDestructors
{
~TestProtectedDestructors();
};
TestProtectedDestructors::~TestProtectedDestructors() {}

22
tests/Native/AST.h

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
// Tests assignment of AST.Parameter properties
void TestParameterProperties(bool a, const short& b, int* c = nullptr) {};
// Tests various AST helper methods (like FindClass, FindOperator etc.)
namespace Math
{
// Tests FindClass("Math::Complex")
struct Complex {
Complex(double r, double i) : re(r), im(i) {}
Complex operator+(Complex &other);
private:
double re, im;
};
// Tests FindTypedef("Math::Single")
typedef float Single;
// Tests FindOperator method
Complex Complex::operator+(Complex &other) {
return Complex(re + other.re, im + other.im);
}
}
Loading…
Cancel
Save