提交 878f56bf 编写于 作者: C Cyrus Najmabadi

Match implicit '.Slice' pattern

上级 a58bcb8b
......@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Text;
using Roslyn.Test.Utilities;
using Xunit;
......@@ -20,9 +21,6 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider
private static readonly CSharpParseOptions s_parseOptions =
CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8);
private static readonly TestParameters s_testParameters =
new TestParameters(parseOptions: s_parseOptions);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseRangeOperator)]
public async Task TestNotInCSharp7()
{
......@@ -221,6 +219,94 @@ void Goo(string s, string t)
{
var v = t.Substring(s[1..^1][0], t.Length - s[1..^1][0]);
}
}", parseOptions: s_parseOptions);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseRangeOperator)]
public async Task TestWithTypeWithActualSliceMethod1()
{
await TestAsync(
@"
using System;
namespace System
{
public struct Range { }
public readonly ref struct Span<T>
{
public int Length { get { } }
public Span<T> Slice(int start, int length) { }
}
}
class C
{
void Goo(Span<int> s)
{
var v = s.Slice([||]1, s.Length - 1);
}
}",
@"
using System;
namespace System
{
public struct Range { }
public readonly ref struct Span<T>
{
public int Length { get { } }
public Span<T> Slice(int start, int length) { }
}
}
class C
{
void Goo(Span<int> s)
{
var v = s[1..];
}
}", parseOptions: s_parseOptions);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseRangeOperator)]
public async Task TestWithTypeWithActualSliceMethod2()
{
await TestAsync(
@"
using System;
namespace System
{
public struct Range { }
public readonly ref struct Span<T>
{
public int Length { get { } }
public Span<T> Slice(int start, int length) { }
}
}
class C
{
void Goo(Span<int> s)
{
var v = s.Slice([||]1, s.Length - 2);
}
}",
@"
using System;
namespace System
{
public struct Range { }
public readonly ref struct Span<T>
{
public int Length { get { } }
public Span<T> Slice(int start, int length) { }
}
}
class C
{
void Goo(Span<int> s)
{
var v = s[1..^1];
}
}", parseOptions: s_parseOptions);
}
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
......@@ -83,21 +84,33 @@ private MemberInfo ComputeMemberInfo(IMethodSymbol sliceLikeMethod, bool require
}
// A Slice method can either be paired with an Range-taking indexer on the type, or
// an Range-taking overload.
// an Range-taking overload, or an explicit method called .Slice that takes two ints:
//
// https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/ranges.md#implicit-range-support
if (sliceLikeMethod.ReturnType.Equals(containingType))
{
// it's a method like: MyType MyType.Slice(int start, int length). Look for an
// indexer like `MyType MyType.this[Range range]`. If we can't find one return
// 'default' so we'll consider this named-type non-viable.
// it's a method like: MyType MyType.Get(int start, int length). Look for an
// indexer like `MyType MyType.this[Range range]`.
var indexer = GetIndexer(containingType, RangeType, containingType);
if (indexer != null)
{
return new MemberInfo(lengthLikeProperty, overloadedMethodOpt: null);
}
// Also, look to see if the type has a `.Slice(int start, int length)` method.
// This is also a method the compiler knows to look for when a user writes `x[a..b]`
var actualSliceMethod =
sliceLikeMethod.ContainingType.GetMembers(nameof(Span<int>.Slice))
.OfType<IMethodSymbol>()
.FirstOrDefault(s => IsSliceLikeMethod(s));
if (actualSliceMethod != null)
{
return new MemberInfo(lengthLikeProperty, overloadedMethodOpt: null);
}
}
// it's a method like: `SomeType MyType.Slice(int start, int length)`. Look
// for an overload like: `SomeType MyType.Slice(Range)`
// it's a method like: `SomeType MyType.Get(int start, int length)`. Look
// for an overload like: `SomeType MyType.Get(Range)`
var overloadedRangeMethod = GetOverload(sliceLikeMethod, RangeType);
if (overloadedRangeMethod != null)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册