未验证 提交 5a65f666 编写于 作者: J Jinu 提交者: GitHub

Merge pull request #26997 from rik-smeets/infer-type-in-expression-bodied-getter

Infer type in get accessor declarations, expression bodied local functions and local functions inside lambda expressions
......@@ -7730,6 +7730,206 @@ static void Main(string[] args)
Console.WriteLine(arg.[|NotFound|]());
});
}
}");
}
[WorkItem(26993, "https://github.com/dotnet/roslyn/issues/26993")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
public async Task TestGenerateMethodInExpressionBodiedGetter()
{
await TestInRegularAndScriptAsync(
@"class Class
{
int Property
{
get => [|GenerateMethod|]();
}
}",
@"using System;
class Class
{
int Property
{
get => GenerateMethod();
}
private int GenerateMethod()
{
throw new NotImplementedException();
}
}");
}
[WorkItem(26993, "https://github.com/dotnet/roslyn/issues/26993")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
public async Task TestGenerateMethodInExpressionBodiedSetter()
{
await TestInRegularAndScriptAsync(
@"class Class
{
int Property
{
set => [|GenerateMethod|](value);
}
}",
@"using System;
class Class
{
int Property
{
set => GenerateMethod(value);
}
private void GenerateMethod(int value)
{
throw new NotImplementedException();
}
}");
}
[WorkItem(26993, "https://github.com/dotnet/roslyn/issues/26993")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
public async Task TestGenerateMethodInExpressionBodiedLocalFunction()
{
await TestInRegularAndScriptAsync(
@"class Class
{
void Method()
{
int Local() => [|GenerateMethod()|];
}
}",
@"using System;
class Class
{
void Method()
{
int Local() => GenerateMethod();
}
private int GenerateMethod()
{
throw new NotImplementedException();
}
}");
}
[WorkItem(26993, "https://github.com/dotnet/roslyn/issues/26993")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
public async Task TestGenerateMethodInBlockBodiedLocalFunction()
{
await TestInRegularAndScriptAsync(
@"class Class
{
void Method()
{
int Local()
{
return [|GenerateMethod()|];
}
}
}",
@"using System;
class Class
{
void Method()
{
int Local()
{
return GenerateMethod();
}
}
private int GenerateMethod()
{
throw new NotImplementedException();
}
}");
}
[WorkItem(26993, "https://github.com/dotnet/roslyn/issues/26993")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
public async Task TestGenerateMethodInBlockBodiedLocalFunctionInsideLambdaExpression()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Class
{
void Method()
{
Action action = () =>
{
int Local()
{
return [|GenerateMethod()|];
}
}
}
}",
@"
using System;
class Class
{
void Method()
{
Action action = () =>
{
int Local()
{
return GenerateMethod();
}
}
}
private int GenerateMethod()
{
throw new NotImplementedException();
}
}");
}
[WorkItem(26993, "https://github.com/dotnet/roslyn/issues/26993")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
public async Task TestGenerateMethodInExpressionBodiedLocalFunctionInsideLambdaExpression()
{
await TestInRegularAndScriptAsync(
@"
using System;
class Class
{
void Method()
{
Action action = () =>
{
int Local() => [|GenerateMethod()|];
}
}
}",
@"
using System;
class Class
{
void Method()
{
Action action = () =>
{
int Local() => GenerateMethod();
}
}
private int GenerateMethod()
{
throw new NotImplementedException();
}
}");
}
}
......
......@@ -176,17 +176,12 @@ private IEnumerable<TypeInferenceInfo> GetTypesSimple(ExpressionSyntax expressio
private IEnumerable<TypeInferenceInfo> InferTypeInArrowExpressionClause(ArrowExpressionClauseSyntax arrowClause)
{
if (arrowClause.IsParentKind(SyntaxKind.PropertyDeclaration))
{
return InferTypeInPropertyDeclaration(arrowClause.Parent as PropertyDeclarationSyntax);
}
var parentSymbol = SemanticModel.GetDeclaredSymbol(arrowClause.Parent, CancellationToken);
var parentMemberType = GetMemberType(parentSymbol);
if (arrowClause.Parent is BaseMethodDeclarationSyntax)
{
return InferTypeInBaseMethodDeclaration(arrowClause.Parent as BaseMethodDeclarationSyntax);
}
return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
return parentMemberType != null
? SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(parentMemberType))
: SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
protected override IEnumerable<TypeInferenceInfo> InferTypesWorker_DoNotCallDirectly(int position)
......@@ -1189,14 +1184,6 @@ private IEnumerable<TypeInferenceInfo> InferTypeInPropertyDeclaration(PropertyDe
: SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
private IEnumerable<TypeInferenceInfo> InferTypeInBaseMethodDeclaration(BaseMethodDeclarationSyntax declaration)
{
var methodSymbol = SemanticModel.GetDeclaredSymbol(declaration);
return methodSymbol?.ReturnType != null
? SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(methodSymbol.ReturnType))
: SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
private IEnumerable<TypeInferenceInfo> InferTypeInExpressionStatement(ExpressionStatementSyntax expressionStatement, SyntaxToken? previousToken = null)
{
// If we're position based, then that means we're after the semicolon. In this case
......@@ -1870,22 +1857,19 @@ private IEnumerable<TypeInferenceInfo> InferTypeForReturnStatement(ReturnStateme
return;
}
var ancestorExpressions = returnStatement.GetAncestorsOrThis<ExpressionSyntax>();
var ancestor = returnStatement.AncestorsAndSelf().FirstOrDefault(e => e is AnonymousFunctionExpressionSyntax || e is LocalFunctionStatementSyntax);
// If we're in a lambda, then use the return type of the lambda to figure out what to
// infer. i.e. Func<int,string> f = i => { return Goo(); }
var lambda = ancestorExpressions.FirstOrDefault(e => e.IsKind(SyntaxKind.ParenthesizedLambdaExpression, SyntaxKind.SimpleLambdaExpression));
if (lambda != null)
if (ancestor is LambdaExpressionSyntax lambdaExpression)
{
types = InferTypeInLambdaExpression(lambda);
isAsync = lambda is ParenthesizedLambdaExpressionSyntax && ((ParenthesizedLambdaExpressionSyntax)lambda).AsyncKeyword.Kind() != SyntaxKind.None;
// If we're in a lambda, then use the return type of the lambda to figure out what to
// infer. i.e. Func<int,string> f = i => { return Goo(); }
types = InferTypeInLambdaExpression(lambdaExpression);
isAsync = lambdaExpression.AsyncKeyword.Kind() != SyntaxKind.None;
return;
}
// If we are inside a delegate then use the return type of the Invoke Method of the delegate type
var delegateExpression = (AnonymousMethodExpressionSyntax)ancestorExpressions.FirstOrDefault(e => e.IsKind(SyntaxKind.AnonymousMethodExpression));
if (delegateExpression != null)
else if (ancestor is AnonymousMethodExpressionSyntax delegateExpression)
{
// If we are inside a delegate then use the return type of the Invoke Method of the delegate type
var delegateType = InferTypes(delegateExpression).FirstOrDefault().InferredType;
if (delegateType != null && delegateType.IsDelegateType())
{
......@@ -1898,26 +1882,29 @@ private IEnumerable<TypeInferenceInfo> InferTypeForReturnStatement(ReturnStateme
}
}
}
var memberSymbol = GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel, returnStatement.GetAncestorOrThis<MemberDeclarationSyntax>());
if (memberSymbol.IsKind(SymbolKind.Method))
else if (ancestor is LocalFunctionStatementSyntax localFunctionStatement)
{
var method = memberSymbol as IMethodSymbol;
isAsync = method.IsAsync;
types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(method.ReturnType));
// If we are inside a local function then use the return type of the local function
var methodSymbol = (IMethodSymbol)SemanticModel.GetDeclaredSymbol(localFunctionStatement);
types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(methodSymbol.ReturnType));
isAsync = methodSymbol.IsAsync;
return;
}
else if (memberSymbol.IsKind(SymbolKind.Property))
{
types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo((memberSymbol as IPropertySymbol).Type));
return;
}
else if (memberSymbol.IsKind(SymbolKind.Field))
var memberSymbol = GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel, returnStatement.GetAncestorOrThis<MemberDeclarationSyntax>());
switch (memberSymbol)
{
types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo((memberSymbol as IFieldSymbol).Type));
return;
case IMethodSymbol method:
isAsync = method.IsAsync;
types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(method.ReturnType));
return;
case IPropertySymbol property:
types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(property.Type));
return;
case IFieldSymbol field:
types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(field.Type));
return;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册