Exemple #1
0
        void HandleDataReceived(object sender, object e)
        {
            var    container = e as JContainer;
            string type      = (string)container["Type"];

            if (type == typeof(ResetMessage).Name)
            {
                FormsViewClassDeclaration.Reset();
            }
        }
Exemple #2
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);
        }
Exemple #3
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);
        }
Exemple #4
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);
        }
Exemple #5
0
        async void HandleDocumentChanged(object sender, DocumentChangedEventArgs e)
        {
            if (server.ClientsCount == 0)
            {
                return;
            }
            FormsViewClassDeclaration classDecl = null;

            try
            {
                classDecl = await DocumentParser.ParseDocument(e.Filename, e.Text, e.SyntaxTree, e.SemanticModel);
            }
            catch (Exception ex)
            {
                Log.Exception(ex);
                await server.Send(new ErrorMessage($"Error parsing {e.Filename}",
                                                   ex.ToString()));

                return;
            }

            if (classDecl == null)
            {
                return;
            }

            EvalRequestMessage request = new EvalRequestMessage
            {
                Declarations     = classDecl.Code,
                NeedsRebuild     = classDecl.NeedsRebuild,
                OriginalTypeName = classDecl.FullNamespace,
                NewTypeName      = classDecl.CurrentFullNamespace,
                Xaml             = classDecl.Xaml,
                XamlResourceName = classDecl.XamlResourceId,
                StyleSheets      = classDecl.StyleSheets
            };

            try
            {
                await server.Send(request);
            }
            catch (Exception ex)
            {
                Log.Exception(ex);
            }
        }
        /// <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);
        }
Exemple #7
0
 /// <summary>
 /// Tries to find a cached class declaration using this file path.
 /// </summary>
 /// <returns><c>true</c>, if we found matching class, <c>false</c> otherwise.</returns>
 /// <param name="filePath">File path.</param>
 /// <param name="viewClass">View class.</param>
 internal static bool TryGetByFileName(string filePath, out FormsViewClassDeclaration viewClass)
 {
     viewClass = classesCache.SingleOrDefault(x => x.xamlFilePath == filePath || x.codeBehindFilePath == filePath);
     return(viewClass != null);
 }
Exemple #8
0
 /// <summary>
 /// Tries to find a cached class declaration with the same full namespace.
 /// </summary>
 /// <returns><c>true</c>, if we found matching class, <c>false</c> otherwise.</returns>
 /// <param name="fullNamespace">Full namespace.</param>
 /// <param name="viewClass">View class.</param>
 internal static bool TryGetByFullNamespace(string fullNamespace, out FormsViewClassDeclaration viewClass)
 {
     viewClass = classesCache.SingleOrDefault(x => x.FullNamespace == fullNamespace);
     return(viewClass != null);
 }
        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);
        }