Beispiel #1
0
        void ImportFile(ProjectInfo project, MSBuildEvaluationContext context, MSBuildImport import, string file)
        {
            if (!File.Exists(file))
            {
                return;
            }

            var pref = LoadProject(file);

            project.ReferencedProjects.Add(pref);

            var prefProject = new ProjectInfo {
                Project = pref
            };

            AddImportedProject(project, import, prefProject);

            var refCtx = new MSBuildEvaluationContext(context);

            EvaluateProject(prefProject, refCtx, false);

            foreach (var p in prefProject.Properties)
            {
                p.Value.IsImported         = true;
                project.Properties [p.Key] = p.Value;
            }
        }
        public override void Evaluate(object projectInstance)
        {
            var pi = (ProjectInfo)projectInstance;

            pi.EvaluatedItemsIgnoringCondition.Clear();
            pi.EvaluatedItems.Clear();
            pi.Properties.Clear();
            pi.Imports.Clear();
            pi.Targets.Clear();

            // Unload referenced projects after evaluating to avoid unnecessary unload + load
            var oldRefProjects = pi.ReferencedProjects;

            pi.ReferencedProjects = new List <MSBuildProject> ();

            try {
                var context = new MSBuildEvaluationContext();
                foreach (var p in pi.GlobalProperties)
                {
                    context.SetPropertyValue(p.Key, p.Value);
                    pi.Properties [p.Key] = new PropertyInfo {
                        Name = p.Key, Value = p.Value, FinalValue = p.Value
                    };
                }
                EvaluateProject(pi, context);
            }
            finally {
                foreach (var p in oldRefProjects)
                {
                    UnloadProject(p);
                }
                DisposeImportedProjects(pi);
                pi.ImportedProjects.Clear();
            }
        }
        string[] GetImportFiles(ProjectInfo project, MSBuildEvaluationContext context, MSBuildImport import, string extensionsPath)
        {
            var tempCtx = new MSBuildEvaluationContext(context);
            var mep     = MSBuildProjectService.ToMSBuildPath(null, extensionsPath);

            tempCtx.SetPropertyValue("MSBuildExtensionsPath", mep);
            tempCtx.SetPropertyValue("MSBuildExtensionsPath32", mep);
            tempCtx.SetPropertyValue("MSBuildExtensionsPath64", mep);

            var pr = context.EvaluateString(import.Project);

            project.Imports [import] = pr;

            if (!string.IsNullOrEmpty(import.Condition) && !SafeParseAndEvaluate(project, tempCtx, import.Condition, true))
            {
                return(null);
            }

            var path     = MSBuildProjectService.FromMSBuildPath(project.Project.BaseDirectory, pr);
            var fileName = Path.GetFileName(path);

            if (fileName.IndexOfAny(new [] { '*', '?' }) == -1)
            {
                return(File.Exists(path) ? new [] { path } : null);
            }
            else
            {
                var files = Directory.GetFiles(Path.GetDirectoryName(path), fileName);
                Array.Sort(files);
                return(files);
            }
        }
		public MSBuildEvaluationContext (MSBuildEvaluationContext parentContext)
		{
			this.parentContext = parentContext;
			this.project = parentContext.project;
			this.propertiesWithTransforms = parentContext.propertiesWithTransforms;
			this.propertiesWithTransformsSorted = parentContext.propertiesWithTransformsSorted;
		}
 public MSBuildEvaluationContext(MSBuildEvaluationContext parentContext)
 {
     this.parentContext                  = parentContext;
     this.project                        = parentContext.project;
     this.propertiesWithTransforms       = parentContext.propertiesWithTransforms;
     this.propertiesWithTransformsSorted = parentContext.propertiesWithTransformsSorted;
 }
Beispiel #6
0
        void Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildItemGroup items)
        {
            bool conditionIsTrue = true;

            if (!string.IsNullOrEmpty(items.Condition))
            {
                conditionIsTrue = SafeParseAndEvaluate(project, context, items.Condition);
            }

            foreach (var item in items.Items)
            {
                var include = context.EvaluateString(item.Include);
                var exclude = context.EvaluateString(item.Exclude);

                var it = CreateEvaluatedItem(context, project, project.Project, item, include);

                var trueCond = conditionIsTrue && (string.IsNullOrEmpty(it.Condition) || SafeParseAndEvaluate(project, context, it.Condition));

                var excludeRegex = !string.IsNullOrEmpty(exclude) ? new Regex(ExcludeToRegex(exclude)) : null;

                if (it.Include.IndexOf(';') == -1)
                {
                    AddItem(project, context, item, it, it.Include, excludeRegex, trueCond);
                }
                else
                {
                    foreach (var inc in it.Include.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        AddItem(project, context, item, it, inc, excludeRegex, trueCond);
                    }
                }
            }
        }
 public MSBuildEvaluationContext(MSBuildEvaluationContext parentContext)
 {
     this.parentContext                  = parentContext;
     this.project                        = parentContext.project;
     this.propertiesWithTransforms       = parentContext.propertiesWithTransforms;
     this.propertiesWithTransformsSorted = parentContext.propertiesWithTransformsSorted;
     this.ExistsEvaluationCache          = parentContext.ExistsEvaluationCache;
     this.Log = parentContext.Log;
 }
Beispiel #8
0
 void Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildProperty prop)
 {
     if (string.IsNullOrEmpty(prop.Condition) || SafeParseAndEvaluate(project, context, prop.Condition, true))
     {
         var val = context.EvaluateString(prop.Value);
         project.Properties [prop.Name] = new PropertyInfo {
             Name = prop.Name, Value = prop.Value, FinalValue = val
         };
         context.SetPropertyValue(prop.Name, val);
     }
 }
Beispiel #9
0
 void Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildChoose choose, bool evalItems)
 {
     foreach (var op in choose.GetOptions())
     {
         if (op.IsOtherwise || SafeParseAndEvaluate(project, context, op.Condition, true))
         {
             EvaluateObjects(project, context, op.GetAllObjects(), evalItems);
             break;
         }
     }
 }
