public static async Task <List <IMethodSymbol> > FindExtensionMethodsAsync(this ITypeSymbol type, Project project, CancellationToken cancellationToken = default) { var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var members = new List <IMethodSymbol>(10); var isValueType = type.IsValueType; foreach (var typeSymbol in compilation.GlobalNamespace.GetAllTypes(cancellationToken)) { if (typeSymbol.IsStatic == false || typeSymbol.MightContainExtensionMethods == false) { continue; } foreach (var member in typeSymbol.GetMembers()) { if (cancellationToken.IsCancellationRequested) { return(members); } if (member.IsStatic == false || member.Kind != SymbolKind.Method) { continue; } var m = (IMethodSymbol)member; if (m.IsExtensionMethod == false || m.CanBeReferencedByName == false) { continue; } var p = m.Parameters[0]; if (type.CanConvertTo(p.Type)) { members.Add(m); continue; } if (m.IsGenericMethod == false || p.Type.TypeKind != TypeKind.TypeParameter) { continue; } foreach (var item in m.TypeParameters) { if (item != p.Type || item.HasValueTypeConstraint && isValueType == false || item.HasReferenceTypeConstraint && isValueType) { continue; } if (item.HasConstructorConstraint) { } if (item.ConstraintTypes.Length > 0 && item.ConstraintTypes.Any(i => i == type || type.CanConvertTo(i)) == false) { continue; } members.Add(m); } } } return(members); }
/// <summary> /// Finds all members defined or referenced in <paramref name="project"/> which may have a parameter that is of or derived from <paramref name="type"/>. /// </summary> public static async Task <List <ISymbol> > FindInstanceAsParameterAsync(this ITypeSymbol type, Project project, CancellationToken cancellationToken = default) { var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var members = new List <ISymbol>(10); ImmutableArray <IParameterSymbol> parameters; var assembly = compilation.Assembly; foreach (var typeSymbol in compilation.GlobalNamespace.GetAllTypes(cancellationToken)) { foreach (var member in typeSymbol.GetMembers()) { if (cancellationToken.IsCancellationRequested) { return(members); } if (member.Kind != SymbolKind.Field && member.CanBeReferencedByName && (parameters = member.GetParameters()).IsDefaultOrEmpty == false) { if (parameters.Any(p => type.CanConvertTo(p.Type) && p.Type.IsCommonClass() == false) && type.CanAccess(member, assembly)) { members.Add(member); } } } } return(members); }
/// <summary>Checks whether the given symbol has the given <paramref name="kind"/>, <paramref name="returnType"/> and <paramref name="parameters"/>.</summary> /// <param name="symbol">The symbol to be checked.</param> /// <param name="kind">The <see cref="SymbolKind"/> the symbol should have.</param> /// <param name="returnType">The type that the symbol should return.</param> /// <param name="parameters">The parameters the symbol should take.</param> public static bool MatchSignature(this ISymbol symbol, SymbolKind kind, ITypeSymbol returnType, ImmutableArray <IParameterSymbol> parameters) { if (symbol.Kind != kind) { return(false); } if (returnType == null && symbol.GetReturnType() != null || returnType != null && returnType.CanConvertTo(symbol.GetReturnType()) == false) { return(false); } var method = kind == SymbolKind.Method ? symbol as IMethodSymbol : kind == SymbolKind.Event ? (symbol as IEventSymbol).RaiseMethod : null; if (method != null && parameters.IsDefault == false) { var memberParameters = method.Parameters; if (memberParameters.Length != parameters.Length) { return(false); } for (var i = parameters.Length - 1; i >= 0; i--) { var pi = parameters[i]; var mi = memberParameters[i]; if (pi.Type.Equals(mi.Type) == false || pi.RefKind != mi.RefKind) { return(false); } } } return(true); }
public static bool CanConvertTo(this ITypeSymbol symbol, ITypeSymbol target) { if (symbol.Equals(target)) { return(true); } if (target.TypeKind == TypeKind.TypeParameter) { var param = target as ITypeParameterSymbol; foreach (var item in param.ConstraintTypes) { if (item.CanConvertTo(symbol)) { return(true); } } return(false); } if (symbol.TypeKind == TypeKind.TypeParameter) { var param = symbol as ITypeParameterSymbol; foreach (var item in param.ConstraintTypes) { if (item.CanConvertTo(target)) { return(true); } } return(false); } foreach (var item in symbol.Interfaces) { if (item.CanConvertTo(target)) { return(true); } } while ((symbol = symbol.BaseType) != null) { if (symbol.CanConvertTo(target)) { return(true); } } return(false); }