Exemple #1
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     Lingo.PostBuildStep <Translation>(rep, Assembly.GetExecutingAssembly());
     Classify.PostBuildStep <Settings>(rep);
     Classify.PostBuildStep <Style>(rep);
     Classify.PostBuildStep <GameVersionConfig>(rep);
 }
Exemple #2
0
        /// <summary>
        ///     Performs safety checks to ensure that a settings object conforms to various requirements imposed by
        ///     SettingsUtil methods. Run this method as a post-build step to ensure reliability of execution. For an example
        ///     of use, see <see cref="PostBuildChecker.RunPostBuildChecks"/>. This method is available only in DEBUG mode.</summary>
        /// <typeparam name="TSettings">
        ///     The type of the settings object, derived from <see cref="SettingsBase"/>, which would be passed to
        ///     SettingsUtil methods at normal run-time.</typeparam>
        /// <param name="rep">
        ///     Object to report post-build errors to.</param>
        public static void PostBuildStep <TSettings>(IPostBuildReporter rep) where TSettings : SettingsBase
        {
            SettingsAttribute attr;

            try
            {
                attr = GetAttribute(typeof(TSettings));
            }
            catch (Exception e)
            {
                rep.Error(e.Message, "class", typeof(TSettings).Name);
                return;
            }

            switch (attr.Serializer)
            {
            case SettingsSerializer.DotNetBinary:
                break;

            case SettingsSerializer.ClassifyXml:
            case SettingsSerializer.ClassifyJson:
            case SettingsSerializer.ClassifyBinary:
                Classify.PostBuildStep <TSettings>(rep);
                break;
            }
        }
Exemple #3
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     foreach (var pair in _keyBindingsRaw.UniquePairs())
     {
         if (pair.Item1.Mode == pair.Item2.Mode && pair.Item1.Key == pair.Item2.Key && pair.Item1.Modifiers == pair.Item2.Modifiers)
         {
             var tok = "EditMode.{0}, {1}, ConsoleKey.{2}".Fmt(pair.Item1.Mode, pair.Item1.Modifiers == 0 ? "0" : "ConsoleModifiers." + pair.Item1.Modifiers, pair.Item1.Key);
             rep.Error(@"There are two key bindings for {0} in mode {1}.".Fmt(
                           pair.Item1.Modifiers == 0 ? pair.Item1.Key.ToString() : pair.Item1.Modifiers + "+" + pair.Item1.Key,
                           pair.Item1.Mode
                           ), "_keyBindingsRaw", tok);
             rep.Error(@"    -- Second use is here.", "_keyBindingsRaw", tok, tok);
         }
     }
 }
Exemple #4
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     try { initInstructionsDictionary(); }
     catch (DuplicateCharacterException e)
     {
         rep.Error(e.Message, "enum instruction", e.Character.ToString());
         return;
     }
     foreach (var instrKvp in _instructionTypes)
     {
         if (instrKvp.Value == NodeType.BlockHead)
         {
             try { BlockNode.Create(instrKvp.Key, _instructions[instrKvp.Key], 0, 0, null, null, false); }
             catch { rep.Error(@"Block instruction ""{0}"" is not processed.".Fmt(instrKvp), "blockNode createBlockNode", "default"); }
         }
         else if (instrKvp.Value == NodeType.FunctionExecutionNode)
         {
             try { ExecuteFunction.Create(_instructions[instrKvp.Key], 0, 0); }
             catch { rep.Error(@"Function execution instruction ""{0}"" is not processed.".Fmt(instrKvp), "executeFunction createFunctionExecutionNode", "default"); }
         }
     }
 }
