internal List <CompletionData> ReloadAllControls(DothtmlCompletionContext context)
        {
            // get all possible control symbols
            var allClasses     = ReloadAllClasses(context);
            var controlClasses = allClasses
                                 .Where(c => CompletionHelper.GetBaseTypes(c).Any(t => CheckType(t, typeof(DotvvmBindableObject))))
                                 .ToList();

            var result = new List <CompletionData>();

            metadata = new ConcurrentDictionary <string, ControlMetadata>(StringComparer.CurrentCultureIgnoreCase);
            htmlGenericControlMetadata = null;

            foreach (var rule in context.Configuration.Markup.Controls)
            {
                string tagName;
                if (!string.IsNullOrEmpty(rule.Src))
                {
                    // markup control
                    tagName = rule.TagPrefix + ":" + rule.TagName;

                    // TODO: parse markup, find base type and extract metadata

                    result.Add(new CompletionData(tagName));
                }
                else
                {
                    // find all classes declared in the project
                    var controls = controlClasses.Where(c => c.ContainingAssembly.Name == rule.Assembly && c.ContainingNamespace.ToDisplayString() == rule.Namespace);
                    foreach (var control in controls)
                    {
                        tagName = rule.TagPrefix + ":" + control.Name;
                        var controlMetadata = GetControlMetadata(control, rule.TagPrefix, control.Name);
                        metadata[tagName] = controlMetadata;
                        result.Add(new CompletionData(tagName));

                        if (CheckType(control, typeof(HtmlGenericControl)))
                        {
                            htmlGenericControlMetadata = controlMetadata;
                        }
                    }
                }
            }

            return(result);
        }
        private ControlMetadata GetControlMetadata(INamedTypeSymbol control, string tagPrefix, string tagName)
        {
            var attribute = control.GetAttributes().FirstOrDefault(a => CheckType(a.AttributeClass, typeof(ControlMarkupOptionsAttribute)));

            return(new ControlMetadata()
            {
                Type = control,
                TagPrefix = tagPrefix,
                TagName = tagName,
                Name = control.Name,
                Namespace = control.ContainingNamespace.ToDisplayString(),
                Properties = CompletionHelper.GetBaseTypes(control).Concat(new[] { control })
                             .SelectMany(c => c.GetMembers().OfType <IPropertySymbol>())
                             .Where(p => p.DeclaredAccessibility == Accessibility.Public)
                             .Where(p => p.GetMethod != null && p.SetMethod != null)
                             .Select(GetPropertyMetadata)
                             .Where(p => p != null)
                             .ToList(),
                AllowContent = attribute?.NamedArguments.Where(a => a.Key == "AllowContent").Select(a => a.Value.Value as bool?).FirstOrDefault() ?? true,
                DefaultContentProperty = attribute?.NamedArguments.Where(a => a.Key == "DefaultContentProperty").Select(a => a.Value.Value as string).FirstOrDefault()
            });
        }