예제 #1
0
        private void ProcessField(StringBuilder source, IFieldSymbol fieldSymbol, ISymbol attributeSymbol)
        {
            var fieldName        = fieldSymbol.Name;
            var fieldType        = fieldSymbol.Type;
            var attributeData    = fieldSymbol.GetAttributes().Single(ad => ad?.AttributeClass?.Equals(attributeSymbol, SymbolEqualityComparer.Default) ?? false);
            var overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value;
            var propertyName     = ChooseName(fieldName, overridenNameOpt);

            if (propertyName is null || propertyName.Length == 0 || propertyName == fieldName)
            {
                // Issue a diagnostic that we can't process this field.
                return;
            }

            var overridenSetterModifierOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "SetterModifier").Value;
            var setterModifier             = ChooseSetterModifier(overridenSetterModifierOpt);

            if (setterModifier is null)
            {
                source.Append($@"
        public {fieldType} {propertyName}
        {{
            get => {fieldName};
        }}");
            }
            else
            {
                source.Append($@"
        public {fieldType} {propertyName}
        {{
            get => {fieldName};
            {setterModifier}set => this.RaiseAndSetIfChanged(ref {fieldName}, value);
        }}");
            }
예제 #2
0
        public static FieldDeclarationSyntax GenerateFieldDeclaration(
            IFieldSymbol field, CSharpCodeGenerationContextInfo info, CancellationToken cancellationToken)
        {
            var reusableSyntax = GetReuseableSyntaxNodeForSymbol <FieldDeclarationSyntax>(field, info);

            if (reusableSyntax != null)
            {
                return(reusableSyntax);
            }

            var initializer = CodeGenerationFieldInfo.GetInitializer(field) is ExpressionSyntax initializerNode
                ? SyntaxFactory.EqualsValueClause(initializerNode)
                : GenerateEqualsValue(field);

            var fieldDeclaration = SyntaxFactory.FieldDeclaration(
                AttributeGenerator.GenerateAttributeLists(field.GetAttributes(), info),
                GenerateModifiers(field, info),
                SyntaxFactory.VariableDeclaration(
                    field.Type.GenerateTypeSyntax(),
                    SyntaxFactory.SingletonSeparatedList(
                        AddAnnotationsTo(field, SyntaxFactory.VariableDeclarator(field.Name.ToIdentifierToken(), null, initializer)))));

            return(AddFormatterAndCodeGeneratorAnnotationsTo(
                       ConditionallyAddDocumentationCommentTo(fieldDeclaration, field, info, cancellationToken)));
        }
예제 #3
0
        public override MetadataItem VisitField(IFieldSymbol symbol)
        {
            MetadataItem result = GetYamlItem(symbol);

            if (result == null)
            {
                return(null);
            }
            if (result.Syntax == null)
            {
                result.Syntax = new SyntaxDetail {
                    Content = new SortedList <SyntaxLanguage, string>()
                };
            }
            if (result.Syntax.Content == null)
            {
                result.Syntax.Content = new SortedList <SyntaxLanguage, string>();
            }
            _generator.GenerateSyntax(result.Type, symbol, result.Syntax, this);
            _generator.GenerateField(symbol, result, this);

            var typeGenericParameters = symbol.ContainingType.IsGenericType ? symbol.ContainingType.Accept(TypeGenericParameterNameVisitor.Instance) : EmptyListOfString;

            var id = AddSpecReference(symbol.Type, typeGenericParameters);

            result.Syntax.Return = VisitorHelper.GetParameterDescription(symbol, result, id, true, GetTripleSlashCommentParserContext(result, _preserveRawInlineComments));
            Debug.Assert(result.Syntax.Return.Type != null);

            result.Attributes = GetAttributeInfo(symbol.GetAttributes());

            return(result);
        }
예제 #4
0
        private void ProcessPrintableAttributedFields(GeneratorExecutionContext context, MySyntaxReceiver syntaxReceiver, Compilation compilation, INamedTypeSymbol attributeSymbol)
        {
            List <IFieldSymbol> fieldSymbols = new List <IFieldSymbol>();

            foreach (FieldDeclarationSyntax field in syntaxReceiver.CandidateFields)
            {
                SemanticModel model = compilation.GetSemanticModel(field.SyntaxTree);
                foreach (VariableDeclaratorSyntax variable in field.Declaration.Variables)
                {
                    IFieldSymbol fieldSymbol = model.GetDeclaredSymbol(variable) as IFieldSymbol;
                    if (fieldSymbol.GetAttributes()
                        .Any(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default)))
                    {
                        fieldSymbols.Add(fieldSymbol);
                    }
                }
            }

            foreach (IGrouping <INamedTypeSymbol, IFieldSymbol> group in fieldSymbols.GroupBy(f => f.ContainingType))
            {
                string classSource = ProcessClassPrintableAttribute(group.Key, group.ToList(), attributeSymbol, context);
                context.AddSource($"{group.Key.Name}.Printables.cs", SourceText.From(classSource, Encoding.UTF8));
            }

            context.AddSource("PrintableFields.PrintableAttribute", SourceText.From(attributeText, Encoding.UTF8));
        }
예제 #5
0
        private void ProcessField(StringBuilder source, IFieldSymbol fieldSymbol, ISymbol attributeSymbol)
        {
            // 獲取欄位名稱
            string      fieldName = fieldSymbol.Name;
            ITypeSymbol fieldType = fieldSymbol.Type;

            // 獲取 AutoNotify Attribute 和相關的資料
            AttributeData attributeData    = fieldSymbol.GetAttributes().Single(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default));
            TypedConstant overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value;

            string propertyName = chooseName(fieldName, overridenNameOpt);

            if (propertyName.Length == 0 || propertyName == fieldName)
            {
                //TODO: 無法處理,產生診斷資訊
                return;
            }

            source.Append($@"
public {fieldType} {propertyName} 
{{
    get 
    {{
        return this.{fieldName};
    }}
    set
    {{
        this.{fieldName} = value;
        this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof({propertyName})));
    }}
}}
");
        }
