| File: Snippets\SnippetProviders\AbstractForLoopSnippetProvider.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.Linq; using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.Snippets.SnippetProviders; internal abstract class AbstractForLoopSnippetProvider<TStatementSyntax> : AbstractInlineStatementSnippetProvider<TStatementSyntax> where TStatementSyntax : SyntaxNode { protected sealed override bool IsValidAccessingType(ITypeSymbol type, Compilation compilation) { if (IsSuitableIntegerType(type)) { return true; } var hasLengthProperty = FindLengthProperty(type, compilation) is not null; var hasCountProperty = FindCountProperty(type, compilation) is not null; // We want to allow types, which have either `Length` or `Count` property, but not both to avoid ambiguity return hasLengthProperty ^ hasCountProperty; } protected static bool IsSuitableIntegerType(ITypeSymbol type) => type.IsIntegralType() || type.IsNativeIntegerType; protected static IPropertySymbol? FindLengthProperty(ITypeSymbol type, Compilation compilation) => FindAccessibleIntegerProperty(type, compilation, "Length"); protected static IPropertySymbol? FindCountProperty(ITypeSymbol type, Compilation compilation) => FindAccessibleIntegerProperty(type, compilation, "Count"); private static IPropertySymbol? FindAccessibleIntegerProperty(ITypeSymbol type, Compilation compilation, string propertyName) { return type .GetAccessibleMembersInThisAndBaseTypes<IPropertySymbol>(propertyName, compilation.Assembly) .FirstOrDefault(p => p is { GetMethod: { } getMethod } && getMethod.IsAccessibleWithin(compilation.Assembly) && IsSuitableIntegerType(p.Type)); } }