Browse Source

Enabled classes having specializations for secondary bases to call their extensions.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1033/head
Dimitar Dobrev 8 years ago
parent
commit
4b310875d3
  1. 1
      src/AST/Function.cs
  2. 22
      src/AST/Type.cs
  3. 27
      src/AST/TypeExtensions.cs
  4. 4
      src/Generator/Driver.cs
  5. 7
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  6. 6
      src/Generator/Generators/CSharp/CSharpSources.cs
  7. 35
      src/Generator/Passes/MultipleInheritancePass.cs
  8. 66
      src/Generator/Passes/ParamTypeToInterfacePass.cs
  9. 2
      src/Generator/Passes/SpecializationMethodsWithDependentPointersPass.cs
  10. 9
      tests/CSharp/CSharp.Tests.cs

1
src/AST/Function.cs

@ -129,6 +129,7 @@ namespace CppSharp.AST @@ -129,6 +129,7 @@ namespace CppSharp.AST
AbstractImplCall,
DefaultValueOverload,
InterfaceInstance,
InterfaceDispose,
FieldAcessor
}

22
src/AST/Type.cs

@ -668,7 +668,9 @@ namespace CppSharp.AST @@ -668,7 +668,9 @@ namespace CppSharp.AST
Type = new QualifiedType((Type) t.Type.Type.Clone(), t.Type.Qualifiers)
}).ToList();
Template = type.Template;
Desugared = new QualifiedType((Type) type.Desugared.Type.Clone(), type.Desugared.Qualifiers);
if (type.Desugared.Type != null)
Desugared = new QualifiedType((Type) type.Desugared.Type.Clone(),
type.Desugared.Qualifiers);
}
public List<TemplateArgument> Arguments;
@ -797,11 +799,12 @@ namespace CppSharp.AST @@ -797,11 +799,12 @@ namespace CppSharp.AST
public TemplateParameterType(TemplateParameterType type)
: base(type)
{
Parameter = new TypeTemplateParameter
{
Constraint = type.Parameter.Constraint,
Name = type.Parameter.Name
};
if (type.Parameter != null)
Parameter = new TypeTemplateParameter
{
Constraint = type.Parameter.Constraint,
Name = type.Parameter.Name
};
Depth = type.Depth;
Index = type.Index;
IsParameterPack = type.IsParameterPack;
@ -852,6 +855,7 @@ namespace CppSharp.AST @@ -852,6 +855,7 @@ namespace CppSharp.AST
: base(type)
{
Replacement = new QualifiedType((Type) type.Replacement.Type.Clone(), type.Replacement.Qualifiers);
ReplacedParameter = (TemplateParameterType) type.ReplacedParameter.Clone();
}
public override T Visit<T>(ITypeVisitor<T> visitor,
@ -895,7 +899,11 @@ namespace CppSharp.AST @@ -895,7 +899,11 @@ namespace CppSharp.AST
public InjectedClassNameType(InjectedClassNameType type)
: base(type)
{
TemplateSpecialization = (TemplateSpecializationType) type.TemplateSpecialization.Clone();
if (type.TemplateSpecialization != null)
TemplateSpecialization = (TemplateSpecializationType) type.TemplateSpecialization.Clone();
InjectedSpecializationType = new QualifiedType(
(Type) type.InjectedSpecializationType.Type.Clone(),
type.InjectedSpecializationType.Qualifiers);
Class = type.Class;
}

27
src/AST/TypeExtensions.cs

@ -111,12 +111,12 @@ @@ -111,12 +111,12 @@
return t.TryGetClass(out @class);
}
public static bool TryGetClass(this Type t, out Class @class)
public static bool TryGetClass(this Type t, out Class @class, Class value = null)
{
return TryGetDeclaration(t, out @class);
return TryGetDeclaration(t, out @class, value);
}
public static bool TryGetDeclaration<T>(this Type t, out T decl) where T : Declaration
public static bool TryGetDeclaration<T>(this Type t, out T decl, T value = null) where T : Declaration
{
t = t.Desugar();
@ -128,9 +128,8 @@ @@ -128,9 +128,8 @@
{
if (type.Template is TypeAliasTemplate)
{
Class @class;
type.Desugared.Type.TryGetClass(out @class);
decl = @class as T;
type.Desugared.Type.TryGetDeclaration(out decl, value);
decl = decl as T;
return decl != null;
}
@ -141,7 +140,13 @@ @@ -141,7 +140,13 @@
decl = templatedClass.CompleteDeclaration == null
? templatedClass as T
: (T) templatedClass.CompleteDeclaration;
return decl != null;
if (decl != null)
{
if (value != null)
type.Template = new ClassTemplate { TemplatedDecl = value };
return true;
}
return false;
}
var templateTemplateParameter = type.Template as TemplateTemplateParameter;
@ -158,7 +163,13 @@ @@ -158,7 +163,13 @@
if (tagType != null)
{
decl = tagType.Declaration as T;
return decl != null;
if (decl != null)
{
if (value != null)
tagType.Declaration = value;
return true;
}
return false;
}
decl = null;

4
src/Generator/Driver.cs

@ -258,7 +258,6 @@ namespace CppSharp @@ -258,7 +258,6 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new HandleDefaultParamValuesPass());
}
TranslationUnitPasses.AddPass(new MultipleInheritancePass());
TranslationUnitPasses.AddPass(new ParamTypeToInterfacePass());
}
TranslationUnitPasses.AddPass(new DelegatesPass());
@ -266,7 +265,10 @@ namespace CppSharp @@ -266,7 +265,10 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new StripUnusedSystemTypesPass());
if (Options.IsCSharpGenerator)
{
TranslationUnitPasses.AddPass(new SpecializationMethodsWithDependentPointersPass());
TranslationUnitPasses.AddPass(new ParamTypeToInterfacePass());
}
TranslationUnitPasses.AddPass(new MarkUsedClassInternalsPass());