예제 #6
0
        public static FieldDeclarationSyntax GenerateFieldDeclaration(
            IFieldSymbol field, CodeGenerationOptions options)
        {
            var reusableSyntax = GetReuseableSyntaxNodeForSymbol <VariableDeclaratorSyntax>(field, options);

            if (reusableSyntax != null)
            {
                if (reusableSyntax.Parent is VariableDeclarationSyntax variableDeclaration)
                {
                    var newVariableDeclaratorsList = new SeparatedSyntaxList <VariableDeclaratorSyntax>().Add(reusableSyntax);
                    var newVariableDeclaration     = variableDeclaration.WithVariables(newVariableDeclaratorsList);
                    if (variableDeclaration.Parent is FieldDeclarationSyntax fieldDecl)
                    {
                        return(fieldDecl.WithDeclaration(newVariableDeclaration));
                    }
                }
            }

            var initializer = CodeGenerationFieldInfo.GetInitializer(field) is ExpressionSyntax initializerNode
                ? SyntaxFactory.EqualsValueClause(initializerNode)
                : GenerateEqualsValue(field);

            var fieldDeclaration = SyntaxFactory.FieldDeclaration(
                AttributeGenerator.GenerateAttributeLists(field.GetAttributes(), options),
                GenerateModifiers(field, options),
                SyntaxFactory.VariableDeclaration(
                    field.Type.GenerateTypeSyntax(),
                    SyntaxFactory.SingletonSeparatedList(
                        AddAnnotationsTo(field, SyntaxFactory.VariableDeclarator(field.Name.ToIdentifierToken(), null, initializer)))));

            return(AddFormatterAndCodeGeneratorAnnotationsTo(
                       ConditionallyAddDocumentationCommentTo(fieldDeclaration, field, options)));
        }
예제 #7
0
            public override void VisitField(IFieldSymbol symbol)
            {
                foreach (var attr in symbol.GetAttributes())
                {
                    if (attr.AttributeClass == mChecker.mLuaCallCSharpSymbol)
                    {
                        VariableDeclaratorSyntax node = symbol.DeclaringSyntaxReferences.Single().GetSyntax() as VariableDeclaratorSyntax;

                        if (node != null)
                        {
                            var allTypes = node.DescendantNodes().OfType <TypeOfExpressionSyntax>().Select((a) => a.Type);

                            var semanticMode = mChecker.mCompilation.GetSemanticModel(node.SyntaxTree);

                            foreach (var t in allTypes)
                            {
                                var symbolInfo = semanticMode.GetSymbolInfo(t);

                                if (symbolInfo.Symbol != null)
                                {
                                    LuaCallCSharpSymbols.Add(symbolInfo.Symbol);
                                }
                                else
                                {
                                    Console.WriteLine("failed to get GetSymbolInfo from " + t.ToString());
                                }
                            }
                        }
                    }
                }
            }
            private static string GetNewFieldName(IFieldSymbol fieldSymbol)
            {
                var name = fieldSymbol.Name.Trim('_');

                if (name.Length > 2 && char.IsLetter(name[0]) && name[1] == '_')
                {
                    name = name.Substring(2);
                }

                if (name.Length == 0)
                {
                    return(fieldSymbol.Name);
                }

                if (name.Length > 2 && char.IsUpper(name[0]) && char.IsLower(name[1]))
                {
                    name = char.ToLower(name[0]) + name.Substring(1);
                }

                if (fieldSymbol.IsStatic)
                {
                    // Check for ThreadStatic private fields.
                    if (fieldSymbol.GetAttributes().Any(a => a.AttributeClass.Name.Equals("ThreadStaticAttribute", StringComparison.Ordinal)))
                    {
                        return("t_" + name);
                    }
                    else
                    {
                        return("s_" + name);
                    }
                }

                return("_" + name);
            }
