-
Notifications
You must be signed in to change notification settings - Fork 230
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
458feb1
commit 9f6edc4
Showing
36 changed files
with
683 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
analyzers/its/expected/BlazorSample/BlazorSample--net7.0-S6797.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"issues": [ | ||
{ | ||
"id": "S6797", | ||
"message": "Query parameter type 'TimeSpan' is not supported.", | ||
"location": { | ||
"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/BlazorSample/BlazorSample/Pages/S6797/S6797.CsharpOnly.cs#L11", | ||
"region": { | ||
"startLine": 11, | ||
"startColumn": 16, | ||
"endLine": 11, | ||
"endColumn": 24 | ||
} | ||
} | ||
} | ||
] | ||
} |
17 changes: 17 additions & 0 deletions
17
analyzers/its/expected/BlazorSample/BlazorSample--net7.0-S6803.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"issues": [ | ||
{ | ||
"id": "S6803", | ||
"message": "Component parameters can only receive query parameter values in routable components.", | ||
"location": { | ||
"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/BlazorSample/BlazorSample/Pages/S6797/S6797.Partial.razor.cs#L9", | ||
"region": { | ||
"startLine": 9, | ||
"startColumn": 25, | ||
"endLine": 9, | ||
"endColumn": 33 | ||
} | ||
} | ||
} | ||
] | ||
} |
16 changes: 16 additions & 0 deletions
16
analyzers/its/sources/BlazorSample/BlazorSample/Pages/S6797/S6797.CsharpOnly.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System; | ||
using Microsoft.AspNetCore.Components; | ||
|
||
namespace BlazorSample.Pages.S6797 | ||
{ | ||
[Route("/query-parameters")] | ||
public class S6797_CsharpOnly : ComponentBase | ||
{ | ||
[Parameter] | ||
[SupplyParameterFromQuery] | ||
public TimeSpan TimeSpan { get; set; } | ||
|
||
[Parameter] | ||
public TimeSpan TimeSpanParam { get; set; } | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
analyzers/its/sources/BlazorSample/BlazorSample/Pages/S6797/S6797.NoRoute.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
@code { | ||
[Parameter] | ||
[SupplyParameterFromQuery] | ||
public bool BoolParam { get; set; } | ||
|
||
[Parameter] | ||
[SupplyParameterFromQuery] | ||
public DateTime DateTimeParam { get; set; } | ||
} |
1 change: 1 addition & 0 deletions
1
analyzers/its/sources/BlazorSample/BlazorSample/Pages/S6797/S6797.Partial.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
@page "/query-parameters" |
14 changes: 14 additions & 0 deletions
14
analyzers/its/sources/BlazorSample/BlazorSample/Pages/S6797/S6797.Partial.razor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using Microsoft.AspNetCore.Components; | ||
|
||
namespace BlazorSample.Pages.S6797 | ||
{ | ||
public partial class S6797_Partial : ComponentBase | ||
{ | ||
[Parameter] | ||
[SupplyParameterFromQuery] | ||
public TimeSpan TimeSpan { get; set; } | ||
|
||
[Parameter] | ||
public TimeSpan TimeSpanParam { get; set; } | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
analyzers/its/sources/BlazorSample/BlazorSample/Pages/S6797/S6797.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
@page "/query-parameters" | ||
|
||
@code { | ||
[Parameter] | ||
[SupplyParameterFromQuery] | ||
public bool BoolParam { get; set; } | ||
|
||
[Parameter] | ||
[SupplyParameterFromQuery] | ||
public DateTime DateTimeParam { get; set; } | ||
} |
2 changes: 1 addition & 1 deletion
2
analyzers/its/sources/BlazorSample/BlazorSample/Pages/S6798/S6798.Partial.razor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<h2>Why is this an issue?</h2> | ||
<p>The <a | ||
href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.supplyparameterfromqueryattribute">SupplyParameterFromQuery</a> | ||
attribute can be used to specify that a component parameter, of a routable component, comes from the query string.</p> | ||
<p>Component parameters supplied from the query string support the following types:</p> | ||
<ul> | ||
<li> bool, DateTime, decimal, double, float, Guid, int, long, string. </li> | ||
<li> Nullable variants of the preceding types. </li> | ||
<li> Arrays of the preceding types, whether they’re nullable or not nullable. </li> | ||
</ul> | ||
<p>Query parameters should have one of the supported types. Otherwise, an unhandled exception will be raised at runtime.</p> | ||
<pre> | ||
Unhandled exception rendering component: Querystring values cannot be parsed as type '<type>'. | ||
System.NotSupportedException: Querystring values cannot be parsed as type '<type>' | ||
... | ||
</pre> | ||
<h2>How to fix it</h2> | ||
<p>Change the parameter type to one of the following ones:</p> | ||
<ul> | ||
<li> bool, DateTime, decimal, double, float, Guid, int, long, string. </li> | ||
<li> Nullable variants of the preceding types. </li> | ||
<li> Arrays of the preceding types, whether they’re nullable or not nullable. </li> | ||
</ul> | ||
<h3>Code examples</h3> | ||
<h4>Noncompliant code example</h4> | ||
<pre data-diff-id="1" data-diff-type="noncompliant"> | ||
@page "/print" | ||
<p> Parameter value is: @Value </p> | ||
@code { | ||
[Parameter] | ||
[SupplyParameterFromQuery()] | ||
public TimeSpan Value { get; set; } // Noncompliant | ||
} | ||
</pre> | ||
<h4>Compliant solution</h4> | ||
<pre data-diff-id="1" data-diff-type="compliant"> | ||
@page "/print" | ||
<p> Parameter value is: @Value </p> | ||
@code { | ||
[Parameter] | ||
[SupplyParameterFromQuery()] | ||
public long Value { get; set; } // Compliant | ||
} | ||
</pre> | ||
<h2>Resources</h2> | ||
<h3>Documentation</h3> | ||
<ul> | ||
<li> Microsoft Learn - <a | ||
href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.supplyparameterfromqueryattribute">SupplyParameterFromQueryAttribute</a> </li> | ||
</ul> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"title": "Blazor query parameter type should be supported", | ||
"type": "BUG", | ||
"status": "ready", | ||
"remediation": { | ||
"func": "Constant\/Issue", | ||
"constantCost": "5min" | ||
}, | ||
"tags": [ | ||
"blazor" | ||
], | ||
"defaultSeverity": "Major", | ||
"ruleSpecification": "RSPEC-6797", | ||
"sqKey": "S6797", | ||
"scope": "All", | ||
"quickfix": "infeasible", | ||
"code": { | ||
"impacts": { | ||
"RELIABILITY": "MEDIUM" | ||
}, | ||
"attribute": "LOGICAL" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -291,6 +291,7 @@ | |
"S6617", | ||
"S6618", | ||
"S6640", | ||
"S6797", | ||
"S6798", | ||
"S6800", | ||
"S6802", | ||
|
104 changes: 104 additions & 0 deletions
104
analyzers/src/SonarAnalyzer.CSharp/Rules/BlazorQueryParameterRoutableComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/* | ||
* SonarAnalyzer for .NET | ||
* Copyright (C) 2015-2023 SonarSource SA | ||
* mailto: contact AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
|
||
namespace SonarAnalyzer.Rules.CSharp; | ||
|
||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
public sealed class BlazorQueryParameterRoutableComponent : SonarDiagnosticAnalyzer | ||
{ | ||
private const string NoRouteQueryDiagnosticId = "S6803"; | ||
private const string NoRouteQueryMessageFormat = "Component parameters can only receive query parameter values in routable components."; | ||
|
||
private const string QueryTypeDiagnosticId = "S6797"; | ||
private const string QueryTypeMessageFormat = "Query parameter type '{0}' is not supported."; | ||
|
||
private static readonly DiagnosticDescriptor S6803Rule = DescriptorFactory.Create(NoRouteQueryDiagnosticId, NoRouteQueryMessageFormat); | ||
private static readonly DiagnosticDescriptor S6797Rule = DescriptorFactory.Create(QueryTypeDiagnosticId, QueryTypeMessageFormat); | ||
|
||
private static readonly ISet<KnownType> SupportedQueryTypes = new HashSet<KnownType> | ||
{ | ||
KnownType.System_Boolean, | ||
KnownType.System_DateTime, | ||
KnownType.System_Decimal, | ||
KnownType.System_Double, | ||
KnownType.System_Single, | ||
KnownType.System_Int32, | ||
KnownType.System_Int64, | ||
KnownType.System_String, | ||
KnownType.System_Guid | ||
}; | ||
|
||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(S6803Rule, S6797Rule); | ||
|
||
protected override void Initialize(SonarAnalysisContext context) => | ||
context.RegisterCompilationStartAction(c => | ||
{ | ||
if (c.Compilation.GetTypeByMetadataName(KnownType.Microsoft_AspNetCore_Components_RouteAttribute) is not null) | ||
{ | ||
context.RegisterSymbolAction(CheckQueryProperties, SymbolKind.Property); | ||
} | ||
}); | ||
|
||
private static void CheckQueryProperties(SonarSymbolReportingContext c) | ||
{ | ||
var property = (IPropertySymbol)c.Symbol; | ||
if (property.HasAttribute(KnownType.Microsoft_AspNetCore_Components_SupplyParameterFromQueryAttribute) | ||
&& property.HasAttribute(KnownType.Microsoft_AspNetCore_Components_ParameterAttribute)) | ||
{ | ||
if (!property.ContainingType.HasAttribute(KnownType.Microsoft_AspNetCore_Components_RouteAttribute)) | ||
{ | ||
foreach (var location in property.Locations) | ||
{ | ||
c.ReportIssue(Diagnostic.Create(S6803Rule, location)); | ||
} | ||
} | ||
else if (!SupportedQueryTypes.Any(x => IsSupportedType(property.Type, x))) | ||
{ | ||
foreach (var propertyType in property.DeclaringSyntaxReferences.Select(x => ((PropertyDeclarationSyntax)x.GetSyntax()).Type)) | ||
{ | ||
c.ReportIssue(Diagnostic.Create(S6797Rule, propertyType.GetLocation(), GetTypeName(propertyType))); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private static bool IsSupportedType(ITypeSymbol type, KnownType supportType) | ||
{ | ||
if (type is IArrayTypeSymbol arrayTypeSymbol) | ||
{ | ||
type = arrayTypeSymbol.ElementType; | ||
} | ||
|
||
if (KnownType.System_Nullable_T.Matches(type)) | ||
{ | ||
type = ((INamedTypeSymbol)type).TypeArguments[0]; | ||
} | ||
|
||
return supportType.Matches(type); | ||
} | ||
|
||
private static string GetTypeName(TypeSyntax propertyType) => | ||
propertyType switch | ||
{ | ||
GenericNameSyntax genericSyntax when propertyType.NameIs(KnownType.System_Nullable_T.TypeName) => genericSyntax.TypeArgumentList.Arguments[0].GetName(), | ||
{} tuple when TupleTypeSyntaxWrapper.IsInstance(tuple) => KnownType.System_ValueTuple.TypeName, | ||
_ => propertyType.GetName() | ||
}; | ||
} |
Oops, something went wrong.