示例#1
0
 public void TestConstructorNoItems()
 {
     TargetResult result = new TargetResult(new TaskItem[] { }, TestUtilities.GetStopWithErrorResult());
     Assert.Equal(0, result.Items.Length);
     Assert.Null(result.Exception);
     Assert.Equal(TargetResultCode.Failure, result.ResultCode);
 }
示例#2
0
 public void TestConstructorNullItems()
 {
     Assert.Throws<ArgumentNullException>(() =>
     {
         TargetResult result = new TargetResult(null, TestUtilities.GetStopWithErrorResult());
     }
    );
 }
示例#3
0
 public void TestConstructorWithItems()
 {
     TaskItem item = new TaskItem("foo", "bar.proj");
     TargetResult result = new TargetResult(new TaskItem[] { item }, TestUtilities.GetStopWithErrorResult());
     Assert.Equal(1, result.Items.Length);
     Assert.Equal(item.ItemSpec, result.Items[0].ItemSpec);
     Assert.Equal(TargetResultCode.Failure, result.ResultCode);
 }
示例#4
0
 public void TestConstructorWithException()
 {
     TaskItem item = new TaskItem("foo", "bar.proj");
     TargetResult result = new TargetResult(new TaskItem[] { item }, TestUtilities.GetStopWithErrorResult(new ArgumentException()));
     Assert.Equal(1, result.Items.Length);
     Assert.NotNull(result.Exception);
     Assert.Equal(typeof(ArgumentException), result.Exception.GetType());
     Assert.Equal(TargetResultCode.Failure, result.ResultCode);
 }
示例#5
0
        /// <summary>
        /// Clear cached files from disk.
        /// </summary>
        internal void ClearCachedFiles()
        {
            string resultsDirectory = TargetResult.GetCacheDirectory(_configurationId, "None" /*Does not matter because we just need the directory name not the file*/);

            if (Directory.Exists(resultsDirectory))
            {
                FileUtilities.DeleteDirectoryNoThrow(resultsDirectory, true /*recursive*/);
            }
        }
示例#6
0
        /// <summary>
        /// Adds the results for the specified target to this result collection.
        /// </summary>
        /// <param name="target">The target to which these results apply.</param>
        /// <param name="result">The results for the target.</param>
        public void AddResultsForTarget(string target, TargetResult result)
        {
            ErrorUtilities.VerifyThrowArgumentNull(target, "target");
            ErrorUtilities.VerifyThrowArgumentNull(result, "result");
            if (_resultsByTarget.ContainsKey(target))
            {
                ErrorUtilities.VerifyThrow(_resultsByTarget[target].ResultCode == TargetResultCode.Skipped, "Items already exist for target {0}.", target);
            }

            _resultsByTarget[target] = result;
        }
示例#7
0
        public void TestMergeResultsBad2()
        {
            BuildResult result = new BuildResult(1);
            result["foo"] = new TargetResult(new BuildItem[0] { }, BuildResultCode.Success);

            BuildResult result2 = new BuildResult(1);
            result2["foo"] = new TargetResult(new BuildItem[0] { }, BuildResultCode.Success);

            result.MergeResults(result2);
        }
示例#8
0
 public void TestConstructorWithExceptionNull()
 {
     TaskItem item = new TaskItem("foo", "bar.proj");
     TargetResult result = new TargetResult(new TaskItem[] { item }, TestUtilities.GetStopWithErrorResult());
     Assert.AreEqual(1, result.Items.Length);
     Assert.IsNull(result.Exception);
     Assert.AreEqual(TargetResultCode.Failure, result.ResultCode);
 }
示例#9
0
		public void AddResultsForTarget (string target, TargetResult result)
		{
			ResultsByTarget.Add (target, result);
		}
