public static (bool hasAttribute, ITypeSymbol?managedType, CustomTypeMarshallerData?kind) GetMarshallerShapeInfo(ITypeSymbol marshallerType) { var attr = marshallerType.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString() == TypeNames.CustomTypeMarshallerAttribute); if (attr is null) { return(false, null, null); } if (attr.ConstructorArguments.Length == 0) { return(true, null, null); } CustomTypeMarshallerKind kind = CustomTypeMarshallerKind.Value; ITypeSymbol?managedType = attr.ConstructorArguments[0].Value as ITypeSymbol; if (attr.ConstructorArguments.Length > 1) { if (attr.ConstructorArguments[1].Value is not int i) { return(true, managedType, null); } kind = (CustomTypeMarshallerKind)i; } var namedArguments = attr.NamedArguments.ToImmutableDictionary(); int?bufferSize = namedArguments.TryGetValue(CustomMarshallerAttributeFields.BufferSize, out TypedConstant bufferSizeConstant) ? bufferSizeConstant.Value as int? : null; CustomTypeMarshallerDirection direction = namedArguments.TryGetValue(CustomMarshallerAttributeFields.Direction, out TypedConstant directionConstant) ? (CustomTypeMarshallerDirection)directionConstant.Value : CustomTypeMarshallerDirection.Ref; CustomTypeMarshallerFeatures features = namedArguments.TryGetValue(CustomMarshallerAttributeFields.Features, out TypedConstant featuresConstant) ? (CustomTypeMarshallerFeatures)featuresConstant.Value : CustomTypeMarshallerFeatures.None; return(true, managedType, new CustomTypeMarshallerData(kind, direction, features, bufferSize)); }
private static SyntaxNode AddMissingFeatures(string attributeName, AttributeData?customTypeMarshallerAttribute, CustomTypeMarshallerFeatures featuresToAdd, SyntaxGenerator gen) { SyntaxNode newAttributeSyntax = gen.Attribute(attributeName); newAttributeSyntax = gen.AddAttributeArguments(newAttributeSyntax, customTypeMarshallerAttribute.ConstructorArguments.Select(a => gen.AttributeArgument(gen.TypedConstantExpression(a)))); CustomTypeMarshallerFeatures newFeaturesValue = featuresToAdd; int?featuresArgLocation = null; newAttributeSyntax = gen.AddAttributeArguments(newAttributeSyntax, customTypeMarshallerAttribute.NamedArguments .Where((a, i) => { if (a.Key == "Features") { // Capture the original location of the 'Features' named argument so we can update it "in place". featuresArgLocation = customTypeMarshallerAttribute.ConstructorArguments.Length + i; newFeaturesValue |= (CustomTypeMarshallerFeatures)a.Value.Value; return(false); } return(true); }) .Select(a => gen.AttributeArgument(a.Key, gen.TypedConstantExpression(a.Value)))); SyntaxNode featureAttributeArgument = gen.AttributeArgument("Features", gen.GetEnumValueAsFlagsExpression( customTypeMarshallerAttribute.AttributeClass.GetMembers(ManualTypeMarshallingHelper.CustomMarshallerAttributeFields.Features).OfType <IPropertySymbol>().First().Type, (int)newFeaturesValue, includeZeroValueFlags: false)); newAttributeSyntax = featuresArgLocation is null ? gen.AddAttributeArguments(newAttributeSyntax, new[] { featureAttributeArgument }) : gen.InsertAttributeArguments(newAttributeSyntax, featuresArgLocation.Value, new[] { featureAttributeArgument }); return(newAttributeSyntax); }
private static (CustomTypeMarshallerFeatures featuresToAdd, List <Diagnostic> fixedDiagnostics) GetFeaturesToAdd(IEnumerable <Diagnostic> diagnostics) { List <Diagnostic> featuresToAddDiagnostics = new(); CustomTypeMarshallerFeatures featuresToAdd = CustomTypeMarshallerFeatures.None; foreach (var diagnostic in diagnostics) { if (diagnostic.Id == AnalyzerDiagnostics.Ids.ProvidedMethodsNotSpecifiedInFeatures) { featuresToAddDiagnostics.Add(diagnostic); if (diagnostic.Properties.TryGetValue(CustomTypeMarshallerAnalyzer.MissingFeaturesKey, out string missingFeatures) && Enum.TryParse(missingFeatures, out CustomTypeMarshallerFeatures featuresValue)) { featuresToAdd |= featuresValue; } } } return(featuresToAdd, featuresToAddDiagnostics); }
private static async Task <Document> AddMissingFeatures(Document doc, SyntaxNode node, CustomTypeMarshallerFeatures featuresToAdd, CancellationToken ct) { var editor = await DocumentEditor.CreateAsync(doc, ct).ConfigureAwait(false); var gen = editor.Generator; ISymbol marshallerType = editor.SemanticModel.GetDeclaredSymbol(node, ct); AttributeData customTypeMarshallerAttribute = marshallerType.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString() == TypeNames.CustomTypeMarshallerAttribute); SyntaxNode attributeSyntax = await customTypeMarshallerAttribute.ApplicationSyntaxReference !.GetSyntaxAsync(ct).ConfigureAwait(false); SyntaxNode updatedDeclaration = AddMissingFeatures(gen.GetName(attributeSyntax), customTypeMarshallerAttribute, featuresToAdd, gen); editor.ReplaceNode(attributeSyntax, updatedDeclaration); return(editor.GetChangedDocument()); }