diff --git a/src/CppAst.Tests/TestMisc.cs b/src/CppAst.Tests/TestMisc.cs index 08fe826..fb7131d 100644 --- a/src/CppAst.Tests/TestMisc.cs +++ b/src/CppAst.Tests/TestMisc.cs @@ -23,17 +23,30 @@ class Bar : public Foo public: using Foo::Foo; }; + +class Baz : public Bar +{ +public: + using Bar::Bar; + Baz(double y) : y_{y} {} +private: + double y_{0}; +}; ", compilation => { Assert.False(compilation.HasErrors); - Assert.AreEqual(2, compilation.Classes.Count); + Assert.AreEqual(3, 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(2, 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); + + Assert.AreEqual(3, compilation.Classes[2].Constructors.Count); + Assert.AreEqual(CppVisibility.Public, compilation.Classes[2].Constructors[0].Visibility); + Assert.AreEqual(CppVisibility.Public, compilation.Classes[2].Constructors[1].Visibility); + Assert.AreEqual(CppVisibility.Public, compilation.Classes[2].Constructors[2].Visibility); + } ); } diff --git a/src/CppAst/CppFunction.cs b/src/CppAst/CppFunction.cs index ca94a83..694e7e6 100644 --- a/src/CppAst/CppFunction.cs +++ b/src/CppAst/CppFunction.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace CppAst @@ -86,6 +87,69 @@ public int DefaultParamCount } } + /// + /// Checks whether the two functions are the same or not + /// + public bool Equals(CppFunction other) + { + return Visibility.Equals(other.Visibility) && + Attributes.SequenceEqual(other.Attributes) && + TokenAttributes.SequenceEqual(other.TokenAttributes) && + StorageQualifier.Equals(other.StorageQualifier) && + LinkageKind.Equals(other.LinkageKind) && + IsConstructor.Equals(other.IsConstructor) && + Name.Equals(other.Name) && + Parameters.SequenceEqual(other.Parameters) && + TemplateParameters.SequenceEqual(other.TemplateParameters) && + CallingConvention.Equals(other.CallingConvention) && + Visibility.Equals(other.Visibility) && + Flags.Equals(other.Flags) && + ReturnType.Equals(other.ReturnType); + } + + public override bool Equals(object obj) + { + return ReferenceEquals(this, obj) || obj is CppFunction other && Equals(other); + } + + /// + public override int GetHashCode() + { + unchecked + { + int hashCode = base.GetHashCode(); + hashCode = (hashCode * 397) ^ Visibility.GetHashCode(); + hashCode = (hashCode * 397) ^ StorageQualifier.GetHashCode(); + hashCode = (hashCode * 397) ^ LinkageKind.GetHashCode(); + hashCode = (hashCode * 397) ^ IsConstructor.GetHashCode(); + hashCode = (hashCode * 397) ^ Name.GetHashCode(); + hashCode = (hashCode * 397) ^ CallingConvention.GetHashCode(); + hashCode = (hashCode * 397) ^ Visibility.GetHashCode(); + hashCode = (hashCode * 397) ^ Flags.GetHashCode(); + hashCode = (hashCode * 397) ^ ReturnType.GetHashCode(); + + foreach (var templateParameter in TemplateParameters) + { + hashCode = (hashCode * 397) ^ templateParameter.GetHashCode(); + } + foreach (var parameter in Parameters) + { + hashCode = (hashCode * 397) ^ parameter.GetHashCode(); + } + foreach (var attribute in Attributes) + { + hashCode = (hashCode * 397) ^ attribute.GetHashCode(); + } + foreach (var attribute in TokenAttributes) + { + hashCode = (hashCode * 397) ^ attribute.GetHashCode(); + } + + return hashCode; + } + } + + /// /// Gets or sets the flags of this function. /// diff --git a/src/CppAst/CppModelBuilder.cs b/src/CppAst/CppModelBuilder.cs index f20c044..e599ebd 100644 --- a/src/CppAst/CppModelBuilder.cs +++ b/src/CppAst/CppModelBuilder.cs @@ -1260,7 +1260,7 @@ private static CppStorageQualifier GetStorageQualifier(CXCursor cursor) return CppStorageQualifier.None; } -private CppFunction VisitFunctionDecl(CXCursor destinationCursor, 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; @@ -1294,13 +1294,7 @@ private CppFunction VisitFunctionDecl(CXCursor destinationCursor, CXCursor curso if (cursor.Kind == CXCursorKind.CXCursor_Constructor) { - var cppClass = (CppClass)destinationContainer; cppFunction.IsConstructor = true; - cppClass.Constructors.Add(cppFunction); - } - else - { - destinationContainer.Functions.Add(cppFunction); } if (cursor.kind == CXCursorKind.CXCursor_FunctionTemplate) @@ -1401,6 +1395,19 @@ private CppFunction VisitFunctionDecl(CXCursor destinationCursor, CXCursor curso }, new CXClientData((IntPtr)data)); + if (cursor.Kind == CXCursorKind.CXCursor_Constructor) + { + var cppClass = (CppClass)destinationContainer; + if (!cppClass.Constructors.Contains(cppFunction)) + { + cppClass.Constructors.Add(cppFunction); + } + } + else if (!destinationContainer.Functions.Contains(cppFunction)) + { + destinationContainer.Functions.Add(cppFunction); + } + return cppFunction; }