예제 #1
0
        private CSharpProperty BuildProperty(IPropertySymbol symbol, CSharpClass referencingClass, string nameSpace = null)
        {
            var prop = new CSharpProperty();

            var commentXml = symbol.GetDocumentationCommentXml();
            var typeName   = symbol.Type.Name.ToString();
            Dictionary <string, HashSet <string> > references = new Dictionary <string, HashSet <string> >();
            var newTypeName = context.GetTsType(symbol.Type, references);

            //if (newTypeName == null || string.IsNullOrEmpty(newTypeName))
            //{

            //}
            // remove the namespace if it's the same
            if (nameSpace != null && newTypeName.StartsWith(nameSpace))
            {
                newTypeName = newTypeName.Remove(0, nameSpace.Length + 1); // +1 for the dot
            }

            if (references.Count > 0)
            {
                referencingClass.AddReferences(references);
            }

            prop.SetSummaryViaXml(commentXml);
            var name = symbol.Name.ToString();

            prop.DisplayText = name + ": " + newTypeName + ";";

            return(prop);
        }
    private void ConfigureBoundAttribute(
        BoundAttributeDescriptorBuilder builder,
        IPropertySymbol property,
        INamedTypeSymbol containingType)
    {
        var attributeNameAttribute = property
                                     .GetAttributes()
                                     .Where(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, _htmlAttributeNameAttributeSymbol))
                                     .FirstOrDefault();

        bool   hasExplicitName;
        string attributeName;

        if (attributeNameAttribute == null ||
            attributeNameAttribute.ConstructorArguments.Length == 0 ||
            string.IsNullOrEmpty((string)attributeNameAttribute.ConstructorArguments[0].Value))
        {
            hasExplicitName = false;
            attributeName   = HtmlConventions.ToHtmlCase(property.Name);
        }
        else
        {
            hasExplicitName = true;
            attributeName   = (string)attributeNameAttribute.ConstructorArguments[0].Value;
        }

        var hasPublicSetter = property.SetMethod != null && property.SetMethod.DeclaredAccessibility == Accessibility.Public;
        var typeName        = GetFullName(property.Type);

        builder.TypeName = typeName;
        builder.SetPropertyName(property.Name);

        if (hasPublicSetter)
        {
            builder.Name = attributeName;

            if (property.Type.TypeKind == TypeKind.Enum)
            {
                builder.IsEnum = true;
            }

            if (IncludeDocumentation)
            {
                var xml = property.GetDocumentationCommentXml();

                if (!string.IsNullOrEmpty(xml))
                {
                    builder.Documentation = xml;
                }
            }
        }
        else if (hasExplicitName && !IsPotentialDictionaryProperty(property))
        {
            // Specified HtmlAttributeNameAttribute.Name though property has no public setter.
            var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidAttributeNameNullOrEmpty(GetFullName(containingType), property.Name);
            builder.Diagnostics.Add(diagnostic);
        }

        ConfigureDictionaryBoundAttribute(builder, property, containingType, attributeNameAttribute, attributeName, hasPublicSetter);
    }
