diff --git a/src/Executor/CodeExecutor.cs b/src/Executor/CodeExecutor.cs index 293eb2d..998c96e 100644 --- a/src/Executor/CodeExecutor.cs +++ b/src/Executor/CodeExecutor.cs @@ -17,6 +17,11 @@ public static class CodeExecutor /// public static readonly Interpreter Interpreter = new(); + /// + /// The static of . + /// + public static RuntimeResult RuntimeResult => Interpreter.RuntimeResult; + /// /// The runtime context, may be . /// @@ -40,7 +45,7 @@ public static void CreateRuntimeContext(string filePath) /// Use to initialize the runtime context. /// /// Exclude built-in I/O functions like ? - public static void PopulateRuntimeContext(bool excludeIO=false) + public static void PopulateRuntimeContext(bool excludeIO = false) { if (RuntimeContext is null) throw new NullReferenceException($"{nameof(RuntimeContext)} is null! Call {nameof(CreateRuntimeContext)} to create it!"); diff --git a/src/GlobalSuppressions.cs b/src/GlobalSuppressions.cs index 3cb47e8..c5e947a 100644 --- a/src/GlobalSuppressions.cs +++ b/src/GlobalSuppressions.cs @@ -10,3 +10,4 @@ [assembly: SuppressMessage("Style", "IDE0078:Use pattern matching", Justification = "Recommended fix breaks code.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.Core.Text.EzrCharacterList.Multiplication(EzrSquared.Runtime.Types.IEzrObject,EzrSquared.Runtime.RuntimeResult)")] [assembly: SuppressMessage("Style", "IDE0078:Use pattern matching", Justification = "Recommended fix breaks code.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.Collections.EzrList.Multiplication(EzrSquared.Runtime.Types.IEzrObject,EzrSquared.Runtime.RuntimeResult)")] [assembly: SuppressMessage("Style", "IDE0078:Use pattern matching", Justification = "Recommended fix breaks code.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.Core.Text.EzrString.Multiplication(EzrSquared.Runtime.Types.IEzrObject,EzrSquared.Runtime.RuntimeResult)")] +[assembly: SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "That's too many ternary operations.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.EzrSharpCompatibilityWrapper.Validate~System.Boolean")] diff --git a/src/Runtime/Collections/RuntimeEzrObjectDictionary.cs b/src/Runtime/Collections/RuntimeEzrObjectDictionary.cs index 71c28c8..64589a4 100644 --- a/src/Runtime/Collections/RuntimeEzrObjectDictionary.cs +++ b/src/Runtime/Collections/RuntimeEzrObjectDictionary.cs @@ -21,7 +21,7 @@ public class RuntimeEzrObjectDictionary : IMutable /// /// The number of s in the . /// - [SharpAutoWrapper(IsReadOnly = true)] + [SharpAutoWrapper(isReadOnly: true)] public int Length => _items.Count; /// @@ -103,7 +103,7 @@ public bool Remove(IEzrObject key, RuntimeResult result) /// /// The key (hash) to be removed. /// if the operation was successful, if not. - [SharpAutoWrapper(Name = "remove_by_hash")] + [SharpAutoWrapper("remove_by_hash")] public bool RemoveHash(int key) { return _items.Remove(key); diff --git a/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityObjectInstance.cs b/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityObjectInstance.cs index af17d7e..94f72f1 100644 --- a/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityObjectInstance.cs +++ b/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityObjectInstance.cs @@ -1,5 +1,6 @@ using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers; using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.Executables; +using EzrSquared.Runtime.WrapperAttributes; using EzrSquared.Util; using System; using System.Collections.Generic; @@ -29,7 +30,6 @@ public class EzrSharpCompatibilityObjectInstance : EzrSharpCompatibilityWrapper /// /// The object to wrap. /// The C# object's type. - /// Runtime result for carrying any errors. /// The context in which this object was created. /// The starting position of the object. /// The ending position of the object. @@ -45,20 +45,24 @@ public EzrSharpCompatibilityObjectInstance( | DynamicallyAccessedMemberTypes.NonPublicFields)] Type instanceType, - RuntimeResult result, Context parentContext, Position startPosition, Position endPosition) : base(instanceType, parentContext, startPosition, endPosition) + Context parentContext, Position startPosition, Position endPosition) : base(instanceType, parentContext, startPosition, endPosition) { Instance = instance; Tag = $"{Tag}.{SharpMemberName}.{Utils.GetNextUniqueId()}"; - MethodInfo[] publicMethods = instanceType.GetMethods(BindingFlags.Public | BindingFlags.Instance); - Dictionary duplicateNames = new(publicMethods.Length); - for (int i = 0; i < publicMethods.Length; i++) + MethodInfo[] allMethods = instanceType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + Dictionary duplicateNames = new(allMethods.Length); + for (int i = 0; i < allMethods.Length; i++) { - MethodInfo method = publicMethods[i]; - if (method.IsAbstract) + MethodInfo method = allMethods[i]; + if (method.IsAbstract || (!method.IsPublic && method.GetCustomAttribute() is null)) continue; - string methodObjectName = Utils.PascalToSnakeCase(method.Name); + EzrSharpCompatibilityFunction methodObject = new(method, Instance, Context, StartPosition, EndPosition, skipValidation: true); + if (!methodObject.Validate()) + continue; + + string methodObjectName = methodObject.SharpMemberName; if (duplicateNames.TryGetValue(method.Name, out int duplicates)) { methodObjectName += $"_{duplicates}"; @@ -67,31 +71,35 @@ public EzrSharpCompatibilityObjectInstance( else duplicateNames.Add(method.Name, 1); - EzrSharpCompatibilityFunction methodObject = new(method, Instance, Context, StartPosition, EndPosition); - if (methodObject.Validate(result)) - return; - Context.Set(null, methodObjectName, ReferencePool.Get(methodObject, AccessMod.Constant)); } - PropertyInfo[] publicProperties = instanceType.GetProperties(BindingFlags.Public | BindingFlags.Instance); - for (int i = 0; i < publicProperties.Length; i++) + PropertyInfo[] allProperties = instanceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + for (int i = 0; i < allProperties.Length; i++) { - EzrSharpCompatibilityProperty property = new(publicProperties[i], Instance, Context, StartPosition, EndPosition); - if (property.Validate(result)) - return; + PropertyInfo property = allProperties[i]; + if (property.GetMethod?.IsPublic != true && property.SetMethod?.IsPublic != true && property.GetCustomAttribute() is null) + continue; - Context.Set(null, property.SharpMemberName, ReferencePool.Get(property, AccessMod.Constant)); + EzrSharpCompatibilityProperty propertyObject = new(property, Instance, Context, StartPosition, EndPosition, skipValidation: true); + if (!propertyObject.Validate()) + continue; + + Context.Set(null, propertyObject.SharpMemberName, ReferencePool.Get(propertyObject, AccessMod.Constant)); } - FieldInfo[] publicFields = instanceType.GetFields(BindingFlags.Public | BindingFlags.Instance); - for (int i = 0; i < publicFields.Length; i++) + FieldInfo[] allFields = instanceType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + for (int i = 0; i < allFields.Length; i++) { - EzrSharpCompatibilityField field = new(publicFields[i], Instance, Context, StartPosition, EndPosition); - if (field.Validate(result)) - return; + FieldInfo field = allFields[i]; + if (!field.IsPublic && field.GetCustomAttribute() is null) + continue; + + EzrSharpCompatibilityField fieldObject = new(field, Instance, Context, StartPosition, EndPosition, skipValidation: true); + if (!fieldObject.Validate()) + continue; - Context.Set(null, field.SharpMemberName, ReferencePool.Get(field, AccessMod.Constant)); + Context.Set(null, fieldObject.SharpMemberName, ReferencePool.Get(fieldObject, AccessMod.Constant)); } } diff --git a/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityType.cs b/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityType.cs index 6c4e197..1323c39 100644 --- a/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityType.cs +++ b/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityType.cs @@ -74,7 +74,11 @@ public EzrSharpCompatibilityType( if (method.IsAbstract || (!method.IsPublic && method.GetCustomAttribute() is null)) continue; - string methodObjectName = Utils.PascalToSnakeCase(method.Name); + EzrSharpCompatibilityFunction methodObject = new(method, null, Context, StartPosition, EndPosition, skipValidation: true); + if (!methodObject.Validate()) + continue; + + string methodObjectName = methodObject.SharpMemberName; if (duplicateNames.TryGetValue(method.Name, out int duplicates)) { methodObjectName += $"_{duplicates}"; @@ -83,10 +87,6 @@ public EzrSharpCompatibilityType( else duplicateNames.Add(method.Name, 1); - EzrSharpCompatibilityFunction methodObject = new(method, null, Context, StartPosition, EndPosition); - if (!methodObject.Validate(result)) - return; - Context.Set(null, methodObjectName, ReferencePool.Get(methodObject, AccessMod.Constant)); } @@ -97,9 +97,9 @@ public EzrSharpCompatibilityType( if (property.GetMethod?.IsPublic != true && property.SetMethod?.IsPublic != true && property.GetCustomAttribute() is null) continue; - EzrSharpCompatibilityProperty propertyObject = new(property, null, Context, StartPosition, EndPosition); - if (!propertyObject.Validate(result)) - return; + EzrSharpCompatibilityProperty propertyObject = new(property, null, Context, StartPosition, EndPosition, skipValidation: true); + if (!propertyObject.Validate()) + continue; Context.Set(null, propertyObject.SharpMemberName, ReferencePool.Get(propertyObject, AccessMod.Constant)); } @@ -111,9 +111,9 @@ public EzrSharpCompatibilityType( if (!field.IsPublic && field.GetCustomAttribute() is null) continue; - EzrSharpCompatibilityField fieldObject = new(field, null, Context, StartPosition, EndPosition); - if (!fieldObject.Validate(result)) - return; + EzrSharpCompatibilityField fieldObject = new(field, null, Context, StartPosition, EndPosition, skipValidation: true); + if (!fieldObject.Validate()) + continue; Context.Set(null, fieldObject.SharpMemberName, ReferencePool.Get(fieldObject, AccessMod.Constant)); } @@ -122,12 +122,12 @@ public EzrSharpCompatibilityType( for (int i = 0; i < publicConstructors.Length; i++) { ConstructorInfo constructor = publicConstructors[i]; - if (!constructor.IsPublic) + if (!constructor.IsPublic && constructor.GetCustomAttribute() is null) continue; - EzrSharpCompatibilityConstructor constructorObject = new(this, constructor, Context, StartPosition, EndPosition); - if (constructorObject.Validate(result)) - return; + EzrSharpCompatibilityConstructor constructorObject = new(this, constructor, Context, StartPosition, EndPosition, skipValidation: true); + if (!constructorObject.Validate()) + continue; Context.Set(null, $"make_{i}", ReferencePool.Get(constructorObject, AccessMod.Constant)); } diff --git a/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityWrapper.cs b/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityWrapper.cs index 7ed8db3..5a46ba6 100644 --- a/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityWrapper.cs +++ b/src/Runtime/Types/CSharpWrappers/CompatWrappers/EzrSharpCompatibilityWrapper.cs @@ -7,6 +7,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Text; using System.Threading.Tasks; namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers; @@ -48,25 +49,42 @@ public EzrSharpCompatibilityWrapper(MemberInfo wrappedMember, Context parentCont { SharpMember = wrappedMember; AutoWrapperAttribute = wrappedMember.GetCustomAttribute(); - SharpMemberName = !string.IsNullOrEmpty(AutoWrapperAttribute?.Name) ? AutoWrapperAttribute.Name : Utils.PascalToSnakeCase(wrappedMember.Name); + SharpMemberName = !string.IsNullOrEmpty(AutoWrapperAttribute?.Name) ? AutoWrapperAttribute.Name : PascalToSnakeCase(wrappedMember.Name); } /// /// Validates the the current object for wrapping. /// - /// Optional runtime result for carrying runtime errors. /// if the member can be wrapped, otherwise. - public bool Validate(RuntimeResult? result=null) + public bool Validate() { Exception? validationException = SharpAutoWrapperAttribute.Validate(SharpMember); if (validationException is null) return true; - if (AutoWrapperAttribute is not null) - throw validationException; + return AutoWrapperAttribute is not null ? throw validationException : false; + } + + /// + /// Converts a string from PascalCase to snake_case. + /// + /// The text to convert in PascalCase. + /// The converted text in snake_case. + internal protected static string PascalToSnakeCase(string text) + { + StringBuilder result = new(); + result.Append(char.ToLowerInvariant(text[0])); + + for (int i = 1; i < text.Length; ++i) + { + char c = text[i]; + if (char.IsUpper(c)) + result.Append('_').Append(char.ToLowerInvariant(c)); + else + result.Append(c); + } - result?.Failure(new EzrUnsupportedWrappingError($"C# type member \"{SharpMemberName}\" cannot be wrapped into an ezr² type!", Context, StartPosition, EndPosition)); - return false; + return result.ToString(); } /// diff --git a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityConstructor.cs b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityConstructor.cs index 8b64938..29beb55 100644 --- a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityConstructor.cs +++ b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityConstructor.cs @@ -14,7 +14,7 @@ namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.E /// The starting position of the object. /// The ending position of the object. /// Skip method signature validation? -public class EzrSharpCompatibilityConstructor(EzrSharpCompatibilityType constructingTypeWrapper, ConstructorInfo sharpConstructor, Context parentContext, Position startPosition, Position endPosition, bool skipValidation=false) : EzrSharpCompatibilityExecutable(sharpConstructor, null, parentContext, startPosition, endPosition, skipValidation) +public class EzrSharpCompatibilityConstructor(EzrSharpCompatibilityType constructingTypeWrapper, ConstructorInfo sharpConstructor, Context parentContext, Position startPosition, Position endPosition, bool skipValidation = false) : EzrSharpCompatibilityExecutable(sharpConstructor, null, parentContext, startPosition, endPosition, skipValidation) { /// /// The wrapper for this C# constructor's class. @@ -40,7 +40,7 @@ public override void Execute(Reference[] arguments, Interpreter interpreter, Run result.Success(NewNothingConstant()); else { - IEzrObject wrapper = new EzrSharpCompatibilityObjectInstance(output, ConstructingTypeWrapper.SharpType, result, _executionContext, StartPosition, EndPosition); + IEzrObject wrapper = new EzrSharpCompatibilityObjectInstance(output, ConstructingTypeWrapper.SharpType, _executionContext, StartPosition, EndPosition); if (result.ShouldReturn) return; diff --git a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityExecutable.cs b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityExecutable.cs index c1de8a2..fe20943 100644 --- a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityExecutable.cs +++ b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityExecutable.cs @@ -53,7 +53,13 @@ public EzrSharpCompatibilityExecutable(MethodBase sharpMember, object? instance, Executable = sharpMember; Parameters = Executable.GetParameters(); - ParameterNames = Array.ConvertAll(Parameters, p => Utils.PascalToSnakeCase(p.Name ?? string.Empty)); + + ParameterNames = Array.ConvertAll(Parameters, p => + { + string? definedName = p.GetCustomAttribute()?.Name; + return string.IsNullOrEmpty(definedName) ? PascalToSnakeCase(p.Name ?? string.Empty) : definedName; + }); + Instance = instance; if (!skipValidation) diff --git a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityFunction.cs b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityFunction.cs index b8acd3e..bd87ef8 100644 --- a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityFunction.cs +++ b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/Executables/EzrSharpCompatibilityFunction.cs @@ -14,7 +14,7 @@ namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.E /// The starting position of the object. /// The ending position of the object. /// Skip method signature validation? -public class EzrSharpCompatibilityFunction(MethodInfo sharpFunction, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation=false) : EzrSharpCompatibilityExecutable(sharpFunction, instance, parentContext, startPosition, endPosition, skipValidation) +public class EzrSharpCompatibilityFunction(MethodInfo sharpFunction, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation = false) : EzrSharpCompatibilityExecutable(sharpFunction, instance, parentContext, startPosition, endPosition, skipValidation) { /// public override string TypeName { get; protected internal set; } = "csharp function"; diff --git a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/EzrSharpCompatibilityField.cs b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/EzrSharpCompatibilityField.cs index b373093..70d1a64 100644 --- a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/EzrSharpCompatibilityField.cs +++ b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/EzrSharpCompatibilityField.cs @@ -1,5 +1,4 @@ using EzrSquared.Runtime.Types.Core.Errors; -using EzrSquared.Runtime.WrapperAttributes; using EzrSquared.Util; using System; using System.Reflection; @@ -36,7 +35,7 @@ public class EzrSharpCompatibilityField : EzrSharpCompatibilityWrapper /// The starting position of the object. /// The ending position of the object. /// Skip field type validation? - public EzrSharpCompatibilityField(FieldInfo sharpField, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation=false) : base(sharpField, parentContext, startPosition, endPosition) + public EzrSharpCompatibilityField(FieldInfo sharpField, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation = false) : base(sharpField, parentContext, startPosition, endPosition) { SharpField = sharpField; Instance = instance; @@ -85,7 +84,7 @@ public override void Execute(Reference[] arguments, Interpreter interpreter, Run result.Failure(new EzrIllegalOperationError($"Cannot get value from CSharp field wrapper \"{SharpMemberName}\" as it is write-only!", Context, StartPosition, EndPosition)); break; } - + object? value = SharpField.GetValue(Instance); CSharpToEzrObject(value, result); break; diff --git a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/EzrSharpCompatibilityProperty.cs b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/EzrSharpCompatibilityProperty.cs index f4eebfe..3e2e3b0 100644 --- a/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/EzrSharpCompatibilityProperty.cs +++ b/src/Runtime/Types/CSharpWrappers/CompatWrappers/ObjectMembers/EzrSharpCompatibilityProperty.cs @@ -1,5 +1,4 @@ using EzrSquared.Runtime.Types.Core.Errors; -using EzrSquared.Runtime.WrapperAttributes; using EzrSquared.Util; using System; using System.Reflection; @@ -36,7 +35,7 @@ public class EzrSharpCompatibilityProperty : EzrSharpCompatibilityWrapper /// The starting position of the object. /// The ending position of the object. /// Skip property type validation? - public EzrSharpCompatibilityProperty(PropertyInfo sharpProperty, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation=false) : base(sharpProperty, parentContext, startPosition, endPosition) + public EzrSharpCompatibilityProperty(PropertyInfo sharpProperty, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation = false) : base(sharpProperty, parentContext, startPosition, endPosition) { SharpProperty = sharpProperty; Instance = instance; diff --git a/src/Runtime/Types/Collections/EzrDictionary.cs b/src/Runtime/Types/Collections/EzrDictionary.cs index 44b1fb0..f9a1e0a 100644 --- a/src/Runtime/Types/Collections/EzrDictionary.cs +++ b/src/Runtime/Types/Collections/EzrDictionary.cs @@ -64,7 +64,7 @@ public EzrDictionary(RuntimeEzrObjectDictionary value, Context parentContext, Po private void DictionaryExists(SharpMethodParameters arguments) { Reference reference = arguments.ArgumentReferences["key"]; - + bool hasKey = Value.HasKey(reference.Object, arguments.Result); if (arguments.Result.ShouldReturn) return; diff --git a/src/Runtime/Types/Collections/EzrList.cs b/src/Runtime/Types/Collections/EzrList.cs index 3ebfd6d..2389e3e 100644 --- a/src/Runtime/Types/Collections/EzrList.cs +++ b/src/Runtime/Types/Collections/EzrList.cs @@ -28,7 +28,7 @@ public class EzrList : EzrObject, IEzrMutableObject, IEzrIndexedCollection public readonly RuntimeEzrObjectList Value; /// - [SharpAutoWrapper(IsReadOnly = true)] + [SharpAutoWrapper(isReadOnly: true)] public int Length => Value.Count; /// The base value. diff --git a/src/Runtime/Types/Core/Text/EzrCharacterList.cs b/src/Runtime/Types/Core/Text/EzrCharacterList.cs index 30d6b30..15d1d38 100644 --- a/src/Runtime/Types/Core/Text/EzrCharacterList.cs +++ b/src/Runtime/Types/Core/Text/EzrCharacterList.cs @@ -34,7 +34,7 @@ public class EzrCharacterList : EzrObject, IEzrMutableObject, IEzrString, IEzrIn public string StringValue => Value.ToString(); /// - [SharpAutoWrapper(IsReadOnly = true)] + [SharpAutoWrapper(isReadOnly: true)] public int Length => Value.Length; /// diff --git a/src/Runtime/WrapperAttributes/SharpAutoWrapperAttribute.cs b/src/Runtime/WrapperAttributes/SharpAutoWrapperAttribute.cs index 5634dae..0a25407 100644 --- a/src/Runtime/WrapperAttributes/SharpAutoWrapperAttribute.cs +++ b/src/Runtime/WrapperAttributes/SharpAutoWrapperAttribute.cs @@ -5,25 +5,51 @@ namespace EzrSquared.Runtime.WrapperAttributes; /// -/// Attribute for C# type members which to be automatically wrapped from primitive C# types into ezr² types. +/// Attribute for C# type members which to be automatically wrapped from C# types into ezr² types. /// -[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] public class SharpAutoWrapperAttribute : Attribute { /// /// The ezr² name for the member. /// - public string Name = string.Empty; + public readonly string Name = string.Empty; /// /// Is the member read-only? Only for properties and fields. /// - public bool IsReadOnly; + public readonly bool IsReadOnly; /// /// Is the member write-only? Only for properties and fields. /// - public bool IsWriteOnly; + public readonly bool IsWriteOnly; + + /// + /// Creates a new . + /// + /// Is the member read-only? Only for properties and fields. + /// Is the member write-only? Only for properties and fields. + /// Thrown if both and are set to . + public SharpAutoWrapperAttribute(bool isReadOnly = false, bool isWriteOnly = false) + { + IsReadOnly = isReadOnly; + IsWriteOnly = isWriteOnly; + + if (IsWriteOnly && IsReadOnly) + throw new ArgumentException("You can't make a property or field both read-only and write-only."); + } + + /// + /// Creates a new . + /// + /// The ezr² name for the member. + /// Is the member read-only? Only for properties and fields. + /// Is the member write-only? Only for properties and fields. + public SharpAutoWrapperAttribute(string name, bool isReadOnly = false, bool isWriteOnly = false) : this(isReadOnly, isWriteOnly) + { + Name = name; + } /// /// Checks if the given member is supported for wrapping. diff --git a/src/Util/Utils.cs b/src/Util/Utils.cs index e070d2d..8632e01 100644 --- a/src/Util/Utils.cs +++ b/src/Util/Utils.cs @@ -98,26 +98,4 @@ public static (int AdjustedLineNumber, string SourceWithUnderline) SourceWithUnd return (line, result.ToString()); } - - /// - /// Converts a string from PascalCase to snake_case. - /// - /// The text to convert in PascalCase. - /// The converted text in snake_case. - public static string PascalToSnakeCase(string text) - { - StringBuilder result = new(); - result.Append(char.ToLowerInvariant(text[0])); - - for (int i = 1; i < text.Length; ++i) - { - char c = text[i]; - if (char.IsUpper(c)) - result.Append('_').Append(char.ToLowerInvariant(c)); - else - result.Append(c); - } - - return result.ToString(); - } }