Browse Source

Merge pull request #16 from esdrubal/properties

Better CheckDuplicatedNamesPass, GetterSetterToPropertyPass
pull/17/merge
João Matos 13 years ago
parent
commit
ffa17896d8
  1. 25
      src/AST/Declaration.cs
  2. 20
      src/AST/Property.cs
  3. 163
      src/AST/Type.cs
  4. 15
      src/Generator/AST/Utils.cs
  5. 36
      src/Generator/Diagnostics.cs
  6. 3
      src/Generator/Driver.cs
  7. 49
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  8. 91
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  9. 11
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  10. 146
      src/Generator/Passes/CheckAmbiguousOverloads.cs
  11. 149
      src/Generator/Passes/CheckDuplicatedNamesPass.cs
  12. 68
      src/Generator/Passes/DuplicatedNamesCheckerPass.cs
  13. 33
      src/Generator/Passes/FieldToPropertyPass.cs
  14. 7
      src/Generator/Passes/FunctionToInstanceMethodPass.cs
  15. 3
      src/Generator/Passes/FunctionToStaticMethodPass.cs
  16. 100
      src/Generator/Passes/GetterSetterToPropertyPass.cs
  17. 2
      src/Parser/Parser.cpp

25
src/AST/Declaration.cs

@ -38,10 +38,24 @@ namespace CppSharp.AST @@ -38,10 +38,24 @@ namespace CppSharp.AST
/// </summary>
public abstract class Declaration : INamedDecl
{
private DeclarationContext @namespace;
public DeclarationContext OriginalNamespace;
// Namespace the declaration is contained in.
public DeclarationContext Namespace;
public DeclarationContext Namespace
{
get { return @namespace; }
set
{
@namespace = value;
if (OriginalNamespace == null)
OriginalNamespace = @namespace;
}
}
private string name;
public virtual string OriginalName { get; set;}
// Name of the declaration.
public virtual string Name
@ -66,17 +80,14 @@ namespace CppSharp.AST @@ -66,17 +80,14 @@ namespace CppSharp.AST
}
}
// Name of the declaration.
public virtual string OriginalName { get; set;}
public string QualifiedOriginalName
{
get
{
if (Namespace == null)
if (OriginalNamespace == null)
return OriginalName;
return Namespace.IsRoot ? OriginalName
: string.Format("{0}::{1}", Namespace.QualifiedOriginalName, OriginalName);
return OriginalNamespace.IsRoot ? OriginalName
: string.Format("{0}::{1}", OriginalNamespace.QualifiedOriginalName, OriginalName);
}
}

20
src/AST/Property.cs

