public static async Task <Tuple <ConverterProcessingResult, ExpressionSyntax> > ProcessMetadata(SyntaxGenerator generator, SemanticModel semanticModel, ISymbol fieldSymbol, CancellationToken cancellationToken) { var declarator = (VariableDeclaratorSyntax)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken); ExpressionSyntax coerceCallbackSyntax = null; var initializer = (InvocationExpressionSyntax)declarator.Initializer.Value; var metadataInitializer = (ObjectCreationExpressionSyntax)initializer.ArgumentList.Arguments[3].Expression; var metadataChanges = new ConverterProcessingResult(); if (metadataInitializer.ArgumentList.Arguments.Any()) { var currentArgument = 0; var firstArgument = metadataInitializer.ArgumentList.Arguments[currentArgument]; var firstArgumentType = semanticModel.GetTypeInfo(firstArgument.Expression, cancellationToken).ConvertedType; if (firstArgumentType.ToDisplayString() == "System.Windows.PropertyChangedCallback") // Null is a delegate { metadataChanges = metadataChanges.AddStaticConstructorStatements( BuildChangedHandler(generator, fieldSymbol.ContainingType, declarator, firstArgument)); ++currentArgument; if (metadataInitializer.ArgumentList.Arguments.Count > currentArgument) { coerceCallbackSyntax = metadataInitializer.ArgumentList.Arguments[currentArgument].Expression; currentArgument++; } } else { metadataChanges = metadataChanges.AddArguments(metadataInitializer.ArgumentList.Arguments[currentArgument]); ++currentArgument; if (metadataInitializer.ArgumentList.Arguments.Count > currentArgument) { var metadataType = semanticModel.GetTypeInfo(metadataInitializer, cancellationToken).Type; var secondArgument = metadataInitializer.ArgumentList.Arguments[currentArgument].Expression; var secondArgumentType = semanticModel.GetTypeInfo(secondArgument, cancellationToken).ConvertedType; if (secondArgumentType.ToString() == "System.Windows.FrameworkPropertyMetadataOptions") { metadataChanges = metadataChanges.AppendResult(ProcessFrameworkMetadataOptions( generator, semanticModel, secondArgument, secondArgumentType, fieldSymbol.Name, cancellationToken)); ++currentArgument; } } if (metadataInitializer.ArgumentList.Arguments.Count > currentArgument) { var changedCallback = metadataInitializer.ArgumentList.Arguments[currentArgument]; var containingType = fieldSymbol.ContainingType; metadataChanges = metadataChanges.AddStaticConstructorStatements( BuildChangedHandler(generator, containingType, declarator, changedCallback)); ++currentArgument; } if (metadataInitializer.ArgumentList.Arguments.Count > currentArgument) { coerceCallbackSyntax = metadataInitializer.ArgumentList.Arguments[currentArgument].Expression; currentArgument++; } // We do not have support for the remaining metadata items (disable animation, update source trigger) so we stop processing here. } } return(Tuple.Create(metadataChanges, coerceCallbackSyntax)); }
internal static async Task <Document> ConvertProperty(Document document, VariableDeclaratorSyntax declarator, CancellationToken cancellationToken) { var editor = await DocumentEditor.CreateAsync(document, cancellationToken); var semanticModel = editor.SemanticModel; var fieldSymbol = semanticModel.GetDeclaredSymbol(declarator); var initializer = (InvocationExpressionSyntax)declarator.Initializer.Value; var originalRegisterMethodName = ((MemberAccessExpressionSyntax)initializer.Expression).Name.ToString(); var avaloniaInvocation = GenerateBasicInvocation(editor.Generator, fieldSymbol, initializer, originalRegisterMethodName); var originalStaticConstructor = fieldSymbol.ContainingType.StaticConstructors.IsEmpty || fieldSymbol.ContainingType.StaticConstructors[0].DeclaringSyntaxReferences.IsEmpty ? null : (ConstructorDeclarationSyntax)await fieldSymbol.ContainingType.StaticConstructors[0].DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken); var staticConstructor = originalStaticConstructor == null?GenerateEmptyStaticConstructor(editor.Generator, fieldSymbol.ContainingType) : originalStaticConstructor; ExpressionSyntax coerceCallbackSyntax = null; ExpressionSyntax validationCallbackSyntax = null; var changeList = new ConverterProcessingResult(); if (initializer.ArgumentList.Arguments.Count > 3) // Have to break down metadata constructor { var results = await ProcessMetadata(editor.Generator, semanticModel, fieldSymbol, cancellationToken); changeList = changeList.AppendResult(results.Item1); coerceCallbackSyntax = results.Item2; } if (initializer.ArgumentList.Arguments.Count > 4) { validationCallbackSyntax = initializer.ArgumentList.Arguments[4].Expression; } if (coerceCallbackSyntax != null || validationCallbackSyntax != null) { var combinedCoerceValidateExpression = CreateCombinedCoerceValidate(editor.Generator, semanticModel, coerceCallbackSyntax, validationCallbackSyntax); changeList = changeList.AddArguments((ArgumentSyntax)editor.Generator.Argument("validate", RefKind.None, combinedCoerceValidateExpression)); } avaloniaInvocation = avaloniaInvocation.AddArgumentListArguments(changeList.AdditionalInvocationArguments.ToArray()) .WithAdditionalAnnotations(Formatter.Annotation); ReplaceMember(editor, semanticModel, declarator, avaloniaInvocation); staticConstructor = staticConstructor.AddBodyStatements(changeList.AdditionalStaticConstructorStatements.ToArray()) .WithAdditionalAnnotations(Formatter.Annotation); if (originalStaticConstructor != null) { if (originalStaticConstructor.Body.Statements.Count < staticConstructor.Body.Statements.Count) { editor.ReplaceNode(originalStaticConstructor, staticConstructor); } } else if (staticConstructor.Body.Statements.Count > 0) { editor.AddMember(await fieldSymbol.ContainingType.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken), staticConstructor); } return(await ImportAdder.AddImportsAsync(editor.GetChangedDocument(), Annotations.NamespaceImportAnnotation, cancellationToken : cancellationToken)); }
public ConverterProcessingResult AppendResult(ConverterProcessingResult otherResult) { return(new ConverterProcessingResult(AdditionalInvocationArguments.Concat(otherResult.AdditionalInvocationArguments).ToList(), AdditionalStaticConstructorStatements.Concat(otherResult.AdditionalStaticConstructorStatements).ToList())); }