Exemple #5
0
        /// <summary>Checks that the enum values declared in the specified enum type and the TrString fields declared in the specified translation type match exactly.</summary>
        private static void checkEnumTranslation(IPostBuildReporter rep, Type enumType, Type translationType)
        {
            var set = translationType.GetAllFields().Where(f => f.FieldType == typeof(TrString)).Select(f => f.Name).ToHashSet();

            foreach (var enumValue in Enum.GetValues(enumType))
            {
                if (!set.Contains(enumValue.ToString()))
                {
                    rep.Error(@"The translation type ""{0}"" does not contain a field of type {1} with the name ""{2}"" declared in enum type ""{3}"".".Fmt(translationType.FullName, typeof(TrString).Name, enumValue, enumType.FullName), "class " + translationType.Name);
                    rep.Error(@"---- Enum type is here.", "enum " + enumType.Name);
                }
            }
            foreach (var value in set)
            {
                try { Enum.Parse(enumType, value, ignoreCase: false); }
                catch (ArgumentException)
                {
                    rep.Error(@"The enum type ""{0}"" does not contain a value with the name ""{1}"" declared in translation type ""{2}"".".Fmt(enumType.FullName, value, translationType.FullName), "enum " + enumType.Name);
                    rep.Error(@"---- Translation type is here.", "class " + translationType.Name);
                }
            }
        }
Exemple #6
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     SettingsUtil.PostBuildStep<Settings>(rep);
 }
Exemple #7
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     try { initInstructionsDictionary(); }
     catch (DuplicateCharacterException e)
     {
         rep.Error(e.Message, "enum instruction", e.Character.ToString());
         return;
     }
     foreach (var instrKvp in _instructionTypes)
     {
         if (instrKvp.Value == NodeType.BlockHead)
         {
             try { BlockNode.Create(instrKvp.Key, _instructions[instrKvp.Key], 0, 0, null, null, false); }
             catch { rep.Error(@"Block instruction ""{0}"" is not processed.".Fmt(instrKvp), "blockNode createBlockNode", "default"); }
         }
         else if (instrKvp.Value == NodeType.FunctionExecutionNode)
         {
             try { ExecuteFunction.Create(_instructions[instrKvp.Key], 0, 0); }
             catch { rep.Error(@"Function execution instruction ""{0}"" is not processed.".Fmt(instrKvp), "executeFunction createFunctionExecutionNode", "default"); }
         }
     }
 }
Exemple #8
0
 public static void PostBuildCheck(IPostBuildReporter rep)
 {
     CommandLineParser.PostBuildStep <CommandLineBase>(rep, null);
 }
