Exemple #1
0
        // Throws InvalidOperationException at DesignTime: Input XAML contains invalid constructs for generating a class. For example, unexpected content or unknown class or field modifiers.
        public ClassData ReadFromXaml(XamlNodeList nodes)
        {
            if (nodes == null)
            {
                throw FxTrace.Exception.ArgumentNull("nodeList");
            }

            Stack <NamedObject> currentTypes            = new Stack <NamedObject>();
            XamlReader          reader                  = nodes.GetReader();
            XamlSchemaContext   xsc                     = reader.SchemaContext;
            XamlNodeList        strippedXamlNodes       = new XamlNodeList(xsc);
            XamlWriter          strippedXamlNodesWriter = strippedXamlNodes.Writer;

            ClassData result = new ClassData()
            {
                FileName      = this.xamlFileName,
                IsPublic      = this.DefaultClassIsPublic,
                RootNamespace = this.rootNamespace
            };

            // We loop through the provided XAML; for each node, we do two things:
            //  1. If it's a directive that's relevant to x:Class, we extract the data.
            //  2. Unless it's a directive that's exclusively relevant to x:Class, we write it to strippedXamlNodes.
            // The result is two outputs: class data, and stripped XAML that can be used to initialize the
            // an instance of the class.

            bool readNextNode = false;

            while (readNextNode || reader.Read())
            {
                bool stripNodeFromXaml = false;
                readNextNode = false;

                namespaceTable.ManageNamespace(reader);

                switch (reader.NodeType)
                {
                case XamlNodeType.StartObject:
                    if (result.BaseType == null)
                    {
                        result.BaseType = reader.Type;
                    }
                    currentTypes.Push(new NamedObject()
                    {
                        Type       = reader.Type,
                        Visibility = DefaultFieldVisibility,
                    });
                    break;

                case XamlNodeType.EndObject:
                    currentTypes.Pop();
                    break;

                case XamlNodeType.StartMember:
                    XamlMember member = reader.Member;

                    if (member.IsDirective)
                    {
                        bool isRootElement = (currentTypes.Count == 1);
                        stripNodeFromXaml = ProcessDirective(reader, result, currentTypes.Peek(), isRootElement, strippedXamlNodes, out readNextNode);
                    }
                    else
                    {
                        NamedObject currentType     = currentTypes.Peek();
                        XamlType    currentXamlType = currentType.Type;
                        if (currentXamlType.IsUnknown)
                        {
                            result.RequiresCompilationPass2 = true;
                        }
                    }
                    break;

                case XamlNodeType.EndMember:
                    break;

                case XamlNodeType.Value:
                    break;

                case XamlNodeType.NamespaceDeclaration:
                    break;

                case XamlNodeType.None:
                    break;

                case XamlNodeType.GetObject:
                    //Push a dummy NamedObject so that it gets popped when you see the corresponding EndObject
                    currentTypes.Push(new NamedObject());
                    break;

                default:

                    Debug.Fail("Unrecognized XamlNodeType value" + reader.NodeType.ToString());
                    break;
                }

                if (!stripNodeFromXaml)
                {
                    WritestrippedXamlNode(reader, strippedXamlNodesWriter);
                }
            }

            // ClassData.Name should be initialized to a non-null non-empty value if
            // the file contains x:Class. Throw an error if neither is found.
            if (result.Name == null)
            {
                string xClassDirectiveName = "{" + XamlLanguage.Class.PreferredXamlNamespace + "}" + XamlLanguage.Class.Name;

                throw FxTrace.Exception.AsError(LogInvalidOperationException(null, SR.TaskCannotProcessFileWithoutType(xClassDirectiveName)));
            }

            strippedXamlNodes.Writer.Close();
            strippedXamlNodes = RewriteRootNode(strippedXamlNodes, result.Name, result.Namespace);

            result.EmbeddedResourceXaml = strippedXamlNodes;
            return(result);
        }
        private CodeMemberField GenerateField(NamedObject fieldData, ClassData classData)
        {
            CodeTypeReference fieldCodeType = null;

            if (!GetCodeTypeReferenceFromXamlType(fieldData.Type, classData, out fieldCodeType))
            {
                throw FxTrace.Exception.AsError(
                    new InvalidOperationException(SR.TaskCannotResolveFieldType(XamlBuildTaskServices.GetFullTypeName(fieldData.Type), fieldData.Name)),
                    classData.FileName);
            }

            if (!this.codeDomProvider.IsValidIdentifier(fieldData.Name))
            {
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.InvalidIdentifiers(fieldData.Name)),
                    classData.FileName);
            }

            //     <%= fieldData.Visibility %> WithEvents <%= fieldData.Type %> <%= fieldData.Name %>;
            //
            CodeMemberField field = new CodeMemberField()
                {
                    Name = fieldData.Name,
                    Type = fieldCodeType,
                    Attributes = GetMemberAttributes(fieldData.Visibility)
                };
            field.UserData["WithEvents"] = true;
            return field;
        }
