提交 903d2787 编写于 作者: A AlekseyTs

Changed syntax model to reuse VariableDeclarationSyntax for out variable declarations.

上级 fbd993eb
......@@ -41,26 +41,19 @@ corresponding parameter in the signature of the best candidate.
**ArgumentSyntax node is extended as follows to accommodate for the new syntax:**
- ```Expression``` field is made optional.
- Two new optional fields are added.
- ```Expression``` field is replaced with the following field
```
<Field Name="Type" Type="TypeSyntax" Optional="true"/>
<Field Name="Identifier" Type="SyntaxToken" Optional="true">
```
**SemanticModel changes:**
Added new API
```
/// <summary>
/// Given an argument syntax, get symbol for an out var that it declares, if any.
/// </summary>
/// <param name="declarationSyntax">The syntax node that declares a variable.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The symbol that was declared.</returns>
public ISymbol GetDeclaredSymbol(ArgumentSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken));
<Field Name="ExpressionOrDeclaration" Type="CSharpSyntaxNode" >
<PropertyComment>
<summary>
ExpressionSyntax node representing the argument value,
or VariableDeclarationSyntax representing out local declaration.
</summary>
</PropertyComment>
</Field>
```
The Expression property in the public API is preserved.
VariableDeclarationSyntax is expected to contain single VariableDeclarator without initializer or arguments.
**Open issues and TODOs:**
......
......@@ -1370,15 +1370,14 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag
else
{
SourceLocalSymbol sourceLocal;
ArgumentSyntax argument;
type = null;
if (node.SyntaxTree == localSymbolLocation.SourceTree && (object)(sourceLocal = localSymbol as SourceLocalSymbol) != null &&
sourceLocal.IdentifierToken.Parent?.Kind() == SyntaxKind.Argument)
if (node.SyntaxTree == localSymbolLocation.SourceTree &&
(object)(sourceLocal = localSymbol as SourceLocalSymbol) != null &&
ArgumentSyntax.IsIdentifierOfOutVariableDeclaration(sourceLocal.IdentifierToken, out argument))
{
var argument = (ArgumentSyntax)sourceLocal.IdentifierToken.Parent;
if (argument.Identifier == sourceLocal.IdentifierToken &&
argument.Type.IsVar)
if (argument.Type.IsVar)
{
// We are referring to an out variable which might need type inference.
// If it is in fact needs inference, it is illegal to reference it in the same argument list that immediately
......
......@@ -165,9 +165,7 @@ public override void VisitArgument(ArgumentSyntax node)
return;
}
var contextKind = node.Identifier.
Parent. // ArgumentSyntax
Parent. // ArgumentListSyntax
var contextKind = node.Parent. // ArgumentListSyntax
Parent. // invocation/constructor initializer
Kind();
......
......@@ -1210,15 +1210,6 @@ public static ISymbol GetDeclaredSymbol(this SemanticModel semanticModel, Variab
return csmodel?.GetDeclaredSymbol(declarationSyntax, cancellationToken);
}
/// <summary>
/// Given an argument syntax, get symbol for out var that it declares, if any.
/// </summary>
public static ISymbol GetDeclaredSymbol(this SemanticModel semanticModel, ArgumentSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
var csmodel = semanticModel as CSharpSemanticModel;
return csmodel?.GetDeclaredSymbol(declarationSyntax, cancellationToken);
}
/// <summary>
/// Given a declaration pattern syntax, get the corresponding symbol.
/// </summary>
......
......@@ -510,6 +510,8 @@ public SymbolInfo GetSymbolInfo(ExpressionSyntax expression, CancellationToken c
{
CheckSyntaxNode(expression);
SyntaxNode parent;
if (!CanGetSemanticInfo(expression, allowNamedArgumentName: true))
{
return SymbolInfo.None;
......@@ -519,10 +521,12 @@ public SymbolInfo GetSymbolInfo(ExpressionSyntax expression, CancellationToken c
// Named arguments handled in special way.
return this.GetNamedArgumentSymbolInfo((IdentifierNameSyntax)expression, cancellationToken);
}
else if (expression.Parent?.Kind() == SyntaxKind.Argument &&
((ArgumentSyntax)expression.Parent).Type == expression)
else if ((parent = expression.Parent)?.Kind() == SyntaxKind.VariableDeclaration &&
((VariableDeclarationSyntax)parent).Type == expression &&
(parent = parent.Parent)?.Kind() == SyntaxKind.Argument &&
((ArgumentSyntax)parent).Type == expression)
{
TypeSymbol outVarType = (GetDeclaredSymbol((ArgumentSyntax)expression.Parent, cancellationToken) as LocalSymbol)?.Type;
TypeSymbol outVarType = (GetDeclaredSymbol(((ArgumentSyntax)parent).VariableDeclaration.Variables.First(), cancellationToken) as LocalSymbol)?.Type;
if (outVarType?.IsErrorType() == false)
{
......@@ -2667,14 +2671,6 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp
/// <returns>The symbol that was declared.</returns>
public abstract ISymbol GetDeclaredSymbol(VariableDeclaratorSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Given an argument syntax, get symbol for an out var that it declares, if any.
/// </summary>
/// <param name="declarationSyntax">The syntax node that declares a variable.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The symbol that was declared.</returns>
public abstract ISymbol GetDeclaredSymbol(ArgumentSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Given a declaration pattern syntax, get the corresponding symbol.
/// </summary>
......@@ -4569,8 +4565,6 @@ protected sealed override ISymbol GetDeclaredSymbolCore(SyntaxNode declaration,
return this.GetDeclaredSymbol((AnonymousObjectMemberDeclaratorSyntax)node, cancellationToken);
case SyntaxKind.VariableDeclarator:
return this.GetDeclaredSymbol((VariableDeclaratorSyntax)node, cancellationToken);
case SyntaxKind.Argument:
return this.GetDeclaredSymbol((ArgumentSyntax)node, cancellationToken);
case SyntaxKind.DeclarationPattern:
return this.GetDeclaredSymbol((DeclarationPatternSyntax)node, cancellationToken);
case SyntaxKind.NamespaceDeclaration:
......
......@@ -569,18 +569,6 @@ private LocalSymbol GetDeclaredLocal(CSharpSyntaxNode declarationSyntax, SyntaxT
return null;
}
public override ISymbol GetDeclaredSymbol(ArgumentSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
CheckSyntaxNode(declarationSyntax);
if (declarationSyntax.Expression != null)
{
return null;
}
return GetDeclaredLocal(declarationSyntax, declarationSyntax.Identifier);
}
public override ISymbol GetDeclaredSymbol(DeclarationPatternSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
CheckSyntaxNode(declarationSyntax);
......
......@@ -1643,18 +1643,6 @@ public override ISymbol GetDeclaredSymbol(VariableDeclaratorSyntax declarationSy
return memberModel == null ? null : memberModel.GetDeclaredSymbol(declarationSyntax, cancellationToken);
}
/// <summary>
/// Given an argument syntax, get symbol for an out var that it declares, if any.
/// </summary>
/// <param name="declarationSyntax">The syntax node that declares a variable.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The symbol that was declared.</returns>
public override ISymbol GetDeclaredSymbol(ArgumentSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
var memberModel = this.GetMemberModel(declarationSyntax);
return memberModel == null ? null : memberModel.GetDeclaredSymbol(declarationSyntax, cancellationToken);
}
/// <summary>
/// Given a declaration pattern syntax, get the corresponding symbol.
/// </summary>
......
......@@ -4942,8 +4942,7 @@ private static bool CanReuseVariableDeclarator(CSharp.Syntax.VariableDeclaratorS
var expression = item as ExpressionSyntax;
if (expression != null)
{
args.Add(_syntaxFactory.Argument(null, default(SyntaxToken), expression,
type: null, identifier: default(SyntaxToken)));
args.Add(_syntaxFactory.Argument(null, default(SyntaxToken), expression));
}
else
{
......@@ -9470,8 +9469,6 @@ private ArgumentSyntax ParseArgumentExpression(bool isIndexer)
}
ExpressionSyntax expression;
TypeSyntax typeSyntax = null;
SyntaxToken identifier = default(SyntaxToken);
if (isIndexer && (this.CurrentToken.Kind == SyntaxKind.CommaToken || this.CurrentToken.Kind == SyntaxKind.CloseBracketToken))
{
......@@ -9493,9 +9490,14 @@ private ArgumentSyntax ParseArgumentExpression(bool isIndexer)
refOrOutKeyword != null && refOrOutKeyword.Kind == SyntaxKind.OutKeyword &&
IsPossibleOutVarDeclaration())
{
expression = null;
typeSyntax = ParseType(parentIsParameter: false);
identifier = CheckFeatureAvailability(this.ParseIdentifierToken(), MessageID.IDS_FeatureOutVar);
TypeSyntax typeSyntax = ParseType(parentIsParameter: false);
SyntaxToken identifier = CheckFeatureAvailability(this.ParseIdentifierToken(), MessageID.IDS_FeatureOutVar);
return _syntaxFactory.Argument(nameColon, refOrOutKeyword,
_syntaxFactory.VariableDeclaration(typeSyntax,
new SeparatedSyntaxList<VariableDeclaratorSyntax>(
new SyntaxList<CSharpSyntaxNode>(
_syntaxFactory.VariableDeclarator(identifier, null, null)))));
}
else
{
......@@ -9503,7 +9505,7 @@ private ArgumentSyntax ParseArgumentExpression(bool isIndexer)
}
}
return _syntaxFactory.Argument(nameColon, refOrOutKeyword, expression, typeSyntax, identifier);
return _syntaxFactory.Argument(nameColon, refOrOutKeyword, expression);
}
private bool IsPossibleOutVarDeclaration()
......@@ -9789,8 +9791,7 @@ private ExpressionSyntax ParseCastOrParenExpressionOrLambdaOrTuple(Precedence pr
// ( <expr>, must be a tuple
if (this.CurrentToken.Kind == SyntaxKind.CommaToken)
{
var firstArg = _syntaxFactory.Argument(nameColon: null, refOrOutKeyword: default(SyntaxToken), expression: expression,
type: null, identifier: default(SyntaxToken));
var firstArg = _syntaxFactory.Argument(nameColon: null, refOrOutKeyword: default(SyntaxToken), expressionOrDeclaration: expression);
return ParseTupleExpressionTail(openParen, firstArg);
}
......@@ -9801,8 +9802,7 @@ private ExpressionSyntax ParseCastOrParenExpressionOrLambdaOrTuple(Precedence pr
var nameColon = _syntaxFactory.NameColon((IdentifierNameSyntax)expression, EatToken());
expression = ParseSubExpression(0);
var firstArg = _syntaxFactory.Argument(nameColon, refOrOutKeyword: default(SyntaxToken), expression: expression,
type: null, identifier: default(SyntaxToken));
var firstArg = _syntaxFactory.Argument(nameColon, refOrOutKeyword: default(SyntaxToken), expressionOrDeclaration: expression);
return ParseTupleExpressionTail(openParen, firstArg);
}
......@@ -9837,13 +9837,11 @@ private TupleExpressionSyntax ParseTupleExpressionTail(SyntaxToken openParen, Ar
var nameColon = _syntaxFactory.NameColon((IdentifierNameSyntax)expression, EatToken());
expression = ParseSubExpression(0);
arg = _syntaxFactory.Argument(nameColon, refOrOutKeyword: default(SyntaxToken), expression: expression,
type: null, identifier: default(SyntaxToken));
arg = _syntaxFactory.Argument(nameColon, refOrOutKeyword: default(SyntaxToken), expressionOrDeclaration: expression);
}
else
{
arg = _syntaxFactory.Argument(nameColon: null, refOrOutKeyword: default(SyntaxToken), expression: expression,
type: null, identifier: default(SyntaxToken));
arg = _syntaxFactory.Argument(nameColon: null, refOrOutKeyword: default(SyntaxToken), expressionOrDeclaration: expression);
}
list.Add(arg);
......
Microsoft.CodeAnalysis.CSharp.Conversion.IsTuple.get -> bool
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Identifier.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Type.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.WithIdentifier(Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.WithType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.ExpressionOrDeclaration.get -> Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken outKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.VariableDeclarationSyntax declaration) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode expressionOrDeclaration) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.VariableDeclaration.get -> Microsoft.CodeAnalysis.CSharp.Syntax.VariableDeclarationSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.WithExpressionOrDeclaration(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode expressionOrDeclaration) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.RefKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.WithRefKeyword(Microsoft.CodeAnalysis.SyntaxToken refKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax
......@@ -173,14 +172,13 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.TupleTypeSyntax.Accept(Microsoft.C
override Microsoft.CodeAnalysis.CSharp.Syntax.TupleTypeSyntax.Accept<TResult>(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult> visitor) -> TResult
override Microsoft.CodeAnalysis.CSharp.Syntax.WhenClauseSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
override Microsoft.CodeAnalysis.CSharp.Syntax.WhenClauseSyntax.Accept<TResult>(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult> visitor) -> TResult
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax declarationSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.ISymbol
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.DeclarationPatternSyntax declarationSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.ISymbol
static Microsoft.CodeAnalysis.CSharp.SyntaxExtensions.Update(this Microsoft.CodeAnalysis.CSharp.Syntax.IndexerDeclarationSyntax syntax, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax> attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifier, Microsoft.CodeAnalysis.SyntaxToken thisKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.BracketedParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.AccessorListSyntax accessorList) -> Microsoft.CodeAnalysis.CSharp.Syntax.IndexerDeclarationSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxExtensions.Update(this Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax syntax, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax> attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.CSharp.Syntax.ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifier, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax> constraintClauses, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument() -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken outKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.SyntaxToken outKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode expressionOrDeclaration) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken outKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.VariableDeclarationSyntax declaration) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode expressionOrDeclaration) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.SyntaxToken outKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.VariableDeclarationSyntax declaration) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ArrowExpressionClause(Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.CasePatternSwitchLabel(Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern, Microsoft.CodeAnalysis.CSharp.Syntax.WhenClauseSyntax whenClause, Microsoft.CodeAnalysis.SyntaxToken colonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.CasePatternSwitchLabelSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.CasePatternSwitchLabel(Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern, Microsoft.CodeAnalysis.SyntaxToken colonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.CasePatternSwitchLabelSyntax
......
......@@ -95,10 +95,10 @@ internal Binder Binder
Debug.Assert(declarationKind != LocalDeclarationKind.ForEachIterationVariable);
if (initializer == null)
{
if (identifierToken.Parent?.Kind() == SyntaxKind.Argument)
ArgumentSyntax argument;
if (ArgumentSyntax.IsIdentifierOfOutVariableDeclaration(identifierToken, out argument))
{
var argument = (ArgumentSyntax)identifierToken.Parent;
if (argument.Identifier == identifierToken && argument.Type.IsVar)
if (argument.Type.IsVar)
{
return new PossibleOutVarLocalSymbol(containingSymbol, binder, refKind, typeSyntax, identifierToken, declarationKind);
}
......@@ -537,12 +537,13 @@ private class PossibleOutVarLocalSymbol : SourceLocalSymbol
LocalDeclarationKind declarationKind)
: base(containingSymbol, binder, refKind, typeSyntax, identifierToken, declarationKind)
{
Debug.Assert(identifierToken.Parent.Kind() == SyntaxKind.Argument &&
((ArgumentSyntax)identifierToken.Parent).Identifier == identifierToken);
Debug.Assert(identifierToken.Parent.Parent.Parent is ConstructorInitializerSyntax ?
binder.ScopeDesignator == identifierToken.Parent.Parent :
binder.ScopeDesignator.Contains(identifierToken.Parent.Parent.Parent));
#if DEBUG
ArgumentSyntax argument;
Debug.Assert(ArgumentSyntax.IsIdentifierOfOutVariableDeclaration(identifierToken, out argument));
Debug.Assert(argument.Parent.Parent is ConstructorInitializerSyntax ?
binder.ScopeDesignator == argument.Parent :
binder.ScopeDesignator.Contains(argument.Parent.Parent));
#endif
}
protected override TypeSymbol InferTypeOfVarVariable(DiagnosticBag diagnostics)
......@@ -550,6 +551,8 @@ protected override TypeSymbol InferTypeOfVarVariable(DiagnosticBag diagnostics)
// Try binding immediately enclosing invocation expression, this should force the inference.
CSharpSyntaxNode invocation = (CSharpSyntaxNode)IdentifierToken.
Parent. // VariableDeclaratorSyntax
Parent. // VariableDeclarationSyntax
Parent. // ArgumentSyntax
Parent. // ArgumentListSyntax
Parent; // invocation/constructor initializer
......
// 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.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.Syntax
{
public partial class ArgumentSyntax
{
/// <summary>
/// Get expression representing the value of the argument.
/// </summary>
public ExpressionSyntax Expression
{
get
{
if (RefOrOutKeyword.Kind() != SyntaxKind.OutKeyword)
{
return (ExpressionSyntax)ExpressionOrDeclaration;
}
return ExpressionOrDeclaration as ExpressionSyntax;
}
}
public ArgumentSyntax WithExpression(ExpressionSyntax expression)
{
return this.Update(this.NameColon, this.RefOrOutKeyword, expression);
}
/// <summary>
/// Get declaration of an Out Variable for the argument.
/// </summary>
public VariableDeclarationSyntax VariableDeclaration
{
get
{
if (RefOrOutKeyword.Kind() != SyntaxKind.OutKeyword || ExpressionOrDeclaration.Kind() != SyntaxKind.VariableDeclaration)
{
return null;
}
return (VariableDeclarationSyntax)ExpressionOrDeclaration;
}
}
/// <summary>
/// Get identifier for out variable declaration, or default(SyntaxToken).
/// </summary>
internal SyntaxToken Identifier
{
get
{
VariableDeclarationSyntax declaration = VariableDeclaration;
if (declaration != null)
{
return declaration.Variables.First().Identifier;
}
return default(SyntaxToken);
}
}
/// <summary>
/// Get type syntax for out variable declaration, or null.
/// </summary>
internal TypeSyntax Type
{
get
{
VariableDeclarationSyntax declaration = VariableDeclaration;
if (declaration != null)
{
return declaration.Type;
}
return null;
}
}
public ArgumentSyntax Update(NameColonSyntax nameColon, SyntaxToken refOrOutKeyword, ExpressionSyntax expression)
{
return this.Update(nameColon, refOrOutKeyword, expression, type: null, identifier: default(SyntaxToken)) ;
return this.Update(nameColon, refOrOutKeyword, (CSharpSyntaxNode)expression) ;
}
public ArgumentSyntax Update(NameColonSyntax nameColon, SyntaxToken refOrOutKeyword, TypeSyntax type, SyntaxToken identifier)
public ArgumentSyntax Update(NameColonSyntax nameColon, SyntaxToken outKeyword, VariableDeclarationSyntax declaration)
{
return this.Update(nameColon, refOrOutKeyword, null, type, identifier);
if (outKeyword.Kind() != SyntaxKind.OutKeyword)
{
throw new ArgumentException(nameof(outKeyword));
}
if (declaration != null && !IsValidOutVariableDeclaration(declaration))
{
throw new ArgumentException(nameof(declaration));
}
return this.Update(nameColon, outKeyword, (CSharpSyntaxNode)declaration);
}
internal static bool IsValidOutVariableDeclaration(VariableDeclarationSyntax declaration)
{
return (declaration.Variables.Count == 1 &&
declaration.Variables.First().ArgumentList == null &&
declaration.Variables.First().Initializer == null);
}
internal static bool IsIdentifierOfOutVariableDeclaration(SyntaxToken identifier, out ArgumentSyntax declaringArgument)
{
Debug.Assert(identifier.Kind() == SyntaxKind.IdentifierToken || identifier.Kind() == SyntaxKind.None);
SyntaxNode parent;
if ((parent = identifier.Parent)?.Kind() == SyntaxKind.VariableDeclarator &&
(parent = parent.Parent)?.Kind() == SyntaxKind.VariableDeclaration &&
(parent = parent.Parent)?.Kind() == SyntaxKind.Argument)
{
var argument = (ArgumentSyntax)parent;
if (argument.Identifier == identifier)
{
declaringArgument = argument;
return true;
}
}
declaringArgument = null;
return false;
}
}
}
......@@ -1101,17 +1101,13 @@
<summary>SyntaxToken representing the optional ref or out keyword.</summary>
</PropertyComment>
</Field>
<Field Name="Expression" Type="ExpressionSyntax" Optional="true">
<PropertyComment>
<summary>ExpressionSyntax node representing the argument.</summary>
</PropertyComment>
</Field>
<Field Name="Type" Type="TypeSyntax" Optional="true"/>
<Field Name="Identifier" Type="SyntaxToken" Optional="true">
<Field Name="ExpressionOrDeclaration" Type="CSharpSyntaxNode" >
<PropertyComment>
<summary>Gets the identifier.</summary>
<summary>
ExpressionSyntax node representing the argument value,
or VariableDeclarationSyntax representing out local declaration.
</summary>
</PropertyComment>
<Kind Name="IdentifierToken"/>
</Field>
<TypeComment>
<summary>Class which represents the syntax node for argument.</summary>
......
......@@ -2517,10 +2517,7 @@ public static UsingDirectiveSyntax UsingDirective(NameEqualsSyntax alias, NameSy
/// <summary>Creates a new ArgumentSyntax instance.</summary>
public static ArgumentSyntax Argument(NameColonSyntax nameColon, SyntaxToken refOrOutKeyword, ExpressionSyntax expression)
{
if (expression == null)
throw new ArgumentNullException(nameof(expression));
return Argument(nameColon, refOrOutKeyword, expression, null, default(SyntaxToken));
return Argument(nameColon, refOrOutKeyword, (CSharpSyntaxNode)expression);
}
/// <summary>Creates a new ArgumentSyntax instance.</summary>
......@@ -2530,30 +2527,25 @@ public static ArgumentSyntax Argument(ExpressionSyntax expression)
}
/// <summary>Creates a new ArgumentSyntax instance.</summary>
public static ArgumentSyntax Argument(NameColonSyntax nameColon, SyntaxToken outKeyword, TypeSyntax type, SyntaxToken identifier)
public static ArgumentSyntax Argument(NameColonSyntax nameColon, SyntaxToken outKeyword, VariableDeclarationSyntax declaration)
{
if (outKeyword.Kind() != SyntaxKind.OutKeyword)
{
throw new ArgumentException(nameof(outKeyword));
}
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (identifier.Kind() != SyntaxKind.IdentifierToken)
if (declaration != null && !ArgumentSyntax.IsValidOutVariableDeclaration(declaration))
{
throw new ArgumentException(nameof(identifier));
throw new ArgumentException(nameof(declaration));
}
return Argument(nameColon, outKeyword, null, type, identifier);
return Argument(nameColon, outKeyword, (CSharpSyntaxNode)declaration);
}
/// <summary>Creates a new ArgumentSyntax instance.</summary>
public static ArgumentSyntax Argument(SyntaxToken outKeyword, TypeSyntax type, SyntaxToken identifier)
public static ArgumentSyntax Argument(SyntaxToken outKeyword, VariableDeclarationSyntax declaration)
{
return Argument(default(NameColonSyntax), outKeyword, type, identifier);
return Argument(default(NameColonSyntax), outKeyword, declaration);
}
}
}
......@@ -186,9 +186,6 @@ public static bool IsInTypeOnlyContext(ExpressionSyntax node)
case DeclarationPattern:
return ((DeclarationPatternSyntax)parent).Type == node;
case Argument:
return ((ArgumentSyntax)parent).Type == node;
}
}
......
......@@ -138,10 +138,11 @@ private static void VerifyModelForOutVar(SemanticModel model, ArgumentSyntax dec
private static void VerifyModelForOutVar(SemanticModel model, ArgumentSyntax decl, bool isDelegateCreation, params IdentifierNameSyntax[] references)
{
var symbol = model.GetDeclaredSymbol(decl);
var variableDeclaratorSyntax = GetVariableDeclarator(decl);
var symbol = model.GetDeclaredSymbol(variableDeclaratorSyntax);
Assert.Equal(decl.Identifier.ValueText, symbol.Name);
Assert.Equal(LocalDeclarationKind.RegularVariable, ((LocalSymbol)symbol).DeclarationKind);
Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)decl));
Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)variableDeclaratorSyntax));
Assert.Same(symbol, model.LookupSymbols(decl.SpanStart, name: decl.Identifier.ValueText).Single());
Assert.True(model.LookupNames(decl.SpanStart).Contains(decl.Identifier.ValueText));
......@@ -195,6 +196,11 @@ private static void VerifyModelForOutVar(SemanticModel model, ArgumentSyntax dec
}
}
private static VariableDeclaratorSyntax GetVariableDeclarator(ArgumentSyntax decl)
{
return decl.VariableDeclaration.Variables.Single();
}
private static bool FlowsIn(ExpressionSyntax dataFlowParent, ArgumentSyntax decl, IdentifierNameSyntax[] references)
{
foreach (var reference in references)
......@@ -1213,7 +1219,7 @@ struct var
var x1Decl = GetOutVarDeclaration(tree, "x1");
VerifyModelForOutVar(model, x1Decl);
Assert.Equal("Cls.var", ((LocalSymbol)model.GetDeclaredSymbol(x1Decl)).Type.ToTestDisplayString());
Assert.Equal("Cls.var", ((LocalSymbol)model.GetDeclaredSymbol(GetVariableDeclarator(x1Decl))).Type.ToTestDisplayString());
}
[Fact]
......@@ -1326,7 +1332,7 @@ static object Test1(out int x, out int x2)
VerifyModelForOutVar(model, x1Decl, x1Ref);
Assert.Null(model.GetAliasInfo(x1Decl.Type));
Assert.Equal("System.Int32 x1", model.GetDeclaredSymbol(x1Decl).ToTestDisplayString());
Assert.Equal("System.Int32 x1", model.GetDeclaredSymbol(GetVariableDeclarator(x1Decl)).ToTestDisplayString());
}
[Fact]
......@@ -1367,7 +1373,7 @@ static object Test1(out int x, int x2)
VerifyModelForOutVar(model, x1Decl, x1Ref);
Assert.Null(model.GetAliasInfo(x1Decl.Type));
Assert.Equal("System.Int32 x1", model.GetDeclaredSymbol(x1Decl).ToTestDisplayString());
Assert.Equal("System.Int32 x1", model.GetDeclaredSymbol(GetVariableDeclarator(x1Decl)).ToTestDisplayString());
}
[Fact]
......@@ -1410,7 +1416,7 @@ static void Test2(object x, object y)
VerifyModelForOutVar(model, x1Decl, x1Ref);
Assert.Null(model.GetAliasInfo(x1Decl.Type));
Assert.Equal("System.Int32 x1", model.GetDeclaredSymbol(x1Decl).ToTestDisplayString());
Assert.Equal("System.Int32 x1", model.GetDeclaredSymbol(GetVariableDeclarator(x1Decl)).ToTestDisplayString());
}
[Fact]
......@@ -1453,7 +1459,7 @@ static void Test2(object x, object y)
VerifyModelForOutVar(model, x1Decl, x1Ref);
Assert.Null(model.GetAliasInfo(x1Decl.Type));
Assert.Equal("System.Int32 x1", model.GetDeclaredSymbol(x1Decl).ToTestDisplayString());
Assert.Equal("System.Int32 x1", model.GetDeclaredSymbol(GetVariableDeclarator(x1Decl)).ToTestDisplayString());
}
[Fact]
......@@ -1492,7 +1498,7 @@ static void Test2(object x, object y)
VerifyModelForOutVar(model, x1Decl, x1Ref);
Assert.Null(model.GetAliasInfo(x1Decl.Type));
Assert.Equal("var x1", model.GetDeclaredSymbol(x1Decl).ToTestDisplayString());
Assert.Equal("var x1", model.GetDeclaredSymbol(GetVariableDeclarator(x1Decl)).ToTestDisplayString());
}
[Fact]
......@@ -1571,7 +1577,7 @@ static void Test2(object x, object y)
VerifyModelForOutVar(model, x1Decl, true, x1Ref);
Assert.Null(model.GetAliasInfo(x1Decl.Type));
Assert.Equal("var x1", model.GetDeclaredSymbol(x1Decl).ToTestDisplayString());
Assert.Equal("var x1", model.GetDeclaredSymbol(GetVariableDeclarator(x1Decl)).ToTestDisplayString());
}
[Fact]
......@@ -1787,7 +1793,7 @@ static void Test2(object x, object y)
VerifyModelForOutVar(model, x1Decl, x1Ref);
Assert.Null(model.GetAliasInfo(x1Decl.Type));
Assert.Equal("dynamic x1", model.GetDeclaredSymbol(x1Decl).ToTestDisplayString());
Assert.Equal("dynamic x1", model.GetDeclaredSymbol(GetVariableDeclarator(x1Decl)).ToTestDisplayString());
}
[Fact]
......@@ -1827,6 +1833,45 @@ static void Test2(object x, object y)
var varRef = GetReferences(tree, "var").Skip(1).Single();
VerifyModelForOutVar(model, varDecl, varRef);
}
[Fact]
public void SimpleVar_16()
{
var text = @"
public class Cls
{
public static void Main()
{
if (Test1(out var x1))
{
System.Console.WriteLine(x1);
}
}
static bool Test1(out int x)
{
x = 123;
return true;
}
}";
var compilation = CreateCompilationWithMscorlib(text,
options: TestOptions.ReleaseExe,
parseOptions: TestOptions.Regular.WithOutVarFeature());
CompileAndVerify(compilation, expectedOutput: @"123").VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = GetOutVarDeclaration(tree, "x1");
var x1Ref = GetReference(tree, "x1");
Assert.Equal("System.Int32", model.GetTypeInfo(x1Ref).Type.ToTestDisplayString());
VerifyModelForOutVar(model, x1Decl, x1Ref);
Assert.Null(model.GetAliasInfo(x1Decl.Type));
}
[Fact]
public void VarAndBetterness_01()
......
......@@ -1183,6 +1183,7 @@ public static bool IsParameterTypeContext(this SyntaxTree syntaxTree, int positi
{
// cases:
// const var
// out var
// for (var
// foreach (var
// using (var
......@@ -1198,6 +1199,13 @@ public static bool IsParameterTypeContext(this SyntaxTree syntaxTree, int positi
return true;
}
if (token.IsKind(SyntaxKind.OutKeyword) &&
token.Parent.IsKind(SyntaxKind.Argument) &&
((ArgumentSyntax)token.Parent).VariableDeclaration != null)
{
return true;
}
if (token.IsKind(SyntaxKind.OpenParenToken))
{
var previous = token.GetPreviousToken(includeSkipped: true);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册