Beispiel #1
0
        private BaseNode CreateNodeFromElement(XElement element, BaseNode parent, ILogger logger)
        {
            Contract.Requires(element != null);
            Contract.Requires(logger != null);

            BaseNode CreateNode()
            {
                var converter = CustomNodeSerializer.GetReadConverter(element);

                if (converter != null)
                {
                    return(converter.CreateNodeFromElement(element, parent, project.Classes, logger, CreateNodeFromElement));
                }

                if (!buildInStringToTypeMap.TryGetValue(element.Attribute(XmlTypeAttribute)?.Value ?? string.Empty, out var nodeType))
                {
                    logger.Log(LogLevel.Error, $"Skipping node with unknown type: {element.Attribute(XmlTypeAttribute)?.Value}");
                    logger.Log(LogLevel.Warning, element.ToString());

                    return(null);
                }

                return(BaseNode.CreateInstanceFromType(nodeType, false));
            }

            var node = CreateNode();

            if (node == null)
            {
                logger.Log(LogLevel.Error, "Could not create node.");

                return(null);
            }

            node.ParentNode = parent;

            node.Name     = element.Attribute(XmlNameAttribute)?.Value ?? string.Empty;
            node.Comment  = element.Attribute(XmlCommentAttribute)?.Value ?? string.Empty;
            node.IsHidden = bool.TryParse(element.Attribute(XmlHiddenAttribute)?.Value, out var val) && val;

            if (node is BaseWrapperNode wrapperNode)
            {
                ClassNode GetClassNodeFromElementReference()
                {
                    var reference = NodeUuid.FromBase64String(element.Attribute(XmlReferenceAttribute)?.Value, false);

                    if (!project.ContainsClass(reference))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with unknown reference: {reference}");
                        logger.Log(LogLevel.Warning, element.ToString());

                        return(null);
                    }

                    return(project.GetClassByUuid(reference));
                }

                // Legacy Support
                if (node is ClassPointerNode || node is ClassInstanceArrayNode || node is ClassPointerArrayNode)
                {
                    var innerClass = GetClassNodeFromElementReference();
                    if (innerClass == null)
                    {
                        return(null);
                    }

                    switch (node)
                    {
                    case BaseClassArrayNode classArrayNode:
                        node = classArrayNode.GetEquivalentNode(0, innerClass);
                        break;

                    case ClassPointerNode classPointerNode:
                        node = classPointerNode.GetEquivalentNode(innerClass);
                        break;
                    }
                }
                else
                {
                    BaseNode innerNode = null;

                    if (node is BaseClassWrapperNode)
                    {
                        innerNode = GetClassNodeFromElementReference();
                        if (innerNode == null)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        var innerElement = element.Elements().FirstOrDefault();
                        if (innerElement != null)
                        {
                            innerNode = CreateNodeFromElement(innerElement, node, logger);
                        }
                    }

                    if (wrapperNode.CanChangeInnerNodeTo(innerNode))
                    {
                        var rootWrapperNode = node.GetRootWrapperNode();
                        if (rootWrapperNode.ShouldPerformCycleCheckForInnerNode() &&
                            innerNode is ClassNode classNode &&
                            ClassUtil.IsCyclicIfClassIsAccessibleFromParent(node.GetParentClass(), classNode, project.Classes))
                        {
                            logger.Log(LogLevel.Error, $"Skipping node with cyclic class reference: {node.GetParentClass().Name}->{rootWrapperNode.Name}");

                            return(null);
                        }

                        wrapperNode.ChangeInnerNode(innerNode);
                    }
                    else
                    {
                        logger.Log(LogLevel.Error, $"The node {innerNode} is not a valid child for {node}.");
                    }
                }
            }

            switch (node)
            {
            case VirtualMethodTableNode vtableNode:
            {
                var nodes = element
                            .Elements(XmlMethodElement)
                            .Select(e => new VirtualMethodNode
                    {
                        Name     = e.Attribute(XmlNameAttribute)?.Value ?? string.Empty,
                        Comment  = e.Attribute(XmlCommentAttribute)?.Value ?? string.Empty,
                        IsHidden = e.Attribute(XmlHiddenAttribute)?.Value.Equals("True") ?? false
                    });

                foreach (var vmethodNode in nodes)
                {
                    vtableNode.AddNode(vmethodNode);
                }
                break;
            }

            case BaseWrapperArrayNode arrayNode:
            {
                TryGetAttributeValue(element, XmlCountAttribute, out var count, logger);
                arrayNode.Count = count;
                break;
            }

            case BaseTextNode textNode:
            {
                TryGetAttributeValue(element, XmlLengthAttribute, out var length, logger);
                textNode.Length = length;
                break;
            }

            case BitFieldNode bitFieldNode:
            {
                TryGetAttributeValue(element, XmlBitsAttribute, out var bits, logger);
                bitFieldNode.Bits = bits;
                break;
            }

            case FunctionNode functionNode:
            {
                functionNode.Signature = element.Attribute(XmlSignatureAttribute)?.Value ?? string.Empty;

                var reference = NodeUuid.FromBase64String(element.Attribute(XmlReferenceAttribute)?.Value, false);
                if (project.ContainsClass(reference))
                {
                    functionNode.BelongsToClass = project.GetClassByUuid(reference);
                }
                break;
            }
            }

            return(node);
        }
