Exemplo n.º 1
0
        //
        // Top node of grammar
        //    See grammar for how the following methods relate to each
        //    other.
        //
        private GenericExpressionNode Expr(string expression)
        {
            GenericExpressionNode node = BooleanTerm(expression);

            if (!lexer.IsNext(Token.TokenType.EndOfInput))
            {
                node = ExprPrime(expression, node);
            }

            #region REMOVE_COMPAT_WARNING
            // Check for potential change in behavior
            if (LoggingServices != null && !warnedForExpression &&
                node.PotentialAndOrConflict())
            {
                // We only want to warn once even if there multiple () sub expressions
                warnedForExpression = true;
                // Try to figure out where this expression was located
                string projectFile  = String.Empty;
                int    lineNumber   = 0;
                int    columnNumber = 0;
                if (this.conditionAttribute != null)
                {
                    projectFile = XmlUtilities.GetXmlNodeFile(this.conditionAttribute, String.Empty /* no project file if XML is purely in-memory */);
                    XmlSearcher.GetLineColumnByNode(this.conditionAttribute, out lineNumber, out columnNumber);
                }
                // Log a warning regarding the fact the expression may have been evaluated
                // incorrectly in earlier version of MSBuild
                LoggingServices.LogWarning(logBuildEventContext, new BuildEventFileInfo(projectFile, lineNumber, columnNumber), "ConditionMaybeEvaluatedIncorrectly", expression);
            }
            #endregion

            return(node);
        }
Exemplo n.º 2
0
        //
        // Main entry point for parser.
        // You pass in the expression you want to parse, and you get an
        // ExpressionTree out the back end.
        //
        internal GenericExpressionNode Parse(string expression, XmlAttribute conditionAttributeRef, ParserOptions optionSettings)
        {
            // We currently have no support (and no scenarios) for disallowing property references
            // in Conditions.
            ErrorUtilities.VerifyThrow(0 != (optionSettings & ParserOptions.AllowProperties),
                                       "Properties should always be allowed.");

            this.conditionAttribute = conditionAttributeRef;
            this.options            = optionSettings;

            lexer = new Scanner(expression, options);
            if (!lexer.Advance())
            {
                errorPosition = lexer.GetErrorPosition();
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, lexer.GetErrorResource(), expression, errorPosition, lexer.UnexpectedlyFound);
            }
            GenericExpressionNode node = Expr(expression);

            if (!lexer.IsNext(Token.TokenType.EndOfInput))
            {
                errorPosition = lexer.GetErrorPosition();
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
            }
            return(node);
        }
