未验证 提交 9511dc00 编写于 作者: J Julia Feng 提交者: GitHub

Merge pull request #41371 from y87feng/40967

Introduce explicit downcast refactoring if a variable requires a cast to compile
......@@ -72,5 +72,6 @@ internal static class PredefinedCodeFixProviderNames
public const string UseThrowExpression = nameof(UseThrowExpression);
public const string PreferFrameworkType = nameof(PreferFrameworkType);
public const string MakeStructFieldsWritable = nameof(MakeStructFieldsWritable);
public const string AddExplicitCast = nameof(AddExplicitCast);
}
}
// 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.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.AddExplicitCast;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.AddExplicitCast
{
public partial class AddExplicitCastTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (null, new AddExplicitCastCodeFixProvider());
protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> actions)
=> FlattenActions(actions);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task SimpleVariableDeclaration()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
void M()
{
Base b;
Derived d = [|b|];
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
void M()
{
Base b;
Derived d = (Derived)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task SimpleVariableDeclarationWithFunctionInnvocation()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
void M()
{
Derived d = [|returnBase()|];
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
void M()
{
Derived d = (Derived)returnBase();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ReturnStatementWithObject()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
Derived returnBase() {
Base b;
return b[||];
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
Derived returnBase() {
Base b;
return (Derived)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ReturnStatementWithIEnumerable()
{
await TestInRegularAndScriptAsync(
@"
using System.Collections.Generic;
class Program
{
class Base {}
class Derived : Base {}
IEnumerable<Derived> returnBase() {
Base b;
return b[||];
}
}",
@"
using System.Collections.Generic;
class Program
{
class Base {}
class Derived : Base {}
IEnumerable<Derived> returnBase() {
Base b;
return (IEnumerable<Derived>)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ReturnStatementWithIEnumerator()
{
await TestInRegularAndScriptAsync(
@"
using System.Collections.Generic;
class Program
{
class Base {}
class Derived : Base {}
IEnumerator<Derived> returnBase() {
Base b;
return b[||];
}
}",
@"
using System.Collections.Generic;
class Program
{
class Base {}
class Derived : Base {}
IEnumerator<Derived> returnBase() {
Base b;
return (IEnumerator<Derived>)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ReturnStatementWithFunctionInnvocation()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
Derived returnDerived() {
return [|returnBase()|];
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
Derived returnDerived() {
return (Derived)returnBase();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task SimpleFunctionArgumentsWithObject1()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
void passDerived(Derived d) {}
void M() {
Base b;
passDerived([|b|]);
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
void passDerived(Derived d) {}
void M() {
Base b;
passDerived((Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task SimpleFunctionArgumentsWithObject2()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
void passDerived(int i, Derived d) {}
void M() {
Base b;
passDerived(1, [|b|]);
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
void passDerived(int i, Derived d) {}
void M() {
Base b;
passDerived(1, (Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task SimpleFunctionArgumentsWithFunctionInvocation()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
void passDerived(Derived d) {}
void M() {
passDerived([|returnBase()|]);
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
Base returnBase() {
Base b;
return b;
}
void passDerived(Derived d) {}
void M() {
passDerived((Derived)returnBase());
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task YieldReturnStatementWithObject()
{
await TestInRegularAndScriptAsync(
@"
using System.Collections.Generic;
class Program
{
class Base {}
class Derived : Base {}
IEnumerable<Derived> returnDerived() {
Base b;
yield return [|b|];
}
}",
@"
using System.Collections.Generic;
class Program
{
class Base {}
class Derived : Base {}
IEnumerable<Derived> returnDerived() {
Base b;
yield return (Derived)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task SimpleConstructorArgumentsWithObject()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public Test(Derived d) {}
}
void M() {
Base b;
Test t = new Test(b[||]);
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public Test(Derived d) {}
}
void M() {
Base b;
Test t = new Test((Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ReturnTypeWithTask()
{
await TestInRegularAndScriptAsync(
@"
using System.Threading.Tasks;
class Program
{
class Base {}
class Derived : Base {}
async Task<Derived> M() {
Base b;
return [||]b;
}
}",
@"
using System.Threading.Tasks;
class Program
{
class Base {}
class Derived : Base {}
async Task<Derived> M() {
Base b;
return (Derived)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task VariableDeclarationWithPublicFieldMember()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public Base b;
public Test(Base b) { this.b = b; }
}
void M() {
Base b;
Test t = new Test(b);
Derived d = [||]t.b;
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public Base b;
public Test(Base b) { this.b = b; }
}
void M() {
Base b;
Test t = new Test(b);
Derived d = (Derived)t.b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task VariableDeclarationWithPrivateFieldMember()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
Base b;
public Test(Base b) { this.b = b; }
}
void M() {
Base b;
Test t = new Test(b);
Derived d = [||]t.b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task PublicMemberFunctionArgument1()
{
await TestInRegularAndScriptAsync(
@"
using System.Collections.Generic;
class Program
{
class Base {}
class Derived : Base {}
void M() {
Base b;
List<Derived> list = new List<Derived>();
list.Add(b[||]);
}
}",
@"
using System.Collections.Generic;
class Program
{
class Base {}
class Derived : Base {}
void M() {
Base b;
List<Derived> list = new List<Derived>();
list.Add((Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task PublicMemberFunctionArgument2()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public void testing(Derived d) {}
}
void M() {
Base b;
Test t;
t.testing(b[||]);
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public void testing(Derived d) {}
}
void M() {
Base b;
Test t;
t.testing((Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task PrivateMemberFunctionArgument()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
private void testing(Derived d) {}
}
void M() {
Base b;
Test t;
t.testing(b[||]);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MemberFunctions()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public void testing(Derived d) {}
private void testing(Base b) {}
}
void M() {
Base b;
Test t;
t.testing(b[||]);
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public void testing(Derived d) {}
private void testing(Base b) {}
}
void M() {
Base b;
Test t;
t.testing((Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task BaseConstructorArgument()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public Test(Derived d) {}
}
class Derived_Test : Test {
public Derived_Test (Base b) : base([||]b) {}
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public Test(Derived d) {}
}
class Derived_Test : Test {
public Derived_Test (Base b) : base((Derived)b) {}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ThisConstructorArgument()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public Test(Derived d) {}
public Test(Base b, int i) : this([||]b) {}
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
class Test {
public Test(Derived d) {}
public Test(Base b, int i) : this((Derived)b) {}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction1()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M() {
Func<Base, Derived> foo = d => [||]d;
}
}",
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M() {
Func<Base, Derived> foo = d => (Derived)d;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction2()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void Foo() {
Func<Derived, Derived> func = d => d;
Base b;
Base b2 = func([||]b);
}
}",
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void Foo() {
Func<Derived, Derived> func = d => d;
Base b;
Base b2 = func((Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction3()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void Foo() {
Func<Base, Base> func = d => d;
Base b;
Derived b2 = [||]func(b);
}
}",
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void Foo() {
Func<Base, Base> func = d => d;
Base b;
Derived b2 = (Derived)func(b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction4()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
Derived Foo() {
Func<Base, Base> func = d => d;
Base b;
return [||]func(b);
}
}",
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
Derived Foo() {
Func<Base, Base> func = d => d;
Base b;
return (Derived)func(b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction5_ReturnStatement()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
Action<Derived> Foo() {
return [||](Base b) => { };
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction6_Arguments()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M(Derived d, Action<Derived> action) { }
void Foo() {
Base b = new Derived();
M([||]b, (Derived d) => { });
}
}",
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M(Derived d, Action<Derived> action) { }
void Foo() {
Base b = new Derived();
M((Derived)b, (Derived d) => { });
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction7_Arguments()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M(Derived d, Action<Derived> action) { }
void Foo() {
Base b = new Derived();
M([||]b, (Base base) => { });
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction8_Arguments()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M(Derived d, params Action<Derived>[] action) { }
void Foo() {
Base b1 = new Derived();
M([||]b1, (Derived d) => { }, (Derived d) => { });
}
}",
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M(Derived d, params Action<Derived>[] action) { }
void Foo() {
Base b1 = new Derived();
M((Derived)b1, (Derived d) => { }, (Derived d) => { });
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task LambdaFunction9_Arguments()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M(Derived d, params Action<Derived>[] action) { }
void Foo() {
Base b1 = new Derived();
M([||]b1, action: new Action<Derived>[0], (Derived d) => { }, (Derived d) => { });
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task InheritInterfaces1()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
interface Base1 {}
interface Base2 {}
class Derived : Base1, Base2 {}
void Foo(Base2 b) {
Derived d = [||]b;
}
}",
@"
class Program
{
interface Base1 {}
interface Base2 {}
class Derived : Base1, Base2 {}
void Foo(Base2 b) {
Derived d = (Derived)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task InheritInterfaces2()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
interface Base1 {}
interface Base2 {}
class Derived1 : Base1, Base2 {}
class Derived2 : Derived1 {}
void Foo(Base2 b) {
Derived2 d = [||]b;
}
}",
@"
class Program
{
interface Base1 {}
interface Base2 {}
class Derived1 : Base1, Base2 {}
class Derived2 : Derived1 {}
void Foo(Base2 b) {
Derived2 d = (Derived2)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task InheritInterfaces3()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
interface Base1 {}
interface Base2 : Base1 {}
Base2 Foo(Base1 b) {
return [||]b;
}
}",
@"
class Program
{
interface Base1 {}
interface Base2 : Base1 {}
Base2 Foo(Base1 b) {
return (Base2)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task InheritInterfaces4()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
interface Base1 {}
interface Base2 : Base1 {}
void Foo(Base1 b) {
Base2 b2 = [||]b;
}
}",
@"
class Program
{
interface Base1 {}
interface Base2 : Base1 {}
void Foo(Base1 b) {
Base2 b2 = (Base2)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task InheritInterfaces5()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
interface Base1 {}
interface Base2 : Base1 {}
void Foo(Base1 b) {
Base2 b2 = [||]b;
}
}",
@"
class Program
{
interface Base1 {}
interface Base2 : Base1 {}
void Foo(Base1 b) {
Base2 b2 = (Base2)b;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task InheritInterfaces6()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
interface Base1 {}
interface Base2 : Base1 {}
interface Base3 {}
class Derived1 : Base2, Base3 {}
class Derived2 : Derived1 {}
void Foo(Derived2 b) {}
void M(Base1 b) {
Foo([||]b);
}
}",
@"
class Program
{
interface Base1 {}
interface Base2 : Base1 {}
interface Base3 {}
class Derived1 : Base2, Base3 {}
class Derived2 : Derived1 {}
void Foo(Derived2 b) {}
void M(Base1 b) {
Foo((Derived2)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task GenericType()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M()
{
Func<Base, Base> func1 = b => b;
Func<Derived, Derived> func2 = [||]func1;
}
}",
@"
using System;
class Program
{
class Base {}
class Derived : Base {}
void M()
{
Func<Base, Base> func1 = b => b;
Func<Derived, Derived> func2 = (Func<Derived, Derived>)func1;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task GenericType2()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base { }
class Derived : Base { }
void Foo(Func<Derived, Derived> func) { }
void M()
{
Func<Base, Base> func1 = b => b;
Foo(func1[||]);
}
}",
@"
using System;
class Program
{
class Base { }
class Derived : Base { }
void Foo(Func<Derived, Derived> func) { }
void M()
{
Func<Base, Base> func1 = b => b;
Foo((Func<Derived, Derived>)func1);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task GenericType3()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Program
{
class Base { }
class Derived : Base { }
Func<Derived, Derived> Foo(Func<Derived, Derived> func)
{
Func<Base, Base> func1 = b => b;
return func1[||];
}
}",
@"
using System;
class Program
{
class Base { }
class Derived : Base { }
Func<Derived, Derived> Foo(Func<Derived, Derived> func)
{
Func<Base, Base> func1 = b => b;
return (Func<Derived, Derived>)func1;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task GenericType4()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
void Foo()
{
B<CB> b = null;
A<IA> c1 = [||]b;
}
public interface IA { }
public class CB : IA { }
public interface A<T> where T : IA { }
public class B<T> : A<T> where T : CB { }
}",
@"
class Program
{
void Foo()
{
B<CB> b = null;
A<IA> c1 = (A<IA>)b;
}
public interface IA { }
public class CB : IA { }
public interface A<T> where T : IA { }
public class B<T> : A<T> where T : CB { }
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task GenericType5()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
void Foo()
{
B<IB> b = null;
A<IA> c1 = [||]b;
}
public interface IA { }
public interface IB : IA { }
public class A<T> where T : IA { }
public class B<T> : A<T> where T : IB { }
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task GenericType6()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
void Foo()
{
B<IB, int> b = null;
A<IA, string> c1 = [||]b;
}
public interface IA { }
public class IB : IA { }
public interface A<T, U> where T : IA { }
public class B<T, U> : A<T, U> where T : IB { }
}",
@"
class Program
{
void Foo()
{
B<IB, int> b = null;
A<IA, string> c1 = (A<IA, string>)b;
}
public interface IA { }
public class IB : IA { }
public interface A<T, U> where T : IA { }
public class B<T, U> : A<T, U> where T : IB { }
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ObjectInitializer()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
void M() {
Derived d = [||]new Base();
Derived d2 = new Test();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ObjectInitializer2()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
void M() {
Derived d = new Base();
Derived d2 = [||]new Test();
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
void M() {
Derived d = new Base();
Derived d2 = (Derived)new Test();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ObjectInitializer3()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
Derived returnDerived() {
return [||]new Base();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ObjectInitializer4()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
Derived returnDerived() {
return [||]new Test();
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
Derived returnDerived() {
return (Derived)new Test();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ObjectInitializer5()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
void M(Derived d) { }
void Foo() {
M([||]new Base());
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ObjectInitializer6()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
void M(Derived d) { }
void Foo() {
M([||]new Test());
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
void M(Derived d) { }
void Foo() {
M((Derived)new Test());
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ObjectInitializer7()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Test
{
static public explicit operator Derived(Test t) { return new Derived(); }
}
void M(Derveed d) { }
void Foo() {
M([||]new Base());
}
}");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/41500")]
public async Task RedundantCast1()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo() {
Base b;
Derived d = [||](Base)b;
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo() {
Base b;
Derived d = (Derived)b;
}
}");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/41500")]
public async Task RedundantCast2()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived1 : Base { }
class Derived2 : Derived1 { }
void Foo() {
Base b;
Derived2 d = [||](Derived1)b;
}
}",
@"
class Program
{
class Base { }
class Derived1 : Base { }
class Derived2 : Derived1 { }
void Foo() {
Base b;
Derived2 d = (Derived2)b;
}
}");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/41500")]
public async Task RedundantCast3()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
void M(Derived d) { }
void Foo() {
Base b;
M([||](Base)b);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
void M(Derived d) { }
void Foo() {
Base b;
M((Derived)b);
}
}");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/41500")]
public async Task RedundantCast4()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived1 : Base { }
class Derived2 : Derived1 { }
void M(Derived2 d) { }
void Foo() {
Base b;
M([||](Derived1)b);
}
}",
@"
class Program
{
class Base { }
class Derived1 : Base { }
class Derived2 : Derived1 { }
void M(Derived2 d) { }
void Foo() {
Base b;
M((Derived2)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ExactMethodCandidate()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base
{
public void Testing(Base d) { }
}
class Derived : Base
{
public void Testing(Derived d) { }
}
void M()
{
Base b = new Base();
Derived d = new Derived();
d.Testing([||]b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates1_ArgumentsInOrder_NoLabels()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
void Foo(string s, Derived d) {}
void Foo(string s, int i) {}
void M()
{
Base b = new Base();
Foo("""", [||]b);
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
void Foo(string s, Derived d) {}
void Foo(string s, int i) {}
void M()
{
Base b = new Base();
Foo("""", (Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates2_ArgumentsInOrder_NoLabels()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
void Foo(string s, Derived d, out int i) {
i = 1;
}
void Foo(string s, Derived d) {}
void M()
{
Base b = new Base();
Foo("""", [||]b, out var i);
}
}",
@"
class Program
{
class Base {}
class Derived : Base {}
void Foo(string s, Derived d, out int i) {
i = 1;
}
void Foo(string s, Derived d) {}
void M()
{
Base b = new Base();
Foo("""", (Derived)b, out var i);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates3_ArgumentsInOrder_NoLabels_Params()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo(string s, Derived d, out int i, params object[] list)
{
i = 1;
}
void M()
{
Base b = new Base();
Foo("""", [||]b, out var i);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo(string s, Derived d, out int i, params object[] list)
{
i = 1;
}
void M()
{
Base b = new Base();
Foo("""", (Derived)b, out var i);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates4_ArgumentsInOrder_NoLabels_Params()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo(string s, Derived d, out int i, params object[] list)
{
i = 1;
}
void M()
{
Base b = new Base();
Foo("""", [||]b, out var i, 1);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo(string s, Derived d, out int i, params object[] list)
{
i = 1;
}
void M()
{
Base b = new Base();
Foo("""", (Derived)b, out var i, 1);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates5_ArgumentsInOrder_NoLabels_Params()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo(string s, Derived d, out int i, params object[] list)
{
i = 1;
}
void M()
{
Base b = new Base();
Foo("""", [||]b, out var i, 1, 2, 3);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo(string s, Derived d, out int i, params object[] list)
{
i = 1;
}
void M()
{
Base b = new Base();
Foo("""", (Derived)b, out var i, 1, 2, 3);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates6_ArgumentsInOrder_NoLabels_Params()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, params Derived2[] list) { }
void M()
{
Base b = new Base();
Foo("""", [||]b);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, params Derived2[] list) { }
void M()
{
Base b = new Base();
Foo("""", (Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates7_ArgumentsInOrder_NoLabels_Params()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, params Derived2[] list) { }
void M()
{
Base b = new Base();
Foo("""", b, [||]b);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, params Derived2[] list) { }
void M()
{
Base b = new Base();
Foo("""", b, (Derived2)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates8_ArgumentsInOrder_NoLabels()
{
await TestInRegularAndScriptAsync(
@"
namespace ExtensionMethods
{
public class Base { }
public class Derived : Base { }
class Program
{
Program()
{
string s = """";
Base b = new Derived();
Derived d = new Derived();
s.Foo([||]b, d);
}
}
public static class MyExtensions
{
public static void Foo(this string str, Derived d, Derived d2) { }
}
}",
@"
namespace ExtensionMethods
{
public class Base { }
public class Derived : Base { }
class Program
{
Program()
{
string s = """";
Base b = new Derived();
Derived d = new Derived();
s.Foo((Derived)b, d);
}
}
public static class MyExtensions
{
public static void Foo(this string str, Derived d, Derived d2) { }
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates9_ArgumentsOutOfOrder_NoLabels()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived1 : Base {}
class Derived2 : Derived1 {}
void Foo(string s, Derived d) {}
void Foo(string s, int i) {}
void M()
{
Base b = new Base();
Foo(b[||], """");
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates10_ArgumentsInOrder_SomeLabels()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i) { }
void M()
{
Base b = new Base();
Foo("""", d: [||]b, 1);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i) { }
void M()
{
Base b = new Base();
Foo("""", d: (Derived)b, 1);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates11_ArgumentsInOrder_SomeLabels_Params()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: [||]b, 1, list: strlist);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: (Derived)b, 1, list: strlist);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates12_ArgumentsInOrder_SomeLabels_Params()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: [||]b, list: strlist, i: 1);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: (Derived)b, list: strlist, i: 1);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates13_ArgumentsOutOfOrder_SomeLabels()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo(d: [||]b, """", 1, list: strlist);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates14_ArgumentsOutOfOrder_AllLabels()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo(d: [||]b, s: """", list: strlist, i: 1);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo(d: (Derived)b, s: """", list: strlist, i: 1);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates15_ArgumentsOutOfOrder_AllLabels()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo(d: """", s: [||]b, list: strlist, i: 1);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates17_ArgumentsInOrder_SomeLabels()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, int j = 1) { }
void M()
{
Base b = new Base();
Foo("""", d: [||]b, 1);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, int j = 1) { }
void M()
{
Base b = new Base();
Foo("""", d: (Derived)b, 1);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates18_ArgumentsInOrder_SomeLabels()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, params Derived2[] d2list) { }
void M()
{
Base b = new Base();
var dlist = new Derived[] {};
Foo("""", d: b, [||]dlist);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, params Derived2[] d2list) { }
void M()
{
Base b = new Base();
var dlist = new Derived[] {};
Foo("""", d: b, (Derived2[])dlist);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates19_ArgumentsInOrder_NoLabels_Params()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(params Derived2[] d2list) { }
void M()
{
Base b = new Base();
var dlist = new Derived[] {};
Foo([||]dlist, new Derived2());
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates20_ArgumentsInOrder_NoLabels_Params()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(params Derived2[] d2list) { }
void M()
{
Base b = new Base();
var dlist = new Derived[] {};
Foo([||]dlist, dlist);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates21_ArgumentsInOrder_Labels()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
void Foo(Derived d, int i) { }
void M()
{
Base b = new Base();
Foo([||]b, i:1, i:1);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MethodCandidates22_ArgumentsInOrder()
{
await TestMissingInRegularAndScriptAsync(
@"
class Program
{
class Base {}
class Derived : Base {}
void Foo(string s, Derived d, out Derived i) {
i = new Derived();
}
void Foo(string s, Derived d) {}
void M()
{
Base b = new Base();
Foo("""", [||]b, out Base i);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ConstructorCandidates1()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Derived d, int i, params object[] list) { }
}
void M()
{
Base b = new Base();
var strlist = new string[1];
Test t = new Test(d: [||]b, s:"""", i:1, list : strlist);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Derived d, int i, params object[] list) { }
}
void M()
{
Base b = new Base();
var strlist = new string[1];
Test t = new Test(d: (Derived)b, s:"""", i:1, list : strlist);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ConstructorCandidates2()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Derived d, int i, params object[] list) { }
}
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Test t = new Test("""", d: [||]b, i:1, ""1"", ""2"", ""3"");
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Derived d, int i, params object[] list) { }
}
void Foo(string s, Derived d, int i, params object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Test t = new Test("""", d: (Derived)b, i:1, ""1"", ""2"", ""3"");
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ConstructorCandidates3()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : [||]b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : (Derived)b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions1()
{
var initialMarkup =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : [||]b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
Test(string s, Derived2 d, int i) { }
}
}";
using (var workspace = CreateWorkspaceFromOptions(initialMarkup, new TestParameters()))
{
var (actions, actionToInvoke) = await GetCodeActionsAsync(workspace, new TestParameters());
Assert.Equal(2, actions.Length);
}
var expect_0 =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : (Derived)b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
Test(string s, Derived2 d, int i) { }
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_0, index: 0,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "Derived"));
var expect_1 =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : (Derived2)b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
Test(string s, Derived2 d, int i) { }
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_1, index: 1,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "Derived2"));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions2()
{
var initialMarkup =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : [||]b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
Test(string s, int i, Derived2 d) { }
}
}";
using (var workspace = CreateWorkspaceFromOptions(initialMarkup, new TestParameters()))
{
var (actions, actionToInvoke) = await GetCodeActionsAsync(workspace, new TestParameters());
Assert.Equal(2, actions.Length);
}
var expect_0 =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : (Derived)b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
Test(string s, int i, Derived2 d) { }
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_0, index: 0,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "Derived"));
var expect_1 =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : (Derived2)b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
Test(string s, int i, Derived2 d) { }
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_1, index: 1,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "Derived2"));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions3()
{
var initialMarkup =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : [||]b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
Test(string s, Derived d, int i, params object[] list)) { }
}
}";
var expected =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d : (Derived)b, s : s, i : i) { }
Test(string s, Derived d, int i) { }
Test(string s, Derived d, int i, params object[] list)) { }
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions4()
{
var initialMarkup =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, int j, int i, Derived d) { }
void Foo(string s, int i, Derived2 d) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", 1, i:1, d: [||]b);
}
}";
var expected =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, int j, int i, Derived d) { }
void Foo(string s, int i, Derived2 d) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", 1, i:1, d: (Derived)b);
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions5()
{
var initialMarkup =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void Foo(string s, Derived2 d, int i, object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: [||]b, list: strlist, i: 1);
}
}";
using (var workspace = CreateWorkspaceFromOptions(initialMarkup, new TestParameters()))
{
var (actions, actionToInvoke) = await GetCodeActionsAsync(workspace, new TestParameters());
Assert.Equal(2, actions.Length);
}
var expect_0 =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void Foo(string s, Derived2 d, int i, object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: (Derived)b, list: strlist, i: 1);
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_0, index: 0,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "Derived"));
var expect_1 =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i, params object[] list) { }
void Foo(string s, Derived2 d, int i, object[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: (Derived2)b, list: strlist, i: 1);
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_1, index: 1,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "Derived2"));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions6()
{
var initialMarkup =
@"
class Program
{
class Base {
static public explicit operator string(Base b) { return """"; }
}
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i) { }
void Foo(string s, Derived2 d, int i) { }
void Foo(string s, string d, int i) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: [||]b, i: 1);
}
}";
using (var workspace = CreateWorkspaceFromOptions(initialMarkup, new TestParameters()))
{
var (actions, actionToInvoke) = await GetCodeActionsAsync(workspace, new TestParameters());
Assert.Equal(3, actions.Length);
}
var expect_0 =
@"
class Program
{
class Base {
static public explicit operator string(Base b) { return """"; }
}
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i) { }
void Foo(string s, Derived2 d, int i) { }
void Foo(string s, string d, int i) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: (string)b, i: 1);
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_0, index: 0,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "string"));
var expect_1 =
@"
class Program
{
class Base {
static public explicit operator string(Base b) { return """"; }
}
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i) { }
void Foo(string s, Derived2 d, int i) { }
void Foo(string s, string d, int i) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: (Derived)b, i: 1);
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_1, index: 1,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "Derived"));
var expect_2 =
@"
class Program
{
class Base {
static public explicit operator string(Base b) { return """"; }
}
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s, Derived d, int i) { }
void Foo(string s, Derived2 d, int i) { }
void Foo(string s, string d, int i) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo("""", d: (Derived2)b, i: 1);
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expect_2, index: 2,
title: string.Format(CodeAnalysis.CSharp.CSharpFeaturesResources.Convert_type_to_0, "Derived2"));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions7()
{
var initialMarkup =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s1, int i, Derived d) { }
void Foo(string s2, int i, Derived2 d) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo(s1:"""", 1, d: [||]b);
}
}";
var expected =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(string s1, int i, Derived d) { }
void Foo(string s2, int i, Derived2 d) { }
void M()
{
Base b = new Base();
var strlist = new string[1];
Foo(s1:"""", 1, d: (Derived)b);
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions8()
{
var initialMarkup =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo4(Derived d, string a, string b, params string[] list) { }
void Foo4(Derived2 d, params string[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[] { };
Foo4([||]b, ""1"", ""2"", list: strlist);
}
}";
var expected =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo4(Derived d, string a, string b, params string[] list) { }
void Foo4(Derived2 d, params string[] list) { }
void M()
{
Base b = new Base();
var strlist = new string[] { };
Foo4((Derived)b, ""1"", ""2"", list: strlist);
}
}";
await TestInRegularAndScriptAsync(initialMarkup, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleOptions9()
{
var initialMarkup =
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void Foo(Derived d1) { }
void Foo(Derived2 d2) { }
void M() {
Foo([||]new Base());
}
}";
await TestMissingInRegularAndScriptAsync(initialMarkup);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleErrors1()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void M(Derived2 d2) { }
void Foo(Base b) {
Derived d;
M(d = [|b|]);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void M(Derived2 d2) { }
void Foo(Base b) {
Derived d;
M(d = (Derived)b);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task MultipleErrors2()
{
await TestInRegularAndScriptAsync(
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void M(Derived2 d2) { }
void Foo(Base b) {
Derived d;
M([||]d = b);
}
}",
@"
class Program
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
void M(Derived2 d2) { }
void Foo(Base b) {
Derived d;
M((Derived2)(d = b));
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
public async Task ErrorType()
{
await TestMissingInRegularAndScriptAsync(
@"
class C
{
void M(C c)
{
TypeThatDoesntExist t = new TypeThatDoesntExist();
M([||]t);
}
}");
}
}
}
// 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.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.AddExplicitCast
{
public partial class AddExplicitCastTests
{
#region "Fix all occurrences tests"
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task CS0266TestFixAllInDocument()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
Base ReturnBase(Derived)
{
Base b = new Base();
return b;
}
Derived ReturnDerived(Base b)
{
return b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
{
Base b;
yield return b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived()
{
Base b;
return b;
} ]]>
<![CDATA[ async Task<Derived> M() ]]>
{
Base b;
return b;
}
Derived ReturnDerived2(Base b)
{
return ReturnBase();
}
Derived Foo()
{
<![CDATA[ Func<Base, Base> func = d => d; ]]>
Base b;
return func(b);
}
public Program1()
{
Base b;
Derived d = {|FixAllInDocument:b|};
d = new Base() { };
Derived d2 = ReturnBase();
Derived d2 = ReturnBase(b);
Test t = new Test();
t.D = b;
t.d = b;
d = t.B;
<![CDATA[ Func<Base, Derived> foo = d => d; ]]>
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
class Test
{
static public explicit operator Derived2(Test t) { return new Derived2(); }
}
Derived2 returnDerived2_1() {
return new Derived1();
}
Derived2 returnDerived2_2() {
return new Test();
}
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Derived2 derived2 = b1;
derived2 = b3;
Base2 base2 = b1;
derived2 = d1;
Derived2 d2 = new Test();
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
public class Program3
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
Derived2 returnD2(Base b)
{
Derived d;
return d = b;
}
}
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
Base ReturnBase(Derived)
{
Base b = new Base();
return b;
}
Derived ReturnDerived(Base b)
{
return (Derived)b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
{
Base b;
yield return (Derived)b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived()
{
Base b;
return (IEnumerable<Derived>)b;
} ]]>
<![CDATA[ async Task<Derived> M() ]]>
{
Base b;
return (Derived)b;
}
Derived ReturnDerived2(Base b)
{
return (Derived)ReturnBase();
}
Derived Foo()
{
<![CDATA[ Func<Base, Base> func = d => d; ]]>
Base b;
return (Derived)func(b);
}
public Program1()
{
Base b;
Derived d = (Derived)b;
d = new Base() { };
Derived d2 = (Derived)ReturnBase();
Derived d2 = ReturnBase(b);
Test t = new Test();
t.D = (Derived)b;
t.d = b;
d = (Derived)t.B;
<![CDATA[ Func<Base, Derived> foo = d => (Derived)d; ]]>
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
d2 = (Derived)foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
class Test
{
static public explicit operator Derived2(Test t) { return new Derived2(); }
}
Derived2 returnDerived2_1() {
return new Derived1();
}
Derived2 returnDerived2_2() {
return new Test();
}
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Derived2 derived2 = b1;
derived2 = b3;
Base2 base2 = b1;
derived2 = d1;
Derived2 d2 = new Test();
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
public class Program3
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
Derived2 returnD2(Base b)
{
Derived d;
return d = b;
}
}
</Document>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task CS0266TestFixAllInProject()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
Base ReturnBase(Derived)
{
Base b = new Base();
return b;
}
Derived ReturnDerived(Base b)
{
return b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
{
Base b;
yield return b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived()
{
Base b;
return b;
} ]]>
<![CDATA[ async Task<Derived> M() ]]>
{
Base b;
return b;
}
Derived ReturnDerived2(Base b)
{
return ReturnBase();
}
Derived Foo()
{
<![CDATA[ Func<Base, Base> func = d => d; ]]>
Base b;
return func(b);
}
public Program1()
{
Base b;
Derived d = {|FixAllInProject:b|};
d = new Base() { };
Derived d2 = ReturnBase();
Derived d2 = ReturnBase(b);
Test t = new Test();
t.D = b;
t.d = b;
d = t.B;
<![CDATA[ Func<Base, Derived> foo = d => d; ]]>
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
class Test
{
static public explicit operator Derived2(Test t) { return new Derived2(); }
}
Derived2 returnDerived2_1() {
return new Derived1();
}
Derived2 returnDerived2_2() {
return new Test();
}
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Derived2 derived2 = b1;
derived2 = b3;
Base2 base2 = b1;
derived2 = d1;
Derived2 d2 = new Test();
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
public class Program3
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
Derived2 returnD2(Base b)
{
Derived d;
return d = b;
}
}
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
Base ReturnBase(Derived)
{
Base b = new Base();
return b;
}
Derived ReturnDerived(Base b)
{
return (Derived)b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
{
Base b;
yield return (Derived)b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived()
{
Base b;
return (IEnumerable<Derived>)b;
} ]]>
<![CDATA[ async Task<Derived> M() ]]>
{
Base b;
return (Derived)b;
}
Derived ReturnDerived2(Base b)
{
return (Derived)ReturnBase();
}
Derived Foo()
{
<![CDATA[ Func<Base, Base> func = d => d; ]]>
Base b;
return (Derived)func(b);
}
public Program1()
{
Base b;
Derived d = (Derived)b;
d = new Base() { };
Derived d2 = (Derived)ReturnBase();
Derived d2 = ReturnBase(b);
Test t = new Test();
t.D = (Derived)b;
t.d = b;
d = (Derived)t.B;
<![CDATA[ Func<Base, Derived> foo = d => (Derived)d; ]]>
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
d2 = (Derived)foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
class Test
{
static public explicit operator Derived2(Test t) { return new Derived2(); }
}
Derived2 returnDerived2_1() {
return new Derived1();
}
Derived2 returnDerived2_2() {
return (Derived2)new Test();
}
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Derived2 derived2 = (Derived2)b1;
derived2 = (Derived2)b3;
Base2 base2 = (Base2)b1;
derived2 = (Derived2)d1;
Derived2 d2 = (Derived2)new Test();
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
public class Program3
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
Derived2 returnD2(Base b)
{
Derived d;
return d = b;
}
}
</Document>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task CS0266TestFixAllInSolution()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
Base ReturnBase(Derived)
{
Base b = new Base();
return b;
}
Derived ReturnDerived(Base b)
{
return b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
{
Base b;
yield return b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived()
{
Base b;
return b;
} ]]>
<![CDATA[ async Task<Derived> M() ]]>
{
Base b;
return b;
}
Derived ReturnDerived2(Base b)
{
return ReturnBase();
}
Derived Foo()
{
<![CDATA[ Func<Base, Base> func = d => d; ]]>
Base b;
return func(b);
}
public Program1()
{
Base b;
Derived d = {|FixAllInSolution:b|};
d = new Base() { };
Derived d2 = ReturnBase();
Derived d2 = ReturnBase(b);
Test t = new Test();
t.D = b;
t.d = b;
d = t.B;
<![CDATA[ Func<Base, Derived> foo = d => d; ]]>
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
class Test
{
static public explicit operator Derived2(Test t) { return new Derived2(); }
}
Derived2 returnDerived2_1() {
return new Derived1();
}
Derived2 returnDerived2_2() {
return new Test();
}
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Derived2 derived2 = b1;
derived2 = b3;
Base2 base2 = b1;
derived2 = d1;
Derived2 d2 = new Test();
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
public class Program3
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
Derived2 returnD2(Base b)
{
Derived d;
return d = b;
}
}
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
Base ReturnBase(Derived)
{
Base b = new Base();
return b;
}
Derived ReturnDerived(Base b)
{
return (Derived)b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
{
Base b;
yield return (Derived)b;
}
<![CDATA[ IEnumerable<Derived> ReturnDerived()
{
Base b;
return (IEnumerable<Derived>)b;
} ]]>
<![CDATA[ async Task<Derived> M() ]]>
{
Base b;
return (Derived)b;
}
Derived ReturnDerived2(Base b)
{
return (Derived)ReturnBase();
}
Derived Foo()
{
<![CDATA[ Func<Base, Base> func = d => d; ]]>
Base b;
return (Derived)func(b);
}
public Program1()
{
Base b;
Derived d = (Derived)b;
d = new Base() { };
Derived d2 = (Derived)ReturnBase();
Derived d2 = ReturnBase(b);
Test t = new Test();
t.D = (Derived)b;
t.d = b;
d = (Derived)t.B;
<![CDATA[ Func<Base, Derived> foo = d => (Derived)d; ]]>
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
d2 = (Derived)foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
class Test
{
static public explicit operator Derived2(Test t) { return new Derived2(); }
}
Derived2 returnDerived2_1() {
return new Derived1();
}
Derived2 returnDerived2_2() {
return (Derived2)new Test();
}
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Derived2 derived2 = (Derived2)b1;
derived2 = (Derived2)b3;
Base2 base2 = (Base2)b1;
derived2 = (Derived2)d1;
Derived2 d2 = (Derived2)new Test();
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
public class Program3
{
class Base { }
class Derived : Base { }
class Derived2 : Derived { }
Derived2 returnD2(Base b)
{
Derived d;
return (Derived2)(d = (Derived)b);
}
}
</Document>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task CS1503TestFixAllInDocument()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Test(Derived derived)
{
d = derived;
B = derived;
}
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
public void testing(Derived d) { }
private void testing(Base b) { }
}
class Test2 : Test
{
public Test2(Base b) : base(b) { }
}
class Test3
{
public Test3(Derived b) { }
public Test3(int i, Base b) : this(b) { }
public void testing(int i, Derived d) { }
private void testing(int i, Base d) { }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
void PassDerived(Derived d) { }
void PassDerived(int i, Derived d) { }
public Program1()
{
Base b;
Derived d = b;
PassDerived({|FixAllInDocument:b|});
PassDerived(ReturnBase());
PassDerived(1, b);
PassDerived(1, ReturnBase());
<![CDATA[ List<Derived> list = new List<Derived>(); ]]>
list.Add(b);
Test t = new Test();
t.testing(b);
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
Derived d2 = foo2(b);
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1(b1);
Foo1(d1);
Foo2(b1);
Foo3(b1);
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
class Program3
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1(b1);
Foo1(d1);
Foo2(b1);
Foo3(b1);
}
}
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Test(Derived derived)
{
d = derived;
B = derived;
}
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
public void testing(Derived d) { }
private void testing(Base b) { }
}
class Test2 : Test
{
public Test2(Base b) : base((Derived)b) { }
}
class Test3
{
public Test3(Derived b) { }
public Test3(int i, Base b) : this((Derived)b) { }
public void testing(int i, Derived d) { }
private void testing(int i, Base d) { }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
void PassDerived(Derived d) { }
void PassDerived(int i, Derived d) { }
public Program1()
{
Base b;
Derived d = b;
PassDerived((Derived)b);
PassDerived((Derived)ReturnBase());
PassDerived(1, (Derived)b);
PassDerived(1, (Derived)ReturnBase());
<![CDATA[ List<Derived> list = new List<Derived>(); ]]>
list.Add((Derived)b);
Test t = new Test();
t.testing((Derived)b);
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
Derived d2 = foo2((Derived)b);
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1(b1);
Foo1(d1);
Foo2(b1);
Foo3(b1);
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
class Program3
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1(b1);
Foo1(d1);
Foo2(b1);
Foo3(b1);
}
}
</Document>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task CS1503TestFixAllInProject()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Test(Derived derived)
{
d = derived;
B = derived;
}
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
public void testing(Derived d) { }
private void testing(Base b) { }
}
class Test2 : Test
{
public Test2(Base b) : base(b) { }
}
class Test3
{
public Test3(Derived b) { }
public Test3(int i, Base b) : this(b) { }
public void testing(int i, Derived d) { }
private void testing(int i, Base d) { }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
void PassDerived(Derived d) { }
void PassDerived(int i, Derived d) { }
public Program1()
{
Base b;
Derived d = b;
PassDerived({|FixAllInProject:b|});
PassDerived(ReturnBase());
PassDerived(1, b);
PassDerived(1, ReturnBase());
<![CDATA[ List<Derived> list = new List<Derived>(); ]]>
list.Add(b);
Test t = new Test();
t.testing(b);
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
Derived d2 = foo2(b);
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
class Test
{
static public explicit operator Derived1(Test t) { return new Derived1(); }
static public explicit operator Derived2(Test t) { return new Derived2(); }
}
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
void Foo4(int i, string j, Derived1 d) { }
void Foo4(string j, int i, Derived1 d) { }
void Foo5(string j, int i, Derived2 d, int x = 1) { }
void Foo5(string j, int i, Derived1 d, params Derived2[] d2list) { }
void Foo6(Derived1 d, params Derived2[] d2list) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1(b1);
Foo1(d1);
Foo2(b1);
Foo3(b1);
Foo4(1, """", b1);
Foo4(i: 1, j: """", b1); // one operation, fix
Foo5("""", 1, b1); // multiple operations, no fix-all
Foo5(d: b1, i: 1, j: """", x: 1); // all arguments out of order - match
Foo5(1, """", x: 1, d: b1); // part of arguments out of order - mismatch
Foo5(1, """", d: b1, b2, b3, d1); // part of arguments out of order - mismatch
Foo5("""", 1, d: b1, b2, b3, d1); // part of arguments out of order - match
var d2list = new Derived2[] { };
Foo5(d2list: d2list, j: """", i: 1, d: b2);
var d1list = new Derived1[] { };
Foo5(d2list: d1list, j: """", i: 1, d: b2);
Foo6(b1);
Foo6(new Test()); // params is optional, object creation can be cast with explicit cast operator
Foo6(new Test(), new Derived1()); // object creation cannot be cast without explicit cast operator
Foo6(new Derived1(), new Test());
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
class Program3
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1(b1);
Foo1(d1);
Foo2(b1);
Foo3(b1);
}
}
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Test(Derived derived)
{
d = derived;
B = derived;
}
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
public void testing(Derived d) { }
private void testing(Base b) { }
}
class Test2 : Test
{
public Test2(Base b) : base((Derived)b) { }
}
class Test3
{
public Test3(Derived b) { }
public Test3(int i, Base b) : this((Derived)b) { }
public void testing(int i, Derived d) { }
private void testing(int i, Base d) { }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
void PassDerived(Derived d) { }
void PassDerived(int i, Derived d) { }
public Program1()
{
Base b;
Derived d = b;
PassDerived((Derived)b);
PassDerived((Derived)ReturnBase());
PassDerived(1, (Derived)b);
PassDerived(1, (Derived)ReturnBase());
<![CDATA[ List<Derived> list = new List<Derived>(); ]]>
list.Add((Derived)b);
Test t = new Test();
t.testing((Derived)b);
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
Derived d2 = foo2((Derived)b);
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
class Test
{
static public explicit operator Derived1(Test t) { return new Derived1(); }
static public explicit operator Derived2(Test t) { return new Derived2(); }
}
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
void Foo4(int i, string j, Derived1 d) { }
void Foo4(string j, int i, Derived1 d) { }
void Foo5(string j, int i, Derived2 d, int x = 1) { }
void Foo5(string j, int i, Derived1 d, params Derived2[] d2list) { }
void Foo6(Derived1 d, params Derived2[] d2list) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1((Derived2)b1);
Foo1((Derived2)d1);
Foo2((Base2)b1);
Foo3((Derived2)b1);
Foo4(1, """", (Derived1)b1);
Foo4(i: 1, j: """", (Derived1)b1); // one operation, fix
Foo5("""", 1, b1); // multiple operations, no fix-all
Foo5(d: (Derived2)b1, i: 1, j: """", x: 1); // all arguments out of order - match
Foo5(1, """", x: 1, d: b1); // part of arguments out of order - mismatch
Foo5(1, """", d: b1, b2, b3, d1); // part of arguments out of order - mismatch
Foo5("""", 1, d: (Derived1)b1, (Derived2)b2, (Derived2)b3, (Derived2)d1); // part of arguments out of order - match
var d2list = new Derived2[] { };
Foo5(d2list: d2list, j: """", i: 1, d: (Derived1)b2);
var d1list = new Derived1[] { };
Foo5(d2list: (Derived2[])d1list, j: """", i: 1, d: (Derived1)b2);
Foo6((Derived1)b1);
Foo6((Derived1)new Test()); // params is optional, object creation can be cast with explicit cast operator
Foo6((Derived1)new Test(), new Derived1()); // object creation cannot be cast without explicit cast operator
Foo6(new Derived1(), (Derived2)new Test());
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
class Program3
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1(b1);
Foo1(d1);
Foo2(b1);
Foo3(b1);
}
}
</Document>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task CS1503TestFixAllInSolution()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Test(Derived derived)
{
d = derived;
B = derived;
}
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
public void testing(Derived d) { }
private void testing(Base b) { }
}
class Test2 : Test
{
public Test2(Base b) : base(b) { }
}
class Test3
{
public Test3(Derived b) { }
public Test3(int i, Base b) : this(b) { }
public void testing(int i, Derived d) { }
private void testing(int i, Base d) { }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
void PassDerived(Derived d) { }
void PassDerived(int i, Derived d) { }
public Program1()
{
Base b;
Derived d = b;
PassDerived({|FixAllInSolution:b|});
PassDerived(ReturnBase());
PassDerived(1, b);
PassDerived(1, ReturnBase());
<![CDATA[ List<Derived> list = new List<Derived>(); ]]>
list.Add(b);
Test t = new Test();
t.testing(b);
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
Derived d2 = foo2(b);
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1(b1);
Foo1(d1);
Foo2(b1);
Foo3(b1);
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
class Program3
{
interface Base { }
class Derived1 : Base { }
class Derived2 : Derived1 { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d: b, s: s, i: i) { } // 2 operations, no fix in fix-all
Test(string s, Derived1 d, int i) { }
Test(string s, Derived2 d, int i) { }
}
void Foo(Derived1 d, int a, int b, params int[] list) { }
void Foo(Derived2 d, params int[] list) { }
private void M2(Base b, Derived1 d1, Derived2 d2)
{
Foo(b, 1, 2); // 2 operations, no fix in fix-all
var intlist = new int[] { };
Foo(b, 1, 2, list: intlist); // 2 operations
}
}
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
class Base { }
class Derived : Base { }
class Test
{
private Derived d;
private Base b;
public Test(Derived derived)
{
d = derived;
B = derived;
}
public Derived D { get => d; set => d = value; }
public Base B { get => b; set => b = value; }
public void testing(Derived d) { }
private void testing(Base b) { }
}
class Test2 : Test
{
public Test2(Base b) : base((Derived)b) { }
}
class Test3
{
public Test3(Derived b) { }
public Test3(int i, Base b) : this((Derived)b) { }
public void testing(int i, Derived d) { }
private void testing(int i, Base d) { }
}
Base ReturnBase()
{
Base b = new Base();
return b;
}
void PassDerived(Derived d) { }
void PassDerived(int i, Derived d) { }
public Program1()
{
Base b;
Derived d = b;
PassDerived((Derived)b);
PassDerived((Derived)ReturnBase());
PassDerived(1, (Derived)b);
PassDerived(1, (Derived)ReturnBase());
<![CDATA[ List<Derived> list = new List<Derived>(); ]]>
list.Add((Derived)b);
Test t = new Test();
t.testing((Derived)b);
<![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
Derived d2 = foo2((Derived)b);
d2 = foo2(d);
}
}
</Document>
<Document>
public class Program2
{
interface Base1 { }
interface Base2 : Base1 { }
interface Base3 { }
class Derived1 : Base2, Base3 { }
class Derived2 : Derived1 { }
void Foo1(Derived2 b) { }
void Foo2(Base2 b) { }
void Foo3(Derived2 b1) { }
void Foo3(int i) { }
private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
{
Foo1((Derived2)b1);
Foo1((Derived2)d1);
Foo2((Base2)b1);
Foo3((Derived2)b1);
}
}
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
class Program3
{
interface Base { }
class Derived1 : Base { }
class Derived2 : Derived1 { }
class Test
{
public Test(string s, Base b, int i, params object[] list) : this(d: b, s: s, i: i) { } // 2 operations, no fix in fix-all
Test(string s, Derived1 d, int i) { }
Test(string s, Derived2 d, int i) { }
}
void Foo(Derived1 d, int a, int b, params int[] list) { }
void Foo(Derived2 d, params int[] list) { }
private void M2(Base b, Derived1 d1, Derived2 d2)
{
Foo(b, 1, 2); // 2 operations, no fix in fix-all
var intlist = new int[] { };
Foo(b, 1, 2, list: intlist); // 2 operations
}
}
</Document>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected);
}
#endregion
}
}
......@@ -643,6 +643,12 @@
<value>Reverse 'for' statement</value>
<comment>{Locked="for"} "for" is a C# keyword and should not be localized.</comment>
</data>
<data name="Add_explicit_cast" xml:space="preserve">
<value>Add explicit cast</value>
</data>
<data name="Convert_type_to_0" xml:space="preserve">
<value>Convert type to '{0}'</value>
</data>
<data name="Convert_to_regular_string" xml:space="preserve">
<value>Convert to regular string</value>
</data>
......
// 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.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.AddExplicitCast
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.AddExplicitCast), Shared]
internal sealed partial class AddExplicitCastCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
/// <summary>
/// CS0266: Cannot implicitly convert from type 'x' to 'y'. An explicit conversion exists (are you missing a cast?)
/// </summary>
private const string CS0266 = nameof(CS0266);
/// <summary>
/// CS1503: Argument 1: cannot convert from 'x' to 'y'
/// </summary>
private const string CS1503 = nameof(CS1503);
/// <summary>
/// Give a set of least specific types with a limit, and the part exceeding the limit doesn't show any code fix, but logs telemetry
/// </summary>
private const int MaximumConversionOptions = 3;
[ImportingConstructor]
public AddExplicitCastCodeFixProvider()
{
}
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CS0266, CS1503);
internal override CodeFixCategory CodeFixCategory => CodeFixCategory.Compile;
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var diagnostic = context.Diagnostics.First();
var root = await document.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>();
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var targetNode = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true)
.GetAncestorsOrThis<ExpressionSyntax>().FirstOrDefault();
if (targetNode == null)
return;
var hasSolution = TryGetTargetTypeInfo(
semanticModel, root, diagnostic.Id, targetNode, cancellationToken,
out var nodeType, out var potentialConversionTypes);
if (!hasSolution)
{
return;
}
if (potentialConversionTypes.Length == 1)
{
context.RegisterCodeFix(new MyCodeAction(
CSharpFeaturesResources.Add_explicit_cast,
c => FixAsync(context.Document, context.Diagnostics.First(), c)),
context.Diagnostics);
}
else
{
var actions = ArrayBuilder<CodeAction>.GetInstance();
// MaximumConversionOptions: we show at most [MaximumConversionOptions] options for this code fixer
for (var i = 0; i < Math.Min(MaximumConversionOptions, potentialConversionTypes.Length); i++)
{
var convType = potentialConversionTypes[i];
actions.Add(new MyCodeAction(
string.Format(
CSharpFeaturesResources.Convert_type_to_0,
convType.ToMinimalDisplayString(semanticModel, context.Span.Start)),
_ => ApplySingleConversionToDocumentAsync(document, ApplyFix(root, targetNode, convType))));
}
if (potentialConversionTypes.Length > MaximumConversionOptions)
{
// If the number of potential conversion types is larger than options we could show, report telemetry
Logger.Log(FunctionId.CodeFixes_AddExplicitCast,
KeyValueLogMessage.Create(m =>
{
m["NumberOfCandidates"] = potentialConversionTypes.Length;
}));
}
context.RegisterCodeFix(new CodeAction.CodeActionWithNestedActions(
CSharpFeaturesResources.Add_explicit_cast,
actions.ToImmutableAndFree(), isInlinable: false),
context.Diagnostics);
}
}
private static SyntaxNode ApplyFix(SyntaxNode currentRoot, ExpressionSyntax targetNode, ITypeSymbol conversionType)
{
// TODO:
// the Simplifier doesn't remove the redundant cast from the expression
// Issue link: https://github.com/dotnet/roslyn/issues/41500
var castExpression = targetNode.Cast(conversionType).WithAdditionalAnnotations(Simplifier.Annotation);
var newRoot = currentRoot.ReplaceNode(targetNode, castExpression);
return newRoot;
}
private static Task<Document> ApplySingleConversionToDocumentAsync(Document document, SyntaxNode currentRoot)
=> Task.FromResult(document.WithSyntaxRoot(currentRoot));
/// <summary>
/// Output the current type information of the target node and the conversion type(s) that the target node is going to be cast by.
/// Implicit downcast can appear on Variable Declaration, Return Statement, and Function Invocation
/// <para/>
/// For example:
/// Base b; Derived d = [||]b;
/// "b" is the current node with type "Base", and the potential conversion types list which "b" can be cast by is {Derived}
/// </summary>
/// <param name="diagnosticId"> The ID of the diagnostic.</param>
/// <param name="targetNode"> The node to be cast.</param>
/// <param name="targetNodeType"> Output the type of "targetNode".</param>
/// <param name="potentialConversionTypes"> Output the potential conversions types that "targetNode" can be cast to</param>
/// <returns>
/// True, if the target node has at least one potential conversion type, and they are assigned to "potentialConversionTypes"
/// False, if the target node has no conversion type.
/// </returns>
private static bool TryGetTargetTypeInfo(
SemanticModel semanticModel, SyntaxNode root, string diagnosticId, ExpressionSyntax targetNode,
CancellationToken cancellationToken, [NotNullWhen(true)] out ITypeSymbol? targetNodeType,
out ImmutableArray<ITypeSymbol> potentialConversionTypes)
{
potentialConversionTypes = ImmutableArray<ITypeSymbol>.Empty;
var targetNodeInfo = semanticModel.GetTypeInfo(targetNode, cancellationToken);
targetNodeType = targetNodeInfo.Type;
if (targetNodeType == null)
return false;
// The error happens either on an assignement operation or on an invocation expression.
// If the error happens on assignment operation, "ConvertedType" is different from the current "Type"
using var _ = ArrayBuilder<ITypeSymbol>.GetInstance(out var mutablePotentialConversionTypes);
if (diagnosticId == CS0266
&& targetNodeInfo.ConvertedType != null
&& !targetNodeType.Equals(targetNodeInfo.ConvertedType))
{
mutablePotentialConversionTypes.Add(targetNodeInfo.ConvertedType);
}
else if (diagnosticId == CS1503
&& targetNode.GetAncestorsOrThis<ArgumentSyntax>().FirstOrDefault() is ArgumentSyntax targetArgument
&& targetArgument.Parent is ArgumentListSyntax argumentList
&& argumentList.Parent is SyntaxNode invocationNode) // invocation node could be Invocation Expression, Object Creation, Base Constructor...
{
mutablePotentialConversionTypes.AddRange(GetPotentialConversionTypes(semanticModel, root, targetNodeType,
targetArgument, argumentList, invocationNode, cancellationToken));
}
// clear up duplicate types
potentialConversionTypes = FilterValidPotentialConversionTypes(semanticModel, targetNode, targetNodeType,
mutablePotentialConversionTypes);
return !potentialConversionTypes.IsEmpty;
static ImmutableArray<ITypeSymbol> GetPotentialConversionTypes(
SemanticModel semanticModel, SyntaxNode root, ITypeSymbol targetNodeType, ArgumentSyntax targetArgument,
ArgumentListSyntax argumentList, SyntaxNode invocationNode, CancellationToken cancellationToken)
{
// Implicit downcast appears on the argument of invocation node,
// get all candidate functions and extract potential conversion types
var symbolInfo = semanticModel.GetSymbolInfo(invocationNode, cancellationToken);
var candidateSymbols = symbolInfo.CandidateSymbols;
using var _ = ArrayBuilder<ITypeSymbol>.GetInstance(out var mutablePotentialConversionTypes);
foreach (var candidateSymbol in candidateSymbols.OfType<IMethodSymbol>())
{
if (CanArgumentTypesBeConvertedToParameterTypes(
semanticModel, root, argumentList, candidateSymbol.Parameters, targetArgument,
cancellationToken, out var targetArgumentConversionType))
{
mutablePotentialConversionTypes.Add(targetArgumentConversionType);
}
}
// Sort the potential conversion types by inheritance distance, so that
// operations are in order and user can choose least specific types(more accurate)
mutablePotentialConversionTypes.Sort(new InheritanceDistanceComparer(semanticModel, targetNodeType));
return mutablePotentialConversionTypes.ToImmutable();
}
static ImmutableArray<ITypeSymbol> FilterValidPotentialConversionTypes(
SemanticModel semanticModel, ExpressionSyntax targetNode, ITypeSymbol targetNodeType,
ArrayBuilder<ITypeSymbol> mutablePotentialConversionTypes)
{
using var _ = ArrayBuilder<ITypeSymbol>.GetInstance(out var validPotentialConversionTypes);
foreach (var targetNodeConversionType in mutablePotentialConversionTypes)
{
var commonConversion = semanticModel.Compilation.ClassifyCommonConversion(
targetNodeType, targetNodeConversionType);
// For cases like object creation expression. for example:
// Derived d = [||]new Base();
// It is always invalid except the target node has explicit conversion operator or is numeric.
if (targetNode.IsKind(SyntaxKind.ObjectCreationExpression)
&& !commonConversion.IsUserDefined)
{
continue;
}
if (commonConversion.Exists)
{
validPotentialConversionTypes.Add(targetNodeConversionType);
}
}
return validPotentialConversionTypes.Distinct().ToImmutableArray();
}
}
/// <summary>
/// Test if all argument types can be converted to corresponding parameter types.
/// </summary>
/// For example:
/// class Base { }
/// class Derived1 : Base { }
/// class Derived2 : Base { }
/// class Derived3 : Base { }
/// void DoSomething(int i, Derived1 d) { }
/// void DoSomething(string s, Derived2 d) { }
/// void DoSomething(int i, Derived3 d) { }
///
/// Base b;
/// DoSomething(1, [||]b);
///
/// *void DoSomething(string s, Derived2 d) { }* is not the perfect match candidate function for
/// *DoSomething(1, [||]b)* because int and string are not ancestor-descendant relationship. Thus,
/// Derived2 is not a potential conversion type.
///
/// <param name="argumentList"> The argument list of invocation expression</param>
/// <param name="parameters"> The parameters of function</param>
/// <param name="targetArgument"> The target argument that contains target node</param>
/// <param name="targetArgumentConversionType"> Output the corresponding parameter type of
/// the target arugment if function returns true</param>
/// <returns>
/// True, if arguments and parameters match perfectly. <paramref name="targetArgumentConversionType"/> Output the corresponding parameter type
/// False, otherwise.
/// </returns>
private static bool CanArgumentTypesBeConvertedToParameterTypes(
SemanticModel semanticModel, SyntaxNode root, ArgumentListSyntax argumentList,
ImmutableArray<IParameterSymbol> parameters, ArgumentSyntax targetArgument,
CancellationToken cancellationToken, [NotNullWhen(true)] out ITypeSymbol? targetArgumentConversionType)
{
targetArgumentConversionType = null;
// No conversion happens under this case
if (parameters.Length == 0)
return false;
var arguments = argumentList.Arguments;
var newArguments = new List<ArgumentSyntax>();
for (var i = 0; i < arguments.Count; i++)
{
// Parameter index cannot out of its range, #arguments is larger than #parameter only if the last parameter with keyword params
var parameterIndex = Math.Min(i, parameters.Length - 1);
// If the argument has a name, get the corresponding parameter index
var nameSyntax = arguments[i].NameColon?.Name;
if (nameSyntax != null)
{
var name = nameSyntax.Identifier.ValueText;
if (!FindCorrespondingParameterByName(name, parameters, ref parameterIndex))
return false;
}
// The argument is either in order with parameters, or have a matched name with parameters.
var argumentExpression = arguments[i].Expression;
var parameterType = parameters[parameterIndex].Type;
if (parameters[parameterIndex].IsParams
&& parameters.Last().Type is IArrayTypeSymbol paramsType
&& (semanticModel.ClassifyConversion(argumentExpression, paramsType.ElementType).Exists))
{
newArguments.Add(arguments[i].WithExpression(argumentExpression.Cast(paramsType.ElementType)));
if (arguments[i].Equals(targetArgument))
targetArgumentConversionType = paramsType.ElementType;
}
else if (semanticModel.ClassifyConversion(argumentExpression, parameterType).Exists)
{
newArguments.Add(arguments[i].WithExpression(argumentExpression.Cast(parameterType)));
if (arguments[i].Equals(targetArgument))
targetArgumentConversionType = parameterType;
}
else if (argumentExpression.Kind() == SyntaxKind.DeclarationExpression
&& semanticModel.GetTypeInfo(argumentExpression, cancellationToken).Type is ITypeSymbol argumentType
&& semanticModel.Compilation.ClassifyCommonConversion(argumentType, parameterType).IsIdentity)
{
// Direct conversion from a declaration expression to a type is unspecified, thus we classify the
// conversion from the type of declaration expression to the parameter type
// An example for this case:
// void Foo(out int i) { i = 1; }
// Foo([|out var i|]);
// "var i" is a declaration expression
//
// In addition, since this case is with keyword "out", the type of declaration expression and the
// parameter type must be identical in order to match.
newArguments.Add(arguments[i]);
}
else
{
return false;
}
}
return IsInvocationExpressionWithNewArgumentsApplicable(semanticModel, root, argumentList, newArguments, targetArgument);
}
private static bool FindCorrespondingParameterByName(
string argumentName, ImmutableArray<IParameterSymbol> parameters, ref int parameterIndex)
{
for (var j = 0; j < parameters.Length; j++)
{
if (argumentName.Equals(parameters[j].Name))
{
parameterIndex = j;
return true;
}
}
return false;
}
/// <summary>
/// Check whether the invocation expression with new arguments is applicatble.
/// </summary>
/// <param name="oldArgumentList" >old argumentList node</param>
/// <param name="newArguments"> new arguments that are cast by corresponding parameter types</param>
/// <param name="targetNode"> The node needs to be cast.</param>
/// <returns>
/// Return true if the invocation expression with new arguments is applicatble.
/// Otherwise, return false
/// </returns>
private static bool IsInvocationExpressionWithNewArgumentsApplicable(
SemanticModel semanticModel, SyntaxNode root, ArgumentListSyntax oldArgumentList,
List<ArgumentSyntax> newArguments, SyntaxNode targetNode)
{
var separatedSyntaxList = SyntaxFactory.SeparatedList(newArguments);
var newRoot = root.ReplaceNode(oldArgumentList, oldArgumentList.WithArguments(separatedSyntaxList));
var newArgumentListNode = newRoot.FindNode(targetNode.Span).GetAncestorsOrThis<ArgumentListSyntax>().FirstOrDefault();
if (newArgumentListNode.Parent is SyntaxNode newExpression)
{
var symbolInfo = semanticModel.GetSpeculativeSymbolInfo(newExpression.SpanStart, newExpression,
SpeculativeBindingOption.BindAsExpression);
return symbolInfo.Symbol != null;
}
return false;
}
protected override async Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var targetNodes = diagnostics.SelectAsArray(
d => root.FindNode(d.Location.SourceSpan, getInnermostNodeForTie: true)
.GetAncestorsOrThis<ExpressionSyntax>().FirstOrDefault());
await editor.ApplyExpressionLevelSemanticEditsAsync(
document, targetNodes,
(semanticModel, targetNode) => true,
(semanticModel, currentRoot, targetNode) =>
{
// All diagnostics have the same error code
if (TryGetTargetTypeInfo(semanticModel, currentRoot, diagnostics[0].Id, targetNode,
cancellationToken, out var nodeType, out var potentialConversionTypes)
&& potentialConversionTypes.Length == 1)
{
return ApplyFix(currentRoot, targetNode, potentialConversionTypes[0]);
}
return currentRoot;
},
cancellationToken).ConfigureAwait(false);
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
public MyCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument)
: base(title, createChangedDocument, equivalenceKey: title)
{
}
}
}
}
// 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.
#nullable enable
using System;
using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.AddExplicitCast
{
/// <summary>
/// Sort types by inheritance distance from the base type in ascending order, i.e., less specific type
/// has higher priority because it has less probability to make mistakes
/// <para/>
/// For example:
/// class Base { }
/// class Derived1 : Base { }
/// class Derived2 : Derived1 { }
///
/// void Foo(Derived1 d1) { }
/// void Foo(Derived2 d2) { }
///
/// Base b = new Derived1();
/// Foo([||]b);
///
/// operations:
/// 1. Convert type to 'Derived1'
/// 2. Convert type to 'Derived2'
///
/// 'Derived1' is less specific than 'Derived2' compared to 'Base'
/// </summary>
internal sealed class InheritanceDistanceComparer : IComparer<ITypeSymbol>
{
private readonly ITypeSymbol _baseType;
private readonly SemanticModel _semanticModel;
public InheritanceDistanceComparer(SemanticModel semanticModel, ITypeSymbol baseType)
{
_semanticModel = semanticModel;
_baseType = baseType;
}
public int Compare(ITypeSymbol x, ITypeSymbol y)
{
var xDist = GetInheritanceDistance(x);
var yDist = GetInheritanceDistance(y);
return xDist.CompareTo(yDist);
}
/// <summary>
/// Calculate the inheritance distance between _baseType and derivedType.
/// </summary>
private int GetInheritanceDistanceRecursive(ITypeSymbol? derivedType)
{
if (derivedType == null)
return int.MaxValue;
if (derivedType.Equals(_baseType))
return 0;
var distance = GetInheritanceDistanceRecursive(derivedType.BaseType);
if (derivedType.Interfaces.Length != 0)
{
foreach (var interfaceType in derivedType.Interfaces)
{
distance = Math.Min(GetInheritanceDistanceRecursive(interfaceType), distance);
}
}
return distance == int.MaxValue ? distance : distance + 1;
}
/// <summary>
/// Wrapper funtion of [GetInheritanceDistance], also consider the class with explicit conversion operator
/// has the highest priority.
/// </summary>
private int GetInheritanceDistance(ITypeSymbol type)
{
var conversion = _semanticModel.Compilation.ClassifyCommonConversion(_baseType, type);
// If the node has the explicit conversion operator, then it has the shortest distance
// since explicit conversion operator is defined by users and has the highest priority
var distance = conversion.IsUserDefined ? 0 : GetInheritanceDistanceRecursive(type);
return distance;
}
}
}
......@@ -12,6 +12,11 @@
<target state="translated">Přidat await</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Přidat chybějící direktivy using</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Deklarovat jako s možnou hodnotou null</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">"await" hinzufügen</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Fehlende using-Anweisungen hinzufügen</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Als für NULL-Werte zulässig deklarieren</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">Añadir await</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Añadir valores using que faltan</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Declara como que acepta valores NULL</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">Ajouter une expression await</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Ajouter les instructions using manquantes</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Déclarer comme nullable</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">Aggiungi await</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Aggiungi using mancanti</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Dichiara come nullable</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">await を追加する</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">不足している using を追加する</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Null 許容型として宣言する</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">await 추가</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">누락된 using 추가</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Nullable로 선언</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">Dodaj element await</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Dodaj brakujące instrukcje using</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Zadeklaruj jako dopuszczający wartość null</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">Adicionar aguardar</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Adicionar usings ausentes</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Declarar como anulável</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">Добавить await</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Добавить отсутствующие директивы using</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Объявить как тип, допускающий значения null</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">Ekleme bekliyor</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">Eksik usings Ekle</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">Olarak null olabilecek ilan</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">添加 await</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">添加缺少的 using</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">声明成可为 null</target>
......
......@@ -12,6 +12,11 @@
<target state="translated">新增等候</target>
<note />
</trans-unit>
<trans-unit id="Add_explicit_cast">
<source>Add explicit cast</source>
<target state="new">Add explicit cast</target>
<note />
</trans-unit>
<trans-unit id="Add_missing_usings">
<source>Add missing usings</source>
<target state="translated">新增遺漏的 using</target>
......@@ -92,6 +97,11 @@
<target state="new">Convert to verbatim string</target>
<note />
</trans-unit>
<trans-unit id="Convert_type_to_0">
<source>Convert type to '{0}'</source>
<target state="new">Convert type to '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Declare_as_nullable">
<source>Declare as nullable</source>
<target state="translated">宣告為可為 Null</target>
......
......@@ -40,6 +40,7 @@ public static class Features
public const string CodeActionsAddBraces = "CodeActions.AddBraces";
public const string CodeActionsAddConstructorParametersFromMembers = "CodeActions.AddConstructorParametersFromMembers";
public const string CodeActionsAddDocCommentNodes = "CodeActions.AddDocCommentParamNodes";
public const string CodeActionsAddExplicitCast = "CodeActions.AddExplicitCast";
public const string CodeActionsAddFileBanner = "CodeActions.AddFileBanner";
public const string CodeActionsAddImport = "CodeActions.AddImport";
public const string CodeActionsAddMissingReference = "CodeActions.AddMissingReference";
......
......@@ -475,5 +475,7 @@ internal enum FunctionId
LanguageServer_ActivateFailed = 382,
LanguageServer_OnLoadedFailed = 383,
CodeFixes_AddExplicitCast = 384,
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册