示例#10
0
		// FIXME: Exception should be caught at caller site.
		bool DoBuildTarget (ProjectTargetInstance target, TargetResult targetResult, InternalBuildArguments args)
		{
			var request = submission.BuildRequest;
	
			// Here we check cancellation (only after TargetStarted event).
			if (args.CheckCancel ()) {
				targetResult.Failure (new BuildAbortedException ("Build has canceled"));
				return false;
			}
			
			try {
				foreach (var child in target.Children) {
					// Evaluate additional target properties
					var tp = child as ProjectPropertyGroupTaskInstance;
					if (tp != null) {
						if (!args.Project.EvaluateCondition (tp.Condition))
							continue;
						foreach (var p in tp.Properties) {
							if (!args.Project.EvaluateCondition (p.Condition))
								continue;
							var value = args.Project.ExpandString (p.Value);
							project.SetProperty (p.Name, value);
						}
						continue;
					}

					var ii = child as ProjectItemGroupTaskInstance;
					if (ii != null) {
						if (!args.Project.EvaluateCondition (ii.Condition))
							continue;
						foreach (var item in ii.Items) {
							if (!args.Project.EvaluateCondition (item.Condition))
								continue;
							project.AddItem (item.ItemType, project.ExpandString (item.Include));
						}
						continue;
					}
					
					var task = child as ProjectTaskInstance;
					if (task != null) {
						current_task = task;
						if (!args.Project.EvaluateCondition (task.Condition)) {
							LogMessageEvent (new BuildMessageEventArgs (string.Format ("Task '{0}' was skipped because condition '{1}' wasn't met.", task.Name, task.Condition), null, null, MessageImportance.Low));
							continue;
						}
						if (!RunBuildTask (target, task, targetResult, args))
							return false;
						continue;
					}

					var onError = child as ProjectOnErrorInstance;
					if (onError != null)
						continue; // evaluated under catch clause.

					throw new NotSupportedException (string.Format ("Unexpected Target element children \"{0}\"", child.GetType ()));
				}
			} catch (Exception ex) {
				// fallback task specified by OnError element
				foreach (var c in target.Children.OfType<ProjectOnErrorInstance> ()) {
					if (!args.Project.EvaluateCondition (c.Condition))
						continue;
					foreach (var fallbackTarget in project.ExpandString (c.ExecuteTargets).Split (';'))
						BuildTargetByName (fallbackTarget, args);
				}
				int line = target.Location != null ? target.Location.Line : 0;
				int col = target.Location != null ? target.Location.Column : 0;
				LogErrorEvent (new BuildErrorEventArgs (null, null, target.FullPath, line, col, 0, 0, ex.Message, null, null));
				targetResult.Failure (ex);
				return false;
			}
			return true;
		}
示例#11
0
			public void AddTargetResult (string targetName, TargetResult targetResult)
			{
				if (!Result.HasResultsForTarget (targetName))
					Result.AddResultsForTarget (targetName, targetResult);
			}
示例#12
0
        /// <summary>
        /// When a target build fails, we don't just stop building that target; we also pop all of the other dependency targets of its 
        /// parent target off the stack. Extract that logic into a standalone method so that it can be used when dealing with targets that 
        /// are skipped-unsuccessful as well as first-time failures. 
        /// </summary>
        private void PopDependencyTargetsOnTargetFailure(TargetEntry topEntry, TargetResult targetResult, ref bool stopProcessingStack)
        {
            if (targetResult.WorkUnitResult.ActionCode == WorkUnitActionCode.Stop)
            {
                // Pop down to our parent, since any other dependencies our parent had should no longer
                // execute.  If we encounter an error target on the way down, also stop since the failure
                // of one error target in a set declared in OnError should not cause the others to stop running.
                while ((!_targetsToBuild.IsEmpty) && (_targetsToBuild.Peek() != topEntry.ParentEntry) && !_targetsToBuild.Peek().ErrorTarget)
                {
                    TargetEntry entry = _targetsToBuild.Pop();
                    entry.LeaveLegacyCallTargetScopes();

                    // This target is no longer actively building (if it was).
                    _requestEntry.RequestConfiguration.ActivelyBuildingTargets.Remove(topEntry.Name);

                    // If we come across an entry which requires us to stop processing (for instance, an aftertarget of the original
                    // CallTarget target) then we need to use that flag, not the one from the top entry.
                    if (entry.StopProcessingOnCompletion)
                    {
                        stopProcessingStack = true;
                    }
                }

                // Mark our parent for error execution
                if (topEntry.ParentEntry != null && topEntry.ParentEntry.State != TargetEntryState.Completed)
                {
                    topEntry.ParentEntry.MarkForError();
                }
            }
        }
示例#13
0
 public void AddResultsForTarget(string target, TargetResult result)
 {
     ResultsByTarget.Add(target, result);
 }
