From 6f5a46d7c3edd75832e9d600969291a4653e67dc Mon Sep 17 00:00:00 2001 From: duckdoom5 Date: Tue, 4 Mar 2025 12:15:41 +0100 Subject: [PATCH 1/4] Misc changes/fixes --- src/Core/Diagnostics.cs | 5 ++++- src/CppParser/Bootstrap/StmtCodeGenerators.cs | 2 +- src/Generator/Types/Std/Stdlib.CSharp.cs | 3 +++ tests/dotnet/Common/Common.h | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Core/Diagnostics.cs b/src/Core/Diagnostics.cs index a7f40ac6c2..c10733ab6a 100644 --- a/src/Core/Diagnostics.cs +++ b/src/Core/Diagnostics.cs @@ -128,7 +128,10 @@ public void Emit(DiagnosticInfo info) { Console.WriteLine(message); } - Debug.WriteLine(message); + + // Don't output debug messages to VS output window. This is extremely slow. + if (info.Kind > DiagnosticKind.Debug) + Debug.WriteLine(message); } public void PushIndent(int level) diff --git a/src/CppParser/Bootstrap/StmtCodeGenerators.cs b/src/CppParser/Bootstrap/StmtCodeGenerators.cs index fef1a24e94..faaf2ef200 100644 --- a/src/CppParser/Bootstrap/StmtCodeGenerators.cs +++ b/src/CppParser/Bootstrap/StmtCodeGenerators.cs @@ -344,7 +344,7 @@ public override bool VisitProperty(Property property) { var expr = $"_S->{fieldName} = static_cast(WalkExpression(S->{methodName}()));"; - if (fieldName == "base" && typeName is "CXXDependentScopeMemberExpr") + if (fieldName == "base" && @class.Name == "CXXDependentScopeMemberExpr") { // Clang asserts that 'getBase()' is not called when 'isImplicitAccess()' returns true WriteLine("if (!S->isImplicitAccess())"); diff --git a/src/Generator/Types/Std/Stdlib.CSharp.cs b/src/Generator/Types/Std/Stdlib.CSharp.cs index 6673604ad2..30dd436b49 100644 --- a/src/Generator/Types/Std/Stdlib.CSharp.cs +++ b/src/Generator/Types/Std/Stdlib.CSharp.cs @@ -307,10 +307,13 @@ public override Type SignatureType(TypePrinterContext ctx) { if (ctx.Kind == TypePrinterContextKind.Managed) return new CILType(typeof(string)); + var typePrinter = new CSharpTypePrinter(null); typePrinter.PushContext(TypePrinterContextKind.Native); + if (ctx.Type.Desugar().IsAddress()) return new CustomType(typePrinter.IntPtrType); + ClassTemplateSpecialization basicString = GetBasicString(ctx.Type); return new CustomType(basicString.Visit(typePrinter).Type); } diff --git a/tests/dotnet/Common/Common.h b/tests/dotnet/Common/Common.h index 2bb28256e4..322491bbd8 100644 --- a/tests/dotnet/Common/Common.h +++ b/tests/dotnet/Common/Common.h @@ -1,4 +1,5 @@ -#include "../Tests.h" +#pragma once +#include "../Tests.h" #include "AnotherUnit.h" #ifdef _WIN32 From 6c8002b84428b2f042b34b73845a891d09ee0f80 Mon Sep 17 00:00:00 2001 From: duckdoom5 Date: Thu, 6 Mar 2025 18:18:11 +0100 Subject: [PATCH 2/4] Add color to console output --- src/Core/Diagnostics.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Core/Diagnostics.cs b/src/Core/Diagnostics.cs index c10733ab6a..b0626bc3b3 100644 --- a/src/Core/Diagnostics.cs +++ b/src/Core/Diagnostics.cs @@ -112,13 +112,25 @@ public ConsoleDiagnostics() Level = DiagnosticKind.Message; } + private string GetColorForDiagKind(DiagnosticKind kind) => + kind switch + { + DiagnosticKind.Debug => null, + DiagnosticKind.Message => null, + DiagnosticKind.Warning => "\u001b[33m", // yellow + DiagnosticKind.Error => "\u001b[91m", // red + _ => null + }; + public void Emit(DiagnosticInfo info) { if (info.Kind < Level) return; var currentIndentation = Indents.Sum(); - var message = new string(' ', currentIndentation) + info.Message; + var colorString = GetColorForDiagKind(info.Kind); + var colorReset = colorString == null ? null : "\u001b[0m"; + var message = $"{new string(' ', currentIndentation)}{colorString}{info.Message}{colorReset}"; if (info.Kind == DiagnosticKind.Error) { From c016d47745cd28ddbfb745c1a111cfe311d45f6a Mon Sep 17 00:00:00 2001 From: duckdoom5 Date: Thu, 6 Mar 2025 18:25:14 +0100 Subject: [PATCH 3/4] Code cleanup --- src/Generator/Passes/RenamePass.cs | 170 +++++++++++++---------------- 1 file changed, 76 insertions(+), 94 deletions(-) diff --git a/src/Generator/Passes/RenamePass.cs b/src/Generator/Passes/RenamePass.cs index 6db369e6b3..9dc5778fb9 100644 --- a/src/Generator/Passes/RenamePass.cs +++ b/src/Generator/Passes/RenamePass.cs @@ -43,27 +43,33 @@ protected RenamePass(RenameTargets targets) public virtual bool Rename(Declaration decl, out string newName) { - if (decl is Method method && !method.IsStatic) + switch (decl) { - Method rootBaseMethod; - if (method.OriginalNamespace is Class @class && @class.IsInterface) - rootBaseMethod = (Method)method.OriginalFunction; - else - rootBaseMethod = method.GetRootBaseMethod(); - if (rootBaseMethod != null && rootBaseMethod != method) + case Method { IsStatic: false } method: { - newName = rootBaseMethod.Name; - return true; - } - } + Method rootBaseMethod; + if (method.OriginalNamespace is Class { IsInterface: true }) + rootBaseMethod = (Method)method.OriginalFunction; + else + rootBaseMethod = method.GetRootBaseMethod(); + if (rootBaseMethod != null && rootBaseMethod != method) + { + newName = rootBaseMethod.Name; + return true; + } - if (decl is Property property && !property.IsStatic) - { - var rootBaseProperty = ((Class)property.Namespace).GetBasePropertyByName(property); - if (rootBaseProperty != null && rootBaseProperty != property) + break; + } + case Property { IsStatic: false } property: { - newName = rootBaseProperty.Name; - return true; + var rootBaseProperty = ((Class)property.Namespace).GetBasePropertyByName(property); + if (rootBaseProperty != null && rootBaseProperty != property) + { + newName = rootBaseProperty.Name; + return true; + } + + break; } } @@ -73,62 +79,46 @@ public virtual bool Rename(Declaration decl, out string newName) public bool IsRenameableDecl(Declaration decl) { - if (decl is Class) - return Targets.HasFlag(RenameTargets.Class); - - var method = decl as Method; - if (method != null) + switch (decl) { - return Targets.HasFlag(RenameTargets.Method) && - method.Kind == CXXMethodKind.Normal && - method.Name != "dispose"; - } - - var function = decl as Function; - if (function != null) - { - // Special case the IDisposable.Dispose method. - return Targets.HasFlag(RenameTargets.Function) && - (!function.IsOperator && function.Name != "dispose"); - } - - if (decl is Parameter) - return Targets.HasFlag(RenameTargets.Parameter); - - if (decl is Enumeration.Item) - return Targets.HasFlag(RenameTargets.EnumItem); - - if (decl is Enumeration) - return Targets.HasFlag(RenameTargets.Enum); - - var property = decl as Property; - if (property != null) - return Targets.HasFlag(RenameTargets.Property) && !property.IsIndexer; - - if (decl is Event) - return Targets.HasFlag(RenameTargets.Event); - - if (decl is TypedefDecl) - return Targets.HasFlag(RenameTargets.Delegate); - - if (decl is Namespace && !(decl is TranslationUnit)) - return Targets.HasFlag(RenameTargets.Namespace); - - if (decl is Variable) - return Targets.HasFlag(RenameTargets.Variable); - - var field = decl as Field; - if (field != null) - { - if (!Targets.HasFlag(RenameTargets.Field)) + case Class: + return Targets.HasFlag(RenameTargets.Class); + case Method method: + return Targets.HasFlag(RenameTargets.Method) && + method.Kind == CXXMethodKind.Normal && + method.Name != "dispose"; + case Function function: + // Special case the IDisposable.Dispose method. + return Targets.HasFlag(RenameTargets.Function) && + (!function.IsOperator && function.Name != "dispose"); + case Parameter: + return Targets.HasFlag(RenameTargets.Parameter); + case Enumeration.Item: + return Targets.HasFlag(RenameTargets.EnumItem); + case Enumeration: + return Targets.HasFlag(RenameTargets.Enum); + case Property property: + return Targets.HasFlag(RenameTargets.Property) && !property.IsIndexer; + case Event: + return Targets.HasFlag(RenameTargets.Event); + case TypedefDecl: + return Targets.HasFlag(RenameTargets.Delegate); + case Namespace when !(decl is TranslationUnit): + return Targets.HasFlag(RenameTargets.Namespace); + case Variable: + return Targets.HasFlag(RenameTargets.Variable); + case Field when !Targets.HasFlag(RenameTargets.Field): + return false; + case Field field: + { + var fieldProperty = ((Class)field.Namespace).Properties.FirstOrDefault( + p => p.Field == field); + return (fieldProperty != null && + fieldProperty.IsInRefTypeAndBackedByValueClassField()); + } + default: return false; - var fieldProperty = ((Class)field.Namespace).Properties.FirstOrDefault( - p => p.Field == field); - return (fieldProperty != null && - fieldProperty.IsInRefTypeAndBackedByValueClassField()); } - - return false; } public override bool VisitDeclaration(Declaration decl) @@ -148,8 +138,7 @@ public override bool VisitDeclaration(Declaration decl) private bool Rename(Declaration decl) { - string newName; - if (!Rename(decl, out newName) || AreThereConflicts(decl, newName)) + if (!Rename(decl, out var newName) || AreThereConflicts(decl, newName)) return false; decl.Name = newName; @@ -167,8 +156,7 @@ private static bool AreThereConflicts(Declaration decl, string newName) declarations.AddRange(decl.Namespace.Events); declarations.Add(decl.Namespace); - var function = decl as Function; - if (function != null) + if (decl is Function function) // account for overloads declarations.AddRange(GetFunctionsWithTheSameParams(function)); else @@ -177,11 +165,10 @@ private static bool AreThereConflicts(Declaration decl, string newName) declarations.AddRange(decl.Namespace.Variables); declarations.AddRange(from typedefDecl in decl.Namespace.Typedefs let pointerType = typedefDecl.Type.Desugar() as PointerType - where pointerType != null && pointerType.GetFinalPointee() is FunctionType + where pointerType?.GetFinalPointee() is FunctionType select typedefDecl); - var specialization = decl as ClassTemplateSpecialization; - if (specialization != null) + if (decl is ClassTemplateSpecialization specialization) declarations.RemoveAll(d => specialization.TemplatedDecl.TemplatedDecl == d); var @class = decl.Namespace as Class; @@ -201,8 +188,7 @@ where typedefDecl.Type.Desugar() is FunctionType if (decl is Method && decl.IsGenerated) return @class.GetPropertyByName(newName) != null; - var property = decl as Property; - if (property != null) + if (decl is Property property) { Property existingProperty = @class.Properties.Find( p => p != decl && p.Name == newName); @@ -216,8 +202,7 @@ where typedefDecl.Type.Desugar() is FunctionType } } - var enumItem = decl as Enumeration.Item; - if (enumItem != null) + if (decl is Enumeration.Item enumItem) return ((Enumeration)enumItem.Namespace).Items.Any( i => i != decl && i.Name == newName); @@ -226,8 +211,7 @@ where typedefDecl.Type.Desugar() is FunctionType private static IEnumerable GetFunctionsWithTheSameParams(Function function) { - var method = function as Method; - if (method != null) + if (function is Method method) { return ((Class)method.Namespace).Methods.Where( m => !m.Ignore && m.Parameters.SequenceEqual(function.Parameters, new ParameterComparer())); @@ -391,14 +375,12 @@ public static string ConvertCaseString(Declaration decl, RenameCasePattern patte if (decl.Name.All(c => !char.IsLetter(c))) return decl.Name; - var typedef = decl as TypedefDecl; - if (typedef != null && typedef.IsSynthetized) - return decl.Name; - - var property = decl as Property; - if (property != null && property.GetMethod != null && - property.GetMethod.SynthKind == FunctionSynthKind.InterfaceInstance) - return decl.Name; + switch (decl) + { + case TypedefDecl { IsSynthetized: true }: + case Property { GetMethod.SynthKind: FunctionSynthKind.InterfaceInstance }: + return decl.Name; + } var sb = new StringBuilder(decl.Name); // check if it's been renamed to avoid a keyword @@ -412,14 +394,14 @@ public static string ConvertCaseString(Declaration decl, RenameCasePattern patte { case RenameCasePattern.UpperCamelCase: // ensure separation in enum items by not ending up with more capitals in a row than before - if (sb.Length == 1 || !char.IsUpper(sb[1]) || !(decl is Enumeration.Item)) + if (sb.Length == 1 || !char.IsUpper(sb[1]) || decl is not Enumeration.Item) sb[0] = char.ToUpperInvariant(sb[0]); - if (@class != null && @class.Type == ClassType.Interface) + if (@class is { Type: ClassType.Interface }) sb[1] = char.ToUpperInvariant(sb[1]); break; case RenameCasePattern.LowerCamelCase: sb[0] = char.ToLowerInvariant(sb[0]); - if (@class != null && @class.Type == ClassType.Interface) + if (@class is { Type: ClassType.Interface }) sb[1] = char.ToLowerInvariant(sb[1]); break; } From 887e4e4e12d110640362de18dba0768b6a677b38 Mon Sep 17 00:00:00 2001 From: duckdoom5 Date: Thu, 6 Mar 2025 18:33:15 +0100 Subject: [PATCH 4/4] Fix C++20 compile error --- include/CppSharp.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/CppSharp.h b/include/CppSharp.h index 5543007d66..385ed34bd6 100644 --- a/include/CppSharp.h +++ b/include/CppSharp.h @@ -6,6 +6,7 @@ // // Licensed under the MIT license // ------------------------------------------------------------------------------------------- // +// clang-format off #pragma once #if defined(__cplusplus_cli) @@ -293,7 +294,7 @@ namespace clix { /// String to be marshalled to the other side /// The marshaled representation of the string template::Select::Either< + typename detail::IfManaged::Select::template Either< typename detail::StringTypeSelector::Type, System::String^>::Type >