Skip to content

Commit 6b91cd6

Browse files
author
Sébastien Geiser
committed
More option for fody + More tests
1 parent db92cb2 commit 6b91cd6

File tree

15 files changed

+139
-10
lines changed

15 files changed

+139
-10
lines changed

CodingSeb.Localization.AssemblyToProcess/LocalizedWithFodyClass.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@ public class LocalizedWithFodyClass : NotifyPropertyChangedBase
77
{
88
[Localize]
99
public string TestProperty => Loc.Tr("TestLabel");
10+
11+
[Localize(nameof(TextIdInAttribute))]
12+
public string TextIdInAttribute { get; set; }
1013
}
1114
}

CodingSeb.Localization.Examples/CodingSeb.Localization.Examples.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
</ItemGroup>
1212

1313
<ItemGroup>
14+
<ProjectReference Include="..\CodingSeb.Localization.FodyAddin\CodingSeb.Localization.FodyAddin.csproj" />
15+
<WeaverFiles Include="$(SolutionDir)\CodingSeb.Localization.FodyAddin.Fody\bin\$(Configuration)\netstandard2.0\CodingSebLocalization.Fody.dll" />
1416
<ProjectReference Include="..\CodingSeb.Localization.JsonFileLoader\CodingSeb.Localization.JsonFileLoader.csproj" />
1517
<ProjectReference Include="..\CodingSeb.Localization.WPF\CodingSeb.Localization.WPF.csproj" />
1618
</ItemGroup>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
22
<PropertyChanged />
3+
<CodingSebLocalization/>
34
</Weavers>

CodingSeb.Localization.Examples/FodyWeavers.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
</xs:attribute>
3434
</xs:complexType>
3535
</xs:element>
36+
<xs:element name="CodingSebLocalization" minOccurs="0" maxOccurs="1" type="xs:anyType" />
3637
</xs:all>
3738
<xs:attribute name="VerifyAssembly" type="xs:boolean">
3839
<xs:annotation>

CodingSeb.Localization.Examples/MainWindow.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
</DataTemplate>
9292
</ListBox.ItemTemplate>
9393
</ListBox>
94+
<TextBlock Text="{Binding AutoTranslation}" />
9495
</StackPanel>
9596
</DockPanel>
9697
</Window>

CodingSeb.Localization.Examples/ViewModel/MainViewModel.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ public List<string> Labels
3737
}
3838
}
3939

40-
public string AutoTranslation => Loc.Tr("ANiceText");
40+
[Localize("ANiceText")]
41+
public string AutoTranslation { get; set; }
4142

4243
public string Label { get; set; }
4344

CodingSeb.Localization.FodyAddin.Fody/CodingSeb.Localization.FodyAddin.Fody.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<Project Sdk="Microsoft.NET.Sdk">
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
5+
<AssemblyName>CodingSebLocalization.Fody</AssemblyName>
56
</PropertyGroup>
67
<ItemGroup>
78
<PackageReference Include="FodyHelpers" Version="6.3.0" />

CodingSeb.Localization.FodyAddin.Fody/ModuleWeaver.cs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ private void AddCurrentLanguageChangedSensitivity(TypeDefinition typeDefinition)
7373
{
7474
IEnumerable<PropertyDefinition> propertyToLocalize = typeDefinition.Properties.Where(property => property.HasLocalizeAttribute());
7575

76+
propertyToLocalize.ToList().ForEach(EventuallyInjectPropertyCode);
77+
7678
var propertyListFieldDefinition = AddLocalizedPropertyNamesStaticList(typeDefinition, propertyToLocalize.Select(p => p.Name));
7779
var triggerPropertyChangedMethod = typeDefinition.FindPropertyChangedTriggerMethod();
7880
var currentLanguageChangedMethod = AddCurrentLanguageChangedMethod(typeDefinition, propertyListFieldDefinition, triggerPropertyChangedMethod);
@@ -81,15 +83,46 @@ private void AddCurrentLanguageChangedSensitivity(TypeDefinition typeDefinition)
8183
UnSubscribeFromLanguageChangedInDestructors(GetOrCreateFinalizer(typeDefinition), currentLanguageChangedMethod);
8284
}
8385

