From a62de54d0eae8da55d5214dc3c03d1b4cadaa80f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 24 May 2021 21:37:15 -0700 Subject: [PATCH] NRTenable --- .../GenerateConversionCodeFixProvider.cs | 6 +- .../GenerateMethodCodeFixProvider.cs | 2 +- .../GenerateTypeCodeFixProvider.cs | 2 +- .../AbstractGenerateMemberCodeFixProvider.cs | 2 +- .../Pythia/Api/PythiaSyntaxExtensions.cs | 2 +- .../Extensions/ExpressionSyntaxExtensions.cs | 87 ++++++++++--------- 6 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateConversionCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateConversionCodeFixProvider.cs index 5cffa6cd2e1c7..138f868763ba6 100644 --- a/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateConversionCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateConversionCodeFixProvider.cs @@ -46,17 +46,13 @@ node is SimpleNameSyntax || node is ExpressionSyntax; } - protected override SyntaxNode GetTargetNode(SyntaxNode node) + protected override SyntaxNode? GetTargetNode(SyntaxNode node) { if (node is InvocationExpressionSyntax invocation) - { return invocation.Expression.GetRightmostName(); - } if (node is MemberBindingExpressionSyntax memberBindingExpression) - { return memberBindingExpression.Name; - } return node; } diff --git a/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateMethodCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateMethodCodeFixProvider.cs index f8b2c9a791d67..c0a307f077a85 100644 --- a/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateMethodCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateMethodCodeFixProvider.cs @@ -76,7 +76,7 @@ node is SimpleNameSyntax || node is ExpressionSyntax; } - protected override SyntaxNode GetTargetNode(SyntaxNode node) + protected override SyntaxNode? GetTargetNode(SyntaxNode node) { switch (node) { diff --git a/src/Features/CSharp/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.cs index c9206be502d5d..0ad17420edac7 100644 --- a/src/Features/CSharp/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.cs @@ -57,7 +57,7 @@ protected override bool IsCandidate(SyntaxNode node, SyntaxToken token, Diagnost return false; } - protected override SyntaxNode GetTargetNode(SyntaxNode node) + protected override SyntaxNode? GetTargetNode(SyntaxNode node) => ((ExpressionSyntax)node).GetRightmostName(); protected override Task> GetCodeActionsAsync( diff --git a/src/Features/Core/Portable/CodeFixes/GenerateMember/AbstractGenerateMemberCodeFixProvider.cs b/src/Features/Core/Portable/CodeFixes/GenerateMember/AbstractGenerateMemberCodeFixProvider.cs index db10642703a8d..0963f4fd751de 100644 --- a/src/Features/Core/Portable/CodeFixes/GenerateMember/AbstractGenerateMemberCodeFixProvider.cs +++ b/src/Features/Core/Portable/CodeFixes/GenerateMember/AbstractGenerateMemberCodeFixProvider.cs @@ -54,7 +54,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) } } - protected virtual SyntaxNode GetTargetNode(SyntaxNode node) + protected virtual SyntaxNode? GetTargetNode(SyntaxNode node) => node; private IEnumerable GetTargetNodes( diff --git a/src/Workspaces/CSharp/Portable/ExternalAccess/Pythia/Api/PythiaSyntaxExtensions.cs b/src/Workspaces/CSharp/Portable/ExternalAccess/Pythia/Api/PythiaSyntaxExtensions.cs index b494a7557f463..57a9b2f0ffe53 100644 --- a/src/Workspaces/CSharp/Portable/ExternalAccess/Pythia/Api/PythiaSyntaxExtensions.cs +++ b/src/Workspaces/CSharp/Portable/ExternalAccess/Pythia/Api/PythiaSyntaxExtensions.cs @@ -22,7 +22,7 @@ public static SyntaxToken FindTokenOnLeftOfPosition(this SyntaxTree syntaxTree, public static bool IsFoundUnder(this SyntaxNode node, Func childGetter) where TParent : SyntaxNode => Shared.Extensions.SyntaxNodeExtensions.IsFoundUnder(node, childGetter); - public static SimpleNameSyntax GetRightmostName(this ExpressionSyntax node) + public static SimpleNameSyntax? GetRightmostName(this ExpressionSyntax node) => CSharp.Extensions.ExpressionSyntaxExtensions.GetRightmostName(node); public static bool IsInStaticContext(this SyntaxNode node) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/ExpressionSyntaxExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/ExpressionSyntaxExtensions.cs index 084825335ead7..68a6c3deaea5a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/ExpressionSyntaxExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/ExpressionSyntaxExtensions.cs @@ -2,9 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - -using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -20,7 +17,7 @@ internal static partial class ExpressionSyntaxExtensions { public static ExpressionSyntax WalkUpParentheses(this ExpressionSyntax expression) { - while (expression.IsParentKind(SyntaxKind.ParenthesizedExpression, out ExpressionSyntax parentExpr)) + while (expression.IsParentKind(SyntaxKind.ParenthesizedExpression, out ExpressionSyntax? parentExpr)) expression = parentExpr; return expression; @@ -28,7 +25,7 @@ public static ExpressionSyntax WalkUpParentheses(this ExpressionSyntax expressio public static ExpressionSyntax WalkDownParentheses(this ExpressionSyntax expression) { - while (expression.IsKind(SyntaxKind.ParenthesizedExpression, out ParenthesizedExpressionSyntax parenExpression)) + while (expression.IsKind(SyntaxKind.ParenthesizedExpression, out ParenthesizedExpressionSyntax? parenExpression)) expression = parenExpression.Expression; return expression; @@ -37,8 +34,8 @@ public static ExpressionSyntax WalkDownParentheses(this ExpressionSyntax express public static bool IsQualifiedCrefName(this ExpressionSyntax expression) => expression.IsParentKind(SyntaxKind.NameMemberCref) && expression.Parent.IsParentKind(SyntaxKind.QualifiedCref); - public static bool IsSimpleMemberAccessExpressionName(this ExpressionSyntax expression) - => expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression, out MemberAccessExpressionSyntax memberAccess) && memberAccess.Name == expression; + public static bool IsSimpleMemberAccessExpressionName([NotNullWhen(true)] this ExpressionSyntax? expression) + => expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression, out MemberAccessExpressionSyntax? memberAccess) && memberAccess.Name == expression; public static bool IsAnyMemberAccessExpressionName(this ExpressionSyntax expression) { @@ -51,15 +48,15 @@ public static bool IsAnyMemberAccessExpressionName(this ExpressionSyntax express expression.IsMemberBindingExpressionName(); } - public static bool IsMemberBindingExpressionName(this ExpressionSyntax expression) - => expression.IsParentKind(SyntaxKind.MemberBindingExpression, out MemberBindingExpressionSyntax memberBinding) && + public static bool IsMemberBindingExpressionName([NotNullWhen(true)] this ExpressionSyntax? expression) + => expression.IsParentKind(SyntaxKind.MemberBindingExpression, out MemberBindingExpressionSyntax? memberBinding) && memberBinding.Name == expression; - public static bool IsRightSideOfQualifiedName(this ExpressionSyntax expression) - => expression.IsParentKind(SyntaxKind.QualifiedName, out QualifiedNameSyntax qualifiedName) && qualifiedName.Right == expression; + public static bool IsRightSideOfQualifiedName([NotNullWhen(true)] this ExpressionSyntax? expression) + => expression.IsParentKind(SyntaxKind.QualifiedName, out QualifiedNameSyntax? qualifiedName) && qualifiedName.Right == expression; public static bool IsRightSideOfColonColon(this ExpressionSyntax expression) - => expression.IsParentKind(SyntaxKind.AliasQualifiedName, out AliasQualifiedNameSyntax aliasName) && aliasName.Name == expression; + => expression.IsParentKind(SyntaxKind.AliasQualifiedName, out AliasQualifiedNameSyntax? aliasName) && aliasName.Name == expression; public static bool IsRightSideOfDot(this ExpressionSyntax name) => IsSimpleMemberAccessExpressionName(name) || IsMemberBindingExpressionName(name) || IsRightSideOfQualifiedName(name) || IsQualifiedCrefName(name); @@ -80,19 +77,17 @@ public static bool IsRightOfCloseParen(this ExpressionSyntax expression) && firstToken.GetPreviousToken().Kind() == SyntaxKind.CloseParenToken; } - public static bool IsLeftSideOfDot(this ExpressionSyntax expression) + public static bool IsLeftSideOfDot([NotNullWhen(true)] this ExpressionSyntax? expression) { if (expression == null) - { return false; - } return IsLeftSideOfQualifiedName(expression) || IsLeftSideOfSimpleMemberAccessExpression(expression); } public static bool IsLeftSideOfSimpleMemberAccessExpression(this ExpressionSyntax expression) - => (expression?.Parent).IsKind(SyntaxKind.SimpleMemberAccessExpression, out MemberAccessExpressionSyntax memberAccess) && + => (expression?.Parent).IsKind(SyntaxKind.SimpleMemberAccessExpression, out MemberAccessExpressionSyntax? memberAccess) && memberAccess.Expression == expression; public static bool IsLeftSideOfDotOrArrow(this ExpressionSyntax expression) @@ -100,16 +95,16 @@ public static bool IsLeftSideOfDotOrArrow(this ExpressionSyntax expression) (expression.Parent is MemberAccessExpressionSyntax memberAccess && memberAccess.Expression == expression); public static bool IsLeftSideOfQualifiedName(this ExpressionSyntax expression) - => (expression?.Parent).IsKind(SyntaxKind.QualifiedName, out QualifiedNameSyntax qualifiedName) && qualifiedName.Left == expression; + => (expression?.Parent).IsKind(SyntaxKind.QualifiedName, out QualifiedNameSyntax? qualifiedName) && qualifiedName.Left == expression; - public static bool IsLeftSideOfExplicitInterfaceSpecifier(this NameSyntax name) + public static bool IsLeftSideOfExplicitInterfaceSpecifier([NotNullWhen(true)] this NameSyntax? name) => name.IsParentKind(SyntaxKind.ExplicitInterfaceSpecifier); public static bool IsExpressionOfInvocation(this ExpressionSyntax expression) - => expression.IsParentKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax invocation) && + => expression.IsParentKind(SyntaxKind.InvocationExpression, out InvocationExpressionSyntax? invocation) && invocation.Expression == expression; - public static bool TryGetNameParts(this ExpressionSyntax expression, out IList parts) + public static bool TryGetNameParts(this ExpressionSyntax expression, [NotNullWhen(true)] out IList? parts) { var partsList = new List(); if (!TryGetNameParts(expression, partsList)) @@ -124,7 +119,7 @@ public static bool TryGetNameParts(this ExpressionSyntax expression, out IList parts) { - if (expression.IsKind(SyntaxKind.SimpleMemberAccessExpression, out MemberAccessExpressionSyntax memberAccess)) + if (expression.IsKind(SyntaxKind.SimpleMemberAccessExpression, out MemberAccessExpressionSyntax? memberAccess)) { if (!TryGetNameParts(memberAccess.Expression, parts)) { @@ -133,7 +128,7 @@ public static bool TryGetNameParts(this ExpressionSyntax expression, List part public static bool IsAnyLiteralExpression(this ExpressionSyntax expression) => expression is LiteralExpressionSyntax; - public static bool IsInConstantContext(this ExpressionSyntax expression) + public static bool IsInConstantContext([NotNullWhen(true)] this ExpressionSyntax? expression) { + if (expression == null) + return false; + if (expression.GetAncestor() != null) - { return true; - } var attributeArgument = expression.GetAncestor(); if (attributeArgument != null) @@ -184,9 +180,7 @@ public static bool IsInConstantContext(this ExpressionSyntax expression) } if (expression.IsParentKind(SyntaxKind.ConstantPattern)) - { return true; - } // note: the above list is not intended to be exhaustive. If more cases // are discovered that should be considered 'constant' contexts in the @@ -213,7 +207,7 @@ private static ExpressionSyntax GetExpressionToAnalyzeForWrites(ExpressionSyntax { if (expression.IsRightSideOfDotOrArrow()) { - expression = expression.Parent as ExpressionSyntax; + expression = (ExpressionSyntax)expression.GetRequiredParent(); } expression = expression.WalkUpParentheses(); @@ -348,7 +342,7 @@ public static bool IsWrittenTo(this ExpressionSyntax expression, SemanticModel s expression == memberAccess.Expression) { var symbol = semanticModel.GetSymbolInfo(memberAccess, cancellationToken).Symbol; - if (symbol is IMethodSymbol { MethodKind: MethodKind.ReducedExtension, ReducedFrom: var reducedFrom } && + if (symbol is IMethodSymbol { MethodKind: MethodKind.ReducedExtension, ReducedFrom: IMethodSymbol reducedFrom } && reducedFrom.Parameters.Length > 0 && reducedFrom.Parameters.First().RefKind == RefKind.Ref) { @@ -359,7 +353,7 @@ public static bool IsWrittenTo(this ExpressionSyntax expression, SemanticModel s return false; } - public static bool IsAttributeNamedArgumentIdentifier(this ExpressionSyntax expression) + public static bool IsAttributeNamedArgumentIdentifier([NotNullWhen(true)] this ExpressionSyntax? expression) { var nameEquals = expression?.Parent as NameEqualsSyntax; return nameEquals.IsParentKind(SyntaxKind.AttributeArgument); @@ -367,9 +361,9 @@ public static bool IsAttributeNamedArgumentIdentifier(this ExpressionSyntax expr public static bool IsOperandOfIncrementOrDecrementExpression(this ExpressionSyntax expression) { - if (expression != null) + if (expression?.Parent is SyntaxNode parent) { - switch (expression.Parent.Kind()) + switch (parent.Kind()) { case SyntaxKind.PostIncrementExpression: case SyntaxKind.PreIncrementExpression: @@ -478,9 +472,12 @@ public static bool CanReplaceWithLValue( // is some form of member binding expression and they cannot be replaced with an LValue. if (expression.IsKind(SyntaxKind.ConditionalAccessExpression)) { - return expression.Parent.Kind() != SyntaxKind.ConditionalAccessExpression; + return expression is { Parent: { RawKind: not (int)SyntaxKind.ConditionalAccessExpression } }; } + if (expression.Parent == null) + return false; + switch (expression.Parent.Kind()) { case SyntaxKind.InvocationExpression: @@ -569,7 +566,7 @@ public static bool CanReplaceWithLValue( } if (parentNonExpression != null && - parentNonExpression.IsKind(SyntaxKind.FromClause, out FromClauseSyntax fromClause) && + parentNonExpression.IsKind(SyntaxKind.FromClause, out FromClauseSyntax? fromClause) && topExpression != null && fromClause.Type == topExpression) { @@ -640,10 +637,18 @@ public static bool CanAccessInstanceAndStaticMembersOffOf( public static bool IsNameOfArgumentExpression(this ExpressionSyntax expression) { - return expression.IsParentKind(SyntaxKind.Argument) && - expression.Parent.IsParentKind(SyntaxKind.ArgumentList) && - expression.Parent.Parent.Parent is InvocationExpressionSyntax invocation && - invocation.IsNameOfInvocation(); + return expression is + { + Parent: + { + RawKind: (int)SyntaxKind.Argument, + Parent: + { + RawKind: (int)SyntaxKind.ArgumentList, + Parent: InvocationExpressionSyntax invocation + } + } + } && invocation.IsNameOfInvocation(); } public static bool IsNameOfInvocation(this InvocationExpressionSyntax invocation) @@ -652,7 +657,7 @@ public static bool IsNameOfInvocation(this InvocationExpressionSyntax invocation identifierName.Identifier.IsKindOrHasMatchingText(SyntaxKind.NameOfKeyword); } - public static SimpleNameSyntax GetRightmostName(this ExpressionSyntax node) + public static SimpleNameSyntax? GetRightmostName(this ExpressionSyntax node) { if (node is MemberAccessExpressionSyntax memberAccess && memberAccess.Name != null) { @@ -847,7 +852,7 @@ public static bool TryConvertToStatement( this ExpressionSyntax expression, SyntaxToken? semicolonTokenOpt, bool createReturnStatementForExpression, - out StatementSyntax statement) + [NotNullWhen(true)] out StatementSyntax? statement) { // It's tricky to convert an arrow expression with directives over to a block. // We'd need to find and remove the directives *after* the arrow expression and @@ -866,7 +871,7 @@ public static bool TryConvertToStatement( private static StatementSyntax ConvertToStatement(ExpressionSyntax expression, SyntaxToken semicolonToken, bool createReturnStatementForExpression) { - if (expression.IsKind(SyntaxKind.ThrowExpression, out ThrowExpressionSyntax throwExpression)) + if (expression.IsKind(SyntaxKind.ThrowExpression, out ThrowExpressionSyntax? throwExpression)) { return SyntaxFactory.ThrowStatement(throwExpression.ThrowKeyword, throwExpression.Expression, semicolonToken); }