示例#14
0
        /// <summary>
        /// Generate results for the targets requested to be built. Using the TestDataProvider also simulate any
        /// P2P callbacks on the first target. In order to test the cancels there is also functionality to allow the
        /// target execution to wait on a cancel event before exiting
        /// </summary>
        private BuildResult GenerateResults(string[] targetNames)
        {
            bool simulatedResults = false;
            BuildResult result = new BuildResult(_requestEntry.Request);
            foreach (string target in targetNames)
            {
                if (!simulatedResults)
                {
                    SimulateCallBacks();
                    simulatedResults = true;
                }

                // Wait for this to be cancelled
                if (_testDefinition.WaitForCancel)
                {
                    _cancellationToken.WaitHandle.WaitOne();
                    _buildDone.Set();
                    throw new BuildAbortedException();
                }

                if (_testDefinition.ExecutionTime > 0)
                {
                    Thread.Sleep(_testDefinition.ExecutionTime);
                }

                TaskItem[] items = new TaskItem[] { new TaskItem("itemValue", _requestEntry.RequestConfiguration.ProjectFullPath) };
                TargetResult targetResult = new TargetResult(items, TestUtilities.GetSuccessResult());
                result.AddResultsForTarget(target, targetResult);
            }

            _buildDone.Set();
            return result;
        }
示例#15
0
        public void TestTranslationNoException()
        {
            TaskItem item = new TaskItem("foo", "bar.proj");
            item.SetMetadata("a", "b");

            TargetResult result = new TargetResult(new TaskItem[] { item }, TestUtilities.GetStopWithErrorResult());

            ((INodePacketTranslatable)result).Translate(TranslationHelpers.GetWriteTranslator());
            TargetResult deserializedResult = TargetResult.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());

            Assert.Equal(result.ResultCode, deserializedResult.ResultCode);
            Assert.True(TranslationHelpers.CompareCollections(result.Items, deserializedResult.Items, TaskItemComparer.Instance));
            Assert.True(TranslationHelpers.CompareExceptions(result.Exception, deserializedResult.Exception));
        }
示例#16
0
        /// <summary>
        /// Invokes the specified targets using Dev9 behavior.
        /// </summary>
        /// <param name="targets">The targets to build.</param>
        /// <param name="continueOnError">True to continue building the remaining targets if one fails.</param>
        /// <returns>The results for each target.</returns>
        /// <remarks>
        /// Dev9 behavior refers to the following:
        /// 1. The changes made during the calling target up to this point are NOT visible to this target.
        /// 2. The changes made by this target are NOT visible to the calling target.
        /// 3. Changes made by the calling target OVERRIDE changes made by this target.
        /// </remarks>
        async Task<ITargetResult[]> ITargetBuilderCallback.LegacyCallTarget(string[] targets, bool continueOnError, ElementLocation taskLocation)
        {
            List<TargetSpecification> targetToPush = new List<TargetSpecification>();
            ITargetResult[] results = new TargetResult[targets.Length];
            bool originalLegacyCallTargetContinueOnError = _legacyCallTargetContinueOnError;

            _legacyCallTargetContinueOnError = _legacyCallTargetContinueOnError || continueOnError;

            // Our lookup is the one used at the beginning of the calling target.
            Lookup callTargetLookup = _baseLookup;

            // We now record this lookup in the calling target's entry so that it may
            // leave the scope just before it commits its own changes to the base lookup.
            TargetEntry currentTargetEntry = _targetsToBuild.Peek();
            currentTargetEntry.EnterLegacyCallTargetScope(callTargetLookup);

            ITaskBuilder taskBuilder = _componentHost.GetComponent(BuildComponentType.TaskBuilder) as ITaskBuilder;
            try
            {
                // Flag set to true if one of the targets we call fails.
                bool errorResult = false;

                // Now walk through the list of targets, invoking each one.
                for (int i = 0; i < targets.Length; i++)
                {
                    if (_cancellationToken.IsCancellationRequested || errorResult)
                    {
                        results[i] = new TargetResult(new TaskItem[] { }, new WorkUnitResult(WorkUnitResultCode.Skipped, WorkUnitActionCode.Continue, null));
                    }
                    else
                    {
                        targetToPush.Clear();
                        targetToPush.Add(new TargetSpecification(targets[i], taskLocation));

                        // We push the targets one at a time to emulate the original CallTarget behavior.
                        bool pushed = await PushTargets(targetToPush, currentTargetEntry, callTargetLookup, false, true, TargetPushType.Normal);
                        ErrorUtilities.VerifyThrow(pushed, "Failed to push any targets onto the stack.  Target: {0} Current Target: {1}", targets[i], currentTargetEntry.Target.Name);
                        await ProcessTargetStack(taskBuilder);

                        if (!_cancellationToken.IsCancellationRequested)
                        {
                            results[i] = _buildResult[targets[i]];
                            if (results[i].ResultCode == TargetResultCode.Failure)
                            {
                                errorResult = true;
                            }
                        }
                        else
                        {
                            results[i] = new TargetResult(new TaskItem[] { }, new WorkUnitResult(WorkUnitResultCode.Skipped, WorkUnitActionCode.Continue, null));
                        }
                    }
                }
            }
            finally
            {
                // Restore the state of the TargetBuilder to that it was prior to the CallTarget call.
                // Any targets we have pushed on at this point we need to get rid of since we aren't going to process them.
                // If there were normal task errors, standard error handling semantics would have taken care of them.
                // If there was an exception, such as a circular dependency error, items may still be on the stack so we must clear them.
                while (!Object.ReferenceEquals(_targetsToBuild.Peek(), currentTargetEntry))
                {
                    _targetsToBuild.Pop();
                }

                _legacyCallTargetContinueOnError = originalLegacyCallTargetContinueOnError;
                ((IBuildComponent)taskBuilder).ShutdownComponent();
            }

            return results;
        }
