提交 ee2f9864 编写于 作者: C Cyrus Najmabadi

Merge remote-tracking branch 'upstream/master' into conflictMarkerFixAll

......@@ -5,6 +5,8 @@
<clear />
<add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" />
<add key="dotnet5" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json" />
<add key="system-commandline" value="https://dotnet.myget.org/F/system-commandline/api/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="myget-dotnet-coreclr" value="https://dotnet.myget.org/F/dotnet-coreclr/api/v3/index.json" />
......@@ -12,9 +14,6 @@
<add key="dotnet-corefxtestdata" value="https://dotnet.myget.org/F/dotnet-corefxtestdata/api/v3/index.json" />
<add key="dotnet-buildtools" value="https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json" />
<add key="experimental-vs-packages" value="https://dotnet.myget.org/F/experimental-vs-packages/api/v3/index.json" />
<add key="symreader" value="https://dotnet.myget.org/F/symreader/api/v3/index.json" />
<add key="symreader-portable" value="https://dotnet.myget.org/F/symreader-portable/api/v3/index.json" />
<add key="symreader-converter" value="https://dotnet.myget.org/F/symreader-converter/api/v3/index.json" />
<add key="symreader-native" value="https://dotnet.myget.org/F/symreader-native/api/v3/index.json" />
<add key="metadata-tools" value="https://dotnet.myget.org/F/metadata-tools/api/v3/index.json" />
<add key="interactive-window" value="https://dotnet.myget.org/F/interactive-window/api/v3/index.json" />
......@@ -22,7 +21,6 @@
<add key="roslyn-tools" value="https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json" />
<add key="roslyn-analyzers" value="https://dotnet.myget.org/F/roslyn-analyzers/api/v3/index.json" />
<add key="roslyn" value="https://dotnet.myget.org/F/roslyn/api/v3/index.json" />
<add key="sourcelink" value="https://dotnet.myget.org/F/sourcelink/api/v3/index.json" />
<add key="vs-devcore" value="https://myget.org/F/vs-devcore/api/v3/index.json" />
<add key="vs-editor" value="https://myget.org/F/vs-editor/api/v3/index.json" />
<add key="roslyn_concord" value="https://myget.org/F/roslyn_concord/api/v3/index.json" />
......
......@@ -3,9 +3,9 @@
<ProductDependencies>
</ProductDependencies>
<ToolsetDependencies>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20129.1">
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20151.1">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>86e54fb5076d46a6f959f0329d53c1c72e2280df</Sha>
<Sha>8ccad075bbb0db445e03eed0a6073d27bdd4f31a</Sha>
</Dependency>
</ToolsetDependencies>
</Dependencies>
......@@ -69,8 +69,8 @@
<MicrosoftDiagnosticsRuntimeVersion>0.8.31-beta</MicrosoftDiagnosticsRuntimeVersion>
<MicrosoftDiagnosticsTracingTraceEventVersion>1.0.35</MicrosoftDiagnosticsTracingTraceEventVersion>
<MicrosoftDiaSymReaderVersion>1.3.0</MicrosoftDiaSymReaderVersion>
<MicrosoftDiaSymReaderConverterVersion>1.1.0-beta2-19409-01</MicrosoftDiaSymReaderConverterVersion>
<MicrosoftDiaSymReaderConverterXmlVersion>1.1.0-beta2-19409-01</MicrosoftDiaSymReaderConverterXmlVersion>
<MicrosoftDiaSymReaderConverterVersion>1.1.0-beta2-20115-01</MicrosoftDiaSymReaderConverterVersion>
<MicrosoftDiaSymReaderConverterXmlVersion>1.1.0-beta2-20115-01</MicrosoftDiaSymReaderConverterXmlVersion>
<MicrosoftDiaSymReaderNativeVersion>1.7.0</MicrosoftDiaSymReaderNativeVersion>
<MicrosoftDiaSymReaderPortablePdbVersion>1.5.0</MicrosoftDiaSymReaderPortablePdbVersion>
<MicrosoftDotNetVersionToolsVersion>3.0.0-preview1-03617-02</MicrosoftDotNetVersionToolsVersion>
......
......@@ -7,6 +7,6 @@
"xcopy-msbuild": "16.4.0-alpha"
},
"msbuild-sdks": {
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20129.1"
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20151.1"
}
}
......@@ -746,7 +746,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Property
''' <summary>
''' True if integer overflow checking is off.
''' True if integer overflow checking is On.
''' </summary>
Public Overridable ReadOnly Property CheckOverflow As Boolean
Get
......
......@@ -67,14 +67,10 @@ protected override void TryCompleteTag(ITextView textView, ITextBuffer subjectBu
// We need to check for non-trivia XML text tokens after $$ that match the expected end tag text.
if (token.Parent.IsKind(SyntaxKind.XmlElementEndTag) &&
token.Parent.IsParentKind(SyntaxKind.XmlElement))
token.Parent.IsParentKind(SyntaxKind.XmlElement, out XmlElementSyntax parentElement) &&
!HasFollowingEndTagTrivia(parentElement, token))
{
var parentElement = token.Parent.Parent as XmlElementSyntax;
if (!HasFollowingEndTagTrivia(parentElement, token))
{
CheckNameAndInsertText(textView, subjectBuffer, position, parentElement.StartTag, null, "{0}>");
}
CheckNameAndInsertText(textView, subjectBuffer, position, parentElement.StartTag, null, "{0}>");
}
}
}
......
......@@ -4851,6 +4851,32 @@ void Test()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTemporary)]
[WorkItem(18322, "https://github.com/dotnet/roslyn/issues/18322")]
public async Task TestInlineIntoExtensionMethodInvokedOnThis()
{
await TestInRegularAndScriptAsync(
@"public class Class1
{
void M()
{
var [|c|] = 8;
this.DoStuff(c);
}
}
public static class Class1Extensions { public static void DoStuff(this Class1 c, int x) { } }",
@"public class Class1
{
void M()
{
this.DoStuff(8);
}
}
public static class Class1Extensions { public static void DoStuff(this Class1 c, int x) { } }");
}
[WorkItem(8716, "https://github.com/dotnet/roslyn/issues/8716")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTemporary)]
public async Task DoNotQualifyInlinedLocalFunction()
......
......@@ -757,6 +757,136 @@ int Goo()
return v();
}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInvokeDelegateWithConditionalAccess)]
[WorkItem(13226, "https://github.com/dotnet/roslyn/issues/13226")]
public async Task TestWithLambdaInitializer()
{
await TestInRegularAndScript1Async(
@"
using System;
class C
{
void Goo()
{
Action v = () => {};
[||]if (v != null)
{
v();
}
}
}",
@"
using System;
class C
{
void Goo()
{
Action v = () => {};
v?.Invoke();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInvokeDelegateWithConditionalAccess)]
[WorkItem(13226, "https://github.com/dotnet/roslyn/issues/13226")]
public async Task TestWithLambdaInitializer2()
{
await TestInRegularAndScript1Async(
@"
using System;
class C
{
void Goo()
{
Action v = (() => {});
[||]if (v != null)
{
v();
}
}
}",
@"
using System;
class C
{
void Goo()
{
Action v = (() => {});
v?.Invoke();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInvokeDelegateWithConditionalAccess)]
[WorkItem(13226, "https://github.com/dotnet/roslyn/issues/13226")]
public async Task TestForWithAnonymousMethod()
{
await TestInRegularAndScript1Async(
@"
using System;
class C
{
void Goo()
{
Action v = delegate {};
[||]if (v != null)
{
v();
}
}
}",
@"
using System;
class C
{
void Goo()
{
Action v = delegate {};
v?.Invoke();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInvokeDelegateWithConditionalAccess)]
[WorkItem(13226, "https://github.com/dotnet/roslyn/issues/13226")]
public async Task TestWithMethodReference()
{
await TestInRegularAndScript1Async(
@"
using System;
class C
{
void Goo()
{
Action v = Console.WriteLine;
[||]if (v != null)
{
v();
}
}
}",
@"
using System;
class C
{
void Goo()
{
Action v = Console.WriteLine;
v?.Invoke();
}
}");
}
}
......
......@@ -3081,5 +3081,29 @@ static void Main(string[] args)
await TestAsync(text, "global::System.Object", mode);
}
[WorkItem(14277, "https://github.com/dotnet/roslyn/issues/14277")]
[Theory, CombinatorialData, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestValueInNestedTuple1(TestMode mode)
{
await TestInMethodAsync(
@"(int, (string, bool)) x = ([|Goo()|], ("""", true));", "global::System.Int32", mode);
}
[WorkItem(14277, "https://github.com/dotnet/roslyn/issues/14277")]
[Theory, CombinatorialData, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestValueInNestedTuple2(TestMode mode)
{
await TestInMethodAsync(
@"(int, (string, bool)) x = (1, ("""", [|Goo()|]));", "global::System.Boolean", mode);
}
[WorkItem(14277, "https://github.com/dotnet/roslyn/issues/14277")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestValueInNestedTuple3()
{
await TestInMethodAsync(
@"(int, string) x = (1, [||]);", "global::System.String", TestMode.Position);
}
}
}
......@@ -700,6 +700,20 @@ End Class
Await TestInMethodAsync(text, "System.Int32", mode)
End Function
<WorkItem(14277, "https://github.com/dotnet/roslyn/issues/14277")>
<Theory, CombinatorialData, Trait(Traits.Feature, Traits.Features.TypeInferenceService)>
Public Async Function TestValueInNestedTuple1(mode As TestMode) As Task
Await TestInMethodAsync(
"dim x as (integer, (string, boolean)) = ([|Goo()|], ("""", true));", "global::System.Int32", mode)
End Function
<WorkItem(14277, "https://github.com/dotnet/roslyn/issues/14277")>
<Theory, CombinatorialData, Trait(Traits.Feature, Traits.Features.TypeInferenceService)>
Public Async Function TestValueInNestedTuple2(mode As TestMode) As Task
Await TestInMethodAsync(
"dim x as (integer, (string, boolean)) = (1, ("""", [|Goo()|]))", "global::System.Boolean", mode)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)>
<WorkItem(643, "https://github.com/dotnet/roslyn/issues/643")>
Public Async Function TestAwaitExpressionWithChainingMethod() As Task
......
......@@ -150,23 +150,21 @@ private static TypeSyntax TryGetDeclarationTypeToFix(SyntaxNode node)
}
// string x { get; set; } = null;
if (node.Parent.IsParentKind(SyntaxKind.PropertyDeclaration) == true)
if (node.Parent.IsParentKind(SyntaxKind.PropertyDeclaration, out PropertyDeclarationSyntax propertyDeclaration))
{
var propertyDeclaration = (PropertyDeclarationSyntax)node.Parent.Parent;
return propertyDeclaration.Type;
}
// void M(string x = null) { }
if (node.Parent.IsParentKind(SyntaxKind.Parameter) == true)
if (node.Parent.IsParentKind(SyntaxKind.Parameter, out ParameterSyntax parameter))
{
var parameter = (ParameterSyntax)node.Parent.Parent;
return parameter.Type;
}
// static string M() => null;
if (node.IsParentKind(SyntaxKind.ArrowExpressionClause) && node.Parent.IsParentKind(SyntaxKind.MethodDeclaration))
if (node.IsParentKind(SyntaxKind.ArrowExpressionClause) &&
node.Parent.IsParentKind(SyntaxKind.MethodDeclaration, out MethodDeclarationSyntax arrowMethod))
{
var arrowMethod = (MethodDeclarationSyntax)node.Parent.Parent;
return arrowMethod.ReturnType;
}
......
......@@ -52,13 +52,12 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
return;
}
if (!variableDeclarator.IsParentKind(SyntaxKind.VariableDeclaration) ||
if (!variableDeclarator.IsParentKind(SyntaxKind.VariableDeclaration, out VariableDeclarationSyntax variableDeclaration) ||
!variableDeclarator.Parent.IsParentKind(SyntaxKind.LocalDeclarationStatement))
{
return;
}
var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent;
if (variableDeclarator.Initializer == null ||
variableDeclarator.Initializer.Value.IsMissing ||
variableDeclarator.Initializer.Value.IsKind(SyntaxKind.StackAllocArrayCreationExpression))
......@@ -132,9 +131,8 @@ private static bool HasConflict(IdentifierNameSyntax identifier, VariableDeclara
identifierNode = identifier;
}
if (identifierNode.IsParentKind(SyntaxKind.Argument))
if (identifierNode.IsParentKind(SyntaxKind.Argument, out ArgumentSyntax argument))
{
var argument = (ArgumentSyntax)identifierNode.Parent;
if (argument.RefOrOutKeyword.Kind() != SyntaxKind.None)
{
return true;
......@@ -385,11 +383,9 @@ private SyntaxNode RemoveDeclaratorFromScope(VariableDeclaratorSyntax variableDe
// If the local is parented by a label statement, we can't remove this statement. Instead,
// we'll replace the local declaration with an empty expression statement.
if (newLocalDeclaration.IsParentKind(SyntaxKind.LabeledStatement))
if (newLocalDeclaration.IsParentKind(SyntaxKind.LabeledStatement, out LabeledStatementSyntax labeledStatement))
{
var labeledStatement = (LabeledStatementSyntax)newLocalDeclaration.Parent;
var newLabeledStatement = labeledStatement.ReplaceNode(newLocalDeclaration, SyntaxFactory.ParseStatement(""));
return newScope.ReplaceNode(labeledStatement, newLabeledStatement);
}
......@@ -582,9 +578,9 @@ private static bool IsInDeconstructionAssignmentLeft(ExpressionSyntax node)
{
return false;
}
else if (parent.IsParentKind(SyntaxKind.SimpleAssignmentExpression))
else if (parent.IsParentKind(SyntaxKind.SimpleAssignmentExpression, out AssignmentExpressionSyntax assignment))
{
return ((AssignmentExpressionSyntax)parent.Parent).Left == parent;
return assignment.Left == parent;
}
parent = parent.Parent;
......
......@@ -251,15 +251,17 @@ private bool IsAttributeValueContext(SyntaxToken token, out string tagName, out
{
XmlAttributeSyntax attributeSyntax = null;
if (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute))
if (token.Parent.IsKind(SyntaxKind.IdentifierName) &&
token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute, out XmlNameAttributeSyntax xmlName))
{
// Handle the special 'name' attributes: name="bar$$
attributeSyntax = (XmlNameAttributeSyntax)token.Parent.Parent;
attributeSyntax = xmlName;
}
else if (token.IsKind(SyntaxKind.XmlTextLiteralToken) && token.Parent.IsKind(SyntaxKind.XmlTextAttribute))
else if (token.IsKind(SyntaxKind.XmlTextLiteralToken) &&
token.Parent.IsKind(SyntaxKind.XmlTextAttribute, out XmlTextAttributeSyntax xmlText))
{
// Handle the other general text attributes: foo="bar$$
attributeSyntax = (XmlTextAttributeSyntax)token.Parent;
attributeSyntax = xmlText;
}
else if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) || token.Parent.IsKind(SyntaxKind.XmlTextAttribute))
{
......
......@@ -287,13 +287,13 @@ bool TryProcessLocalDeclarationStatement(LocalDeclarationStatementSyntax localDe
.Where(statement => Equals(semanticModel.GetEnclosingSymbol(
statement.SpanStart, cancellationToken), memberDeclarationSymbol)).Count();
if (forEachInfo.ForEachStatement.IsParentKind(SyntaxKind.Block) &&
if (forEachInfo.ForEachStatement.IsParentKind(SyntaxKind.Block, out BlockSyntax block) &&
forEachInfo.ForEachStatement.Parent.Parent == memberDeclarationSyntax)
{
// Check that
// a. There are either just a single 'yield return' or 'yield return' with 'yield break' just after.
// b. Those foreach and 'yield break' (if exists) are last statements in the method (do not count local function declaration statements).
var statementsOnBlockWithForEach = ((BlockSyntax)forEachInfo.ForEachStatement.Parent).Statements
var statementsOnBlockWithForEach = block.Statements
.Where(statement => statement.Kind() != SyntaxKind.LocalFunctionStatement).ToArray();
var lastNonLocalFunctionStatement = statementsOnBlockWithForEach.Last();
if (yieldStatementsCount == 1 && lastNonLocalFunctionStatement == forEachInfo.ForEachStatement)
......
......@@ -79,13 +79,10 @@ private void AddCatchParameters()
var block = GetImmediatelyContainingBlock();
// if we're the start of a "catch(Goo e)" clause, then add "e".
if (block != null && block.IsParentKind(SyntaxKind.CatchClause))
if (block != null && block.IsParentKind(SyntaxKind.CatchClause, out CatchClauseSyntax catchClause) &&
catchClause.Declaration != null && catchClause.Declaration.Identifier.Kind() != SyntaxKind.None)
{
var catchClause = (CatchClauseSyntax)block.Parent;
if (catchClause.Declaration != null && catchClause.Declaration.Identifier.Kind() != SyntaxKind.None)
{
_expressions.Add(catchClause.Declaration.Identifier.ValueText);
}
_expressions.Add(catchClause.Declaration.Identifier.ValueText);
}
}
......
......@@ -43,9 +43,8 @@ public CSharpGenerateDefaultConstructorsService()
var node = semanticDocument.Root.FindToken(textSpan.Start).GetAncestor<TypeSyntax>();
if (node != null)
{
if (node.Parent is BaseTypeSyntax && node.Parent.IsParentKind(SyntaxKind.BaseList))
if (node.Parent is BaseTypeSyntax && node.Parent.IsParentKind(SyntaxKind.BaseList, out BaseListSyntax baseList))
{
var baseList = (BaseListSyntax)node.Parent.Parent;
if (baseList.Types.Count > 0 &&
baseList.Types[0].Type == node &&
baseList.IsParentKind(SyntaxKind.ClassDeclaration))
......
......@@ -107,9 +107,8 @@ protected override bool IsValidSymbol(ISymbol symbol, SemanticModel semanticMode
if (memberAccess == null || memberAccess.Name == simpleName)
{
if (simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression))
if (simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression, out invocationExpressionOpt))
{
invocationExpressionOpt = (InvocationExpressionSyntax)simpleNameOrMemberAccessExpression.Parent;
isInConditionalAccessExpression = inConditionalMemberAccess;
return !invocationExpressionOpt.ArgumentList.CloseParenToken.IsMissing;
}
......
......@@ -62,9 +62,8 @@ protected override bool IsArrayElementType(ExpressionSyntax expression)
ExpressionSyntax expression,
CancellationToken cancellationToken)
{
if (expression is TypeSyntax && expression.IsParentKind(SyntaxKind.TypeArgumentList))
if (expression is TypeSyntax && expression.IsParentKind(SyntaxKind.TypeArgumentList, out TypeArgumentListSyntax typeArgumentList))
{
var typeArgumentList = (TypeArgumentListSyntax)expression.Parent;
var symbolInfo = semanticModel.GetSymbolInfo(typeArgumentList.Parent, cancellationToken);
var symbol = symbolInfo.GetAnySymbol();
if (symbol.IsConstructor())
......@@ -94,12 +93,10 @@ protected override bool IsArrayElementType(ExpressionSyntax expression)
protected override bool IsInInterfaceList(ExpressionSyntax expression)
{
if (expression is TypeSyntax &&
expression.Parent is BaseTypeSyntax &&
expression.Parent.IsParentKind(SyntaxKind.BaseList) &&
((BaseTypeSyntax)expression.Parent).Type == expression)
expression.Parent is BaseTypeSyntax baseType &&
expression.Parent.IsParentKind(SyntaxKind.BaseList, out BaseListSyntax baseList) &&
baseType.Type == expression)
{
var baseList = (BaseListSyntax)expression.Parent.Parent;
// If it's after the first item, then it's definitely an interface.
if (baseList.Types[0] != expression.Parent)
{
......@@ -114,11 +111,9 @@ protected override bool IsInInterfaceList(ExpressionSyntax expression)
}
if (expression is TypeSyntax &&
expression.IsParentKind(SyntaxKind.TypeConstraint) &&
expression.Parent.IsParentKind(SyntaxKind.TypeParameterConstraintClause))
expression.IsParentKind(SyntaxKind.TypeConstraint, out TypeConstraintSyntax typeConstraint) &&
expression.Parent.IsParentKind(SyntaxKind.TypeParameterConstraintClause, out TypeParameterConstraintClauseSyntax constraintClause))
{
var typeConstraint = (TypeConstraintSyntax)expression.Parent;
var constraintClause = (TypeParameterConstraintClauseSyntax)typeConstraint.Parent;
var index = constraintClause.Constraints.IndexOf(typeConstraint);
// If it's after the first item, then it's definitely an interface.
......
......@@ -32,9 +32,9 @@ public CSharpImplementInterfaceService()
{
if (!cancellationToken.IsCancellationRequested)
{
if (node is TypeSyntax interfaceNode && interfaceNode.Parent is BaseTypeSyntax &&
if (node is TypeSyntax interfaceNode && interfaceNode.Parent is BaseTypeSyntax baseType &&
interfaceNode.Parent.IsParentKind(SyntaxKind.BaseList) &&
((BaseTypeSyntax)interfaceNode.Parent).Type == interfaceNode)
baseType.Type == interfaceNode)
{
if (interfaceNode.Parent.Parent.IsParentKind(SyntaxKind.ClassDeclaration) ||
interfaceNode.Parent.Parent.IsParentKind(SyntaxKind.StructDeclaration))
......
......@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.InvokeDelegateWithConditionalAccess
......@@ -265,6 +266,21 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
// Syntactically this looks good. Now make sure that the local is a delegate type.
var semanticModel = syntaxContext.SemanticModel;
// The initializer can't be inlined if it's an actual lambda/method reference.
// These cannot be invoked with `?.` (only delegate *values* can be).
var initializer = declarator.Initializer.Value.WalkDownParentheses();
if (initializer.IsAnyLambdaOrAnonymousMethod())
{
return false;
}
var initializerSymbol = semanticModel.GetSymbolInfo(initializer, cancellationToken).GetAnySymbol();
if (initializerSymbol is IMethodSymbol)
{
return false;
}
var localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(declarator, cancellationToken);
// Ok, we made a local just to check it for null and invoke it. Looks like something
......
......@@ -85,8 +85,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
var anonymousFunction = (AnonymousFunctionExpressionSyntax)syntaxContext.Node;
var semanticModel = syntaxContext.SemanticModel;
if (!CheckForPattern(semanticModel, anonymousFunction, cancellationToken,
out var localDeclaration))
if (!CheckForPattern(anonymousFunction, out var localDeclaration))
{
return;
}
......@@ -170,10 +169,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
}
private bool CheckForPattern(
SemanticModel semanticModel,
AnonymousFunctionExpressionSyntax anonymousFunction,
CancellationToken cancellationToken,
out LocalDeclarationStatementSyntax localDeclaration)
AnonymousFunctionExpressionSyntax anonymousFunction, out LocalDeclarationStatementSyntax localDeclaration)
{
// Look for:
//
......@@ -182,24 +178,20 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
//
// Type t = null;
// t = <anonymous function>
return CheckForSimpleLocalDeclarationPattern(semanticModel, anonymousFunction, cancellationToken, out localDeclaration) ||
CheckForCastedLocalDeclarationPattern(semanticModel, anonymousFunction, cancellationToken, out localDeclaration) ||
CheckForLocalDeclarationAndAssignment(semanticModel, anonymousFunction, cancellationToken, out localDeclaration);
return CheckForSimpleLocalDeclarationPattern(anonymousFunction, out localDeclaration) ||
CheckForCastedLocalDeclarationPattern(anonymousFunction, out localDeclaration) ||
CheckForLocalDeclarationAndAssignment(anonymousFunction, out localDeclaration);
}
private bool CheckForSimpleLocalDeclarationPattern(
SemanticModel semanticModel,
AnonymousFunctionExpressionSyntax anonymousFunction,
CancellationToken cancellationToken,
out LocalDeclarationStatementSyntax localDeclaration)
AnonymousFunctionExpressionSyntax anonymousFunction, out LocalDeclarationStatementSyntax localDeclaration)
{
// Type t = <anonymous function>
if (anonymousFunction.IsParentKind(SyntaxKind.EqualsValueClause) &&
anonymousFunction.Parent.IsParentKind(SyntaxKind.VariableDeclarator) &&
anonymousFunction.Parent.Parent.IsParentKind(SyntaxKind.VariableDeclaration) &&
anonymousFunction.Parent.Parent.Parent.IsParentKind(SyntaxKind.LocalDeclarationStatement))
anonymousFunction.Parent.Parent.Parent.IsParentKind(SyntaxKind.LocalDeclarationStatement, out localDeclaration))
{
localDeclaration = (LocalDeclarationStatementSyntax)anonymousFunction.Parent.Parent.Parent.Parent;
if (!localDeclaration.Declaration.Type.IsVar)
{
return true;
......@@ -295,10 +287,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
}
private bool CheckForCastedLocalDeclarationPattern(
SemanticModel semanticModel,
AnonymousFunctionExpressionSyntax anonymousFunction,
CancellationToken cancellationToken,
out LocalDeclarationStatementSyntax localDeclaration)
AnonymousFunctionExpressionSyntax anonymousFunction, out LocalDeclarationStatementSyntax localDeclaration)
{
// var t = (Type)(<anonymous function>)
var containingStatement = anonymousFunction.GetAncestor<StatementSyntax>();
......@@ -327,22 +316,16 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
}
private bool CheckForLocalDeclarationAndAssignment(
SemanticModel semanticModel,
AnonymousFunctionExpressionSyntax anonymousFunction,
CancellationToken cancellationToken,
out LocalDeclarationStatementSyntax localDeclaration)
AnonymousFunctionExpressionSyntax anonymousFunction, out LocalDeclarationStatementSyntax localDeclaration)
{
// Type t = null;
// t = <anonymous function>
if (anonymousFunction.IsParentKind(SyntaxKind.SimpleAssignmentExpression) &&
anonymousFunction.Parent.IsParentKind(SyntaxKind.ExpressionStatement) &&
anonymousFunction.Parent.Parent.IsParentKind(SyntaxKind.Block))
if (anonymousFunction.IsParentKind(SyntaxKind.SimpleAssignmentExpression, out AssignmentExpressionSyntax assignment) &&
anonymousFunction.Parent.IsParentKind(SyntaxKind.ExpressionStatement, out ExpressionStatementSyntax expressionStatement) &&
anonymousFunction.Parent.Parent.IsParentKind(SyntaxKind.Block, out BlockSyntax block))
{
var assignment = (AssignmentExpressionSyntax)anonymousFunction.Parent;
if (assignment.Left.IsKind(SyntaxKind.IdentifierName))
{
var expressionStatement = (ExpressionStatementSyntax)assignment.Parent;
var block = (BlockSyntax)expressionStatement.Parent;
var expressionStatementIndex = block.Statements.IndexOf(expressionStatement);
if (expressionStatementIndex >= 1)
{
......
......@@ -3587,8 +3587,8 @@ private static bool IsAutoImplementedProperty(PropertyDeclarationSyntax property
private static bool IsExtensionMethod(MethodDeclarationSyntax methodDeclaration)
{
if (!methodDeclaration.IsParentKind(SyntaxKind.ClassDeclaration) ||
!((ClassDeclarationSyntax)methodDeclaration.Parent).Modifiers.Any(SyntaxKind.StaticKeyword))
if (!methodDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, out ClassDeclarationSyntax classDecl) ||
!classDecl.Modifiers.Any(SyntaxKind.StaticKeyword))
{
return false;
}
......
......@@ -16,17 +16,17 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
[Export(typeof(IOptionPersister))]
internal class CommentTaskTokenSerializer : IOptionPersister
{
private readonly VisualStudioWorkspace _workspace;
private readonly ITaskList _taskList;
private readonly IGlobalOptionService _globalOptionService;
private string _lastCommentTokenCache = null;
[ImportingConstructor]
public CommentTaskTokenSerializer(
VisualStudioWorkspace workspace,
IGlobalOptionService globalOptionService,
[Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
{
_workspace = workspace;
_globalOptionService = globalOptionService;
// The SVsTaskList may not be available or doesn't actually implement ITaskList
// in the "devenv /build" scenario
......@@ -68,8 +68,7 @@ private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
var commentString = GetTaskTokenList(_taskList);
var optionSet = _workspace.Options;
var optionValue = optionSet.GetOption(TodoCommentOptions.TokenList);
var optionValue = _globalOptionService.GetOption(TodoCommentOptions.TokenList);
if (optionValue == commentString)
{
return;
......@@ -79,7 +78,7 @@ private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
_lastCommentTokenCache = commentString;
// let people to know that comment string has changed
_workspace.SetOptions(optionSet.WithChangedOption(TodoCommentOptions.TokenList, _lastCommentTokenCache));
_globalOptionService.RefreshOption(TodoCommentOptions.TokenList, _lastCommentTokenCache);
}
private static string GetTaskTokenList(ITaskList taskList)
......
......@@ -75,12 +75,12 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
var method = compilerFailFast.GetMethod(nameof(FailFast.OnFatalException), BindingFlags.Static | BindingFlags.NonPublic);
property.SetValue(null, Delegate.CreateDelegate(property.PropertyType, method));
_workspace = _componentModel.GetService<VisualStudioWorkspace>();
_workspace.Services.GetService<IExperimentationService>();
// Ensure the options persisters are loaded since we have to fetch options from the shell
_componentModel.GetExtensions<IOptionPersister>();
_workspace = _componentModel.GetService<VisualStudioWorkspace>();
_workspace.Services.GetService<IExperimentationService>();
RoslynTelemetrySetup.Initialize(this);
InitializeColors();
......
......@@ -71,13 +71,11 @@ private bool CouldBeGenericType(SyntaxToken identifier)
return false;
}
if (identifierName.IsMemberAccessExpressionName())
// ?.X.Identifier or ?.X.Y.Identifier is never a generic type.
if (identifierName.IsMemberAccessExpressionName() &&
identifier.Parent.IsParentKind(SyntaxKind.ConditionalAccessExpression))
{
// ?.X.Identifier or ?.X.Y.Identifier is never a generic type.
if (identifier.Parent.IsParentKind(SyntaxKind.ConditionalAccessExpression))
{
return false;
}
return false;
}
// Add more cases as necessary.
......
......@@ -35,9 +35,8 @@ internal static class DefaultExpressionSyntaxExtensions
private static bool? CanReplaceWithDefaultLiteralFast(
DefaultExpressionSyntax defaultExpression, SemanticModel semanticModel, CancellationToken cancellationToken)
{
if (defaultExpression.IsParentKind(SyntaxKind.EqualsValueClause))
if (defaultExpression.IsParentKind(SyntaxKind.EqualsValueClause, out EqualsValueClauseSyntax equalsValueClause))
{
var equalsValueClause = (EqualsValueClauseSyntax)defaultExpression.Parent;
var typeSyntax = GetTypeSyntax(equalsValueClause);
if (typeSyntax != null)
......@@ -66,14 +65,12 @@ internal static class DefaultExpressionSyntaxExtensions
private static TypeSyntax GetTypeSyntax(EqualsValueClauseSyntax equalsValueClause)
{
if (equalsValueClause.IsParentKind(SyntaxKind.VariableDeclarator) &&
equalsValueClause.Parent.IsParentKind(SyntaxKind.VariableDeclaration))
equalsValueClause.Parent.IsParentKind(SyntaxKind.VariableDeclaration, out VariableDeclarationSyntax declaration))
{
var declaration = (VariableDeclarationSyntax)equalsValueClause.Parent.Parent;
return declaration.Type;
}
else if (equalsValueClause.IsParentKind(SyntaxKind.Parameter))
else if (equalsValueClause.IsParentKind(SyntaxKind.Parameter, out ParameterSyntax parameter))
{
var parameter = (ParameterSyntax)equalsValueClause.Parent;
return parameter.Type;
}
......
......@@ -299,30 +299,14 @@ private bool IsExpandWithinMultiLineLambda(SyntaxNode node)
return true;
}
if (node.IsParentKind(SyntaxKind.ParenthesizedLambdaExpression))
if (node.IsParentKind(SyntaxKind.ParenthesizedLambdaExpression, out ParenthesizedLambdaExpressionSyntax parenLambda))
{
var parent = (ParenthesizedLambdaExpressionSyntax)node;
if (ReferenceEquals(parent.ParameterList, node))
{
return true;
}
else
{
return false;
}
return ReferenceEquals(parenLambda.ParameterList, node);
}
if (node.IsParentKind(SyntaxKind.SimpleLambdaExpression))
if (node.IsParentKind(SyntaxKind.SimpleLambdaExpression, out SimpleLambdaExpressionSyntax simpleLambda))
{
var parent = (SimpleLambdaExpressionSyntax)node;
if (ReferenceEquals(parent.Parameter, node))
{
return true;
}
else
{
return false;
}
return ReferenceEquals(simpleLambda.Parameter, node);
}
return true;
......
......@@ -84,9 +84,8 @@ private bool IsPassedToDelegateCreationExpression(ArgumentSyntax argument, IType
{
if (type.IsDelegateType() &&
argument.IsParentKind(SyntaxKind.ArgumentList) &&
argument.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression))
argument.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression, out ObjectCreationExpressionSyntax objectCreationExpression))
{
var objectCreationExpression = (ObjectCreationExpressionSyntax)argument.Parent.Parent;
var objectCreationType = _semanticModel.GetTypeInfo(objectCreationExpression).Type;
if (objectCreationType.Equals(type))
{
......
......@@ -482,9 +482,9 @@ private static bool IsThisOrTypeOrNamespace(MemberAccessExpressionSyntax memberA
var symbol = semanticModel.GetSymbolInfo(memberAccess.Name).Symbol;
if (previousToken.Kind() == SyntaxKind.OpenParenToken &&
previousToken.Parent.IsKind(SyntaxKind.ParenthesizedExpression) &&
previousToken.Parent.IsKind(SyntaxKind.ParenthesizedExpression, out ParenthesizedExpressionSyntax parenExpr) &&
!previousToken.Parent.IsParentKind(SyntaxKind.ParenthesizedExpression) &&
((ParenthesizedExpressionSyntax)previousToken.Parent).Expression.Kind() == SyntaxKind.SimpleMemberAccessExpression &&
parenExpr.Expression.Kind() == SyntaxKind.SimpleMemberAccessExpression &&
symbol != null && symbol.Kind == SymbolKind.Method)
{
return false;
......
......@@ -641,18 +641,15 @@ private static bool IsAmbiguousCast(ExpressionSyntax expression, ExpressionSynta
// Can't simplify a type name in a cast expression if it would then cause the cast to be
// parsed differently. For example: (Goo::Bar)+1 is a cast. But if that simplifies to
// (Bar)+1 then that's an arithmetic expression.
if (expression.IsParentKind(SyntaxKind.CastExpression))
if (expression.IsParentKind(SyntaxKind.CastExpression, out CastExpressionSyntax castExpression) &&
castExpression.Type == expression)
{
var castExpression = (CastExpressionSyntax)expression.Parent;
if (castExpression.Type == expression)
{
var newCastExpression = castExpression.ReplaceNode(castExpression.Type, simplifiedNode);
var reparsedCastExpression = SyntaxFactory.ParseExpression(newCastExpression.ToString());
var newCastExpression = castExpression.ReplaceNode(castExpression.Type, simplifiedNode);
var reparsedCastExpression = SyntaxFactory.ParseExpression(newCastExpression.ToString());
if (!reparsedCastExpression.IsKind(SyntaxKind.CastExpression))
{
return true;
}
if (!reparsedCastExpression.IsKind(SyntaxKind.CastExpression))
{
return true;
}
}
......@@ -674,8 +671,8 @@ private static bool IsQualifiedNameInUsingDirective(SemanticModel model, NameSyn
name = (NameSyntax)name.Parent;
}
if (name.IsParentKind(SyntaxKind.UsingDirective) &&
((UsingDirectiveSyntax)name.Parent).Alias == null)
if (name.IsParentKind(SyntaxKind.UsingDirective, out UsingDirectiveSyntax usingDirective) &&
usingDirective.Alias == null)
{
// We're a qualified name in a using. We don't want to reduce this name as people like
// fully qualified names in usings so they can properly tell what the name is resolving
......
......@@ -6,7 +6,6 @@
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
......@@ -15,24 +14,11 @@
namespace Microsoft.CodeAnalysis.Options.EditorConfig
{
[Export(typeof(IDocumentOptionsProviderFactory)), Shared]
[ExportMetadata("Name", PredefinedDocumentOptionsProviderNames.EditorConfig)]
internal sealed class EditorConfigDocumentOptionsProviderFactory : IDocumentOptionsProviderFactory
internal static class EditorConfigDocumentOptionsProviderFactory
{
[ImportingConstructor]
public EditorConfigDocumentOptionsProviderFactory()
public static IDocumentOptionsProvider Create(Workspace workspace)
{
}
public IDocumentOptionsProvider? TryCreate(Workspace workspace)
{
if (!ShouldUseNativeEditorConfigSupport(workspace))
{
// Simply disable if the feature isn't on
return null;
}
return new EditorConfigDocumentOptionsProvider(workspace.Services.GetRequiredService<IErrorLoggerService>());
return new EditorConfigDocumentOptionsProvider(workspace.Services.GetService<IErrorLoggerService>());
}
private const string LocalRegistryPath = @"Roslyn\Internal\OnOff\Features\";
......@@ -48,15 +34,21 @@ public static bool ShouldUseNativeEditorConfigSupport(Workspace workspace)
private class EditorConfigDocumentOptionsProvider : IDocumentOptionsProvider
{
private readonly IErrorLoggerService _errorLogger;
private readonly IErrorLoggerService? _errorLogger;
public EditorConfigDocumentOptionsProvider(IErrorLoggerService errorLogger)
public EditorConfigDocumentOptionsProvider(IErrorLoggerService? errorLogger)
{
_errorLogger = errorLogger;
}
public async Task<IDocumentOptions?> GetOptionsForDocumentAsync(Document document, CancellationToken cancellationToken)
{
if (!ShouldUseNativeEditorConfigSupport(document.Project.Solution.Workspace))
{
// Simply disable if the feature isn't on
return null;
}
var options = await document.GetAnalyzerOptionsAsync(cancellationToken).ConfigureAwait(false);
return new DocumentOptions(options, _errorLogger);
......@@ -65,9 +57,9 @@ public EditorConfigDocumentOptionsProvider(IErrorLoggerService errorLogger)
private class DocumentOptions : IDocumentOptions
{
private readonly ImmutableDictionary<string, string> _options;
private readonly IErrorLoggerService _errorLogger;
private readonly IErrorLoggerService? _errorLogger;
public DocumentOptions(ImmutableDictionary<string, string> options, IErrorLoggerService errorLogger)
public DocumentOptions(ImmutableDictionary<string, string> options, IErrorLoggerService? errorLogger)
{
_options = options;
_errorLogger = errorLogger;
......
......@@ -14,9 +14,11 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.ErrorLogger;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.EditorConfig;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
......@@ -87,6 +89,8 @@ protected Workspace(HostServices host, string? workspaceKind)
var info = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create());
var emptyOptions = new SerializableOptionSet(languages: ImmutableHashSet<string>.Empty, _optionService, serializableOptions: ImmutableHashSet<IOption>.Empty, values: ImmutableDictionary<OptionKey, object?>.Empty);
_latestSolution = CreateSolution(info, emptyOptions);
_optionService.RegisterDocumentOptionsProvider(EditorConfigDocumentOptionsProviderFactory.Create(this));
}
internal void LogTestMessage(string message)
......
......@@ -18,10 +18,8 @@ internal static partial class ExpressionSyntaxExtensions
{
public static ExpressionSyntax WalkUpParentheses(this ExpressionSyntax expression)
{
while (expression.IsParentKind(SyntaxKind.ParenthesizedExpression))
{
expression = (ExpressionSyntax)expression.Parent;
}
while (expression.IsParentKind(SyntaxKind.ParenthesizedExpression, out ExpressionSyntax parentExpr))
expression = parentExpr;
return expression;
}
......@@ -42,10 +40,8 @@ public static bool IsQualifiedCrefName(this ExpressionSyntax expression)
}
public static bool IsMemberAccessExpressionName(this ExpressionSyntax expression)
{
return (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) && ((MemberAccessExpressionSyntax)expression.Parent).Name == expression) ||
IsMemberBindingExpressionName(expression);
}
=> (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression, out MemberAccessExpressionSyntax memberAccess) && memberAccess.Name == expression) ||
IsMemberBindingExpressionName(expression);
public static bool IsAnyMemberAccessExpressionName(this ExpressionSyntax expression)
{
......@@ -59,20 +55,14 @@ public static bool IsAnyMemberAccessExpressionName(this ExpressionSyntax express
}
private static bool IsMemberBindingExpressionName(this ExpressionSyntax expression)
{
return expression.IsParentKind(SyntaxKind.MemberBindingExpression) &&
((MemberBindingExpressionSyntax)expression.Parent).Name == expression;
}
=> expression.IsParentKind(SyntaxKind.MemberBindingExpression, out MemberBindingExpressionSyntax memberBinding) &&
memberBinding.Name == expression;
public static bool IsRightSideOfQualifiedName(this ExpressionSyntax expression)
{
return expression.IsParentKind(SyntaxKind.QualifiedName) && ((QualifiedNameSyntax)expression.Parent).Right == expression;
}
=> expression.IsParentKind(SyntaxKind.QualifiedName, out QualifiedNameSyntax qualifiedName) && qualifiedName.Right == expression;
public static bool IsRightSideOfColonColon(this ExpressionSyntax expression)
{
return expression.IsParentKind(SyntaxKind.AliasQualifiedName) && ((AliasQualifiedNameSyntax)expression.Parent).Name == expression;
}
=> expression.IsParentKind(SyntaxKind.AliasQualifiedName, out AliasQualifiedNameSyntax aliasName) && aliasName.Name == expression;
public static bool IsRightSideOfDot(this ExpressionSyntax name)
{
......@@ -127,7 +117,7 @@ public static bool IsLeftSideOfExplicitInterfaceSpecifier(this NameSyntax name)
=> name.IsParentKind(SyntaxKind.ExplicitInterfaceSpecifier);
public static bool IsExpressionOfInvocation(this ExpressionSyntax expression)
=> (expression?.Parent).IsKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax invocation) &&
=> expression.IsParentKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax invocation) &&
invocation.Expression == expression;
public static bool TryGetNameParts(this ExpressionSyntax expression, out IList<string> parts)
......
......@@ -52,15 +52,15 @@ public static bool LooksLikeStandaloneTypeName(this SimpleNameSyntax simpleName)
}
// type names can't be invoked.
if (simpleName.IsParentKind(SyntaxKind.InvocationExpression) &&
((InvocationExpressionSyntax)simpleName.Parent).Expression == simpleName)
if (simpleName.IsParentKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax invocation) &&
invocation.Expression == simpleName)
{
return false;
}
// type names can't be indexed into.
if (simpleName.IsParentKind(SyntaxKind.ElementAccessExpression) &&
((ElementAccessExpressionSyntax)simpleName.Parent).Expression == simpleName)
if (simpleName.IsParentKind(SyntaxKind.ElementAccessExpression, out ElementAccessExpressionSyntax elementAccess) &&
elementAccess.Expression == simpleName)
{
return false;
}
......
......@@ -43,6 +43,19 @@ public static bool IsKind<TNode>([NotNullWhen(returnValue: true)] this SyntaxNod
public static bool IsParentKind([NotNullWhen(returnValue: true)] this SyntaxNode? node, SyntaxKind kind)
=> CodeAnalysis.CSharpExtensions.IsKind(node?.Parent, kind);
public static bool IsParentKind<TNode>([NotNullWhen(returnValue: true)] this SyntaxNode? node, SyntaxKind kind, [NotNullWhen(returnValue: true)] out TNode? result)
where TNode : SyntaxNode
{
if (node.IsParentKind(kind))
{
result = (TNode)node.Parent!;
return true;
}
result = null;
return false;
}
public static bool IsParentKind([NotNullWhen(returnValue: true)] this SyntaxNode? node, SyntaxKind kind1, SyntaxKind kind2)
=> IsKind(node?.Parent, kind1, kind2);
......@@ -255,10 +268,10 @@ public static SyntaxList<AttributeListSyntax> GetAttributeLists(this SyntaxNode
var current = node;
while (current?.Parent != null)
{
if (current.IsParentKind(SyntaxKind.ConditionalAccessExpression) &&
((ConditionalAccessExpressionSyntax)current.Parent).WhenNotNull == current)
if (current.IsParentKind(SyntaxKind.ConditionalAccessExpression, out ConditionalAccessExpressionSyntax? conditional) &&
conditional.WhenNotNull == current)
{
return (ConditionalAccessExpressionSyntax)current.Parent;
return conditional;
}
current = current.Parent;
......@@ -325,10 +338,8 @@ public static bool IsCompoundAssignExpression(this SyntaxNode node)
}
public static bool IsLeftSideOfAssignExpression([NotNullWhen(returnValue: true)] this SyntaxNode? node)
{
return node.IsParentKind(SyntaxKind.SimpleAssignmentExpression) &&
((AssignmentExpressionSyntax)node.Parent!).Left == node;
}
=> node.IsParentKind(SyntaxKind.SimpleAssignmentExpression, out AssignmentExpressionSyntax? assignment) &&
assignment.Left == node;
public static bool IsLeftSideOfAnyAssignExpression(this SyntaxNode node)
{
......@@ -728,12 +739,9 @@ public static bool ContainsInterleavedDirective(this SyntaxNode syntaxNode, Text
=> CSharpSyntaxFacts.Instance.GetNodeWithoutLeadingBannerAndPreprocessorDirectives(node, out strippedTrivia);
public static bool IsVariableDeclaratorValue(this SyntaxNode node)
{
return
node.IsParentKind(SyntaxKind.EqualsValueClause) &&
node.Parent.IsParentKind(SyntaxKind.VariableDeclarator) &&
((EqualsValueClauseSyntax)node.Parent).Value == node;
}
=> node.IsParentKind(SyntaxKind.EqualsValueClause, out EqualsValueClauseSyntax? equalsValue) &&
equalsValue.IsParentKind(SyntaxKind.VariableDeclarator) &&
equalsValue.Value == node;
public static BlockSyntax? FindInnermostCommonBlock(this IEnumerable<SyntaxNode> nodes)
{
......
......@@ -127,10 +127,8 @@ public bool IsNameOfMemberAccessExpression([NotNullWhen(true)] SyntaxNode? node)
#nullable restore
public bool IsObjectCreationExpressionType(SyntaxNode node)
{
return node.IsParentKind(SyntaxKind.ObjectCreationExpression) &&
((ObjectCreationExpressionSyntax)node.Parent).Type == node;
}
=> node.IsParentKind(SyntaxKind.ObjectCreationExpression, out ObjectCreationExpressionSyntax objectCreation) &&
objectCreation.Type == node;
public bool IsAttributeName(SyntaxNode node)
{
......@@ -164,11 +162,8 @@ public SyntaxToken GetIdentifierOfGenericName(SyntaxNode genericName)
}
public bool IsUsingDirectiveName(SyntaxNode node)
{
return
node.IsParentKind(SyntaxKind.UsingDirective) &&
((UsingDirectiveSyntax)node.Parent).Name == node;
}
=> node.IsParentKind(SyntaxKind.UsingDirective, out UsingDirectiveSyntax usingDirective) &&
usingDirective.Name == node;
public bool IsUsingAliasDirective(SyntaxNode node)
=> node is UsingDirectiveSyntax usingDirectiveNode && usingDirectiveNode.Alias != null;
......@@ -436,13 +431,13 @@ public bool IsTypeNamedVarInVariableOrFieldDeclaration(SyntaxToken token, Syntax
if (typedParent.IsKind(SyntaxKind.IdentifierName))
{
TypeSyntax declaredType = null;
if (typedParent.IsParentKind(SyntaxKind.VariableDeclaration))
if (typedParent.IsParentKind(SyntaxKind.VariableDeclaration, out VariableDeclarationSyntax varDecl))
{
declaredType = ((VariableDeclarationSyntax)typedParent.Parent).Type;
declaredType = varDecl.Type;
}
else if (typedParent.IsParentKind(SyntaxKind.FieldDeclaration))
else if (typedParent.IsParentKind(SyntaxKind.FieldDeclaration, out FieldDeclarationSyntax fieldDecl))
{
declaredType = ((FieldDeclarationSyntax)typedParent.Parent).Declaration.Type;
declaredType = fieldDecl.Declaration.Type;
}
return declaredType == typedParent && typedToken.ValueText == "var";
......@@ -643,9 +638,9 @@ public bool IsObjectInitializerNamedAssignmentIdentifier(SyntaxNode node)
initializedInstance = objectInitializer.Parent;
return true;
}
else if (objectInitializer.IsParentKind(SyntaxKind.SimpleAssignmentExpression))
else if (objectInitializer.IsParentKind(SyntaxKind.SimpleAssignmentExpression, out AssignmentExpressionSyntax assignment))
{
initializedInstance = ((AssignmentExpressionSyntax)objectInitializer.Parent).Left;
initializedInstance = assignment.Left;
return true;
}
}
......@@ -1217,22 +1212,16 @@ public SyntaxNode GetRightHandSideOfAssignment(SyntaxNode node)
=> (node as AssignmentExpressionSyntax)?.Right;
public bool IsInferredAnonymousObjectMemberDeclarator(SyntaxNode node)
{
return node.IsKind(SyntaxKind.AnonymousObjectMemberDeclarator) &&
((AnonymousObjectMemberDeclaratorSyntax)node).NameEquals == null;
}
=> node.IsKind(SyntaxKind.AnonymousObjectMemberDeclarator, out AnonymousObjectMemberDeclaratorSyntax anonObject) &&
anonObject.NameEquals == null;
public bool IsOperandOfIncrementExpression(SyntaxNode node)
{
return node.IsParentKind(SyntaxKind.PostIncrementExpression) ||
node.IsParentKind(SyntaxKind.PreIncrementExpression);
}
=> node.IsParentKind(SyntaxKind.PostIncrementExpression) ||
node.IsParentKind(SyntaxKind.PreIncrementExpression);
public bool IsOperandOfDecrementExpression(SyntaxNode node)
{
return node.IsParentKind(SyntaxKind.PostDecrementExpression) ||
node.IsParentKind(SyntaxKind.PreDecrementExpression);
}
=> node.IsParentKind(SyntaxKind.PostDecrementExpression) ||
node.IsParentKind(SyntaxKind.PreDecrementExpression);
public bool IsOperandOfIncrementOrDecrementExpression(SyntaxNode node)
{
......
......@@ -73,13 +73,10 @@ protected override bool ShouldAnalyzeForEachStatement(ForEachStatementSyntax for
{
// var (x, y) = e;
// foreach (var (x, y) in e) ...
if (typeName.IsParentKind(SyntaxKind.DeclarationExpression))
if (typeName.IsParentKind(SyntaxKind.DeclarationExpression, out DeclarationExpressionSyntax declExpression) &&
declExpression.Designation.IsKind(SyntaxKind.ParenthesizedVariableDesignation))
{
var parent = (DeclarationExpressionSyntax)typeName.Parent;
if (parent.Designation.IsKind(SyntaxKind.ParenthesizedVariableDesignation))
{
return true;
}
return true;
}
// If it is currently not var, explicit typing exists, return.
......
......@@ -308,14 +308,14 @@ private static bool IsDynamicInvocation(ExpressionSyntax castExpression, Semanti
{
var typeInfo = default(TypeInfo);
if (castExpression.Parent.Parent.IsParentKind(SyntaxKind.InvocationExpression))
if (castExpression.Parent.Parent.IsParentKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax invocation))
{
typeInfo = semanticModel.GetTypeInfo((InvocationExpressionSyntax)castExpression.Parent.Parent.Parent, cancellationToken);
typeInfo = semanticModel.GetTypeInfo(invocation, cancellationToken);
}
if (castExpression.Parent.Parent.IsParentKind(SyntaxKind.ElementAccessExpression))
if (castExpression.Parent.Parent.IsParentKind(SyntaxKind.ElementAccessExpression, out ElementAccessExpressionSyntax elementAccess))
{
typeInfo = semanticModel.GetTypeInfo((ElementAccessExpressionSyntax)castExpression.Parent.Parent.Parent, cancellationToken);
typeInfo = semanticModel.GetTypeInfo(elementAccess, cancellationToken);
}
if (typeInfo.Type != null && typeInfo.Type.Kind == SymbolKind.DynamicType)
......
......@@ -610,16 +610,10 @@ private static bool IsGenericInterfaceOrDelegateTypeParameterList(SyntaxNode nod
{
if (node.IsKind(SyntaxKind.TypeParameterList))
{
if (node.IsParentKind(SyntaxKind.InterfaceDeclaration))
{
var decl = node.Parent as TypeDeclarationSyntax;
return decl.TypeParameterList == node;
}
else if (node.IsParentKind(SyntaxKind.DelegateDeclaration))
{
var decl = node.Parent as DelegateDeclarationSyntax;
return decl.TypeParameterList == node;
}
if (node.IsParentKind(SyntaxKind.InterfaceDeclaration, out TypeDeclarationSyntax typeDecl))
return typeDecl.TypeParameterList == node;
else if (node.IsParentKind(SyntaxKind.DelegateDeclaration, out DelegateDeclarationSyntax delegateDecl))
return delegateDecl.TypeParameterList == node;
}
return false;
......
......@@ -955,12 +955,11 @@ public static bool IsDefaultExpressionContext(this SyntaxTree syntaxTree, int po
// Might be an incomplete conditional expression or an incomplete declaration of a method returning a nullable type.
// Bind T to see if it is a type. If it is we don't show signature help.
if (name.IsParentKind(SyntaxKind.LessThanExpression) &&
name.Parent.IsParentKind(SyntaxKind.ConditionalExpression) &&
name.Parent.IsParentKind(SyntaxKind.ConditionalExpression, out ConditionalExpressionSyntax conditional) &&
name.Parent.Parent.IsParentKind(SyntaxKind.ExpressionStatement) &&
name.Parent.Parent.Parent.IsParentKind(SyntaxKind.GlobalStatement))
{
var conditionOrType = semanticModelOpt.GetSymbolInfo(
((ConditionalExpressionSyntax)name.Parent.Parent).Condition, cancellationToken);
var conditionOrType = semanticModelOpt.GetSymbolInfo(conditional.Condition, cancellationToken);
if (conditionOrType.GetBestOrAllSymbols().FirstOrDefault() != null &&
conditionOrType.GetBestOrAllSymbols().FirstOrDefault().Kind == SymbolKind.NamedType)
{
......@@ -1016,10 +1015,9 @@ public static bool IsDefaultExpressionContext(this SyntaxTree syntaxTree, int po
if (token.IsKind(SyntaxKind.CloseBracketToken) &&
token.Parent.IsKind(SyntaxKind.AttributeList) &&
token.Parent.IsParentKind(SyntaxKind.Parameter) &&
token.Parent.IsParentKind(SyntaxKind.Parameter, out ParameterSyntax parameter) &&
token.Parent.Parent.Parent.IsDelegateOrConstructorOrLocalFunctionOrMethodOrOperatorParameterList(includeOperators))
{
var parameter = (ParameterSyntax)token.Parent.Parent;
var parameterList = (ParameterListSyntax)parameter.Parent;
parameterIndex = parameterList.Parameters.IndexOf(parameter);
......@@ -1031,7 +1029,7 @@ public static bool IsDefaultExpressionContext(this SyntaxTree syntaxTree, int po
token.Parent.IsKind(SyntaxKind.Parameter) &&
token.Parent.Parent.IsDelegateOrConstructorOrLocalFunctionOrMethodOrOperatorParameterList(includeOperators))
{
var parameter = (ParameterSyntax)token.Parent;
parameter = (ParameterSyntax)token.Parent;
var parameterList = (ParameterListSyntax)parameter.Parent;
parameterIndex = parameterList.Parameters.IndexOf(parameter);
......@@ -1323,9 +1321,8 @@ public static bool IsPossibleTupleOpenParenOrComma(this SyntaxToken possibleComm
// in script
if (possibleCommaOrParen.Parent.IsKind(SyntaxKind.ParameterList) &&
possibleCommaOrParen.Parent.IsParentKind(SyntaxKind.ParenthesizedLambdaExpression))
possibleCommaOrParen.Parent.IsParentKind(SyntaxKind.ParenthesizedLambdaExpression, out ParenthesizedLambdaExpressionSyntax parenthesizedLambda))
{
var parenthesizedLambda = (ParenthesizedLambdaExpressionSyntax)possibleCommaOrParen.Parent.Parent;
if (parenthesizedLambda.ArrowToken.IsMissing)
{
return true;
......@@ -1434,11 +1431,10 @@ private static bool IsPossibleVarDeconstructionOpenParenOrComma(SyntaxToken left
{
if (leftToken.IsKind(SyntaxKind.OpenParenToken, SyntaxKind.CommaToken) &&
leftToken.Parent.IsKind(SyntaxKind.ArgumentList) &&
leftToken.Parent.IsParentKind(SyntaxKind.InvocationExpression))
leftToken.Parent.IsParentKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax invocation))
{
var invocation = (InvocationExpressionSyntax)leftToken.Parent.Parent;
if (invocation.Expression.IsKind(SyntaxKind.IdentifierName) &&
((IdentifierNameSyntax)invocation.Expression).Identifier.ValueText == "var")
if (invocation.Expression.IsKind(SyntaxKind.IdentifierName, out IdentifierNameSyntax identifierName) &&
identifierName.Identifier.ValueText == "var")
{
return true;
}
......@@ -2149,14 +2145,12 @@ public static bool IsLabelContext(this SyntaxTree syntaxTree, int position, Canc
{
var type = previousToken.Parent as TypeSyntax;
if (type.IsParentKind(SyntaxKind.VariableDeclaration) &&
type.Parent.IsParentKind(SyntaxKind.LocalDeclarationStatement))
type.Parent.IsParentKind(SyntaxKind.LocalDeclarationStatement, out LocalDeclarationStatementSyntax declStatement))
{
var declStatement = type.Parent.Parent as LocalDeclarationStatementSyntax;
// note, this doesn't apply for cases where we know it
// absolutely is not multiplication or a conditional expression.
var underlyingType = type is PointerTypeSyntax
? ((PointerTypeSyntax)type).ElementType
var underlyingType = type is PointerTypeSyntax pointerType
? pointerType.ElementType
: ((NullableTypeSyntax)type).ElementType;
if (!underlyingType.IsPotentialTypeName(semanticModelOpt, cancellationToken))
......@@ -2309,9 +2303,8 @@ public static bool IsLabelContext(this SyntaxTree syntaxTree, int position, Canc
// can support a collection initializer. If not, this must be an object initializer
// and can't be an expression context.
if (semanticModelOpt != null &&
token.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression))
token.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression, out ObjectCreationExpressionSyntax objectCreation))
{
var objectCreation = (ObjectCreationExpressionSyntax)token.Parent.Parent;
var containingSymbol = semanticModelOpt.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
if (semanticModelOpt.GetSymbolInfo(objectCreation.Type, cancellationToken).Symbol is ITypeSymbol type && !type.CanSupportCollectionInitializer(containingSymbol))
{
......@@ -2681,8 +2674,8 @@ public static bool IsNameOfContext(this SyntaxTree syntaxTree, int position, Sem
if (CodeAnalysis.CSharpExtensions.IsKind(token, SyntaxKind.IdentifierToken) &&
token.Parent.IsKind(SyntaxKind.IdentifierName))
{
if (token.Parent.IsParentKind(SyntaxKind.Argument) &&
CodeAnalysis.CSharpExtensions.IsKind(((ArgumentSyntax)token.Parent.Parent).RefOrOutKeyword, SyntaxKind.OutKeyword))
if (token.Parent.IsParentKind(SyntaxKind.Argument, out ArgumentSyntax argument) &&
argument.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword))
{
return false;
}
......
......@@ -105,19 +105,19 @@ public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node,
// lock ((x)) -> lock (x)
// using ((x)) -> using (x)
// catch when ((x)) -> catch when (x)
if ((node.IsParentKind(SyntaxKind.EqualsValueClause) && ((EqualsValueClauseSyntax)node.Parent).Value == node) ||
(node.IsParentKind(SyntaxKind.IfStatement) && ((IfStatementSyntax)node.Parent).Condition == node) ||
(node.IsParentKind(SyntaxKind.ReturnStatement) && ((ReturnStatementSyntax)node.Parent).Expression == node) ||
(node.IsParentKind(SyntaxKind.YieldReturnStatement) && ((YieldStatementSyntax)node.Parent).Expression == node) ||
(node.IsParentKind(SyntaxKind.ThrowStatement) && ((ThrowStatementSyntax)node.Parent).Expression == node) ||
(node.IsParentKind(SyntaxKind.SwitchStatement) && ((SwitchStatementSyntax)node.Parent).Expression == node) ||
(node.IsParentKind(SyntaxKind.WhileStatement) && ((WhileStatementSyntax)node.Parent).Condition == node) ||
(node.IsParentKind(SyntaxKind.DoStatement) && ((DoStatementSyntax)node.Parent).Condition == node) ||
(node.IsParentKind(SyntaxKind.ForStatement) && ((ForStatementSyntax)node.Parent).Condition == node) ||
if ((node.IsParentKind(SyntaxKind.EqualsValueClause, out EqualsValueClauseSyntax equalsValue) && equalsValue.Value == node) ||
(node.IsParentKind(SyntaxKind.IfStatement, out IfStatementSyntax ifStatement) && ifStatement.Condition == node) ||
(node.IsParentKind(SyntaxKind.ReturnStatement, out ReturnStatementSyntax returnStatement) && returnStatement.Expression == node) ||
(node.IsParentKind(SyntaxKind.YieldReturnStatement, out YieldStatementSyntax yieldStatement) && yieldStatement.Expression == node) ||
(node.IsParentKind(SyntaxKind.ThrowStatement, out ThrowStatementSyntax throwStatement) && throwStatement.Expression == node) ||
(node.IsParentKind(SyntaxKind.SwitchStatement, out SwitchStatementSyntax switchStatement) && switchStatement.Expression == node) ||
(node.IsParentKind(SyntaxKind.WhileStatement, out WhileStatementSyntax whileStatement) && whileStatement.Condition == node) ||
(node.IsParentKind(SyntaxKind.DoStatement, out DoStatementSyntax doStatement) && doStatement.Condition == node) ||
(node.IsParentKind(SyntaxKind.ForStatement, out ForStatementSyntax forStatement) && forStatement.Condition == node) ||
(node.IsParentKind(SyntaxKind.ForEachStatement, SyntaxKind.ForEachVariableStatement) && ((CommonForEachStatementSyntax)node.Parent).Expression == node) ||
(node.IsParentKind(SyntaxKind.LockStatement) && ((LockStatementSyntax)node.Parent).Expression == node) ||
(node.IsParentKind(SyntaxKind.UsingStatement) && ((UsingStatementSyntax)node.Parent).Expression == node) ||
(node.IsParentKind(SyntaxKind.CatchFilterClause) && ((CatchFilterClauseSyntax)node.Parent).FilterExpression == node))
(node.IsParentKind(SyntaxKind.LockStatement, out LockStatementSyntax lockStatement) && lockStatement.Expression == node) ||
(node.IsParentKind(SyntaxKind.UsingStatement, out UsingStatementSyntax usingStatement) && usingStatement.Expression == node) ||
(node.IsParentKind(SyntaxKind.CatchFilterClause, out CatchFilterClauseSyntax catchFilter) && catchFilter.FilterExpression == node))
{
return true;
}
......@@ -139,7 +139,7 @@ public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node,
// Cases:
// y((x)) -> y(x)
if (node.IsParentKind(SyntaxKind.Argument) && ((ArgumentSyntax)node.Parent).Expression == node)
if (node.IsParentKind(SyntaxKind.Argument, out ArgumentSyntax argument) && argument.Expression == node)
{
return true;
}
......@@ -213,10 +213,16 @@ public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node,
return true;
}
// (this) -> this
if (expression.IsKind(SyntaxKind.ThisExpression))
{
return true;
}
// x ?? (throw ...) -> x ?? throw ...
if (expression.IsKind(SyntaxKind.ThrowExpression) &&
node.IsParentKind(SyntaxKind.CoalesceExpression) &&
((BinaryExpressionSyntax)node.Parent).Right == node)
node.IsParentKind(SyntaxKind.CoalesceExpression, out BinaryExpressionSyntax binary) &&
binary.Right == node)
{
return true;
}
......@@ -462,9 +468,8 @@ private static bool RemovalMayIntroduceCastAmbiguity(ParenthesizedExpressionSynt
// (X?)(...)
// (global::X)(...)
if (node.IsParentKind(SyntaxKind.CastExpression))
if (node.IsParentKind(SyntaxKind.CastExpression, out CastExpressionSyntax castExpression))
{
var castExpression = (CastExpressionSyntax)node.Parent;
if (castExpression.Type.IsKind(
SyntaxKind.PredefinedType,
SyntaxKind.ArrayType,
......@@ -589,9 +594,8 @@ private static bool IsPreviousExpressionPotentiallyAmbiguous(ExpressionSyntax no
{
ExpressionSyntax previousExpression = null;
if (node.IsParentKind(SyntaxKind.Argument))
if (node.IsParentKind(SyntaxKind.Argument, out ArgumentSyntax argument))
{
var argument = (ArgumentSyntax)node.Parent;
if (argument.Parent is ArgumentListSyntax argumentList)
{
var argumentIndex = argumentList.Arguments.IndexOf(argument);
......@@ -627,9 +631,8 @@ private static bool IsNextExpressionPotentiallyAmbiguous(ExpressionSyntax node)
{
ExpressionSyntax nextExpression = null;
if (node.IsParentKind(SyntaxKind.Argument))
if (node.IsParentKind(SyntaxKind.Argument, out ArgumentSyntax argument))
{
var argument = (ArgumentSyntax)node.Parent;
if (argument.Parent is ArgumentListSyntax argumentList)
{
var argumentIndex = argumentList.Arguments.IndexOf(argument);
......
......@@ -262,9 +262,8 @@ private static bool CanBindToken(SyntaxToken token)
SemanticModel semanticModel, ExpressionSyntax expression, CancellationToken cancellationToken)
{
var topExpression = expression.WalkUpParentheses();
if (topExpression.IsParentKind(SyntaxKind.Argument))
if (topExpression.IsParentKind(SyntaxKind.Argument, out ArgumentSyntax argument))
{
var argument = (ArgumentSyntax)topExpression.Parent;
if (argument.NameColon != null)
{
return argument.NameColon.Name.Identifier.ValueText;
......@@ -332,14 +331,16 @@ public static ISet<INamespaceSymbol> GetUsingNamespacesInScope(this SemanticMode
// as the interface type itself.
if (type != null)
{
if (type.Parent is BaseTypeSyntax && type.Parent.IsParentKind(SyntaxKind.BaseList) && ((BaseTypeSyntax)type.Parent).Type == type)
if (type.Parent is BaseTypeSyntax baseType &&
type.Parent.IsParentKind(SyntaxKind.BaseList, out BaseListSyntax baseList) &&
baseType.Type == type)
{
var containingType = semanticModel.GetDeclaredSymbol(type.GetAncestor<BaseTypeDeclarationSyntax>(), cancellationToken) as INamedTypeSymbol;
if (containingType != null && containingType.TypeKind == TypeKind.Interface)
{
return containingType.DeclaredAccessibility;
}
else if (((BaseListSyntax)type.Parent.Parent).Types[0] == type.Parent)
else if (baseList.Types[0] == type.Parent)
{
return containingType.DeclaredAccessibility;
}
......@@ -348,10 +349,9 @@ public static ISet<INamespaceSymbol> GetUsingNamespacesInScope(this SemanticMode
// 4) The type of a constant must be at least as accessible as the constant itself.
// 5) The type of a field must be at least as accessible as the field itself.
if (type.IsParentKind(SyntaxKind.VariableDeclaration) &&
if (type.IsParentKind(SyntaxKind.VariableDeclaration, out VariableDeclarationSyntax variableDeclaration) &&
type.Parent.IsParentKind(SyntaxKind.FieldDeclaration))
{
var variableDeclaration = (VariableDeclarationSyntax)type.Parent;
return semanticModel.GetDeclaredSymbol(
variableDeclaration.Variables[0], cancellationToken).DeclaredAccessibility;
}
......@@ -360,10 +360,9 @@ public static ISet<INamespaceSymbol> GetUsingNamespacesInScope(this SemanticMode
if (type.IsParentKind(SyntaxKind.ObjectCreationExpression) &&
type.Parent.IsParentKind(SyntaxKind.EqualsValueClause) &&
type.Parent.Parent.IsParentKind(SyntaxKind.VariableDeclarator) &&
type.Parent.Parent.Parent.IsParentKind(SyntaxKind.VariableDeclaration) &&
type.Parent.Parent.Parent.IsParentKind(SyntaxKind.VariableDeclaration, out variableDeclaration) &&
type.Parent.Parent.Parent.Parent.IsParentKind(SyntaxKind.FieldDeclaration))
{
var variableDeclaration = (VariableDeclarationSyntax)type.Parent.Parent.Parent.Parent;
return semanticModel.GetDeclaredSymbol(
variableDeclaration.Variables[0], cancellationToken).DeclaredAccessibility;
}
......@@ -420,10 +419,9 @@ public static ISet<INamespaceSymbol> GetUsingNamespacesInScope(this SemanticMode
}
// 8) The type of an event must be at least as accessible as the event itself.
if (type.IsParentKind(SyntaxKind.VariableDeclaration) &&
if (type.IsParentKind(SyntaxKind.VariableDeclaration, out variableDeclaration) &&
type.Parent.IsParentKind(SyntaxKind.EventFieldDeclaration))
{
var variableDeclaration = (VariableDeclarationSyntax)type.Parent;
var symbol = semanticModel.GetDeclaredSymbol(variableDeclaration.Variables[0], cancellationToken);
if (symbol != null)
{
......
......@@ -239,6 +239,7 @@ protected override IEnumerable<TypeInferenceInfo> InferTypesWorker_DoNotCallDire
SwitchLabelSyntax switchLabel => InferTypeInSwitchLabel(switchLabel, token),
SwitchStatementSyntax switchStatement => InferTypeInSwitchStatement(switchStatement, token),
ThrowStatementSyntax throwStatement => InferTypeInThrowStatement(throwStatement, token),
TupleExpressionSyntax tupleExpression => InferTypeInTupleExpression(tupleExpression, token),
UsingStatementSyntax usingStatement => InferTypeInUsingStatement(usingStatement, token),
WhenClauseSyntax whenClause => InferTypeInWhenClause(whenClause, token),
WhileStatementSyntax whileStatement => InferTypeInWhileStatement(whileStatement, token),
......@@ -277,52 +278,45 @@ private IEnumerable<TypeInferenceInfo> InferTypeInAnonymousObjectCreation(Anonym
return InferTypeInConstructorInitializer(initializer, index, argument);
}
if (argument.Parent.IsParentKind(SyntaxKind.InvocationExpression))
if (argument.Parent.IsParentKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax invocation))
{
var invocation = argument.Parent.Parent as InvocationExpressionSyntax;
var index = invocation.ArgumentList.Arguments.IndexOf(argument);
return InferTypeInInvocationExpression(invocation, index, argument);
}
if (argument.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression))
if (argument.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression, out ObjectCreationExpressionSyntax creation))
{
// new Outer(Goo());
//
// new Outer(a: Goo());
//
// etc.
var creation = argument.Parent.Parent as ObjectCreationExpressionSyntax;
var index = creation.ArgumentList.Arguments.IndexOf(argument);
return InferTypeInObjectCreationExpression(creation, index, argument);
}
if (argument.Parent.IsParentKind(SyntaxKind.ElementAccessExpression))
if (argument.Parent.IsParentKind(SyntaxKind.ElementAccessExpression, out ElementAccessExpressionSyntax elementAccess))
{
// Outer[Goo()];
//
// Outer[a: Goo()];
//
// etc.
var elementAccess = argument.Parent.Parent as ElementAccessExpressionSyntax;
var index = elementAccess.ArgumentList.Arguments.IndexOf(argument);
return InferTypeInElementAccessExpression(elementAccess, index, argument);
}
if (argument.IsParentKind(SyntaxKind.TupleExpression))
if (argument.IsParentKind(SyntaxKind.TupleExpression, out TupleExpressionSyntax tupleExpression))
{
return InferTypeInTupleExpression((TupleExpressionSyntax)argument.Parent, argument);
return InferTypeInTupleExpression(tupleExpression, argument);
}
}
if (argument.Parent.IsParentKind(SyntaxKind.ImplicitElementAccess) &&
argument.Parent.Parent.IsParentKind(SyntaxKind.SimpleAssignmentExpression) &&
argument.Parent.Parent.Parent.IsParentKind(SyntaxKind.ObjectInitializerExpression) &&
argument.Parent.Parent.Parent.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression))
argument.Parent.Parent.Parent.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression, out ObjectCreationExpressionSyntax objectCreation))
{
var objectCreation = (ObjectCreationExpressionSyntax)argument.Parent.Parent.Parent.Parent.Parent;
var types = GetTypes(objectCreation).Select(t => t.InferredType);
if (types.Any(t => t is INamedTypeSymbol))
......@@ -335,6 +329,22 @@ private IEnumerable<TypeInferenceInfo> InferTypeInAnonymousObjectCreation(Anonym
return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
private IEnumerable<TypeInferenceInfo> InferTypeInTupleExpression(
TupleExpressionSyntax tupleExpression, SyntaxToken previousToken)
{
if (previousToken == tupleExpression.OpenParenToken)
return InferTypeInTupleExpression(tupleExpression, tupleExpression.Arguments[0]);
if (previousToken.IsKind(SyntaxKind.CommaToken))
{
var argsAndCommas = tupleExpression.Arguments.GetWithSeparators();
var commaIndex = argsAndCommas.IndexOf(previousToken);
return InferTypeInTupleExpression(tupleExpression, (ArgumentSyntax)argsAndCommas[commaIndex + 1]);
}
return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
private IEnumerable<TypeInferenceInfo> InferTypeInTupleExpression(
TupleExpressionSyntax tupleExpression, ArgumentSyntax argument)
{
......@@ -1164,26 +1174,18 @@ private IEnumerable<TypeInferenceInfo> InferTypeInEqualsValueClause(EqualsValueC
{
// If we have a position, it has to be after the =
if (previousToken.HasValue && previousToken.Value != equalsValue.EqualsToken)
{
return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
if (equalsValue.IsParentKind(SyntaxKind.VariableDeclarator))
{
return InferTypeInVariableDeclarator((VariableDeclaratorSyntax)equalsValue.Parent);
}
if (equalsValue.IsParentKind(SyntaxKind.VariableDeclarator, out VariableDeclaratorSyntax varDecl))
return InferTypeInVariableDeclarator(varDecl);
if (equalsValue.IsParentKind(SyntaxKind.PropertyDeclaration))
{
return InferTypeInPropertyDeclaration((PropertyDeclarationSyntax)equalsValue.Parent);
}
if (equalsValue.IsParentKind(SyntaxKind.PropertyDeclaration, out PropertyDeclarationSyntax propertyDecl))
return InferTypeInPropertyDeclaration(propertyDecl);
if (equalsValue.IsParentKind(SyntaxKind.Parameter))
if (equalsValue.IsParentKind(SyntaxKind.Parameter) &&
SemanticModel.GetDeclaredSymbol(equalsValue.Parent, CancellationToken) is IParameterSymbol parameter)
{
if (SemanticModel.GetDeclaredSymbol(equalsValue.Parent, CancellationToken) is IParameterSymbol parameter)
{
return CreateResult(parameter.Type);
}
return CreateResult(parameter.Type);
}
return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
......@@ -1326,7 +1328,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
}
}
if (initializerExpression.IsParentKind(SyntaxKind.ImplicitArrayCreationExpression))
if (initializerExpression.IsParentKind(SyntaxKind.ImplicitArrayCreationExpression, out ImplicitArrayCreationExpressionSyntax implicitArray))
{
// new[] { 1, x }
......@@ -1334,7 +1336,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
// appropriate array type, then use the element type of the array. Otherwise,
// look at the siblings of this expression and use their type instead.
var arrayTypes = this.InferTypes((ExpressionSyntax)initializerExpression.Parent);
var arrayTypes = this.InferTypes(implicitArray);
var elementTypes = arrayTypes.OfType<IArrayTypeSymbol>().Select(a => new TypeInferenceInfo(a.ElementType)).Where(IsUsableTypeFunc);
if (elementTypes.Any())
......@@ -1354,10 +1356,9 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
}
}
}
else if (initializerExpression.IsParentKind(SyntaxKind.EqualsValueClause))
else if (initializerExpression.IsParentKind(SyntaxKind.EqualsValueClause, out EqualsValueClauseSyntax equalsValueClause))
{
// = { Goo() }
var equalsValueClause = (EqualsValueClauseSyntax)initializerExpression.Parent;
var types = InferTypeInEqualsValueClause(equalsValueClause).Select(t => t.InferredType);
if (types.Any(t => t is IArrayTypeSymbol))
......@@ -1365,10 +1366,9 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
return types.OfType<IArrayTypeSymbol>().Select(t => new TypeInferenceInfo(t.ElementType));
}
}
else if (initializerExpression.IsParentKind(SyntaxKind.ArrayCreationExpression))
else if (initializerExpression.IsParentKind(SyntaxKind.ArrayCreationExpression, out ArrayCreationExpressionSyntax arrayCreation))
{
// new int[] { Goo() }
var arrayCreation = (ArrayCreationExpressionSyntax)initializerExpression.Parent;
var types = GetTypes(arrayCreation).Select(t => t.InferredType);
if (types.Any(t => t is IArrayTypeSymbol))
......@@ -1376,12 +1376,9 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
return types.OfType<IArrayTypeSymbol>().Select(t => new TypeInferenceInfo(t.ElementType));
}
}
else if (initializerExpression.IsParentKind(SyntaxKind.ObjectCreationExpression))
else if (initializerExpression.IsParentKind(SyntaxKind.ObjectCreationExpression, out ObjectCreationExpressionSyntax objectCreation))
{
// new List<T> { Goo() }
var objectCreation = (ObjectCreationExpressionSyntax)initializerExpression.Parent;
var types = GetTypes(objectCreation).Select(t => t.InferredType);
if (types.Any(t => t is INamedTypeSymbol))
{
......@@ -1679,10 +1676,10 @@ private IEnumerable<TypeInferenceInfo> InferTypeInNameColon(NameColonSyntax name
// context.
var name = memberAccessExpression.Name.Identifier.Value;
if (name.Equals(nameof(Task<int>.ConfigureAwait)) &&
memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) &&
memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax invocation) &&
memberAccessExpression.Parent.IsParentKind(SyntaxKind.AwaitExpression))
{
return InferTypes((ExpressionSyntax)memberAccessExpression.Parent);
return InferTypes(invocation);
}
else if (name.Equals(nameof(Task<int>.ContinueWith)))
{
......@@ -1704,9 +1701,8 @@ private IEnumerable<TypeInferenceInfo> InferTypeInNameColon(NameColonSyntax name
// goo.Select
// We want to infer IEnumerable<T>. We can try to figure out what
// T if we get a delegate as the first argument to Select/Where.
if (ienumerableType != null && memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression))
if (ienumerableType != null && memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression, out invocation))
{
var invocation = (InvocationExpressionSyntax)memberAccessExpression.Parent;
if (invocation.ArgumentList.Arguments.Count > 0)
{
var argumentExpression = invocation.ArgumentList.Arguments[0].Expression;
......@@ -1719,10 +1715,9 @@ private IEnumerable<TypeInferenceInfo> InferTypeInNameColon(NameColonSyntax name
? delegateType.TypeArguments[0]
: this.Compilation.ObjectType;
if (IsUnusableType(typeArg) && argumentExpression is LambdaExpressionSyntax)
if (IsUnusableType(typeArg) && argumentExpression is LambdaExpressionSyntax lambdaExpression)
{
typeArg = InferTypeForFirstParameterOfLambda((LambdaExpressionSyntax)argumentExpression) ??
this.Compilation.ObjectType;
typeArg = InferTypeForFirstParameterOfLambda(lambdaExpression) ?? this.Compilation.ObjectType;
}
return CreateResult(ienumerableType.Construct(typeArg));
......@@ -2113,18 +2108,18 @@ private IEnumerable<TypeInferenceInfo> InferTypeInVariableDeclarator(VariableDec
private IEnumerable<TypeInferenceInfo> InferTypeInVariableComponentAssignment(ExpressionSyntax left)
{
if (left.IsKind(SyntaxKind.DeclarationExpression))
if (left.IsKind(SyntaxKind.DeclarationExpression, out DeclarationExpressionSyntax declExpr))
{
return GetTypes(((DeclarationExpressionSyntax)left).Type);
return GetTypes(declExpr.Type);
}
else if (left.IsKind(SyntaxKind.TupleExpression))
else if (left.IsKind(SyntaxKind.TupleExpression, out TupleExpressionSyntax tupleExpression))
{
// We have something of the form:
// (int a, int b) = ...
//
// This is a deconstruction, and a decent deconstructable type we can infer here
// is ValueTuple<int,int>.
var tupleType = GetTupleType((TupleExpressionSyntax)left);
var tupleType = GetTupleType(tupleExpression);
if (tupleType != null)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册