예제 #9
0
                static bool IsDataContractSerializable(IFieldSymbol symbol, INamedTypeSymbol dataContractAttribute, INamedTypeSymbol dataMemberAttribute)
                {
                    if (dataContractAttribute is null || dataMemberAttribute is null)
                    {
                        return(false);
                    }

                    return(symbol.GetAttributes().Any(static (x, dataMemberAttribute) => SymbolEqualityComparer.Default.Equals(x.AttributeClass, dataMemberAttribute), dataMemberAttribute) &&
        static void VerifyField(DiagnosticsReportContext context, IFieldSymbol field, HashSet <ITypeSymbol> alreadyAnalyzed, HashSet <int> definedIndexes)
        {
            if (field.IsStatic)
            {
                return;
            }

            if (field.DeclaredAccessibility != Accessibility.Public)
            {
                return;
            }

            var attributes = field.GetAttributes();

            if (attributes.FindAttributeShortName(IgnoreShortName) != null)
            {
                return;
            }

            if (!field.ContainingType.IsValueType)
            {
                context.Add(Diagnostic.Create(ClassNotSupportPublicField, field.Locations[0], field.ContainingType?.Name, field.Name));
                return;
            }

            var indexAttr = attributes.FindAttributeShortName(IndexAttributeShortName);

            if (indexAttr == null || indexAttr.ConstructorArguments.Length == 0)
            {
                context.Add(Diagnostic.Create(PublicPropertyNeedsIndex, field.Locations[0], field.ContainingType?.Name, field.Name));
                return;
            }

            var index = indexAttr.ConstructorArguments[0];

            if (index.IsNull)
            {
                return; // null is normal compiler error.
            }

            if (!definedIndexes.Add((int)index.Value))
            {
                context.Add(Diagnostic.Create(IndexAttributeDuplicate, field.Locations[0], field.ContainingType?.Name, field.Name, index.Value));
                return;
            }

            if ((int)index.Value >= 100)
            {
                context.Add(Diagnostic.Create(IndexIsTooLarge, field.Locations[0], index.Value, field.Name));
            }

            var namedType = field.Type as INamedTypeSymbol;

            if (namedType != null) // if <T> is unnamed type, it can't analyze.
            {
                VerifyType(context, field.Locations[0], field.Type, alreadyAnalyzed, field);
            }
        }
예제 #11
0
        private void ProcessField(StringBuilder source, IFieldSymbol fieldSymbol, ISymbol attributeSymbol)
        {
            // get the name and type of the field
            string      fieldName = fieldSymbol.Name;
            ITypeSymbol fieldType = fieldSymbol.Type;

            // get the AutoNotify attribute from the field, and any associated data
            AttributeData attributeData    = fieldSymbol.GetAttributes().Single(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default));
            TypedConstant overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value;

            string propertyName = chooseName(fieldName, overridenNameOpt);

            if (propertyName.Length == 0 || propertyName == fieldName)
            {
                //TODO: issue a diagnostic that we can't process this field
                return;
            }

            source.Append($@"
public {fieldType} {propertyName} 
{{
    get 
    {{
		StateManager.OnPropertyRead(this, nameof({propertyName}));
		this.PropertyRead?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof({propertyName})));
        return this.{fieldName};
    }}
    set
    {{
        this.{fieldName} = value;
		StateManager.OnPropertyChanged(this, nameof({propertyName}), value);
        this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof({propertyName})));
    }}
}}
");

            string chooseName(string fieldName, TypedConstant overridenNameOpt)
            {
                if (!overridenNameOpt.IsNull)
                {
                    return(overridenNameOpt.Value.ToString());
                }

                fieldName = fieldName.TrimStart('_');
                if (fieldName.Length == 0)
                {
                    return(string.Empty);
                }

                if (fieldName.Length == 1)
                {
                    return(fieldName.ToUpper());
                }

                return(fieldName.Substring(0, 1).ToUpper() + fieldName.Substring(1));
            }
        }
예제 #12
0
        public static void GenerateSerializableProperty(
            this StringBuilder source,
            Compilation compilation,
            string indent,
            IFieldSymbol fieldSymbol,
            Accessibility getter,
            Accessibility?setter,
            bool isVirtual,
            ISymbol?parentFieldOrProperty
            )
        {
            var fieldName = fieldSymbol.Name;

            var invalidatePropertiesAttribute = fieldSymbol
                                                .GetAttributes()
                                                .OfType <AttributeData>()
                                                .FirstOrDefault(
                attr => attr.AttributeClass?.Equals(
                    compilation.GetTypeByMetadataName(SymbolMetadata.INVALIDATEPROPERTIES_ATTRIBUTE),
                    SymbolEqualityComparer.Default
                    ) ?? false
                );

            var propertyIndent = $"{indent}    ";
            var innerIndent    = $"{propertyIndent}    ";

            var propertyAccessor = setter > getter ? setter : getter;
            var getterAccessor   = getter == propertyAccessor ? Accessibility.NotApplicable : getter;

            source.GeneratePropertyStart(indent, propertyAccessor.Value, isVirtual, fieldSymbol);

            // Getter
            source.GeneratePropertyGetterReturnsField(propertyIndent, fieldSymbol, getterAccessor);

            if (setter != null && setter != Accessibility.NotApplicable)
            {
                var setterAccessor = setter == propertyAccessor ? Accessibility.NotApplicable : setter;

                var parentSymbol = parentFieldOrProperty?.Name ?? "this";

                // Setter
                source.GeneratePropertySetterStart(propertyIndent, false, setterAccessor.Value);
                source.AppendLine($"{innerIndent}if (value != {fieldName})");
                source.AppendLine($"{innerIndent}{{");
                source.AppendLine($"{innerIndent}    {fieldName} = value;");
                source.AppendLine($"{innerIndent}    {parentSymbol}.MarkDirty();");

                if (invalidatePropertiesAttribute != null)
                {
                    source.AppendLine($"{innerIndent}    InvalidateProperties();");
                }
                source.AppendLine($"{innerIndent}}}");
                source.GeneratePropertyGetSetEnd(propertyIndent, false);
            }

            source.GeneratePropertyEnd(indent);
        }