Exemple #9
0
        /// <summary>Checks the specified assemblies for any obvious Lingo-related problems, including unused strings, mismatched enum translations.</summary>
        /// <typeparam name="TTranslation">The type of the translation class.</typeparam>
        /// <param name="rep">Post-build step reporter.</param>
        /// <param name="assemblies">A list of assemblies to check. The Lingo assembly is included automatically to ensure correct operation.</param>
        public static void PostBuildStep <TTranslation>(IPostBuildReporter rep, params Assembly[] assemblies)
        {
            if (!assemblies.Contains(Assembly.GetExecutingAssembly()))
            {
                assemblies = assemblies.Concat(Assembly.GetExecutingAssembly()).ToArray();
            }

            // Check that all enum translations are sensible
            var allEnumTrs = allEnumTranslations(assemblies).ToList();

            foreach (var tr in allEnumTrs)
            {
                checkEnumTranslation(rep, tr.EnumType, tr.TranslationType);
            }

            // Check all component model member translations
            foreach (var type in assemblies.SelectMany(a => a.GetTypes()))
            {
                // All functions returning MemberTr and accepting a TranslationBase descendant must conform
                var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(p => p.Name).ToHashSet();
                foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
                {
                    if (method.ReturnType == typeof(MemberTr) && method.GetParameters().Length == 1 && typeof(TranslationBase).IsAssignableFrom(method.GetParameters()[0].ParameterType))
                    {
                        if (!method.IsStatic)
                        {
                            rep.Error("A member translation method must be static. Translation method: {0}".Fmt(method.DeclaringType.FullName + "." + method.Name), "class " + method.DeclaringType.Name, typeof(MemberTr).Name + " " + method.Name);
                        }
                        if (!method.Name.EndsWith("Tr"))
                        {
                            rep.Error("The name of a member translation method must end with the letters \"Tr\". Translation method: {0}".Fmt(method.DeclaringType.FullName + "." + method.Name), "class " + method.DeclaringType.Name, typeof(MemberTr).Name + " " + method.Name);
                        }
                        var propertyName = method.Name.Substring(0, method.Name.Length - 2);
                        if (!properties.Contains(propertyName))
                        {
                            rep.Error("Member translation method has no corresponding property named \"{1}\". Translation method: {0}".Fmt(method.DeclaringType.FullName + "." + method.Name, propertyName), "class " + method.DeclaringType.Name, typeof(MemberTr).Name + " " + method.Name);
                        }
                    }
                }
            }

            // Find unused strings
            var fields = new HashSet <FieldInfo>();

            addAllLingoRelevantFields(typeof(TTranslation), fields);

            // Treat all fields used for enum translations as used
            foreach (var f in allEnumTrs.SelectMany(et => et.TranslationType.GetAllFields()))
            {
                fields.Remove(f);
            }

            // Treat all fields that occur in a ldfld / ldflda instruction as used
            foreach (var mod in assemblies.SelectMany(a => a.GetModules(false)))
            {
                foreach (var typ in mod.GetTypes())
                {
                    foreach (var meth in
                             typ.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).Where(m => m.DeclaringType == typ).Cast <MethodBase>().Concat(
                                 typ.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).Where(c => c.DeclaringType == typ).Cast <MethodBase>()))
                    {
                        foreach (var instr in ILReader.ReadIL(meth, typ))
                        {
                            if (instr.OpCode == OpCodes.Ldfld || instr.OpCode == OpCodes.Ldflda)
                            {
                                fields.Remove((FieldInfo)instr.Operand);
                                if (fields.Count == 0)
                                {
                                    goto done; // don't have to break the loop early, but there's really no point in searching the rest of the code now
                                }
                            }
                        }
                    }
                }
            }

            // Report warnings for all unused strings (not errors so that the developer can test things in the presence of unused strings)
done:
            foreach (var field in fields)
            {
                rep.Warning("Unused Lingo field: " + field.DeclaringType.FullName + "." + field.Name, "class " + field.DeclaringType.Name, field.FieldType.Name, field.Name);
            }
        }
Exemple #10
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     CommandLineParser.PostBuildStep <CmdLine>(rep, null);
 }
Exemple #11
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     SettingsUtil.PostBuildStep <Settings>(rep);
 }
Exemple #12
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     Classify.PostBuildStep(typeof(Settings), rep);
     Classify.PostBuildStep(typeof(Cloud), rep);
 }
Exemple #13
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
 }
Exemple #14
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     if (Characters.Length != Engrish.Length)
         rep.Error("listStringElementNode: Number of characters ({0}) does not equal number of Engrish terms ({1}).".Fmt(Characters.Length, Engrish.Length), "class listStringElementNode", "Characters");
     var numInstr = EnumStrong.GetValues<ListStringInstruction>().Length;
     if (Characters.Length != 20 * numInstr)
         rep.Error("listStringElementNode: Number of characters ({0}) does not equal 20 times the number of list/string instructions ({1}).".Fmt(Characters.Length, numInstr), "class listStringElementNode", "Engrish");
 }
Exemple #15
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     foreach (var field in typeof(Instruction).GetFields(BindingFlags.Public | BindingFlags.Static))
     {
         var attr = field.GetCustomAttributes<InstructionAttribute>().First();
         var instr = (Instruction) field.GetValue(null);
         if (attr.Type == NodeType.SingularNode && !field.IsDefined<SingularListStringInstructionAttribute>())
         {
             try { getMethod(instr); }
             catch { rep.Error(@"Instruction ""{0}"" has no method.".Fmt(instr), "singularNode", "getMethod", "default"); }
         }
     }
 }
Exemple #16
0
 private static void PostBuildCheck(IPostBuildReporter rep)
 {
     Classify.PostBuildStep <Settings>(rep);
 }