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. 10
      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. 17
      src/Generator/Passes/MultipleInheritancePass.cs
  8. 64
      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
AbstractImplCall, AbstractImplCall,
DefaultValueOverload, DefaultValueOverload,
InterfaceInstance, InterfaceInstance,
InterfaceDispose,
FieldAcessor FieldAcessor
} }

10
src/AST/Type.cs

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

27
src/AST/TypeExtensions.cs

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

4
src/Generator/Driver.cs

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

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

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

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

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

17
src/Generator/Passes/MultipleInheritancePass.cs

@ -88,6 +88,7 @@ namespace CppSharp.Passes
@interface = specializedInterface; @interface = specializedInterface;
} }
@interface.Name = name; @interface.Name = name;
@interface.USR = @base.USR;
@interface.Namespace = @base.Namespace; @interface.Namespace = @base.Namespace;
@interface.Access = @base.Access; @interface.Access = @base.Access;
@interface.Type = ClassType.Interface; @interface.Type = ClassType.Interface;
@ -128,6 +129,16 @@ namespace CppSharp.Passes
}; };
@interface.Properties.Add(instance); @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); @interface.Events.AddRange(@base.Events);
@ -157,7 +168,8 @@ namespace CppSharp.Passes
@interface.TemplateParameters.AddRange(@base.TemplateParameters); @interface.TemplateParameters.AddRange(@base.TemplateParameters);
templatedInterfaces[@base] = @interface; templatedInterfaces[@base] = @interface;
foreach (var spec in @base.Specializations) foreach (var spec in @base.Specializations)
GetNewInterface(name, spec); @interface.Specializations.Add(
(ClassTemplateSpecialization) GetNewInterface(name, spec));
} }
return @interface; return @interface;
} }
@ -184,7 +196,8 @@ namespace CppSharp.Passes
private void ImplementInterfaceMethods(Class @class, Class @interface) 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( var existingImpl = @class.Methods.FirstOrDefault(
m => m.OriginalName == method.OriginalName && m => m.OriginalName == method.OriginalName &&

64
src/Generator/Passes/ParamTypeToInterfacePass.cs

@ -6,8 +6,21 @@ namespace CppSharp.Passes
{ {
public class ParamTypeToInterfacePass : TranslationUnitPass 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) public override bool VisitFunctionDecl(Function function)
{ {
if (!base.VisitFunctionDecl(function))
return false;
if (!function.IsOperator || function.Parameters.Count > 1) if (!function.IsOperator || function.Parameters.Count > 1)
{ {
var originalReturnType = function.OriginalReturnType; var originalReturnType = function.OriginalReturnType;
@ -17,32 +30,57 @@ namespace CppSharp.Passes
if (function.OperatorKind != CXXOperatorKind.Conversion && if (function.OperatorKind != CXXOperatorKind.Conversion &&
function.OperatorKind != CXXOperatorKind.ExplicitConversion) 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; var qualifiedType = parameter.QualifiedType;
ChangeToInterfaceType(ref qualifiedType); ChangeToInterfaceType(ref qualifiedType);
parameter.QualifiedType = qualifiedType; parameter.QualifiedType = qualifiedType;
} }
return base.VisitFunctionDecl(function); return true;
} }
private static void ChangeToInterfaceType(ref QualifiedType type) public override bool VisitProperty(Property property)
{
var tagType = (type.Type.GetFinalPointee() ?? type.Type) as TagType;
if (tagType != null)
{ {
var @class = tagType.Declaration as Class; if (!base.VisitProperty(property))
if (@class != null) return false;
var type = property.QualifiedType;
ChangeToInterfaceType(ref type);
property.QualifiedType = type;
return true;
}
private static void ChangeToInterfaceType(ref QualifiedType type)
{ {
var @interface = @class.Namespace.Classes.Find(c => c.OriginalClass == @class); var finalType = (type.Type.GetFinalPointee() ?? type.Type).Desugar();
if (@interface != null) Class @class;
if (!finalType.TryGetClass(out @class))
return;
var specialization = @class as ClassTemplateSpecialization;
Class @interface = null;
if (specialization == null)
{ {
type.Type = (Type) type.Type.Clone(); @interface = @class.Namespace.Classes.Find(
((TagType) (type.Type.GetFinalPointee() ?? type.Type)).Declaration = @interface; 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
public override bool VisitClassDecl(Class @class) 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)) @class.Specializations.All(s => !s.IsGenerated))
return false; return false;

9
tests/CSharp/CSharp.Tests.cs

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

Loading…
Cancel
Save