예제 #13
0
    private void ProcessField(StringBuilder source, IFieldSymbol fieldSymbol, ISymbol attributeSymbol)
    {
        var fieldName        = fieldSymbol.Name;
        var fieldType        = fieldSymbol.Type;
        var attributeData    = fieldSymbol.GetAttributes().Single(ad => ad?.AttributeClass?.Equals(attributeSymbol, SymbolEqualityComparer.Default) ?? false);
        var overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value;
        var propertyName     = ChooseName(fieldName, overridenNameOpt);

        if (propertyName is null || propertyName.Length == 0 || propertyName == fieldName)
        {
            // Issue a diagnostic that we can't process this field.
            return;
        }

        source.Append($@"
        protected static readonly PropertyChangedEventArgs {fieldName}PropertyChangedEventArgs = new PropertyChangedEventArgs(nameof({propertyName}));");

        var overridenIgnoreDataMemberOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "IgnoreDataMember").Value;
        var ignoreDataMember             = false;

        if (!overridenIgnoreDataMemberOpt.IsNull && overridenIgnoreDataMemberOpt.Value is not null)
        {
            ignoreDataMember = (bool)overridenIgnoreDataMemberOpt.Value;
        }

        if (ignoreDataMember)
        {
            source.Append($@"
		[IgnoreDataMember]"        );
        }
        else
        {
            source.Append($@"
		[DataMember(IsRequired = false, EmitDefaultValue = true)]"        );
        }

        var overridenSetterModifierOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "SetterModifier").Value;
        var setterModifier             = ChooseSetterModifier(overridenSetterModifierOpt);

        if (setterModifier is null)
        {
            source.Append($@"
        public {fieldType} {propertyName}
        {{
            get => {fieldName};
        }}");
        }
        else
        {
            source.Append($@"
        public {fieldType} {propertyName}
        {{
            get => {fieldName};
            {setterModifier}set => RaiseAndSetIfChanged(ref {fieldName}, value, {fieldName}PropertyChangedEventArgs);
        }}");
        }
예제 #14
0
            private bool IsFieldSerializableByAttributes(IFieldSymbol field)
            {
                if (field.GetAttributes()
                    .Any(attr => s_serializingFieldAttributes.Contains(NameHelper.GetFullName(attr.AttributeClass))))
                {
                    return(true);
                }

                return(false);
            }
예제 #15
0
 public FieldSymbolInfo(IFieldSymbol f)
 {
     ContainingType = new TypeSymbolInfo(f.ContainingType);
     RealField      = f;
     FieldType      = new TypeSymbolInfo(f.Type);
     Accessibility  = f.DeclaredAccessibility.ConvertToStructure();
     Attributes     = EnumerableExtensions.CreateLazyImmutableArray(() => RealField.GetAttributes()
                                                                    .Select(AotSymbolExtensions.ConvertToStructure)
                                                                    .Where(i => i != null));
 }
예제 #16
0
        public override IList <CustomAttributeData> GetCustomAttributesData()
        {
            var attributes = new List <CustomAttributeData>();

            foreach (AttributeData a in _field.GetAttributes())
            {
                attributes.Add(new CustomAttributeDataWrapper(a, _metadataLoadContext));
            }
            return(attributes);
        }
예제 #17
0
        private BuilderFieldInfo?TryGetAttributedField(IFieldSymbol fieldSymbol)
        {
            var builderFieldAttribute = fieldSymbol.GetAttributes()
                                        .FirstOrDefault(x => x.AttributeClass?.Name == AttributeName <BuilderFieldAttribute> .GetName() ||
                                                        x.AttributeClass?.Name == AttributeName <BuilderFieldAttribute> .GetPlainName());

            if (builderFieldAttribute is null)
            {
                return(null);
            }

            return(new BuilderFieldInfo(fieldSymbol.Name, fieldSymbol.Type.Name));
        }
예제 #18
0
        public void Execute(GeneratorExecutionContext context)
        {
            // Добавить текст атрибута и вспомогательный класс
            context.AddSource("AutoNotifyAttribute", SourceText.From(attributeAndHelperText, Encoding.UTF8));

            // получаем наш заполненный SyntaxReceiver
            if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
            {
                return;
            }

            // мы создадим новую Compilation с атрибутом
            // TODO: в будущем будет разрешено добавлять исходники во время инициализации, так что этот шаг не будет нужен
            CSharpParseOptions options     = (context.Compilation as CSharpCompilation).SyntaxTrees[0].Options as CSharpParseOptions;
            Compilation        compilation = context.Compilation.AddSyntaxTrees(
                CSharpSyntaxTree.ParseText(SourceText.From(attributeAndHelperText, Encoding.UTF8), options));

            // получаем добавленный атрибут and INotifyPropertyChanged
            INamedTypeSymbol attributeSymbol = compilation.GetTypeByMetadataName("AutoNotify.AutoNotifyAttribute");
            INamedTypeSymbol notifySymbol    = compilation.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged");

            // обходим поля-кандидаты, выбираем только те, у которых действительно есть нужный атрибут
            List <IFieldSymbol> fieldSymbols = new List <IFieldSymbol>();

            foreach (FieldDeclarationSyntax field in receiver.CandidateFields)
            {
                SemanticModel model = compilation.GetSemanticModel(field.SyntaxTree);
                foreach (VariableDeclaratorSyntax variable in field.Declaration.Variables)
                {
                    // получаем символ, декларируемый этим полем, и запоминаем его, если он и правда имеет атрибут
                    IFieldSymbol fieldSymbol = model.GetDeclaredSymbol(variable) as IFieldSymbol;
                    if (fieldSymbol.GetAttributes().Any(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default)))
                    {
                        fieldSymbols.Add(fieldSymbol);
                    }
                }
            }

            // сгруппируем поля по классам, и сгенерируем новые исходные файлы
            foreach (IGrouping <INamedTypeSymbol, IFieldSymbol> group in fieldSymbols.GroupBy(f => f.ContainingType))
            {
                CompilationUnitSyntax classDef = ProcessClass(group.Key, group.ToList(), attributeSymbol, notifySymbol, context, options);
                if (classDef is null)
                {
                    continue;
                }
                var classSource  = classDef.ToFullString();
                var filenameHint = $"{group.Key.Name}_autoNotify.cs";
                context.AddSource(filenameHint, SourceText.From(classSource, Encoding.UTF8));
            }
        }
예제 #19
0
        private void ProcessField(StringBuilder source, IFieldSymbol fieldSymbol, ISymbol attributeSymbol)
        {
            // get the name and type of the field
            string      fieldName = fieldSymbol.Name;
            ITypeSymbol fieldType = fieldSymbol.Type;

            // get the AutoNotify attribute from the field, and any associated data
            AttributeData attributeData    = fieldSymbol.GetAttributes().Single(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default));
            TypedConstant overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value;

            string propertyName = ChooseName();

            if (propertyName.Length == 0 || propertyName == fieldName)
            {
                //TODO: issue a diagnostic that we can't process this field
                return;
            }

            source.AppendLinesIndented(2, "");
            source.AppendLinesIndented(2, $"/// <inheritdoc cref=\"{fieldName}\" />");
            source.AppendLinesIndented(2, $"public {fieldType} {propertyName}");
            source.AppendLinesIndented(2, "{");
            source.AppendLinesIndented(3, $"get => this.{fieldName};");
            source.AppendLinesIndented(3, "set");
            source.AppendLinesIndented(3, "{");
            source.AppendLinesIndented(4, $"this.{fieldName} = value;");
            source.AppendLinesIndented(4, $"this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof({propertyName})));");
            source.AppendLinesIndented(3, "}");
            source.AppendLinesIndented(2, "}");

            string ChooseName()
            {
                if (!overridenNameOpt.IsNull)
                {
                    return(overridenNameOpt.Value.ToString());
                }

                fieldName = fieldName.TrimStart('_');
                if (fieldName.Length == 0)
                {
                    return(string.Empty);
                }

                if (fieldName.Length == 1)
                {
                    return(fieldName.ToUpper());
                }

                return(fieldName.Substring(0, 1).ToUpper() + fieldName.Substring(1));
            }
        }
        private static bool IsSuppressable(IFieldSymbol fieldSymbol)
        {
            if (fieldSymbol.GetAttributes().Any(a => a.AttributeClass.Matches(typeof(SerializeField)) || a.AttributeClass.Matches(typeof(SerializeReference))))
            {
                return(true);
            }

            if (fieldSymbol.DeclaredAccessibility == Accessibility.Public && fieldSymbol.ContainingType.Extends(typeof(Object)))
            {
                return(true);
            }

            return(false);
        }
        private IFieldSymbol GetExplicitlyAssignedField(IFieldSymbol originalField, SyntaxGenerator syntaxFactoryService)
        {
            var originalInitializer = GetFieldInitializer(originalField);
            if (originalInitializer != null || !originalField.HasConstantValue)
            {
                return originalField;
            }

            var constantValueExpression = syntaxFactoryService.LiteralExpression(originalField.ConstantValue);
            var newInitializer = CreateConstantValueInitializer(constantValueExpression);

            return CodeGenerationSymbolFactory.CreateFieldSymbol(originalField.GetAttributes(), originalField.DeclaredAccessibility, originalField.GetSymbolModifiers(),
                originalField.Type, originalField.Name, originalField.HasConstantValue, originalField.ConstantValue, newInitializer);
        }
예제 #22
0
        public void WriteFieldDefinition(IFieldSymbol fieldSymbol, bool doNotWrapStatic = false)
        {
            if (fieldSymbol.ContainingType.IsGenericType)
            {
                this.WriteTemplateDeclaration(fieldSymbol.ContainingType);
                this.NewLine();
            }

            if (fieldSymbol.IsStatic && fieldSymbol.GetAttributes().Any(a => a.AttributeClass.Name == "ThreadStaticAttribute" && a.AttributeClass.ContainingSymbol.Name == "System"))
            {
                this.TextSpan("thread_local");
                this.WhiteSpace();
            }

            if (fieldSymbol.IsStatic && !doNotWrapStatic)
            {
                this.TextSpan("__static<");
            }

            this.WriteType(fieldSymbol.Type);

            if (fieldSymbol.IsStatic && !doNotWrapStatic)
            {
                this.TextSpan(",");
                this.WhiteSpace();
                this.WriteType(fieldSymbol.ContainingType, true, true, true);
                this.TextSpan(">");
            }

            this.WhiteSpace();

            if (fieldSymbol.ContainingNamespace != null)
            {
                this.WriteNamespace(fieldSymbol.ContainingNamespace);
                this.TextSpan("::");
            }

            var receiverType = fieldSymbol.ContainingType;

            this.WriteTypeName(receiverType, false);
            if (receiverType.IsGenericType)
            {
                this.WriteTemplateDefinition(fieldSymbol.ContainingType);
            }

            this.TextSpan("::");

            this.WriteName(fieldSymbol);
        }
예제 #23
0
        private IFieldSymbol GetExplicitlyAssignedField(IFieldSymbol originalField, SyntaxGenerator syntaxFactoryService)
        {
            var originalInitializer = GetFieldInitializer(originalField);

            if (originalInitializer != null || !originalField.HasConstantValue)
            {
                return(originalField);
            }

            var constantValueExpression = syntaxFactoryService.LiteralExpression(originalField.ConstantValue);
            var newInitializer          = CreateConstantValueInitializer(constantValueExpression);

            return(CodeGenerationSymbolFactory.CreateFieldSymbol(originalField.GetAttributes(), originalField.DeclaredAccessibility, originalField.GetSymbolModifiers(),
                                                                 originalField.Type, originalField.Name, originalField.HasConstantValue, originalField.ConstantValue, newInitializer));
        }
        public void Execute(GeneratorExecutionContext context)
        {
            string ns = Helper.GetNamespace(context, "AutoNotify");

            // add the attribute text
            string snippet = attributeText.Replace("{ns}", ns);

            context.AddSource("AutoNotifyAttribute", SourceText.From(snippet, Encoding.UTF8));

            // retreive the populated receiver
            if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
            {
                return;
            }

            // we're going to create a new compilation that contains the attribute.
            // TODO: we should allow source generators to provide source during initialize, so that this step isn't required.
            CSharpParseOptions options     = (context.Compilation as CSharpCompilation).SyntaxTrees[0].Options as CSharpParseOptions;
            Compilation        compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(snippet, Encoding.UTF8), options));

            // get the newly bound attribute, and INotifyPropertyChanged
            INamedTypeSymbol attributeSymbol = compilation.GetTypeByMetadataName($"{ns}.AutoNotifyAttribute");
            INamedTypeSymbol notifySymbol    = compilation.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged");

            // loop over the candidate fields, and keep the ones that are actually annotated
            List <IFieldSymbol> fieldSymbols = new List <IFieldSymbol>();

            foreach (FieldDeclarationSyntax field in receiver.CandidateFields)
            {
                SemanticModel model = compilation.GetSemanticModel(field.SyntaxTree);
                foreach (VariableDeclaratorSyntax variable in field.Declaration.Variables)
                {
                    // Get the symbol being decleared by the field, and keep it if its annotated
                    IFieldSymbol fieldSymbol = model.GetDeclaredSymbol(variable) as IFieldSymbol;
                    if (fieldSymbol.GetAttributes().Any(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default)))
                    {
                        fieldSymbols.Add(fieldSymbol);
                    }
                }
            }

            // group the fields by class, and generate the source
            foreach (IGrouping <INamedTypeSymbol, IFieldSymbol> group in fieldSymbols.GroupBy(f => f.ContainingType))
            {
                string classSource = ProcessClass(group.Key, group.ToList(), attributeSymbol, notifySymbol, context);
                context.AddSource($"{group.Key.Name}_autoNotify.cs", SourceText.From(classSource, Encoding.UTF8));
            }
        }
