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, cancellationToken: cancellationToken).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 != _metadataName || method.Arity != _arity || method.Parameters.Length != _originalParameterTypeKeys.Length) { continue; } // Is this a conversion operator? If so, we must also compare the return type. if (_returnType != null) { if (!_returnType.Equals(SymbolKey.Create(method.ReturnType, cancellationToken), comparisonOptions)) { continue; } } if (!ParametersMatch(comparisonOptions, 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 void Resolve( PooledArrayBuilder <IParameterSymbol> result, SymbolKeyReader reader, string metadataName, ImmutableArray <IParameterSymbol> parameters) { foreach (var parameter in parameters) { if (SymbolKey.Equals(reader.Compilation, parameter.MetadataName, metadataName)) { result.AddIfNotNull(parameter); } } }
private static IEnumerable <(ISymbol symbol, int ordinal)> EnumerateSymbols( Compilation compilation, ISymbol containingSymbol, SymbolKind kind, string localName, CancellationToken cancellationToken) { var ordinal = 0; foreach (var declaringLocation in containingSymbol.DeclaringSyntaxReferences) { // This operation can potentially fail. If containingSymbol came from // a SpeculativeSemanticModel, containingSymbol.ContainingAssembly.Compilation // may not have been rebuilt to reflect the trees used by the // SpeculativeSemanticModel to produce containingSymbol. In that case, // asking the ContainingAssembly's compilation for a SemanticModel based // on trees for containingSymbol with throw an ArgumentException. // Unfortunately, the best way to avoid this (currently) is to see if // we're asking for a model for a tree that's part of the compilation. // (There's no way to get back to a SemanticModel from a symbol). // TODO (rchande): It might be better to call compilation.GetSemanticModel // and catch the ArgumentException. The compilation internally has a // Dictionary<SyntaxTree, ...> that it uses to check if the SyntaxTree // is applicable wheras the public interface requires us to enumerate // the entire IEnumerable of trees in the Compilation. if (!Contains(compilation.SyntaxTrees, declaringLocation.SyntaxTree)) { continue; } var node = declaringLocation.GetSyntax(cancellationToken); if (node.Language == LanguageNames.VisualBasic) { node = node.Parent; } var semanticModel = compilation.GetSemanticModel(node.SyntaxTree); foreach (var token in node.DescendantNodes()) { var symbol = semanticModel.GetDeclaredSymbol(token, cancellationToken); if (symbol != null && symbol.Kind == kind && SymbolKey.Equals(compilation, symbol.Name, localName)) { yield return(symbol, ordinal++); } } } }
private static IEnumerable <IParameterSymbol> Resolve( SymbolKeyReader reader, ISymbol container, string metadataName) { if (container is IMethodSymbol) { return(((IMethodSymbol)container).Parameters.Where( p => SymbolKey.Equals(reader.Compilation, p.MetadataName, metadataName))); } else if (container is IPropertySymbol) { return(((IPropertySymbol)container).Parameters.Where( p => SymbolKey.Equals(reader.Compilation, p.MetadataName, metadataName))); } else { return(SpecializedCollections.EmptyEnumerable <IParameterSymbol>()); } }
public static SymbolKeyResolution Resolve(SymbolKeyReader reader) { var cancellationToken = reader.CancellationToken; var name = reader.ReadString(); var kind = (SymbolKind)reader.ReadInteger(); var locations = reader.ReadLocationArray(); var ordinal = reader.ReadInteger(); // First check if we can recover the symbol just through the original location. foreach (var loc in locations) { var resolutionOpt = reader.ResolveLocation(loc); if (resolutionOpt.HasValue) { var resolution = resolutionOpt.Value; var symbol = resolution.GetAnySymbol(); if (symbol?.Kind == kind && SymbolKey.Equals(reader.Compilation, name, symbol.Name)) { return(resolution); } } } // Couldn't recover. See if we can still find a match across the textual drift. if (ordinal != int.MaxValue && TryGetSemanticModel(reader.Compilation, locations[0].SourceTree, out var semanticModel)) { foreach (var symbol in EnumerateSymbols(semanticModel, kind, name, cancellationToken)) { if (symbol.ordinal == ordinal) { return(new SymbolKeyResolution(symbol.symbol)); } } } return(default);
private static IEnumerable <IParameterSymbol> Resolve( SymbolKeyReader reader, ISymbol container, string metadataName) { if (container is IMethodSymbol) { return(((IMethodSymbol)container).Parameters.Where( p => SymbolKey.Equals(reader.Compilation, p.MetadataName, metadataName))); } else if (container is IPropertySymbol) { return(((IPropertySymbol)container).Parameters.Where( p => SymbolKey.Equals(reader.Compilation, p.MetadataName, metadataName))); } else if (container is IEventSymbol) { // Parameters can be owned by events in VB. i.e. it's legal in VB to have: // // Public Event E(a As Integer, b As Integer); // // In this case it's equivalent to: // // Public Delegate UnutterableCompilerName(a As Integer, b As Integer) // public Event E As UnutterableCompilerName // // So, in this case, to resolve the parameter, we go have to map the event, // then find the delegate it returns, then find the parameter in the delegate's // 'Invoke' method. var eventSymbol = (IEventSymbol)container; var delegateInvoke = (eventSymbol.Type as INamedTypeSymbol)?.DelegateInvokeMethod; if (delegateInvoke != null) { return(delegateInvoke.Parameters.Where( p => SymbolKey.Equals(reader.Compilation, p.MetadataName, metadataName))); } } return(SpecializedCollections.EmptyEnumerable <IParameterSymbol>()); }