@ -5,11 +5,6 @@ namespace CppSharp.AST @@ -5,11 +5,6 @@ namespace CppSharp.AST
/// </summary>
public class Property : Declaration, ITypedDecl
{
public Property()
{
}
public Type Type
{
get { return QualifiedType.Type; }
@ -17,17 +12,12 @@ namespace CppSharp.AST @@ -17,17 +12,12 @@ namespace CppSharp.AST
public QualifiedType QualifiedType { get; set; }
public Method GetMethod
{
get;
set;
}
public Method GetMethod { get; set; }
public Method SetMethod
{
get;
set;
}
public Method SetMethod { get; set; }
// The field that should be get and set by this property
public Field Field { get; set; }
public override T Visit<T>(IDeclVisitor<T> visitor)
{

163
src/AST/Type.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace CppSharp.AST
{
@ -162,6 +163,14 @@ namespace CppSharp.AST @@ -162,6 +163,14 @@ namespace CppSharp.AST
{
return Type.ToString();
}
public override bool Equals(object obj)
{
if (!(obj is QualifiedType)) return false;
var type = (QualifiedType) obj;
return Type.Equals(type.Type) && Qualifiers.Equals(type.Qualifiers);
}
}
/// <summary>
@ -184,6 +193,14 @@ namespace CppSharp.AST @@ -184,6 +193,14 @@ namespace CppSharp.AST
{
return visitor.VisitTagType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as TagType;
if (type == null) return false;
return Declaration.Equals(type.Declaration);
}
}
/// <summary>
@ -216,6 +233,18 @@ namespace CppSharp.AST @@ -216,6 +233,18 @@ namespace CppSharp.AST
{
return visitor.VisitArrayType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as ArrayType;
if (type == null) return false;
var equals = Type.Equals(type.Type) && SizeType.Equals(type.SizeType);
if (SizeType == ArraySize.Constant)
equals &= Size.Equals(type.Size);
return equals;
}
}
/// <summary>
@ -238,6 +267,14 @@ namespace CppSharp.AST @@ -238,6 +267,14 @@ namespace CppSharp.AST
{
return visitor.VisitFunctionType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as FunctionType;
if (type == null) return false;
return ReturnType.Equals(type.ReturnType) && Parameters.SequenceEqual(type.Parameters);
}
}
/// <summary>
@ -281,6 +318,15 @@ namespace CppSharp.AST @@ -281,6 +318,15 @@ namespace CppSharp.AST
{
return visitor.VisitPointerType(this, QualifiedPointee.Qualifiers);
}
public override bool Equals(object obj)
{
var type = obj as PointerType;
if (type == null) return false;
return QualifiedPointee.Equals(type.QualifiedPointee)
&& Modifier == type.Modifier;
}
}
/// <summary>
@ -299,6 +345,14 @@ namespace CppSharp.AST @@ -299,6 +345,14 @@ namespace CppSharp.AST
{
return visitor.VisitMemberPointerType(this, quals);
}
public override bool Equals(object obj)
{
var pointer = obj as MemberPointerType;
if (pointer == null) return false;
return Pointee.Equals(pointer.Pointee);
}
}
/// <summary>
@ -317,6 +371,15 @@ namespace CppSharp.AST @@ -317,6 +371,15 @@ namespace CppSharp.AST
{
return visitor.VisitTypedefType(this, quals);
}
public override bool Equals(object obj)
{
var typedef = obj as TypedefType;
if (typedef == null) return false;
var t = Declaration.Equals(typedef.Declaration);
return t;
}
}
/// <summary>
@ -337,6 +400,14 @@ namespace CppSharp.AST @@ -337,6 +400,14 @@ namespace CppSharp.AST
{
return visitor.VisitDecayedType(this, quals);
}
public override bool Equals(object obj)
{
var decay = obj as DecayedType;
if (decay == null) return false;
return Original.Equals(decay.Original);
}
}
/// <summary>
@ -382,6 +453,28 @@ namespace CppSharp.AST @@ -382,6 +453,28 @@ namespace CppSharp.AST
public QualifiedType Type;
public Declaration Declaration;
public long Integral;
public override bool Equals(object obj)
{
if (!(obj is TemplateArgument)) return false;
var arg = (TemplateArgument) obj;
if (Kind != arg.Kind) return false;
switch (Kind)
{
case ArgumentKind.Type:
return Type.Equals(arg.Type);
case ArgumentKind.Declaration:
return Declaration.Equals(arg.Declaration);
case ArgumentKind.Integral:
return Integral.Equals(arg.Integral);
case ArgumentKind.Expression:
return true;
default:
throw new Exception("Unknowed TemplateArgument Kind");
}
}
}
/// <summary>
@ -405,6 +498,15 @@ namespace CppSharp.AST @@ -405,6 +498,15 @@ namespace CppSharp.AST
{
return visitor.VisitTemplateSpecializationType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as TemplateSpecializationType;
if (type == null) return false;
return Arguments.SequenceEqual(type.Arguments)
&& Template.Equals(type.Template);
}
}
/// <summary>
@ -412,18 +514,21 @@ namespace CppSharp.AST @@ -412,18 +514,21 @@ namespace CppSharp.AST
/// </summary>
public class TemplateParameterType : Type
{
public TemplateParameterType()
{
}
public TemplateParameter Parameter;
public Template Template;
public override T Visit<T>(ITypeVisitor<T> visitor,
TypeQualifiers quals = new TypeQualifiers())
{
return visitor.VisitTemplateParameterType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as TemplateParameterType;
if (type == null) return false;
return Parameter.Equals(type.Parameter);
}
}
/// <summary>
@ -431,11 +536,6 @@ namespace CppSharp.AST @@ -431,11 +536,6 @@ namespace CppSharp.AST
/// </summary>
public class TemplateParameterSubstitutionType : Type
{
public TemplateParameterSubstitutionType()
{
}
public QualifiedType Replacement;
public override T Visit<T>(ITypeVisitor<T> visitor,
@ -443,6 +543,14 @@ namespace CppSharp.AST @@ -443,6 +543,14 @@ namespace CppSharp.AST
{
return visitor.VisitTemplateParameterSubstitutionType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as TemplateParameterSubstitutionType;
if (type == null) return false;
return Replacement.Equals(type.Replacement);
}
}
/// <summary>
@ -451,11 +559,6 @@ namespace CppSharp.AST @@ -451,11 +559,6 @@ namespace CppSharp.AST
/// </summary>
public class InjectedClassNameType : Type
{
public InjectedClassNameType()
{
}
public TemplateSpecializationType TemplateSpecialization;
public Class Class;
@ -464,6 +567,15 @@ namespace CppSharp.AST @@ -464,6 +567,15 @@ namespace CppSharp.AST
{
return visitor.VisitInjectedClassNameType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as InjectedClassNameType;
if (type == null) return false;
return TemplateSpecialization.Equals(type.TemplateSpecialization)
&& Class.Equals(type.Class);
}
}
/// <summary>
@ -471,11 +583,6 @@ namespace CppSharp.AST @@ -471,11 +583,6 @@ namespace CppSharp.AST
/// </summary>
public class DependentNameType : Type
{
public DependentNameType()
{
}
public override T Visit<T>(ITypeVisitor<T> visitor,
TypeQualifiers quals = new TypeQualifiers())
{
@ -500,6 +607,14 @@ namespace CppSharp.AST @@ -500,6 +607,14 @@ namespace CppSharp.AST
{
return visitor.VisitCILType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as CILType;
if (type == null) return false;
return Type == type.Type;
}
}
#region Primitives
@ -567,6 +682,14 @@ namespace CppSharp.AST @@ -567,6 +682,14 @@ namespace CppSharp.AST
{
return visitor.VisitBuiltinType(this, quals);
}
public override bool Equals(object obj)
{
var type = obj as BuiltinType;
if (type == null) return false;
return Type == type.Type;
}
}
#endregion

15
src/Generator/AST/Utils.cs

@ -3,23 +3,24 @@ namespace CppSharp.AST @@ -3,23 +3,24 @@ namespace CppSharp.AST
{
public static class ASTUtils
{
public static bool CheckIgnoreFunction(Class @class, Function function)
public static bool CheckIgnoreFunction(Function function)
{
if (function.Ignore) return true;
if (function is Method)
return CheckIgnoreMethod(@class, function as Method);
return CheckIgnoreMethod(function as Method);
return false;
}
public static bool CheckIgnoreMethod(Class @class, Method method)
public static bool CheckIgnoreMethod(Method method)
{
if (method.Ignore) return true;
var isEmptyCtor = method.IsConstructor && method.Parameters.Count == 0;
if (@class.IsValueType && isEmptyCtor)
var @class = method.Namespace as Class;
if (@class != null && @class.IsValueType && isEmptyCtor)
return true;
if (method.IsCopyConstructor || method.IsMoveConstructor)
@ -40,14 +41,12 @@ namespace CppSharp.AST @@ -40,14 +41,12 @@ namespace CppSharp.AST
return false;
}
public static bool CheckIgnoreField(Class @class, Field field)
public static bool CheckIgnoreField(Field field)
{
if (field.Ignore) return true;
if (field.Access != AccessSpecifier.Public)
return true;
return false;
return field.Ignore;
}
}
}

36
src/Generator/Diagnostics.cs

@ -72,6 +72,42 @@ namespace CppSharp @@ -72,6 +72,42 @@ namespace CppSharp
consumer.Emit(diagInfo);
}
public static void EmitMessage(this IDiagnosticConsumer consumer,
string msg, params object[] args)
{
var diagInfo = new DiagnosticInfo
{
Kind = DiagnosticKind.Message,
Message = string.Format(msg, args)
};
consumer.Emit(diagInfo);
}
public static void EmitWarning(this IDiagnosticConsumer consumer,
string msg, params object[] args)
{
var diagInfo = new DiagnosticInfo
{
Kind = DiagnosticKind.Warning,
Message = string.Format(msg, args)
};
consumer.Emit(diagInfo);
}
public static void EmitError(this IDiagnosticConsumer consumer,
string msg, params object[] args)
{
var diagInfo = new DiagnosticInfo
{
Kind = DiagnosticKind.Error,
Message = string.Format(msg, args)
};
consumer.Emit(diagInfo);
}
}
public class TextDiagnosticPrinter : IDiagnosticConsumer

