// 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; }
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; }