示例#1
0
		public bool Initialize (string taskName, IDictionary<string, string> factoryIdentityParameters, IDictionary<string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost)
		{
			task_name = taskName;
			if (parameterGroup != null)
				parameter_group = new Dictionary<string, TaskPropertyInfo> (parameterGroup);
			
			List<string> references = new List<string> ();
			List<string> namespace_uses = new List<string> ();
			namespace_uses.Add ("Microsoft.Build.Framework");
			string type = null, language = null, code = null;

			var xml = XmlReader.Create (new StringReader (taskBody), new XmlReaderSettings () { ConformanceLevel = ConformanceLevel.Fragment });
			for (xml.MoveToContent (); !xml.EOF; xml.MoveToContent ()) {
				switch (xml.NodeType) {
				case XmlNodeType.Element:
					switch (xml.LocalName) {
					case "Reference":
						references.Add (xml.GetAttribute ("Include"));
						xml.Skip ();
						break;
					case "Using":
						namespace_uses.Add (xml.GetAttribute ("Namespace"));
						xml.Skip ();
						break;
					case "Code":
						// MSB3757: Multiple Code elements have been found, this is not allowed.
						if (code != null)
							throw new InvalidProjectFileException (null, "Multiple Code elements are not allowed", "MSB", "3757", null);
						type = xml.GetAttribute ("Type");
						language = xml.GetAttribute ("Language");
						code = xml.ReadElementContentAsString ();
						break;
					}
					break;
				default:
					xml.Skip ();
					break;
				}
			}
			if (language == "vb")
				throw new NotImplementedException (string.Format ("{0} is not supported language for inline task", language));
			if (language != "cs")
				throw new InvalidProjectFileException (null, string.Format ("{0} is not supported language for inline task", language), "MSB", "4175", null);
			string gen = null;
			// The documentation says "ITask", but the very first example shows "Log" which is not in ITask! It is likely that the generated code uses Task or TaskExtension.
			string classTemplate = @"public class " + taskName + " : Microsoft.Build.Utilities.Task { @@EXECUTE@@ }";
			foreach (var ns in namespace_uses)
				gen += "using " + ns + ";\n";
			switch (type) {
			case "Class":
				gen += code;
				break;
			case "Method":
				gen += classTemplate.Replace ("@@EXECUTE@@", code);
				break;
			case "Fragment":
				gen += classTemplate.Replace ("@@EXECUTE@@", "public override bool Execute () { " + code + " return true; }");
				break;
			}

			var cscParams = new CompilerParameters ();
			cscParams.ReferencedAssemblies.Add ("Microsoft.Build.Framework.dll");
			cscParams.ReferencedAssemblies.Add ("Microsoft.Build.Utilities.v4.0.dll"); // since we use Task, it depends on this dll.
			var results = new CSharpCodeProvider ().CompileAssemblyFromSource (cscParams, gen);
			var errors = new CompilerError [results.Errors.Count];
			results.Errors.CopyTo (errors, 0);
			if (errors.Any (e => !e.IsWarning)) {
				string msg = string.Format ("Invalid '{0}' source code of '{1}' type: {2}", language, type, string.Join (" ", errors.Where (e => !e.IsWarning).Select (e => e.ToString ())));
				throw new InvalidProjectFileException (null, msg, "MSB", "3758", null);
			}
			assembly = results.CompiledAssembly;
			return true;
		}