Beispiel #10
0
        void Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildPropertyGroup group)
        {
            if (!string.IsNullOrEmpty(group.Condition) && !SafeParseAndEvaluate(project, context, group.Condition, true))
            {
                return;
            }

            foreach (var prop in group.GetProperties())
            {
                Evaluate(project, context, prop);
            }
        }
Beispiel #11
0
        void Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildImportGroup imports, bool evalItems)
        {
            if (!string.IsNullOrEmpty(imports.Condition) && !SafeParseAndEvaluate(project, context, imports.Condition, true))
            {
                return;
            }

            foreach (var item in imports.Imports)
            {
                Evaluate(project, context, item, evalItems);
            }
        }
        void Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildImport import, bool evalItems)
        {
            if (evalItems)
            {
                // Properties have already been evaluated
                // Don't evaluate properties, only items and other elements
                foreach (var p in GetImportedProjects(project, import))
                {
                    EvaluateProject(p, new MSBuildEvaluationContext(context), true);

                    foreach (var it in p.EvaluatedItems)
                    {
                        it.IsImported = true;
                        project.EvaluatedItems.Add(it);
                    }
                    foreach (var it in p.EvaluatedItemsIgnoringCondition)
                    {
                        it.IsImported = true;
                        project.EvaluatedItemsIgnoringCondition.Add(it);
                    }
                    foreach (var t in p.Targets)
                    {
                        t.IsImported = true;
                        project.Targets.Add(t);
                    }
                    foreach (var cp in p.ConditionedProperties)
                    {
                        foreach (var v in cp.Value)
                        {
                            project.ConditionedProperties.AddProperty(cp.Key, v);
                        }
                    }
                }
                return;
            }

            // For some reason, Mono can have several extension paths, so we need to try each of them
            foreach (var ep in MSBuildEvaluationContext.GetApplicableExtensionsPaths())
            {
                var files = GetImportFiles(project, context, import, ep);
                if (files == null || files.Length == 0)
                {
                    continue;
                }
                foreach (var f in files)
                {
                    ImportFile(project, context, import, f);
                }
                return;
            }

            // No import was found
        }
        static MSBuildItemEvaluated CreateEvaluatedItem(MSBuildEvaluationContext context, MSBuildProject project, MSBuildItem sourceItem, string include)
        {
            var it = new MSBuildItemEvaluated(project, sourceItem.Name, sourceItem.Include, include);
            var md = new Dictionary <string, MSBuildPropertyEvaluated> ();

            foreach (var c in sourceItem.Metadata.GetProperties())
            {
                md [c.Name] = new MSBuildPropertyEvaluated(project, c.Name, c.Value, context.EvaluateString(c.Value));
            }
            ((MSBuildPropertyGroupEvaluated)it.Metadata).SetProperties(md);
            it.SourceItem = sourceItem;
            it.Condition  = sourceItem.Condition;
            return(it);
        }
Beispiel #14
0
 static void AddItem(ProjectInfo project, MSBuildEvaluationContext context, MSBuildItem item, MSBuildItemEvaluated it, string include, Regex excludeRegex, bool trueCond)
 {
     if (include.IndexOf('*') != -1)
     {
         var path = include;
         if (path == "**" || path.EndsWith("\\**"))
         {
             path = path + "/*";
         }
         var subpath = path.Split('\\');
         foreach (var eit in ExpandWildcardFilePath(project, project.Project, context, item, project.Project.BaseDirectory, FilePath.Null, false, subpath, 0))
         {
             if (excludeRegex != null && excludeRegex.IsMatch(eit.Include))
             {
                 continue;
             }
             project.EvaluatedItemsIgnoringCondition.Add(eit);
             if (trueCond)
             {
                 project.EvaluatedItems.Add(eit);
             }
         }
     }
     else if (include != it.Include)
     {
         if (excludeRegex != null && excludeRegex.IsMatch(include))
         {
             return;
         }
         it = CreateEvaluatedItem(context, project, project.Project, item, include);
         project.EvaluatedItemsIgnoringCondition.Add(it);
         if (trueCond)
         {
             project.EvaluatedItems.Add(it);
         }
     }
     else
     {
         if (excludeRegex != null && excludeRegex.IsMatch(include))
         {
             return;
         }
         project.EvaluatedItemsIgnoringCondition.Add(it);
         if (trueCond)
         {
             project.EvaluatedItems.Add(it);
         }
     }
 }
 void Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildTarget target)
 {
     if (SafeParseAndEvaluate(project, context, target.Condition))
     {
         var newTarget = new MSBuildTarget(target.Name, target.Tasks);
         newTarget.AfterTargets         = context.EvaluateString(target.AfterTargets);
         newTarget.Inputs               = context.EvaluateString(target.Inputs);
         newTarget.Outputs              = context.EvaluateString(target.Outputs);
         newTarget.BeforeTargets        = context.EvaluateString(target.BeforeTargets);
         newTarget.DependsOnTargets     = context.EvaluateString(target.DependsOnTargets);
         newTarget.Returns              = context.EvaluateString(target.Returns);
         newTarget.KeepDuplicateOutputs = context.EvaluateString(target.KeepDuplicateOutputs);
         project.Targets.Add(newTarget);
     }
 }
Beispiel #16
0
        void EvaluateProject(ProjectInfo pi, MSBuildEvaluationContext context)
        {
            context.InitEvaluation(pi.Project);
            var objects = pi.Project.GetAllObjects();

            // If there is a .user project file load it using a fake import item added at the end of the objects list
            if (File.Exists(pi.Project.FileName + ".user"))
            {
                objects = objects.Concat(new MSBuildImport {
                    Project = pi.Project.FileName + ".user"
                });
            }

            EvaluateObjects(pi, context, objects, false);
            EvaluateObjects(pi, context, objects, true);
        }
        public void Dump()
        {
            var allProps = new HashSet <string> ();

            MSBuildEvaluationContext ctx = this;

            while (ctx != null)
            {
                allProps.UnionWith(ctx.properties.Select(p => p.Key));
                ctx = ctx.parentContext;
            }
            foreach (var v in allProps.OrderBy(s => s))
            {
                Log.LogMessage(string.Format($"{v,-30} = {GetPropertyValue (v)}"));
            }
        }
