Example #1
0
            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;
                }
            }