提交 750b1ef6 编写于 作者: C Cyrus Najmabadi

Extract 'use var' from 'simplify type names'

上级 fb028b7c
......@@ -795,19 +795,9 @@ private static bool CanReplace(ISymbol symbol)
return memberAccess.TryReduce(semanticModel, out replacementNode, out issueSpan, optionSet, cancellationToken);
}
if (expression is TypeSyntax typeName)
if (expression is NameSyntax name)
{
// First, see if we can replace this type with var if that's what the user prefers.
// That always overrides all other simplification.
if (typeName.IsReplaceableByVar(semanticModel, out replacementNode, out issueSpan, optionSet, cancellationToken))
{
return true;
}
if (expression is NameSyntax name)
{
return name.TryReduce(semanticModel, out replacementNode, out issueSpan, optionSet, cancellationToken);
}
return name.TryReduce(semanticModel, out replacementNode, out issueSpan, optionSet, cancellationToken);
}
return false;
......@@ -1653,11 +1643,6 @@ private static int GetNamespaceId(SyntaxList<MemberDeclarationSyntax> members, N
var aliasInfo = semanticModel.GetAliasInfo(name, cancellationToken);
if (nameHasNoAlias && aliasInfo == null)
{
if (IsReplaceableByVar(name, semanticModel, out replacementNode, out issueSpan, optionSet, cancellationToken))
{
return true;
}
// Don't simplify to predefined type if name is part of a QualifiedName.
// QualifiedNames can't contain PredefinedTypeNames (although MemberAccessExpressions can).
// In other words, the left side of a QualifiedName can't be a PredefinedTypeName.
......@@ -2354,31 +2339,6 @@ private static bool IsThisOrTypeOrNamespace(MemberAccessExpressionSyntax memberA
return false;
}
private static bool IsReplaceableByVar(
this TypeSyntax simpleName,
SemanticModel semanticModel,
out TypeSyntax replacementNode,
out TextSpan issueSpan,
OptionSet optionSet,
CancellationToken cancellationToken)
{
var typeStyle = CSharpUseImplicitTypeHelper.Instance.AnalyzeTypeName(
simpleName, semanticModel, optionSet, cancellationToken);
if (!typeStyle.IsStylePreferred || !typeStyle.CanConvert())
{
replacementNode = null;
issueSpan = default;
return false;
}
replacementNode = SyntaxFactory.IdentifierName("var")
.WithLeadingTrivia(simpleName.GetLeadingTrivia())
.WithTrailingTrivia(simpleName.GetTrailingTrivia());
issueSpan = simpleName.Span;
return true;
}
private static bool ContainsOpenName(NameSyntax name)
{
if (name is QualifiedNameSyntax qualifiedName)
......
......@@ -23,6 +23,7 @@ internal partial class CSharpSimplificationService : AbstractSimplificationServi
// 2. Extension method reducer may insert parentheses. So run it before the parentheses remover.
private static readonly ImmutableArray<AbstractReducer> s_reducers =
ImmutableArray.Create<AbstractReducer>(
new CSharpVarReducer(),
new CSharpNameReducer(),
new CSharpNullableAnnotationReducer(),
new CSharpCastReducer(),
......
......@@ -20,9 +20,9 @@ protected abstract class AbstractReductionRewriter : CSharpSyntaxRewriter, IRedu
private readonly ObjectPool<IReductionRewriter> _pool;
protected CSharpParseOptions ParseOptions { get; private set; }
private OptionSet _optionSet;
private CancellationToken _cancellationToken;
private SemanticModel _semanticModel;
protected OptionSet OptionSet { get; private set; }
protected CancellationToken CancellationToken { get; private set; }
protected SemanticModel SemanticModel { get; private set; }
public bool HasMoreWork { get; private set; }
......@@ -38,17 +38,17 @@ protected AbstractReductionRewriter(ObjectPool<IReductionRewriter> pool)
public void Initialize(ParseOptions parseOptions, OptionSet optionSet, CancellationToken cancellationToken)
{
ParseOptions = (CSharpParseOptions)parseOptions;
_optionSet = optionSet;
_cancellationToken = cancellationToken;
OptionSet = optionSet;
CancellationToken = cancellationToken;
}
public void Dispose()
{
ParseOptions = null;
_optionSet = null;
_cancellationToken = CancellationToken.None;
OptionSet = null;
CancellationToken = CancellationToken.None;
_processedParentNodes.Clear();
_semanticModel = null;
SemanticModel = null;
HasMoreWork = false;
alwaysSimplify = false;
......@@ -72,12 +72,16 @@ private static SyntaxNode GetParentNode(SyntaxNode node)
private static SyntaxNode GetParentNode(ExpressionSyntax expression)
{
var topMostExpression = expression
.AncestorsAndSelf()
.OfType<ExpressionSyntax>()
.LastOrDefault();
var lastExpression = expression;
for (SyntaxNode current = expression; current != null; current = current.Parent)
{
if (current is ExpressionSyntax currentExpression)
{
lastExpression = currentExpression;
}
}
return topMostExpression.Parent;
return lastExpression.Parent;
}
private static SyntaxNode GetParentNode(CrefSyntax cref)
......@@ -107,7 +111,7 @@ private static SyntaxNode GetParentNode(StatementSyntax statement)
{
Debug.Assert(parentNode != null);
_cancellationToken.ThrowIfCancellationRequested();
this.CancellationToken.ThrowIfCancellationRequested();
if (!this.alwaysSimplify && !node.HasAnnotation(Simplifier.Annotation))
{
......@@ -122,7 +126,7 @@ private static SyntaxNode GetParentNode(StatementSyntax statement)
if (!node.HasAnnotation(SimplificationHelpers.DontSimplifyAnnotation))
{
var simplifiedNode = simplifier(node, _semanticModel, _optionSet, _cancellationToken);
var simplifiedNode = simplifier(node, this.SemanticModel, this.OptionSet, this.CancellationToken);
if (simplifiedNode != node)
{
_processedParentNodes.Add(parentNode);
......@@ -151,10 +155,10 @@ private static SyntaxNode GetParentNode(StatementSyntax statement)
protected SyntaxToken SimplifyToken(SyntaxToken token, Func<SyntaxToken, SemanticModel, OptionSet, CancellationToken, SyntaxToken> simplifier)
{
_cancellationToken.ThrowIfCancellationRequested();
this.CancellationToken.ThrowIfCancellationRequested();
return token.HasAnnotation(Simplifier.Annotation)
? simplifier(token, _semanticModel, _optionSet, _cancellationToken)
? simplifier(token, this.SemanticModel, this.OptionSet, this.CancellationToken)
: token;
}
......@@ -178,7 +182,7 @@ public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax
public SyntaxNodeOrToken VisitNodeOrToken(SyntaxNodeOrToken nodeOrToken, SemanticModel semanticModel, bool simplifyAllDescendants)
{
_semanticModel = semanticModel;
this.SemanticModel = semanticModel;
this.alwaysSimplify = simplifyAllDescendants;
this.HasMoreWork = false;
_processedParentNodes.Clear();
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Simplification;
namespace Microsoft.CodeAnalysis.CSharp.Simplification
{
internal partial class CSharpVarReducer
{
private class Rewriter : AbstractReductionRewriter
{
public Rewriter(ObjectPool<IReductionRewriter> pool)
: base(pool)
{
}
private SyntaxNode ProcessTypeSyntax(TypeSyntax typeSyntax)
{
this.CancellationToken.ThrowIfCancellationRequested();
if (!alwaysSimplify && !typeSyntax.HasAnnotation(Simplifier.Annotation))
{
return typeSyntax;
}
if (typeSyntax.HasAnnotation(SimplificationHelpers.DontSimplifyAnnotation))
{
return typeSyntax;
}
var typeStyle = CSharpUseImplicitTypeHelper.Instance.AnalyzeTypeName(
typeSyntax, this.SemanticModel, this.OptionSet, this.CancellationToken);
if (!typeStyle.IsStylePreferred || !typeStyle.CanConvert())
{
return typeSyntax;
}
return SyntaxFactory.IdentifierName("var")
.WithLeadingTrivia(typeSyntax.GetLeadingTrivia())
.WithTrailingTrivia(typeSyntax.GetTrailingTrivia());
}
public override SyntaxNode VisitPredefinedType(PredefinedTypeSyntax node)
=> ProcessTypeSyntax(node);
public override SyntaxNode VisitAliasQualifiedName(AliasQualifiedNameSyntax node)
=> ProcessTypeSyntax(node);
public override SyntaxNode VisitQualifiedName(QualifiedNameSyntax node)
=> ProcessTypeSyntax(node);
public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
=> ProcessTypeSyntax(node);
public override SyntaxNode VisitGenericName(GenericNameSyntax node)
=> ProcessTypeSyntax(node);
public override SyntaxNode VisitArrayType(ArrayTypeSyntax node)
=> ProcessTypeSyntax(node);
public override SyntaxNode VisitNullableType(NullableTypeSyntax node)
=> ProcessTypeSyntax(node);
public override SyntaxNode VisitPointerType(PointerTypeSyntax node)
=> ProcessTypeSyntax(node);
public override SyntaxNode VisitTupleType(TupleTypeSyntax node)
=> ProcessTypeSyntax(node);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CSharp.Simplification
{
internal partial class CSharpVarReducer : AbstractCSharpReducer
{
private static readonly ObjectPool<IReductionRewriter> s_pool = new ObjectPool<IReductionRewriter>(
() => new Rewriter(s_pool));
public CSharpVarReducer() : base(s_pool)
{
}
}
}
......@@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Utilities
{
internal partial class CSharpTypeStyleHelper
{
protected class State
protected struct State
{
private readonly Dictionary<UseVarPreference, ReportDiagnostic> _styleToSeverityMap;
......@@ -25,6 +25,10 @@ protected class State
private State(bool isVariableDeclarationContext)
{
TypeStylePreference = default;
IsInIntrinsicTypeContext = default;
IsTypeApparentInContext = default;
this.IsInVariableDeclarationContext = isVariableDeclarationContext;
_styleToSeverityMap = new Dictionary<UseVarPreference, ReportDiagnostic>();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册