private Dictionary <string, CodePropertyReferenceExpression> CreatePropertiesForResources(IEnumerable <Resource> resources)
 {
     return(resources.ToDictionary(resource => resource.Key, resource =>
     {
         DataTemplateResource dataTemplateResource = resource as DataTemplateResource;
         Tuple <CodeMemberField, CodeMemberProperty> result;
         if (dataTemplateResource != null)                 // in case of data templates
         {
             const string type = "Storm.Mvvm.DataTemplate";
             result = CodeGeneratorHelper.GenerateProxyProperty(resource.PropertyName, type, fieldReference => new List <CodeStatement>
             {
                 // _field = new DataTemplate();
                 new CodeAssignStatement(fieldReference, new CodeObjectCreateExpression(CodeGeneratorHelper.GetTypeReferenceFromName(type))),
                 // _field.ViewId = Resource.Id.***
                 new CodeAssignStatement(new CodePropertyReferenceExpression(fieldReference, "ViewId"), CodeGeneratorHelper.GetAndroidResourceReference(ResourcePart.Layout, dataTemplateResource.ViewId)),
                 // _field.LayoutInflater = LayoutInflater;
                 new CodeAssignStatement(new CodePropertyReferenceExpression(fieldReference, "LayoutInflater"), GetLayoutInflaterReference()),
                 // _field.ViewHolderType = typeof(viewholder class)
                 new CodeAssignStatement(new CodePropertyReferenceExpression(fieldReference, "ViewHolderType"), new CodeTypeOfExpression(string.Format("{0}.{1}", Configuration.GeneratedNamespace, dataTemplateResource.ViewHolderClassName))),
             });
         }
         else
         {
             // create a proxy property to handle the resource
             string type = resource.Type;
             Dictionary <string, string> assignments = resource.Properties;
             result = CodeGeneratorHelper.GenerateProxyProperty(resource.PropertyName, type, fieldReference => CodeGeneratorHelper.GenerateStatementsCreateAndAssign(fieldReference, type, assignments));
         }
         Fields.Add(result.Item1);
         Properties.Add(result.Item2);
         return CodeGeneratorHelper.GetPropertyReference(result.Item2);
     }));
 }
        private void GenerateCommandParameterProperties(List <ExpressionContainer> expressionContainers)
        {
            foreach (IGrouping <string, ExpressionContainer> expressions in expressionContainers.GroupBy(x => x.TargetObject))
            {
                const string attributeName = "CommandParameter";
                Regex        commandParameterEventRegex = new Regex("^(?<eventName>[a-zA-Z0-9_]+)\\." + attributeName, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                List <ExpressionContainer> commandParameterEventExpressions = expressions.Where(x => commandParameterEventRegex.IsMatch(x.TargetField)).ToList();
                ExpressionContainer        commandParameterExpression       = expressions.SingleOrDefault(x => attributeName.Equals(x.TargetField, StringComparison.InvariantCultureIgnoreCase));

                commandParameterEventExpressions.ForEach(x => x.IsCommandParameterExpression = true);
                if (commandParameterExpression != null)
                {
                    commandParameterExpression.IsCommandParameterExpression = true;
                }

                foreach (ExpressionContainer expression in commandParameterEventExpressions)
                {
                    //find associated event (if exists)
                    string eventName = commandParameterEventRegex.Match(expression.TargetField).Groups["eventName"].Value;
                    ExpressionContainer associatedExpression = expressions.FirstOrDefault(x => eventName.Equals(x.TargetField, StringComparison.InvariantCultureIgnoreCase) && !x.IsCommandParameterExpression);
                    if (associatedExpression != null)
                    {
                        // create proxy property CommandParameterProxy to handle this
                        var result = CodeGeneratorHelper.GenerateProxyProperty(NameGeneratorHelper.GetCommandParameterName(), "CommandParameterProxy");

                        Properties.Add(result.Item2);
                        Fields.Add(result.Item1);

                        string propertyName = CodeGeneratorHelper.GetPropertyReference(result.Item2).PropertyName;

                        // retarget the binding expression to this new property and to the Value field
                        expression.TargetObject = propertyName;
                        expression.TargetField  = "Value";

                        associatedExpression.CommandParameterTarget = propertyName;
                    }
                }

                if (commandParameterExpression != null)
                {
                    // create proxy property CommandParameterProxy to handle this
                    var result = CodeGeneratorHelper.GenerateProxyProperty(NameGeneratorHelper.GetCommandParameterName(), "CommandParameterProxy");

                    Properties.Add(result.Item2);
                    Fields.Add(result.Item1);

                    string propertyName = CodeGeneratorHelper.GetPropertyReference(result.Item2).PropertyName;

                    // retarget the binding expression to this new property and to the Value field
                    commandParameterExpression.TargetObject = propertyName;
                    commandParameterExpression.TargetField  = "Value";

                    foreach (ExpressionContainer associatedExpression in expressions.Where(x => string.IsNullOrEmpty(x.CommandParameterTarget) && !x.IsCommandParameterExpression))
                    {
                        associatedExpression.CommandParameterTarget = propertyName;
                    }
                }
            }
        }
Пример #3
0
 protected override CodeMethodReferenceExpression GetFindViewByIdReference(string typeName)
 {
     return(new CodeMethodReferenceExpression(
                CodeGeneratorHelper.GetPropertyReference("RootView"),
                "FindViewById",
                CodeGeneratorHelper.GetTypeReferenceFromName(typeName)
                ));
 }
        private CodeMethodReferenceExpression CreateSetupResourcesMethod(List <ExpressionContainer> expressions, Dictionary <string, CodePropertyReferenceExpression> resourceReferences)
        {
            CodeMemberMethod method = new CodeMemberMethod
            {
                Attributes = MemberAttributes.Private,
                Name       = NameGeneratorHelper.ASSIGN_RESOURCE_TO_RESOURCE_METHOD_NAME,
            };

            // Create dependency graph to check for cycle in resource assignment
            Dictionary <string, DependencyNode> dependencies = resourceReferences.ToDictionary(x => x.Value.PropertyName, x => new DependencyNode(x.Value.PropertyName));

            foreach (ExpressionContainer expression in expressions)
            {
                string source    = expression.TargetObject;
                string targetKey = expression.Expression.GetValue(ResourceExpression.KEY);
                string target    = resourceReferences[targetKey].PropertyName;

                dependencies[source].Add(dependencies[target]);
            }

            // Check for cycle
            List <DependencyNode> processedNodes = new List <DependencyNode>();
            List <DependencyNode> waitingNodes   = dependencies.Values.ToList();

            while (waitingNodes.Any())
            {
                DependencyNode node = waitingNodes.FirstOrDefault(x => x.Dependencies.All(o => o.IsMarked));

                if (node == null)
                {
                    Log.LogError("Error : Circular references in Resources");
                    throw new InvalidOperationException("Cirular references");
                }

                node.IsMarked = true;
                processedNodes.Add(node);
                waitingNodes.Remove(node);
            }

            // If no cycles, we have the order to assign all resources in correct order
            Dictionary <DependencyNode, IEnumerable <ExpressionContainer> > orderedExpressions = processedNodes.ToDictionary(x => x, x => expressions.Where(o => o.TargetObject == x.Id));

            foreach (DependencyNode node in processedNodes)
            {
                foreach (ExpressionContainer expression in orderedExpressions[node])
                {
                    string resourceKey = expression.Expression.GetValue(ResourceExpression.KEY);
                    method.Statements.Add(SetValueStatement(CodeGeneratorHelper.GetPropertyReference(expression.TargetObject), expression.TargetField, resourceReferences[resourceKey]));
                }
            }

            Methods.Add(method);
            return(CodeGeneratorHelper.GetMethodReference(method));
        }
        private CodePropertyReferenceExpression CreateLocalizationServiceProperty()
        {
            CodeMethodReferenceExpression resolveMethodReference = new CodeMethodReferenceExpression(
                new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(CodeGeneratorHelper.GetTypeReferenceFromName("DependencyService")), "Container"),
                "Resolve",
                CodeGeneratorHelper.GetTypeReferenceFromName("ILocalizationService")
                );
            CodeMethodInvokeExpression invokeMethod = new CodeMethodInvokeExpression(resolveMethodReference);

            Tuple <CodeMemberField, CodeMemberProperty> result = CodeGeneratorHelper.GenerateProxyProperty(NameGeneratorHelper.LOCALIZATION_SERVICE_PROPERTY_NAME, "ILocalizationService", invokeMethod);

            Fields.Add(result.Item1);
            Properties.Add(result.Item2);

            return(CodeGeneratorHelper.GetPropertyReference(result.Item2));
        }
        private CodeMethodReferenceExpression CreateSetupResourceForViewElementMethod(List <ExpressionContainer> expressions, Dictionary <string, CodePropertyReferenceExpression> resourceReferences)
        {
            CodeMemberMethod method = new CodeMemberMethod
            {
                Attributes = MemberAttributes.Private,
                Name       = NameGeneratorHelper.ASSIGN_RESOURCE_TO_VIEW_METHOD_NAME,
            };

            foreach (ExpressionContainer expression in expressions)
            {
                string resourceKey = expression.Expression.GetValue(ResourceExpression.KEY);
                method.Statements.Add(SetValueStatement(CodeGeneratorHelper.GetPropertyReference(expression.TargetObject), expression.TargetField, resourceReferences[resourceKey]));
            }

            Methods.Add(method);
            return(CodeGeneratorHelper.GetMethodReference(method));
        }
        private CodeMethodReferenceExpression CreateAssignTranslationMethod(List <ExpressionContainer> expressions, CodePropertyReferenceExpression localizationServiceReference)
        {
            CodeMemberMethod method = new CodeMemberMethod
            {
                Attributes = MemberAttributes.Private,
                Name       = NameGeneratorHelper.ASSIGN_TRANSLATION_METHOD_NAME,
            };

            foreach (ExpressionContainer expression in expressions)
            {
                CodeMethodInvokeExpression valueReference = GenerateStatementToGetTranslation(localizationServiceReference, expression.Expression);
                method.Statements.Add(SetValueStatement(CodeGeneratorHelper.GetPropertyReference(expression.TargetObject), expression.TargetField, valueReference));
            }

            Methods.Add(method);
            return(CodeGeneratorHelper.GetMethodReference(method));
        }