Exemplo n.º 3
0
        private GenericExpressionNode BooleanTermPrime(string expression, GenericExpressionNode lhs)
        {
            if (lexer.IsNext(Token.TokenType.EndOfInput))
            {
                return(lhs);
            }
            else if (Same(expression, Token.TokenType.And))
            {
                GenericExpressionNode rhs = RelationalExpr(expression);
                if (rhs == null)
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                }

                OperatorExpressionNode andNode = new AndExpressionNode();
                andNode.LeftChild  = lhs;
                andNode.RightChild = rhs;
                return(BooleanTermPrime(expression, andNode));
            }
            else
            {
                // Should this be error case?
                return(lhs);
            }
        }
        /// <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>
        /// <owner>danmose</owner>
        private string ExpandArgumentForScalarParameter(string function, GenericExpressionNode argumentNode, ConditionEvaluationState state)
        {
            string argument = argumentNode.GetUnexpandedValue(state);

            List <TaskItem> items = state.expanderToUse.ExpandAllIntoTaskItems(argument, state.conditionAttribute);

            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.VerifyThrowInvalidProject(false,
                                                                state.conditionAttribute,
                                                                "CannotPassMultipleItemsIntoScalarFunction", function, argument,
                                                                state.expanderToUse.ExpandAllIntoString(argument, state.conditionAttribute));
            }

            return(expandedValue);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Evaluates a string representing a condition from a "condition" attribute.
        /// If the condition is a malformed string, it throws an InvalidProjectFileException.
        /// This method uses cached expression trees to avoid generating them from scratch every time it's called.
        /// This method is thread safe and is called from engine and task execution module threads
        /// </summary>
        /// <param name="condition">Can be null</param>
        /// <param name="conditionAttribute">XML attribute on which the condition is evaluated</param>
        /// <param name="expander">All the data available for expanding embedded properties, metadata, and items</param>
        /// <param name="conditionedPropertiesTable">Can be null</param>
        /// <param name="itemListOptions"></param>
        /// <param name="loggingServices">Can be null</param>
        /// <param name="buildEventContext"> contains contextual information for logging events</param>
        /// <returns>true, if the expression evaluates to true, otherwise false</returns>
        internal static bool EvaluateCondition
        (
            string condition,
            XmlAttribute conditionAttribute,
            Expander expander,
            Hashtable conditionedPropertiesTable,
            ParserOptions itemListOptions,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext
        )
        {
            ErrorUtilities.VerifyThrow((conditionAttribute != null) || (condition.Length == 0),
                                       "If condition is non-empty, you must provide the XML node representing the condition.");

            // An empty condition is equivalent to a "true" condition.
            if ((null == condition) || (condition.Length == 0))
            {
                return(true);
            }

            Hashtable cachedExpressionTreesForCurrentOptions = cachedExpressionTrees[(int)itemListOptions];

            // Try and see if we have an expression tree for this condition already
            GenericExpressionNode parsedExpression = (GenericExpressionNode)cachedExpressionTreesForCurrentOptions[condition];

            if (parsedExpression == null)
            {
                Parser conditionParser = new Parser();

                #region REMOVE_COMPAT_WARNING
                conditionParser.LoggingServices      = loggingServices;
                conditionParser.LogBuildEventContext = buildEventContext;
                #endregion

                parsedExpression = conditionParser.Parse(condition, conditionAttribute, itemListOptions);

                // It's possible two threads will add a different tree to the same entry in the hashtable,
                // but it should be rare and it's not a problem - the previous entry will be thrown away.
                // We could ensure no dupes with double check locking but it's not really necessary here.
                // Also, we don't want to lock on every read.
                lock (cachedExpressionTreesForCurrentOptions)
                {
                    cachedExpressionTreesForCurrentOptions[condition] = parsedExpression;
                }
            }

            ConditionEvaluationState state = new ConditionEvaluationState(conditionAttribute, expander, conditionedPropertiesTable, condition);
            bool result;

            // We are evaluating this expression now and it can cache some state for the duration,
            // so we don't want multiple threads working on the same expression
            lock (parsedExpression)
            {
                result = parsedExpression.Evaluate(state);
                parsedExpression.ResetState();
            }

            return(result);
        }
Exemplo n.º 6
0
        private void Args(string expression, ArrayList arglist)
        {
            GenericExpressionNode arg = Arg(expression);

            arglist.Add(arg);
            if (Same(expression, Token.TokenType.Comma))
            {
                Args(expression, arglist);
            }
        }
Exemplo n.º 7
0
        private GenericExpressionNode BooleanTerm(string expression)
        {
            GenericExpressionNode node = RelationalExpr(expression);

            if (node == null)
            {
                errorPosition = lexer.GetErrorPosition();
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
            }

            if (!lexer.IsNext(Token.TokenType.EndOfInput))
            {
                node = BooleanTermPrime(expression, node);
            }
            return(node);
        }
Exemplo n.º 8
0
        private GenericExpressionNode RelationalExpr(string expression)
        {
            {
                GenericExpressionNode lhs = Factor(expression);
                if (lhs == null)
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                }

                OperatorExpressionNode node = RelationalOperation(expression);
                if (node == null)
                {
                    return(lhs);
                }
                GenericExpressionNode rhs = Factor(expression);
                node.LeftChild  = lhs;
                node.RightChild = rhs;
                return(node);
            }
        }
