public void Resolve(IList <ISymbol> results) { if (string.IsNullOrEmpty(_name)) { return; } // Try to parse the name as declaration ID generated from symbol's documentation comment Id. List <ISymbol> docIdResults; if (DocumentationCommentId.TryGetSymbolsForDeclarationId(RemovePrefix(_name, s_suppressionPrefix), _compilation, out docIdResults)) { foreach (var result in docIdResults) { results.Add(result); } return; } // Parse 'e:' prefix used by FxCop to differentiate between event and non-event symbols of the same name. bool isEvent = false; if (_name.Length >= 2 && _name[0] == 'e' && _name[1] == ':') { isEvent = true; _index = 2; } INamespaceOrTypeSymbol containingSymbol = _compilation.GlobalNamespace; bool?segmentIsNamedTypeName = null; while (true) { var segment = ParseNextNameSegment(); // Special case: Roslyn names indexers "this[]" in CSharp, FxCop names them "Item" with parameters in [] brackets bool isIndexerProperty = false; if (segment == "Item" && PeekNextChar() == '[') { isIndexerProperty = true; if (_compilation.Language == LanguageNames.CSharp) { segment = "this[]"; } } var candidateMembers = containingSymbol.GetMembers(segment); if (candidateMembers.Length == 0) { return; } if (segmentIsNamedTypeName.HasValue) { candidateMembers = segmentIsNamedTypeName.Value ? candidateMembers.Where(s => s.Kind == SymbolKind.NamedType).ToImmutableArray() : candidateMembers.Where(s => s.Kind != SymbolKind.NamedType).ToImmutableArray(); segmentIsNamedTypeName = null; } int? arity = null; ParameterInfo[] parameters = null; // Check for generic arity if (_scope != TargetScope.Namespace && PeekNextChar() == '`') { ++_index; arity = ReadNextInteger(); } // Check for method or indexer parameter list var nextChar = PeekNextChar(); if (!isIndexerProperty && nextChar == '(' || isIndexerProperty && nextChar == '[') { parameters = ParseParameterList(); if (parameters == null) { // Failed to resolve parameter list return; } } else if (nextChar == '.' || nextChar == '+') { ++_index; if (arity > 0 || nextChar == '+') { // The name continues and either has an arity or specifically continues with a '+' // so segment must be the name of a named type containingSymbol = GetFirstMatchingNamedType(candidateMembers, arity ?? 0); } else { // The name continues with a '.' and does not specify a generic arity // so segment must be the name of a namespace or a named type containingSymbol = GetFirstMatchingNamespaceOrType(candidateMembers); } if (containingSymbol == null) { // If we cannot resolve the name on the left of the delimiter, we have no // hope of finding the symbol. return; } else if (containingSymbol.Kind == SymbolKind.NamedType) { // If segment resolves to a named type, that restricts what the next segment // can resolve to depending on whether the name continues with '+' or '.' segmentIsNamedTypeName = nextChar == '+'; } continue; } if (_scope == TargetScope.Member && !isIndexerProperty && parameters != null) { TypeInfo?returnType = null; if (PeekNextChar() == ':') { ++_index; returnType = ParseNamedType(null); } foreach (var method in GetMatchingMethods(candidateMembers, arity, parameters, returnType)) { results.Add(method); } return; } ISymbol singleResult = null; switch (_scope) { case TargetScope.Namespace: singleResult = candidateMembers.FirstOrDefault(s => s.Kind == SymbolKind.Namespace); break; case TargetScope.Type: singleResult = GetFirstMatchingNamedType(candidateMembers, arity ?? 0); break; case TargetScope.Member: if (isIndexerProperty) { singleResult = GetFirstMatchingIndexer(candidateMembers, parameters); } else if (isEvent) { singleResult = candidateMembers.FirstOrDefault(s => s.Kind == SymbolKind.Event); } else { singleResult = candidateMembers.FirstOrDefault(s => s.Kind != SymbolKind.Namespace && s.Kind != SymbolKind.NamedType); } break; default: throw ExceptionUtilities.UnexpectedValue(_scope); } if (singleResult != null) { results.Add(singleResult); } return; } }