示例#17
0
		bool DoBuildTarget (ProjectTargetInstance target, TargetResult targetResult, InternalBuildArguments args)
		{
			var request = submission.BuildRequest;
	
			// Here we check cancellation (only after TargetStarted event).
			if (args.CheckCancel ()) {
				targetResult.Failure (new BuildAbortedException ("Build has canceled"));
				return false;
			}
			
			var propsToRestore = new Dictionary<string,string> ();
			var itemsToRemove = new List<ProjectItemInstance> ();
			try {
				// Evaluate additional target properties
				foreach (var c in target.Children.OfType<ProjectPropertyGroupTaskInstance> ()) {
					if (!args.Project.EvaluateCondition (c.Condition))
						continue;
					foreach (var p in c.Properties) {
						if (!args.Project.EvaluateCondition (p.Condition))
							continue;
						var value = args.Project.ExpandString (p.Value);
						propsToRestore.Add (p.Name, project.GetPropertyValue (value));
						project.SetProperty (p.Name, value);
					}
				}
				
				// Evaluate additional target items
				foreach (var c in target.Children.OfType<ProjectItemGroupTaskInstance> ()) {
					if (!args.Project.EvaluateCondition (c.Condition))
						continue;
					foreach (var item in c.Items) {
						if (!args.Project.EvaluateCondition (item.Condition))
							continue;
						Func<string,ProjectItemInstance> creator = i => new ProjectItemInstance (project, item.ItemType, item.Metadata.Select (m => new KeyValuePair<string,string> (m.Name, m.Value)), i);
						foreach (var ti in project.GetAllItems (item.Include, item.Exclude, creator, creator, s => s == item.ItemType, (ti, s) => ti.SetMetadata ("RecurseDir", s)))
							itemsToRemove.Add (ti);
					}
				}
				
				foreach (var c in target.Children.OfType<ProjectOnErrorInstance> ()) {
					if (!args.Project.EvaluateCondition (c.Condition))
						continue;
					throw new NotImplementedException ();
				}
				
				// run tasks
				foreach (var ti in target.Children.OfType<ProjectTaskInstance> ()) {
					current_task = ti;
					if (!args.Project.EvaluateCondition (ti.Condition)) {
						LogMessageEvent (new BuildMessageEventArgs (string.Format ("Task '{0}' was skipped because condition '{1}' wasn't met.", ti.Name, ti.Condition), null, null, MessageImportance.Low));
						continue;
					}
					if (!RunBuildTask (target, ti, targetResult, args))
						return false;
				}
			} finally {
				// restore temporary property state to the original state.
				foreach (var p in propsToRestore) {
					if (p.Value == string.Empty)
						project.RemoveProperty (p.Key);
					else
						project.SetProperty (p.Key, p.Value);
				}
				foreach (var item in itemsToRemove)
					project.RemoveItem (item);
			}
			return true;
		}