예제 #25
0
        private void ProcessField(StringBuilder source, IFieldSymbol fieldSymbol, ISymbol attributeSymbol)
        {
            // get the name and type of the field
            string      fieldName = fieldSymbol.Name;
            ITypeSymbol fieldType = fieldSymbol.Type;

            // get the GenerateProperty attribute from the field, and any associated data
            AttributeData attributeData = fieldSymbol.GetAttributes().Single(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default));

            TypedConstant overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value;

            string propertyName = GeneratePropertyName(fieldName, overridenNameOpt);

            if (propertyName.Length == 0 || propertyName == fieldName)
            {
                //TODO: issue a diagnostic that we can't process this field
                return;
            }

            TypedConstant overridenAccessOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "AccessModifier").Value;
            string        accessModifier     = overridenAccessOpt.IsNull ? "public" : overridenAccessOpt.Value.ToString();

            TypedConstant overridenAccessGetOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "AccessModifierGet").Value;
            string        accessModifierGet     = overridenAccessGetOpt.IsNull ? "" : $"{overridenAccessGetOpt.Value.ToString()} ";

            TypedConstant overridenAccessSetOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "AccessModifierSet").Value;
            string        accessModifierSet     = overridenAccessSetOpt.IsNull ? "" : $"{overridenAccessSetOpt.Value.ToString()} ";

            source.Append($@"
        {accessModifier} {fieldType} {propertyName} 
        {{
            {accessModifierGet}get 
            {{
                return this.{fieldName};
            }}

            {accessModifierSet}set
            {{
                var oldValue = this.{fieldName};
                if (oldValue == value) return;
                this.PropertyChanging?.Invoke(this, new DotNetApp.Extensions.PropertyChangingExtendedEventArgs<{fieldType}>(nameof({propertyName}), oldValue, value));
                this.{fieldName} = value;
                this.PropertyChanged?.Invoke(this, new DotNetApp.Extensions.PropertyChangedExtendedEventArgs<{fieldType}>(nameof({propertyName}), oldValue, value));
            }}
        }}

");
        }
