/// <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);
        }
Exemple #5
0
        /// <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;
        }
Exemple #7
0
        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
                });
            });
        }
Exemple #8
0
        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));
            }
        }
Exemple #9
0
        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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
 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));
 }
Exemple #12
0
        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);
        }
Exemple #13
0
        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);
        }
Exemple #14
0
        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());
        }
Exemple #15
0
        // 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
            });
        }
Exemple #16
0
        // 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);
            }
        }
Exemple #18
0
        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());
        }
Exemple #19
0
        // 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
            });
        }
Exemple #20
0
        /// <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;
        }
Exemple #22
0
        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());
        }
Exemple #23
0
        //[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");
        }
Exemple #24
0
        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>());
        }
Exemple #25
0
        //[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
                });
            }
        }
Exemple #28
0
        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);
        }
Exemple #29
0
        /// <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;
 }
Exemple #40
0
        /// <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);
 }
Exemple #54
0
        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;
        }
Exemple #56
0
        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));
            }
        }
Exemple #57
0
        /// <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;
 }