Beispiel #18
0
        static bool SafeParseAndEvaluate(ProjectInfo project, MSBuildEvaluationContext context, string condition, bool collectConditionedProperties = false)
        {
            try {
                if (String.IsNullOrEmpty(condition))
                {
                    return(true);
                }

                try {
                    ConditionExpression ce = ConditionParser.ParseCondition(condition);

                    if (!ce.CanEvaluateToBool(context))
                    {
                        throw new InvalidProjectFileException(String.Format("Can not evaluate \"{0}\" to bool.", condition));
                    }

                    if (collectConditionedProperties)
                    {
                        ce.CollectConditionProperties(project.ConditionedProperties);
                    }

                    return(ce.BoolEvaluate(context));
                } catch (ExpressionParseException epe) {
                    throw new InvalidProjectFileException(
                              String.Format("Unable to parse condition \"{0}\" : {1}", condition, epe.Message),
                              epe);
                } catch (ExpressionEvaluationException epe) {
                    throw new InvalidProjectFileException(
                              String.Format("Unable to evaluate condition \"{0}\" : {1}", condition, epe.Message),
                              epe);
                }
            }
            catch {
                // The condition is likely to be invalid
                return(false);
            }
        }
Beispiel #19
0
 void EvaluateObjects(ProjectInfo pi, MSBuildEvaluationContext context, IEnumerable <MSBuildObject> objects, bool evalItems)
 {
     foreach (var ob in objects)
     {
         if (evalItems)
         {
             if (ob is MSBuildItemGroup)
             {
                 Evaluate(pi, context, (MSBuildItemGroup)ob);
             }
             else if (ob is MSBuildTarget)
             {
                 Evaluate(pi, context, (MSBuildTarget)ob);
             }
         }
         else
         {
             if (ob is MSBuildPropertyGroup)
             {
                 Evaluate(pi, context, (MSBuildPropertyGroup)ob);
             }
         }
         if (ob is MSBuildImportGroup)
         {
             Evaluate(pi, context, (MSBuildImportGroup)ob, evalItems);
         }
         else if (ob is MSBuildImport)
         {
             Evaluate(pi, context, (MSBuildImport)ob, evalItems);
         }
         else if (ob is MSBuildChoose)
         {
             Evaluate(pi, context, (MSBuildChoose)ob, evalItems);
         }
     }
 }
		void EvaluateProject (ProjectInfo pi, MSBuildEvaluationContext context, bool evalItems)
		{
			context.InitEvaluation (pi.Project);
			EvaluateObjects (pi, context, pi.Project.GetAllObjects (), evalItems);
		}
		static void AddItem (ProjectInfo project, MSBuildEvaluationContext context, MSBuildItem item, MSBuildItemEvaluated it, string include, Regex excludeRegex, bool trueCond)
		{
			// Don't add the result from any item that has an empty include. MSBuild never returns those.
			if (include == string.Empty)
				return;
			
			if (IsIncludeTransform (include)) {
				// This is a transform
				List<MSBuildItemEvaluated> evalItems;
				var transformExp = include.Substring (2, include.Length - 3);
				if (ExecuteTransform (project, context, item, transformExp, out evalItems)) {
					foreach (var newItem in evalItems) {
						project.EvaluatedItemsIgnoringCondition.Add (newItem);
						if (trueCond)
							project.EvaluatedItems.Add (newItem);
					}
				}
			} else if (include.IndexOf ('*') != -1) {
				var path = include;
				if (path == "**" || path.EndsWith ("\\**"))
					path = path + "/*";
				var subpath = path.Split ('\\');
				foreach (var eit in ExpandWildcardFilePath (project, project.Project, context, item, project.Project.BaseDirectory, FilePath.Null, false, subpath, 0)) {
					if (excludeRegex != null && excludeRegex.IsMatch (eit.Include))
						continue;
					project.EvaluatedItemsIgnoringCondition.Add (eit);
					if (trueCond)
						project.EvaluatedItems.Add (eit);
				}
			} else if (include != it.Include) {
				if (excludeRegex != null && excludeRegex.IsMatch (include))
					return;
				it = CreateEvaluatedItem (context, project, project.Project, item, include);
				project.EvaluatedItemsIgnoringCondition.Add (it);
				if (trueCond)
					project.EvaluatedItems.Add (it);
			} else {
				if (excludeRegex != null && excludeRegex.IsMatch (include))
					return;
				project.EvaluatedItemsIgnoringCondition.Add (it);
				if (trueCond)
					project.EvaluatedItems.Add (it);
			}
		}
		internal static bool ExecuteStringTransform (List<MSBuildItemEvaluated> evaluatedItemsCollection, MSBuildEvaluationContext context, string transformExp, out string items)
		{
			// This method works mostly like ExecuteTransform, but instead of returning a list of items, it returns a string as result.
			// Since there is no need to create full blown evaluated items, it can be more efficient than ExecuteTransform.

			items = "";

			string itemName, expression, itemFunction; object [] itemFunctionArgs;
			if (!ParseTransformExpression (context, transformExp, out itemName, out expression, out itemFunction, out itemFunctionArgs))
				return false;

			var transformItems = evaluatedItemsCollection.Where (i => i.Name == itemName).ToArray ();
			if (itemFunction != null) {
				string result; bool ignoreMetadata;
				if (ExecuteSummaryItemFunction (transformItems, itemFunction, itemFunctionArgs, out result)) {
					// The item function returns a value. Just return it.
					items = result;
					return true;
				} else if (ExecuteTransformItemListFunction (ref transformItems, itemFunction, itemFunctionArgs, out ignoreMetadata)) {
					var sb = new StringBuilder ();
					for (int n = 0; n < transformItems.Length; n++) {
						if (n > 0)
							sb.Append (';');
						sb.Append (transformItems[n].Include);
					}	
					items = sb.ToString ();
					return true;
				}
			}

			var sbi = new StringBuilder ();

			int count = 0;
			foreach (var eit in transformItems) {
				context.SetItemContext (eit.Include, null, eit.Metadata);
				try {
					string evaluatedInclude; bool skip;
					if (itemFunction != null && ExecuteTransformIncludeItemFunction (context, eit, itemFunction, itemFunctionArgs, out evaluatedInclude, out skip)) {
						if (skip) continue;
					} else if (expression != null)
						evaluatedInclude = context.EvaluateString (expression);
					else
						evaluatedInclude = eit.Include;

					if (count++ > 0)
						sbi.Append (';');
					sbi.Append (evaluatedInclude);

				} finally {
					context.ClearItemContext ();
				}
			}
			items = sbi.ToString ();
			return true;
		}
