using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace StardewModdingAPI.ModBuildConfig.Analyzer
{
/// Provides generic utilities for SMAPI's Roslyn analyzers.
internal static class AnalyzerUtilities
{
/*********
** Public methods
*********/
/// Get the metadata for a member access expression.
/// The member access expression.
/// provides methods for asking semantic questions about syntax nodes.
/// The object type which has the member.
/// The type of the accessed member.
/// The name of the accessed member.
/// Returns true if the node is a member access expression, else false.
public static bool GetMemberInfo(SyntaxNode node, SemanticModel semanticModel, out ITypeSymbol declaringType, out TypeInfo memberType, out string memberName)
{
// simple access
if (node is MemberAccessExpressionSyntax memberAccess)
{
declaringType = semanticModel.GetTypeInfo(memberAccess.Expression).Type;
memberType = semanticModel.GetTypeInfo(node);
memberName = memberAccess.Name.Identifier.Text;
return true;
}
// conditional access
if (node is ConditionalAccessExpressionSyntax conditionalAccess && conditionalAccess.WhenNotNull is MemberBindingExpressionSyntax conditionalBinding)
{
declaringType = semanticModel.GetTypeInfo(conditionalAccess.Expression).Type;
memberType = semanticModel.GetTypeInfo(node);
memberName = conditionalBinding.Name.Identifier.Text;
return true;
}
// invalid
declaringType = null;
memberType = default(TypeInfo);
memberName = null;
return false;
}
/// Get the class types in a type's inheritance chain, including itself.
/// The initial type.
public static IEnumerable GetConcreteTypes(ITypeSymbol type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}
}