Exemple #3
0
        bool ProcessDirective(XamlReader reader, ClassData classData,
                              NamedObject currentObject, bool isRootElement, XamlNodeList strippedXamlNodes, out bool readNextNode)
        {
            Fx.Assert(reader.NodeType == XamlNodeType.StartMember, "Current node should be a Start Member Node");

            XamlMember member = reader.Member;
            bool       directiveRecognized = false;

            readNextNode = false;

            switch (member.Name)
            {
            case "Name":
                // Unlike all the other directives that we process, x:Name should be written
                // to the stripped output.
                strippedXamlNodes.Writer.WriteStartMember(member);

                string objectName = ReadAtom(reader, XamlLanguage.Name.Name);
                if (!objectName.StartsWith(XamlBuildTaskServices.SerializerReferenceNamePrefix,
                                           StringComparison.Ordinal))
                {
                    currentObject.Name = objectName;
                    classData.NamedObjects.Add(currentObject);
                }

                strippedXamlNodes.Writer.WriteValue(objectName);
                strippedXamlNodes.Writer.WriteEndMember();
                directiveRecognized = true;
                break;

            case "Class":
                if (isRootElement)
                {
                    string fullClassName = ReadAtom(reader, XamlLanguage.Class.Name);
                    SetClassName(fullClassName, classData);
                    directiveRecognized = true;
                }
                break;

            case "ClassModifier":
                if (isRootElement)
                {
                    string classModifier = ReadAtom(reader, XamlLanguage.ClassModifier.Name);
                    classData.IsPublic  = XamlBuildTaskServices.IsPublic(classModifier);
                    directiveRecognized = true;
                }
                break;

            case "FieldModifier":
                string fieldModifier = ReadAtom(reader, XamlLanguage.FieldModifier.Name);
                currentObject.Visibility = XamlBuildTaskServices.GetMemberVisibility(fieldModifier);
                directiveRecognized      = true;
                break;

            case "Code":
                string codeSnippet = ReadAtom(reader, XamlLanguage.Code.Name);
                classData.CodeSnippets.Add(codeSnippet);
                directiveRecognized = true;
                break;

            case "Members":
                foreach (PropertyData property in ReadProperties(reader.ReadSubtree()))
                {
                    classData.Properties.Add(property);
                }
                if (!classData.RequiresCompilationPass2)
                {
                    foreach (PropertyData property in classData.Properties)
                    {
                        if (property.Type.IsUnknown)
                        {
                            classData.RequiresCompilationPass2 = true;
                            break;
                        }
                    }
                }
                directiveRecognized = true;
                readNextNode        = true;
                break;

            case "ClassAttributes":
                foreach (AttributeData attribute in ReadAttributesCollection(reader.ReadSubtree()))
                {
                    classData.Attributes.Add(attribute);
                }
                directiveRecognized = true;
                readNextNode        = true;
                break;
            }

            if (directiveRecognized == true && readNextNode == false)
            {
                reader.Read();
                Fx.Assert(reader.NodeType == XamlNodeType.EndMember, "Current node should be a XamlEndmember");
            }

            return(directiveRecognized);
        }
        bool ProcessDirective(XamlReader reader, ClassData classData,
            NamedObject currentObject, bool isRootElement, XamlNodeList strippedXamlNodes, out bool readNextNode)
        {
            Fx.Assert(reader.NodeType == XamlNodeType.StartMember, "Current node should be a Start Member Node");

            XamlMember member = reader.Member;
            bool directiveRecognized = false;
            readNextNode = false;

            switch (member.Name)
            {
                case "Name":
                    // Unlike all the other directives that we process, x:Name should be written
                    // to the stripped output.
                    strippedXamlNodes.Writer.WriteStartMember(member);

                    string objectName = ReadAtom(reader, XamlLanguage.Name.Name);
                    if (!objectName.StartsWith(XamlBuildTaskServices.SerializerReferenceNamePrefix,
                        StringComparison.Ordinal))
                    {
                        currentObject.Name = objectName;
                        classData.NamedObjects.Add(currentObject);
                    }

                    strippedXamlNodes.Writer.WriteValue(objectName);
                    strippedXamlNodes.Writer.WriteEndMember();
                    directiveRecognized = true;
                    break;

                case "Class":
                    if (isRootElement)
                    {
                        string fullClassName = ReadAtom(reader, XamlLanguage.Class.Name);
                        SetClassName(fullClassName, classData);
                        directiveRecognized = true;
                    }
                    break;

                case "ClassModifier":
                    if (isRootElement)
                    {
                        string classModifier = ReadAtom(reader, XamlLanguage.ClassModifier.Name);
                        classData.IsPublic = XamlBuildTaskServices.IsPublic(classModifier);
                        directiveRecognized = true;
                    }
                    break;

                case "FieldModifier":
                    string fieldModifier = ReadAtom(reader, XamlLanguage.FieldModifier.Name);
                    currentObject.Visibility = XamlBuildTaskServices.GetMemberVisibility(fieldModifier);
                    directiveRecognized = true;
                    break;

                case "Code":
                    string codeSnippet = ReadAtom(reader, XamlLanguage.Code.Name);
                    classData.CodeSnippets.Add(codeSnippet);
                    directiveRecognized = true;
                    break;

                case "Members":
                    foreach (PropertyData property in ReadProperties(reader.ReadSubtree()))
                    {
                        classData.Properties.Add(property);
                    }
                    if (!classData.RequiresCompilationPass2)
                    {
                        foreach (PropertyData property in classData.Properties)
                        {
                            if (property.Type.IsUnknown)
                            {
                                classData.RequiresCompilationPass2 = true;
                                break;
                            }
                        }
                    }
                    directiveRecognized = true;
                    readNextNode = true;
                    break;

                case "ClassAttributes":
                    foreach (AttributeData attribute in ReadAttributesCollection(reader.ReadSubtree()))
                    {
                        classData.Attributes.Add(attribute);
                    }
                    directiveRecognized = true;
                    readNextNode = true;
                    break;

            }

            if (directiveRecognized == true && readNextNode == false)
            {
                reader.Read();
                Fx.Assert(reader.NodeType == XamlNodeType.EndMember, "Current node should be a XamlEndmember");
            }

            return directiveRecognized;
        }