-
Notifications
You must be signed in to change notification settings - Fork 215
Add a suppressor for CS8618 #11601
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
Add a suppressor for CS8618 #11601
Conversation
...oft.CodeAnalysis.Razor.Compiler/src/Analyzers/ComponentParameterNullableWarningSuppressor.cs
Outdated
Show resolved
Hide resolved
src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Analyzers/AnalyzerResources.resx
Outdated
Show resolved
Hide resolved
...oft.CodeAnalysis.Razor.Compiler/src/Analyzers/ComponentParameterNullableWarningSuppressor.cs
Outdated
Show resolved
Hide resolved
...oft.CodeAnalysis.Razor.Compiler/src/Analyzers/ComponentParameterNullableWarningSuppressor.cs
Outdated
Show resolved
Hide resolved
...oft.CodeAnalysis.Razor.Compiler/src/Analyzers/ComponentParameterNullableWarningSuppressor.cs
Outdated
Show resolved
Hide resolved
- Use symbols rather than syntax - Only report if both parameter and editor required are on the property - Thread through the cancellation token
Ok, updated to use symbols. Will work on adding some tests if we're happy with this approach. |
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.
Think this is in a good enough place to go for the tests.
@@ -1,4 +1,4 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<Project Sdk="Microsoft.NET.Sdk"> |
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.
BOM?
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.
Looks like it was missing the BOM and this adds it back.
if (attributes.Any(ad => SymbolEqualityComparer.Default.Equals(ad.AttributeClass, parameterSymbol)) | ||
&& attributes.Any(ad => SymbolEqualityComparer.Default.Equals(ad.AttributeClass, editorRequiredSymbol))) |
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.
Nit: cute syntax, but potentially loops through the list twice. Maybe a foreach
would be better 🙂.
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.
- remove XunitVerifiers and use default verifier instead (see https://github.com/dotnet/roslyn-sdk/blob/main/src/Microsoft.CodeAnalysis.Testing/README.md#obsolete-packages) - Remove uneeded .xunit package references
using System; | ||
using Microsoft.AspNetCore.Components; | ||
public class MyComponent |
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 test makes me wonder. Should we be checking that these attributes are being used in something that implements IComponent
?
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.
I don't think that's required, consider this example:
abstract class B
{
[Parameter, EditorRequired] string Param { get; set; }
}
class C : B, IComponent;
B
doesn't implement IComponent
but can still be instantiated as a component through C
.
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.
IMO, for this type of edge case, I'd prefer to have false positives, rather than false negatives (iow, I think we should check for implementing IComponent
). If we get feedback that this case is still being hit and causing pain, then we can take another look at it.
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.
Yeah, lets keep it tightly scoped for now, and we can expand it later if we get feedback on it
...oft.NET.Sdk.Razor.SourceGenerators.Tests/ComponentParameterNullableWarningSuppressorTests.cs
Show resolved
Hide resolved
...oft.NET.Sdk.Razor.SourceGenerators.Tests/ComponentParameterNullableWarningSuppressorTests.cs
Outdated
Show resolved
Hide resolved
using System; | ||
using Microsoft.AspNetCore.Components; | ||
public class MyComponent |
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.
I don't think that's required, consider this example:
abstract class B
{
[Parameter, EditorRequired] string Param { get; set; }
}
class C : B, IComponent;
B
doesn't implement IComponent
but can still be instantiated as a component through C
.
...oft.CodeAnalysis.Razor.Compiler/src/Analyzers/ComponentParameterNullableWarningSuppressor.cs
Outdated
Show resolved
Hide resolved
|
||
public override void ReportSuppressions(SuppressionAnalysisContext context) | ||
{ | ||
var editorRequiredSymbol = context.Compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.EditorRequiredAttribute"); |
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.
Couple Qs:
- Should we bail out of the analyzer here if the value is
null
? - This will fail in the face of multiple definitions of this type. Not against that but want to make sure we clearly decided this.
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.
Added an early return if we can't find the types, and a test to show behavior in the presence of duplicate attributes.
public override void ReportSuppressions(SuppressionAnalysisContext context) | ||
{ | ||
var editorRequiredSymbol = context.Compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.EditorRequiredAttribute"); | ||
var parameterSymbol = context.Compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.ParameterAttribute"); |
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.
Should we bail out if this is null
?
Ensure the parameter is well defined
...oft.NET.Sdk.Razor.SourceGenerators.Tests/ComponentParameterNullableWarningSuppressorTests.cs
Outdated
Show resolved
Hide resolved
...oft.NET.Sdk.Razor.SourceGenerators.Tests/ComponentParameterNullableWarningSuppressorTests.cs
Outdated
Show resolved
Hide resolved
...oft.NET.Sdk.Razor.SourceGenerators.Tests/ComponentParameterNullableWarningSuppressorTests.cs
Outdated
Show resolved
Hide resolved
...oft.NET.Sdk.Razor.SourceGenerators.Tests/ComponentParameterNullableWarningSuppressorTests.cs
Outdated
Show resolved
Hide resolved
public class MyComponent : ComponentBase | ||
{ | ||
[Parameter, EditorRequired] | ||
public string MyParameter { get; set; } |
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.
Consider also testing string?
.
} | ||
|
||
[Theory] | ||
[InlineData("init;")] |
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 looks like the runtime supports init
parameters just fine, so perhaps we should suppress the warning for them as well?
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.
So it turns out this already supported init
properties, this test just wasn't explicitly checking IsSuppressed(false)
so it was incorrectly passing. I've added an explicit suppress check for all the instances where it should be false
and split init
out into its own passing test.
...oft.NET.Sdk.Razor.SourceGenerators.Tests/ComponentParameterNullableWarningSuppressorTests.cs
Show resolved
Hide resolved
} | ||
|
||
// containing type implements IComponent | ||
if (!symbol.ContainingType.AllInterfaces.Any(@interface => @interface.Equals(componentSymbol, SymbolEqualityComparer.Default))) |
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.
nit: not sure if we have an overload like this available
if (!symbol.ContainingType.AllInterfaces.Any(@interface => @interface.Equals(componentSymbol, SymbolEqualityComparer.Default))) | |
if (!symbol.ContainingType.AllInterfaces.Any(static (@interface, componentSymbol) => @interface.Equals(componentSymbol, SymbolEqualityComparer.Default), componentSymbol)) |
...oft.CodeAnalysis.Razor.Compiler/src/Analyzers/ComponentParameterNullableWarningSuppressor.cs
Outdated
Show resolved
Hide resolved
…rs/ComponentParameterNullableWarningSuppressor.cs Co-authored-by: Fred Silberberg <[email protected]>
@chsienki If the component has a constructor, CS8618 puts the warning on the constructor rather than on the property. It seems this suppressor does not work as it should when components have a constructor defined. Also, I would still love to see this suppressor for |
Adds a suppressor for CS8618 when a component property has
EditorRequired
attached to it.