Пример #8
0
 protected override CodePropertyReferenceExpression GetLayoutInflaterReference()
 {
     return(CodeGeneratorHelper.GetPropertyReference("LayoutInflater"));
 }
        private void CreateBindingOverrideMethod(List <ExpressionContainer> bindingExpressions, CodePropertyReferenceExpression localizationServiceReference, Dictionary <string, CodePropertyReferenceExpression> resourceReferences, params CodeMethodReferenceExpression[] preCallMethods)
        {
            CodeTypeReference listOfBindingObjectTypeReference = CodeGeneratorHelper.GetTypeReferenceFromName("List<BindingObject>");
            CodeTypeReference bindingObjectTypeReference       = CodeGeneratorHelper.GetTypeReferenceFromName("BindingObject");
            CodeTypeReference bindingExpressionTypeReference   = CodeGeneratorHelper.GetTypeReferenceFromName("BindingExpression");

            CodeMemberMethod method = new CodeMemberMethod
            {
                Attributes = MemberAttributes.Family | MemberAttributes.Override,
                Name       = NameGeneratorHelper.GET_BINDING_METHOD_NAME,
                ReturnType = listOfBindingObjectTypeReference
            };

            foreach (CodeMethodReferenceExpression preCallMethod in preCallMethods)
            {
                method.Statements.Add(new CodeMethodInvokeExpression(preCallMethod));
            }

            var variableCreationResult = CodeGeneratorHelper.CreateVariable(listOfBindingObjectTypeReference, "result");

            method.Statements.Add(variableCreationResult.Item1);
            CodeVariableReferenceExpression resultReference = variableCreationResult.Item2;

            // group binding expression by target object to simplify
            foreach (IGrouping <string, ExpressionContainer> groupedExpressions in bindingExpressions.GroupBy(x => x.TargetObject))
            {
                // create a variable for this binding object and build it with the Property of the view element
                variableCreationResult = CodeGeneratorHelper.CreateVariable(bindingObjectTypeReference, NameGeneratorHelper.GetBindingObjectName(), CodeGeneratorHelper.GetPropertyReference(groupedExpressions.Key));                //viewElementReferences[groupedExpressions.Key]);
                method.Statements.Add(variableCreationResult.Item1);

                CodeVariableReferenceExpression objectReference = variableCreationResult.Item2;
                method.Statements.Add(new CodeMethodInvokeExpression(resultReference, "Add", objectReference));


                foreach (ExpressionContainer expressionContainer in groupedExpressions)
                {
                    Expression expression = expressionContainer.Expression;
                    // create a binding expression for this
                    variableCreationResult = CodeGeneratorHelper.CreateVariable(bindingExpressionTypeReference, NameGeneratorHelper.GetBindingExpressionName(), new CodePrimitiveExpression(expressionContainer.TargetField),
                                                                                new CodePrimitiveExpression(expression.GetValue(BindingExpression.PATH)));
                    method.Statements.Add(variableCreationResult.Item1);

                    CodeVariableReferenceExpression expressionReference = variableCreationResult.Item2;

                    if (expression.Has(BindingExpression.MODE) && expression.Get <ModeExpression>(BindingExpression.MODE).Value != BindingMode.OneWay)
                    {
                        // Expression could only be of type ModeExpression
                        BindingMode mode = expression.Get <ModeExpression>(BindingExpression.MODE).Value;
                        method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(expressionReference, "Mode"),
                                                                      new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("BindingMode"), mode.ToString())));
                    }
                    if (expression.Has(BindingExpression.UPDATE_EVENT) && !string.IsNullOrWhiteSpace(expression.GetValue(BindingExpression.UPDATE_EVENT)))
                    {
                        // Expression could only be of type Text
                        string updateEvent = expression.GetValue(BindingExpression.UPDATE_EVENT);
                        method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(expressionReference, "UpdateEvent"), new CodePrimitiveExpression(updateEvent)));
                    }
                    if (expression.Has(BindingExpression.CONVERTER))
                    {
                        // Expression could be type Resource or (Binding : not implemented for now)
                        Expression converterExpression = expression[BindingExpression.CONVERTER];
                        if (converterExpression.IsOfType(ExpressionType.Binding))
                        {
                            Log.LogError("Binding expression for converter is not implemented yet");
                            throw new NotImplementedException("Binding expression for converter is not implemented yet");
                        }
                        else if (converterExpression.IsOfType(ExpressionType.Resource))
                        {
                            string resourceKey = converterExpression.GetValue(ResourceExpression.KEY);
                            CodePropertyReferenceExpression resourceReference = resourceReferences[resourceKey];

                            method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(expressionReference, "Converter"), resourceReference));
                        }
                    }
                    if (expression.Has(BindingExpression.CONVERTER_PARAMETER))
                    {
                        // Expression could be of type Resource, Translation, Text or (Binding : not implemented for now)
                        Expression converterParameterExpression = expression[BindingExpression.CONVERTER_PARAMETER];
                        if (converterParameterExpression.IsOfType(ExpressionType.Binding))
                        {
                            Log.LogError("Binding expression for converter parameter is not implemented yet");
                            throw new NotImplementedException("Binding expression for converter parameter is not implemented yet");
                        }
                        else if (converterParameterExpression.IsOfType(ExpressionType.Resource))
                        {
                            string resourceKey = converterParameterExpression.GetValue(ResourceExpression.KEY);
                            CodePropertyReferenceExpression resourceReference = resourceReferences[resourceKey];

                            method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(expressionReference, "ConverterParameter"), resourceReference));
                        }
                        else if (converterParameterExpression.IsOfType(ExpressionType.Translation))
                        {
                            CodeMethodInvokeExpression valueReference = GenerateStatementToGetTranslation(localizationServiceReference, converterParameterExpression);
                            method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(expressionReference, "ConverterParameter"), valueReference));
                        }
                        else if (converterParameterExpression.IsOfType(ExpressionType.Value))
                        {
                            TextExpression textExpression = converterParameterExpression as TextExpression;
                            if (textExpression != null)
                            {
                                string converterParameterValue = textExpression.Value;
                                method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(expressionReference, "ConverterParameter"), new CodePrimitiveExpression(converterParameterValue)));
                            }
                            else
                            {
                                throw new InvalidOperationException("Can't get a textExpression from a ExpressionType.Value expression...");
                            }
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(expressionContainer.CommandParameterTarget))
                    {
                        method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(expressionReference, "CommandParameter"),
                                                                      CodeGeneratorHelper.GetPropertyReference(expressionContainer.CommandParameterTarget)));
                    }

                    method.Statements.Add(new CodeMethodInvokeExpression(objectReference, "AddExpression", expressionReference));
                }
            }

            method.Statements.Add(new CodeMethodReturnStatement(resultReference));

            Methods.Add(method);
        }