Exemple #1
0
        internal static object GetNodeData(Node node, Type type)
        {
            if (node.Value == Utilities.NullIndicator)
            {
                return(null);
            }


            // Ensures that the type's static constructor has been run before we try to load it.
            // A convenient place to add base type rules is in the type's static constructor, so
            // this ensures the base type rules are registered before they are needed.
            System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);

            if (type == typeof(string) && node.Value == MultiLineStringNode.Terminator && node.ChildNodeType == NodeChildrenType.multiLineString && node.ChildLines.Count > 0)
            {
                return(MultiLineStringSpecialCaseHandler.ParseSpecialStringCase(node));
            }

            if (BaseTypesManager.IsBaseType(type))
            {
                return(RetrieveDataWithErrorChecking(() => RetrieveBaseTypeNode(node, type)));
            }

            if (CollectionTypesManager.IsSupportedType(type))
            {
                return(RetrieveDataWithErrorChecking(() => CollectionTypesManager.RetrieveCollection(node, type)));
            }

            if (!node.Value.IsNullOrEmpty())
            {
                return(RetrieveDataWithErrorChecking(() => ComplexTypeShortcuts.GetFromShortcut(node.Value, type)));
            }

            return(RetrieveDataWithErrorChecking(() => ComplexTypes.RetrieveComplexType(node, type)));


            object RetrieveDataWithErrorChecking(Func <object> retrieveDataFunction)
            {
                try
                {
                    return(retrieveDataFunction.Invoke());
                }
                catch (CannotRetrieveDataFromNodeException deeperException)
                {
                    // If there's a parsing error deeper in the tree, we want to throw *that* error, so the user gets a line
                    // number appropriate to the actual error.
                    throw deeperException;
                }
                catch
                {
                    throw new CannotRetrieveDataFromNodeException(node, type);
                }
            }
        }
        private static bool TryConstructorShortcut(string shortcut, Type type, out object result)
        {
            try {
                if (shortcut.StartsWith("(") && shortcut.EndsWith(")"))
                {
                    string text         = shortcut.Substring(1, shortcut.Length - 2); // remove the ( and )
                    var    paramStrings = text.Split(',');

                    var constructors = type.GetConstructors();

                    ConstructorInfo constructor = constructors[0];

                    if (constructors.Length > 1)
                    {
                        foreach (var c in constructors)
                        {
                            // todo: it would be nice to check constructor parameter types for compatibility with paramStrings.
                            // say a type had one constructor that took a string, and one constructor that took an int. We should be able to pick the right one.
                            if (c.GetParameters().Length == paramStrings.Length)
                            {
                                constructor = c;
                                break;
                            }
                        }
                    }

                    var parameters        = constructor.GetParameters();
                    var constructorParams = new object[parameters.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        if (i < paramStrings.Length)
                        {
                            constructorParams[i] = BaseTypesManager.ParseBaseType(paramStrings[i].Trim(), parameters[i].ParameterType);
                        }
                        else // optional parameter support
                        {
                            constructorParams[i] = parameters[i].DefaultValue;
                        }
                    }

                    result = constructor.Invoke(constructorParams);
                    return(true);
                }
            } catch { }   // I am a good programmer

            result = null;
            return(false);
        }
Exemple #3
0
        internal static void SetNodeData(Node node, object data, Type type, FileStyle style)
        {
            if (data == null)
            {
                node.ClearChildren();
                node.Value = Utilities.NullIndicator;
                return;
            }
            else if (node.Value == Utilities.NullIndicator)
            {
                node.Value = String.Empty;
            }

            // Ensure the type is initialized. This is especially important if it's added as
            // a base type in the type's static constructor.
            System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);

            // If we try to save a single-line string and find it is currently saved as a multi-line string, we do NOT remove the mutli-line formatting.
            // The reason for this is that there might be comments on the """s, and we want to preserve those comments.
            // Also, this happens in only two cases:
            //     1. A string that is usually single-line is manually switched to multi-line formatting by a user
            //     2. A string is saved as multi-line, then later saved as single-line
            // In case 1, we don't want to piss off the user; keep it how they like it.
            // In case 2, the string is probably going to be saved again later with multiple lines. It doesn't seem necessary to disrupt the structure
            // of the file for something temporary.
            string dataAsString = data as string;

            if (type == typeof(string) && (dataAsString.ContainsNewLine() || node.ChildNodes.Count > 0))
            {
                MultiLineStringSpecialCaseHandler.SetStringSpecialCase(node, dataAsString, style);
            }

            else if (BaseTypesManager.IsBaseType(type))
            {
                SetBaseTypeNode(node, data, type, style);
            }

            else if (CollectionTypesManager.IsSupportedType(type))
            {
                CollectionTypesManager.SetCollectionNode(node, data, type, style);
            }

            else
            {
                ComplexTypes.SetComplexNode(node, data, type, style);
            }
        }
Exemple #4
0
        private static object RetrieveBaseTypeNode(Node node, Type type)
        {
            // Base types are unique in that they CAN be serialized as a single line, and indeed that is how SUCC will always save them.
            // However, you CAN manually write a file that uses complex type rules for a base type, and thanks to the logic in this method,
            // it will still work.
            // See https://github.com/JimmyCushnie/SUCC/issues/26

            if (node.ChildNodeType == NodeChildrenType.key && node.ChildNodes.Count > 0)
            {
                return(ComplexTypes.RetrieveComplexType(node, type));
            }

            if (BaseTypesManager.TryParseBaseType(node.Value, type, out var result))
            {
                return(result);
            }

            return(ComplexTypeShortcuts.GetFromShortcut(node.Value, type));
        }
        private static bool TryMethodShortcut(string shortcut, Type type, out object result)
        {
            try {
                if (shortcut.Contains("(") && shortcut.Contains(")"))
                {
                    string methodname = shortcut.Substring(0, shortcut.IndexOf('('));
                    var    method     = type.GetMethod(methodname, BindingFlags.Public | BindingFlags.Static);

                    if (method != null && method.ReturnType == type)
                    {
                        var parameters = method.GetParameters();

                        string s            = shortcut.Substring(shortcut.IndexOf('(') + 1, shortcut.Length - shortcut.IndexOf('(') - 2);
                        var    paramStrings = s.Split(',');

                        var methodParams = new object[parameters.Length];
                        for (int i = 0; i < parameters.Length; i++)
                        {
                            if (i < paramStrings.Length)
                            {
                                methodParams[i] = BaseTypesManager.ParseBaseType(paramStrings[i].Trim(), parameters[i].ParameterType);
                            }
                            else // optional parameter support
                            {
                                methodParams[i] = parameters[i].DefaultValue;
                            }
                        }

                        result = method.Invoke(null, methodParams);
                        return(true);
                    }
                }
            } catch { }  // Who am I kidding. I am a bad programmer :(

            result = null;
            return(false);
        }
Exemple #6
0
 private static void SetBaseTypeNode(Node node, object data, Type type, FileStyle style)
 {
     node.ClearChildren(NodeChildrenType.none);
     node.Value = BaseTypesManager.SerializeBaseType(data, type, style);
 }