3
src/Generator/Driver.cs

@ -125,6 +125,7 @@ namespace CppSharp @@ -125,6 +125,7 @@ namespace CppSharp
Passes.CleanUnit(Options);
Passes.SortDeclarations();
Passes.ResolveIncompleteDecls();
Passes.CheckIgnoredDecls();
}
public void AddPostPasses()
@ -132,7 +133,7 @@ namespace CppSharp @@ -132,7 +133,7 @@ namespace CppSharp
Passes.CleanInvalidDeclNames();
Passes.CheckIgnoredDecls();
Passes.CheckFlagEnums();
Passes.CheckAmbiguousOverloads();
Passes.CheckDuplicateNames();
Generator.SetupPasses(Passes);
}

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

@ -213,8 +213,6 @@ namespace CppSharp.Generators.CLI @@ -213,8 +213,6 @@ namespace CppSharp.Generators.CLI
GenerateClassFields(@class);
// Generate a property for each field if class is not value type
if (@class.IsRefType)
GenerateClassProperties(@class);
GenerateClassEvents(@class);
@ -250,8 +248,8 @@ namespace CppSharp.Generators.CLI @@ -250,8 +248,8 @@ namespace CppSharp.Generators.CLI
PushIndent();
WriteLine("property System::IntPtr Instance");
WriteStartBraceIndent();
WriteLine("virtual System::IntPtr get() override;");
WriteLine("virtual void set(System::IntPtr instance) override;");
WriteLine("virtual System::IntPtr get();");
WriteLine("virtual void set(System::IntPtr instance);");
WriteCloseBraceIndent();
NewLine();
@ -273,9 +271,6 @@ namespace CppSharp.Generators.CLI @@ -273,9 +271,6 @@ namespace CppSharp.Generators.CLI
var function = functionTemplate.TemplatedFunction;
var typeNames = template.Parameters.Select(
param => "typename " + param.Name).ToList();
var typeCtx = new CLITypePrinterContext()
{
Kind = TypePrinterContextKind.Template,
@ -288,7 +283,12 @@ namespace CppSharp.Generators.CLI @@ -288,7 +283,12 @@ namespace CppSharp.Generators.CLI
var retType = function.ReturnType.Type.Visit(typePrinter,
function.ReturnType.Qualifiers);
WriteLine("generic<{0}>", string.Join(", ", typeNames));
var typeNamesStr = "";
var paramNames = template.Parameters.Select(param => param.Name).ToList();
if (paramNames.Any())
typeNamesStr = "typename " + string.Join(", typename ", paramNames);
WriteLine("generic<{0}>", typeNamesStr);
WriteLine("{0} {1}({2});", retType, SafeIdentifier(function.Name),
GenerateParametersList(function.Parameters));
}
@ -346,7 +346,7 @@ namespace CppSharp.Generators.CLI @@ -346,7 +346,7 @@ namespace CppSharp.Generators.CLI
PushIndent();
foreach (var field in @class.Fields)
{
if (ASTUtils.CheckIgnoreField(@class, field)) continue;
if (ASTUtils.CheckIgnoreField(field)) continue;
GenerateDeclarationCommon(field);
if (@class.IsUnion)
@ -401,7 +401,7 @@ namespace CppSharp.Generators.CLI @@ -401,7 +401,7 @@ namespace CppSharp.Generators.CLI
var staticMethods = new List<Method>();
foreach (var method in @class.Methods)
{
if (ASTUtils.CheckIgnoreMethod(@class, method))
if (ASTUtils.CheckIgnoreMethod(method))
continue;
if (method.IsConstructor)
@ -477,39 +477,33 @@ namespace CppSharp.Generators.CLI @@ -477,39 +477,33 @@ namespace CppSharp.Generators.CLI
public void GenerateClassProperties(Class @class)
{
PushIndent();
foreach (var field in @class.Fields)
{
if (ASTUtils.CheckIgnoreField(@class, field))
continue;
GenerateDeclarationCommon(field);
GenerateProperty(field);
}
PopIndent();
PushIndent();
foreach (var prop in @class.Properties)
{
if (prop.Ignore) continue;
GenerateDeclarationCommon(prop);
GenerateProperty(prop);
var isGetter = prop.GetMethod != null || prop.Field != null;
var isSetter = prop.SetMethod != null || prop.Field != null;
GenerateProperty(prop, isGetter, isSetter);
}
PopIndent();
}
public void GenerateProperty<T>(T decl)
public void GenerateProperty<T>(T decl, bool isGetter = true, bool isSetter = true)
where T : Declaration, ITypedDecl
{
if (!(isGetter || isSetter))
return;
PushBlock(CLIBlockKind.Property, decl);
var type = decl.Type.Visit(TypePrinter, decl.QualifiedType.Qualifiers);
WriteLine("property {0} {1}", type, decl.Name);
WriteStartBraceIndent();
WriteLine("{0} get();", type);
WriteLine("void set({0});", type);
if(isGetter) WriteLine("{0} get();", type);
if(isSetter) WriteLine("void set({0});", type);
WriteCloseBraceIndent();
PopBlock();
@ -517,10 +511,7 @@ namespace CppSharp.Generators.CLI @@ -517,10 +511,7 @@ namespace CppSharp.Generators.CLI
public void GenerateMethod(Method method)
{
if (method.Ignore) return;
if (method.Access != AccessSpecifier.Public)
return;
if (ASTUtils.CheckIgnoreMethod(method)) return;
PushBlock(CLIBlockKind.Method, method);

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

@ -5,6 +5,7 @@ using System.IO; @@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using CppSharp.AST;
using CppSharp.Types;
using Type = CppSharp.AST.Type;
namespace CppSharp.Generators.CLI
{
@ -124,7 +125,7 @@ namespace CppSharp.Generators.CLI @@ -124,7 +125,7 @@ namespace CppSharp.Generators.CLI
foreach (var method in @class.Methods)
{
if (ASTUtils.CheckIgnoreMethod(@class, method))
if (ASTUtils.CheckIgnoreMethod(method))
continue;
GenerateDeclarationCommon(method);
@ -154,16 +155,11 @@ namespace CppSharp.Generators.CLI @@ -154,16 +155,11 @@ namespace CppSharp.Generators.CLI
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
}
foreach (var field in @class.Fields)
{
if (ASTUtils.CheckIgnoreField(@class, field))
continue;
GenerateFieldProperty(field);
}
}
foreach (var property in @class.Properties)
GenerateProperty(property);
foreach (var @event in @class.Events)
{
if (@event.Ignore)
@ -209,9 +205,6 @@ namespace CppSharp.Generators.CLI @@ -209,9 +205,6 @@ namespace CppSharp.Generators.CLI
var function = template.TemplatedFunction;
var typeNames = template.Parameters.Select(
param => "typename " + param.Name).ToList();
var typeCtx = new CLITypePrinterContext()
{
Kind = TypePrinterContextKind.Template,
@ -224,9 +217,14 @@ namespace CppSharp.Generators.CLI @@ -224,9 +217,14 @@ namespace CppSharp.Generators.CLI
var retType = function.ReturnType.Type.Visit(typePrinter,
function.ReturnType.Qualifiers);
WriteLine("generic<{0}>", string.Join(", ", typeNames));
WriteLine("{0} {1}::{2}({3})", retType, QualifiedIdentifier(@class),
SafeIdentifier(function.Name),
var typeNamesStr = "";
var paramNames = template.Parameters.Select(param => param.Name).ToList();
if (paramNames.Any())
typeNamesStr = "typename " + string.Join(", typename ", paramNames);
WriteLine("generic<{0}>", typeNamesStr);
WriteLine("{0} {1}::{2}({3})", retType,
QualifiedIdentifier(@class), SafeIdentifier(function.Name),
GenerateParametersList(function.Parameters));
WriteStartBraceIndent();
@ -239,21 +237,45 @@ namespace CppSharp.Generators.CLI @@ -239,21 +237,45 @@ namespace CppSharp.Generators.CLI
printer.Context = oldCtx;
}
private void GenerateFieldProperty(Field field)
private void GenerateProperty(Property property)
{
var @class = field.Class;
if (property.Ignore) return;
PushBlock(CLIBlockKind.Property);
var @class = property.Namespace as Class;
GeneratePropertyGetter(field, @class);
GeneratePropertySetter(field, @class);
if (property.Field != null)
{
GeneratePropertyGetter(property.Field, @class, property.Name, property.Type);
GeneratePropertySetter(property.Field, @class, property.Name, property.Type);
}
else
{
GeneratePropertyGetter(property.GetMethod, @class, property.Name, property.Type);
GeneratePropertySetter(property.SetMethod, @class, property.Name, property.Type);
}
PopBlock();
}
private void GeneratePropertySetter<T>(T decl, Class @class)
private void GeneratePropertySetter<T>(T decl, Class @class, string name, Type type)
where T : Declaration, ITypedDecl
{
if (decl == null)
return;
WriteLine("void {0}::{1}::set({2} value)", QualifiedIdentifier(@class),
decl.Name, decl.Type);
name, type);
WriteStartBraceIndent();
if (decl is Function)
{
var func = decl as Function;
if(func.Parameters[0].Name != "value")
WriteLine("auto {0} = value;", func.Parameters[0].Name);
GenerateFunctionCall(func, @class);
}
else
{
var param = new Parameter
{
Name = "value",
@ -281,18 +303,29 @@ namespace CppSharp.Generators.CLI @@ -281,18 +303,29 @@ namespace CppSharp.Generators.CLI
Write(marshal.Context.SupportBefore);
WriteLine("{0} = {1};", variable, marshal.Context.Return);
}
WriteCloseBraceIndent();
NewLine();
}
private void GeneratePropertyGetter<T>(T decl, Class @class)
private void GeneratePropertyGetter<T>(T decl, Class @class, string name, Type type)
where T : Declaration, ITypedDecl
{
WriteLine("{0} {1}::{2}::get()", decl.Type, QualifiedIdentifier(@class),
decl.Name);
if (decl == null)
return;
WriteLine("{0} {1}::{2}::get()", type, QualifiedIdentifier(@class),
name);
WriteStartBraceIndent();
if (decl is Function)
{
var func = decl as Function;
GenerateFunctionCall(func, @class);
}
else
{
string variable;
if (decl is Variable)
variable = string.Format("::{0}::{1}",
@ -315,6 +348,8 @@ namespace CppSharp.Generators.CLI @@ -315,6 +348,8 @@ namespace CppSharp.Generators.CLI
Write(marshal.Context.SupportBefore);
WriteLine("return {0};", marshal.Context.Return);
}
WriteCloseBraceIndent();
NewLine();
@ -428,10 +463,10 @@ namespace CppSharp.Generators.CLI @@ -428,10 +463,10 @@ namespace CppSharp.Generators.CLI
private void GenerateVariable(Variable variable, Class @class)
{
GeneratePropertyGetter(variable, @class);
GeneratePropertyGetter(variable, @class, variable.Name, variable.Type);
if (!variable.QualifiedType.Qualifiers.IsConst)
GeneratePropertySetter(variable, @class);
GeneratePropertySetter(variable, @class, variable.Name, variable.Type);
}
private void GenerateClassConstructor(Class @class, bool isIntPtr)
@ -483,7 +518,7 @@ namespace CppSharp.Generators.CLI @@ -483,7 +518,7 @@ namespace CppSharp.Generators.CLI
foreach (var field in @class.Fields)
{
if (ASTUtils.CheckIgnoreField(@class, field)) continue;
if (ASTUtils.CheckIgnoreField(field)) continue;
var nativeField = string.Format("{0}{1}",
nativeVar, field.OriginalName);
@ -621,7 +656,7 @@ namespace CppSharp.Generators.CLI @@ -621,7 +656,7 @@ namespace CppSharp.Generators.CLI
foreach (var field in @class.Fields)
{
if (ASTUtils.CheckIgnoreField(@class, field)) continue;
if (ASTUtils.CheckIgnoreField(field)) continue;
var varName = string.Format("_native.{0}", field.OriginalName);

11
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -384,7 +384,7 @@ namespace CppSharp.Generators.CSharp @@ -384,7 +384,7 @@ namespace CppSharp.Generators.CSharp
foreach (var method in @class.Methods)
{
if (ASTUtils.CheckIgnoreMethod(@class, method))
if (ASTUtils.CheckIgnoreMethod(method))
continue;
if (method.IsConstructor)
@ -432,7 +432,7 @@ namespace CppSharp.Generators.CSharp @@ -432,7 +432,7 @@ namespace CppSharp.Generators.CSharp
foreach (var field in @class.Fields)
{
if (ASTUtils.CheckIgnoreField(@class, field)) continue;
if (ASTUtils.CheckIgnoreField(field)) continue;
var nativeField = string.Format("{0}->{1}",
Helpers.GeneratedIdentifier("ptr"), field.OriginalName);
@ -582,13 +582,14 @@ namespace CppSharp.Generators.CSharp @@ -582,13 +582,14 @@ namespace CppSharp.Generators.CSharp
foreach (var field in @class.Fields)
{
if (ASTUtils.CheckIgnoreField(field)) continue;
GenerateClassField(@class, isInternal, field);
}
}
private void GenerateClassField(Class @class, bool isInternal, Field field)
{
if (ASTUtils.CheckIgnoreField(@class, field)) return;
if (ASTUtils.CheckIgnoreField(field)) return;
PushBlock(CSharpBlockKind.Field);
@ -794,7 +795,7 @@ namespace CppSharp.Generators.CSharp @@ -794,7 +795,7 @@ namespace CppSharp.Generators.CSharp
var staticMethods = new List<Method>();
foreach (var method in @class.Methods)
{
if (ASTUtils.CheckIgnoreMethod(@class, method))
if (ASTUtils.CheckIgnoreMethod(method))
continue;
if (method.IsConstructor)
@ -985,7 +986,7 @@ namespace CppSharp.Generators.CSharp @@ -985,7 +986,7 @@ namespace CppSharp.Generators.CSharp
foreach (var ctor in @class.Constructors)
{
if (ASTUtils.CheckIgnoreMethod(@class, ctor))
if (ASTUtils.CheckIgnoreMethod(ctor))
continue;
GenerateMethod(ctor, @class);

146
src/Generator/Passes/CheckAmbiguousOverloads.cs

@ -1,146 +0,0 @@ @@ -1,146 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using CppSharp.AST;
using CppSharp.Generators;
namespace CppSharp.Passes
{
struct OverloadSignature
{
public string Return;
public List<string> Parameters;
public Function Function;
public OverloadSignature(Function function)
{
Function = function;
Return = function.ReturnType.ToString();
Parameters = new List<string>();
foreach (var param in function.Parameters)
{
var paramType = param.Type.ToString();
Parameters.Add(paramType);
}
}
public static bool IsAmbiguous(OverloadSignature overload1,
OverloadSignature overload2, Class @class)
{
if (overload1.Function == overload2.Function)
return false;
if (ASTUtils.CheckIgnoreFunction(@class, overload1.Function))
return false;
if (ASTUtils.CheckIgnoreFunction(@class, overload2.Function))
return false;
// TODO: Default parameters?
if (overload1.Parameters.Count != overload2.Parameters.Count)
return false;
if (overload1.Parameters.Count == 0)
return true;
for (var i = 0; i < overload1.Parameters.Count; i++)
{
if (overload1.Parameters[i] != overload2.Parameters[i])
return false;
}
return true;
}
};
public class CheckAmbiguousOverloads : TranslationUnitPass
{
private readonly ISet<Function> visited;
public CheckAmbiguousOverloads()
{
visited = new HashSet<Function>();
Options.VisitNamespaceEnums = false;
Options.VisitNamespaceTemplates = false;
Options.VisitNamespaceTypedefs = false;
Options.VisitNamespaceEvents = false;
Options.VisitNamespaceVariables = false;
Options.VisitClassBases = false;
Options.VisitClassFields = false;
Options.VisitClassProperties = false;
}
public override bool VisitClassDecl(Class @class)
{
visited.Clear();
return base.VisitClassDecl(@class);
}
public override bool VisitMethodDecl(Method method)
{
CheckOverloads(method);
return false;
}
public override bool VisitFunctionDecl(Function function)
{
CheckOverloads(function);
return false;
}
private bool CheckOverloads(Function function)
{
if (visited.Contains(function))
return false;
if (function.Ignore)
return false;
var overloads = function.Namespace.GetFunctionOverloads(function);
var signatures = overloads.Select(fn => new OverloadSignature(fn)).ToList();
foreach (var sig1 in signatures)
{
visited.Add(sig1.Function);
if (sig1.Function.Ignore)
continue;
foreach (var sig2 in signatures)
{
if (sig2.Function.Ignore)
continue;
var @class = function.Namespace as Class;
if (!OverloadSignature.IsAmbiguous(sig1, sig2, @class))
continue;
Driver.Diagnostics.EmitWarning(DiagnosticId.AmbiguousOverload,
"Overload {0} is ambiguous, renaming automatically",
sig1.Function.QualifiedOriginalName);
RenameOverload(sig1.Function);
return false;
}
}
return true;
}
public void RenameOverload(Function function)
{
function.Name = function.Name + "0";
}
}
public static class CheckAmbiguousOverloadsExtensions
{
public static void CheckAmbiguousOverloads(this PassBuilder builder)
{
var pass = new CheckAmbiguousOverloads();
builder.AddPass(pass);
}
}
}

149
src/Generator/Passes/CheckDuplicatedNamesPass.cs

@ -0,0 +1,149 @@ @@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using CppSharp.AST;
namespace CppSharp.Passes
{
class DeclarationName
{
private readonly string Name;
private readonly Dictionary<string, int> methodSignatures;
private int Count;
public DeclarationName(string name)
{
Name = name;
methodSignatures = new Dictionary<string, int>();
}
public bool UpdateName(Declaration decl)
{
if (decl.Name != Name)
throw new Exception("Invalid name");
var method = decl as Method;
if (method != null)
{
return UpdateName(method);
}
var count = Count++;
if (count == 0)
return false;
decl.Name += count.ToString(CultureInfo.InvariantCulture);
return true;
}
private bool UpdateName(Method method)
{
var @params = method.Parameters.Select(p => p.QualifiedType.ToString());
var signature = string.Format("{0}({1})", Name,string.Join( ", ", @params));
if (Count == 0)
Count++;
if (!methodSignatures.ContainsKey(signature))
{
methodSignatures.Add(signature, 0);
return false;
}
var methodCount = ++methodSignatures[signature];
if (Count < methodCount+1)
Count = methodCount+1;
method.Name += methodCount.ToString(CultureInfo.InvariantCulture);
return true;
}
}
public class CheckDuplicatedNamesPass : TranslationUnitPass
{
private readonly IDictionary<string, DeclarationName> names;
public CheckDuplicatedNamesPass()
{
names = new Dictionary<string, DeclarationName>();
}
public override bool VisitFieldDecl(Field decl)
{
if (ASTUtils.CheckIgnoreField(decl))
return false;
if(!AlreadyVisited(decl))
CheckDuplicate(decl);
return false;
}
public override bool VisitProperty(Property decl)
{
if(!AlreadyVisited(decl))
CheckDuplicate(decl);
return false;
}
public override bool VisitMethodDecl(Method decl)
{
if (ASTUtils.CheckIgnoreMethod(decl))
return false;
if(!AlreadyVisited(decl))
CheckDuplicate(decl);
return false;
}
public override bool VisitClassDecl(Class @class)
{
if (AlreadyVisited(@class) || @class.IsIncomplete)
return false;
// DeclarationName should always process methods first,
// so we visit methods first.
foreach (var method in @class.Methods)
VisitMethodDecl(method);
foreach (var field in @class.Fields)
VisitFieldDecl(field);
foreach (var property in @class.Properties)
VisitProperty(property);
return false;
}
void CheckDuplicate(Declaration decl)
{
if (decl.IsDependent || decl.Ignore)
return;
if (string.IsNullOrWhiteSpace(decl.Name))
return;
var fullName = decl.QualifiedName;
// If the name is not yet on the map, then add it.
if (!names.ContainsKey(fullName))
names.Add(fullName, new DeclarationName(decl.Name));
if (names[fullName].UpdateName(decl))
Driver.Diagnostics.EmitWarning("Duplicate name {0}, renamed to {1}", fullName, decl.Name);
}
}
public static class CheckDuplicateNamesExtensions
{
public static void CheckDuplicateNames(this PassBuilder builder)
{
var pass = new CheckDuplicatedNamesPass();
builder.AddPass(pass);
}
}
}

68
src/Generator/Passes/DuplicatedNamesCheckerPass.cs

@ -1,68 +0,0 @@ @@ -1,68 +0,0 @@
using System;
using System.Collections.Generic;
using CppSharp.AST;
namespace CppSharp.Passes
{
public class DuplicatedNamesCheckerPass : TranslationUnitPass
{
private readonly IDictionary<string, Declaration> names;
public DuplicatedNamesCheckerPass()
{
names = new Dictionary<string, Declaration>();
}
public override bool VisitClassDecl(Class @class)
{
if (@class.Ignore) return false;
names.Clear();
return base.VisitClassDecl(@class);
}
public override bool VisitDeclaration(Declaration decl)
{
if (AlreadyVisited(decl))
return true;
Visited.Add(decl);
CheckDuplicate(decl);
return base.VisitDeclaration(decl);
}
public override bool VisitParameterDecl(Parameter parameter)
{
return true;
}
void CheckDuplicate(Declaration decl)
{
if (string.IsNullOrWhiteSpace(decl.Name))
return;
Declaration duplicate;
// If the name is not yet on the map, then add it.
if (!names.TryGetValue(decl.Name, out duplicate))
{
names[decl.Name] = decl;
return;
}
// Else we found a duplicate name and need to change it.
Console.WriteLine("Found a duplicate named declaration: {0}",
decl.Name);
}
}
public static class CheckDuplicateNamesExtensions
{
public static void CheckDuplicateNames(this PassBuilder builder)
{
var pass = new DuplicatedNamesCheckerPass();
builder.AddPass(pass);
}
}
}

33
src/Generator/Passes/FieldToPropertyPass.cs

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
using CppSharp.AST;
namespace CppSharp.Passes
{
public class FieldToPropertyPass : TranslationUnitPass
{
public override bool VisitFieldDecl(Field field)
{
var @class = field.Namespace as Class;
if (@class == null)
return false;
if (@class.IsValueType)
return false;
if (ASTUtils.CheckIgnoreField(field))
return false;
var prop = new Property()
{
Name = field.Name,
Namespace = field.Namespace,
QualifiedType = field.QualifiedType,
Field = field
};
@class.Properties.Add(prop);
field.ExplicityIgnored = true;
return false;
}
}
}

7
src/Generator/Passes/FunctionToInstanceMethodPass.cs

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
using System;
using System.Linq;
using CppSharp.AST;
using CppSharp.Generators;
namespace CppSharp.Passes
{
@ -44,19 +45,23 @@ namespace CppSharp.Passes @@ -44,19 +45,23 @@ namespace CppSharp.Passes
var method = new Method()
{
Namespace = @class,
OriginalNamespace = function.Namespace,
Name = function.Name,
OriginalName = function.OriginalName,
Mangled = function.Mangled,
Access = AccessSpecifier.Public,
Kind = CXXMethodKind.Normal,
ReturnType = function.ReturnType,
Parameters = function.Parameters.Skip(1).ToList(),
Parameters = function.Parameters,
CallingConvention = function.CallingConvention,
IsVariadic = function.IsVariadic,
IsInline = function.IsInline,
Conversion = MethodConversionKind.FunctionToInstanceMethod
};
if (Driver.Options.GeneratorKind == LanguageGeneratorKind.CSharp)
method.Parameters = method.Parameters.Skip(1).ToList();
@class.Methods.Add(method);
Console.WriteLine("Instance method: {0}::{1}", @class.Name,

3
src/Generator/Passes/FunctionToStaticMethodPass.cs

@ -33,7 +33,8 @@ namespace CppSharp.Passes @@ -33,7 +33,8 @@ namespace CppSharp.Passes
// Create a new fake method so it acts as a static method.
var method = new Method()
{
Namespace = @class.Namespace,
Namespace = @class,
OriginalNamespace = function.Namespace,
Name = name,
OriginalName = function.OriginalName,
Mangled = function.Mangled,

100
src/Generator/Passes/GetterSetterToPropertyPass.cs

@ -1,4 +1,6 @@ @@ -1,4 +1,6 @@
using System;
using System.Diagnostics;
using System.Linq;
using CppSharp.AST;
namespace CppSharp.Passes
@ -44,51 +46,97 @@ namespace CppSharp.Passes @@ -44,51 +46,97 @@ namespace CppSharp.Passes
return !isRetVoid && isGetter && method.Parameters.Count == 0;
}
Property GetOrCreateProperty(Class @class, string name, QualifiedType type)
{
var prop = @class.Properties.FirstOrDefault(property => property.Name == name
&& property.QualifiedType.Equals(type));
var prop2 = @class.Properties.FirstOrDefault(property => property.Name == name);
if (prop == null && prop2 != null)
Driver.Diagnostics.EmitWarning(DiagnosticId.PropertySynthetized,
"Property {0}::{1} already exist with type {2}", @class.Name, name, type.Type.ToString());
if (prop != null)
return prop;
prop = new Property
{
Name = name,
Namespace = @class,
QualifiedType = type
};
@class.Properties.Add(prop);
return prop;
}
public override bool VisitMethodDecl(Method method)
{
//var expansions = method.PreprocessedEntities.OfType<MacroExpansion>();
//if (expansions.Any(e => e.Text.Contains("ACCESSOR")))
// System.Diagnostics.Debugger.Break();
if (AlreadyVisited(method))
return false;
if (!IsGetter(method))
if (ASTUtils.CheckIgnoreMethod(method))
return false;
var @class = method.Namespace as Class;
foreach (var classMethod in @class.Methods)
if (@class == null || @class.IsIncomplete)
return false;
if (IsGetter(method))
{
if (!IsSetter(classMethod))
continue;
var name = method.Name.Substring("get".Length);
var prop = GetOrCreateProperty(@class, name, method.ReturnType);
prop.GetMethod = method;
if (classMethod.Parameters[0].Type.Equals(method.ReturnType.Type))
continue;
// Do not generate the original method now that we know it is a getter.
method.IsGenerated = false;
var getName = method.Name.Substring("get".Length);
var setName = classMethod.Name.Substring("set".Length);
Driver.Diagnostics.EmitMessage(DiagnosticId.PropertySynthetized,
"Getter created: {0}::{1}", @class.Name, name);
if (getName != setName)
continue;
return false;
}
// We found a compatible pair of methods, create a property.
var prop = new Property
if (IsSetter(method) && IsValidSetter(method))
{
Name = getName,
Namespace = @class,
QualifiedType = method.ReturnType
};
var name = method.Name.Substring("set".Length);
// Ignore the original methods now that we have a property.
method.ExplicityIgnored = true;
classMethod.ExplicityIgnored = true;
var type = method.Parameters[0].QualifiedType;
var prop = GetOrCreateProperty(@class, name, type);
prop.SetMethod = method;
@class.Properties.Add(prop);
// Ignore the original method now that we know it is a setter.
method.IsGenerated = false;
Driver.Diagnostics.EmitMessage(DiagnosticId.PropertySynthetized,
"Getter/setter property created: {0}::{1}", @class.Name,
getName);
return true;
"Setter created: {0}::{1}", @class.Name, name);
return false;
}
return false;
}
// Check if a matching getter exist or no other setter exists.
private bool IsValidSetter(Method method)
{
var @class = method.Namespace as Class;
var name = method.Name.Substring("set".Length);
if (method.Parameters.Count == 0)
return false;
var type = method.Parameters[0].Type;
var getter = @class.Methods.FirstOrDefault(m => m.Name == "Get" + name && m.Type.Equals(type));
var otherSetter = @class.Methods.FirstOrDefault(m => m.Name == method.Name
&& m.Parameters.Count == 1
&& !m.Parameters[0].Type.Equals(type));
return getter != null || otherSetter == null;
}
}
}

2
src/Parser/Parser.cpp

@ -463,6 +463,7 @@ void Parser::WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C) @@ -463,6 +463,7 @@ void Parser::WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C)
{
case TargetCXXABI::Microsoft:
{
#if SVN_REVISION >= 187409
MicrosoftVFTableContext VTContext(*AST);
auto VFPtrs = VTContext.getVFPtrOffsets(RD);
@ -481,6 +482,7 @@ void Parser::WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C) @@ -481,6 +482,7 @@ void Parser::WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C)
C->Layout->VFTables->Add(Info);
break;
}
#endif
}
case TargetCXXABI::GenericItanium:
{

Loading…
Cancel
Save