示例#2
0
        bool Initialize(string taskName, IDictionary <string, string> factoryIdentityParameters, IDictionary <string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost)
        {
            task_name = taskName;
            if (parameterGroup != null)
            {
                parameter_group = new Dictionary <string, TaskPropertyInfo> (parameterGroup);
            }

            List <string> references     = new List <string> ();
            List <string> namespace_uses = new List <string> ();

            namespace_uses.Add("Microsoft.Build.Framework");
            string type = null, language = null, code = null;

            var xml = XmlReader.Create(new StringReader(taskBody), new XmlReaderSettings()
            {
                ConformanceLevel = ConformanceLevel.Fragment
            });

            for (xml.MoveToContent(); !xml.EOF; xml.MoveToContent())
            {
                switch (xml.NodeType)
                {
                case XmlNodeType.Element:
                    switch (xml.LocalName)
                    {
                    case "Reference":
                        references.Add(xml.GetAttribute("Include"));
                        xml.Skip();
                        break;

                    case "Using":
                        namespace_uses.Add(xml.GetAttribute("Namespace"));
                        xml.Skip();
                        break;

                    case "Code":
                        // MSB3757: Multiple Code elements have been found, this is not allowed.
                        if (code != null)
                        {
                            throw new InvalidProjectFileException(null, "Multiple Code elements are not allowed", "MSB", "3757", null);
                        }
                        type     = xml.GetAttribute("Type");
                        language = xml.GetAttribute("Language");
                        code     = xml.ReadElementContentAsString();
                        break;
                    }
                    break;

                default:
                    xml.Skip();
                    break;
                }
            }
            if (language == "vb")
            {
                throw new NotImplementedException(string.Format("{0} is not supported language for inline task", language));
            }
            if (language != "cs")
            {
                throw new InvalidProjectFileException(null, string.Format("{0} is not supported language for inline task", language), "MSB", "4175", null);
            }
            string gen = null;
            // The documentation says "ITask", but the very first example shows "Log" which is not in ITask! It is likely that the generated code uses Task or TaskExtension.
            string classTemplate = @"public class " + taskName + " : Microsoft.Build.Utilities.Task { @@EXECUTE@@ }";

            foreach (var ns in namespace_uses)
            {
                gen += "using " + ns + ";\n";
            }
            switch (type)
            {
            case "Class":
                gen += code;
                break;

            case "Method":
                gen += classTemplate.Replace("@@EXECUTE@@", code);
                break;

            case "Fragment":
                gen += classTemplate.Replace("@@EXECUTE@@", "public override bool Execute () { " + code + " return true; }");
                break;
            }

            var cscParams = new CompilerParameters();

            cscParams.ReferencedAssemblies.Add("Microsoft.Build.Framework.dll");
            cscParams.ReferencedAssemblies.Add("Microsoft.Build.Utilities.v4.0.dll");              // since we use Task, it depends on this dll.
            var results = new CSharpCodeProvider().CompileAssemblyFromSource(cscParams, gen);
            var errors  = new CompilerError [results.Errors.Count];

            results.Errors.CopyTo(errors, 0);
            if (errors.Any(e => !e.IsWarning))
            {
                string msg = string.Format("Invalid '{0}' source code of '{1}' type: {2}", language, type, string.Join(" ", errors.Where(e => !e.IsWarning).Select(e => e.ToString())));
                throw new InvalidProjectFileException(null, msg, "MSB", "3758", null);
            }
            assembly = results.CompiledAssembly;
            return(true);
        }