Beispiel #23
0
 void EvaluateProject(ProjectInfo pi, MSBuildEvaluationContext context)
 {
     context.InitEvaluation(pi.Project);
     EvaluateObjects(pi, context, pi.Project.GetAllObjects(), false);
     EvaluateObjects(pi, context, pi.Project.GetAllObjects(), true);
 }
 public MSBuildEvaluationContext(MSBuildEvaluationContext parentContext)
 {
     this.parentContext = parentContext;
     this.project       = parentContext.project;
 }
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildTarget target)
		{
			bool condIsTrue = SafeParseAndEvaluate (project, context, target.Condition);
			var newTarget = new MSBuildTarget (target.Name, target.Tasks);
			newTarget.AfterTargets = context.EvaluateString (target.AfterTargets);
			newTarget.Inputs = context.EvaluateString (target.Inputs);
			newTarget.Outputs = context.EvaluateString (target.Outputs);
			newTarget.BeforeTargets = context.EvaluateString (target.BeforeTargets);
			newTarget.DependsOnTargets = context.EvaluateString (target.DependsOnTargets);
			newTarget.Returns = context.EvaluateString (target.Returns);
			newTarget.KeepDuplicateOutputs = context.EvaluateString (target.KeepDuplicateOutputs);
			project.TargetsIgnoringCondition.Add (newTarget);
			if (condIsTrue)
				project.Targets.Add (newTarget);
		}
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildItemGroup items)
		{
			bool conditionIsTrue = true;

			if (!string.IsNullOrEmpty (items.Condition))
				conditionIsTrue = SafeParseAndEvaluate (project, context, items.Condition);

			foreach (var item in items.Items) {

				var include = context.EvaluateString (item.Include);
				var exclude = context.EvaluateString (item.Exclude);

				var it = CreateEvaluatedItem (context, project, project.Project, item, include);

				var trueCond = conditionIsTrue && (string.IsNullOrEmpty (it.Condition) || SafeParseAndEvaluate (project, context, it.Condition));

				var excludeRegex = !string.IsNullOrEmpty (exclude) ? new Regex (ExcludeToRegex (exclude)) : null;

				if (it.Include.IndexOf (';') == -1)
					AddItem (project, context, item, it, it.Include, excludeRegex, trueCond);
				else {
					foreach (var inc in it.Include.Split (new [] {';'}, StringSplitOptions.RemoveEmptyEntries))
						AddItem (project, context, item, it, inc, excludeRegex, trueCond);
				}
			}
		}
		void EvaluateObjects (ProjectInfo pi, MSBuildEvaluationContext context, IEnumerable<MSBuildObject> objects, bool evalItems)
		{
			foreach (var ob in objects) {
				if (evalItems) {
					if (ob is MSBuildItemGroup)
						Evaluate (pi, context, (MSBuildItemGroup)ob);
					else if (ob is MSBuildTarget)
						Evaluate (pi, context, (MSBuildTarget)ob);
				} else {
					if (ob is MSBuildPropertyGroup)
						Evaluate (pi, context, (MSBuildPropertyGroup)ob);
				}
				if (ob is MSBuildImportGroup)
					Evaluate (pi, context, (MSBuildImportGroup)ob, evalItems);
				else if (ob is MSBuildImport)
					Evaluate (pi, context, (MSBuildImport)ob, evalItems);
				else if (ob is MSBuildChoose)
					Evaluate (pi, context, (MSBuildChoose)ob, evalItems);
			}
		}
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildPropertyGroup group)
		{
			if (!string.IsNullOrEmpty (group.Condition) && !SafeParseAndEvaluate (project, context, group.Condition, true))
				return;

			foreach (var prop in group.GetProperties ())
				Evaluate (project, context, prop);
		}
		void EvaluateProject (ProjectInfo pi, MSBuildEvaluationContext context, bool evalItems)
		{
			// XmlDocument is not thread safe, so we need to lock while evaluating
			context.InitEvaluation (pi.Project);
			EvaluateObjects (pi, context, pi.Project.GetAllObjects (), evalItems);
		}
		void EvaluateProject (ProjectInfo pi, MSBuildEvaluationContext context)
		{
			context.InitEvaluation (pi.Project);
			EvaluateObjects (pi, context, pi.Project.GetAllObjects (), false);
			EvaluateObjects (pi, context, pi.Project.GetAllObjects (), true);
		}
		public override void Evaluate (object projectInstance)
		{
			var pi = (ProjectInfo) projectInstance;

			pi.EvaluatedItemsIgnoringCondition.Clear ();
			pi.EvaluatedItems.Clear ();
			pi.Properties.Clear ();
			pi.Imports.Clear ();
			pi.Targets.Clear ();
			pi.TargetsIgnoringCondition.Clear ();

			// Unload referenced projects after evaluating to avoid unnecessary unload + load
			var oldRefProjects = pi.ReferencedProjects;
			pi.ReferencedProjects = new List<MSBuildProject> ();

			try {
				var context = new MSBuildEvaluationContext ();
				foreach (var p in pi.GlobalProperties) {
					context.SetPropertyValue (p.Key, p.Value);
					pi.Properties [p.Key] = new PropertyInfo { Name = p.Key, Value = p.Value, FinalValue = p.Value };
				}
				EvaluateProject (pi, context);
			}
			finally {
				foreach (var p in oldRefProjects)
					UnloadProject (p);
				DisposeImportedProjects (pi);
				pi.ImportedProjects.Clear ();
			}
		}
		void EvaluateProject (ProjectInfo pi, MSBuildEvaluationContext context)
		{
			context.InitEvaluation (pi.Project);
			var objects = pi.Project.GetAllObjects ();

			// If there is a .user project file load it using a fake import item added at the end of the objects list
			if (File.Exists (pi.Project.FileName + ".user"))
				objects = objects.Concat (new MSBuildImport {Project = pi.Project.FileName + ".user" });

			EvaluateObjects (pi, context, objects, false);
			EvaluateObjects (pi, context, objects, true);

			// Once items have been evaluated, we need to re-evaluate properties that contain item transformations
			// (or that contain references to properties that have transformations).

			foreach (var propName in context.GetPropertiesNeedingTransformEvaluation ()) {
				PropertyInfo prop;
				if (pi.Properties.TryGetValue (propName, out prop)) {
					// Execute the transformation
					prop.FinalValue = context.EvaluateWithItems (prop.FinalValue, pi.EvaluatedItems);

					// Set the resulting value back to the context, so other properties depending on this
					// one will get the new value when re-evaluated.
					context.SetPropertyValue (propName, prop.FinalValue);
				}
			}
		}
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildProperty prop)
		{
			if (string.IsNullOrEmpty (prop.Condition) || SafeParseAndEvaluate (project, context, prop.Condition, true)) {
				bool needsItemEvaluation;
				var val = context.Evaluate (prop.UnevaluatedValue, out needsItemEvaluation);
				if (needsItemEvaluation)
					context.SetPropertyNeedsTransformEvaluation (prop.Name);
				project.Properties [prop.Name] = new PropertyInfo { Name = prop.Name, Value = prop.UnevaluatedValue, FinalValue = val };
				context.SetPropertyValue (prop.Name, val);
			}
		}
 void Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildTarget target)
 {
     // TODO NPM
     project.Targets.Add(target);
 }
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildTarget target)
		{
			// TODO NPM
			project.Targets.Add (target);
		}
		static bool SafeParseAndEvaluate (ProjectInfo project, MSBuildEvaluationContext context, string condition, bool collectConditionedProperties = false)
		{
			try {
				if (String.IsNullOrEmpty (condition))
					return true;

				try {
					ConditionExpression ce = ConditionParser.ParseCondition (condition);

					if (!ce.CanEvaluateToBool (context))
						throw new InvalidProjectFileException (String.Format ("Can not evaluate \"{0}\" to bool.", condition));

					if (collectConditionedProperties)
						ce.CollectConditionProperties (project.ConditionedProperties);

					return ce.BoolEvaluate (context);
				} catch (ExpressionParseException epe) {
					throw new InvalidProjectFileException (
						String.Format ("Unable to parse condition \"{0}\" : {1}", condition, epe.Message),
						epe);
				} catch (ExpressionEvaluationException epe) {
					throw new InvalidProjectFileException (
						String.Format ("Unable to evaluate condition \"{0}\" : {1}", condition, epe.Message),
						epe);
				}
			}
			catch {
				// The condition is likely to be invalid
				return false;
			}
		}
		static MSBuildItemEvaluated CreateEvaluatedItem (MSBuildEvaluationContext context, ProjectInfo pinfo, MSBuildProject project, MSBuildItem sourceItem, string include)
		{
			var it = new MSBuildItemEvaluated (project, sourceItem.Name, sourceItem.Include, include);
			var md = new Dictionary<string,IMSBuildPropertyEvaluated> ();
			foreach (var c in sourceItem.Metadata.GetProperties ()) {
				if (string.IsNullOrEmpty (c.Condition) || SafeParseAndEvaluate (pinfo, context, c.Condition, true))
					md [c.Name] = new MSBuildPropertyEvaluated (project, c.Name, c.Value, context.EvaluateString (c.Value));
			}
			((MSBuildPropertyGroupEvaluated)it.Metadata).SetProperties (md);
			it.SourceItem = sourceItem;
			it.Condition = sourceItem.Condition;
			return it;
		}
		static bool ExecuteTransformIncludeItemFunction (MSBuildEvaluationContext context, MSBuildItemEvaluated item, string itemFunction, object [] itemFunctionArgs, out string evaluatedInclude, out bool skip)
		{
			evaluatedInclude = null;
			skip = false;

			switch (itemFunction) {
			case "DirectoryName":
				var path = MSBuildProjectService.FromMSBuildPath (context.Project.BaseDirectory, item.Include);
				evaluatedInclude = Path.GetDirectoryName (path);
				return true;
			case "Metadata":
				if (itemFunctionArgs.Length != 1)
					return false;
				var p = item.Metadata.GetProperty (itemFunctionArgs [0].ToString ());
				if (p == null) {
					skip = true;
					return true;
				} else {
					evaluatedInclude = p.Value;
					return true;
				}
			}
			if (knownStringItemFunctions.Contains (itemFunction)) {
				object res;
				if (context.EvaluateMember (itemFunction, typeof (string), itemFunction, item.Include, itemFunctionArgs, out res)) {
					evaluatedInclude = res.ToString ();
					return true;
				}
			}
			return false;
		}
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildProperty prop)
		{
			if (string.IsNullOrEmpty (prop.Condition) || SafeParseAndEvaluate (project, context, prop.Condition, true)) {
				var val = context.EvaluateString (prop.Value);
				project.Properties [prop.Name] = new PropertyInfo { Name = prop.Name, Value = prop.Value, FinalValue = val };
				context.SetPropertyValue (prop.Name, val);
			}
		}
