Example #1
0
        /// <summary>
        /// Updates the XAML of the class declaration.
        /// </summary>
        /// <param name="xaml">Xaml.</param>
        internal async Task UpdateXaml(XAMLDocument xaml)
        {
            Xaml = xaml.XAML;
            LoadStyleSheets(xaml);
            await UpdateAutoGeneratedCodeBehind();

            autoGenCodeBehindCode = null;
            FillAutoGenCodeBehind();
        }
Example #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:XAMLator.Client.FormsViewClassDeclaration"/> class
 /// from a XAML document.
 /// </summary>
 /// <param name="codeBehindFilePath">Code behind file path.</param>
 /// <param name="xaml">XAML.</param>
 public FormsViewClassDeclaration(string codeBehindFilePath, XAMLDocument xaml)
 {
     this.codeBehindFilePath = codeBehindFilePath;
     this.xamlFilePath       = xaml.FilePath;
     StyleSheets             = new Dictionary <string, string>();
     Namespace = xaml.Type.Substring(0, xaml.Type.LastIndexOf('.'));
     ClassName = xaml.Type.Split('.').Last();
     classesCache.Add(this);
     UpdateXaml(xaml);
 }
Example #3
0
        /// <summary>
        /// Parses document updates from the IDE and return the class associated
        /// with the changes.
        /// </summary>
        /// <returns>The class declaration that changed.</returns>
        /// <param name="fileName">File name changed.</param>
        /// <param name="text">Text changed.</param>
        /// <param name="syntaxTree">Syntax tree.</param>
        /// <param name="semanticModel">Semantic model.</param>
        public static async Task <FormsViewClassDeclaration> ParseDocument(string fileName,
                                                                           string text,
                                                                           SyntaxTree syntaxTree,
                                                                           SemanticModel semanticModel)
        {
            XAMLDocument xamlDocument = null;
            FormsViewClassDeclaration formsViewClass = null;

            // FIXME: Support any kind of types, not just Xamarin.Forms views
            if (!fileName.EndsWith(".xaml") && !fileName.EndsWith(".xaml.cs") && !fileName.EndsWith(".cs"))
            {
                return(null);
            }

            // Check if we have already an instance of the class declaration for that file
            if (!FormsViewClassDeclaration.TryGetByFileName(fileName, out formsViewClass))
            {
                if (fileName.EndsWith(".xaml"))
                {
                    xamlDocument = XAMLDocument.Parse(fileName, text);
                    // Check if we have an instance of class by namespace
                    if (!FormsViewClassDeclaration.TryGetByFullNamespace(xamlDocument.Type, out formsViewClass))
                    {
                        formsViewClass = await CreateFromXaml(xamlDocument);
                    }
                }
                else
                {
                    formsViewClass = await CreateFromCodeBehind(fileName, syntaxTree, semanticModel);
                }
            }

            if (formsViewClass == null)
            {
                return(null);
            }

            // The document is a XAML file
            if (fileName.EndsWith(".xaml") && xamlDocument == null)
            {
                xamlDocument = XAMLDocument.Parse(fileName, text);
                await formsViewClass.UpdateXaml(xamlDocument);
            }
            // The document is code behind or a view without XAML
            if (fileName.EndsWith(".cs"))
            {
                var classDeclaration = FormsViewClassDeclaration.FindClass(syntaxTree, formsViewClass.ClassName);
                if (formsViewClass.NeedsClassInitialization)
                {
                    formsViewClass.FillClassInfo(classDeclaration, semanticModel);
                }
                formsViewClass.UpdateCode(classDeclaration, semanticModel);
            }
            return(formsViewClass);
        }
Example #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:XAMLator.Client.FormsViewClassDeclaration"/> class
 /// from a code behind document.
 /// </summary>
 /// <param name="classDeclarationSyntax">Class declaration syntax.</param>
 /// <param name="model">Model.</param>
 /// <param name="codeBehindFilePath">Code behind file path.</param>
 /// <param name="xaml">Xaml.</param>
 public FormsViewClassDeclaration(ClassDeclarationSyntax classDeclarationSyntax, SemanticModel model,
                                  string codeBehindFilePath, XAMLDocument xaml)
 {
     this.codeBehindFilePath = codeBehindFilePath;
     this.xamlFilePath       = xaml.FilePath;
     StyleSheets             = new Dictionary <string, string>();
     FillClassInfo(classDeclarationSyntax, model);
     UpdateXaml(xaml);
     UpdateCode(classDeclarationSyntax);
     classesCache.Add(this);
 }
