void HandleDataReceived(object sender, object e) { var container = e as JContainer; string type = (string)container["Type"]; if (type == typeof(ResetMessage).Name) { FormsViewClassDeclaration.Reset(); } }
/// <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); }
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); }
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); }
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); }
/// <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); }
/// <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); }