public void ExpandAllIntoStringLeaveEscapedComplex() { ReadOnlyLookup lookup; Dictionary<string, string> itemMetadata; CreateComplexPropertiesItemsMetadata(out lookup, out itemMetadata); Expander expander = new Expander(lookup, itemMetadata); XmlAttribute xmlattribute = (new XmlDocument()).CreateAttribute("dummy"); xmlattribute.Value = "@(Resource->'%(Filename)') ; @(Content) ; @(NonExistent) ; $(NonExistent) ; %(NonExistent) ; " + "$(OutputPath) ; $(TargetPath) ; %(Language)_%(Culture)"; Assertion.AssertEquals( @"string$(p);dialogs%253b ; splash.bmp ; ; ; ; \jk ; l\mno%253bpqr\stu ; subdir1\;subdir2\ ; english_abc%253bdef;ghi", expander.ExpandAllIntoStringLeaveEscaped(xmlattribute.Value, xmlattribute)); Assertion.AssertEquals( @"string$(p);dialogs%253b ; splash.bmp ; ; ; ; \jk ; l\mno%253bpqr\stu ; subdir1\;subdir2\ ; english_abc%253bdef;ghi", expander.ExpandAllIntoStringLeaveEscaped(xmlattribute)); }
/// <summary> /// Given the properties and dictionary of previously encountered item definitions, evaluates /// this specific item definition child element and adds to the dictionary as necessary. /// </summary> /// <exception cref="InvalidProjectFileException">If the item definition is incorrectly defined</exception> private void EvaluateItemDefinitionChildElement(XmlElement itemDefinitionChildElement, BuildPropertyGroup properties, ItemDefinitionsDictionary itemDefinitionsDictionary) { ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(itemDefinitionChildElement); ProjectErrorUtilities.VerifyThrowInvalidProject(!FileUtilities.IsItemSpecModifier(itemDefinitionChildElement.Name), itemDefinitionChildElement, "ItemSpecModifierCannotBeCustomMetadata", itemDefinitionChildElement.Name); ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[itemDefinitionChildElement.Name] == null, itemDefinitionChildElement, "CannotModifyReservedItemMetadata", itemDefinitionChildElement.Name); XmlAttribute conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(itemDefinitionChildElement, /* sole attribute */ true); string condition = ProjectXmlUtilities.GetAttributeValue(conditionAttribute); MetadataDictionary metadataDictionary = null; string itemType = itemDefinitionChildElement.ParentNode.Name; itemDefinitionsDictionary.TryGetValue(itemType, out metadataDictionary); Expander expander = new Expander(properties, itemType, metadataDictionary); if (!Utilities.EvaluateCondition(condition, conditionAttribute, expander, ParserOptions.AllowPropertiesAndItemMetadata, parentProject)) { return; } string unevaluatedMetadataValue = Utilities.GetXmlNodeInnerContents(itemDefinitionChildElement); bool containsItemVector = ItemExpander.ExpressionContainsItemVector(unevaluatedMetadataValue); // We don't allow expressions like @(foo) in the value, as no items exist at this point. ProjectErrorUtilities.VerifyThrowInvalidProject(!containsItemVector, itemDefinitionChildElement, "MetadataDefinitionCannotContainItemVectorExpression", unevaluatedMetadataValue, itemDefinitionChildElement.Name); string evaluatedMetadataValue = expander.ExpandAllIntoStringLeaveEscaped(unevaluatedMetadataValue, itemDefinitionChildElement); if (metadataDictionary == null) { metadataDictionary = new MetadataDictionary(StringComparer.OrdinalIgnoreCase); itemDefinitionsDictionary.Add(itemType, metadataDictionary); } // We only store the evaluated value; build items store the unevaluated value as well, but apparently only to // gather recursive portions (its re-evaluation always goes back to the XML). // Overwrite any existing default value for this particular metadata metadataDictionary[itemDefinitionChildElement.Name] = evaluatedMetadataValue; }
/// <summary> /// Determines if the new item spec that the user is trying to add to the project /// already matches an existing wildcarded item declared in the project. We only /// consider it a "match" in very specific circumstances... if there's anything /// weird or not-mainline about the new item spec or the existing item, we fail /// the match in order to "play it safe". /// </summary> internal bool NewItemSpecMatchesExistingWildcard(string newItemSpec) { Project parentProject = GetParentProject(); ErrorUtilities.VerifyThrow(parentProject != null, "This method should only get called on persisted items."); BuildPropertyGroup evaluatedProperties = parentProject.evaluatedProperties; if ( // The original item spec should have had at least one "*" or "?" in it. FileMatcher.HasWildcards(this.Include) && // The original item should not have a Condition. (this.Condition.Length == 0) && // The original item should not have an Exclude. (this.Exclude.Length == 0) && // The new item spec should NOT have any wildcards. !FileMatcher.HasWildcards(newItemSpec) ) { Expander propertyExpander = new Expander(evaluatedProperties); string newItemSpecExpandedEscaped = propertyExpander.ExpandAllIntoStringLeaveEscaped(newItemSpec, null); // New item spec should not have any unescaped semicolons ... this can really mess us up. if (-1 == newItemSpecExpandedEscaped.IndexOf(';')) { // Expand any properties in the new item spec that the user gave us. string newItemSpecExpandedUnescaped = EscapingUtilities.UnescapeAll(newItemSpecExpandedEscaped); // Loop over each piece separated by semicolons. List<string> itemIncludePieces = propertyExpander.ExpandAllIntoStringListLeaveEscaped(this.Include, this.IncludeAttribute); foreach (string itemIncludePiece in itemIncludePieces) { bool containsEscapedWildcards = EscapingUtilities.ContainsEscapedWildcards(itemIncludePiece); bool containsRealWildcards = FileMatcher.HasWildcards(itemIncludePiece); // If this is the piece that has the wildcards ... if (containsRealWildcards && !containsEscapedWildcards) { string itemIncludePieceContainingWildcardUnescaped = EscapingUtilities.UnescapeAll(itemIncludePiece); FileMatcher.Result match = FileMatcher.FileMatch(itemIncludePieceContainingWildcardUnescaped, newItemSpecExpandedUnescaped); if (match.isLegalFileSpec && match.isMatch) { // The wildcard in the original item spec will match the new item that // user is trying to add. return true; } } } } } return false; }
public void PropertyFunctionConstructor1() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("ver1", @"1.2.3.4"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped(@"$([System.Version]::new($(ver1)))", null); Version v = new Version(result); Assertion.AssertEquals(1, v.Major); Assertion.AssertEquals(2, v.Minor); Assertion.AssertEquals(3, v.Build); Assertion.AssertEquals(4, v.Revision); }
public void PropertyFunctionStaticMethodMakeRelative() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("ParentPath", @"c:\abc\def"); pg.SetProperty("FilePath", @"c:\abc\def\foo.cpp"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped(@"$([MSBuild]::MakeRelative($(ParentPath), `$(FilePath)`))", null); Assertion.AssertEquals(@"foo.cpp", result); }
public void PropertyFunctionInvalid7() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("[$(SomeStuff.Substring(-10))]", null); }
public void PropertyFunctionInvalidNoMetadataFunctions() { BuildPropertyGroup pg = new BuildPropertyGroup(); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("[%(LowerLetterList.Identity.ToUpper())]", null); Assertion.AssertEquals("[%(LowerLetterList.Identity.ToUpper())]", result); }
public void PropertyFunctionPropertyManualGet() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(SomeStuff.get_Length())", null); Assertion.AssertEquals("18", result); }
public void PropertyFunctionPropertyNoArgumentsConcat() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(SomeStuff.ToLower())_goop", null); Assertion.AssertEquals("this is some stuff_goop", result); }
public void PropertyFunctionNoArguments() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(SomeStuff.ToUpper())", null); Assertion.AssertEquals("THIS IS SOME STUFF", result); }
public void PropertyFunctionNoArgumentsTrim() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("FileName", " foobar.baz "); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(FileName.Trim())", null); Assertion.AssertEquals("foobar.baz", result); }
public void PropertyFunctionNullReturn() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$([System.Convert]::ChangeType(,$(SomeStuff.GetType())))", null); Assertion.AssertEquals("", result); }
public void PropertyFunctionNullArgument() { BuildPropertyGroup pg = new BuildPropertyGroup(); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$([System.Convert]::ChangeType('null',$(SomeStuff.GetType())))", null); Assertion.AssertEquals("null", result); }
public void ExpandAllIntoStringExpectIdenticalReference() { ReadOnlyLookup lookup; Dictionary<string, string> itemMetadata; CreateComplexPropertiesItemsMetadata(out lookup, out itemMetadata); Expander expander = new Expander(lookup, itemMetadata); XmlAttribute xmlattribute = (new XmlDocument()).CreateAttribute("dummy"); // Create a *non-literal* string. If we used a literal string, the CLR might (would) intern // it, which would mean that Expander would inevitably return a reference to the same string. // In real builds, the strings will never be literals, and we want to test the behavior in // that situation. xmlattribute.Value = "abc123" + new Random().Next(); string expandedString = expander.ExpandAllIntoStringLeaveEscaped(xmlattribute.Value, xmlattribute); // Verify neither string got interned, so that this test is meaningful Assertion.Assert(null == string.IsInterned(xmlattribute.Value)); Assertion.Assert(null == string.IsInterned(expandedString)); // Finally verify Expander indeed didn't create a new string. Assertion.Assert(Object.ReferenceEquals(xmlattribute.Value, expandedString)); }
public void PropertyFunctionInvalid3() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("Value", "3"); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(SomeStuff.ToUpper().Foo)", null); }
public void PropertyFunctionPropertyPathRootSubtraction() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("RootPath", @"c:\this\is\the\root"); pg.SetProperty("MyPath", @"c:\this\is\the\root\my\project\is\here.proj"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(MyPath.SubString($(RootPath.Length)))", null); Assertion.AssertEquals(@"\my\project\is\here.proj", result); }
public void PropertyFunctionInvalid4() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("Value", "3"); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("[$(SomeStuff($(System.DateTime.Now)))]", null); }
public void PropertyFunctionPropertyWithArgumentExpandedProperty() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("Value", "3"); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(SomeStuff.SubString(1$(Value)))", null); Assertion.AssertEquals("STUff", result); }
public void PropertyFunctionInvalid8() { BuildPropertyGroup pg = new BuildPropertyGroup(); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(([System.DateTime]::Now).ToString(\"MM.dd.yyyy\"))", null); }
public void PropertyFunctionPropertyWithArgumentBooleanReturn() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("PathRoot", @"c:\goo"); pg.SetProperty("PathRoot2", @"c:\goop\"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped(@"$(PathRoot2.Endswith(\))", null); Assertion.AssertEquals("True", result); result = expander.ExpandAllIntoStringLeaveEscaped(@"$(PathRoot.Endswith(\))", null); Assertion.AssertEquals("False", result); }
public void PropertyFunctionNoCollisionsOnType() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("System", "The System Namespace"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(System)", null); Assertion.AssertEquals("The System Namespace", result); }
public void PropertyFunctionPropertyWithArgumentChained() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("Value", "3"); pg.SetProperty("SomeStuff", "This IS SOME STUff"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(SomeStuff.ToUpper().ToLower())", null); Assertion.AssertEquals("this is some stuff", result); }
public void PropertyFunctionConstructor2() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("ver1", @"1.2.3.4"); pg.SetProperty("ver2", @"2.2.3.4"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped(@"$([System.Version]::new($(ver1)).CompareTo($([System.Version]::new($(ver2)))))", null); Assertion.AssertEquals(@"-1", result); }
public void PropertyFunctionPropertyWithArgumentNested() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("Value", "12345"); pg.SetProperty("SomeStuff", "1234567890"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(SomeStuff.SubString($(Value.get_Length())))", null); Assertion.AssertEquals("67890", result); }
/// <summary> /// Sets the project's default targets from the given list of semi-colon-separated target names after expanding all /// embedded properties in the list. /// </summary> /// <owner>SumedhK</owner> /// <param name="defaultTargetsList"></param> /// <param name="propertyBag"></param> private void SetDefaultTargets(string defaultTargetsList, BuildPropertyGroup propertyBag) { Expander propertyExpander = new Expander(propertyBag); this.defaultTargetNames = propertyExpander.ExpandAllIntoStringListLeaveEscaped(defaultTargetsList, null).ToArray(); BuildProperty defaultTargetsProperty = new BuildProperty(ReservedPropertyNames.projectDefaultTargets, propertyExpander.ExpandAllIntoStringLeaveEscaped(defaultTargetsList, null), PropertyType.ReservedProperty); this.ReservedProperties.SetProperty(defaultTargetsProperty); // we also need to push this property directly into the evaluatedProperties bucket // since this property was computed "late", i.e. after the initial evaluation. this.evaluatedProperties.SetProperty(defaultTargetsProperty); }
public void PropertyFunctionGenericListReturn() { BuildPropertyGroup pg = new BuildPropertyGroup(); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$([MSBuild]::__GetListTest())", null); Assertion.AssertEquals("A;B;C;D", result); }
/// <summary> /// Populate the lists of evaluated and unevaluated metadata with all metadata that have true conditions. /// </summary> /// <remarks> /// FUTURE: Currently this isn't done when the item is constructed; so for example HasMetadata will always return /// false until EvaluatedAllItemMetadata is explicitly called. The reason for this is that Metadata are /// not first class objects, they are merely string pairs produced by running over the child XML with a particular expander. /// When Metadata are first class objects this method can be changed to merely evaluate them, /// just as BuildItemGroup.Evaluate does for BuildItem, then methods like HasMetadata behave more sanely. Of course this /// could be a breaking change. /// </remarks> internal void EvaluateAllItemMetadata ( Expander expander, ParserOptions parserOptions, EngineLoggingServices loggingServices, BuildEventContext buildEventContext ) { ErrorUtilities.VerifyThrow(expander != null, "Null expander passed in."); // Cache all custom attributes on the item. For a persisted item, this will walk the item's child nodes, and // cache the custom attributes using a "last one wins" policy. For a virtual item, this method does nothing. // We only evaluate metadata by reading XML if (IsBackedByXml) { ErrorUtilities.VerifyThrow((this.evaluatedCustomMetadata != null) && (this.unevaluatedCustomMetadata != null), "Item is not initialized properly."); // We're evaluating from scratch, so clear out any old cached attributes. this.evaluatedCustomMetadata.Clear(); this.unevaluatedCustomMetadata.Clear(); // Let the expander know about our own item type, so it can // expand unqualified metadata expressions SpecificItemDefinitionLibrary specificItemDefinitionLibrary = new SpecificItemDefinitionLibrary(name, itemDefinitionLibrary); expander = new Expander(expander, specificItemDefinitionLibrary); List<XmlElement> metadataElements = xml.GetChildren(); // look at all the item's child nodes foreach (XmlElement metadataElement in metadataElements) { // confirm that the child node is not conditionally disabled bool condition = true; XmlAttribute conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(metadataElement, true /*no other attributes allowed*/); if (conditionAttribute != null) { condition = Utilities.EvaluateCondition(conditionAttribute.Value, conditionAttribute, expander, null, parserOptions, loggingServices, buildEventContext); } if (condition) { // cache its value, both the evaluated and unevaluated. string unevaluatedMetadataValue = Utilities.GetXmlNodeInnerContents(metadataElement); unevaluatedCustomMetadata[metadataElement.Name] = unevaluatedMetadataValue; string evaluatedMetadataValue = expander.ExpandAllIntoStringLeaveEscaped(unevaluatedMetadataValue, metadataElement); evaluatedCustomMetadata[metadataElement.Name] = evaluatedMetadataValue; // Add this metadata to the running table we're using, so that one piece of metadata can refer to another one above expander.SetMetadataInMetadataTable(name, metadataElement.Name, evaluatedMetadataValue); } } } }
public void PropertyFunctionArrayReturnManualSplitter() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("List", "A-B-C-D"); pg.SetProperty("Splitter", "-"); Expander expander = new Expander(pg); string result = expander.ExpandAllIntoStringLeaveEscaped("$(List.Split($(Splitter.ToCharArray())))", null); Assertion.AssertEquals("A;B;C;D", result); }
/// <summary> /// Given a property bag, this method evaluates the current property, /// expanding any property references contained within. It stores this /// evaluated value in the "finalValue" member. /// </summary> /// <owner>RGoel</owner> internal void Evaluate ( Expander expander ) { ErrorUtilities.VerifyThrow(expander != null, "Expander required to evaluated property."); this.finalValueEscaped = expander.ExpandAllIntoStringLeaveEscaped(this.Value, this.propertyElement); }
public void RegistryPropertyMultiString() { try { BuildPropertyGroup pg = new BuildPropertyGroup(); Expander expander = new Expander(pg); RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\MSBuild_test"); key.SetValue("Value", new string[] { "A", "B", "C", "D" }, RegistryValueKind.MultiString); string result = expander.ExpandAllIntoStringLeaveEscaped(@"$(Registry:HKEY_CURRENT_USER\Software\Microsoft\MSBuild_test@Value)", null); Assertion.AssertEquals("A;B;C;D", result); } finally { Registry.CurrentUser.DeleteSubKey(@"Software\Microsoft\MSBuild_test"); } }