private IEnumerable <IMethodSymbol> Resolve(Compilation compilation, INamedTypeSymbol container, bool ignoreAssemblyKey, CancellationToken cancellationToken) { var comparisonOptions = new ComparisonOptions(compilation.IsCaseSensitive, ignoreAssemblyKey, compareMethodTypeParametersByName: true); ITypeSymbol[] typeArguments = null; if (typeArgumentKeysOpt != null) { typeArguments = typeArgumentKeysOpt.Select(a => a.Resolve(compilation).Symbol as ITypeSymbol).ToArray(); if (typeArguments.Any(a => a == null)) { yield break; } } foreach (var method in container.GetMembers().OfType <IMethodSymbol>()) { // Quick checks first if (method.MetadataName != this.metadataName || method.Arity != this.arity || method.Parameters.Length != this.originalParameterTypeKeys.Length) { continue; } // Is this a conversion operator? If so, we must also compare the return type. if (this.returnType != null) { if (!this.returnType.Equals(SymbolKey.Create(method.ReturnType, compilation, cancellationToken), comparisonOptions)) { continue; } } if (!ParametersMatch(comparisonOptions, compilation, method.OriginalDefinition.Parameters, refKinds, originalParameterTypeKeys, cancellationToken)) { continue; } // It matches, so let's return it, but we might have to do some construction first var methodToReturn = method; if (isPartialMethodImplementationPart) { methodToReturn = methodToReturn.PartialImplementationPart ?? methodToReturn; } if (typeArguments != null) { methodToReturn = methodToReturn.Construct(typeArguments); } yield return(methodToReturn); } }
private static bool ParametersMatch( ComparisonOptions options, Compilation compilation, ImmutableArray <IParameterSymbol> parameters, RefKind[] refKinds, SymbolKey[] typeKeys, CancellationToken cancellationToken) { if (parameters.Length != refKinds.Length) { return(false); } for (int i = 0; i < refKinds.Length; i++) { // The ref-out distinction is not interesting for SymbolKey because you can't overload // based on the difference. var parameter = parameters[i]; if (!SymbolEquivalenceComparer.AreRefKindsEquivalent(refKinds[i], parameter.RefKind, distinguishRefFromOut: false)) { return(false); } // We are checking parameters for equality, if they refer to method type parameters, // then we don't want to recurse through the method (which would then recurse right // back into the parameters). So we ask that type parameters only be checked by // metadataName to prevent that. var newOptions = new ComparisonOptions( options.IgnoreCase, options.IgnoreAssemblyKey, compareMethodTypeParametersByName: true); if (!typeKeys[i].Equals(SymbolKey.Create(parameter.Type, compilation, cancellationToken), newOptions)) { return(false); } } return(true); }
private static bool ParametersMatch( ComparisonOptions options, Compilation compilation, ImmutableArray <IParameterSymbol> parameters, RefKind[] refKinds, SymbolKey[] typeKeys, CancellationToken cancellationToken) { if (parameters.Length != refKinds.Length) { return(false); } for (int i = 0; i < refKinds.Length; i++) { var parameter = parameters[i]; if (refKinds[i] != parameters[i].RefKind) { return(false); } // We are checking parameters for equality, if they refer to method type parameters, // then we don't want to recurse through the method (which would then recurse right // back into the parameters). So we ask that type parameters only be checked by // metadataName to prevent that. var newOptions = new ComparisonOptions( options.IgnoreCase, options.IgnoreAssemblyKey, compareMethodTypeParametersByName: true); if (!typeKeys[i].Equals(SymbolKey.Create(parameter.Type, compilation, cancellationToken), newOptions)) { return(false); } } return(true); }
public static SymbolKey GetSymbolKey(this ISymbol symbol, CancellationToken cancellationToken = default) => SymbolKey.Create(symbol, cancellationToken);
public static SymbolKey GetSymbolKey(this ISymbol symbol) { return(SymbolKey.Create(symbol, null, CancellationToken.None)); }
internal static SymbolKey GetSymbolKey(this ISymbol symbol, Compilation compilation, CancellationToken cancellationToken) { return(SymbolKey.Create(symbol, compilation, cancellationToken)); }