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;
}