예제 #26
0
        public void WriteFieldDeclaration(IFieldSymbol fieldSymbol, bool doNotWrapStatic = false)
        {
            if (fieldSymbol.IsStatic)
            {
                this.TextSpan("static");
                this.WhiteSpace();

                if (fieldSymbol.GetAttributes().Any(a => a.AttributeClass.Name == "ThreadStaticAttribute" && a.AttributeClass.ContainingSymbol.Name == "System"))
                {
                    this.TextSpan("thread_local");
                    this.WhiteSpace();
                }

                if (!doNotWrapStatic)
                {
                    this.TextSpan("__static<");
                }
            }

            var fieldSymbolOriginal = fieldSymbol as FieldSymbol;

            if (fieldSymbolOriginal != null && fieldSymbolOriginal.IsFixed)
            {
                this.WriteType(((IPointerTypeSymbol)fieldSymbol.Type).PointedAtType);
            }
            else
            {
                this.WriteType(fieldSymbol.Type);
            }

            if (fieldSymbol.IsStatic && !doNotWrapStatic)
            {
                this.TextSpan(",");
                this.WhiteSpace();
                this.WriteType(fieldSymbol.ContainingType, true, true, true);
                this.TextSpan(">");
            }

            this.WhiteSpace();
            this.WriteName(fieldSymbol);

            if (fieldSymbolOriginal != null && fieldSymbolOriginal.IsFixed)
            {
                this.TextSpan("[");
                this.TextSpan(fieldSymbolOriginal.FixedSize.ToString());
                this.TextSpan("]");
            }
        }
