|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using TestHelper;
namespace Microsoft.AspNetCore.Components.Analyzers;
public class ComponentParameterUsageAnalyzerTest : DiagnosticVerifier
{
public ComponentParameterUsageAnalyzerTest()
{
ComponentTestSource = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class TestComponent : IComponent
{{
[Parameter] public string TestProperty {{ get; set; }}
[Parameter] public int TestInt {{ get; set; }}
public string NonParameter {{ get; set; }}
}}
}}" + ComponentsTestDeclarations.Source;
}
private string ComponentTestSource { get; }
[Fact]
public void ComponentPropertySimpleAssignment_Warns()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class OtherComponent : IComponent
{{
private TestComponent _testComponent;
void Render()
{{
_testComponent = new TestComponent();
_testComponent.TestProperty = ""Hello World"";
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test,
new DiagnosticResult
{
Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id,
Message = "Component parameter 'TestProperty' should not be set outside of its component.",
Severity = DiagnosticSeverity.Warning,
Locations = new[]
{
new DiagnosticResultLocation("Test0.cs", 11, 17)
}
});
}
[Fact]
public void ComponentPropertyCoalesceAssignment__Warns()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class OtherComponent : IComponent
{{
private TestComponent _testComponent;
void Render()
{{
_testComponent = new TestComponent();
_testComponent.TestProperty ??= ""Hello World"";
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test,
new DiagnosticResult
{
Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id,
Message = "Component parameter 'TestProperty' should not be set outside of its component.",
Severity = DiagnosticSeverity.Warning,
Locations = new[]
{
new DiagnosticResultLocation("Test0.cs", 11, 17)
}
});
}
[Fact]
public void ComponentPropertyCompoundAssignment__Warns()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class OtherComponent : IComponent
{{
private TestComponent _testComponent;
void Render()
{{
_testComponent = new TestComponent();
_testComponent.TestProperty += ""Hello World"";
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test,
new DiagnosticResult
{
Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id,
Message = "Component parameter 'TestProperty' should not be set outside of its component.",
Severity = DiagnosticSeverity.Warning,
Locations = new[]
{
new DiagnosticResultLocation("Test0.cs", 11, 17)
}
});
}
[Fact]
public void ComponentPropertyIncrement_Warns()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class OtherComponent : IComponent
{{
private TestComponent _testComponent;
void Render()
{{
_testComponent = new TestComponent();
_testComponent.TestInt++;
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test,
new DiagnosticResult
{
Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id,
Message = "Component parameter 'TestInt' should not be set outside of its component.",
Severity = DiagnosticSeverity.Warning,
Locations = new[]
{
new DiagnosticResultLocation("Test0.cs", 11, 17)
}
});
}
[Fact]
public void ComponentPropertyDecrement_Warns()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class OtherComponent : IComponent
{{
private TestComponent _testComponent;
void Render()
{{
_testComponent = new TestComponent();
_testComponent.TestInt--;
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test,
new DiagnosticResult
{
Id = DiagnosticDescriptors.ComponentParametersShouldNotBeSetOutsideOfTheirDeclaredComponent.Id,
Message = "Component parameter 'TestInt' should not be set outside of its component.",
Severity = DiagnosticSeverity.Warning,
Locations = new[]
{
new DiagnosticResultLocation("Test0.cs", 11, 17)
}
});
}
[Fact]
public void ComponentPropertyExpression_Ignores()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class TypeName
{{
void Method()
{{
System.IO.Console.WriteLine(new TestComponent().TestProperty);
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test);
}
[Fact]
public void ComponentPropertyExpressionInStatement_Ignores()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class TypeName
{{
void Method()
{{
var testComponent = new TestComponent();
for (var i = 0; i < testComponent.TestProperty.Length; i++)
{{
}}
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test);
}
[Fact]
public void RetrievalOfComponentPropertyValueInAssignment_Ignores()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class TypeName
{{
void Method()
{{
var testComponent = new TestComponent();
AnotherProperty = testComponent.TestProperty;
}}
public string AnotherProperty {{ get; set; }}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test);
}
[Fact]
public void ShadowedComponentPropertyAssignment_Ignores()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class TypeName
{{
void Method()
{{
var testComponent = new InheritedComponent();
testComponent.TestProperty = ""Hello World"";
}}
}}
class InheritedComponent : TestComponent
{{
public new string TestProperty {{ get; set; }}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test);
}
[Fact]
public void InheritedImplicitComponentPropertyAssignment_Ignores()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class TypeName : TestComponent
{{
void Method()
{{
this.TestProperty = ""Hello World"";
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test);
}
[Fact]
public void ImplicitComponentPropertyAssignment_Ignores()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class TypeName : IComponent
{{
void Method()
{{
TestProperty = ""Hello World"";
}}
[Parameter] public string TestProperty {{ get; set; }}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test);
}
[Fact]
public void ComponentPropertyAssignment_NonParameter_Ignores()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class OtherComponent : IComponent
{{
private TestComponent _testComponent;
void Render()
{{
_testComponent = new TestComponent();
_testComponent.NonParameter = ""Hello World"";
}}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test);
}
[Fact]
public void NonComponentPropertyAssignment_Ignores()
{
var test = $@"
namespace ConsoleApplication1
{{
using {typeof(ParameterAttribute).Namespace};
class OtherComponent : IComponent
{{
private SomethingElse _testNonComponent;
void Render()
{{
_testNonComponent = new NotAComponent();
_testNonComponent.TestProperty = ""Hello World"";
}}
}}
class NotAComponent
{{
[Parameter] public string TestProperty {{ get; set; }}
}}
}}" + ComponentTestSource;
VerifyCSharpDiagnostic(test);
}
protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() => new ComponentParameterUsageAnalyzer();
}
|