示例#18
0
        /// <summary>
        /// Checks if the target results are as expected.
        /// </summary>
        private void InternalValidateTargetEndResult(TargetResult targetResult, TargetResultCode expectedResultCode, string[] items)
        {
            int foundCount = 0;

            Assert.AreEqual(expectedResultCode, targetResult.ResultCode, "Expected result is not the same as the received result");
            if (items != null)
            {
                foreach (string item in items)
                {
                    bool foundItemValue = false;

                    foreach (ITaskItem i in targetResult.Items)
                    {
                        if (item == i.ItemSpec)
                        {
                            foundItemValue = true;
                            foundCount++;
                            break;
                        }
                    }

                    Assert.IsTrue(foundItemValue, "Item not found in result");
                }

                Assert.IsTrue(foundCount == items.Length, "Total items expected was not the same as what was received.");
            }
        }
示例#19
0
        /// <summary>
        /// Adds the results for the specified target to this result collection.
        /// </summary>
        /// <param name="target">The target to which these results apply.</param>
        /// <param name="result">The results for the target.</param>
        public void AddResultsForTarget(string target, TargetResult result)
        {
            ErrorUtilities.VerifyThrowArgumentNull(target, "target");
            ErrorUtilities.VerifyThrowArgumentNull(result, "result");
            if (_resultsByTarget.ContainsKey(target))
            {
                ErrorUtilities.VerifyThrow(_resultsByTarget[target].ResultCode == TargetResultCode.Skipped, "Items already exist for target {0}.", target);
            }

            _resultsByTarget[target] = result;
        }
示例#20
0
		bool BuildTargetByName (string targetName, InternalBuildArguments args)
		{
			var request = submission.BuildRequest;
			var parameters = submission.BuildManager.OngoingBuildParameters;
			ProjectTargetInstance target;
			TargetResult dummyResult;

			if (args.Result.ResultsByTarget.TryGetValue (targetName, out dummyResult) && dummyResult.ResultCode == TargetResultCode.Success) {
				LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because it was already built successfully.", targetName), null, null, MessageImportance.Low));
				return true; // do not add result.
			}
			
			var targetResult = new TargetResult ();

			// null key is allowed and regarded as blind success(!) (as long as it could retrieve target)
			if (!request.ProjectInstance.Targets.TryGetValue (targetName, out target))
				// FIXME: from MSBuild.exe it is given MSB4057. Can we assign a number too?
				throw new InvalidOperationException (string.Format ("target '{0}' was not found in project '{1}'", targetName, project.FullPath));
			else if (!args.Project.EvaluateCondition (target.Condition)) {
				LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because condition '{1}' was not met.", target.Name, target.Condition), null, null, MessageImportance.Low));
				targetResult.Skip ();
			} else {
				// process DependsOnTargets first.
				foreach (var dep in project.ExpandString (target.DependsOnTargets).Split (';').Select (s => s.Trim ()).Where (s => !string.IsNullOrEmpty (s))) {
					LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' depends on '{1}'.", target.Name, dep), null, null, MessageImportance.Low));
					if (!BuildTargetByName (dep, args)) {
						LogMessageEvent (new BuildMessageEventArgs (string.Format ("Quit target '{0}', as dependency target '{1}' has failed.", target.Name, dep), null, null, MessageImportance.Low));
						return false;
					}
				}
				
				Func<string,ITaskItem> creator = s => new TargetOutputTaskItem () { ItemSpec = s };
			
				event_source.FireTargetStarted (this, new TargetStartedEventArgs ("Target Started", null, target.Name, project.FullPath, target.FullPath));
				try {
					// FIXME: examine in which scenario Inputs/Outputs inconsistency results in errors. Now it rather prevents csproj build.
					/*if (!string.IsNullOrEmpty (target.Inputs) != !string.IsNullOrEmpty (target.Outputs)) {
						targetResult.Failure (new InvalidProjectFileException (target.Location, null, string.Format ("Target {0} has mismatching Inputs and Outputs specification. When one is specified, another one has to be specified too.", targetName), null, null, null));
					} else*/ {
						bool skip = false;
						if (!string.IsNullOrEmpty (target.Inputs)) {
							var inputs = args.Project.GetAllItems (target.Inputs, string.Empty, creator, creator, s => true, (t, s) => {
							});
							if (!inputs.Any ()) {
								LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because there is no input.", target.Name), null, null, MessageImportance.Low));
								skip = true;
							} else {
								var outputs = args.Project.GetAllItems (target.Outputs, string.Empty, creator, creator, s => true, (t, s) => {
								});
								var needsUpdates = GetOlderOutputsThanInputs (inputs, outputs).FirstOrDefault ();
								if (needsUpdates != null)
									LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' needs to be built because new output {1} is needed.", target.Name, needsUpdates.ItemSpec), null, null, MessageImportance.Low));
								else {
									LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because all the outputs are newer than all the inputs.", target.Name), null, null, MessageImportance.Low));
									skip = true;
								}
							}
						}
						if (skip) {
							targetResult.Skip ();
						} else {
							if (DoBuildTarget (target, targetResult, args)) {
								var items = args.Project.GetAllItems (target.Outputs, string.Empty, creator, creator, s => true, (t, s) => {
								});
								targetResult.Success (items);
							}
						}
					}
				} finally {
					event_source.FireTargetFinished (this, new TargetFinishedEventArgs ("Target Finished", null, targetName, project.FullPath, target.FullPath, targetResult.ResultCode != TargetResultCode.Failure));
				}
			}
			args.AddTargetResult (targetName, targetResult);
			
			return targetResult.ResultCode != TargetResultCode.Failure;
		}