Example #5
0
 void LoadStyleSheets(XAMLDocument xaml)
 {
     foreach (var styleSheetPath in xaml.StyleSheets)
     {
         try
         {
             StyleSheets[styleSheetPath] = File.ReadAllText(ResolveStyleSheetPath(xaml, styleSheetPath));
         }
         catch (Exception ex)
         {
             Log.Exception(ex);
         }
     }
 }
Example #6
0
        static async Task <FormsViewClassDeclaration> CreateFromCodeBehind(string fileName,
                                                                           SyntaxTree syntaxTree, SemanticModel semanticModel)

        {
            string xaml               = null;
            string xamlFilePath       = null;
            string codeBehindFilePath = null;
            string className          = null;
            ClassDeclarationSyntax classDeclaration;
            XAMLDocument           xamlDocument = null;

            codeBehindFilePath = fileName;
            var xamlCandidate = fileName.Substring(0, fileName.Length - 3);

            if (File.Exists(xamlCandidate))
            {
                xamlFilePath = xamlCandidate;
                xaml         = File.ReadAllText(xamlFilePath);
            }

            // FIXME: Handle XF views without XAML
            if (xamlFilePath != null)
            {
                // Parse the XAML file
                xamlDocument     = XAMLDocument.Parse(xamlFilePath, xaml);
                className        = xamlDocument.Type.Split('.').Last();
                classDeclaration = FormsViewClassDeclaration.FindClass(syntaxTree, className);
            }
            else
            {
                try
                {
                    classDeclaration = FormsViewClassDeclaration.FindFormsViewClass(syntaxTree, semanticModel);
                }
                catch (Exception ex)
                {
                    Log.Exception(ex);
                    Log.Error("The class is not a Xamarin.Forms View or Page");
                    return(null);
                }
            }
            var formsClass = new FormsViewClassDeclaration(classDeclaration, semanticModel,
                                                           codeBehindFilePath, xamlDocument);

            if (xamlDocument != null)
            {
                await formsClass.UpdateXaml(xamlDocument);
            }
            return(formsClass);
        }
Example #7
0
        static async Task <FormsViewClassDeclaration> CreateFromXaml(XAMLDocument xamlDocument)

        {
            string codeBehindFilePath = xamlDocument.FilePath + ".cs";

            if (!File.Exists(codeBehindFilePath))
            {
                Log.Error("XAML file without code behind");
                return(null);
            }
            var xamlClass = new FormsViewClassDeclaration(codeBehindFilePath, xamlDocument);
            await xamlClass.UpdateXaml(xamlDocument);

            return(xamlClass);
        }
Example #8
0
        /// <summary>
        /// Request to preview a xaml document.
        /// </summary>
        /// <returns>The evaluation response.</returns>
        /// <param name="doc">The XAML document.</param>
        public async Task <EvalResponse> PreviewXaml(XAMLDocument doc)
        {
            EvalRequest request = new EvalRequest {
                Xaml = doc.XAML, XamlType = doc.Type
            };
            var content  = new StringContent(Serializer.SerializeJson(request), Encoding.UTF8);
            var response = await client.PostAsync(baseUri + "/xaml", content);

            if (response.IsSuccessStatusCode)
            {
                return(Serializer.DeserializeJson <EvalResponse>(await response.Content.ReadAsStringAsync()));
            }
            else
            {
                return(null);
            }
        }
