| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,8 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Diagnostics; | ||
| using System.Linq; | ||
| using System.Reflection; | ||
| using System.Runtime.InteropServices; | ||
| using System.Runtime.Serialization; | ||
|
|
||
| Expand Down Expand Up | @@ -79,41 +82,80 @@ public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, | |
| BorrowedReference bases = Runtime.PyTuple_GetItem(args, 1); | ||
| BorrowedReference dict = Runtime.PyTuple_GetItem(args, 2); | ||
|
|
||
| // We do not support multiple inheritance, so the bases argument | ||
| // should be a 1-item tuple containing the type we are subtyping. | ||
| // That type must itself have a managed implementation. We check | ||
| // that by making sure its metatype is the CLR metatype. | ||
| // Extract interface types and base class types. | ||
| var interfaces = new List<Type>(); | ||
|
|
||
| if (Runtime.PyTuple_Size(bases) != 1) | ||
| { | ||
| return Exceptions.RaiseTypeError("cannot use multiple inheritance with managed classes"); | ||
| } | ||
| // More than one base type case be declared, but an exception will be thrown | ||
| // if more than one is a class/not an interface. | ||
| var baseTypes = new List<ClassBase>(); | ||
|
|
||
| BorrowedReference base_type = Runtime.PyTuple_GetItem(bases, 0); | ||
| BorrowedReference mt = Runtime.PyObject_TYPE(base_type); | ||
|
|
||
| if (!(mt == PyCLRMetaType || mt == Runtime.PyTypeType)) | ||
| var baseClassCount = Runtime.PyTuple_Size(bases); | ||
| if (baseClassCount == 0) | ||
| { | ||
| return Exceptions.RaiseTypeError("invalid metatype"); | ||
| return Exceptions.RaiseTypeError("zero base classes "); | ||
| } | ||
|
|
||
| // Ensure that the reflected type is appropriate for subclassing, | ||
| // disallowing subclassing of delegates, enums and array types. | ||
|
|
||
| if (GetManagedObject(base_type) is ClassBase cb) | ||
| for (nint i = 0; i < baseClassCount; i++) | ||
| { | ||
| try | ||
| var baseTypeIt = Runtime.PyTuple_GetItem(bases, (int)i); | ||
|
|
||
| if (GetManagedObject(baseTypeIt) is ClassBase classBaseIt) | ||
| { | ||
| if (!cb.CanSubclass()) | ||
| if (!classBaseIt.type.Valid) | ||
| { | ||
| return Exceptions.RaiseTypeError("Invalid type used as a super type."); | ||
| } | ||
| if (classBaseIt.type.Value.IsInterface) | ||
| { | ||
| return Exceptions.RaiseTypeError("delegates, enums and array types cannot be subclassed"); | ||
| interfaces.Add(classBaseIt.type.Value); | ||
| } | ||
| else | ||
| { | ||
| baseTypes.Add(classBaseIt); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| return Exceptions.RaiseTypeError("Non .NET type used as super class for meta type. This is not supported."); | ||
| } | ||
|
Comment thread
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityWhat if it is not a .NET class or interface? You can't simply ignore it.
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityAdded exceptions here in the latest version.
Sorry, something went wrong.
All reactions
|
||
| catch (SerializationException) | ||
| } | ||
| // if the base type count is 0, there might still be interfaces to implement. | ||
| if (baseTypes.Count == 0) | ||
| { | ||
| baseTypes.Add(new ClassBase(typeof(object))); | ||
| } | ||
|
|
||
| // Multiple inheritance is not supported, unless the other types are interfaces | ||
| if (baseTypes.Count > 1) | ||
| { | ||
| var types = string.Join(", ", baseTypes.Select(baseType => baseType.type.Value)); | ||
| return Exceptions.RaiseTypeError($"Multiple inheritance with managed classes cannot be used. Types: {types} "); | ||
| } | ||
|
|
||
| // check if the list of interfaces contains no duplicates. | ||
| if (interfaces.Distinct().Count() != interfaces.Count) | ||
| { | ||
| // generate a string containing the problematic types. | ||
| var duplicateTypes = interfaces.GroupBy(type => type) | ||
| .Where(typeGroup => typeGroup.Count() > 1) | ||
| .Select(typeGroup => typeGroup.Key); | ||
| var duplicateTypesString = string.Join(", ", duplicateTypes); | ||
|
|
||
| return Exceptions.RaiseTypeError($"An interface can only be implemented once. Duplicate types: {duplicateTypesString}"); | ||
| } | ||
|
|
||
| var cb = baseTypes[0]; | ||
| try | ||
| { | ||
| if (!cb.CanSubclass()) | ||
| { | ||
| return Exceptions.RaiseTypeError($"Underlying C# Base class {cb.type} has been deleted"); | ||
| return Exceptions.RaiseTypeError("delegates, enums and array types cannot be subclassed"); | ||
| } | ||
| } | ||
| catch (SerializationException) | ||
| { | ||
| return Exceptions.RaiseTypeError($"Underlying C# Base class {cb.type} has been deleted"); | ||
| } | ||
|
|
||
| BorrowedReference slots = Runtime.PyDict_GetItem(dict, PyIdentifier.__slots__); | ||
| if (slots != null) | ||
| Expand All | @@ -130,10 +172,12 @@ public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, | |
| using var clsDict = new PyDict(dict); | ||
| if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__")) | ||
| { | ||
| return TypeManager.CreateSubType(name, base_type, clsDict); | ||
| return TypeManager.CreateSubType(name, baseTypes[0], interfaces, clsDict); | ||
| } | ||
| } | ||
|
|
||
| var base_type = Runtime.PyTuple_GetItem(bases, 0); | ||
|
Comment thread
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Qualitybases here can be empty since you removed check above.
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityHow can bases be length 0? This should only be called when a C# type is subclassed, right? In this case, it should at least be length 1.
Sorry, something went wrong.
All reactions
|
||
|
|
||
| // otherwise just create a basic type without reflecting back into the managed side. | ||
| IntPtr func = Util.ReadIntPtr(Runtime.PyTypeType, TypeOffset.tp_new); | ||
| NewReference type = NativeCall.Call_3(func, tp, args, kw); | ||
| Expand Down | ||
| Back | FazBrowse Home | New Git URL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityIMHO, repeating the same base interface multiple times should be an error.
And it might be, add a test.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityTest added.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.