示例#3
0
        bool Initialize(string taskName, IDictionary <string, string> factoryIdentityParameters, IDictionary <string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost)
        {
            task_name = taskName;
            if (parameterGroup != null)
            {
                parameter_group = new Dictionary <string, TaskPropertyInfo> (parameterGroup);
            }

            List <string> references     = new List <string> ();
            List <string> namespace_uses = new List <string> ();

            namespace_uses.Add("Microsoft.Build.Framework");
            string type = null, language = null, code = null;

            var xml = XmlReader.Create(new StringReader(taskBody), new XmlReaderSettings()
            {
                ConformanceLevel = ConformanceLevel.Fragment
            });

            for (xml.MoveToContent(); !xml.EOF; xml.MoveToContent())
            {
                switch (xml.NodeType)
                {
                case XmlNodeType.Element:
                    switch (xml.LocalName)
                    {
                    case "Reference":
                        references.Add(xml.GetAttribute("Include"));
                        xml.Skip();
                        break;

                    case "Using":
                        namespace_uses.Add(xml.GetAttribute("Namespace"));
                        xml.Skip();
                        break;

                    case "Code":
                        // MSB3757: Multiple Code elements have been found, this is not allowed.
                        if (code != null)
                        {
                            throw new InvalidProjectFileException(null, "Multiple Code elements are not allowed", "MSB", "3757", null);
                        }
                        type     = xml.GetAttribute("Type");
                        language = xml.GetAttribute("Language");
                        code     = xml.ReadElementContentAsString();
                        break;
                    }
                    break;

                default:
                    xml.Skip();
                    break;
                }
            }

            if (language != "cs" && language != "vb")
            {
                throw new InvalidProjectFileException(null, string.Format("{0} is not supported language for inline task", language), "MSB", "4175", null);
            }

            CodeCompileUnit ccu;

            if (type == "Class")                // 'code' contains the whole class that implements the task
            {
                ccu = new CodeSnippetCompileUnit(code);
            }
            else                // 'code' contains parts of the class that implements the task
            {
                ccu = new CodeCompileUnit();
                var nsp = new CodeNamespace();
                nsp.Imports.AddRange(namespace_uses.Select(x => new CodeNamespaceImport(x)).ToArray());
                ccu.Namespaces.Add(nsp);

                var taskClass = new CodeTypeDeclaration {
                    IsClass        = true,
                    Name           = taskName,
                    TypeAttributes = TypeAttributes.Public
                };

                var parameters = new List <CodeMemberProperty> ();
                var parametersBackingFields = new List <CodeMemberField> ();

                // add a public property + backing field for each parameter
                foreach (var param in parameter_group)
                {
                    var prop = new CodeMemberProperty {
                        Attributes = MemberAttributes.Public | MemberAttributes.Final,
                        Name       = param.Value.Name,
                        Type       = new CodeTypeReference(param.Value.PropertyType)
                    };

                    var propBf = new CodeMemberField {
                        Attributes = MemberAttributes.Private,
                        Name       = "_" + prop.Name,
                        Type       = prop.Type
                    };

                    // add getter and setter to the property
                    prop.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), propBf.Name)));
                    prop.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), propBf.Name), new CodePropertySetValueReferenceExpression()));

                    parameters.Add(prop);
                    parametersBackingFields.Add(propBf);
                }

                taskClass.Members.AddRange(parameters.ToArray());
                taskClass.Members.AddRange(parametersBackingFields.ToArray());
                taskClass.BaseTypes.Add("Microsoft.Build.Utilities.Task"); // The documentation says "ITask", but the very first example shows "Log" which is not in ITask! It is likely that the generated code uses Task or TaskExtension.

                if (type == "Method")                                      // 'code' contains the 'Execute' method directly
                {
                    taskClass.Members.Add(new CodeSnippetTypeMember(code));
                }
                else if (type == "Fragment")                    // 'code' contains the body of the 'Execute' method
                {
                    var method = new CodeMemberMethod {
                        Attributes = MemberAttributes.Public | MemberAttributes.Override,
                        Name       = "Execute",
                        ReturnType = new CodeTypeReference(typeof(bool))
                    };

                    // add the code and a 'return true' at the end of the method
                    method.Statements.Add(new CodeSnippetStatement(code));
                    method.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(true)));

                    taskClass.Members.Add(method);
                }
                else
                {
                    throw new ArgumentException("Invalid type: " + type);
                }

                nsp.Types.Add(taskClass);
            }

            var cscParams = new CompilerParameters();

            cscParams.ReferencedAssemblies.Add("Microsoft.Build.Framework.dll");
            cscParams.ReferencedAssemblies.Add("Microsoft.Build.Utilities.v4.0.dll");              // since we use Task, it depends on this dll.
            cscParams.ReferencedAssemblies.AddRange(GetReferences(references, taskFactoryLoggingHost));
            cscParams.GenerateInMemory = true;
            var results = CodeDomProvider.CreateProvider(language).CompileAssemblyFromDom(cscParams, ccu);
            var errors  = new CompilerError [results.Errors.Count];

            results.Errors.CopyTo(errors, 0);
            if (errors.Any(e => !e.IsWarning))
            {
                string msg = string.Format("Invalid '{0}' source code of '{1}' type: {2}", language, type, string.Join(" ", errors.Where(e => !e.IsWarning).Select(e => e.ToString())));
                throw new InvalidProjectFileException(null, msg, "MSB", "3758", null);
            }
            assembly = results.CompiledAssembly;
            return(true);
        }