Beispiel #40
0
 void EvaluateProject(ProjectInfo pi, MSBuildEvaluationContext context, bool evalItems)
 {
     // XmlDocument is not thread safe, so we need to lock while evaluating
     context.InitEvaluation(pi.Project);
     EvaluateObjects(pi, context, pi.Project.GetAllObjects(), evalItems);
 }
		MSBuildItemEvaluated Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildItem item)
		{
			return CreateEvaluatedItem (context, project, project.Project, item, context.EvaluateString (item.Include));
		}
		static bool ParseTransformExpression (MSBuildEvaluationContext context, string include, out string itemName, out string expression, out string itemFunction, out object [] itemFunctionArgs)
		{
			// This method parses the transforms and extracts: the name of the item list to transform, the whole transform expression (or null if there isn't). If the expression can be
			// parsed as an item funciton, then it returns the function name and the list of arguments. Otherwise those parameters are null.
		
			expression = null;
			itemFunction = null;
			itemFunctionArgs = null;
		
			int i = include.IndexOf ("->", StringComparison.Ordinal);
			if (i == -1) {
				itemName = include.Trim ();
				return itemName.Length > 0;
			}
			itemName = include.Substring (0, i).Trim ();
			if (itemName.Length == 0)
				return false;
			
			expression = include.Substring (i + 2).Trim ();
			if (expression.Length > 1 && expression[0]=='\'' && expression[expression.Length - 1] == '\'') {
				expression = expression.Substring (1, expression.Length - 2);
				return true;
			}
			i = expression.IndexOf ('(');
			if (i == -1)
				return true;

			var func = expression.Substring (0, i).Trim ();
			if (knownItemFunctions.Contains (func)) {
				itemFunction = func;
				i++;
				context.EvaluateParameters (expression, ref i, out itemFunctionArgs);
				return true;
			}
			return true;
		}
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildImport import, bool evalItems)
		{
			if (evalItems) {
				// Properties have already been evaluated
				// Don't evaluate properties, only items and other elements
				foreach (var p in GetImportedProjects (project, import)) {
					
					EvaluateProject (p, new MSBuildEvaluationContext (context), true);

					foreach (var it in p.EvaluatedItems) {
						it.IsImported = true;
						project.EvaluatedItems.Add (it);
					}
					foreach (var it in p.EvaluatedItemsIgnoringCondition) {
						it.IsImported = true;
						project.EvaluatedItemsIgnoringCondition.Add (it);
					}
					foreach (var t in p.Targets) {
						t.IsImported = true;
						project.Targets.Add (t);
					}
					foreach (var t in p.TargetsIgnoringCondition) {
						t.IsImported = true;
						project.TargetsIgnoringCondition.Add (t);
					}
					project.ConditionedProperties.Append (p.ConditionedProperties);
				}
				return;
            }

			// For some reason, Mono can have several extension paths, so we need to try each of them
			foreach (var ep in MSBuildEvaluationContext.GetApplicableExtensionsPaths ()) {
				var files = GetImportFiles (project, context, import, ep);
				if (files == null || files.Length == 0)
					continue;
				foreach (var f in files)
					ImportFile (project, context, import, f);
				return;
			}

			// No import was found
		}
		static bool ExecuteTransform (ProjectInfo project, MSBuildEvaluationContext context, MSBuildItem item, string transformExp, out List<MSBuildItemEvaluated> items)
		{
			bool ignoreMetadata = false;

			items = new List<MSBuildItemEvaluated> ();
			string itemName, expression, itemFunction; object [] itemFunctionArgs;

			// This call parses the transforms and extracts: the name of the item list to transform, the whole transform expression (or null if there isn't). If the expression can be
			// parsed as an item funciton, then it returns the function name and the list of arguments. Otherwise those parameters are null.
			if (!ParseTransformExpression (context, transformExp, out itemName, out expression, out itemFunction, out itemFunctionArgs))
				return false;

			// Get the items mathing the referenced item list
			var transformItems = project.EvaluatedItems.Where (i => i.Name == itemName).ToArray ();

			if (itemFunction != null) {
				// First of all, try to execute the function as a summary function, that is, a function that returns a single value for
				// the whole list (such as Count).
				// After that, try executing as a list transformation function: a function that changes the order or filters out items from the list.

				string result;
				if (ExecuteSummaryItemFunction (transformItems, itemFunction, itemFunctionArgs, out result)) {
					// The item function returns a value. Just create an item with that value
					var newItem = new MSBuildItemEvaluated (project.Project, item.Name, item.Include, result);
					project.EvaluatedItemsIgnoringCondition.Add (newItem);
					items.Add (newItem);
					return true;
				} else if (ExecuteTransformItemListFunction (ref transformItems, itemFunction, itemFunctionArgs, out ignoreMetadata)) {
					expression = null;
					itemFunction = null;
				}
			}

			foreach (var eit in transformItems) {
				// Some item functions cause the erasure of metadata. Take that into account now.
				context.SetItemContext (eit.Include, null, ignoreMetadata || item == null ? null : eit.Metadata);
				try {
					// If there is a function that transforms the include of the item, it needs to be applied now. Otherwise just use the transform expression
					// as include, or the transformed item include if there is no expression.

					string evaluatedInclude; bool skip;
					if (itemFunction != null && ExecuteTransformIncludeItemFunction (context, eit, itemFunction, itemFunctionArgs, out evaluatedInclude, out skip)) {
						if (skip) continue;
					} else if (expression != null)
						evaluatedInclude = context.EvaluateString (expression);
					else
						evaluatedInclude = eit.Include;

					var newItem = new MSBuildItemEvaluated (project.Project, item.Name, item.Include, evaluatedInclude);
					if (!ignoreMetadata) {
						var md = new Dictionary<string, IMSBuildPropertyEvaluated> ();
						// Add metadata from the evaluated item
						var col = (MSBuildPropertyGroupEvaluated)eit.Metadata;
						foreach (var p in col.GetRegisteredProperties ()) {
							md [p.Name] = new MSBuildPropertyEvaluated (project.Project, p.Name, p.UnevaluatedValue, p.Value);
						}
						// Now override metadata from the new item definition
						foreach (var c in item.Metadata.GetProperties ()) {
							if (string.IsNullOrEmpty (c.Condition) || SafeParseAndEvaluate (project, context, c.Condition, true))
								md [c.Name] = new MSBuildPropertyEvaluated (project.Project, c.Name, c.Value, context.EvaluateString (c.Value));
						}
						((MSBuildPropertyGroupEvaluated)newItem.Metadata).SetProperties (md);
					}
					newItem.SourceItem = item;
					newItem.Condition = item.Condition;
					items.Add (newItem);
				} finally {
					context.ClearItemContext ();
				}
			}
			return true;
		}
		string[] GetImportFiles (ProjectInfo project, MSBuildEvaluationContext context, MSBuildImport import, string extensionsPath)
		{
			if (extensionsPath != null) {
				var tempCtx = new MSBuildEvaluationContext (context);
				var mep = MSBuildProjectService.ToMSBuildPath (null, extensionsPath);
				tempCtx.SetPropertyValue ("MSBuildExtensionsPath", mep);
				tempCtx.SetPropertyValue ("MSBuildExtensionsPath32", mep);
				tempCtx.SetPropertyValue ("MSBuildExtensionsPath64", mep);
				context = tempCtx;
			}

			var pr = context.EvaluateString (import.Project);
			project.Imports [import] = pr;

			if (!string.IsNullOrEmpty (import.Condition) && !SafeParseAndEvaluate (project, context, import.Condition, true))
				return null;

			var path = MSBuildProjectService.FromMSBuildPath (project.Project.BaseDirectory, pr);
			var fileName = Path.GetFileName (path);

			if (fileName.IndexOfAny (new [] { '*', '?' }) == -1) {
				return File.Exists (path) ? new [] { path } : null;
			}
			else {
				var files = Directory.GetFiles (Path.GetDirectoryName (path), fileName);
				Array.Sort (files);
				return files;
			}
		}
