/// <summary> /// Whether it can be evaluated as a Version /// </summary> internal override bool CanVersionEvaluate(ConditionEvaluator.IConditionEvaluationState state) { // Check if the value can be formatted as a Version number // This is needed for nodes that identify as Numeric but can't be parsed as numbers (e.g. 8.1.1.0 vs 8.1) Version unused; return Version.TryParse(_value, out unused); }
/// <summary> /// Evaluate as boolean /// </summary> internal override bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state) { ProjectErrorUtilities.VerifyThrowInvalidProject (LeftChild.CanBoolEvaluate(state), state.ElementLocation, "ExpressionDoesNotEvaluateToBoolean", LeftChild.GetUnexpandedValue(state), LeftChild.GetExpandedValue(state), state.Condition); if (!LeftChild.BoolEvaluate(state)) { // Short circuit return false; } else { ProjectErrorUtilities.VerifyThrowInvalidProject (RightChild.CanBoolEvaluate(state), state.ElementLocation, "ExpressionDoesNotEvaluateToBoolean", RightChild.GetUnexpandedValue(state), RightChild.GetExpandedValue(state), state.Condition); return RightChild.BoolEvaluate(state); } }
/// <summary> /// Returns true if this node evaluates to an empty string, /// otherwise false. /// It may be cheaper to determine whether an expression will evaluate /// to empty than to fully evaluate it. /// Implementations should cache the result so that calls after the first are free. /// </summary> internal override bool EvaluatesToEmpty(ConditionEvaluator.IConditionEvaluationState state) { if (_cachedExpandedValue == null) { if (_expandable) { string expandBreakEarly = state.ExpandIntoStringBreakEarly(_value); if (expandBreakEarly == null) { // It broke early: we can't store the value, we just // know it's non empty return false; } // It didn't break early, the result is accurate, // so store it so the work isn't done again. _cachedExpandedValue = expandBreakEarly; } else { _cachedExpandedValue = _value; } } return (_cachedExpandedValue.Length == 0); }
/// <summary> /// The main evaluate entry point for expression trees /// </summary> /// <param name="state"></param> /// <returns></returns> internal bool Evaluate(ConditionEvaluator.IConditionEvaluationState state) { ProjectErrorUtilities.VerifyThrowInvalidProject( CanBoolEvaluate(state), state.ElementLocation, "ConditionNotBooleanDetail", state.Condition, GetExpandedValue(state)); return BoolEvaluate(state); }
/// <summary> /// Modifies items in the world - specifically, changes their metadata. Changes to items that are part of the project manifest are backed up, so /// they can be reverted when the project is reset after the end of the build. /// </summary> /// <param name="child">The item specification to evaluate and modify.</param> /// <param name="bucket">The batching bucket.</param> /// <param name="keepMetadata">An <see cref="ISet{String}"/> of metadata names to keep.</param> /// <param name="removeMetadata">An <see cref="ISet{String}"/> of metadata names to remove.</param> private void ExecuteModify(ProjectItemGroupTaskItemInstance child, ItemBucket bucket, ISet <string> keepMetadata, ISet <string> removeMetadata) { ICollection <ProjectItemInstance> group = bucket.Lookup.GetItems(child.ItemType); if (group == null || group.Count == 0) { // No items of this type to modify return; } // Figure out what metadata names and values we need to set var metadataToSet = new Lookup.MetadataModifications(keepMetadata != null); // Filter the metadata as appropriate if (keepMetadata != null) { foreach (var metadataName in keepMetadata) { metadataToSet[metadataName] = Lookup.MetadataModification.CreateFromNoChange(); } } else if (removeMetadata != null) { foreach (var metadataName in removeMetadata) { metadataToSet[metadataName] = Lookup.MetadataModification.CreateFromRemove(); } } foreach (ProjectItemGroupTaskMetadataInstance metadataInstance in child.Metadata) { bool condition = ConditionEvaluator.EvaluateCondition ( metadataInstance.Condition, ParserOptions.AllowAll, bucket.Expander, ExpanderOptions.ExpandAll, Project.Directory, metadataInstance.ConditionLocation, LoggingContext.LoggingService, LoggingContext.BuildEventContext, FileSystems.Default); if (condition) { string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(metadataInstance.Value, ExpanderOptions.ExpandAll, metadataInstance.Location); metadataToSet[metadataInstance.Name] = Lookup.MetadataModification.CreateFromNewValue(evaluatedValue); } } // Now apply the changes. This must be done after filtering, since explicitly set metadata overrides filters. bucket.Lookup.ModifyItems(child.ItemType, group, metadataToSet); }
public PromotionModule( PromotionService promotionService, IPromotionPolicyProvider policyFactory, ConditionEvaluator ruleEngine) { Require.NotNull(promotionService, "promotionService"); Require.NotNull(policyFactory, "policyFactory"); Require.NotNull(ruleEngine, "ruleEngine"); _promotionService = promotionService; _policyFactory = policyFactory; _ruleEngine = ruleEngine; }
public void should_throw_for_unrecognized_params() { var ruleEngine = new ConditionEvaluator(); Assert.Throws <UnrecognizedParameterException>(() => { var condition = "Age > 10 OR NotExistParam == 5"; ruleEngine.Evaluate(condition, new Person { Age = 10 }); }); }
public override IEnumerable <ConfiguredActivity> Execute(object dataContext) { var evaluator = new ConditionEvaluator(); var success = evaluator.Evaluate(Conditions, dataContext); if (success) { return(Further(Then, dataContext)); } else { return(Further(Else, dataContext)); } }
public void TestIntegrationWithResourceBounds() { var evaluator = new ConditionEvaluator(); var sut = new PermissionsService(new ConditionParser(), (new PermissionsScanner().All(typeof(Permissions))), evaluator); sut.InsertSerialized(new GrantStub { ConditionCode = "0 < 1", GrantType = GrantType.Allow, Index = 1, NodeKey = Permissions.Product.View.Key, PermissionType = PermissionType.ResourceBound, Identifier = 1, PermissionChain = PermissionChainName }); sut.InsertSerialized(new GrantStub { ConditionCode = "1 < 0", GrantType = GrantType.Deny, Index = 2, NodeKey = Permissions.Product.View.Key, PermissionType = PermissionType.ResourceBound, Identifier = 1, PermissionChain = PermissionChainName }); // We have an explicit grant, this should be true sut.GetResultUsingChain(PermissionChainName, Permissions.Product.View, 1, new Product()).ShouldBe(PermissionResult.Allowed); sut.GetResultUsingChain(PermissionChainName, Permissions.Product.Buy, 1, new Product()).ShouldBe(PermissionResult.Unset); var entries = new List <IPermissionGrantSerialized>() { new GrantStub { ConditionCode = "false", GrantType = GrantType.Allow, Index = 1, NodeKey = Permissions.Product.View.Key, PermissionType = PermissionType.ResourceBound, Identifier = 1, PermissionChain = PermissionChainName } }; sut.ReplaceAllGrants(entries); sut.GetResultUsingChain(PermissionChainName, Permissions.Product.View, 1, new Product()).ShouldBe(PermissionResult.Unset); }
public void TestMultiplePropertyReferences() { var sut = new ConditionEvaluator(); var product = new Product { Name = "Huel", Category = new Category { CategoryId = 5 } }; sut.Evaluate(product, Les2LanguageService.Value.ParseSingle("resource.Category.CategoryId == 5 || resource.Category.CategoryId == 6 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7 || resource.Category.CategoryId == 7")) .ShouldBe(true); }
public void ConditionExpressionEvaluate() { Assert.Equal(1, ConditionEvaluator.Evaluate(true, 1, 2)); Assert.Equal(1, ConditionEvaluator.Evaluate(1, 1, 2)); Assert.Equal(1, ConditionEvaluator.Evaluate(2.3f, 1, 2)); Assert.Equal(1, ConditionEvaluator.Evaluate("aa", 1, 2)); Assert.Equal(1, ConditionEvaluator.Evaluate(new object(), 1, 2)); Assert.Equal(2, ConditionEvaluator.Evaluate(false, 1, 2)); Assert.Equal(2, ConditionEvaluator.Evaluate(0, 1, 2)); Assert.Equal(2, ConditionEvaluator.Evaluate(-9, 1, 2)); Assert.Equal(2, ConditionEvaluator.Evaluate(-0f, 1, 2)); Assert.Equal(2, ConditionEvaluator.Evaluate(-9.0f, 1, 2)); Assert.Equal(2, ConditionEvaluator.Evaluate(null, 1, 2)); Assert.Equal(2, ConditionEvaluator.Evaluate("", 1, 2)); }
public void TestLogic() { var sut = new ConditionEvaluator(); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("false && true")).ShouldBe(false); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("true && true")).ShouldBe(true); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("true && false")).ShouldBe(false); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("false && false")).ShouldBe(false); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("false || true")).ShouldBe(true); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("true || true")).ShouldBe(true); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("true || false")).ShouldBe(true); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("false || false")).ShouldBe(false); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("!false")).ShouldBe(true); sut.Evaluate(null, Les2LanguageService.Value.ParseSingle("!true")).ShouldBe(false); }
public void TestEnum() { var sut = new ConditionEvaluator(); var product = new Product { Name = "Huel", Category = new Category { CategoryId = 5, Type = CategoryType.Product } }; sut.Evaluate(product, Les2LanguageService.Value.ParseSingle("resource.Category.Type == 'Product'")) .ShouldBe(true); }
public void EvaluateConfig(IEngineEnvironmentSettings environmentSettings, IVariableCollection vars, IMacroConfig rawConfig, IParameterSet parameters, ParameterSetter setter) { SwitchMacroConfig config = rawConfig as SwitchMacroConfig; if (config == null) { throw new InvalidCastException("Couldn't cast the rawConfig as SwitchMacroConfig"); } ConditionEvaluator evaluator = EvaluatorSelector.Select(config.Evaluator, Cpp2StyleEvaluatorDefinition.Evaluate); string result = string.Empty; // default if no condition assigns a value foreach (KeyValuePair <string, string> switchInfo in config.Switches) { string condition = switchInfo.Key; string value = switchInfo.Value; if (string.IsNullOrEmpty(condition)) { // no condition, this is the default. result = value; break; } else { byte[] conditionBytes = Encoding.UTF8.GetBytes(condition); int length = conditionBytes.Length; int position = 0; IProcessorState state = new GlobalRunSpec.ProcessorState(environmentSettings, vars, conditionBytes, Encoding.UTF8); if (evaluator(state, ref length, ref position, out bool faulted)) { result = value; break; } } } Parameter p = new Parameter { IsVariable = true, Name = config.VariableName, DataType = config.DataType }; vars[config.VariableName] = result.ToString(); setter(p, result.ToString()); }
// Nice to have: Generalize this type of setup similarly to Line, Block, & Custom public static List <IOperationProvider> MSBuildConditionalSetup(string evaluatorType, bool wholeLine, bool trimWhiteSpace, string id) { ConditionEvaluator evaluator = EvaluatorSelector.Select(evaluatorType); IOperationProvider conditional = new InlineMarkupConditional( new MarkupTokens("<", "</", ">", "/>", "Condition=\"", "\""), wholeLine, trimWhiteSpace, evaluator, "$({0})", id ); return(new List <IOperationProvider>() { conditional }); }
// Nice to have: Generalize this type of setup similarly to Line, Block, & Custom public static List <IOperationProvider> CStyleNoCommentsConditionalSetup(string evaluatorType, bool wholeLine, bool trimWhiteSpace, string id) { ConditionalKeywords defaultKeywords = new ConditionalKeywords(); List <ITokenConfig> ifTokens = new List <ITokenConfig>(); List <ITokenConfig> elseifTokens = new List <ITokenConfig>(); List <ITokenConfig> elseTokens = new List <ITokenConfig>(); List <ITokenConfig> endifTokens = new List <ITokenConfig>(); foreach (string ifKeyword in defaultKeywords.IfKeywords) { ifTokens.Add($"{defaultKeywords.KeywordPrefix}{ifKeyword}".TokenConfig()); } foreach (string elseifKeyword in defaultKeywords.ElseIfKeywords) { elseifTokens.Add($"{defaultKeywords.KeywordPrefix}{elseifKeyword}".TokenConfig()); } foreach (string elseKeyword in defaultKeywords.ElseKeywords) { elseTokens.Add($"{defaultKeywords.KeywordPrefix}{elseKeyword}".TokenConfig()); } foreach (string endifKeyword in defaultKeywords.EndIfKeywords) { endifTokens.Add($"{defaultKeywords.KeywordPrefix}{endifKeyword}".TokenConfig()); } ConditionalTokens tokens = new ConditionalTokens { IfTokens = ifTokens, ElseTokens = elseTokens, ElseIfTokens = elseifTokens, EndIfTokens = endifTokens }; ConditionEvaluator evaluator = EvaluatorSelector.Select(evaluatorType); IOperationProvider conditional = new Conditional(tokens, wholeLine, trimWhiteSpace, evaluator, id, true); return(new List <IOperationProvider>() { conditional }); }
/// <summary> /// Evaluates as boolean and evaluates children as boolean, numeric, or string. /// Order in which comparisons are attempted is numeric, boolean, then string. /// Updates conditioned properties table. /// </summary> internal override bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state) { ProjectErrorUtilities.VerifyThrowInvalidProject (LeftChild != null && RightChild != null, state.ElementLocation, "IllFormedCondition", state.Condition); // It's sometimes possible to bail out of expansion early if we just need to know whether // the result is empty string. // If at least one of the left or the right hand side will evaluate to empty, // and we know which do, then we already have enough information to evaluate this expression. // That means we don't have to fully expand a condition like " '@(X)' == '' " // which is a performance advantage if @(X) is a huge item list. if (LeftChild.EvaluatesToEmpty(state) || RightChild.EvaluatesToEmpty(state)) { UpdateConditionedProperties(state); return Compare(LeftChild.EvaluatesToEmpty(state), RightChild.EvaluatesToEmpty(state)); } if (LeftChild.CanNumericEvaluate(state) && RightChild.CanNumericEvaluate(state)) { return Compare(LeftChild.NumericEvaluate(state), RightChild.NumericEvaluate(state)); } else if (LeftChild.CanBoolEvaluate(state) && RightChild.CanBoolEvaluate(state)) { return Compare(LeftChild.BoolEvaluate(state), RightChild.BoolEvaluate(state)); } else // string comparison { string leftExpandedValue = LeftChild.GetExpandedValue(state); string rightExpandedValue = RightChild.GetExpandedValue(state); ProjectErrorUtilities.VerifyThrowInvalidProject (leftExpandedValue != null && rightExpandedValue != null, state.ElementLocation, "IllFormedCondition", state.Condition); UpdateConditionedProperties(state); return Compare(leftExpandedValue, rightExpandedValue); } }
public void EvaluateConfig(IEngineEnvironmentSettings environmentSettings, IVariableCollection vars, IMacroConfig rawConfig, IParameterSet parameters, ParameterSetter setter) { EvaluateMacroConfig config = rawConfig as EvaluateMacroConfig; if (config == null) { throw new InvalidCastException("Couldn't cast the rawConfig as EvaluateMacroConfig"); } ConditionEvaluator evaluator = EvaluatorSelector.Select(config.Evaluator, Cpp2StyleEvaluatorDefinition.Evaluate); byte[] data = Encoding.UTF8.GetBytes(config.Value); int len = data.Length; int pos = 0; IProcessorState state = new GlobalRunSpec.ProcessorState(environmentSettings, vars, data, Encoding.UTF8); bool result = evaluator(state, ref len, ref pos, out bool faulted); Parameter p; if (parameters.TryGetParameterDefinition(config.VariableName, out ITemplateParameter existingParam)) { // If there is an existing parameter with this name, it must be reused so it can be referenced by name // for other processing, for example: if the parameter had value forms defined for creating variants. // When the param already exists, use its definition, but set IsVariable = true for consistency. p = (Parameter)existingParam; p.IsVariable = true; if (string.IsNullOrEmpty(p.DataType)) { p.DataType = config.DataType; } } else { p = new Parameter { IsVariable = true, Name = config.VariableName, DataType = config.DataType }; } vars[config.VariableName] = result.ToString(); setter(p, result.ToString()); }
// Nice to have: Generalize this type of setup similarly to Line, Block, & Custom public static List <IOperationProvider> CStyleNoCommentsConditionalSetup(string evaluatorType, bool wholeLine, bool trimWhiteSpace, string id) { ConditionalTokens tokens = new ConditionalTokens { IfTokens = new[] { "#if".TokenConfig() }, ElseTokens = new[] { "#else".TokenConfig() }, ElseIfTokens = new[] { "#elseif".TokenConfig() }, EndIfTokens = new[] { "#endif".TokenConfig() } }; ConditionEvaluator evaluator = EvaluatorSelector.Select(evaluatorType); IOperationProvider conditional = new Conditional(tokens, wholeLine, trimWhiteSpace, evaluator, id, true); return(new List <IOperationProvider>() { conditional }); }
/// <summary> /// Retrieves the error targets for this target. /// </summary> /// <param name="projectLoggingContext">The project logging context.</param> /// <returns>A list of error targets.</returns> internal List <TargetSpecification> GetErrorTargets(ProjectLoggingContext projectLoggingContext) { VerifyState(_state, TargetEntryState.ErrorExecution); ErrorUtilities.VerifyThrow(_legacyCallTargetScopes == null, "We should have already left any legacy call target scopes."); List <TargetSpecification> allErrorTargets = new List <TargetSpecification>(_target.OnErrorChildren.Count); foreach (ProjectOnErrorInstance errorTargetInstance in _target.OnErrorChildren) { bool condition = ConditionEvaluator.EvaluateCondition ( errorTargetInstance.Condition, ParserOptions.AllowPropertiesAndItemLists, _expander, ExpanderOptions.ExpandPropertiesAndItems, _requestEntry.ProjectRootDirectory, errorTargetInstance.ConditionLocation, projectLoggingContext.LoggingService, projectLoggingContext.BuildEventContext ); if (condition) { IList <string> errorTargets = _expander.ExpandIntoStringListLeaveEscaped(errorTargetInstance.ExecuteTargets, ExpanderOptions.ExpandPropertiesAndItems, errorTargetInstance.ExecuteTargetsLocation); foreach (string escapedErrorTarget in errorTargets) { string errorTargetName = EscapingUtilities.UnescapeAll(escapedErrorTarget); allErrorTargets.Add(new TargetSpecification(errorTargetName, errorTargetInstance.ExecuteTargetsLocation)); } } } // If this target never executed (for instance, because one of its dependencies errored) then we need to // create a result for this target to report when it gets to the Completed state. if (null == _targetResult) { _targetResult = new TargetResult(new TaskItem[] { }, new WorkUnitResult(WorkUnitResultCode.Failed, WorkUnitActionCode.Stop, null)); } _state = TargetEntryState.Completed; return(allErrorTargets); }
/// <summary> /// Evaluate as boolean /// </summary> internal override bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state) { bool isLeftNum = LeftChild.CanNumericEvaluate(state); bool isLeftVersion = LeftChild.CanVersionEvaluate(state); bool isRightNum = RightChild.CanNumericEvaluate(state); bool isRightVersion = RightChild.CanVersionEvaluate(state); bool isNumeric = isLeftNum && isRightNum; bool isVersion = isLeftVersion && isRightVersion; bool isValidComparison = isNumeric || isVersion || (isLeftNum && isRightVersion) || (isLeftVersion && isRightNum); ProjectErrorUtilities.VerifyThrowInvalidProject (isValidComparison, state.ElementLocation, "ComparisonOnNonNumericExpression", state.Condition, /* helpfully display unexpanded token and expanded result in error message */ (LeftChild.CanNumericEvaluate(state) ? RightChild.GetUnexpandedValue(state) : LeftChild.GetUnexpandedValue(state)), (LeftChild.CanNumericEvaluate(state) ? RightChild.GetExpandedValue(state) : LeftChild.GetExpandedValue(state))); // If the values identify as numeric, make that comparison instead of the Version comparison since numeric has a stricter definition if (isNumeric) { return Compare(LeftChild.NumericEvaluate(state), RightChild.NumericEvaluate(state)); } else if (isVersion) { return Compare(LeftChild.VersionEvaluate(state), RightChild.VersionEvaluate(state)); } // If the numbers are of a mixed type, call that specific Compare method if (isLeftNum && isRightVersion) { return Compare(LeftChild.NumericEvaluate(state), RightChild.VersionEvaluate(state)); } else if (isLeftVersion && isRightNum) { return Compare(LeftChild.VersionEvaluate(state), RightChild.NumericEvaluate(state)); } // Throw error here as this code should be unreachable ErrorUtilities.ThrowInternalErrorUnreachable(); return false; }
public void Evaluate(string variableName, IVariableCollection vars, JObject def, IParameterSet parameters, ParameterSetter setter) { string evaluatorName = def.ToString("evaluator"); ConditionEvaluator evaluator = EvaluatorSelector.Select(evaluatorName); byte[] data = Encoding.UTF8.GetBytes(def.ToString("action")); int len = data.Length; int pos = 0; IProcessorState state = new GlobalRunSpec.ProcessorState(vars, data, Encoding.UTF8); bool res = evaluator(state, ref len, ref pos); Parameter p = new Parameter { IsVariable = true, Name = variableName }; setter(p, res.ToString()); }
//[TestMethod] public void TestConditionCallback() { List <ACondition> cdts = new List <ACondition>(); ConditionInput <int> i = 128; var intCdt = new ConditionEvaluator { Condition = ConditionEvaluator.CONDITION.MORE, Input = 127 }; intCdt.SetRefOutput(i); //intCdt.Callback = () => intCdt.Input++; //cdts.Add(intCdt); Assert.IsTrue(ACondition.EvaluateSet(cdts), "1 Conditions are not satisfied"); //intCdt.Callback(); Assert.IsFalse(ACondition.EvaluateSet(cdts), "2 Conditions are not satisfied"); }
public void TestNxNode() { var evaluator = new ConditionEvaluator(); var sut = new PermissionsService(new ConditionParser(), (new PermissionsScanner().All(typeof(Permissions))), evaluator); ActualValueDelegate <bool> del = () => { sut.InsertSerialized(new GrantStub { GrantType = GrantType.Allow, Index = 1, NodeKey = "Dog.Feed", PermissionType = PermissionType.ResourceBound, Identifier = 1, PermissionChain = PermissionChainName }); return(true); }; Assert.That(del, Throws.TypeOf <ArgumentException>()); }
//[TestMethod] public void TestConditions() { List <ACondition> cdts = new List <ACondition>(); ConditionInput <int> i = new ConditionInput <int> { Value = 42 }; var intCdt = new ConditionEvaluator { Condition = ConditionEvaluator.CONDITION.EQUAL, Input = 42 }; intCdt.SetRefOutput(i); //cdts.Add(intCdt); Assert.IsTrue(ACondition.EvaluateSet(cdts), "1 Conditions are not satisfied"); i.Value = 0; Assert.IsFalse(ACondition.EvaluateSet(cdts), "2 Conditions are not satisfied"); }
public void ApplyRule(RewriteContext context) { // Due to the path string always having a leading slash, // remove it from the path before regex comparison var path = context.HttpContext.Request.Path; MatchResults initMatchResults; if (path == PathString.Empty) { initMatchResults = InitialMatch.Evaluate(path.ToString(), context); } else { initMatchResults = InitialMatch.Evaluate(path.ToString().Substring(1), context); } if (!initMatchResults.Success) { context.Logger.UrlRewriteNotMatchedRule(Name); return; } MatchResults?condResult = null; if (Conditions != null) { condResult = ConditionEvaluator.Evaluate(Conditions, context, initMatchResults.BackReferences); if (!condResult.Success) { context.Logger.UrlRewriteNotMatchedRule(Name); return; } } context.Logger.UrlRewriteMatchedRule(Name); // at this point we know the rule passed, evaluate the replacement. Action.ApplyAction(context, initMatchResults?.BackReferences, condResult?.BackReferences); }
public static List <IOperationProvider> GenerateConditionalSetup(string startToken, string endToken, string pseudoEndToken, ConditionalKeywords keywords, ConditionalOperationOptions options) { ConditionEvaluator evaluator = EvaluatorSelector.Select(options.EvaluatorType); ConditionalTokens tokens = new ConditionalTokens { EndIfTokens = new[] { $"{keywords.KeywordPrefix}{keywords.EndIfKeyword}".TokenConfig(), $"{startToken}{keywords.KeywordPrefix}{keywords.EndIfKeyword}".TokenConfig() }, ActionableIfTokens = new[] { $"{startToken}{keywords.KeywordPrefix}{keywords.IfKeyword}".TokenConfig() }, ActionableElseTokens = new[] { $"{keywords.KeywordPrefix}{keywords.ElseKeyword}".TokenConfig(), $"{startToken}{keywords.KeywordPrefix}{keywords.ElseKeyword}".TokenConfig() }, ActionableElseIfTokens = new[] { $"{keywords.KeywordPrefix}{keywords.ElseIfKeyword}".TokenConfig(), $"{startToken}{keywords.KeywordPrefix}{keywords.ElseIfKeyword}".TokenConfig() }, }; if (!string.IsNullOrWhiteSpace(pseudoEndToken)) { Guid operationIdGuid = new Guid(); string commentFixOperationId = $"Fix pseudo tokens ({pseudoEndToken} {operationIdGuid})"; string commentFixResetId = $"Reset pseudo token fixer ({pseudoEndToken} {operationIdGuid})"; tokens.ActionableOperations = new[] { commentFixOperationId, commentFixResetId }; IOperationProvider balancedComments = new BalancedNesting(startToken.TokenConfig(), endToken.TokenConfig(), pseudoEndToken.TokenConfig(), commentFixOperationId, commentFixResetId, options.OnByDefault); IOperationProvider conditional = new Conditional(tokens, options.WholeLine, options.TrimWhitespace, evaluator, options.Id, options.OnByDefault); return(new List <IOperationProvider>() { conditional, balancedComments }); } else { IOperationProvider conditional = new Conditional(tokens, options.WholeLine, options.TrimWhitespace, evaluator, options.Id, options.OnByDefault); return(new List <IOperationProvider>() { conditional }); } }
public void TestIntegrationWithGenericNodes() { var evaluator = new ConditionEvaluator(); var sut = new PermissionsService(new ConditionParser(), (new PermissionsScanner().All(typeof(Permissions))), evaluator); sut.InsertSerialized(new GrantStub { GrantType = GrantType.Allow, Index = 1, NodeKey = Permissions.Product.Create.Key, PermissionType = PermissionType.Generic, Identifier = 1, PermissionChain = PermissionChainName }); sut.InsertSerialized(new GrantStub { GrantType = GrantType.Allow, Index = 1, NodeKey = Permissions.Product.Buy.Key, PermissionType = PermissionType.ResourceBound, ConditionCode = "resource.Name ~= 'test_*'", Identifier = 1, PermissionChain = PermissionChainName }); // We have an explicit grant, this should be true sut.GetResultUsingChain(PermissionChainName, Permissions.Product.Create, 1).ShouldBe(PermissionResult.Allowed); sut.GetResultUsingChain(PermissionChainName, Permissions.Product.Buy, 1, new Product { Name = "test_product", Price = 5d }).ShouldBe(PermissionResult.Allowed); }
/// <inheritdoc /> public override IReadOnlyList <IDiagnosticResult> Analyze(Project project) { var propertyGroups = project.ProjectDocument.Element(project.XmlNamespace + "Project") .Elements(project.XmlNamespace + "PropertyGroup").ToArray(); var configurationSet = new HashSet <string>(); var platformSet = new HashSet <string>(); var configurationsFromProperty = ParseFromProperty("Configurations") ?? new[] { "Debug", "Release" }; var platformsFromProperty = ParseFromProperty("Platforms") ?? new[] { "AnyCPU" }; foreach (var configuration in configurationsFromProperty) { configurationSet.Add(configuration); } foreach (var platform in platformsFromProperty) { platformSet.Add(platform); } var list = new List <IDiagnosticResult>(); foreach (var x in project.ProjectDocument.Descendants()) { var condition = x.Attribute("Condition"); if (condition == null) { continue; } var conditionValue = condition.Value; if (!conditionValue.Contains("$(Configuration)") && !conditionValue.Contains("$(Platform)")) { continue; } var conditionEvaluated = ConditionEvaluator.GetConditionValues(conditionValue); if (conditionEvaluated.TryGetValue("Configuration", out var configurations)) { foreach (var configuration in configurations) { if (!configurationSet.Contains(configuration)) { list.Add( CreateDiagnosticResult(project, $"Configuration '{configuration}' is used in project file but not mentioned in $(Configurations).", project.FilePath) .LoadLocationFromElement(x)); } } } if (conditionEvaluated.TryGetValue("Platform", out var platforms)) { foreach (var platform in platforms) { if (!platformSet.Contains(platform)) { list.Add( CreateDiagnosticResult(project, $"Platform '{platform}' is used in project file but not mentioned in $(Platforms).", project.FilePath) .LoadLocationFromElement(x)); } } } } return(list); string[] ParseFromProperty(string name) => propertyGroups.Where(x => x.Attribute("Condition") == null) .Elements(project.XmlNamespace + name) .FirstOrDefault() ?.Value .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); }
/// <summary> /// Evaluate node as boolean /// </summary> internal override bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state) { if (String.Compare(_functionName, "exists", StringComparison.OrdinalIgnoreCase) == 0) { // Check we only have one argument VerifyArgumentCount(1, state); // Expand properties and items, and verify the result is an appropriate scalar string expandedValue = ExpandArgumentForScalarParameter("exists", (GenericExpressionNode)_arguments[0], state); if (String.IsNullOrEmpty(expandedValue)) { return false; } try { if (state.EvaluationDirectory != null && !Path.IsPathRooted(expandedValue)) { expandedValue = Path.GetFullPath(Path.Combine(state.EvaluationDirectory, expandedValue)); } } catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception. { if (ExceptionHandling.NotExpectedException(e)) throw; // Ignore invalid characters or path related exceptions // We will ignore the PathTooLong exception caused by GetFullPath becasue in single proc this code // is not executed and the condition is just evaluated to false as File.Exists and Directory.Exists does not throw in this situation. // To be consistant with that we will return a false in this case also. // DevDiv Bugs: 46035 return false; } if (state.LoadedProjectsCache != null && state.LoadedProjectsCache.TryGet(expandedValue) != null) { return true; } bool exists = FileUtilities.FileOrDirectoryExistsNoThrow(expandedValue); return exists; } else if (String.Compare(_functionName, "HasTrailingSlash", StringComparison.OrdinalIgnoreCase) == 0) { // Check we only have one argument VerifyArgumentCount(1, state); // Expand properties and items, and verify the result is an appropriate scalar string expandedValue = ExpandArgumentForScalarParameter("HasTrailingSlash", (GenericExpressionNode)_arguments[0], state); // Is the last character a backslash? if (expandedValue.Length != 0) { char lastCharacter = expandedValue[expandedValue.Length - 1]; // Either back or forward slashes satisfy the function: this is useful for URL's return (lastCharacter == Path.DirectorySeparatorChar || lastCharacter == Path.AltDirectorySeparatorChar); } else { return false; } } // We haven't implemented any other "functions" else { ProjectErrorUtilities.VerifyThrowInvalidProject( false, state.ElementLocation, "UndefinedFunctionCall", state.Condition, _functionName); return false; } }
/// <summary> /// Whether it can be evaluated as a boolean: never allowed for numerics /// </summary> internal override bool CanBoolEvaluate(ConditionEvaluator.IConditionEvaluationState state) { // Numeric expressions are never allowed to be treated as booleans. return false; }
/// <summary> /// Evaluate as numeric /// </summary> internal override double NumericEvaluate(ConditionEvaluator.IConditionEvaluationState state) { return ConversionUtilities.ConvertDecimalOrHexToDouble(_value); }
internal override void ExecuteTask(Lookup lookup) { foreach (ProjectItemGroupTaskItemInstance child in _taskInstance.Items) { List <ItemBucket> buckets = null; try { List <string> parameterValues = new List <string>(); GetBatchableValuesFromBuildItemGroupChild(parameterValues, child); buckets = BatchingEngine.PrepareBatchingBuckets(parameterValues, lookup, child.ItemType, _taskInstance.Location); // "Execute" each bucket foreach (ItemBucket bucket in buckets) { bool condition = ConditionEvaluator.EvaluateCondition ( child.Condition, ParserOptions.AllowAll, bucket.Expander, ExpanderOptions.ExpandAll, Project.Directory, child.ConditionLocation, LoggingContext.LoggingService, LoggingContext.BuildEventContext, FileSystems.Default); if (condition) { HashSet <string> keepMetadata = null; HashSet <string> removeMetadata = null; HashSet <string> matchOnMetadata = null; MatchOnMetadataOptions matchOnMetadataOptions = MatchOnMetadataConstants.MatchOnMetadataOptionsDefaultValue; if (!String.IsNullOrEmpty(child.KeepMetadata)) { var keepMetadataEvaluated = bucket.Expander.ExpandIntoStringListLeaveEscaped(child.KeepMetadata, ExpanderOptions.ExpandAll, child.KeepMetadataLocation).ToList(); if (keepMetadataEvaluated.Count > 0) { keepMetadata = new HashSet <string>(keepMetadataEvaluated); } } if (!String.IsNullOrEmpty(child.RemoveMetadata)) { var removeMetadataEvaluated = bucket.Expander.ExpandIntoStringListLeaveEscaped(child.RemoveMetadata, ExpanderOptions.ExpandAll, child.RemoveMetadataLocation).ToList(); if (removeMetadataEvaluated.Count > 0) { removeMetadata = new HashSet <string>(removeMetadataEvaluated); } } if (!String.IsNullOrEmpty(child.MatchOnMetadata)) { var matchOnMetadataEvaluated = bucket.Expander.ExpandIntoStringListLeaveEscaped(child.MatchOnMetadata, ExpanderOptions.ExpandAll, child.MatchOnMetadataLocation).ToList(); if (matchOnMetadataEvaluated.Count > 0) { matchOnMetadata = new HashSet <string>(matchOnMetadataEvaluated); } Enum.TryParse(child.MatchOnMetadataOptions, out matchOnMetadataOptions); } if ((child.Include.Length != 0) || (child.Exclude.Length != 0)) { // It's an item -- we're "adding" items to the world ExecuteAdd(child, bucket, keepMetadata, removeMetadata); } else if (child.Remove.Length != 0) { // It's a remove -- we're "removing" items from the world ExecuteRemove(child, bucket, matchOnMetadata, matchOnMetadataOptions); } else { // It's a modify -- changing existing items ExecuteModify(child, bucket, keepMetadata, removeMetadata); } } } } finally { if (buckets != null) { // Propagate the item changes to the bucket above foreach (ItemBucket bucket in buckets) { bucket.LeaveScope(); } } } } }
/// <summary> /// Whether the node can be evaluated as a version: by default, /// this is not allowed /// </summary> internal override bool CanVersionEvaluate(ConditionEvaluator.IConditionEvaluationState state) { return false; }
/// <summary> /// Returns expanded value with '!' prepended. Useful for error messages. /// </summary> internal override string GetExpandedValue(ConditionEvaluator.IConditionEvaluationState state) { return "!" + LeftChild.GetExpandedValue(state); }
internal override bool CanBoolEvaluate(ConditionEvaluator.IConditionEvaluationState state) { return LeftChild.CanBoolEvaluate(state); }
/// <summary> /// Version evaluation is never allowed for operators /// </summary> internal override Version VersionEvaluate(ConditionEvaluator.IConditionEvaluationState state) { ErrorUtilities.VerifyThrow(false, "Cannot version evaluate an operator"); return null; }
private void AssertParseEvaluate(Parser p, string expression, Expander<ProjectPropertyInstance, ProjectItemInstance> expander, bool expected, ConditionEvaluator.IConditionEvaluationState state) { if (expander.Metadata == null) { expander.Metadata = new StringMetadataTable(null); } GenericExpressionNode tree = p.Parse(expression, ParserOptions.AllowAll, MockElementLocation.Instance); if (state == null) { state = new ConditionEvaluator.ConditionEvaluationState<ProjectPropertyInstance, ProjectItemInstance> ( String.Empty, expander, ExpanderOptions.ExpandAll, null, Environment.CurrentDirectory, ElementLocation.EmptyLocation ); } bool result = tree.Evaluate(state); Assert.AreEqual(expected, result); }
/// <summary> /// Value before any item and property expressions are expanded /// </summary> /// <returns></returns> internal override string GetUnexpandedValue(ConditionEvaluator.IConditionEvaluationState state) { return null; }
/// <summary> /// Retrieves the list of dependencies this target needs to have built and moves the target to the next state. /// Never returns null. /// </summary> /// <returns>A collection of targets on which this target depends.</returns> internal List <TargetSpecification> GetDependencies(ProjectLoggingContext projectLoggingContext) { VerifyState(_state, TargetEntryState.Dependencies); // Resolve the target now, since from this point on we are going to be doing work with the actual instance. GetTargetInstance(); // We first make sure no batching was attempted with the target's condition. // UNDONE: (Improvement) We want to allow this actually. In order to do this we need to determine what the // batching buckets are, and if there are any which aren't empty, return our list of dependencies. // Only in the case where all bucket conditions fail do we want to skip the target entirely (and // this skip building the dependencies.) if (ExpressionShredder.ContainsMetadataExpressionOutsideTransform(_target.Condition)) { ProjectErrorUtilities.ThrowInvalidProject(_target.ConditionLocation, "TargetConditionHasInvalidMetadataReference", _target.Name, _target.Condition); } // If condition is false (based on propertyBag), set this target's state to // "Skipped" since we won't actually build it. bool condition = ConditionEvaluator.EvaluateCondition ( _target.Condition, ParserOptions.AllowPropertiesAndItemLists, _expander, ExpanderOptions.ExpandPropertiesAndItems, _requestEntry.ProjectRootDirectory, _target.ConditionLocation, projectLoggingContext.LoggingService, projectLoggingContext.BuildEventContext ); if (!condition) { _targetResult = new TargetResult(new TaskItem[0] { }, new WorkUnitResult(WorkUnitResultCode.Skipped, WorkUnitActionCode.Continue, null)); _state = TargetEntryState.Completed; if (!projectLoggingContext.LoggingService.OnlyLogCriticalEvents) { // Expand the expression for the Log. string expanded = _expander.ExpandIntoStringAndUnescape(_target.Condition, ExpanderOptions.ExpandPropertiesAndItems, _target.ConditionLocation); // By design: Not building dependencies. This is what NAnt does too. // NOTE: In the original code, this was logged from the target logging context. However, the target // hadn't been "started" by then, so you'd get a target message outside the context of a started // target. In the Task builder (and original Task Engine), a Task Skipped message would be logged in // the context of the target, not the task. This should be the same, especially given that we // wish to allow batching on the condition of a target. projectLoggingContext.LogComment(MessageImportance.Low, "TargetSkippedFalseCondition", _target.Name, _target.Condition, expanded); } return(new List <TargetSpecification>()); } IList <string> dependencies = _expander.ExpandIntoStringListLeaveEscaped(_target.DependsOnTargets, ExpanderOptions.ExpandPropertiesAndItems, _target.DependsOnTargetsLocation); List <TargetSpecification> dependencyTargets = new List <TargetSpecification>(dependencies.Count); foreach (string escapedDependency in dependencies) { string dependencyTargetName = EscapingUtilities.UnescapeAll(escapedDependency); dependencyTargets.Add(new TargetSpecification(dependencyTargetName, _target.DependsOnTargetsLocation)); } _state = TargetEntryState.Execution; return(dependencyTargets); }
internal abstract bool CanNumericEvaluate(ConditionEvaluator.IConditionEvaluationState state);
internal abstract bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state);
private void ExecuteAdd(ProjectItemGroupTaskItemInstance child, ItemBucket bucket, ISet <string> keepMetadata, ISet <string> removeMetadata) { // First, collect up the appropriate metadata collections. We need the one from the item definition, if any, and // the one we are using for this batching bucket. ProjectItemDefinitionInstance itemDefinition; Project.ItemDefinitions.TryGetValue(child.ItemType, out itemDefinition); // The NestedMetadataTable will handle the aggregation of the different metadata collections NestedMetadataTable metadataTable = new NestedMetadataTable(child.ItemType, bucket.Expander.Metadata, itemDefinition); IMetadataTable originalMetadataTable = bucket.Expander.Metadata; bucket.Expander.Metadata = metadataTable; // Second, expand the item include and exclude, and filter existing metadata as appropriate. List <ProjectItemInstance> itemsToAdd = ExpandItemIntoItems(child, bucket.Expander, keepMetadata, removeMetadata); // Third, expand the metadata. foreach (ProjectItemGroupTaskMetadataInstance metadataInstance in child.Metadata) { bool condition = ConditionEvaluator.EvaluateCondition ( metadataInstance.Condition, ParserOptions.AllowAll, bucket.Expander, ExpanderOptions.ExpandAll, Project.Directory, metadataInstance.Location, LoggingContext.LoggingService, LoggingContext.BuildEventContext, FileSystems.Default); if (condition) { string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(metadataInstance.Value, ExpanderOptions.ExpandAll, metadataInstance.Location); // This both stores the metadata so we can add it to all the items we just created later, and // exposes this metadata to further metadata evaluations in subsequent loop iterations. metadataTable.SetValue(metadataInstance.Name, evaluatedValue); } } // Finally, copy the added metadata onto the new items. The set call is additive. ProjectItemInstance.SetMetadata(metadataTable.AddedMetadata, itemsToAdd); // Add in one operation for potential copy-on-write // Restore the original metadata table. bucket.Expander.Metadata = originalMetadataTable; // Determine if we should NOT add duplicate entries bool keepDuplicates = ConditionEvaluator.EvaluateCondition ( child.KeepDuplicates, ParserOptions.AllowAll, bucket.Expander, ExpanderOptions.ExpandAll, Project.Directory, child.KeepDuplicatesLocation, LoggingContext.LoggingService, LoggingContext.BuildEventContext, FileSystems.Default); if (LogTaskInputs && !LoggingContext.LoggingService.OnlyLogCriticalEvents && itemsToAdd?.Count > 0) { ItemGroupLoggingHelper.LogTaskParameter( LoggingContext, TaskParameterMessageKind.AddItem, child.ItemType, itemsToAdd, logItemMetadata: true, child.Location); } // Now add the items we created to the lookup. bucket.Lookup.AddNewItemsOfItemType(child.ItemType, itemsToAdd, !keepDuplicates); // Add in one operation for potential copy-on-write }
internal abstract double NumericEvaluate(ConditionEvaluator.IConditionEvaluationState state);
/// <summary> /// Evaluate as boolean /// </summary> internal override bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state) { // Should be unreachable: all calls check CanBoolEvaluate() first ErrorUtilities.VerifyThrow(false, "Can't evaluate a numeric expression as boolean."); return false; }
internal abstract Version VersionEvaluate(ConditionEvaluator.IConditionEvaluationState state);
/// <summary> /// Evaluate as a Version /// </summary> internal override Version VersionEvaluate(ConditionEvaluator.IConditionEvaluationState state) { return Version.Parse(_value); }
/// <summary> /// Returns true if this node evaluates to an empty string, /// otherwise false. /// (It may be cheaper to determine whether an expression will evaluate /// to empty than to fully evaluate it.) /// Implementations should cache the result so that calls after the first are free. /// </summary> internal virtual bool EvaluatesToEmpty(ConditionEvaluator.IConditionEvaluationState state) { return false; }
/// <summary> /// Whether it can be evaluated as numeric /// </summary> internal override bool CanNumericEvaluate(ConditionEvaluator.IConditionEvaluationState state) { // It is not always possible to numerically evaluate even a numerical expression - // for example, it may overflow a double. So check here. return ConversionUtilities.ValidDecimalOrHexNumber(_value); }
/// <summary> /// Value before any item and property expressions are expanded /// </summary> /// <returns></returns> internal abstract string GetUnexpandedValue(ConditionEvaluator.IConditionEvaluationState state);
/// <summary> /// Get the expanded value /// </summary> internal override string GetExpandedValue(ConditionEvaluator.IConditionEvaluationState state) { return _value; }
/// <summary> /// Numeric evaluation is never allowed for operators /// </summary> internal override double NumericEvaluate(ConditionEvaluator.IConditionEvaluationState state) { // Should be unreachable: all calls check CanNumericEvaluate() first ErrorUtilities.VerifyThrow(false, "Cannot numeric evaluate an operator"); return 0.0D; }
/// <summary> /// Check that the number of function arguments is correct. /// </summary> /// <param name="expected"></param> private void VerifyArgumentCount(int expected, ConditionEvaluator.IConditionEvaluationState state) { ProjectErrorUtilities.VerifyThrowInvalidProject (_arguments.Count == expected, state.ElementLocation, "IncorrectNumberOfFunctionArguments", state.Condition, _arguments.Count, expected); }
protected override IEnumerable <CommandParameters> Execute(IEnumerable <CommandParameters> inParametersList) { foreach (var inParameters in inParametersList) { //inParameters = GetCurrentInParameters(); string host = inParameters.GetValue <string>("Host"); string user = inParameters.GetValue <string>("User"); string passWord = inParameters.GetValue <string>("Password"); int? port = inParameters.GetValue <int?>("Port"); bool enableSecure = inParameters.GetValue <bool>("EnableSecure"); if (!port.HasValue) { if (enableSecure) { port = 995; } else { port = 110; } } this.pop3Client.Connect(host, port.Value, enableSecure); this.pop3Client.Authenticate(user, passWord, AuthenticationMethod.UsernameAndPassword); this.LogDebugFormat("Start reading emails from Host='{0}', User='******'", host, user); int count = this.pop3Client.GetMessageCount(); this.LogDebugFormat("Found {0} emails", count); int emailIdx = 0; int emailDownloaded = 0; for (int i = count; i >= 1; i--) { MessageHeader pop3MessageHeader = this.pop3Client.GetMessageHeaders(i); emailIdx++; this.ExecuteParameters.SetOrAddValue("EmailFrom", pop3MessageHeader.From.Address); this.ExecuteParameters.SetOrAddValue("EmailTo", string.Join(",", pop3MessageHeader.To)); this.ExecuteParameters.SetOrAddValue("EmailSubject", pop3MessageHeader.Subject); this.ExecuteParameters.SetOrAddValue("EmailDate", pop3MessageHeader.DateSent.ToString()); if (this.FilterConditions.IsNullOrEmpty() || ConditionEvaluator.CheckMatchingConditions(this.FilterConditions, this.ExecuteParameters.ToDictionary())) { Message pop3Message = this.pop3Client.GetMessage(i); emailDownloaded++; { // Body string bodyText = ""; string bodyFileName = !string.IsNullOrEmpty(pop3Message.Headers.Subject) ? pop3Message.Headers.Subject : pop3Message.Headers.DateSent.ToStringOrEmpty(); var body = pop3Message.FindFirstHtmlVersion(); if (body != null) { bodyText = body.GetBodyAsText(); bodyFileName += ".html"; } else { body = pop3Message.FindFirstPlainTextVersion(); if (body != null) { bodyText = body.GetBodyAsText(); bodyFileName += ".txt"; } } var outParameters = this.GetCurrentOutParameters(); outParameters.SetOrAddValue("Data", bodyText); outParameters.SetOrAddValue("File", FileUtil.SanitizeFileName(bodyFileName)); yield return(outParameters); } // Attachments var attachments = pop3Message.FindAllAttachments(); foreach (var attachment in attachments) { var outParameters = this.GetCurrentOutParameters(); outParameters.SetOrAddValue("Data", attachment.Body); outParameters.SetOrAddValue("File", FileUtil.SanitizeFileName(attachment.FileName)); yield return(outParameters); } } } this.LogDebugFormat( "End reading emails from Host='{0}', User='******': EmailChecked={2}, EmailDownloaded={3}", host, user, emailIdx, emailDownloaded); } }
/// <summary> /// Expands properties and items in the argument, and verifies that the result is consistent /// with a scalar parameter type. /// </summary> /// <param name="function">Function name for errors</param> /// <param name="argumentNode">Argument to be expanded</param> /// <returns>Scalar result</returns> private string ExpandArgumentForScalarParameter(string function, GenericExpressionNode argumentNode, ConditionEvaluator.IConditionEvaluationState state) { string argument = argumentNode.GetUnexpandedValue(state); IList<TaskItem> items; items = state.ExpandIntoTaskItems(argument); string expandedValue = String.Empty; if (items.Count == 0) { // Empty argument, that's fine. } else if (items.Count == 1) { expandedValue = items[0].ItemSpec; } else // too many items for the function { // We only allow a single item to be passed into a scalar parameter. ProjectErrorUtilities.ThrowInvalidProject( state.ElementLocation, "CannotPassMultipleItemsIntoScalarFunction", function, argument, state.ExpandIntoString(argument)); } return expandedValue; }
private void FilterUnneededProperties(Project project, XElement propertyGroup, IDictionary <string, string> globalOverrides, string msbuildProjectName) { var removeQueue = new List <XElement>(); foreach (var child in propertyGroup.Elements()) { var parentCondition = propertyGroup.Attribute("Condition")?.Value.Trim() ?? ""; var hasParentCondition = parentCondition.Length > 1; // no sane condition is 1 char long var parentConditionEvaluated = ConditionEvaluator.GetNonAmbiguousConditionContracts(parentCondition); var parentConditionHasPlatform = parentConditionEvaluated.TryGetValue("Platform", out var parentConditionPlatform); var parentConditionHasConfiguration = parentConditionEvaluated.TryGetValue("Configuration", out var parentConditionConfiguration); var parentConditionPlatformLower = parentConditionPlatform?.ToLowerInvariant(); var parentConditionConfigurationLower = parentConditionConfiguration?.ToLowerInvariant(); var isDebugOnly = parentConditionHasConfiguration && parentConditionConfigurationLower == "debug"; var isReleaseOnly = parentConditionHasConfiguration && parentConditionConfigurationLower == "release"; var tagLocalName = child.Name.LocalName; var valueLower = child.Value.ToLowerInvariant(); var valueLowerTrim = valueLower.Trim(); var emptyValue = valueLowerTrim.Length == 0; var hasGlobalOverride = globalOverrides.TryGetValue(tagLocalName, out var globalOverride); var globalOverrideLower = globalOverride?.ToLowerInvariant(); // Regex is the easiest way to replace string between two unknown chars preserving both as is // so that bin\Debug\net472 is turned into bin\$(Configuration)\net472 // and bin/Debug\net472 is turned into bin/$(Configuration)\net472, preserving path separators var configurationPathRegex = parentConditionHasConfiguration ? new Regex($@"([\\/]){parentConditionConfiguration}([\\/])") : null; var platformPathRegex = parentConditionHasPlatform ? new Regex($@"([\\/]){parentConditionPlatform}([\\/])") : null; var hasCondition = child.PropertyCondition(out var fullCondition); var fullState = hasCondition ? ConditionEvaluator.GetConditionState(fullCondition) : null; switch (tagLocalName) { // VS2013 NuGet bugs workaround case "NuGetPackageImportStamp": // legacy generic properties case "MinimumVisualStudioVersion": case "VisualStudioVersion": case "OldToolsVersion": // legacy frameworks case "TargetFrameworkIdentifier" when !hasParentCondition: case "TargetFrameworkProfile" when !hasParentCondition && emptyValue: // VCS properties case "SccProjectName" when emptyValue: case "SccLocalPath" when emptyValue: case "SccAuxPath" when emptyValue: case "SccProvider" when emptyValue: // Project properties set to defaults (Microsoft.NET.Sdk) case "OutputType" when ValidateDefaultValue("library"): case "FileAlignment" when ValidateDefaultValue("512"): case "ErrorReport" when ValidateDefaultValue("prompt"): case "Deterministic" when ValidateDefaultValue("true"): case "WarningLevel" when ValidateDefaultValue("4"): case "DebugType" when ValidateDefaultValue("portable"): case "ResolveNuGetPackages" when ValidateDefaultValue("false"): case "SkipImportNuGetProps" when ValidateDefaultValue("true"): case "SkipImportNuGetBuildTargets" when ValidateDefaultValue("true"): case "RestoreProjectStyle" when ValidateDefaultValue("packagereference"): case "AllowUnsafeBlocks" when ValidateDefaultValue("false"): case "TreatWarningsAsErrors" when ValidateDefaultValue("false"): case "Prefer32Bit" when ValidateDefaultValue("false"): case "SignAssembly" when ValidateDefaultValue("false"): case "DelaySign" when ValidateDefaultValue("false"): case "GeneratePackageOnBuild" when ValidateDefaultValue("false"): case "PackageRequireLicenseAcceptance" when ValidateDefaultValue("false"): case "DebugSymbols" when ValidateDefaultValue("false"): case "CheckForOverflowUnderflow" when ValidateDefaultValue("false"): case "AppendTargetFrameworkToOutputPath" when ValidateDefaultValue("true"): case "AppDesignerFolder" when ValidateDefaultValue("properties"): case "DefaultProjectTypeGuid" when ValidateDefaultValue("{fae04ec0-301f-11d3-bf4b-00c04f79efbc}"): case "DefaultLanguageSourceExtension" when ValidateDefaultValue(".cs"): case "Language" when ValidateDefaultValue("C#"): case "TargetRuntime" when ValidateDefaultValue("managed"): case "Utf8Output" when ValidateDefaultValue("true"): case "PlatformName" when ValidateDefaultValue("$(platform)") || ( parentConditionHasPlatform && ValidateDefaultValue(parentConditionPlatformLower) ): case "RestorePackages" when ValidateDefaultValue("true"): case "SchemaVersion" when ValidateDefaultValue("2.0"): case "AssemblyVersion" when ValidateDefaultVersion(): case "FileVersion" when ValidateDefaultVersion(): case "Version" when ValidateDefaultValue("1.0.0"): // Conditional platform default values case "PlatformTarget" when parentConditionHasPlatform && child.Value == parentConditionPlatform && !hasGlobalOverride: // Conditional configuration (Debug/Release) default values case "DefineConstants" when isDebugOnly && ValidateDefaultConstants(valueLower, "debug", "trace") && !hasGlobalOverride: case "DefineConstants" when isReleaseOnly && ValidateDefaultConstants(valueLower, "trace") && !hasGlobalOverride: case "Optimize" when isDebugOnly && valueLower == "false" && !hasGlobalOverride: case "Optimize" when isReleaseOnly && valueLower == "true" && !hasGlobalOverride: case "DebugSymbols" when isDebugOnly && valueLower == "true" && !hasGlobalOverride: // Default project values for Platform and Configuration case "Platform" when ValidateEmptyConditionValue() && valueLower == "anycpu": case "Configuration" when ValidateEmptyConditionValue() && valueLower == "debug": case "Platforms" when !hasParentCondition && ValidateDefaultConstants(valueLower, "anycpu"): case "Configurations" when !hasParentCondition && ValidateDefaultConstants(valueLower, "debug", "release"): // Extra ProjectName duplicates case "RootNamespace" when IsDefaultProjectNameValued(): case "AssemblyName" when IsDefaultProjectNameValued(): case "TargetName" when IsDefaultProjectNameValued(): case "ProjectGuid" when ProjectGuidMatchesSolutionProjectGuid(): { removeQueue.Add(child); break; } } if (parentConditionHasConfiguration || parentConditionHasPlatform) { switch (tagLocalName) { case "OutputPath": case "IntermediateOutputPath": case "DocumentationFile": case "CodeAnalysisRuleSet": { child.Value = ReplaceWithPlaceholders(child.Value); break; } } } // following local methods will capture parent scope bool ValidateDefaultValue(string @default) { return((!hasParentCondition && valueLower == @default) || (hasParentCondition && ValidateConditionedDefaultValue(@default))); } bool ValidateConditionedDefaultValue(string @default) { return((valueLower == @default) && (!hasGlobalOverride || globalOverrideLower == @default)); } bool ValidateDefaultVersion() { return(ValidateDefaultValue("1.0.0.0") || ValidateDefaultValue("1.0.0") || ValidateDefaultValue("1.0") || ValidateDefaultValue("1")); } string ReplaceWithPlaceholders(string value) { if (parentConditionHasConfiguration) { value = configurationPathRegex.Replace(value, "$1$(Configuration)$2"); } if (parentConditionHasPlatform) { value = platformPathRegex.Replace(value, "$1$(Platform)$2"); } return(value); } bool ValidateEmptyConditionValue() { if (!hasCondition || string.IsNullOrWhiteSpace(fullCondition)) { return(true); } return((fullCondition.Count(x => x == '=') == 2) && fullCondition.Contains("''")); } bool IsDefaultProjectNameValued() { return(ValidateEmptyConditionValue() && ( child.Value == msbuildProjectName || IgnoreProjectNameValues.Contains(child.Value) )); } } // we cannot remove elements correctly while iterating through elements, 2nd pass is needed foreach (var child in removeQueue) { child.Remove(); } bool ProjectGuidMatchesSolutionProjectGuid() { return(project.Solution != null && project.Solution.ProjectPaths .Any(x => x.ProjectName == project.ProjectName && x.ProjectGuid == project.ProjectGuid)); } }
/// <summary> /// Runs all of the tasks for this target, batched as necessary. /// </summary> internal async Task ExecuteTarget(ITaskBuilder taskBuilder, BuildRequestEntry requestEntry, ProjectLoggingContext projectLoggingContext, CancellationToken cancellationToken) { #if MSBUILDENABLEVSPROFILING try { string beginTargetBuild = String.Format(CultureInfo.CurrentCulture, "Build Target {0} in Project {1} - Start", this.Name, projectFullPath); DataCollection.CommentMarkProfile(8800, beginTargetBuild); #endif try { VerifyState(_state, TargetEntryState.Execution); ErrorUtilities.VerifyThrow(!_isExecuting, "Target {0} is already executing", _target.Name); _cancellationToken = cancellationToken; _isExecuting = true; // Generate the batching buckets. Note that each bucket will get a lookup based on the baseLookup. This lookup will be in its // own scope, which we will collapse back down into the baseLookup at the bottom of the function. List <ItemBucket> buckets = BatchingEngine.PrepareBatchingBuckets(GetBatchableParametersForTarget(), _baseLookup, _target.Location); WorkUnitResult aggregateResult = new WorkUnitResult(); TargetLoggingContext targetLoggingContext = null; bool targetSuccess = false; int numberOfBuckets = buckets.Count; string projectFullPath = requestEntry.RequestConfiguration.ProjectFullPath; string parentTargetName = null; if (ParentEntry != null && ParentEntry.Target != null) { parentTargetName = ParentEntry.Target.Name; } for (int i = 0; i < numberOfBuckets; i++) { ItemBucket bucket = buckets[i]; // If one of the buckets failed, stop building. if (aggregateResult.ActionCode == WorkUnitActionCode.Stop) { break; } targetLoggingContext = projectLoggingContext.LogTargetBatchStarted(projectFullPath, _target, parentTargetName); WorkUnitResult bucketResult = null; targetSuccess = false; Lookup.Scope entryForInference = null; Lookup.Scope entryForExecution = null; try { // This isn't really dependency analysis. This is up-to-date checking. Based on this we will be able to determine if we should // run tasks in inference or execution mode (or both) or just skip them altogether. ItemDictionary <ProjectItemInstance> changedTargetInputs; ItemDictionary <ProjectItemInstance> upToDateTargetInputs; Lookup lookupForInference; Lookup lookupForExecution; // UNDONE: (Refactor) Refactor TargetUpToDateChecker to take a logging context, not a logging service. TargetUpToDateChecker dependencyAnalyzer = new TargetUpToDateChecker(requestEntry.RequestConfiguration.Project, _target, targetLoggingContext.LoggingService, targetLoggingContext.BuildEventContext); DependencyAnalysisResult dependencyResult = dependencyAnalyzer.PerformDependencyAnalysis(bucket, out changedTargetInputs, out upToDateTargetInputs); switch (dependencyResult) { // UNDONE: Need to enter/leave debugger scope properly for the <Target> element. case DependencyAnalysisResult.FullBuild: case DependencyAnalysisResult.IncrementalBuild: case DependencyAnalysisResult.SkipUpToDate: // Create the lookups used to hold the current set of properties and items lookupForInference = bucket.Lookup; lookupForExecution = bucket.Lookup.Clone(); // Push the lookup stack up one so that we are only modifying items and properties in that scope. entryForInference = lookupForInference.EnterScope("ExecuteTarget() Inference"); entryForExecution = lookupForExecution.EnterScope("ExecuteTarget() Execution"); // if we're doing an incremental build, we need to effectively run the task twice -- once // to infer the outputs for up-to-date input items, and once to actually execute the task; // as a result we need separate sets of item and property collections to track changes if (dependencyResult == DependencyAnalysisResult.IncrementalBuild) { // subset the relevant items to those that are up-to-date foreach (string itemType in upToDateTargetInputs.ItemTypes) { lookupForInference.PopulateWithItems(itemType, upToDateTargetInputs[itemType]); } // subset the relevant items to those that have changed foreach (string itemType in changedTargetInputs.ItemTypes) { lookupForExecution.PopulateWithItems(itemType, changedTargetInputs[itemType]); } } // We either have some work to do or at least we need to infer outputs from inputs. bucketResult = await ProcessBucket(taskBuilder, targetLoggingContext, GetTaskExecutionMode(dependencyResult), lookupForInference, lookupForExecution); // Now aggregate the result with the existing known results. There are four rules, assuming the target was not // skipped due to being up-to-date: // 1. If this bucket failed or was cancelled, the aggregate result is failure. // 2. If this bucket Succeeded and we have not previously failed, the aggregate result is a success. // 3. Otherwise, the bucket was skipped, which has no effect on the aggregate result. // 4. If the bucket's action code says to stop, then we stop, regardless of the success or failure state. if (dependencyResult != DependencyAnalysisResult.SkipUpToDate) { aggregateResult = aggregateResult.AggregateResult(bucketResult); } else { if (aggregateResult.ResultCode == WorkUnitResultCode.Skipped) { aggregateResult = aggregateResult.AggregateResult(new WorkUnitResult(WorkUnitResultCode.Success, WorkUnitActionCode.Continue, null)); } } // Pop the lookup scopes, causing them to collapse their values back down into the // bucket's lookup. // NOTE: this order is important because when we infer outputs, we are trying // to produce the same results as would be produced from a full build; as such // if we're doing both the infer and execute steps, we want the outputs from // the execute step to override the outputs of the infer step -- this models // the full build scenario more correctly than if the steps were reversed entryForInference.LeaveScope(); entryForInference = null; entryForExecution.LeaveScope(); entryForExecution = null; targetSuccess = (bucketResult != null) && (bucketResult.ResultCode == WorkUnitResultCode.Success); break; case DependencyAnalysisResult.SkipNoInputs: case DependencyAnalysisResult.SkipNoOutputs: // We have either no inputs or no outputs, so there is nothing to do. targetSuccess = true; break; } } catch (InvalidProjectFileException e) { // Make sure the Invalid Project error gets logged *before* TargetFinished. Otherwise, // the log is confusing. targetLoggingContext.LogInvalidProjectFileError(e); if (null != entryForInference) { entryForInference.LeaveScope(); } if (null != entryForExecution) { entryForExecution.LeaveScope(); } aggregateResult = aggregateResult.AggregateResult(new WorkUnitResult(WorkUnitResultCode.Failed, WorkUnitActionCode.Stop, null)); } finally { // Don't log the last target finished event until we can process the target outputs as we want to attach them to the // last target batch. if (targetLoggingContext != null && i < numberOfBuckets - 1) { targetLoggingContext.LogTargetBatchFinished(projectFullPath, targetSuccess, null); targetLoggingContext = null; } } } // Produce the final results. List <TaskItem> targetOutputItems = new List <TaskItem>(); try { // If any legacy CallTarget operations took place, integrate them back in to the main lookup now. LeaveLegacyCallTargetScopes(); // Publish the items for each bucket back into the baseLookup. Note that EnterScope() was actually called on each // bucket inside of the ItemBucket constructor, which is why you don't see it anywhere around here. foreach (ItemBucket bucket in buckets) { bucket.LeaveScope(); } string targetReturns = _target.Returns; ElementLocation targetReturnsLocation = _target.ReturnsLocation; // If there are no targets in the project file that use the "Returns" attribute, that means that we // revert to the legacy behavior in the case where Returns is not specified (null, rather // than the empty string, which indicates no returns). Legacy behavior is for all // of the target's Outputs to be returned. // On the other hand, if there is at least one target in the file that uses the Returns attribute, // then all targets in the file are run according to the new behaviour (return nothing unless otherwise // specified by the Returns attribute). if (targetReturns == null) { if (!_target.ParentProjectSupportsReturnsAttribute) { targetReturns = _target.Outputs; targetReturnsLocation = _target.OutputsLocation; } } if (!String.IsNullOrEmpty(targetReturns)) { // Determine if we should keep duplicates. bool keepDupes = ConditionEvaluator.EvaluateCondition ( _target.KeepDuplicateOutputs, ParserOptions.AllowPropertiesAndItemLists, _expander, ExpanderOptions.ExpandPropertiesAndItems, requestEntry.ProjectRootDirectory, _target.KeepDuplicateOutputsLocation, projectLoggingContext.LoggingService, projectLoggingContext.BuildEventContext ); // NOTE: we need to gather the outputs in batches, because the output specification may reference item metadata // Also, we are using the baseLookup, which has possibly had changes made to it since the project started. Because of this, the // set of outputs calculated here may differ from those which would have been calculated at the beginning of the target. It is // assumed the user intended this. List <ItemBucket> batchingBuckets = BatchingEngine.PrepareBatchingBuckets(GetBatchableParametersForTarget(), _baseLookup, _target.Location); if (keepDupes) { foreach (ItemBucket bucket in batchingBuckets) { targetOutputItems.AddRange(bucket.Expander.ExpandIntoTaskItemsLeaveEscaped(targetReturns, ExpanderOptions.ExpandAll, targetReturnsLocation)); } } else { HashSet <TaskItem> addedItems = new HashSet <TaskItem>(); foreach (ItemBucket bucket in batchingBuckets) { IList <TaskItem> itemsToAdd = bucket.Expander.ExpandIntoTaskItemsLeaveEscaped(targetReturns, ExpanderOptions.ExpandAll, targetReturnsLocation); foreach (TaskItem item in itemsToAdd) { if (!addedItems.Contains(item)) { targetOutputItems.Add(item); addedItems.Add(item); } } } } } } finally { if (targetLoggingContext != null) { // log the last target finished since we now have the target outputs. targetLoggingContext.LogTargetBatchFinished(projectFullPath, targetSuccess, targetOutputItems != null && targetOutputItems.Count > 0 ? targetOutputItems : null); } } _targetResult = new TargetResult(targetOutputItems.ToArray(), aggregateResult); if (aggregateResult.ResultCode == WorkUnitResultCode.Failed && aggregateResult.ActionCode == WorkUnitActionCode.Stop) { _state = TargetEntryState.ErrorExecution; } else { _state = TargetEntryState.Completed; } } finally { _isExecuting = false; } #if MSBUILDENABLEVSPROFILING } finally { string endTargetBuild = String.Format(CultureInfo.CurrentCulture, "Build Target {0} in Project {1} - End", this.Name, projectFullPath); DataCollection.CommentMarkProfile(8801, endTargetBuild); } #endif }
public void GetBuckets() { ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance(); List <string> parameters = new List <string>(); parameters.Add("@(File);$(unittests)"); parameters.Add("$(obj)\\%(Filename).ext"); parameters.Add("@(File->'%(extension)')"); // attributes in transforms don't affect batching ItemDictionary <ProjectItemInstance> itemsByType = new ItemDictionary <ProjectItemInstance>(); IList <ProjectItemInstance> items = new List <ProjectItemInstance>(); items.Add(new ProjectItemInstance(project, "File", "a.foo", project.FullPath)); items.Add(new ProjectItemInstance(project, "File", "b.foo", project.FullPath)); items.Add(new ProjectItemInstance(project, "File", "c.foo", project.FullPath)); items.Add(new ProjectItemInstance(project, "File", "d.foo", project.FullPath)); items.Add(new ProjectItemInstance(project, "File", "e.foo", project.FullPath)); itemsByType.ImportItems(items); items = new List <ProjectItemInstance>(); items.Add(new ProjectItemInstance(project, "Doc", "a.doc", project.FullPath)); items.Add(new ProjectItemInstance(project, "Doc", "b.doc", project.FullPath)); items.Add(new ProjectItemInstance(project, "Doc", "c.doc", project.FullPath)); items.Add(new ProjectItemInstance(project, "Doc", "d.doc", project.FullPath)); items.Add(new ProjectItemInstance(project, "Doc", "e.doc", project.FullPath)); itemsByType.ImportItems(items); PropertyDictionary <ProjectPropertyInstance> properties = new PropertyDictionary <ProjectPropertyInstance>(); properties.Set(ProjectPropertyInstance.Create("UnitTests", "unittests.foo")); properties.Set(ProjectPropertyInstance.Create("OBJ", "obj")); List <ItemBucket> buckets = BatchingEngine.PrepareBatchingBuckets(parameters, CreateLookup(itemsByType, properties), MockElementLocation.Instance); Assert.Equal(5, buckets.Count); foreach (ItemBucket bucket in buckets) { // non-batching data -- same for all buckets XmlAttribute tempXmlAttribute = (new XmlDocument()).CreateAttribute("attrib"); tempXmlAttribute.Value = "'$(Obj)'=='obj'"; Assert.True(ConditionEvaluator.EvaluateCondition(tempXmlAttribute.Value, ParserOptions.AllowAll, bucket.Expander, ExpanderOptions.ExpandAll, Directory.GetCurrentDirectory(), MockElementLocation.Instance, null, new BuildEventContext(1, 2, 3, 4))); Assert.Equal("a.doc;b.doc;c.doc;d.doc;e.doc", bucket.Expander.ExpandIntoStringAndUnescape("@(doc)", ExpanderOptions.ExpandItems, MockElementLocation.Instance)); Assert.Equal("unittests.foo", bucket.Expander.ExpandIntoStringAndUnescape("$(bogus)$(UNITTESTS)", ExpanderOptions.ExpandPropertiesAndMetadata, MockElementLocation.Instance)); } Assert.Equal("a.foo", buckets[0].Expander.ExpandIntoStringAndUnescape("@(File)", ExpanderOptions.ExpandItems, MockElementLocation.Instance)); Assert.Equal(".foo", buckets[0].Expander.ExpandIntoStringAndUnescape("@(File->'%(Extension)')", ExpanderOptions.ExpandItems, MockElementLocation.Instance)); Assert.Equal("obj\\a.ext", buckets[0].Expander.ExpandIntoStringAndUnescape("$(obj)\\%(Filename).ext", ExpanderOptions.ExpandPropertiesAndMetadata, MockElementLocation.Instance)); // we weren't batching on this attribute, so it has no value Assert.Equal(String.Empty, buckets[0].Expander.ExpandIntoStringAndUnescape("%(Extension)", ExpanderOptions.ExpandAll, MockElementLocation.Instance)); ProjectItemInstanceFactory factory = new ProjectItemInstanceFactory(project, "i"); items = buckets[0].Expander.ExpandIntoItemsLeaveEscaped("@(file)", factory, ExpanderOptions.ExpandItems, MockElementLocation.Instance); Assert.NotNull(items); Assert.Equal(1, items.Count); int invalidProjectFileExceptions = 0; try { // This should throw because we don't allow item lists to be concatenated // with other strings. bool throwAway; items = buckets[0].Expander.ExpandSingleItemVectorExpressionIntoItems("@(file)$(unitests)", factory, ExpanderOptions.ExpandItems, false /* no nulls */, out throwAway, MockElementLocation.Instance); } catch (InvalidProjectFileException ex) { // check we don't lose error codes from IPFE's during build Assert.Equal(ex.ErrorCode, "MSB4012"); invalidProjectFileExceptions++; } // We do allow separators in item vectors, this results in an item group with a single flattened item items = buckets[0].Expander.ExpandIntoItemsLeaveEscaped("@(file, ',')", factory, ExpanderOptions.ExpandItems, MockElementLocation.Instance); Assert.NotNull(items); Assert.Equal(1, items.Count); Assert.Equal("a.foo", items[0].EvaluatedInclude); Assert.Equal(1, invalidProjectFileExceptions); }
private void AssertParseEvaluateThrow(Parser p, string expression, Expander<ProjectPropertyInstance, ProjectItemInstance> expander, ConditionEvaluator.IConditionEvaluationState state) { bool fExceptionCaught; if (expander.Metadata == null) { expander.Metadata = new StringMetadataTable(null); } try { fExceptionCaught = false; GenericExpressionNode tree = p.Parse(expression, ParserOptions.AllowAll, MockElementLocation.Instance); if (state == null) { state = new ConditionEvaluator.ConditionEvaluationState<ProjectPropertyInstance, ProjectItemInstance> ( String.Empty, expander, ExpanderOptions.ExpandAll, null, Environment.CurrentDirectory, ElementLocation.EmptyLocation ); } tree.Evaluate(state); } catch (InvalidProjectFileException e) { Console.WriteLine(e.BaseMessage); fExceptionCaught = true; } Assert.IsTrue(fExceptionCaught); }
/// <summary> /// Whether boolean evaluation is allowed: always allowed for operators /// </summary> internal override bool CanBoolEvaluate(ConditionEvaluator.IConditionEvaluationState state) { return true; }