Beispiel #2
0
        private static XElement CreateElementFromNode(BaseNode node, ILogger logger)
        {
            Contract.Requires(node != null);
            Contract.Requires(logger != null);

            XElement CreateElement()
            {
                var converter = CustomNodeSerializer.GetWriteConverter(node);

                if (converter != null)
                {
                    return(converter.CreateElementFromNode(node, logger, CreateElementFromNode));
                }

                if (!buildInTypeToStringMap.TryGetValue(node.GetType(), out var typeString))
                {
                    logger.Log(LogLevel.Error, $"Skipping node with unknown type: {node.Name}");
                    logger.Log(LogLevel.Warning, node.GetType().ToString());

                    return(null);
                }

                return(new XElement(
                           XmlNodeElement,
                           new XAttribute(XmlTypeAttribute, typeString)
                           ));
            }

            var element = CreateElement();

            if (element == null)
            {
                logger.Log(LogLevel.Error, "Could not create element.");

                return(null);
            }

            element.SetAttributeValue(XmlNameAttribute, node.Name ?? string.Empty);
            element.SetAttributeValue(XmlCommentAttribute, node.Comment ?? string.Empty);
            element.SetAttributeValue(XmlHiddenAttribute, node.IsHidden);

            if (node is BaseWrapperNode wrapperNode)
            {
                if (node is BaseClassWrapperNode classWrapperNode)
                {
                    element.SetAttributeValue(XmlReferenceAttribute, ((ClassNode)classWrapperNode.InnerNode).Uuid);
                }
                else if (wrapperNode.InnerNode != null)
                {
                    element.Add(CreateElementFromNode(wrapperNode.InnerNode, logger));
                }
            }

            switch (node)
            {
            case VirtualMethodTableNode vtableNode:
            {
                element.Add(vtableNode.Nodes.Select(n => new XElement(
                                                        XmlMethodElement,
                                                        new XAttribute(XmlNameAttribute, n.Name ?? string.Empty),
                                                        new XAttribute(XmlCommentAttribute, n.Comment ?? string.Empty),
                                                        new XAttribute(XmlHiddenAttribute, n.IsHidden)
                                                        )));
                break;
            }

            case UnionNode unionNode:
            {
                element.Add(unionNode.Nodes.Select(n => CreateElementFromNode(n, logger)));
                break;
            }

            case BaseWrapperArrayNode arrayNode:
            {
                element.SetAttributeValue(XmlCountAttribute, arrayNode.Count);
                break;
            }

            case BaseTextNode textNode:
            {
                element.SetAttributeValue(XmlLengthAttribute, textNode.Length);
                break;
            }

            case BitFieldNode bitFieldNode:
            {
                element.SetAttributeValue(XmlBitsAttribute, bitFieldNode.Bits);
                break;
            }

            case FunctionNode functionNode:
            {
                var uuid = functionNode.BelongsToClass?.Uuid ?? Guid.Empty;
                element.SetAttributeValue(XmlReferenceAttribute, uuid);
                element.SetAttributeValue(XmlSignatureAttribute, functionNode.Signature);
                break;
            }

            case EnumNode enumNode:
            {
                element.SetAttributeValue(XmlReferenceAttribute, enumNode.Enum.Name);
                break;
            }
            }

            return(element);
        }