示例#4
0
		bool Initialize (string taskName, IDictionary<string, string> factoryIdentityParameters, IDictionary<string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost)
		{
			task_name = taskName;
			if (parameterGroup != null)
				parameter_group = new Dictionary<string, TaskPropertyInfo> (parameterGroup);
			
			List<string> references = new List<string> ();
			List<string> namespace_uses = new List<string> ();
			namespace_uses.Add ("Microsoft.Build.Framework");
			string type = null, language = null, code = null;

			var xml = XmlReader.Create (new StringReader (taskBody), new XmlReaderSettings () { ConformanceLevel = ConformanceLevel.Fragment });
			for (xml.MoveToContent (); !xml.EOF; xml.MoveToContent ()) {
				switch (xml.NodeType) {
				case XmlNodeType.Element:
					switch (xml.LocalName) {
					case "Reference":
						references.Add (xml.GetAttribute ("Include"));
						xml.Skip ();
						break;
					case "Using":
						namespace_uses.Add (xml.GetAttribute ("Namespace"));
						xml.Skip ();
						break;
					case "Code":
						// MSB3757: Multiple Code elements have been found, this is not allowed.
						if (code != null)
							throw new InvalidProjectFileException (null, "Multiple Code elements are not allowed", "MSB", "3757", null);
						type = xml.GetAttribute ("Type");
						language = xml.GetAttribute ("Language");
						code = xml.ReadElementContentAsString ();
						break;
					}
					break;
				default:
					xml.Skip ();
					break;
				}
			}

			if (language != "cs" && language != "vb")
				throw new InvalidProjectFileException (null, string.Format ("{0} is not supported language for inline task", language), "MSB", "4175", null);

			CodeCompileUnit ccu;

			if (type == "Class") {  // 'code' contains the whole class that implements the task
				ccu = new CodeSnippetCompileUnit (code);
			}
			else {  // 'code' contains parts of the class that implements the task
				ccu = new CodeCompileUnit ();
				var nsp = new CodeNamespace ();
				nsp.Imports.AddRange (namespace_uses.Select (x => new CodeNamespaceImport (x)).ToArray ());
				ccu.Namespaces.Add (nsp);

				var taskClass = new CodeTypeDeclaration {
					IsClass = true,
					Name = taskName,
					TypeAttributes = TypeAttributes.Public
				};

				var parameters = new List<CodeMemberProperty> ();
				var parametersBackingFields = new List<CodeMemberField> ();

				// add a public property + backing field for each parameter
				foreach (var param in parameter_group) {
					var prop = new CodeMemberProperty {
						Attributes = MemberAttributes.Public | MemberAttributes.Final,
						Name = param.Value.Name,
						Type = new CodeTypeReference (param.Value.PropertyType)
					};

					var propBf = new CodeMemberField {
						Attributes = MemberAttributes.Private,
						Name = "_" + prop.Name,
						Type = prop.Type
					};

					// add getter and setter to the property
					prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), propBf.Name)));
					prop.SetStatements.Add (new CodeAssignStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), propBf.Name), new CodePropertySetValueReferenceExpression ()));

					parameters.Add (prop);
					parametersBackingFields.Add (propBf);
				}

				taskClass.Members.AddRange (parameters.ToArray ());
				taskClass.Members.AddRange (parametersBackingFields.ToArray ());
				taskClass.BaseTypes.Add ("Microsoft.Build.Utilities.Task");  // The documentation says "ITask", but the very first example shows "Log" which is not in ITask! It is likely that the generated code uses Task or TaskExtension.

				if (type == "Method") {  // 'code' contains the 'Execute' method directly
					taskClass.Members.Add (new CodeSnippetTypeMember (code));
				}
				else if (type == "Fragment") {  // 'code' contains the body of the 'Execute' method
					var method = new CodeMemberMethod {
						Attributes = MemberAttributes.Public | MemberAttributes.Override,
						Name = "Execute",
						ReturnType = new CodeTypeReference (typeof (bool))
					};

					// add the code and a 'return true' at the end of the method
					method.Statements.Add (new CodeSnippetStatement (code));
					method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (true)));

					taskClass.Members.Add (method);
				}
				else {
					throw new ArgumentException ("Invalid type: " + type);
				}

				nsp.Types.Add (taskClass);
			}

			var cscParams = new CompilerParameters ();
			cscParams.ReferencedAssemblies.Add ("Microsoft.Build.Framework.dll");
			cscParams.ReferencedAssemblies.Add ("Microsoft.Build.Utilities.v4.0.dll"); // since we use Task, it depends on this dll.
			cscParams.ReferencedAssemblies.AddRange (GetReferences (references, taskFactoryLoggingHost));
			cscParams.GenerateInMemory = true;
			var results = CodeDomProvider.CreateProvider (language).CompileAssemblyFromDom (cscParams, ccu);
			var errors = new CompilerError [results.Errors.Count];
			results.Errors.CopyTo (errors, 0);
			if (errors.Any (e => !e.IsWarning)) {
				string msg = string.Format ("Invalid '{0}' source code of '{1}' type: {2}", language, type, string.Join (" ", errors.Where (e => !e.IsWarning).Select (e => e.ToString ())));
				throw new InvalidProjectFileException (null, msg, "MSB", "3758", null);
			}
			assembly = results.CompiledAssembly;
			return true;
		}