コード例 #1
0
        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));
        }
コード例 #2
0
        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));
        }
コード例 #3
0
 public ConverterProcessingResult AppendResult(ConverterProcessingResult otherResult)
 {
     return(new ConverterProcessingResult(AdditionalInvocationArguments.Concat(otherResult.AdditionalInvocationArguments).ToList(),
                                          AdditionalStaticConstructorStatements.Concat(otherResult.AdditionalStaticConstructorStatements).ToList()));
 }