예제 #1
0
		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;
		}
예제 #6
0
		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;
        }