7
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -811,14 +811,13 @@ namespace CppSharp.Generators.CSharp @@ -811,14 +811,13 @@ namespace CppSharp.Generators.CSharp
var finalType = type.GetFinalPointee() ?? type;
var templateType = finalType as TemplateParameterSubstitutionType;
type = Context.Parameter.Type.Desugar();
if (templateType != null)
param = $"(({@class.Visit(typePrinter)}) (object) {param})";
if (finalType.TryGetClass(out @interface) &&
@interface.IsInterface)
paramInstance = $"{param}.__PointerTo{@interface.OriginalClass.Name}";
else
paramInstance = $@"{
(templateType != null ? $"(({@class.Visit(typePrinter)}) (object) " : string.Empty)}{
param}{(templateType != null ? ")" : string.Empty)
}.{Helpers.InstanceIdentifier}";
paramInstance = $@"{param}.{Helpers.InstanceIdentifier}";
if (type.IsAddress())
{
Class decl;

6
src/Generator/Generators/CSharp/CSharpSources.cs

@ -459,11 +459,15 @@ namespace CppSharp.Generators.CSharp @@ -459,11 +459,15 @@ namespace CppSharp.Generators.CSharp
GenerateClassSpecifier(@class);
if (@class.Bases.Count == 0)
Write(" : IDisposable");
NewLine();
WriteStartBraceIndent();
foreach (var method in @class.Methods.Where(m =>
!ASTUtils.CheckIgnoreFunction(m.OriginalFunction) &&
(m.OriginalFunction == null ||
!ASTUtils.CheckIgnoreFunction(m.OriginalFunction)) &&
m.Access == AccessSpecifier.Public))
{
PushBlock(BlockKind.Method);

35
src/Generator/Passes/MultipleInheritancePass.cs

@ -88,6 +88,7 @@ namespace CppSharp.Passes @@ -88,6 +88,7 @@ namespace CppSharp.Passes
@interface = specializedInterface;
}
@interface.Name = name;
@interface.USR = @base.USR;
@interface.Namespace = @base.Namespace;
@interface.Access = @base.Access;
@interface.Type = ClassType.Interface;
@ -116,18 +117,28 @@ namespace CppSharp.Passes @@ -116,18 +117,28 @@ namespace CppSharp.Passes
if (@interface.Bases.Count == 0)
{
var instance = new Property
{
Namespace = @interface,
Name = Helpers.InstanceIdentifier,
QualifiedType = new QualifiedType(new BuiltinType(PrimitiveType.IntPtr)),
GetMethod = new Method
{
SynthKind = FunctionSynthKind.InterfaceInstance,
Namespace = @interface
}
};
Namespace = @interface,
Name = Helpers.InstanceIdentifier,
QualifiedType = new QualifiedType(new BuiltinType(PrimitiveType.IntPtr)),
GetMethod = new Method
{
SynthKind = FunctionSynthKind.InterfaceInstance,
Namespace = @interface
}
};
@interface.Properties.Add(instance);
var dispose = new Method
{
Namespace = @interface,
Name = "Dispose",
ReturnType = new QualifiedType(new BuiltinType(PrimitiveType.Void)),
SynthKind = FunctionSynthKind.InterfaceDispose
};
@interface.Methods.Add(dispose);
}
@interface.Events.AddRange(@base.Events);
@ -157,7 +168,8 @@ namespace CppSharp.Passes @@ -157,7 +168,8 @@ namespace CppSharp.Passes
@interface.TemplateParameters.AddRange(@base.TemplateParameters);
templatedInterfaces[@base] = @interface;
foreach (var spec in @base.Specializations)
GetNewInterface(name, spec);
@interface.Specializations.Add(
(ClassTemplateSpecialization) GetNewInterface(name, spec));
}
return @interface;
}
@ -184,7 +196,8 @@ namespace CppSharp.Passes @@ -184,7 +196,8 @@ namespace CppSharp.Passes
private void ImplementInterfaceMethods(Class @class, Class @interface)
{
foreach (var method in @interface.Methods)
foreach (var method in @interface.Methods.Where(
m => m.SynthKind != FunctionSynthKind.InterfaceDispose))
{
var existingImpl = @class.Methods.FirstOrDefault(
m => m.OriginalName == method.OriginalName &&

66
src/Generator/Passes/ParamTypeToInterfacePass.cs

@ -6,8 +6,21 @@ namespace CppSharp.Passes @@ -6,8 +6,21 @@ namespace CppSharp.Passes
{
public class ParamTypeToInterfacePass : TranslationUnitPass
{
public ParamTypeToInterfacePass()
{
VisitOptions.VisitClassBases = false;
VisitOptions.VisitClassFields = false;
VisitOptions.VisitEventParameters = false;
VisitOptions.VisitNamespaceEnums = false;
VisitOptions.VisitNamespaceEvents = false;
VisitOptions.VisitTemplateArguments = false;
}
public override bool VisitFunctionDecl(Function function)
{
if (!base.VisitFunctionDecl(function))
return false;
if (!function.IsOperator || function.Parameters.Count > 1)
{
var originalReturnType = function.OriginalReturnType;
@ -17,32 +30,57 @@ namespace CppSharp.Passes @@ -17,32 +30,57 @@ namespace CppSharp.Passes
if (function.OperatorKind != CXXOperatorKind.Conversion &&
function.OperatorKind != CXXOperatorKind.ExplicitConversion)
foreach (var parameter in function.Parameters.Where(p => p.Kind != ParameterKind.OperatorParameter))
foreach (var parameter in function.Parameters.Where(
p => p.Kind != ParameterKind.OperatorParameter))
{
var qualifiedType = parameter.QualifiedType;
ChangeToInterfaceType(ref qualifiedType);
parameter.QualifiedType = qualifiedType;
}
return base.VisitFunctionDecl(function);
return true;
}
public override bool VisitProperty(Property property)
{
if (!base.VisitProperty(property))
return false;
var type = property.QualifiedType;
ChangeToInterfaceType(ref type);
property.QualifiedType = type;
return true;
}
private static void ChangeToInterfaceType(ref QualifiedType type)
{
var tagType = (type.Type.GetFinalPointee() ?? type.Type) as TagType;
if (tagType != null)
var finalType = (type.Type.GetFinalPointee() ?? type.Type).Desugar();
Class @class;
if (!finalType.TryGetClass(out @class))
return;
var specialization = @class as ClassTemplateSpecialization;
Class @interface = null;
if (specialization == null)
{
var @class = tagType.Declaration as Class;
if (@class != null)
{
var @interface = @class.Namespace.Classes.Find(c => c.OriginalClass == @class);
if (@interface != null)
{
type.Type = (Type) type.Type.Clone();
((TagType) (type.Type.GetFinalPointee() ?? type.Type)).Declaration = @interface;
}
}
@interface = @class.Namespace.Classes.Find(
c => c.OriginalClass == @class && c.IsInterface);
}
else
{
Class template = specialization.TemplatedDecl.TemplatedClass;
Class templatedInterface = @class.Namespace.Classes.Find(
c => c.OriginalClass == template && c.IsInterface);
if (templatedInterface != null)
@interface = templatedInterface.Specializations.FirstOrDefault(
s => s.OriginalClass == specialization);
}
if (@interface == null)
return;
type.Type = (Type) type.Type.Clone();
finalType = (type.Type.GetFinalPointee() ?? type.Type).Desugar();
finalType.TryGetClass(out @class, @interface);
}
}
}

2
src/Generator/Passes/SpecializationMethodsWithDependentPointersPass.cs

@ -56,7 +56,7 @@ namespace CppSharp.Passes @@ -56,7 +56,7 @@ namespace CppSharp.Passes
public override bool VisitClassDecl(Class @class)
{
if (!base.VisitClassDecl(@class) || !@class.IsDependent ||
if (!base.VisitClassDecl(@class) || !@class.IsDependent || @class.IsInterface ||
@class.Specializations.All(s => !s.IsGenerated))
return false;

9
tests/CSharp/CSharp.Tests.cs

@ -895,6 +895,15 @@ public unsafe class CSharpTests : GeneratorTestFixture @@ -895,6 +895,15 @@ public unsafe class CSharpTests : GeneratorTestFixture
}
}
[Test]
public void TestExtensionsOfSpecializationsAsSecondaryBases()
{
using (var hasSpecializationForSecondaryBase = new HasSpecializationForSecondaryBase())
{
Assert.IsTrue(hasSpecializationForSecondaryBase.PropertyReturnDependentPointer() == null);
}
}
[Test]
public void TestAbstractImplementatonsInPrimaryAndSecondaryBases()
{

Loading…
Cancel
Save