예제 #3
0
        protected override void ReadSymbol(IPropertySymbol propertySymbol)
        {
            // we don't need to know about static members
            // because they won't be delegated from child to mixin
            if (propertySymbol.IsStatic)
                return;

            // we ignore private and protected memebers
            var hasGetter = propertySymbol.GetMethod != null &&
                      !(propertySymbol.GetMethod.DeclaredAccessibility == Accessibility.Private ||
                        propertySymbol.GetMethod.DeclaredAccessibility == Accessibility.Protected);
            var hasSetter = propertySymbol.SetMethod != null &&
                      !(propertySymbol.SetMethod.DeclaredAccessibility == Accessibility.Private ||
                        propertySymbol.SetMethod.DeclaredAccessibility == Accessibility.Protected);

            // property has no accessors or accessors are not accessible => skip property
            if (!hasSetter && !hasGetter)
                return;

            Property property = null;

            if (propertySymbol.IsIndexer) // symbol is an indexer property
            {
                var indexerProperty = new IndexerProperty(
                    propertySymbol.Type,
                    hasGetter,
                    hasSetter);
                var parameterReader = new ParameterSymbolReader(indexerProperty);
                parameterReader.VisitSymbol(propertySymbol);
                property = indexerProperty;
            }
            else // symbol is a normal property
            {
                property = new Property(
                    propertySymbol.Name,
                    propertySymbol.Type,
                    hasGetter,
                    hasSetter);
            }
            property.IsAbstract = propertySymbol.IsAbstract;
            property.IsOverride = propertySymbol.IsOverride;

            // store information if accessors are internal,
            // we will need this for the generation later
            property.IsGetterInternal = hasGetter &&
                                        propertySymbol.GetMethod
                                        .DeclaredAccessibility.HasFlag(Accessibility.Internal);
            property.IsSetterInternal = hasSetter &&
                                        propertySymbol.SetMethod
                                        .DeclaredAccessibility.HasFlag(Accessibility.Internal);
                    
            property.Documentation = new DocumentationComment(propertySymbol.GetDocumentationCommentXml());

            _properties.AddProperty(property);
        }
 protected sealed override IEnumerable <Diagnostic> AnalyzeProperty(IPropertySymbol symbol, string commentXml) => AnalyzeComment(symbol, symbol.GetDocumentationCommentXml());
        private void CreateProperty(TagHelperDescriptorBuilder builder, IPropertySymbol property, PropertyKind kind)
        {
            builder.BindAttribute(pb =>
            {
                pb.Name     = property.Name;
                pb.TypeName = property.Type.ToDisplayString(FullNameTypeDisplayFormat);
                pb.SetPropertyName(property.Name);

                if (kind == PropertyKind.Enum)
                {
                    pb.IsEnum = true;
                }

                if (kind == PropertyKind.ChildContent)
                {
                    pb.Metadata.Add(BlazorMetadata.Component.ChildContentKey, bool.TrueString);
                }

                if (kind == PropertyKind.Delegate)
                {
                    pb.Metadata.Add(BlazorMetadata.Component.DelegateSignatureKey, bool.TrueString);
                }

                if (HasTypeParameter(property.Type))
                {
                    pb.Metadata.Add(BlazorMetadata.Component.GenericTypedKey, bool.TrueString);
                }

                var xml = property.GetDocumentationCommentXml();
                if (!string.IsNullOrEmpty(xml))
                {
                    pb.Documentation = xml;
                }
            });

            bool HasTypeParameter(ITypeSymbol type)
            {
                if (type is ITypeParameterSymbol)
                {
                    return(true);
                }

                // We need to check for cases like:
                // [Parameter] List<T> MyProperty { get; set; }
                // AND
                // [Parameter] List<string> MyProperty { get; set; }
                //
                // We need to inspect the type arguments to tell the difference between a property that
                // uses the containing class' type parameter(s) and a vanilla usage of generic types like
                // List<> and Dictionary<,>
                //
                // Since we need to handle cases like RenderFragment<List<T>>, this check must be recursive.
                if (type is INamedTypeSymbol namedType && namedType.IsGenericType)
                {
                    var typeArguments = namedType.TypeArguments;
                    for (var i = 0; i < typeArguments.Length; i++)
                    {
                        if (HasTypeParameter(typeArguments[i]))
                        {
                            return(true);
                        }
                    }

                    // Another case to handle - if the type being inspected is a nested type
                    // inside a generic containing class. The common usage for this would be a case
                    // where a generic templated component defines a 'context' nested class.
                    if (namedType.ContainingType != null && HasTypeParameter(namedType.ContainingType))
                    {
                        return(true);
                    }
                }

                return(false);
            }
        }
 protected override IEnumerable <Diagnostic> AnalyzeProperty(IPropertySymbol symbol) => ShallAnalyzeProperty(symbol)
                                                                                           ? AnalyzeProperty(symbol, symbol.GetDocumentationCommentXml())
                                                                                           : Enumerable.Empty <Diagnostic>();