示例#21
0
 public void AddResultsForTarget (string target, TargetResult result)
 {
         throw new NotImplementedException ();
 }
示例#22
0
		bool RunBuildTask (ProjectTargetInstance target, ProjectTaskInstance taskInstance, TargetResult targetResult, InternalBuildArguments args)
		{
			var request = submission.BuildRequest;

			var host = request.HostServices == null ? null : request.HostServices.GetHostObject (request.ProjectFullPath, target.Name, taskInstance.Name);
			
			// Create Task instance.
			var factoryIdentityParameters = new Dictionary<string,string> ();
			#if NET_4_5
			factoryIdentityParameters ["MSBuildRuntime"] = taskInstance.MSBuildRuntime;
			factoryIdentityParameters ["MSBuildArchitecture"] = taskInstance.MSBuildArchitecture;
			#endif
			var task = args.BuildTaskFactory.CreateTask (taskInstance.Name, factoryIdentityParameters, this);
			if (task == null)
				throw new InvalidOperationException (string.Format ("TaskFactory {0} returned null Task", args.BuildTaskFactory));
			LogMessageEvent (new BuildMessageEventArgs (string.Format ("Using task {0} from {1}", taskInstance.Name, task.GetType ()), null, null, MessageImportance.Low));
			task.HostObject = host;
			task.BuildEngine = this;
			
			// Prepare task parameters.
			var evaluator = new ExpressionEvaluator (project);
			var evaluatedTaskParams = taskInstance.Parameters.Select (p => new KeyValuePair<string,string> (p.Key, project.ExpandString (evaluator, p.Value)));

			var requiredProps = task.GetType ().GetProperties ()
				.Where (p => p.CanWrite && p.GetCustomAttributes (typeof (RequiredAttribute), true).Any ());
			var missings = requiredProps.Where (p => !evaluatedTaskParams.Any (tp => tp.Key.Equals (p.Name, StringComparison.OrdinalIgnoreCase)));
			if (missings.Any ())
				throw new InvalidOperationException (string.Format ("Task {0} of type {1} is used without specifying mandatory property: {2}",
					taskInstance.Name, task.GetType (), string.Join (", ", missings.Select (p => p.Name).ToArray ())));
			
			foreach (var p in evaluatedTaskParams) {
				switch (p.Key.ToLower ()) {
				case "condition":
				case "continueonerror":
					continue;
				}
				var prop = task.GetType ().GetProperty (p.Key);
				if (prop == null)
					throw new InvalidOperationException (string.Format ("Task {0} does not have property {1}", taskInstance.Name, p.Key));
				if (!prop.CanWrite)
					throw new InvalidOperationException (string.Format ("Task {0} has property {1} but it is read-only.", taskInstance.Name, p.Key));
				if (string.IsNullOrEmpty (p.Value) && !requiredProps.Contains (prop))
					continue;
				try {
					prop.SetValue (task, ConvertTo (p.Value, prop.PropertyType, evaluator), null);
				} catch (Exception ex) {
					throw new InvalidOperationException (string.Format ("Failed to convert '{0}' for property '{1}' of type {2}", p.Value, prop.Name, prop.PropertyType), ex);
				}
			}
			
			// Do execute task.
			bool taskSuccess = false;
			event_source.FireTaskStarted (this, new TaskStartedEventArgs ("Task Started", null, project.FullPath, taskInstance.FullPath, taskInstance.Name));
			try {
				taskSuccess = task.Execute ();
			
				if (!taskSuccess) {
					targetResult.Failure (null);
					if (!ContinueOnError) {
						return false;
					}
				} else {
					// Evaluate task output properties and items.
					foreach (var to in taskInstance.Outputs) {
						if (!project.EvaluateCondition (to.Condition))
							continue;
						var toItem = to as ProjectTaskOutputItemInstance;
						var toProp = to as ProjectTaskOutputPropertyInstance;
						string taskParameter = toItem != null ? toItem.TaskParameter : toProp.TaskParameter;
						var pi = task.GetType ().GetProperty (taskParameter);
						if (pi == null)
							throw new InvalidOperationException (string.Format ("Task {0} does not have property {1} specified as TaskParameter", taskInstance.Name, toItem.TaskParameter));
						if (!pi.CanRead)
							throw new InvalidOperationException (string.Format ("Task {0} has property {1} specified as TaskParameter, but it is write-only", taskInstance.Name, toItem.TaskParameter));
						var value = pi.GetValue (task, null);
						var valueString = ConvertFrom (value);
						if (toItem != null) {
							LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Item {0} from TaskParameter {1}: {2}", toItem.ItemType, toItem.TaskParameter, valueString), null, null, MessageImportance.Low));
							Action<ITaskItem> addItem = i => {
								var metadata = new ArrayList (i.MetadataNames).ToArray ().Cast<string> ().Select (n => new KeyValuePair<string,string> (n, i.GetMetadata (n)));
								args.Project.AddItem (toItem.ItemType, i.ItemSpec, metadata);
							};
							var taskItemArray = value as ITaskItem [];
							if (taskItemArray != null) {
								foreach (var ti in taskItemArray)
									addItem (ti);
							} else {
								var taskItem = value as ITaskItem;
								if (taskItem != null) 
									addItem (taskItem);
								else
									foreach (var item in valueString.Split (';'))
										args.Project.AddItem (toItem.ItemType, item);
							}
						} else {
							LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Property {0} from TaskParameter {1}: {2}", toProp.PropertyName, toProp.TaskParameter, valueString), null, null, MessageImportance.Low));
							args.Project.SetProperty (toProp.PropertyName, valueString);
						}
					}
				}
			} finally {
				event_source.FireTaskFinished (this, new TaskFinishedEventArgs ("Task Finished", null, project.FullPath, taskInstance.FullPath, taskInstance.Name, taskSuccess));
			}
			return true;
		}
示例#23
0
 /// <summary>
 /// Constructor allows you to set all the elements of the object
 /// </summary>
 public TargetDefinition(string name, string inputs, string outputs, string condition, string dependsOnTargets, XmlDocument projectXmlDoc)
 {
     _name = name;
     _inputs = inputs;
     _outputs = outputs;
     _condition = condition;
     _dependsOnTargets = dependsOnTargets;
     _tasks = new Dictionary<string, TaskDefinition>();
     _result = null;
     _targetXmlElement = projectXmlDoc.CreateElement("Target", @"http://schemas.microsoft.com/developer/msbuild/2003");
     GenerateTargetElementXml();
 }
 public void AddResultsForTarget(string target, TargetResult result)
 {
     throw new NotImplementedException();
 }
示例#25
0
 public void TestConstructorNullItems()
 {
     TargetResult result = new TargetResult(null, TestUtilities.GetStopWithErrorResult());
 }