public override TypeStyleResult AnalyzeTypeName( TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) { if (typeName.StripRefIfNeeded().IsVar) { return(default);
internal static void ReplaceTypeWithVar(SyntaxEditor editor, TypeSyntax type) { type = type.StripRefIfNeeded(); var implicitType = SyntaxFactory.IdentifierName("var").WithTriviaFrom(type); editor.ReplaceNode(type, implicitType); }
internal override bool TryAnalyzeVariableDeclaration( TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) { // var (x, y) = e; // foreach (var (x, y) in e) ... if (typeName.IsParentKind(SyntaxKind.DeclarationExpression)) { var parent = (DeclarationExpressionSyntax)typeName.Parent; if (parent.Designation.IsKind(SyntaxKind.ParenthesizedVariableDesignation)) { return(true); } } // If it is currently not var, explicit typing exists, return. // this also takes care of cases where var is mapped to a named type via an alias or a class declaration. if (!typeName.StripRefIfNeeded().IsTypeInferred(semanticModel)) { return(false); } if (typeName.Parent.IsKind(SyntaxKind.VariableDeclaration) && typeName.Parent.Parent.IsKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.ForStatement, SyntaxKind.UsingStatement)) { // check assignment for variable declarations. var variableDeclaration = (VariableDeclarationSyntax)typeName.Parent; var variable = variableDeclaration.Variables.First(); if (!AssignmentSupportsStylePreference( variable.Identifier, typeName, variable.Initializer.Value, semanticModel, optionSet, cancellationToken)) { return(false); } // This error case is handled by a separate code fix (UseExplicitTypeForConst). if ((variableDeclaration.Parent as LocalDeclarationStatementSyntax)?.IsConst == true) { return(false); } } else if (typeName.Parent is ForEachStatementSyntax foreachStatement && foreachStatement.Type == typeName) { if (!AssignmentSupportsStylePreference( foreachStatement.Identifier, typeName, foreachStatement.Expression, semanticModel, optionSet, cancellationToken)) { return(false); } } return(true); }
/// <summary> /// Analyzes the assignment expression and rejects a given declaration if it is unsuitable for explicit typing. /// </summary> /// <returns> /// false, if explicit typing cannot be used. /// true, otherwise. /// </returns> protected override bool AssignmentSupportsStylePreference( SyntaxToken identifier, TypeSyntax typeName, ExpressionSyntax initializer, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) { // is or contains an anonymous type // cases : // var anon = new { Num = 1 }; // var enumerableOfAnons = from prod in products select new { prod.Color, prod.Price }; var declaredType = semanticModel.GetTypeInfo(typeName.StripRefIfNeeded(), cancellationToken).Type; if (declaredType.ContainsAnonymousType()) { return(false); } // cannot find type if initializer resolves to an ErrorTypeSymbol var initializerTypeInfo = semanticModel.GetTypeInfo(initializer, cancellationToken); return(!initializerTypeInfo.Type.IsErrorType()); }
internal static async Task HandleDeclarationAsync( Document document, SyntaxEditor editor, SyntaxNode node, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var declarationContext = node.Parent; TypeSyntax typeSyntax = null; ParenthesizedVariableDesignationSyntax parensDesignation = null; if (declarationContext is RefTypeSyntax refType) { declarationContext = declarationContext.Parent; } if (declarationContext is VariableDeclarationSyntax varDecl) { typeSyntax = varDecl.Type; } else if (declarationContext is ForEachStatementSyntax forEach) { typeSyntax = forEach.Type; } else if (declarationContext is DeclarationExpressionSyntax declarationExpression) { typeSyntax = declarationExpression.Type; if (declarationExpression.Designation.IsKind(SyntaxKind.ParenthesizedVariableDesignation)) { parensDesignation = (ParenthesizedVariableDesignationSyntax)declarationExpression.Designation; } } else { Contract.Fail($"unhandled kind {declarationContext.Kind().ToString()}"); } if (parensDesignation is null) { var typeSymbol = semanticModel.GetTypeInfo(typeSyntax.StripRefIfNeeded()).ConvertedType; // We're going to be passed through the simplifier. Tell it to not just convert // this back to var (as that would defeat the purpose of this refactoring entirely). var typeName = typeSymbol.GenerateTypeSyntax(allowVar: false) .WithLeadingTrivia(node.GetLeadingTrivia()) .WithTrailingTrivia(node.GetTrailingTrivia()); Debug.Assert(!typeName.ContainsDiagnostics, "Explicit type replacement likely introduced an error in code"); editor.ReplaceNode(node, typeName); } else { var tupleTypeSymbol = semanticModel.GetTypeInfo(typeSyntax.Parent).ConvertedType; var leadingTrivia = node.GetLeadingTrivia() .Concat(parensDesignation.GetAllPrecedingTriviaToPreviousToken().Where(t => !t.IsWhitespace()).Select(t => t.WithoutAnnotations(SyntaxAnnotation.ElasticAnnotation))); var tupleDeclaration = GenerateTupleDeclaration(tupleTypeSymbol, parensDesignation).WithLeadingTrivia(leadingTrivia); editor.ReplaceNode(declarationContext, tupleDeclaration); } }