예제 #27
0
		public static string GetWidgetFieldName (IFieldSymbol field)
		{
			foreach (AttributeData att in field.GetAttributes ())	{
				var type = att.AttributeClass;
				if (type.Name == "Widget" ||  type.Name == "WidgetAttribute") {
					var pArgs = att.ConstructorArguments;
					if (pArgs != null && pArgs.Length > 0) {
						var exp = pArgs[0].Value;
						if (exp != null)
							return exp.ToString ();
					} else {
						return field.Name;
					}
				}
			}
			return field.Name;
		}
예제 #28
0
        private void ProcessField(StringBuilder source, IFieldSymbol fieldSymbol, ISymbol attributeSymbol)
        {
            string      fieldName = fieldSymbol.Name;
            ITypeSymbol fieldType = fieldSymbol.Type;

            AttributeData attributeData    = fieldSymbol.GetAttributes().Single(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default));
            TypedConstant overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value;

            string propertyName = CreatePropertyName(fieldName, overridenNameOpt);

            if (propertyName.Length == 0 || propertyName == fieldName)
            {
                //TODO: issue a diagnostic that we can't process this field
                return;
            }

            source.Append($@"
public {fieldType} {propertyName} 
{{
    get => this.{fieldName};
    set => Set(ref this.{fieldName}, value);
}}

");

            string CreatePropertyName(string fieldName, TypedConstant overridenNameOpt)
            {
                if (!overridenNameOpt.IsNull)
                {
                    return(overridenNameOpt.Value.ToString());
                }

                fieldName = fieldName.TrimStart('_');
                if (fieldName.Length == 0)
                {
                    return(string.Empty);
                }

                if (fieldName.Length == 1)
                {
                    return(fieldName.ToUpper());
                }

                return(fieldName.Substring(0, 1).ToUpper() + fieldName.Substring(1));
            }
        }
예제 #29
0
        private static bool BackingFieldHasNonSerializedAttribute(IFieldSymbol fieldSymbol, Compilation compilation)
        {
            ImmutableArray <AttributeData> attributes = fieldSymbol.GetAttributes();

            for (int i = 0; i < attributes.Length; i++)
            {
                INamedTypeSymbol attributeSymbol = attributes[i].AttributeClass;

                if (attributeSymbol.MetadataName == "NonSerializedAttribute" &&
                    attributeSymbol.Equals(compilation.GetTypeByMetadataName(MetadataNames.System_NonSerializedAttribute)))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #30
0
 /// <summary>
 /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation
 /// </summary>
 public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
 {
     // any field with at least one attribute is a candidate for property generation
     if (context.Node is FieldDeclarationSyntax fieldDeclarationSyntax &&
         fieldDeclarationSyntax.AttributeLists.Count > 0)
     {
         foreach (VariableDeclaratorSyntax variable in fieldDeclarationSyntax.Declaration.Variables)
         {
             // Get the symbol being declared by the field, and keep it if its annotated
             IFieldSymbol fieldSymbol = context.SemanticModel.GetDeclaredSymbol(variable) as IFieldSymbol;
             if (fieldSymbol.GetAttributes().Any(ad => ad.AttributeClass.ToDisplayString() == "Comet.AutoNotifyAttribute"))
             {
                 Fields.Add(fieldSymbol);
             }
         }
     }
 }
예제 #31
0
        public override MetadataItem VisitField(IFieldSymbol symbol)
        {
            var item = GetMetadataItem(symbol);

            if (item == null)
            {
                return(null);
            }

            item.EnsureSyntax();

            item.Syntax.Content = symbol.GenerateSyntax(item.Type, ApiFilter);
            item.Modifiers      = symbol.GetFieldModifiers();
            item.Syntax.Return  = CreateParameter(symbol, item, true);
            item.Attributes     = GetAttributeInfo(symbol.GetAttributes());

            return(item);
        }
예제 #32
0
        public void Execute(GeneratorExecutionContext context)
        {
            // 新增 Attrbite 文字
            context.AddSource("AutoNotifyAttribute", SourceText.From(attributeText, Encoding.UTF8));

            // 獲取先前的語法接收器
            if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
            {
                return;
            }

            // 建立處目標名稱的屬性
            CSharpParseOptions options     = (context.Compilation as CSharpCompilation).SyntaxTrees[0].Options as CSharpParseOptions;
            Compilation        compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(attributeText, Encoding.UTF8), options));

            // 獲取新繫結的 Attribute,並獲取INotifyPropertyChanged
            INamedTypeSymbol attributeSymbol = compilation.GetTypeByMetadataName("AutoNotify.AutoNotifyAttribute");
            INamedTypeSymbol notifySymbol    = compilation.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged");

            // 遍歷欄位,只保留有 AutoNotify 標註的欄位
            List <IFieldSymbol> fieldSymbols = new List <IFieldSymbol>();

            foreach (FieldDeclarationSyntax field in receiver.CandidateFields)
            {
                SemanticModel model = compilation.GetSemanticModel(field.SyntaxTree);
                foreach (VariableDeclaratorSyntax variable in field.Declaration.Variables)
                {
                    // 獲取欄位符號資訊,如果有 AutoNotify 標註則儲存
                    IFieldSymbol fieldSymbol = ModelExtensions.GetDeclaredSymbol(model, variable) as IFieldSymbol;
                    if (fieldSymbol.GetAttributes().Any(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default)))
                    {
                        fieldSymbols.Add(fieldSymbol);
                    }
                }
            }

            // 按 class 對欄位進行分組,並生成程式碼
            foreach (IGrouping <INamedTypeSymbol, IFieldSymbol> group in fieldSymbols.GroupBy(f => f.ContainingType))
            {
                string classSource = ProcessClass(group.Key, group.ToList(), attributeSymbol, notifySymbol, context);
                context.AddSource($"{group.Key.Name}_autoNotify.cs", SourceText.From(classSource, Encoding.UTF8));
            }
        }
