public void BehaviourTest(StructureTestData testData) { using (var sr = new StringReader(testData.Ftl)) { var resource = new RuntimeParser().GetResource(sr); var entryJson = RuntimeAstToJson.ToJson(resource.Entries); entryJson.Should().BeOfType <JObject>(); var entries = (JObject)entryJson; // For some reason, this does a really shallow test -- just checks // keys in the objects rather than the contents. Probably better // to just replace the expected outputs with the whole serialized // json. foreach (var expectedKeyValue in testData.Expected) { entries.Should().ContainKey(expectedKeyValue.Key); var entry = entries[expectedKeyValue.Key]; expectedKeyValue.Value.Should().NotBeNull(); expectedKeyValue.Value.Should().BeOfType <JObject>(); var expected = (JObject)expectedKeyValue.Value; if (expected["value"].Type == JTokenType.Boolean && (bool)((JValue)expected["value"]).Value) { entry.Should().Match <JToken>( x => x.Type == JTokenType.String || x.Type == JTokenType.Object && ((JObject)x).ContainsKey("val")); } else { entry.Should().Match <JToken>( x => x.Type != JTokenType.String && !(x.Type == JTokenType.Object && ((JObject)x).ContainsKey("val"))); } if (expected.ContainsKey("attributes")) { entry.Type.Should().Be(JTokenType.Object); var entryObj = (JObject)entry; entryObj.Should().ContainKey("attrs"); var expectedKeys = ((JObject)expected["attributes"]) .Properties().Select(x => x.Name); var entryKeys = ((JObject)entryObj["attrs"]) .Properties().Select(x => x.Name); expectedKeys.Should().BeEquivalentTo(entryKeys); } else { entry.Should().Match <JToken>( x => x.Type == JTokenType.String || (x.Type == JTokenType.Object && !((JObject)x).ContainsKey("attrs"))); } } } }
static int RuntimeParse(string file, StreamReader sr, Dictionary <string, Location> messages) { var p = new RuntimeParser(); var resource = p.GetResource(sr); int errors = 0; foreach (var error in resource.Errors) { Console.WriteLine($"{file}: {error.Message}"); ++errors; } if (messages != null) { foreach (var message in resource.Entries) { errors += DuplicateCheck(message.Key, file, null, messages); } } return(errors); }
public void StructureTest(StructureTestData testData) { using (var sr = new StringReader(testData.Ftl)) { var resource = new RuntimeParser().GetResource(sr); var entryJson = RuntimeAstToJson.ToJson(resource.Entries); bool resultsEqual = JToken.DeepEquals(entryJson, testData.Expected); if (!resultsEqual) { Console.WriteLine("parsed ="); Console.WriteLine(entryJson); Console.WriteLine("expected ="); Console.WriteLine(testData.Expected); var jdp = new JsonDiffPatch(); var diff = jdp.Diff(entryJson, testData.Expected); Console.WriteLine("diff ="); Console.WriteLine(diff); } resultsEqual.Should().BeTrue(); } }
public void Run(Action <string> emitError, Action <string> emitWarning, ModData modData) { var language = "en"; var translation = new Translation(language, modData.Manifest.Translations, modData.DefaultFileSystem); foreach (var modType in modData.ObjectCreator.GetTypes()) { foreach (var fieldInfo in modType.GetFields(Binding).Where(m => m.HasAttribute <TranslationReferenceAttribute>())) { if (fieldInfo.FieldType != typeof(string)) { emitError($"Translation attribute on non string field {fieldInfo.Name}."); } var key = (string)fieldInfo.GetValue(string.Empty); if (!translation.HasAttribute(key)) { emitError($"{key} not present in {language} translation."); } var translationReference = fieldInfo.GetCustomAttributes <TranslationReferenceAttribute>(true)[0]; if (translationReference.RequiredVariableNames != null && translationReference.RequiredVariableNames.Length > 0) { referencedVariablesPerKey.GetOrAdd(key, translationReference.RequiredVariableNames); } referencedKeys.Add(key); } } foreach (var file in modData.Manifest.Translations) { var stream = modData.DefaultFileSystem.Open(file); using (var reader = new StreamReader(stream)) { var runtimeParser = new RuntimeParser(); var result = runtimeParser.GetResource(reader); foreach (var entry in result.Entries) { if (!referencedKeys.Contains(entry.Key)) { emitWarning($"Unused key `{entry.Key}` in {file}."); } var message = entry.Value; var node = message.Value; variableReferences.Clear(); if (node is Pattern pattern) { foreach (var element in pattern.Elements) { if (element is SelectExpression selectExpression) { foreach (var variant in selectExpression.Variants) { if (variant.Value is Pattern variantPattern) { foreach (var variantElement in variantPattern.Elements) { CheckVariableReference(variantElement, entry, emitWarning, file); } } } } CheckVariableReference(element, entry, emitWarning, file); } if (referencedVariablesPerKey.ContainsKey(entry.Key)) { var referencedVariables = referencedVariablesPerKey[entry.Key]; foreach (var referencedVariable in referencedVariables) { if (!variableReferences.Contains(referencedVariable)) { emitError($"Missing variable `{referencedVariable}` for key `{entry.Key}` in {file}."); } } } } } } } }