Пример #1
0
        ClassData ReadClassData(XamlNodeList xamlNodes, string xamlFileName)
        {
            ClassImporter importer  = new ClassImporter(xamlFileName, this.AssemblyName, this.Language.Equals("VB") ? this.RootNamespace : null);
            ClassData     classData = importer.ReadFromXaml(xamlNodes);

            return(classData);
        }
Пример #2
0
        void SetClassName(string fullClassName, ClassData classData)
        {
            int lastIndex = fullClassName.LastIndexOf('.');

            if (lastIndex != -1)
            {
                string classNamespace = fullClassName.Substring(0, lastIndex);
                string className      = fullClassName.Substring(lastIndex + 1);

                classData.Name      = className;
                classData.Namespace = classNamespace;
            }
            else
            {
                classData.Name      = fullClassName;
                classData.Namespace = String.Empty;
            }

            if (string.IsNullOrEmpty(classData.Name))
            {
                throw FxTrace.Exception.AsError(LogInvalidOperationException(null, SR.ClassNameMustBeNonEmpty));
            }
        }
Пример #3
0
        bool ExecuteExtensions(ClassData classData, ITaskItem markupItem)
        {
            // Execute pass1 extensions only
            // we skip pass1 extensions if we are doing in-proc compile
            if (!this.IsInProcessXamlMarkupCompile)
            {
                bool extensionExecutedSuccessfully = true;
                foreach (IXamlBuildTypeGenerationExtension extension in this.xamlBuildTypeGenerationExtensions)
                {
                    if (extension == null)
                    {
                        continue;
                    }

                    this.BuildContextForExtensions.InputTaskItem = markupItem;
                    try
                    {
                        extensionExecutedSuccessfully = extension.Execute(classData, this.BuildContextForExtensions) && extensionExecutedSuccessfully;
                    }
                    catch (Exception e)
                    {
                        if (Fx.IsFatal(e))
                        {
                            throw;
                        }
                        throw FxTrace.Exception.AsError(new LoggableException(SR.ExceptionThrownInExtension(extension.ToString(), e.GetType().ToString(), e.Message)));
                    }
                }

                if (this.BuildLogger.HasLoggedErrors || !extensionExecutedSuccessfully)
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #4
0
 void RemoveXamlSpaceAttribute(ClassData classData)
 {
     using (XamlReader reader = classData.EmbeddedResourceXaml.GetReader())
     {
         XamlNodeList newList = new XamlNodeList(reader.SchemaContext);
         using (XamlWriter writer = newList.Writer)
         {
             bool nodesAvailable = reader.Read();
             while (nodesAvailable)
             {
                 if (reader.NodeType == XamlNodeType.StartMember && reader.Member == XamlLanguage.Space)
                 {
                     reader.Skip();
                 }
                 else
                 {
                     writer.WriteNode(reader);
                     nodesAvailable = reader.Read();
                 }
             }
         }
         classData.EmbeddedResourceXaml = newList;
     }
 }
Пример #5
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);
        }
Пример #6
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);
        }
