/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Features/CSharpTest/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzerTests.cs
644 строки
17 KB
Cyrus Najmabadi
Renames
23 июл 2025, 10:53
23 июл 2025, 10:53
a167ea9
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.UsePatternMatching; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UsePatternMatching; [Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)] public sealed class CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzerTests(ITestOutputHelper logger) : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_NoEditor(logger) { internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) => (new CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer(), new CSharpIsAndCastCheckWithoutNameCodeFixProvider()); [Fact] public Task TestBinaryExpression() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { return [||]obj is TestFile && ((TestFile)obj).i > 0; } } """, """ class TestFile { int i; bool M(object obj) { return obj is TestFile {|Rename:file|} && file.i > 0; } } """); [Fact] public Task TestNotInCSharp6() => TestMissingAsync( """ class TestFile { int i; bool M(object obj) { return [||]obj is TestFile && ((TestFile)obj).i > 0; } } """, parameters: new TestParameters(parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp6))); [Fact] public Task TestExpressionBody() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) => [||]obj is TestFile && ((TestFile)obj).i > 0; } """, """ class TestFile { int i; bool M(object obj) => obj is TestFile {|Rename:file|} && file.i > 0; } """); [Fact] public Task TestField() => TestInRegularAndScriptAsync( """ class TestFile { int i; static object obj; bool M = [||]obj is TestFile && ((TestFile)obj).i > 0; } """, """ class TestFile { int i; static object obj; bool M = obj is TestFile {|Rename:file|} && file.i > 0; } """); [Fact] public Task TestLambdaBody() => TestInRegularAndScriptAsync( """ using System; class TestFile { int i; void Goo(Func<bool> f) { } bool M(object obj) => Goo(() => [||]obj is TestFile && ((TestFile)obj).i > 0, () => obj is TestFile && ((TestFile)obj).i > 0); } """, """ using System; class TestFile { int i; void Goo(Func<bool> f) { } bool M(object obj) => Goo(() => obj is TestFile {|Rename:file|} && file.i > 0, () => obj is TestFile && ((TestFile)obj).i > 0); } """); [Fact] public Task TestDefiniteAssignment1() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { if ([||]obj is TestFile) { M(((TestFile)obj).i); M(((TestFile)obj).i); } else { M(((TestFile)obj).i); M(((TestFile)obj).i); } } } """, """ class TestFile { int i; bool M(object obj) { if (obj is TestFile {|Rename:file|}) { M(file.i); M(file.i); } else { M(((TestFile)obj).i); M(((TestFile)obj).i); } } } """); [Fact] public Task TestDefiniteAssignment2() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { if (!([||]obj is TestFile)) { M(((TestFile)obj).i); M(((TestFile)obj).i); } else { M(((TestFile)obj).i); M(((TestFile)obj).i); } } } """, """ class TestFile { int i; bool M(object obj) { if (!(obj is TestFile {|Rename:file|})) { M(((TestFile)obj).i); M(((TestFile)obj).i); } else { M(file.i); M(file.i); } } } """); [Fact] public Task TestNotOnAnalyzerMatch() => TestMissingAsync( """ class TestFile { bool M(object obj) { if ([||]obj is TestFile) { var file = (TestFile)obj; } } } """); [Fact] public Task TestNotOnNullable() => TestMissingAsync( """ struct TestFile { bool M(object obj) { if ([||]obj is TestFile?) { var i = ((TestFile?)obj).Value; } } } """); [Fact] public Task TestComplexMatch() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { return [||]M(null) is TestFile && ((TestFile)M(null)).i > 0; } } """, """ class TestFile { int i; bool M(object obj) { return M(null) is TestFile {|Rename:file|} && file.i > 0; } } """); [Fact] public Task TestTrivia() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { return [||]obj is TestFile && /*before*/ ((TestFile)obj) /*after*/.i > 0; } } """, """ class TestFile { int i; bool M(object obj) { return obj is TestFile {|Rename:file|} && /*before*/ file /*after*/.i > 0; } } """); [Fact] public Task TestFixOnlyAfterIsCheck() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { return ((TestFile)obj).i > 0 && [||]obj is TestFile && ((TestFile)obj).i > 0; } } """, """ class TestFile { int i; bool M(object obj) { return ((TestFile)obj).i > 0 && obj is TestFile {|Rename:file|} && file.i > 0; } } """); [Fact] public Task TestArrayNaming() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { return [||]obj is int[] && ((int[])obj) > 0; } } """, """ class TestFile { int i; bool M(object obj) { return obj is int[] {|Rename:v|} && v > 0; } } """); [Fact] public Task TestNamingConflict1() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { TestFile file = null; return [||]obj is TestFile && ((TestFile)obj).i > 0; } } """, """ class TestFile { int i; bool M(object obj) { TestFile file = null; return obj is TestFile {|Rename:file1|} && file1.i > 0; } } """); [Fact] public Task TestNamingConflict2() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { if ([||]obj is TestFile) { TestFile file = null; M(((TestFile)obj).i); } } } """, """ class TestFile { int i; bool M(object obj) { if (obj is TestFile {|Rename:file1|}) { TestFile file = null; M(file1.i); } } } """); [Fact] public Task TestNamingNoConflict1() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { if ([||]obj is TestFile) { var v = new { file = 0 }; M(((TestFile)obj).i); } } } """, """ class TestFile { int i; bool M(object obj) { if (obj is TestFile {|Rename:file|}) { var v = new { file = 0 }; M(file.i); } } } """); [Fact] public Task TestNamingNoConflict2() => TestInRegularAndScriptAsync( """ class TestFile { int i; bool M(object obj) { if ([||]obj is TestFile) { var v = (file: 0, x: 1); M(((TestFile)obj).i); } } } """, """ class TestFile { int i; bool M(object obj) { if (obj is TestFile {|Rename:file|}) { var v = (file: 0, x: 1); M(file.i); } } } """); [Fact] public Task TestNamingNoConflict3() => TestInRegularAndScriptAsync( """ class X { public int file; } class TestFile { int i; bool M(object obj, X x) { if ([||]obj is TestFile) { var v = new { x.file }; M(((TestFile)obj).i); } } } """, """ class X { public int file; } class TestFile { int i; bool M(object obj, X x) { if (obj is TestFile {|Rename:file|}) { var v = new { x.file }; M(file.i); } } } """); [Fact] public Task TestNamingNoConflict4() => TestInRegularAndScriptAsync( """ class X { public int file; } class TestFile { int i; bool M(object obj, X x) { if ([||]obj is TestFile) { var v = (x.file, 0); M(((TestFile)obj).i); } } } """, """ class X { public int file; } class TestFile { int i; bool M(object obj, X x) { if (obj is TestFile {|Rename:file|}) { var v = (x.file, 0); M(file.i); } } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/51340")] public Task TestNoDiagnosticWhenCS0103Happens() => TestDiagnosticMissingAsync( """ using System.Linq; class Bar { private void Foo() { var objects = new SpecificThingType[100]; var d = from obj in objects let aGenericThing = obj.Prop where aGenericTh[||]ing is SpecificThingType let specificThing = (SpecificThingType)aGenericThing select (obj, specificThing); } } class SpecificThingType { public SpecificThingType Prop { get; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58558")] public Task TestInExpressionTree1() => TestMissingAsync( """ using System.Linq.Expressions; object? o = null; Expression<Func<bool>> test = () => [||]o is int && (int)o > 5; """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58558")] public Task TestInExpressionTree2() => TestMissingAsync( """ using System.Linq.Expressions; class C { void M() { object? o = null; Expression<Func<bool>> test = () => [||]o is int && (int)o > 5; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68051")] public Task TestNotWhenCrossingStaticLambda() => TestMissingAsync( """ using System; class C { void Main(object o) { if ([||]o is string) { M(static (object o) => { var s = (string)o; }); } } private void M(Action<object> value) { } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68051")] public Task TestNotWhenCrossingInstanceLambdaThatReferencesDifferentVariable() => TestMissingAsync( """ using System; class C { void Main(object o) { if ([||]o is string) { M((object o) => { var s = (string)o; }); } } private void M(Action<object> value) { } } """); }