diff --git a/src/AST/Class.cs b/src/AST/Class.cs index ca08569f..60a9cdf0 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -33,26 +33,9 @@ namespace CppSharp.AST { get { - Class @class; - if (Type.IsTagDecl(out @class)) - return @class; - - var type = Type.Desugar() as TemplateSpecializationType; - if (type == null) - { - TypedefType typedef; - if (Type.IsPointerTo(out typedef)) - { - type = (TemplateSpecializationType) typedef.Desugar(); - } - else - { - Type.IsPointerTo(out type); - } - } - var templatedClass = ((ClassTemplate) type.Template).TemplatedClass; - return templatedClass.CompleteDeclaration == null ? - templatedClass : (Class) templatedClass.CompleteDeclaration; + Class @class; + Type.TryGetClass(out @class); + return @class; } } @@ -60,8 +43,7 @@ namespace CppSharp.AST { get { - Class @class; - return Type.IsTagDecl(out @class); + return Type.IsClass(); } } } diff --git a/src/AST/ClassExtensions.cs b/src/AST/ClassExtensions.cs index 259c97c6..c9ca3382 100644 --- a/src/AST/ClassExtensions.cs +++ b/src/AST/ClassExtensions.cs @@ -83,9 +83,9 @@ namespace CppSharp.AST Property property = c.Properties.FirstOrDefault(m => m.Name == propertyName); if (property != null) return property; - Declaration decl; + foreach (var baseClassSpecifier in c.Bases.Where( - b => b.Type.IsTagDecl(out decl) && b.Class.IsDeclared)) + b => b.Type.IsClass() && b.Class.IsDeclared)) { property = baseClassSpecifier.Class.GetPropertyByName(propertyName); if (property != null) @@ -102,8 +102,8 @@ namespace CppSharp.AST property = c.Properties.FirstOrDefault(p => p.SetMethod == method); if (property != null) return property; - Declaration decl; - foreach (BaseClassSpecifier @base in c.Bases.Where(b => b.Type.IsTagDecl(out decl))) + + foreach (BaseClassSpecifier @base in c.Bases.Where(b => b.Type.IsClass())) { property = @base.Class.GetPropertyByConstituentMethod(method); if (property != null) @@ -119,8 +119,8 @@ namespace CppSharp.AST m => string.Compare(m.Name, methodName, StringComparison.OrdinalIgnoreCase) == 0); if (method != null) return method; - Declaration decl; - foreach (BaseClassSpecifier @base in c.Bases.Where(b => b.Type.IsTagDecl(out decl))) + + foreach (BaseClassSpecifier @base in c.Bases.Where(b => b.Type.IsClass())) { method = @base.Class.GetMethodByName(methodName); if (method != null) diff --git a/src/AST/PropertyExtensions.cs b/src/AST/PropertyExtensions.cs index 2d1a9a66..21345f3c 100644 --- a/src/AST/PropertyExtensions.cs +++ b/src/AST/PropertyExtensions.cs @@ -14,7 +14,7 @@ namespace CppSharp.AST type = type ?? p.Field.Type; Class decl; - return type.IsTagDecl(out decl) && decl.IsValueType; + return type.TryGetClass(out decl) && decl.IsValueType; } } } \ No newline at end of file diff --git a/src/AST/TypeExtensions.cs b/src/AST/TypeExtensions.cs index ebbfe5de..e6790ddf 100644 --- a/src/AST/TypeExtensions.cs +++ b/src/AST/TypeExtensions.cs @@ -90,33 +90,70 @@ if (ptr == null) return false; return ptr.Pointee.IsPrimitiveType(primitive); - } - - public static bool IsPointerTo(this Type t, out T type) where T : Type - { - var pointee = t.GetPointee(); - type = pointee as T; - if (type == null) - { - var attributedType = pointee as AttributedType; - if (attributedType != null) - type = attributedType.Modified.Type as T; - } - return type != null; } - public static bool IsTagDecl(this Type t, out T decl) where T : Declaration + public static bool IsPointerTo(this Type t, out T type) where T : Type { - var tag = t.Desugar() as TagType; - - if (tag == null) + var pointee = t.GetPointee(); + type = pointee as T; + if (type == null) { - decl = null; - return false; + var attributedType = pointee as AttributedType; + if (attributedType != null) + type = attributedType.Modified.Type as T; } + return type != null; + } - decl = tag.Declaration as T; - return decl != null; + public static bool IsClass(this Type t) + { + Class @class; + return t.TryGetClass(out @class); + } + + public static bool TryGetClass(this Type t, out Class @class) + { + t = t.Desugar(); + + var tag = t as TagType; + if (tag != null) + { + @class = tag.Declaration as Class; + return @class != null; + } + + var type = t as TemplateSpecializationType; + if (type != null) + { + var templatedClass = ((ClassTemplate)type.Template).TemplatedClass; + @class = templatedClass.CompleteDeclaration == null + ? templatedClass + : (Class)templatedClass.CompleteDeclaration; + return @class != null; + } + + @class = null; + return false; + } + + public static bool IsEnum(this Type t) + { + Enumeration @enum; + return t.TryGetEnum(out @enum); + } + + public static bool TryGetEnum(this Type t, out Enumeration @enum) + { + var tag = t.Desugar() as TagType; + + if (tag == null) + { + @enum = null; + return false; + } + + @enum = tag.Declaration as Enumeration; + return @enum != null; } public static Type Desugar(this Type t) diff --git a/src/Generator/AST/ASTRecord.cs b/src/Generator/AST/ASTRecord.cs index 6d50494e..bd5bf040 100644 --- a/src/Generator/AST/ASTRecord.cs +++ b/src/Generator/AST/ASTRecord.cs @@ -147,7 +147,7 @@ namespace CppSharp.Generators.AST var field = (Field)ancestors.Pop(); Class decl; - return field.Type.Desugar().IsTagDecl(out decl) && decl.IsValueType; + return field.Type.Desugar().TryGetClass(out decl) && decl.IsValueType; } } diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index d9b6dd7d..c4b63d47 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -107,7 +107,7 @@ namespace CppSharp.Generators.CLI Context.Driver.TypeDatabase.FindTypeMap(pointee, out typeMap); Class @class; - if (pointee.IsTagDecl(out @class) && typeMap == null) + if (pointee.TryGetClass(out @class) && typeMap == null) { var instance = (pointer.IsReference) ? "&" + Context.ReturnVarName : Context.ReturnVarName; @@ -426,7 +426,7 @@ namespace CppSharp.Generators.CLI } Enumeration @enum; - if (pointee.IsTagDecl(out @enum)) + if (pointee.TryGetEnum(out @enum)) { ArgumentPrefix.Write("&"); Context.Return.Write("(::{0})*{1}", @enum.QualifiedOriginalName, @@ -434,9 +434,9 @@ namespace CppSharp.Generators.CLI return true; } - Class @class; - if (pointee.IsTagDecl(out @class) && @class.IsValueType) - { + Class @class; + if (pointee.TryGetClass(out @class) && @class.IsValueType) + { if (Context.Function == null) Context.Return.Write("&"); return pointee.Visit(this, quals); @@ -655,7 +655,7 @@ namespace CppSharp.Generators.CLI Type type; Class @class; var isRef = property.Type.IsPointerTo(out type) && - !(type.IsTagDecl(out @class) && @class.IsValueType) && + !(type.TryGetClass(out @class) && @class.IsValueType) && !type.IsPrimitiveType(); if (isRef) diff --git a/src/Generator/Generators/CLI/CLITypePrinter.cs b/src/Generator/Generators/CLI/CLITypePrinter.cs index 88dc9c83..dbabd825 100644 --- a/src/Generator/Generators/CLI/CLITypePrinter.cs +++ b/src/Generator/Generators/CLI/CLITypePrinter.cs @@ -161,7 +161,7 @@ namespace CppSharp.Generators.CLI } Enumeration @enum; - if (pointee.IsTagDecl(out @enum)) + if (pointee.TryGetEnum(out @enum)) { var typeName = @enum.Visit(this); return string.Format("{0}*", typeName); diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 035114be..1b833e5c 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -439,7 +439,7 @@ namespace CppSharp.Generators.CSharp } Class @class; - if (pointee.IsTagDecl(out @class) && @class.IsValueType) + if (pointee.TryGetClass(out @class) && @class.IsValueType) { if (Context.Parameter.Usage == ParameterUsage.Out) { @@ -582,7 +582,7 @@ namespace CppSharp.Generators.CSharp if (type.IsAddress()) { Class decl; - if (type.IsTagDecl(out decl) && decl.IsValueType) + if (type.TryGetClass(out decl) && decl.IsValueType) Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier); else Context.Return.Write("{0} == ({2}) null ? global::System.IntPtr.Zero : {0}.{1}", param, diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 0a7ea727..17851ad5 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -314,7 +314,7 @@ namespace CppSharp.Generators.CSharp #region Classes public void GenerateClass(Class @class) - { + { if (@class.IsIncomplete) return; @@ -661,7 +661,7 @@ namespace CppSharp.Generators.CSharp Type type; Class @class; var isRef = property.Type.IsPointerTo(out type) && - !(type.IsTagDecl(out @class) && @class.IsValueType) && + !(type.TryGetClass(out @class) && @class.IsValueType) && !type.IsPrimitiveType(); if (isRef) @@ -704,9 +704,9 @@ namespace CppSharp.Generators.CSharp public void GenerateClassProlog(Class @class) { if (@class.IsUnion) - WriteLine("[StructLayout(LayoutKind.Explicit)]"); - - Write(!@class.IsGenerated ? "internal " : Helpers.GetAccess(@class.Access)); + WriteLine("[StructLayout(LayoutKind.Explicit)]"); + + Write(!@class.IsGenerated ? "internal " : Helpers.GetAccess(@class.Access)); Write("unsafe "); if (Driver.Options.GenerateAbstractImpls && @class.IsAbstract) @@ -766,12 +766,12 @@ namespace CppSharp.Generators.CSharp } } - private void GenerateClassInternalsField(Field field) + private void GenerateClassInternalsField(Field field) { // we do not support dependent fields yet, see https://github.com/mono/CppSharp/issues/197 Class @class; if (field.Type.IsDependent && !field.Type.IsPointer() && - !(field.Type.IsTagDecl(out @class) && @class.IsUnion)) + !(field.Type.TryGetClass(out @class) && @class.IsUnion)) return; var safeIdentifier = Helpers.SafeIdentifier(field.OriginalName); @@ -787,14 +787,14 @@ namespace CppSharp.Generators.CSharp if (field.Expression != null) { - var fieldValuePrinted = field.Expression.CSharpValue(ExpressionPrinter); - Write("{0} {1} {2} = {3};", !field.IsGenerated ? "internal" : "public", - fieldTypePrinted.Type, safeIdentifier, fieldValuePrinted); + var fieldValuePrinted = field.Expression.CSharpValue(ExpressionPrinter); + Write("{0} {1} {2} = {3};", !field.IsGenerated ? "internal" : "public", + fieldTypePrinted.Type, safeIdentifier, fieldValuePrinted); } else - { - Write("{0} {1} {2};", !field.IsGenerated ? "internal" : "public", - fieldTypePrinted.Type, safeIdentifier); + { + Write("{0} {1} {2};", !field.IsGenerated ? "internal" : "public", + fieldTypePrinted.Type, safeIdentifier); } PopBlock(NewLineKind.BeforeNextBlock); @@ -2226,15 +2226,15 @@ namespace CppSharp.Generators.CSharp var @params = GenerateFunctionParamsMarshal(parameters, function); - var originalFunction = function.OriginalFunction ?? function; - + var originalFunction = function.OriginalFunction ?? function; + if (originalFunction.HasIndirectReturnTypeParameter) { var indirectRetType = originalFunction.Parameters.First( parameter => parameter.Kind == ParameterKind.IndirectReturnType); Class retClass; - indirectRetType.Type.Desugar().IsTagDecl(out retClass); + indirectRetType.Type.Desugar().TryGetClass(out retClass); WriteLine("var {0} = new {1}.Internal();", GeneratedIdentifier("ret"), QualifiedIdentifier(retClass.OriginalClass ?? retClass)); @@ -2337,7 +2337,7 @@ namespace CppSharp.Generators.CSharp pointee = pointee.Desugar(); string @null; Class @class; - if (pointee.IsTagDecl(out @class) && @class.IsValueType) + if (pointee.TryGetClass(out @class) && @class.IsValueType) { @null = string.Format("new {0}()", pointee); } @@ -2468,7 +2468,7 @@ namespace CppSharp.Generators.CSharp var paramType = param.Type; Class @class; - if (paramType.Desugar().IsTagDecl(out @class) && @class.IsRefType) + if (paramType.Desugar().TryGetClass(out @class) && @class.IsRefType) { WriteLine("{0} = new {1}();", param.Name, paramType); } diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index fdfde8c0..dc82cf00 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -232,13 +232,13 @@ namespace CppSharp.Generators.CSharp } Enumeration @enum; - if (desugared.IsTagDecl(out @enum)) + if (desugared.TryGetEnum(out @enum)) { return @enum.Name + "*"; } Class @class; - if ((desugared.IsDependent || desugared.IsTagDecl(out @class)) + if ((desugared.IsDependent || desugared.TryGetClass(out @class)) && ContextKind == CSharpTypePrinterContextKind.Native) { return "global::System.IntPtr"; diff --git a/src/Generator/Passes/CheckIgnoredDecls.cs b/src/Generator/Passes/CheckIgnoredDecls.cs index e851524a..c5642840 100644 --- a/src/Generator/Passes/CheckIgnoredDecls.cs +++ b/src/Generator/Passes/CheckIgnoredDecls.cs @@ -1,4 +1,5 @@ -using CppSharp.AST; +using System; +using CppSharp.AST; using CppSharp.AST.Extensions; using CppSharp.Types; @@ -125,7 +126,7 @@ namespace CppSharp.Passes if (param.Kind == ParameterKind.IndirectReturnType) { Class retClass; - param.Type.Desugar().IsTagDecl(out retClass); + param.Type.Desugar().TryGetClass(out retClass); if (retClass == null) { function.ExplicitlyIgnore(); diff --git a/src/Generator/Passes/ConstructorToConversionOperatorPass.cs b/src/Generator/Passes/ConstructorToConversionOperatorPass.cs index bd5728a4..4fc15e5f 100644 --- a/src/Generator/Passes/ConstructorToConversionOperatorPass.cs +++ b/src/Generator/Passes/ConstructorToConversionOperatorPass.cs @@ -27,7 +27,7 @@ namespace CppSharp.Passes return false; var qualifiedPointee = parameterType.QualifiedPointee; Class castFromClass; - if (!qualifiedPointee.Type.IsTagDecl(out castFromClass)) + if (!qualifiedPointee.Type.TryGetClass(out castFromClass)) return false; var castToClass = method.OriginalNamespace as Class; if (castToClass == null) diff --git a/src/Generator/Passes/FunctionToInstanceMethodPass.cs b/src/Generator/Passes/FunctionToInstanceMethodPass.cs index 88973faa..bd8dc16d 100644 --- a/src/Generator/Passes/FunctionToInstanceMethodPass.cs +++ b/src/Generator/Passes/FunctionToInstanceMethodPass.cs @@ -79,7 +79,7 @@ namespace CppSharp.Passes return true; } - return classParam.Type.IsTagDecl(out @class); + return classParam.Type.TryGetClass(out @class); } } }