Пример #7
0
        bool ProcessMarkupItem(ITaskItem markupItem, CodeDomProvider codeDomProvider)
        {
            string markupItemFileName = markupItem.ItemSpec;

            XamlBuildTaskServices.PopulateModifiers(codeDomProvider);

            XamlNodeList xamlNodes = ReadXamlNodes(markupItemFileName);

            if (xamlNodes == null)
            {
                return(false);
            }

            ClassData classData = ReadClassData(xamlNodes, markupItemFileName);

            string outputFileName = GetFileName(markupItemFileName);
            string codeFileName   = Path.ChangeExtension(outputFileName, GetGeneratedSourceExtension(codeDomProvider));
            string markupFileName = Path.ChangeExtension(outputFileName, GeneratedSourceExtension + XamlBuildTaskServices.XamlExtension);

            classData.EmbeddedResourceFileName = Path.GetFileName(markupFileName);
            classData.HelperClassFullName      = this.HelperClassFullName;

            // Check if code file with partial class exists
            classData.SourceFileExists = UserProvidedFileExists(markupItemFileName, codeDomProvider);

            // Store the full type name as metadata on the markup item
            string rootNamespacePrefix = null;
            string namespacePrefix     = null;
            string typeFullName        = null;

            if (this.Language.Equals("VB") && !String.IsNullOrWhiteSpace(classData.RootNamespace))
            {
                rootNamespacePrefix = classData.RootNamespace + ".";
            }

            if (!String.IsNullOrWhiteSpace(classData.Namespace))
            {
                namespacePrefix = classData.Namespace + ".";
            }

            if (rootNamespacePrefix != null)
            {
                if (namespacePrefix != null)
                {
                    typeFullName = rootNamespacePrefix + namespacePrefix + classData.Name;
                }
                else
                {
                    typeFullName = rootNamespacePrefix + classData.Name;
                }
            }
            else
            {
                if (namespacePrefix != null)
                {
                    typeFullName = namespacePrefix + classData.Name;
                }
                else
                {
                    typeFullName = classData.Name;
                }
            }

            markupItem.SetMetadata("typeName", typeFullName);

            // Execute extensions here to give them a chance to mutate the ClassData before we generate code.
            if (this.SupportExtensions)
            {
                if (!ExecuteExtensions(classData, markupItem))
                {
                    return(false);
                }
            }

            // Generate code file
            CodeCompileUnit codeUnit = new ClassGenerator(this.BuildLogger, codeDomProvider, this.Language).Generate(classData);

            WriteCode(codeDomProvider, codeUnit, codeFileName);
            this.GeneratedCodeFiles.Add(codeFileName);

            // Generate resource file
            if (!string.IsNullOrEmpty(this.AssemblyName))
            {
                // Generate xaml "implementation" file
                XmlWriterSettings xmlSettings = new XmlWriterSettings {
                    Indent = true, IndentChars = "  ", CloseOutput = true
                };
                using (XmlWriter xmlWriter = XmlWriter.Create(File.Open(markupFileName, FileMode.Create), xmlSettings))
                {
                    XamlXmlWriterSettings xamlSettings = new XamlXmlWriterSettings()
                    {
                        CloseOutput = true
                    };

                    // Process EmbeddedResourceXaml to remove xml:space="preserve"
                    // due to a bug in XamlXmlWriter. XamlXmlWriter throws
                    // if there are duplicate xml:space attributes.
                    // It is ok to remove the xml:space attribute
                    // as the XamlXmlWriter would add it in the next step
                    // if needed.
                    RemoveXamlSpaceAttribute(classData);

                    using (XamlReader reader = classData.EmbeddedResourceXaml.GetReader())
                    {
                        using (XamlXmlWriter xamlWriter = new XamlXmlWriter(xmlWriter, reader.SchemaContext, xamlSettings))
                        {
                            XamlServices.Transform(reader, xamlWriter);
                        }
                    }
                }
                this.GeneratedResources.Add(markupFileName);
            }

            if (classData.RequiresCompilationPass2)
            {
                this.RequiresCompilationPass2 = true;
            }
            else
            {
                if (!this.SupportExtensions)
                {
                    if (!ValidateXaml(xamlNodes, markupItemFileName))
                    {
                        this.RequiresCompilationPass2 = true;
                    }
                }
                else
                {
                    // skip validation if we are doing in-proc compile
                    // OR if we have pass 2 extensions hooked up
                    // as we anyway need to run pass 2 in that case
                    if (!this.IsInProcessXamlMarkupCompile && !this.MarkupCompilePass2ExtensionsPresent)
                    {
                        if (!ValidateXaml(xamlNodes, markupItemFileName))
                        {
                            this.RequiresCompilationPass2 = true;
                        }
                    }
                }
            }
            return(true);
        }