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( ); }
public static CodeMemberMethod AddMethod(this CodeTypeDeclaration type, string methodName) => type.AddMember(Declare.Method(methodName));
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); }
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); }