Beispiel #46
0
        static IEnumerable <MSBuildItemEvaluated> ExpandWildcardFilePath(ProjectInfo pinfo, MSBuildProject project, MSBuildEvaluationContext context, MSBuildItem sourceItem, FilePath basePath, FilePath baseRecursiveDir, bool recursive, string[] filePath, int index)
        {
            var res = Enumerable.Empty <MSBuildItemEvaluated> ();

            if (index >= filePath.Length)
            {
                return(res);
            }

            var path = filePath [index];

            if (path == "..")
            {
                return(ExpandWildcardFilePath(pinfo, project, context, sourceItem, basePath.ParentDirectory, baseRecursiveDir, recursive, filePath, index + 1));
            }

            if (path == ".")
            {
                return(ExpandWildcardFilePath(pinfo, project, context, sourceItem, basePath, baseRecursiveDir, recursive, filePath, index + 1));
            }

            if (!Directory.Exists(basePath))
            {
                return(res);
            }

            if (path == "**")
            {
                // if this is the last component of the path, there isn't any file specifier, so there is no possible match
                if (index + 1 >= filePath.Length)
                {
                    return(res);
                }

                // If baseRecursiveDir has already been set, don't overwrite it.
                if (baseRecursiveDir.IsNullOrEmpty)
                {
                    baseRecursiveDir = basePath;
                }

                return(ExpandWildcardFilePath(pinfo, project, context, sourceItem, basePath, baseRecursiveDir, true, filePath, index + 1));
            }

            if (recursive)
            {
                // Recursive search. Try to match the remaining subpath in all subdirectories.
                foreach (var dir in Directory.GetDirectories(basePath))
                {
                    res = res.Concat(ExpandWildcardFilePath(pinfo, project, context, sourceItem, dir, baseRecursiveDir, true, filePath, index));
                }
            }

            if (index == filePath.Length - 1)
            {
                // Last path component. It has to be a file specifier.
                string baseDir = basePath.ToRelative(project.BaseDirectory).ToString().Replace('/', '\\');
                if (baseDir == ".")
                {
                    baseDir = "";
                }
                else if (!baseDir.EndsWith("\\", StringComparison.Ordinal))
                {
                    baseDir += '\\';
                }
                var recursiveDir = baseRecursiveDir.IsNullOrEmpty ? FilePath.Null : basePath.ToRelative(baseRecursiveDir);
                res = res.Concat(Directory.GetFiles(basePath, path).Select(f => {
                    context.SetItemContext(f, recursiveDir);
                    var ev = baseDir + Path.GetFileName(f);
                    return(CreateEvaluatedItem(context, pinfo, project, sourceItem, ev));
                }));
            }
            else
            {
                // Directory specifier
                // Look for matching directories.
                // The search here is non-recursive, not matter what the 'recursive' parameter says, since we are trying to match a subpath.
                // The recursive search is done below.

                if (path.IndexOfAny(wildcards) != -1)
                {
                    foreach (var dir in Directory.GetDirectories(basePath, path))
                    {
                        res = res.Concat(ExpandWildcardFilePath(pinfo, project, context, sourceItem, dir, baseRecursiveDir, false, filePath, index + 1));
                    }
                }
                else
                {
                    res = res.Concat(ExpandWildcardFilePath(pinfo, project, context, sourceItem, basePath.Combine(path), baseRecursiveDir, false, filePath, index + 1));
                }
            }

            return(res);
        }
		void ImportFile (ProjectInfo project, MSBuildEvaluationContext context, MSBuildImport import, string file)
		{
			if (!File.Exists (file))
				return;
			
			var pref = LoadProject (file);
			project.ReferencedProjects.Add (pref);

			var prefProject = new ProjectInfo { Project = pref };
			AddImportedProject (project, import, prefProject);

			var refCtx = new MSBuildEvaluationContext (context);

			EvaluateProject (prefProject, refCtx, false);

			foreach (var p in prefProject.Properties) {
				p.Value.IsImported = true;
				project.Properties [p.Key] = p.Value;
			}
		}