86+
private void EventuallyInjectPropertyCode(PropertyDefinition property)
87+
{
88+
var attribute = property.CustomAttributes.FirstOrDefault(a => a.AttributeType.Name.Equals("LocalizeAttribute"));
89+
90+
if (attribute.ConstructorArguments.Count > 0)
91+
{
92+
var textId = attribute.ConstructorArguments[0].Value.ToString();
93+
94+
var instructions = property.GetMethod.Body.Instructions;
95+
96+
instructions.Clear();
97+
98+
instructions.Add(Instruction.Create(OpCodes.Ldstr, textId));
99+
100+
if (attribute.Properties.FirstOrDefault(p => p.Name.Equals("DefaultValue")) is CustomAttributeNamedArgument defaultValueProperty
101+
&& defaultValueProperty.Argument.Value != null)
102+
{
103+
instructions.Add(Instruction.Create(OpCodes.Ldstr, defaultValueProperty.Argument.Value.ToString()));
104+
}
105+
else
106+
{
107+
instructions.Add(Instruction.Create(OpCodes.Ldnull));
108+
}
109+
110+
instructions.Add(Instruction.Create(OpCodes.Ldnull));
111+
instructions.Add(Instruction.Create(OpCodes.Call, ModuleDefinition.ImportReference(typeof(Loc).GetMethod("Tr", new Type[] { typeof(string), typeof(string), typeof(string) }))));
112+
instructions.Add(Instruction.Create(OpCodes.Ret));
113+
}
114+
}
115+
84116
private void SubscribeToLanguageChangedInConstructors(TypeDefinition typeDefinition, MethodDefinition currentLanguageChangedMethod)
85117
{
86118
List<MethodDefinition> exclusiveAlwaysCalledConstructors = typeDefinition.GetConstructors().Where(constructor =>
87119
{
88120
return !constructor.IsStatic &&
89121
constructor.Body.Instructions.Count > 2 &&
90-
constructor.Body.Instructions[1].OpCode == OpCodes.Call &&
91-
constructor.Body.Instructions[1].Operand is MethodReference methodReference &&
92-
methodReference.DeclaringType != typeDefinition;
122+
!constructor.Body.Instructions.Any(i => i.OpCode == OpCodes.Call
123+
&& i.Operand is MethodReference methodReference
124+
&& methodReference.Resolve().IsConstructor
125+
&& methodReference.DeclaringType == typeDefinition);
93126
}).ToList();
94127

95128
exclusiveAlwaysCalledConstructors.ForEach(constructor =>

CodingSeb.Localization.FodyAddin.Tests/WeaverTests.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public void ValidateThatPropertyWithLocalizeAttributeIsUpdateWhenLanguageChanged
2929
Assert.NotNull(propertyNamesField);
3030
Assert.NotNull(languageChangedMethod);
3131

32-
var instance = (dynamic)Activator.CreateInstance(type);
32+
var instance = (dynamic)Activator.CreateInstance(type, true);
3333

3434
List<string> listOfPropertyNames = propertyNamesField.GetValue(instance) as List<string>;
3535

@@ -38,23 +38,28 @@ public void ValidateThatPropertyWithLocalizeAttributeIsUpdateWhenLanguageChanged
3838

3939
INotifyPropertyChanged notifyPropertyChanged = instance as INotifyPropertyChanged;
4040

41-
string propertyName = string.Empty;
41+
List<string> propertyNames = new List<string>();
4242

4343
void NotifyPropertyChanged_PropertyChanged(object sender, PropertyChangedEventArgs e)
4444
{
45-
propertyName = e.PropertyName;
45+
propertyNames.Add(e.PropertyName);
4646
}
4747

4848
notifyPropertyChanged.PropertyChanged += NotifyPropertyChanged_PropertyChanged;
4949

5050
languageChangedMethod.Invoke(instance, new object[] { Loc.Instance, new CurrentLanguageChangedEventArgs("en", "fr") });
51-
Assert.Equal("TestProperty", propertyName);
5251

53-
propertyName = string.Empty;
52+
Assert.Contains("TestProperty", propertyNames);
53+
Assert.Contains("TextIdInAttribute", propertyNames);
54+
55+
propertyNames.Clear();
56+
57+
Assert.Empty(propertyNames);
5458

5559
Loc.Instance.CurrentLanguage = "es";
5660

57-
Assert.Equal("TestProperty", propertyName);
61+
Assert.Contains("TestProperty", propertyNames);
62+
Assert.Contains("TextIdInAttribute", propertyNames);
5863

5964
notifyPropertyChanged.PropertyChanged -= NotifyPropertyChanged_PropertyChanged;
6065
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// This file is used by Code Analysis to maintain SuppressMessage
2+
// attributes that are applied to this project.
3+
// Project-level suppressions either have no target or are given
4+
// a specific target and scoped to a namespace, type, member, etc.
5+
6+
using System.Diagnostics.CodeAnalysis;
7+
8+
[assembly: SuppressMessage("Redundancy", "RCS1163:Unused parameter.", Justification = "<Pending>", Scope = "member", Target = "~M:CodingSeb.Localization.LocalizeAttribute.#ctor(System.String)")]

0 commit comments

Comments
 (0)