未验证 提交 aa4ecc07 编写于 作者: J Jonathon Marolf 提交者: GitHub

Merge pull request #44951 from m-redding/bug-43202

......@@ -7,10 +7,12 @@
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.LanguageServices;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.UseIndexOrRangeOperator
......@@ -77,7 +79,6 @@ protected override void InitializeWorker(AnalysisContext context)
{
return;
}
context.ReportDiagnostic(CreateDiagnostic(resultOpt.Value));
}
......@@ -171,6 +172,14 @@ protected override void InitializeWorker(AnalysisContext context)
return null;
}
var indexer = GetIndexer(targetMethod.ContainingType, infoCache.RangeType, targetMethod.ContainingType);
// Need to make sure that if the target method is being written to, that the indexer returns a ref, is a read/write property,
// or the syntax allows for the slice method to be run
if (invocation.Syntax.IsLeftSideOfAnyAssignExpression() && indexer != null && IsWriteableIndexer(invocation, indexer))
{
return null;
}
// See if we have: (start, end - start). Specifically where the start operation it the
// same as the right side of the subtraction.
var startOperation = invocation.Arguments[0].Value;
......@@ -224,5 +233,12 @@ private Diagnostic CreateDiagnostic(Result result)
private static bool IsConstantInt32(IOperation operation)
=> operation.ConstantValue.HasValue && operation.ConstantValue.Value is int;
private static bool IsWriteableIndexer(IInvocationOperation invocation, IPropertySymbol indexer)
{
var refReturnMismatch = indexer.ReturnsByRef != invocation.TargetMethod.ReturnsByRef;
var indexerIsReadWrite = indexer.IsWriteableFieldOrProperty();
return refReturnMismatch && !indexerIsReadWrite;
}
}
}
......@@ -435,7 +435,6 @@ void Goo(S s)
s[1..^1] = default;
}
}";
await new VerifyCS.Test
{
ReferenceAssemblies = ReferenceAssemblies.NetCore.NetCoreApp31,
......@@ -604,6 +603,154 @@ void Goo(Span<int> s)
}.RunAsync();
}
[WorkItem(43202, "https://github.com/dotnet/roslyn/issues/43202")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseRangeOperator)]
public async Task TestWritableType()
{
var source =
@"
using System;
struct S {
public ref S Slice(int start, int length) => throw null;
public int Length { get; }
public S this[System.Range r] { get => default; }
}
class C
{
void Goo(S s)
{
s.Slice(1, s.Length - 2) = default;
}
}";
await new VerifyCS.Test
{
ReferenceAssemblies = ReferenceAssemblies.NetCore.NetCoreApp31,
TestCode = source,
FixedCode = source,
}.RunAsync();
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseRangeOperator)]
public async Task TestReturnByRef()
{
var source =
@"
struct S { public ref S Slice(int start, int length) => throw null; public int Length { get; } public S this[System.Range r] { get => throw null; } }
class C
{
void Goo(S s)
{
var x = s.Slice([|1, s.Length - 2|]);
}
}";
var fixedSource =
@"
struct S { public ref S Slice(int start, int length) => throw null; public int Length { get; } public S this[System.Range r] { get => throw null; } }
class C
{
void Goo(S s)
{
var x = s[1..^1];
}
}";
await new VerifyCS.Test
{
ReferenceAssemblies = ReferenceAssemblies.NetCore.NetCoreApp31,
TestCode = source,
FixedCode = fixedSource,
}.RunAsync();
}
[WorkItem(43202, "https://github.com/dotnet/roslyn/issues/43202")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseRangeOperator)]
public async Task TestIntWritableType()
{
var source =
@"
using System;
struct S {
public ref S Slice(int start, int length) => throw null;
public int Length { get; }
public S this[int r] { get => default; }
}
class C
{
void Goo(S s)
{
s.Slice([|1, s.Length - 2|]) = default;
}
}";
var fixedSource =
@"
using System;
struct S {
public ref S Slice(int start, int length) => throw null;
public int Length { get; }
public S this[int r] { get => default; }
}
class C
{
void Goo(S s)
{
s[1..^1] = default;
}
}";
await new VerifyCS.Test
{
ReferenceAssemblies = ReferenceAssemblies.NetCore.NetCoreApp31,
TestCode = source,
FixedCode = fixedSource,
}.RunAsync();
}
[WorkItem(43202, "https://github.com/dotnet/roslyn/issues/43202")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseRangeOperator)]
public async Task TestReadWriteProperty()
{
var source =
@"
using System;
struct S {
public ref S Slice(int start, int length) => throw null;
public int Length { get; }
public S this[System.Range r] { get => default; set { } }
}
class C
{
void Goo(S s)
{
s.Slice([|1, s.Length - 2|]) = default;
}
}";
var fixedSource =
@"
using System;
struct S {
public ref S Slice(int start, int length) => throw null;
public int Length { get; }
public S this[System.Range r] { get => default; set { } }
}
class C
{
void Goo(S s)
{
s[1..^1] = default;
}
}";
await new VerifyCS.Test
{
ReferenceAssemblies = ReferenceAssemblies.NetCore.NetCoreApp31,
TestCode = source,
FixedCode = fixedSource,
}.RunAsync();
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseRangeOperator)]
public async Task TestWithTypeWithActualSliceMethod3()
{
......@@ -627,7 +774,6 @@ void Goo(Span<int> s)
var v = s[1..];
}
}";
await new VerifyCS.Test
{
ReferenceAssemblies = ReferenceAssemblies.NetCore.NetCoreApp31,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册