Beispiel #48
0
 MSBuildItemEvaluated Evaluate(ProjectInfo project, MSBuildEvaluationContext context, MSBuildItem item)
 {
     return(CreateEvaluatedItem(context, project, project.Project, item, context.EvaluateString(item.Include)));
 }
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildChoose choose, bool evalItems)
		{
			foreach (var op in choose.GetOptions ()) {
				if (op.IsOtherwise || SafeParseAndEvaluate (project, context, op.Condition, true)) {
					EvaluateObjects (project, context, op.GetAllObjects (), evalItems);
					break;
				}
			}
		}
		static void AddItem (ProjectInfo project, MSBuildEvaluationContext context, MSBuildItem item, MSBuildItemEvaluated it, string include, Regex excludeRegex, bool trueCond)
		{
			if (include.IndexOf ('*') != -1) {
				var path = include;
				if (path == "**" || path.EndsWith ("\\**"))
					path = path + "/*";
				var subpath = path.Split ('\\');
				foreach (var eit in ExpandWildcardFilePath (project, project.Project, context, item, project.Project.BaseDirectory, FilePath.Null, false, subpath, 0)) {
					if (excludeRegex != null && excludeRegex.IsMatch (eit.Include))
						continue;
					project.EvaluatedItemsIgnoringCondition.Add (eit);
					if (trueCond)
						project.EvaluatedItems.Add (eit);
				}
			}
			else if (include != it.Include) {
				if (excludeRegex != null && excludeRegex.IsMatch (include))
					return;
				it = CreateEvaluatedItem (context, project, project.Project, item, include);
				project.EvaluatedItemsIgnoringCondition.Add (it);
				if (trueCond)
					project.EvaluatedItems.Add (it);
			}
			else {
				if (excludeRegex != null && excludeRegex.IsMatch (include))
					return;
				project.EvaluatedItemsIgnoringCondition.Add (it);
				if (trueCond)
					project.EvaluatedItems.Add (it);
			}
		}