Example #9
0
        /// <summary>
        /// Parses document updates from the IDE and return the class associated
        /// with the changes.
        /// </summary>
        /// <returns>The class declaration that changed.</returns>
        /// <param name="fileName">File name changed.</param>
        /// <param name="text">Text changed.</param>
        /// <param name="syntaxTree">Syntax tree.</param>
        /// <param name="semanticModel">Semantic model.</param>
        public static async Task <FormsViewClassDeclaration> ParseDocument(string fileName,
                                                                           string text,
                                                                           SyntaxTree syntaxTree,
                                                                           SemanticModel semanticModel)
        {
            // FIXME: Support any kind of types, not just Xamarin.Forms views
            if (!fileName.EndsWith(".xaml") && !fileName.EndsWith(".xaml.cs"))
            {
                return(null);
            }

            if (!GetOrCreate(fileName, text, syntaxTree, semanticModel,
                             out FormsViewClassDeclaration xamlClass,
                             out XAMLDocument xamlDocument))
            {
                Log.Error("Could not handle document update");
                return(null);
            }

            // The document is a XAML file
            if (fileName.EndsWith(".xaml"))
            {
                if (xamlDocument == null)
                {
                    xamlDocument = XAMLDocument.Parse(fileName, text);
                }
                await xamlClass.UpdateXaml(xamlDocument);
            }
            // The document is code behind
            else if (fileName.EndsWith(".xaml.cs"))
            {
                var classDeclaration = FormsViewClassDeclaration.FindClass(syntaxTree, xamlClass.ClassName);
                if (xamlClass.NeedsClassInitialization)
                {
                    xamlClass.FillClassInfo(classDeclaration, semanticModel);
                }
                xamlClass.UpdateCode(classDeclaration);
            }
            return(xamlClass);
        }
Example #10
0
 string ResolveStyleSheetPath(XAMLDocument xaml, string styleSheetPath)
 {
     if (styleSheetPath.StartsWith(Constants.ROOT_REPLACEMENT))
     {
         styleSheetPath = styleSheetPath.Replace(Constants.ROOT_REPLACEMENT + "/", "");
         var currentDir = Path.GetDirectoryName(xaml.FilePath);
         do
         {
             var filePath = Path.Combine(currentDir, styleSheetPath);
             if (File.Exists(filePath))
             {
                 return(filePath);
             }
             currentDir = Path.GetFullPath(Path.Combine(currentDir, ".."));
         } while (Directory.GetFiles(currentDir).Any(f => f.EndsWith(".sln")) ||
                  currentDir == Directory.GetDirectoryRoot(currentDir));
         return(null);
     }
     else
     {
         return(Path.Combine(Path.GetDirectoryName(xaml.FilePath), styleSheetPath));
     }
 }
Example #11
0
        static bool GetOrCreate(string fileName,
                                string text,
                                SyntaxTree syntaxTree,
                                SemanticModel semanticModel,
                                out FormsViewClassDeclaration xamlClass,
                                out XAMLDocument xamlDocument)
        {
            string xaml = null, xamlFilePath = null, codeBehindFilePath = null;

            xamlDocument = null;

            // Check if we have already an instance of the class declaration for that file
            if (FormsViewClassDeclaration.TryGetByFileName(fileName, out xamlClass))
            {
                return(true);
            }

            if (fileName.EndsWith(".xaml"))
            {
                xaml         = text;
                xamlFilePath = fileName;
                var candidate = xamlFilePath + ".cs";
                if (File.Exists(candidate))
                {
                    codeBehindFilePath = candidate;
                }
            }
            else
            {
                codeBehindFilePath = fileName;
                var candidate = fileName.Substring(0, fileName.Length - 3);
                if (File.Exists(candidate))
                {
                    xamlFilePath = candidate;
                    xaml         = File.ReadAllText(xamlFilePath);
                }
            }

            // FIXME: Handle XF views without XAML
            // Parse the XAML file
            xamlDocument = XAMLDocument.Parse(xamlFilePath, xaml);
            if (xamlDocument == null)
            {
                Log.Error("Error parsing XAML");
                return(false);
            }

            // Check if we have an instance of class by namespace
            if (FormsViewClassDeclaration.TryGetByFullNamespace(xamlDocument.Type, out xamlClass))
            {
                return(true);
            }

            // This is the first time we have an update for this type

            // Create a new class declaration instance from the syntax tree
            if (syntaxTree != null)
            {
                var className        = xamlDocument.Type.Split('.').Last();
                var classDeclaration = FormsViewClassDeclaration.FindClass(syntaxTree, className);
                xamlClass = new FormsViewClassDeclaration(classDeclaration, semanticModel,
                                                          codeBehindFilePath, xamlDocument);
            }
            // Create a new class declaration instance from the XAML
            else
            {
                xamlClass = new FormsViewClassDeclaration(codeBehindFilePath, xamlDocument);
            }
            return(true);
        }