| File: GenerateFromMembers\GenerateFromMembersHelpers.cs | Web Access |
| Project: src\roslyn\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features) |
// 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.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Naming; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.GenerateFromMembers; internal static class GenerateFromMembersHelpers { public static async Task<SelectedMemberInfo?> GetSelectedMemberInfoAsync( Document document, TextSpan textSpan, bool allowPartialSelection, CancellationToken cancellationToken) { var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>(); var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var selectedDeclarations = await syntaxFacts.GetSelectedFieldsAndPropertiesAsync( tree, textSpan, allowPartialSelection, cancellationToken).ConfigureAwait(false); if (selectedDeclarations.Length > 0) { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var selectedMembers = selectedDeclarations.Select( d => semanticModel.GetDeclaredSymbol(d, cancellationToken)).WhereNotNull().ToImmutableArray(); if (selectedMembers.Length > 0) { var containingType = selectedMembers.First().ContainingType; if (containingType != null) { return new SelectedMemberInfo(containingType, selectedDeclarations, selectedMembers); } } } return null; } public static bool IsReadableInstanceFieldOrProperty(ISymbol symbol) => !symbol.IsStatic && IsReadableFieldOrProperty(symbol); public static bool IsWritableInstanceFieldOrProperty(ISymbol symbol) => !symbol.IsStatic && IsWritableFieldOrProperty(symbol); private static bool IsReadableFieldOrProperty(ISymbol symbol) => symbol switch { IFieldSymbol field => IsViableField(field), IPropertySymbol property => IsViableProperty(property) && !property.IsWriteOnly, _ => false, }; private static bool IsWritableFieldOrProperty(ISymbol symbol) => symbol switch { // Can use non const fields and properties with setters in them. IFieldSymbol field => IsViableField(field) && !field.IsConst, IPropertySymbol property => IsViableProperty(property) && property.IsWritableInConstructor(), _ => false, }; private static bool IsViableField(IFieldSymbol field) => field is { AssociatedSymbol: null, CanBeReferencedByName: true }; private static bool IsViableProperty(IPropertySymbol property) => property is { Parameters.IsEmpty: true, CanBeReferencedByName: true }; /// <summary> /// Returns an array of parameter symbols that correspond to selected member symbols. /// If a selected member symbol has an empty base identifier name, the parameter symbol will not be added. /// </summary> /// <param name="selectedMembers"></param> /// <param name="rules"></param> public static ImmutableArray<(IParameterSymbol parameter, ISymbol fieldProperty)> DetermineParameters( ImmutableArray<ISymbol> selectedMembers, ImmutableArray<NamingRule> rules) { using var _ = ArrayBuilder<(IParameterSymbol parameter, ISymbol fieldProperty)>.GetInstance(out var parameters); foreach (var symbol in selectedMembers) { var type = symbol.GetMemberType(); if (type == null) continue; var identifierNameParts = IdentifierNameParts.CreateIdentifierNameParts(symbol, rules); if (identifierNameParts.BaseName == "") continue; var parameterNamingRule = rules.Where(rule => rule.SymbolSpecification.AppliesTo(SymbolKind.Parameter, Accessibility.NotApplicable)).First(); var parameterName = parameterNamingRule.NamingStyle.MakeCompliant(identifierNameParts.BaseName).First(); parameters.Add((CodeGenerationSymbolFactory.CreateParameterSymbol( attributes: default, refKind: RefKind.None, isParams: false, type: type, name: parameterName), symbol)); } return parameters.ToImmutableAndClear(); } public static readonly SymbolDisplayFormat SimpleFormat = new( typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly, genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, parameterOptions: SymbolDisplayParameterOptions.IncludeParamsRefOut | SymbolDisplayParameterOptions.IncludeType, miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes); }