Beispiel #51
0
 void EvaluateProject(ProjectInfo pi, MSBuildEvaluationContext context, bool evalItems)
 {
     context.InitEvaluation(pi.Project);
     EvaluateObjects(pi, context, pi.Project.GetAllObjects(), evalItems);
 }
		void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildImportGroup imports, bool evalItems)
		{
			if (!string.IsNullOrEmpty (imports.Condition) && !SafeParseAndEvaluate (project, context, imports.Condition, true))
				return;

			foreach (var item in imports.Imports)
				Evaluate (project, context, item, evalItems);
		}
		static IEnumerable<MSBuildItemEvaluated> ExpandWildcardFilePath (ProjectInfo pinfo, MSBuildProject project, MSBuildEvaluationContext context, MSBuildItem sourceItem, FilePath basePath, FilePath baseRecursiveDir, bool recursive, string[] filePath, int index)
		{
			var res = Enumerable.Empty<MSBuildItemEvaluated> ();

			if (index >= filePath.Length)
				return res;

			var path = filePath [index];

			if (path == "..")
				return ExpandWildcardFilePath (pinfo, project, context, sourceItem, basePath.ParentDirectory, baseRecursiveDir, recursive, filePath, index + 1);
			
			if (path == ".")
				return ExpandWildcardFilePath (pinfo, project, context, sourceItem, basePath, baseRecursiveDir, recursive, filePath, index + 1);

			if (!Directory.Exists (basePath))
				return res;

			if (path == "**") {
				// if this is the last component of the path, there isn't any file specifier, so there is no possible match
				if (index + 1 >= filePath.Length)
					return res;
				
				// If baseRecursiveDir has already been set, don't overwrite it.
				if (baseRecursiveDir.IsNullOrEmpty)
					baseRecursiveDir = basePath;
				
				return ExpandWildcardFilePath (pinfo, project, context, sourceItem, basePath, baseRecursiveDir, true, filePath, index + 1);
			}

			if (recursive) {
				// Recursive search. Try to match the remaining subpath in all subdirectories.
				foreach (var dir in Directory.GetDirectories (basePath))
					res = res.Concat (ExpandWildcardFilePath (pinfo, project, context, sourceItem, dir, baseRecursiveDir, true, filePath, index));
			}

			if (index == filePath.Length - 1) {
				// Last path component. It has to be a file specifier.
				string baseDir = basePath.ToRelative (project.BaseDirectory).ToString().Replace ('/','\\');
				if (baseDir == ".")
					baseDir = "";
				else if (!baseDir.EndsWith ("\\", StringComparison.Ordinal))
					baseDir += '\\';
				var recursiveDir = baseRecursiveDir.IsNullOrEmpty ? FilePath.Null : basePath.ToRelative (baseRecursiveDir);
				res = res.Concat (Directory.GetFiles (basePath, path).Select (f => {
					context.SetItemContext (f, recursiveDir);
					var ev = baseDir + Path.GetFileName (f);
					return CreateEvaluatedItem (context, pinfo, project, sourceItem, ev);
				}));
			}
			else {
				// Directory specifier
				// Look for matching directories.
				// The search here is non-recursive, not matter what the 'recursive' parameter says, since we are trying to match a subpath.
				// The recursive search is done below.

				if (path.IndexOfAny (wildcards) != -1) {
					foreach (var dir in Directory.GetDirectories (basePath, path))
						res = res.Concat (ExpandWildcardFilePath (pinfo, project, context, sourceItem, dir, baseRecursiveDir, false, filePath, index + 1));
				} else
					res = res.Concat (ExpandWildcardFilePath (pinfo, project, context, sourceItem, basePath.Combine (path), baseRecursiveDir, false, filePath, index + 1));
			}

			return res;
		}
		public MSBuildEvaluationContext (MSBuildEvaluationContext parentContext)
		{
			this.parentContext = parentContext;
			this.project = parentContext.project;
		}
		static MSBuildItemEvaluated CreateEvaluatedItem (MSBuildEvaluationContext context, MSBuildProject project, MSBuildItem sourceItem, string include)
		{
			var it = new MSBuildItemEvaluated (project, sourceItem.Name, sourceItem.Include, include);
			var md = new Dictionary<string,MSBuildPropertyEvaluated> ();
			foreach (var c in sourceItem.Metadata.GetProperties ()) {
				md [c.Name] = new MSBuildPropertyEvaluated (project, c.Name, c.Value, context.EvaluateString (c.Value));
			}
			((MSBuildPropertyGroupEvaluated)it.Metadata).SetProperties (md);
			it.SourceItem = sourceItem;
			it.Condition = sourceItem.Condition;
			return it;
		}