Esempio n. 1
0
        protected void GenerateCultureChangedEvent(CodeTypeDeclaration @class, out CodeExpression notifyCultureChanged)
        {
            var propertyChangedEvent = Declare.Event <PropertyChangedEventHandler> (nameof(INotifyPropertyChanged.PropertyChanged))
                                       .AddTo(@class);

            if (!settings.AccessModifiers.HasBitMask(MemberAttributes.Static))
            {
                @class.BaseTypes.Add(Code.Type <INotifyPropertyChanged> ( ));
                propertyChangedEvent.ImplementationTypes.Add(Code.Type <INotifyPropertyChanged> ( ));
            }
            else
            {
                propertyChangedEvent.Static( ).Name = "Static" + propertyChangedEvent.Name;
            }

            var propertyChanged = Code.Event(@class.Instance( ), propertyChangedEvent.Name);
            var notify          = Declare.Method(NotifyCultureChangedMethodName, settings.AccessModifiers)
                                  .Define(method =>
            {
                method.Add(Declare.Variable <PropertyChangedEventHandler> (NotifyCultureChangedVariableName)
                           .Initialize(propertyChanged));
                method.Add(Code.If(Code.Variable(NotifyCultureChangedVariableName).ValueEquals(Code.Null))
                           .Then(Code.Return( )));
                method.Add(Code.Variable(NotifyCultureChangedVariableName)
                           .InvokeDelegate(@class.Instance( ) ?? Code.Null,
                                           Code.Type <PropertyChangedEventArgs> ( )
                                           .Construct(Code.Null)));
            })
                                  .AddTo(@class);

            notifyCultureChanged = @class.Instance( )
                                   .Method(NotifyCultureChangedMethodName)
                                   .Invoke( );
        }
Esempio n. 2
0
 public static CodeMemberMethod AddMethod(this CodeTypeDeclaration type, string methodName)
 => type.AddMember(Declare.Method(methodName));
Esempio n. 3
0
        private static CodeTypeDeclaration Build(string className, MemberAttributes memberAttributes, IList <ResourceMapping> map, string extensionType, bool generateConstructors, string bindingType, CodeAttributeDeclaration bindingTypeConverter)
        {
            var type = Declare.Class(className + "Extension")
                       .Modifiers(memberAttributes);
            var keyEnum = Declare.NestedEnum(ResourceKeyEnumName)
                          .Modifiers(memberAttributes)
                          .AddSummary(ResourceKeyEnumNameSummary)
                          .AddTo(type);
            var keyEnumType = Code.Type(ResourceKeyEnumName).Local( );
            var objectType  = Code.Type <object> ( );

            type.BaseTypes.Add(Code.Type(extensionType, Code.NestedType(type.Name, ResourceKeyEnumName).Local( )));

            if (generateConstructors)
            {
                var distinctNumberOfArguments = map.Select(mapping => mapping.NumberOfArguments)
                                                .DefaultIfEmpty(0)
                                                .Distinct( )
                                                .OrderBy(numberOfArguments => numberOfArguments);

                foreach (var numberOfArguments in distinctNumberOfArguments)
                {
                    var ctor = new CodeConstructor( )
                    {
                        Attributes = memberAttributes
                    }.AddTo(type);

                    for (var argument = 0; argument < numberOfArguments; argument++)
                    {
                        var parameterName = Format(CultureInfo.InvariantCulture, FormatMethodParameterName, argument);

                        ctor.Parameters.Add(objectType.Parameter(parameterName));
                        ctor.BaseConstructorArgs.Add(Code.Variable(parameterName));
                    }
                }
            }

            var keyPathType = Code.Type(bindingType);

            var _key     = Code.This( ).Field("_key");
            var _keyPath = Code.This( ).Field("_keyPath");
            var _type    = Code.This( ).Field("_type");

            Declare.Field(keyEnumType, _key.FieldName).AddTo(type);
            Declare.Property(keyEnumType, "Key").Public( ).Override( )
            .Get(get => get.Return(_key))
            .Set((set, value) => set.Add(Code.Assign(_key, value)))
            .AddTo(type);


            Declare.Field(keyPathType, _keyPath.FieldName).AddTo(type);
            Declare.Property(keyPathType, "KeyPath").Public( ).Override( )
            .Get(get => get.Return(_keyPath))
            .Set((set, value) => set.Add(Code.Assign(_keyPath, value)))
            .Attributed(bindingTypeConverter)
            .AddTo(type);

            Declare.Field <Type> (_type.FieldName).AddTo(type);
            Declare.Property <Type> ("Type").Public( ).Override( )
            .Get(get => get.Return(_type))
            .Set((set, value) => set.Add(Code.Assign(_type, value)))
            .AddTo(type);

            Declare.Property(Code.Type <ILocalizer> ( ), "Localizer").Protected( ).Override( )
            .Get(get => get.Return(Code.Type(className).Local( ).Static( ).Property(LocalizerPropertyName)))
            .AddTo(type);

            var translation = new CodeArrayCreateExpression(Code.Type <string> ( ));
            var index       = 0;

            foreach (var mapping in map)
            {
                Declare.Field(keyEnumType, mapping.Property).Const( )
                .Modifiers(memberAttributes)
                .Initialize(Code.Constant(index++))
                .AddSummary(ResourceKeyFieldSummaryFormat, mapping.Resource.Name)
                .AddTo(keyEnum);

                translation.Initializers.Add(Code.Constant(mapping.Resource.Name));
            }

            var translator = Declare.Field <string []> (ResourceKeyTranslatorFieldName).Static( )
                             .Initialize(translation)
                             .AddTo(type);

            var translate = Declare.Method <string> ("KeyToName",
                                                     MemberAttributes.Family | MemberAttributes.Override)
                            .AddTo(type);

            var key   = Code.Variable(ResourceKeyParameterName);
            var first = keyEnumType.Static( ).Field(map [0].Property);
            var last  = keyEnumType.Static( ).Field(map [index - 1].Property);

            translate.Parameters.Add(keyEnumType.Parameter(ResourceKeyParameterName));
            translate.Statements.Add(Code.If(key.IsLessThan(first).Or(
                                                 key.IsGreaterThan(last)))
                                     .Then(Code.Throw <ArgumentOutOfRangeException> (Code.Constant(ResourceKeyParameterName))));
            translate.Statements.Return(Code.Static( )
                                        .Field(ResourceKeyTranslatorFieldName)
                                        .Indexer(Code.Variable(ResourceKeyParameterName).Cast <int> ( )));

            return(type);
        }
