public static BuildResult UpdateDesignerFile ( CodeBehindWriter writer, DotNetProject project, ProjectFile file, ProjectFile designerFile ) { var result = new BuildResult (); //parse the ASP.NET file var parsedDocument = TypeSystemService.ParseFile (project, file.FilePath).Result as WebFormsParsedDocument; if (parsedDocument == null) { result.AddError (string.Format ("Failed to parse file '{0}'", file.Name)); return result; } //TODO: ensure type system is up to date CodeCompileUnit ccu; result.Append (GenerateCodeBehind (project, designerFile.FilePath, parsedDocument, out ccu)); if (ccu != null) { writer.WriteFile (designerFile.FilePath, ccu); } return result; }
static void GenerateDesignerCode (CodeBehindWriter writer, ProjectFile xibFile, ProjectFile designerFile) { var ns = new CodeNamespace (((DotNetProject)designerFile.Project).GetDefaultNamespace (designerFile.FilePath)); var ccu = new CodeCompileUnit (); ccu.Namespaces.Add (ns); foreach (var ctd in CodeBehindGenerator.GetTypes (XDocument.Load (xibFile.FilePath), writer.Provider, writer.GeneratorOptions)) ns.Types.Add (ctd); writer.Write (ccu, designerFile.FilePath); }
private IList<FilePath> GenerateCodeBehindForHeader(ProjectTypeCache cache, CodeBehindWriter writer, FilePath file) { IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForHeader -- Parsing {0}", file); // Parse and collect information from the document AntlrFileStream stream = new AntlrFileStream (file); ObjCLexer lexer = new ObjCLexer (stream); CommonTokenStream tokenStream = new CommonTokenStream (lexer); ObjCParser parser = new ObjCParser (tokenStream); ObjCParser.Translation_unitContext context = parser.translation_unit (); NativeClassDescriptionCollector<int> visitor = new NativeClassDescriptionCollector<int> (); context.Accept (visitor); /* IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForHeader -- Dump classes"); foreach (NativeClassDescriptor classDescriptor in visitor.Descriptors) { IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForHeader -- ClassName={0}", classDescriptor.ClassName); IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForHeader -- SuperClassName={0}", classDescriptor.SuperClassName); foreach (NativeMethodDescriptor descriptor in classDescriptor.Methods) { IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForHeader -- {0}", descriptor); } foreach (NativeInstanceVariableDescriptor descriptor in classDescriptor.InstanceVariables) { IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForHeader -- {0}", descriptor); } } */ List<FilePath> designerFiles = new List<FilePath> (); foreach (NativeClassDescriptor classDescriptor in visitor.Descriptors) { // Check if the class should be generated if (!ShouldGenerateForHeader (classDescriptor)) { IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForHeader -- Skipping {0} (no outlets or no actions)", classDescriptor.ClassName); continue; } // Generate the designer part FilePath designerFile = this.CodeGenerator.GenerateCodeBehindCode (cache, writer, classDescriptor.ClassName, new []{ classDescriptor }); if (designerFile != FilePath.Null) { designerFiles.Add (designerFile); } } return designerFiles; }
public static BuildResult GenerateXibDesignCode(CodeBehindWriter writer, MonobjcProject project, IEnumerable<ProjectFile> files) { BuildResult result = null; // Filter out xib files foreach(ProjectFile file in files.Where (BuildUtils.IsXIBFile)) { ProjectFile designerFile = GetDesignerFile (file); try { // Only generate if needed if (designerFile != null && IsMoreRecent (file, designerFile)) { GenerateXibDesignCode(writer, file, designerFile); } } catch (Exception ex) { if (result == null) { result = new BuildResult(); } // Collect errors result.AddError(file.FilePath, 0, 0, null, ex.Message); LoggingService.LogError (String.Format (CultureInfo.CurrentUICulture, "Cannot generate design code for xib file {0}", file.FilePath), ex); } } return result; }
public static BuildResult UpdateXibCodebehind (CodeBehindWriter writer, IPhoneProject project, IEnumerable<ProjectFile> allFiles, bool forceRegen) { BuildResult result = null; var projWrite = File.GetLastWriteTime (project.FileName); foreach (var xibFile in allFiles.Where (x => x.FilePath.Extension == ".xib" && x.BuildAction == BuildAction.Page)) { var designerFile = GetDesignerFile (xibFile); if (designerFile == null) continue; try { var designerWrite = File.GetLastWriteTime (designerFile.FilePath); if (forceRegen || designerWrite < projWrite || designerWrite < File.GetLastWriteTime (xibFile.FilePath)) { GenerateDesignerCode (writer, xibFile, designerFile); } } catch (Exception ex) { result = result ?? new BuildResult (); result.AddError (xibFile.FilePath, 0, 0, null, ex.Message); LoggingService.LogError (String.Format ("Error generating code for xib file '{0}'", xibFile.FilePath), ex); } } return result; }
internal void GenerateDesignerCode (CodeBehindWriter writer, ProjectFile xibFile, ProjectFile designerFile) { var ccu = Generate (xibFile, writer.Provider, writer.GeneratorOptions); writer.Write (ccu, designerFile.FilePath); }
private static void GenerateXibDesignCode(CodeBehindWriter writer, ProjectFile file, ProjectFile designerFile) { // Create the compilation unit CodeCompileUnit ccu = new CodeCompileUnit (); CodeNamespace ns = new CodeNamespace (((DotNetProject)file.Project).GetDefaultNamespace (designerFile.FilePath)); ccu.Namespaces.Add (ns); // Add namespaces ns.Imports.AddRange(CodeBehindGenerator.GetNamespaces(file.Project)); // Parse the XIB document to collect the class names and their definitions IBDocument document = IBDocument.LoadFromFile (file.FilePath.FullPath); ClassDescriptionCollector collector = new ClassDescriptionCollector (); document.Root.Accept (collector); // Iterate over the extracted class names foreach (String className in collector.ClassNames) { CodeTypeDeclaration ctd = CodeBehindGenerator.GetType(collector, writer, className); if (ctd != null) { ns.Types.Add(ctd); } } // Write the result writer.Write (ccu, designerFile.FilePath); }
public static CodeTypeDeclaration GetType(ClassDescriptionCollector collector, CodeBehindWriter writer, String className) { List<IBPartialClassDescription> descriptions = collector[className]; // Don't generate the partial class if there are neither actions nor outlets int actions = descriptions.Sum (description => description.Actions.Count); int outlets = descriptions.Sum (description => description.Outlets.Count); if (actions == 0 && outlets == 0) { return null; } // Create the partial class CodeTypeDeclaration type = new CodeTypeDeclaration(className); type.IsClass = true; type.IsPartial = true; // Create fields for outlets foreach (IBPartialClassDescription.OutletDescription outlet in descriptions.SelectMany(description => description.Outlets)) { type.Members.Add(GetOutletField(outlet)); } // Create methods for actions foreach (IBPartialClassDescription.ActionDescription action in descriptions.SelectMany(description => description.Actions)) { type.Members.Add(GetPartialMethod(action, writer)); type.Members.Add(GetExposedMethod(action)); } return type; }
public static CodeTypeMember GetPartialMethod(IBPartialClassDescription.ActionDescription action, CodeBehindWriter writer) { String selector = action.Message; String name = GenerateMethodName(selector); // Partial method are only possible by using a snippet of code as CodeDom does not handle them CodeSnippetTypeMember partialMethod; if (writer.Provider is CSharpCodeProvider) { partialMethod = new CodeSnippetTypeMember("partial void " + name + "(Id sender);" + Environment.NewLine); } else if (writer.Provider is VBCodeProvider) { // TODO: Check the generated code partialMethod = new CodeSnippetTypeMember("Partial Private Sub " + name + "(Id sender)" + Environment.NewLine + "End Sub" + Environment.NewLine); } else { throw new NotSupportedException("Provider not supported yet : " + writer.Provider); } return partialMethod; }
private IList<FilePath> GenerateCodeBehindForXib(ProjectTypeCache cache, CodeBehindWriter writer, FilePath file) { IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForXib -- Parsing {0}", file); // Parse and collect information from the document IBDocument document = IBDocument.LoadFromFile (file); ClassDescriptionCollector visitor = new ClassDescriptionCollector (); document.Root.Accept (visitor); List<FilePath> designerFiles = new List<FilePath> (); foreach (string className in visitor.ClassNames) { // Check if the class should be generated if (!ShouldGenerateForXib (visitor, className)) { IDELogger.Log ("CodeBehindHandler::GenerateCodeBehindForXib -- Skipping {0} (no outlets, no actions or reserved name)", className); continue; } // Generate the designer part FilePath designerFile = this.CodeGenerator.GenerateCodeBehindCode (cache, writer, className, visitor [className]); if (designerFile != FilePath.Null) { designerFiles.Add (designerFile); } } return designerFiles; }
/// <summary> /// Generates the design code for an Interface Builder file. /// </summary> /// <param name = "resolver">The type resolver.</param> /// <param name = "writer">The writer.</param> /// <param name = "className">Name of the class.</param> /// <param name = "enumerable">The class descriptions.</param> /// <returns>The path to the designer file.</returns> public FilePath GenerateCodeBehindCode(ProjectTypeCache cache, CodeBehindWriter writer, String className, IEnumerable<IIBClassDescriptor> descriptors) { FilePath designerFile = null; String defaultNamespace; MonobjcProject project = cache.Project; IDELogger.Log ("BaseCodeBehindGenerator::GenerateCodeBehindCode -- Generate designer code for '{0}'", className); IType type = cache.ResolvePartialType (className); FilePath mainFile = cache.GetMainFile (type); if (mainFile != FilePath.Null) { if (mainFile.Extension == ".dll") { IDELogger.Log ("BaseCodeBehindGenerator::GenerateCodeBehindCode -- Skipping '{0}' as it comes from a DLL", className); return FilePath.Null; } if (!cache.IsInProject (type)) { IDELogger.Log ("BaseCodeBehindGenerator::GenerateCodeBehindCode -- Skipping '{0}' as it comes from another project", className); return FilePath.Null; } // The filname is based on the compilation unit parent folder and the type name FilePath parentDirectory = mainFile.ParentDirectory; FilePath filename = project.LanguageBinding.GetFileName (type.Name + Constants.DOT_DESIGNER); designerFile = parentDirectory.Combine (filename); defaultNamespace = type.Namespace; } else { // Combine the filename in the default directory FilePath parentDirectory = project.BaseDirectory; FilePath filename = project.LanguageBinding.GetFileName (className + Constants.DOT_DESIGNER); designerFile = parentDirectory.Combine (filename); defaultNamespace = project.GetDefaultNamespace (designerFile); } IDELogger.Log ("BaseCodeBehindGenerator::GenerateCodeBehindCode -- Put designer code in '{0}'", designerFile); // Create the compilation unit CodeCompileUnit ccu = new CodeCompileUnit (); CodeNamespace ns = new CodeNamespace (defaultNamespace); ccu.Namespaces.Add (ns); // Create the partial class CodeTypeDeclaration typeDeclaration = new CodeTypeDeclaration (className); typeDeclaration.IsClass = true; typeDeclaration.IsPartial = true; // List for import collection Set<String> imports = new Set<string> (); imports.Add ("Monobjc"); // Create fields for outlets); foreach (IBOutletDescriptor outlet in descriptors.SelectMany(d => d.Outlets)) { IType outletType = cache.ResolvePartialType (outlet.ClassName); outletType = outletType ?? cache.ResolvePartialType ("id"); outletType = outletType ?? cache.ResolveType (typeof(IntPtr)); IDELogger.Log ("BaseCodeBehindGenerator::GenerateCodeBehindCode -- Resolving outlet '{0}' of type '{1}' => '{2}'", outlet.Name, outlet.ClassName, outletType.FullName); imports.Add (outletType.Namespace); CodeTypeMember property = this.GenerateOutletProperty (outletType, outlet.Name); typeDeclaration.Members.Add (property); } // Create methods for exposed actions foreach (IBActionDescriptor action in descriptors.SelectMany(d => d.Actions)) { IType argumentType = cache.ResolvePartialType (action.Argument); argumentType = argumentType ?? cache.ResolvePartialType ("id"); argumentType = argumentType ?? cache.ResolveType (typeof(IntPtr)); IDELogger.Log ("BaseCodeBehindGenerator::GenerateCodeBehindCode -- Resolving action '{0}' of type '{1}' => '{2}'", action.Message, action.Argument, argumentType.FullName); imports.Add (argumentType.Namespace); CodeTypeMember exposedMethod = this.GenerateActionExposedMethod (action.Message, argumentType); typeDeclaration.Members.Add (exposedMethod); CodeTypeMember partialMethod = this.GenerateActionPartialMethod (action.Message, argumentType); typeDeclaration.Members.Add (partialMethod); } // Add namespaces CodeNamespaceImport[] namespaceImports = imports.Select (import => new CodeNamespaceImport (import)).ToArray (); ns.Imports.AddRange (namespaceImports); // Add the type ns.Types.Add (typeDeclaration); // Write the result writer.WriteFile (designerFile, ccu); return designerFile; }