New issue
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
Introduce new assertions on ParameterInfo #2385
base: develop
Are you sure you want to change the base?
Conversation
Qodana for .NET9 new problems were found
💡 Qodana analysis was run in the pull request mode: only the changed files were checked View the detailed Qodana reportTo be able to view the detailed Qodana report, you can either:
To get - name: 'Qodana Scan'
uses: JetBrains/qodana-action@v2023.2.8
with:
upload-result: true Contact Qodana teamContact us at qodana-support@jetbrains.com
|
1e86698
to
c9f6d16
Compare
Pull Request Test Coverage Report for Build 6676121464
💛 - Coveralls |
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.
🤔 We now miss a Parameters()
extension method like we have in our Reflection API
/// Contains a number of methods to assert that a <see cref="ICustomAttributeProvider"/> is in the expected state. | ||
/// </summary> | ||
[DebuggerNonUserCode] | ||
public abstract class CustomAttributeProviderAssertions<TSubject, TAssertions> : ReferenceTypeAssertions<TSubject, TAssertions> |
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.
🤔 Given that this type may contain other assertions that are reusable across the reflection assertions, I think we should name this something like ReflectionAssertions
🌱 I hope using inheritance isn't going to cause issues later on.
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.
Currently our inheritance hierarchy of type-related assertions follows the inheritance hierarchy of the corresponding BCL types.
I notice that e.g. Assembly
also implements ICustomAttributeProvider
.
How difficult would it be to implement this feature without changing our inheritance hierarchy?
It's not show stopper for me, it just feels a little odd to me to mix these concepts.
|
||
public class ParameterInfoAssertionSpecs | ||
{ | ||
public class BeDecortatedWithOfT |
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.
⛏️ Typo
public class BeDecortatedWithOfT | ||
{ | ||
[Fact] | ||
public void When_asserting_a_parameter_is_decorated_with_attribute_and_it_is_it_succeeds() |
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.
🔧 We have been adopting a more fact-based naming convention for new tests, e.g. A_parameter_that_is_decorated_with_the_expected_attribute_is_valid
or Succeeds_for_a_parameter_with_the_expected_attribute
. For example, It's completely clear from the parent class that every test is about checking whether a parameter is decorated with an attribute, so you can leave that out. Same for the other tests.
} | ||
|
||
[Fact] | ||
public void When_subject_is_null_be_decorated_withOfT_should_fail() |
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.
🔧 Stay away from technical terms like OfT
} | ||
} | ||
|
||
#region Internal classes used in unit tests |
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.
🔧 We prefer not to use regions anymore.
/// <param name="becauseArgs"> | ||
/// Zero or more objects to format using the placeholders in <paramref name="because" />. | ||
/// </param> | ||
public AndWhichConstraint<CustomAttributeProviderAssertions<TSubject, TAssertions>, TAttribute> BeDecoratedWith<TAttribute>( |
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.
This should return AndWhichConstraint<TAssertions, TAttribute>
such that one continue chaining with methods defined on a derived type.
/// Contains a number of methods to assert that a <see cref="ICustomAttributeProvider"/> is in the expected state. | ||
/// </summary> | ||
[DebuggerNonUserCode] | ||
public abstract class CustomAttributeProviderAssertions<TSubject, TAssertions> : ReferenceTypeAssertions<TSubject, TAssertions> |
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.
Currently our inheritance hierarchy of type-related assertions follows the inheritance hierarchy of the corresponding BCL types.
I notice that e.g. Assembly
also implements ICustomAttributeProvider
.
How difficult would it be to implement this feature without changing our inheritance hierarchy?
It's not show stopper for me, it just feels a little odd to me to mix these concepts.
// Do not use MemberInfo.IsDefined | ||
// There is an issue with PropertyInfo and EventInfo preventing the inherit option to work. | ||
// https://github.com/dotnet/runtime/issues/30219 | ||
return Attribute.IsDefined(type, typeof(TAttribute), inherit: false); | ||
return type.IsDefined(typeof(TAttribute), inherit: false); |
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.
It seems this will be calling the MemberInfo.IsDefined
that the comment said not to use.
I dug into this and the related PRs are #748 and #1095.
I checked out develop at #748 and used the prohibited method.
I don't have net45 or netcoreapp1.2 installed, but for the remaining TFMs no tests failed.
Since we no longer support these TFMs directly or indirectly, I think it's safe to use the ICustomAttributeProvider.IsDefined
.
I won't be able to address all the feedback in the coming weeks so please don't hesitate to adapt everything that needs to be adapted if have the time to. Also, note that all the specs were mostly copy/pasted from |
Wow, I did not realize that this pull request was opening Pandora's box! 😅 Indeed a new And yes, I'm currently reading Multiple Inheritance in C# on Stack Overflow to see if I can come up with an elegant solution that does not involve changing the inheritance hierarchy. In the end, that's quite some work ahead for something that was supposed to just be some support for #2380. 😂 |
3a11e43
to
17d9331
Compare
Sorry about that. This tends to happen with an open-source library that has close to 300 million downloads ;-).
You could still decouple #2380 from this one. |
4c33b31
to
632a02a
Compare
Think about coverage and qodana scan, if you can :) |
@0xced did you give up on this? |
632a02a
to
1dbfb54
Compare
I did not give up on this but since that was just a side effect of #2380 and not something I actually need I did not gave it a high priority. |
Qodana for .NET10 new problems were found
💡 Qodana analysis was run in the pull request mode: only the changed files were checked Contact Qodana teamContact us at qodana-support@jetbrains.com
|
All the (Not)BeDecoratedWith(OrInherit) methods are now available on all types that support attributes, i.e. `Assembly`, `MemberInfo`, `ParameterInfo` and `Type`.
TODO: ThatAre... (IsLcid, IsOptional, etc.)
1dbfb54
to
2c0c67e
Compare
All the (Not)BeDecoratedWith methods were implemented for
MemberInfo
but implementing them forICustomAttributeProvider
instead allows for a freeParameterInfoAssertions
implementation.IMPORTANT
./build.sh --target spellcheck
or.\build.ps1 --target spellcheck
before pushing and check the good outcome