예제 #7
0
        /// <summary>
        /// Prepares the <see cref="PropertyMemberBuilder"/> from the <paramref name="symbol"/>
        /// and adds it to <see cref="TypeMemberBuilder.ContentMembers"/>
        /// </summary>
        /// <param name="symbol">Source <see cref="INamedTypeSymbol"/></param>
        /// <param name="root">Builder root</param>
        /// <param name="type">Parent <see cref="TypeMemberBuilder"/></param>
        /// <param name="level">Hierarchy level (used to indent the console output)</param>
        private static void BuildProperty(IPropertySymbol symbol, RootMemberBuilder root, TypeMemberBuilder type, int level)
        {
            if (symbol.IsImplicitlyDeclared)
            {
                return;
            }
            if (symbol.GetAttributes().Any(a => a.AttributeClassString() == "System.Runtime.CompilerServices.CompilerGeneratedAttribute"))
            {
                return;
            }

            var p = new PropertyMemberBuilder()
            {
                Name             = symbol.Name,
                NameBase         = symbol.Name.Replace("[]", ""),
                Symbol           = symbol,
                SourceFiles      = symbol.DeclaringSyntaxReferences.Select(dsr => dsr.SyntaxTree.FilePath).ToList(),
                DocumentationId  = symbol.GetDocumentationCommentId(),
                DocumentationXml = symbol.GetDocumentationCommentXml(),
                Documentation    = Documentation.Read(symbol.GetDocumentationCommentXml()),
                Modifier         = ModifierEnumExtensions.Modifier(symbol.DeclaredAccessibility),
                IsAbstract       = symbol.IsAbstract,
                IsExtern         = symbol.IsExtern,
                IsSealed         = symbol.IsSealed,
                IsStatic         = symbol.IsStatic,
                IsOverride       = symbol.IsOverride,
                IsVirtual        = symbol.IsVirtual,
                IsReadOnly       = symbol.IsReadOnly,
                IsWriteOnly      = symbol.IsWriteOnly,
                IsIndexer        = symbol.IsIndexer,
                TypeRef          = TypeRef.GetOrCreate(symbol.Type, root),
                IsNew            = symbol.GetIsNew(),
                OverridesSymbol  = symbol.OverriddenProperty,
                ExplicitInterfaceImplementationMemberSymbol =
                    symbol.ExplicitInterfaceImplementations != null && symbol.ExplicitInterfaceImplementations.Length > 0
                        ? symbol.ExplicitInterfaceImplementations[0]
                        : null
            };

            var propertyModifier = ModifierEnumExtensions.Modifier(symbol.DeclaredAccessibility);
            var getterModifier   = ModifierEnumExtensions.Modifier(symbol.GetMethod?.DeclaredAccessibility ?? symbol.DeclaredAccessibility);
            var setterModifier   = ModifierEnumExtensions.Modifier(symbol.SetMethod?.DeclaredAccessibility ?? symbol.DeclaredAccessibility);

            if (getterModifier != propertyModifier)
            {
                p.GetterModifier = getterModifier.ToModifierString();
            }
            if (setterModifier != propertyModifier)
            {
                p.SetterModifier = setterModifier.ToModifierString();
            }

            if (symbol.Parameters != null && symbol.Parameters.Length > 0)
            {
                //Process the indexer parameters (the only property kind with parameters
                p.Parameters = GetMethodParameters(symbol.Parameters, root);
                p.Name       = p.Name.Replace("[]",
                                              $"[{string.Join(", ", p.Parameters.Select(param => param.TypeRef.ApplySpecialName(false)))}]");
            }

            p.SetAttributes(root);

            type.ContentMembers.Add(p);
            Console.WriteLine($"{new string(' ', level)} read as {p}");
        }