draconware-dev / SpanExtensions.Net

SpanExtensions.Net aims to make ReadOnlySpan<T> and Span<T> more accessible and overall better integrated into the .Net Ecosystem, by providing alternatives for many missing Extension Methods for Span<T>, ranging from string.Split() over Enumerable.Skip() and Enumerable.Take() to an improved ReadOnlySpan<T>.IndexOf().
MIT License
17 stars 5 forks source link

Source Generator #18

Open Guiorgy opened 4 months ago

Guiorgy commented 4 months ago

Goals:

Imlementation:

Guiorgy commented 4 months ago

Before I continue, can you comment on the naming and project structure? If everything looks file, I'll continue.

PS. It shouldn't take long to get a working generator, there's just a few things missing. Edit: It should be basically done. Just need to fix documentation comments, for some reason new lines are added between them...

dragon7307 commented 4 months ago

Ok, I'll look at it, as soon as I am done with my review of the Tests..

As a side note: Can't the tuples be fixed by just accepting a struct that has two fields and can implicitly be converted to and from a tuple????

Guiorgy commented 4 months ago

Here's a quote from docs:

The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:

  • One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
  • The type object.
  • The type System.Type.
  • An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility.
  • Single-dimensional arrays of the above types.

So, while an attribute can accept anything as a base object, this would handwave any type safety and correctness, and even if you accept that, don't forget that we are using the attribute in a source generator, not in reflection, in other words, what we get is the source code inside the attribute brackets, not the actual objects passed, so parsing that would be... painful...

Edit: Also, when I said basically done I meant the generator itself, I still need to migrate everything to be using the generator, though, I also want to test it in different conditions just in case, so if you want you can play around with it and tell me if you find any problems ;)

Edit2: Span<T> doesn't seem to have .Trim() in .NET 5, and no .IsWhiteSpace() at all? Well, we can add internal extensions to cast Span into ReadOnlySpan and call the builtin extensions I guess. Added

Edit3: A problem I run into while testing is that if we decorate a partial class that is spread into several files, having an attribute with AllowMultiple = false means that only one of those files can be copied. And if we do AllowMultiple = true, the generator assumes that the same class (in the same file) won't be decorated by that attribute several types, not sure what exactly will happen, but pretty sure something will fail. Either way, I doubt someone will decorate the same class with the same attribute several times, but I'd recommend mentioning that in the wiki for future contributors.

Edit4: on my source-generators-pr11-tests testing branch I managed to build and run tests for both Span and ReadOnlySpan with only sources for Span in the projects. The regex patterns used:

Edit5: I'm also considering adding a small generator to generate ToSystemEnumerableExtensions for every split enumerable, since that's just a bunch of boilercode, but honestly, might be simpler to just keep things as are?

Edit6: I think it would be easier to wait for the other 2 PRs to be properly merged before merging this, that way I could modify all 3 projects to use this generator. If you'd like, you could add me as a collaborator temporarily, and I could deal with the merge conflicts and merge the 3 PRs?