private ControlPropertyMetadata GetPropertyMetadata(IPropertySymbol property)
        {
            var attribute = property.GetAttributes().FirstOrDefault(a => CheckType(a.AttributeClass, typeof(MarkupOptionsAttribute)));

            var metadata = new ControlPropertyMetadata()
            {
                Type             = property.Type,
                IsTemplate       = CheckType(property.Type, typeof(ITemplate)) || property.Type.AllInterfaces.Any(i => CheckType(i, typeof(ITemplate))),
                AllowHtmlContent = property.Type.AllInterfaces.Any(i => CheckType(i, typeof(IControlWithHtmlAttributes)))
            };

            if (attribute != null)
            {
                metadata.Name                = attribute.NamedArguments.Where(a => a.Key == "Name").Select(a => a.Value.Value as string).FirstOrDefault() ?? property.Name;
                metadata.AllowBinding        = attribute.NamedArguments.Where(a => a.Key == "AllowBinding").Select(a => a.Value.Value as bool?).FirstOrDefault() ?? true;
                metadata.AllowHardCodedValue = attribute.NamedArguments.Where(a => a.Key == "AllowHardCodedValue").Select(a => a.Value.Value as bool?).FirstOrDefault() ?? true;

                var mappingMode = (MappingMode)(attribute.NamedArguments.Where(a => a.Key == "MappingMode").Select(a => a.Value.Value as int?).FirstOrDefault() ?? (int)MappingMode.Attribute);
                if (mappingMode == MappingMode.InnerElement)
                {
                    metadata.IsElement = true;
                }
                else if (mappingMode == MappingMode.Exclude)
                {
                    return(null);
                }
            }
            else
            {
                metadata.Name                = property.Name;
                metadata.AllowBinding        = true;
                metadata.AllowHardCodedValue = true;
            }

            if (metadata.IsTemplate)
            {
                metadata.IsElement = true;
            }

            return(metadata);
        }
        private IEnumerable <CompletionData> GetElementNamesInPropertyContext(ControlPropertyMetadata controlProperty)
        {
            IEnumerable <CompletionData> filteredControls;

            if (CheckType(controlProperty.Type, typeof(ITemplate)))
            {
                // all controls can appear in a template
                filteredControls = metadata.Select(c => new CompletionData(c.Key, c.Key));
            }
            else
            {
                // resolve element type
                var iEnumerable = CompletionHelper.FindIEnumerableType(controlProperty.Type);
                var elementType = iEnumerable != null ? iEnumerable.TypeArguments[0] : controlProperty.Type;

                // filter the allControls collection
                var filteredControlMetadata = metadata.Where(m => CompletionHelper.IsAssignable(m.Value.Type, elementType));
                filteredControls = filteredControlMetadata.Select(c => new CompletionData(c.Key, c.Key));
            }
            return(filteredControls);
        }
        internal void GetElementContext(List <string> tagNameHierarchy, out ControlMetadata currentControl, out ControlPropertyMetadata currentProperty)
        {
            currentProperty = null;
            currentControl  = null;

            for (int i = 0; i < tagNameHierarchy.Count; i++)
            {
                currentProperty = null;
                currentControl  = null;

                var tagName = tagNameHierarchy[i];
                if (metadata.ContainsKey(tagName))
                {
                    // we have found a control
                    currentControl = metadata[tagName];

                    // the next element in the hierarchy might be a property
                    if (i + 1 < tagNameHierarchy.Count)
                    {
                        currentProperty = currentControl.Properties.FirstOrDefault(p => p.Name == tagNameHierarchy[i + 1] && p.IsElement);
                        if (currentProperty != null)
                        {
                            i++;
                        }
                    }
                }
                else
                {
                    // HTML or unknown element
                    currentControl = htmlGenericControlMetadata;
                }
            }
        }