예제 #33
0
        public static FieldDeclarationSyntax GenerateFieldDeclaration(
            IFieldSymbol field, CodeGenerationDestination destination, CodeGenerationOptions options)
        {
            var reusableSyntax = GetReuseableSyntaxNodeForSymbol<VariableDeclaratorSyntax>(field, options);
            if (reusableSyntax != null)
            {
                var variableDeclaration = reusableSyntax.Parent as VariableDeclarationSyntax;
                if (variableDeclaration != null)
                {
                    var newVariableDeclaratorsList = new SeparatedSyntaxList<VariableDeclaratorSyntax>().Add(reusableSyntax);
                    var newVariableDeclaration = variableDeclaration.WithVariables(newVariableDeclaratorsList);
                    var fieldDecl = variableDeclaration.Parent as FieldDeclarationSyntax;
                    if (fieldDecl != null)
                    {
                        return fieldDecl.WithDeclaration(newVariableDeclaration);
                    }
                }
            }

            var initializerNode = CodeGenerationFieldInfo.GetInitializer(field) as ExpressionSyntax;

            var initializer = initializerNode != null
                ? SyntaxFactory.EqualsValueClause(initializerNode)
                : GenerateEqualsValue(field);

            var fieldDeclaration = SyntaxFactory.FieldDeclaration(
                AttributeGenerator.GenerateAttributeLists(field.GetAttributes(), options),
                GenerateModifiers(field, options),
                SyntaxFactory.VariableDeclaration(
                    field.Type.GenerateTypeSyntax(),
                    SyntaxFactory.SingletonSeparatedList(
                        AddAnnotationsTo(field, SyntaxFactory.VariableDeclarator(field.Name.ToIdentifierToken(), null, initializer)))));

            return AddCleanupAnnotationsTo(
                ConditionallyAddDocumentationCommentTo(fieldDeclaration, field, options));
        }
            private static string GetNewFieldName(IFieldSymbol fieldSymbol)
            {
                var name = fieldSymbol.Name.Trim('_');
                if (name.Length > 2 && char.IsLetter(name[0]) && name[1] == '_')
                {
                    name = name.Substring(2);
                }

                if (name.Length == 0)
                {
                    return fieldSymbol.Name;
                }

                if (name.Length > 2 && char.IsUpper(name[0]) && char.IsLower(name[1]))
                {
                    name = char.ToLower(name[0]) + name.Substring(1);
                }

                if (fieldSymbol.IsStatic)
                {
                    // Check for ThreadStatic private fields.
                    if (fieldSymbol.GetAttributes().Any(a => a.AttributeClass.Name.Equals("ThreadStaticAttribute", StringComparison.Ordinal)))
                    {
                        return "t_" + name;
                    }
                    else
                    {
                        return "s_" + name;
                    }
                }

                return "_" + name;
            }
            private bool IsFieldSerializableByAttributes(IFieldSymbol field)
            {
                if (field.GetAttributes()
                    .Any(attr => s_serializingFieldAttributes.Contains(NameHelper.GetFullName(attr.AttributeClass))))
                {
                    return true;
                }

                return false;
            }
 internal static bool IsValidField(IFieldSymbol field, TypeDeclarationSyntax type)
 {
     if (field == null || field.GetAttributes().Count() > 0)
         return false;
     foreach (var m in type.Members.OfType<FieldDeclarationSyntax>())
     {
         foreach (var i in m.Declaration.Variables)
         {
             if (i.SpanStart == field.Locations.First().SourceSpan.Start)
             {
                 if (i.Initializer != null)
                     return false;
                 break;
             }
         }
     }
     return true;
 }