// 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.Options; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.CSharp.Extensions { internal static class CrefSyntaxExtensions { public static bool TryReduceOrSimplifyExplicitName( this CrefSyntax crefSyntax, SemanticModel semanticModel, out CrefSyntax replacementNode, out TextSpan issueSpan, OptionSet optionSet, CancellationToken cancellationToken) { replacementNode = null; issueSpan = default(TextSpan); // Currently Qualified Cref is the only CrefSyntax We are handling separately if (crefSyntax.Kind() != SyntaxKind.QualifiedCref) { return false; } var qualifiedCrefSyntax = (QualifiedCrefSyntax)crefSyntax; var memberCref = qualifiedCrefSyntax.Member; // Currently we are dealing with only the NameMemberCrefs if (optionSet.GetOption(SimplificationOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, LanguageNames.CSharp) && (memberCref.Kind() == SyntaxKind.NameMemberCref)) { var nameMemberCref = ((NameMemberCrefSyntax)memberCref).Name; var symbolInfo = semanticModel.GetSymbolInfo(nameMemberCref, cancellationToken); var symbol = symbolInfo.Symbol; if (symbol == null) { return false; } if (symbol is INamespaceOrTypeSymbol) { var namespaceOrTypeSymbol = (INamespaceOrTypeSymbol)symbol; // 1. Check for Predefined Types if (symbol is INamedTypeSymbol) { var namedSymbol = (INamedTypeSymbol)symbol; var keywordKind = ExpressionSyntaxExtensions.GetPredefinedKeywordKind(namedSymbol.SpecialType); if (keywordKind != SyntaxKind.None) { replacementNode = SyntaxFactory.TypeCref( SyntaxFactory.PredefinedType( SyntaxFactory.Token(crefSyntax.GetLeadingTrivia(), keywordKind, crefSyntax.GetTrailingTrivia()))); replacementNode = crefSyntax.CopyAnnotationsTo(replacementNode); // we want to show the whole name expression as unnecessary issueSpan = crefSyntax.Span; return true; } } } } var oldSymbol = semanticModel.GetSymbolInfo(crefSyntax, cancellationToken).Symbol; if (oldSymbol != null) { var speculativeBindingOption = SpeculativeBindingOption.BindAsExpression; if (oldSymbol is INamespaceOrTypeSymbol) { speculativeBindingOption = SpeculativeBindingOption.BindAsTypeOrNamespace; } var newSymbol = semanticModel.GetSpeculativeSymbolInfo(crefSyntax.SpanStart, memberCref, speculativeBindingOption).Symbol; if (newSymbol == oldSymbol) { // Copy Trivia and Annotations memberCref = memberCref.WithLeadingTrivia(crefSyntax.GetLeadingTrivia()); memberCref = crefSyntax.CopyAnnotationsTo(memberCref); issueSpan = qualifiedCrefSyntax.Container.Span; replacementNode = memberCref; return true; } } return false; } } }