Exemplo n.º 9
0
 private GenericExpressionNode ExprPrime(string expression, GenericExpressionNode lhs)
 {
     if (Same(expression, Token.TokenType.EndOfInput))
     {
         return(lhs);
     }
     else if (Same(expression, Token.TokenType.Or))
     {
         OperatorExpressionNode orNode = new OrExpressionNode();
         GenericExpressionNode  rhs    = BooleanTerm(expression);
         orNode.LeftChild  = lhs;
         orNode.RightChild = rhs;
         return(ExprPrime(expression, orNode));
     }
     else
     {
         // I think this is ok.  ExprPrime always shows up at
         // the rightmost side of the grammar rhs, the EndOfInput case
         // takes care of things
         return(lhs);
     }
 }
Exemplo n.º 10
0
        private GenericExpressionNode BooleanTermPrime(string expression, GenericExpressionNode lhs)
        {
            if (lexer.IsNext(Token.TokenType.EndOfInput))
            {
                return lhs;
            }
            else if (Same(expression, Token.TokenType.And))
            {
                GenericExpressionNode rhs = RelationalExpr(expression);
                if (null == rhs)
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                }

                OperatorExpressionNode andNode = new AndExpressionNode();
                andNode.LeftChild = lhs;
                andNode.RightChild = rhs;
                return BooleanTermPrime(expression, andNode);
            }
            else
            {
                // Should this be error case?
                return lhs;
            }
        }
Exemplo n.º 11
0
 private GenericExpressionNode ExprPrime(string expression, GenericExpressionNode lhs)
 {
     if (Same(expression, Token.TokenType.EndOfInput))
     {
         return lhs;
     }
     else if (Same(expression, Token.TokenType.Or))
     {
         OperatorExpressionNode orNode = new OrExpressionNode();
         GenericExpressionNode rhs = BooleanTerm(expression);
         orNode.LeftChild = lhs;
         orNode.RightChild = rhs;
         return ExprPrime( expression, orNode );
     }
     else
     {
         // I think this is ok.  ExprPrime always shows up at
         // the rightmost side of the grammar rhs, the EndOfInput case
         // takes care of things
         return lhs;
     }
 }
Exemplo n.º 12
0
        private GenericExpressionNode Factor(string expression)
        {
            // Checks for TokenTypes String, Numeric, Property, ItemMetadata, and ItemList.
            GenericExpressionNode arg = this.Arg(expression);

            // If it's one of those, return it.
            if (arg != null)
            {
                return(arg);
            }

            // If it's not one of those, check for other TokenTypes.
            Token current = lexer.CurrentToken;

            if (Same(expression, Token.TokenType.Function))
            {
                if (!Same(expression, Token.TokenType.LeftParenthesis))
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", lexer.IsNextString(), errorPosition);
                    return(null);
                }
                ArrayList arglist = new ArrayList();
                Arglist(expression, arglist);
                if (!Same(expression, Token.TokenType.RightParenthesis))
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                    return(null);
                }
                return(new FunctionCallExpressionNode(current.String, arglist));
            }
            else if (Same(expression, Token.TokenType.LeftParenthesis))
            {
                GenericExpressionNode child = Expr(expression);
                if (Same(expression, Token.TokenType.RightParenthesis))
                {
                    return(child);
                }
                else
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                }
            }
            else if (Same(expression, Token.TokenType.Not))
            {
                OperatorExpressionNode notNode = new NotExpressionNode();
                GenericExpressionNode  expr    = Factor(expression);
                if (expr == null)
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                }
                notNode.LeftChild = expr;
                return(notNode);
            }
            else
            {
                errorPosition = lexer.GetErrorPosition();
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
            }
            return(null);
        }
Exemplo n.º 13
0
        /// <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>
        /// <owner>danmose</owner>
        private string ExpandArgumentForScalarParameter(string function, GenericExpressionNode argumentNode, ConditionEvaluationState state)
        {
            string argument = argumentNode.GetUnexpandedValue(state);

            List<TaskItem> items = state.expanderToUse.ExpandAllIntoTaskItems(argument, state.conditionAttribute); 

            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.VerifyThrowInvalidProject(false,
                    state.conditionAttribute,
                    "CannotPassMultipleItemsIntoScalarFunction", function, argument,
                    state.expanderToUse.ExpandAllIntoString(argument, state.conditionAttribute));
            }

            return expandedValue;
        }