Esempio n. 4
0
        protected virtual CodeMemberMethod GenerateFormatMethod(ResourceMapping mapping)
        {
            var resource          = mapping.Resource;
            var numberOfArguments = mapping.NumberOfArguments;

            if (numberOfArguments <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(numberOfArguments), numberOfArguments, "Number of argument must be greater than zero");
            }

            var localizer = (CodeExpression)null;

            if (settings.LocalizerType != null)
            {
                localizer = Code.Static( ).Property(LocalizerPropertyName);
            }

            var format           = Code.Type <string> ( ).Static( ).Method(nameof(string.Format));
            var formatExpression = (CodeExpression)Code.Instance(settings.AccessModifiers).Property(mapping.Property);

            if (localizer != null)
            {
                format           = localizer.Method(nameof(ILocalizer.Format));
                formatExpression = Code.Constant(resource.Name);
            }

            var summary      = Format(FormatMethodSummary, GeneratePreview((string)resource.Value));
            var formatMethod = Declare.Method <string> (mapping.FormatMethod, settings.AccessModifiers)
                               .AddSummary(summary + FormatResourceComment(resource.Comment));

            var objectType = Code.Type <object> ( );
            var start      = localizer != null ? 3 : 2;
            var parameters = new CodeExpression [start + numberOfArguments];

            parameters [0] = Code.Instance(settings.AccessModifiers).Field(CultureInfoFieldName);
            parameters [1] = formatExpression;
            if (localizer != null)
            {
                parameters [2] = parameters [1];
                parameters [1] = parameters [0];
            }

            for (var index = 0; index < numberOfArguments; index++)
            {
                var parameterName = Format(CultureInfo.InvariantCulture, FormatMethodParameterName, index);

                formatMethod.Parameters.Add(objectType.Parameter(parameterName));

                parameters [start + index] = Code.Variable(parameterName);

                if (numberOfArguments > 1)
                {
                    formatMethod.AddParameterComment(parameterName, FormatMultiParameterComment, Ordinals [Math.Min(index, Ordinals.Length - 1)]);
                }
                else
                {
                    formatMethod.AddParameterComment(parameterName, FormatParameterComment, index);
                }
            }

            if (numberOfArguments > 3)
            {
                formatMethod.Attributed(Declare.Attribute <SuppressMessageAttribute> ("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray"));
            }

            return(formatMethod.Define(method => method.Return(format.Invoke(parameters)))
                   .AddReturnComment(FormatReturnComment));
        }
        static void GenerateTransformMethod(CodeTypeDeclaration templateType, TemplateSettings settings, ParsedTemplate pt, string templateFile, bool isOverride)
        {
            string baseDirectory = Path.GetDirectoryName(templateFile);

            var transformMeth = Declare.Method("TransformText").Returns <string> ().AsVirtual();

            if (isOverride)
            {
                transformMeth.AsOverride();
            }

            transformMeth.WithStatements(Expression.This.SetProperty("GenerationEnvironment", Expression.Null));

            CodeExpression toStringHelper = settings.IsPreprocessed
                                ? Expression.This.Property("ToStringHelper")
                                : TypeReference.Global(typeof(ToStringHelper)).AsExpression();

            //method references that will need to be used multiple times
            var  writeMeth    = Expression.This.Method("Write");
            var  toStringMeth = toStringHelper.Method("ToStringWithCulture");
            bool helperMode   = false;

            //build the code from the segments
            foreach (TemplateSegment seg in pt.Content)
            {
                CodeStatement  st       = null;
                CodeLinePragma location = null;
                if (!settings.NoLinePragmas)
                {
                    var f = seg.StartLocation.FileName ?? templateFile;
                    if (!string.IsNullOrEmpty(f))
                    {
                        // FIXME: we need to know where the output file will be to make this work properly
                        if (settings.RelativeLinePragmas)
                        {
                            f = FileUtil.AbsoluteToRelativePath(baseDirectory, f);
                        }
                        else
                        {
                            f = Path.GetFullPath(f);
                        }
                    }
                    location = new CodeLinePragma(f, seg.StartLocation.Line);
                }
                switch (seg.Type)
                {
                case SegmentType.Block:
                    if (helperMode)
                    {
                        //TODO: are blocks permitted after helpers?
                        pt.LogError("Blocks are not permitted after helpers", seg.TagStartLocation);
                    }
                    st = Statement.Snippet(seg.Text);
                    break;

                case SegmentType.Expression:
                    st = writeMeth.Invoke(toStringMeth.Invoke(Expression.Snippet(seg.Text))).AsStatement();
                    break;

                case SegmentType.Content:
                    st = writeMeth.Invoke(Expression.Primitive(seg.Text)).AsStatement();
                    break;

                case SegmentType.Helper:
                    if (!string.IsNullOrEmpty(seg.Text))
                    {
                        templateType.AddSnippetMember(seg.Text, location);
                    }
                    helperMode = true;
                    break;

                default:
                    throw new InvalidOperationException();
                }
                if (st != null)
                {
                    if (helperMode)
                    {
                        //convert the statement into a snippet member and attach it to the top level type
                        //TODO: is there a way to do this for languages that use indentation for blocks, e.g. python?
                        using (var writer = new StringWriter()) {
                            settings.Provider.GenerateCodeFromStatement(st, writer, null);
                            var text = writer.ToString();
                            if (!string.IsNullOrEmpty(text))
                            {
                                templateType.AddSnippetMember(text, location);
                            }
                        }
                    }
                    else
                    {
                        st.LinePragma = location;
                        transformMeth.Statements.Add(st);
                        continue;
                    }
                }
            }

            transformMeth.WithStatements(Statement.Return(Expression.This.Property("GenerationEnvironment").InvokeMethod("ToString")));

            templateType.AddMember(transformMeth);
        }
        static void GenerateInitializationMethod(CodeTypeDeclaration type, TemplateSettings settings, bool isOverride)
        {
            var initializeMeth = Declare.Method("Initialize").Returns(TypeReference.Void).AsVirtual();

            if (isOverride)
            {
                initializeMeth.AsOverride();
            }

            //if preprocessed, pass the extension and encoding to the host
            if (settings.IsPreprocessed && settings.HostSpecific)
            {
                var hostProp   = Expression.This.Property("Host");
                var statements = new List <CodeStatement> ();

                if (!string.IsNullOrEmpty(settings.Extension))
                {
                    statements.Add(hostProp.InvokeMethod("SetFileExtension", Expression.Primitive(settings.Extension)).AsStatement());
                }

                if (settings.Encoding != null)
                {
                    statements.Add(
                        hostProp.InvokeMethod("SetOutputEncoding",
                                              // FIXME: this should be Global but that changes codegen output
                                              TypeReference.Default(typeof(Encoding)).Method("GetEncoding")
                                              .Invoke(Expression.Primitive(settings.Encoding.CodePage), Expression.True))
                        .AsStatement());
                }

                if (statements.Count > 0)
                {
                    initializeMeth.WithStatements(
                        Statement.If(hostProp.IsNotNull(),
                                     Then: statements.ToArray())
                        );
                }
            }

            //pre-init code from processors
            foreach (var processor in settings.DirectiveProcessors.Values)
            {
                string code = processor.GetPreInitializationCodeForProcessingRun();
                if (code != null)
                {
                    initializeMeth.Statements.Add(new CodeSnippetStatement(code));
                }
            }

            if (isOverride)
            {
                initializeMeth.WithStatements(Expression.Base.InvokeMethod("Initialize"));
            }

            //post-init code from processors
            foreach (var processor in settings.DirectiveProcessors.Values)
            {
                string code = processor.GetPostInitializationCodeForProcessingRun();
                if (code != null)
                {
                    initializeMeth.Statements.Add(new CodeSnippetStatement(code));
                }
            }

            type.Members.Add(initializeMeth);
        }