/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Analyzers/CSharp/CodeFixes/AddExplicitCast/CSharpAddExplicitCastCodeFixProvider.cs
110 строк
5 KB
Cyrus Najmabadi
Simplify
01 июл 2024, 23:16
01 июл 2024, 23:16
5615c2c
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Immutable; using System.Composition; using System.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeFixes.AddExplicitCast; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.AddExplicitCast; [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.AddExplicitCast), Shared] [method: ImportingConstructor] [method: SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] internal sealed partial class CSharpAddExplicitCastCodeFixProvider() : AbstractAddExplicitCastCodeFixProvider<ExpressionSyntax> { /// <summary> /// CS0266: Cannot implicitly convert from type 'x' to 'y'. An explicit conversion exists (are you missing a cast?) /// </summary> private const string CS0266 = nameof(CS0266); /// <summary> /// CS1503: Argument 1: cannot convert from 'x' to 'y' /// </summary> private const string CS1503 = nameof(CS1503); private readonly ArgumentFixer _argumentFixer = new(); private readonly AttributeArgumentFixer _attributeArgumentFixer = new(); public override ImmutableArray<string> FixableDiagnosticIds => [CS0266, CS1503]; protected override void GetPartsOfCastOrConversionExpression(ExpressionSyntax expression, out SyntaxNode type, out ExpressionSyntax castedExpression) { var castExpression = (CastExpressionSyntax)expression; type = castExpression.Type; castedExpression = castExpression.Expression; } protected override ExpressionSyntax Cast(ExpressionSyntax expression, ITypeSymbol type) => expression.Cast(type); protected override void AddPotentialTargetTypes( Document document, SemanticModel semanticModel, SyntaxNode root, string diagnosticId, ExpressionSyntax spanNode, ArrayBuilder<(ExpressionSyntax node, ITypeSymbol type)> candidates, CancellationToken cancellationToken) { if (diagnosticId == CS0266) { var inferenceService = document.GetRequiredLanguageService<ITypeInferenceService>(); var conversionType = inferenceService.InferType(semanticModel, spanNode, objectAsDefault: false, cancellationToken); if (conversionType is null) return; candidates.Add((spanNode, conversionType)); } else if (diagnosticId == CS1503) { if (spanNode.GetAncestorOrThis<ArgumentSyntax>() is ArgumentSyntax targetArgument && targetArgument.Parent is ArgumentListSyntax argumentList && argumentList.Parent is SyntaxNode invocationNode) { // invocationNode could be Invocation Expression, Object Creation, Base Constructor...) candidates.AddRange(_argumentFixer.GetPotentialConversionTypes( document, semanticModel, root, targetArgument, argumentList, invocationNode, cancellationToken)); } else if (spanNode.GetAncestorOrThis<AttributeArgumentSyntax>() is AttributeArgumentSyntax targetAttributeArgument && targetAttributeArgument.Parent is AttributeArgumentListSyntax attributeArgumentList && attributeArgumentList.Parent is AttributeSyntax attributeNode) { // attribute node candidates.AddRange(_attributeArgumentFixer.GetPotentialConversionTypes( document, semanticModel, root, targetAttributeArgument, attributeArgumentList, attributeNode, cancellationToken)); } } } protected override (SyntaxNode finalTarget, SyntaxNode finalReplacement) Cast( SemanticModel semanticModel, ExpressionSyntax targetNode, ITypeSymbol conversionType) { // The compiler is very ambiguous with assignment expressions `(a += b)`. An error on it may be an error on the // entire expression or on the RHS of the assignment. Have to reverse engineer what it is doing here. if (targetNode is AssignmentExpressionSyntax assignmentExpression && assignmentExpression.IsCompoundAssignExpression()) { var leftType = semanticModel.GetTypeInfo(assignmentExpression.Left).Type; var rightType = semanticModel.GetTypeInfo(assignmentExpression.Right).Type; if (leftType != null && rightType != null) { var conversion = semanticModel.Compilation.ClassifyConversion(rightType, leftType); if (conversion.Exists && conversion.IsExplicit) return (assignmentExpression.Right, this.Cast(assignmentExpression.Right, leftType)); } } return base.Cast(semanticModel, targetNode, conversionType); } }