protected override bool AddLookupItems()

in resharper/resharper-unity/src/Unity/Odin/Feature/Services/CodeCompletion/GroupingAttributes/OdinLayoutAttributesCodeCompletionProvider.cs [54:150]


    protected override bool AddLookupItems(CSharpCodeCompletionContext context, IItemsCollector collector)
    {
        var stringLiteral = context.StringLiteral();
        if (stringLiteral == null)
            return false;

        var nodeInFile = context.NodeInFile;

        var argument = nodeInFile.GetContainingNode<ICSharpArgument>();
        var attribute = AttributeNavigator.GetByArgument(argument);
        
        if (attribute == null)
            return false;

        var declaration = attribute.GetContainingNode<IClassLikeDeclaration>();

        var classLikeDeclaredElement = declaration?.DeclaredElement;
        if (classLikeDeclaredElement == null)
            return false;
        
        var type = attribute.TypeReference?.Resolve().Result.DeclaredElement as ITypeElement;
        if (type == null)
            return false;

        if (!OdinKnownAttributes.LayoutAttributes.TryGetValue(type.GetClrName(), out var parameterName))
            return false;
        
        var literal = stringLiteral.ConstantValue.AsString();
        if (literal == null)
            return false;

        var name = argument.MatchingParameter?.Element.ShortName;
        if (name == null)
            return false;

        if (!parameterName.Equals(name))
            return false;

        var currentMembers = CSharpTypeMemberDeclarationNavigator.GetByAttribute(attribute).Select(t => t.DeclaredElement).ToHashSet();
        var groups = OdinAttributeUtil.CollectGroupInfo(classLikeDeclaredElement).Where(t => t.IsMajorGroup).ToList();

        var resultGroups = new HashSet<string>(groups.Count);
        foreach (var group in groups)
        {
            if (currentMembers.Contains(group.Member))
                continue;

            resultGroups.Add(group.GroupPath);
        }

        var hasResult = false;
        foreach (var layoutName in resultGroups)
        {
            var item = new StringLiteralItem(layoutName, context.CompletionRanges);
            collector.Add(item);
            hasResult = true;
        }

        var lastSlashIndex = literal.LastIndexOf('/');
        if (lastSlashIndex == -1)
            lastSlashIndex = literal.Length;

        var prefixLiteral = literal.Substring(0, lastSlashIndex);
        
        var trie = new QualifiedNamesTrie<string>(false, '/');
        
        foreach (var layoutName in resultGroups)
        {
            var sections = layoutName.Split('/');
            var sb = new StringBuilder(layoutName.Length);
            foreach (var section in sections)
            {
                sb.Append(section);
                trie.Add(sb.ToString(), sb.ToString());
                sb.Append('/');
            }
        }
        
        var node = trie.FindTrieNode(prefixLiteral);
        if (node == null)
            return hasResult;
        
        foreach (var child in node.Children)
        {
            if (child.Data.IsEmpty() || child.Data.Equals("$"))
                continue;
        
            if (resultGroups.Contains(child.Data))
                continue;
            
            var item = new StringLiteralItem(child.Data, context.CompletionRanges);
        
            collector.Add(item);
        }
        
        return true;
    }