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); }}"); }
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))); }
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); }
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)); }
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}))); }} }} "); }
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))); }
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); }
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); } }
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)); } }
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); }
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); }}"); }
private bool IsFieldSerializableByAttributes(IFieldSymbol field) { if (field.GetAttributes() .Any(attr => s_serializingFieldAttributes.Contains(NameHelper.GetFullName(attr.AttributeClass)))) { return(true); } return(false); }
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)); }
public override IList <CustomAttributeData> GetCustomAttributesData() { var attributes = new List <CustomAttributeData>(); foreach (AttributeData a in _field.GetAttributes()) { attributes.Add(new CustomAttributeDataWrapper(a, _metadataLoadContext)); } return(attributes); }
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)); }
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)); } }
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); }
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); }
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)); } }
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)); }} }} "); }
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("]"); } }
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; }
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)); } }
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); }
/// <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); } } } }
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); }
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)); } }
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; }