コード例 #1
0
        static ExpressionNode ParseItem(string buffer, ref int offset, int endOffset, int baseOffset)
        {
            int start = offset - 2;

            string name = ReadName(buffer, ref offset, endOffset);

            if (name == null)
            {
                return(new ExpressionError(baseOffset + offset, ExpressionErrorKind.ExpectingItemName));
            }

            if (offset <= endOffset && buffer [offset] == ')')
            {
                return(new ExpressionItem(baseOffset + start, offset - start + 1, name));
            }

            ConsumeWhitespace(ref offset);

            if (offset > endOffset || buffer [offset] != '-')
            {
                return(new IncompleteExpressionError(
                           baseOffset + offset, offset > endOffset, ExpressionErrorKind.ExpectingRightParenOrDash,
                           new ExpressionItem(baseOffset + start, offset - start + 1, name)
                           ));
            }

            offset++;
            if (offset > endOffset || buffer [offset] != '>')
            {
                return(new ExpressionError(baseOffset + offset, ExpressionErrorKind.ExpectingRightAngleBracket));
            }

            offset++;
            ConsumeWhitespace(ref offset);

            if (offset > endOffset || buffer [offset] != '\'')
            {
                return(new ExpressionError(baseOffset + offset, ExpressionErrorKind.ExpectingApos));
            }

            offset++;
            var endAposOffset = buffer.IndexOf('\'', offset, endOffset - offset + 1);

            if (endAposOffset < 0)
            {
                return(new ExpressionError(baseOffset + endOffset, ExpressionErrorKind.ExpectingApos));
            }

            ExpressionNode transform;

            if (endAposOffset == 0)
            {
                transform = new ExpressionText(offset, "", true);
            }
            else
            {
                //FIXME: disallow items in the transform
                transform = Parse(buffer, offset, endAposOffset - 1, ExpressionOptions.Metadata, baseOffset);
            }

            offset = endAposOffset + 1;
            ConsumeWhitespace(ref offset);

            if (offset > endOffset || buffer [offset] != ')')
            {
                return(new ExpressionError(baseOffset + offset, ExpressionErrorKind.ExpectingRightParen));
            }

            return(new ExpressionItem(baseOffset + start, offset - start + 1, name, transform));

            void ConsumeWhitespace(ref int o)
            {
                while (o <= endOffset && buffer [o] == ' ')
                {
                    o++;
                }
            }
        }
コード例 #2
0
        static TriggerState GetTriggerState(string expression, out int triggerLength, out ExpressionNode triggerExpression)
        {
            triggerLength = 0;

            if (expression.Length == 0)
            {
                triggerExpression = new ExpressionText(0, "", true);
                return(TriggerState.Value);
            }

            if (expression.Length == 1)
            {
                triggerExpression = new ExpressionText(0, expression, true);
                triggerLength     = 1;
                return(TriggerState.Value);
            }

            const ExpressionOptions options = ExpressionOptions.ItemsMetadataAndLists | ExpressionOptions.CommaLists;

            triggerExpression = ExpressionParser.Parse(expression, options);

            if (triggerExpression is ExpressionList el)
            {
                //the last list entry is the thing that triggered it
                triggerExpression = el.Nodes.Last();
                if (triggerExpression is ExpressionError e && e.Kind == ExpressionErrorKind.EmptyListEntry)
                {
                    return(LastChar() == ',' ? TriggerState.CommaValue : TriggerState.SemicolonValue);
                }
                if (triggerExpression is ExpressionText l)
                {
                    if (l.Length == 1)
                    {
                        triggerLength = 1;
                        return(PenultimateChar() == ',' ? TriggerState.CommaValue : TriggerState.SemicolonValue);
                    }
                }
            }

            var lastNode = triggerExpression;

            if (lastNode is Expression expr)
            {
                lastNode = expr.Nodes.Last();
            }

            if (lastNode is ExpressionText lit)
            {
                if (LastChar() == '\\')
                {
                    return(TriggerState.DirectorySeparator);
                }

                if (lit.Value.Length >= 2 && PenultimateChar() == '\\' && IsPossiblePathSegment(LastChar()))
                {
                    triggerLength = 1;
                    return(TriggerState.DirectorySeparator);
                }
            }

            if (lastNode is IncompleteExpressionError iee && iee.WasEOF)
            {
                switch (iee.IncompleteNode)
                {
                case ExpressionItem i:
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParenOrDash && i.Name.Length == 1)
                    {
                        triggerLength = 1;
                        return(TriggerState.Item);
                    }
                    break;

                case ExpressionProperty p:
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParenOrPeriod && p.Name.Length == 1)
                    {
                        triggerLength = 1;
                        return(TriggerState.Property);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingMethodName)
                    {
                        return(TriggerState.MethodName);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingLeftParen)
                    {
                        var inv = p.Find(iee.Offset - 1) as ExpressionPropertyFunctionInvocation;
                        if (inv != null && inv.MethodName != null && inv.MethodName.Length == 1)
                        {
                            triggerLength = 1;
                            return(TriggerState.MethodName);
                        }
                    }
                    break;

                case ExpressionMetadata m:
                    if (iee.Kind == ExpressionErrorKind.ExpectingMetadataName)
                    {
                        return(TriggerState.Metadata);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParenOrPeriod && m.ItemName.Length == 1)
                    {
                        triggerLength = 1;
                        return(TriggerState.MetadataOrItem);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParen && m.MetadataName.Length == 1)
                    {
                        triggerLength = 1;
                        return(TriggerState.Metadata);
                    }
                    break;
                }
                return(TriggerState.None);
            }

            if (lastNode is ExpressionError err)
            {
                switch (err.Kind)
                {
                case ExpressionErrorKind.ExpectingPropertyName:
                    return(TriggerState.Property);

                case ExpressionErrorKind.ExpectingItemName:
                    return(TriggerState.Item);

                case ExpressionErrorKind.ExpectingMetadataOrItemName:
                    return(TriggerState.MetadataOrItem);
                }
                return(TriggerState.None);
            }

            return(TriggerState.None);

            char LastChar() => expression[expression.Length - 1];
            char PenultimateChar() => expression[expression.Length - 2];
            bool IsPossiblePathSegment(char c) => c == '_' || char.IsLetterOrDigit(c) || c == '.';
        }
コード例 #3
0
        public static TriggerState GetConditionTriggerState(
            string expression,
            out int triggerLength, out ExpressionNode triggerExpression,
            out IReadOnlyList <ExpressionNode> comparandValues
            )
        {
            triggerLength     = 0;
            triggerExpression = null;
            comparandValues   = null;

            if (expression.Length == 0 || (expression.Length == 0 && expression[0] == '\''))
            {
                triggerExpression = new ExpressionText(0, "", true);
                return(TriggerState.Value);
            }

            if (expression.Length == 1)
            {
                triggerExpression = new ExpressionText(0, expression, true);
                triggerLength     = 1;
                return(TriggerState.Value);
            }

            var tokens    = new List <Token> ();
            var tokenizer = new ConditionTokenizer();

            tokenizer.Tokenize(expression);

            int lastExpressionStart = 0;

            while (tokenizer.Token.Type != TokenType.EOF)
            {
                switch (tokenizer.Token.Type)
                {
                case TokenType.And:
                case TokenType.Or:
                    lastExpressionStart = tokenizer.Token.Position + tokenizer.Token.Value.Length;
                    break;
                }
                tokens.Add(tokenizer.Token);
                tokenizer.GetNextToken();
            }

            int last = tokens.Count - 1;

            if (last >= 2 && TokenIsCondition(tokens[last - 1].Type))
            {
                var lt = tokens[last];
                if (lt.Type == TokenType.Apostrophe || (lt.Type == TokenType.String && (expression[lt.Position + lt.Value.Length] != '\'')))
                {
                    lastExpressionStart = lt.Position;
                    comparandValues     = ReadPrecedingComparandVariables(tokens, last - 2);
                }
                else
                {
                    triggerLength     = 0;
                    triggerExpression = null;
                    return(TriggerState.None);
                }
            }

            var subexpr = expression.Substring(lastExpressionStart);

            return(GetTriggerState(subexpr, out triggerLength, out triggerExpression));
        }
コード例 #4
0
        static TriggerState GetTriggerState(string expression, out int triggerLength, out ExpressionNode triggerExpression)
        {
            triggerLength = 0;

            if (expression.Length == 0)
            {
                triggerExpression = new ExpressionText(0, "", true);
                return(TriggerState.Value);
            }

            if (expression.Length == 1)
            {
                triggerExpression = new ExpressionText(0, expression, true);
                triggerLength     = 1;
                return(TriggerState.Value);
            }

            const ExpressionOptions options = ExpressionOptions.ItemsMetadataAndLists | ExpressionOptions.CommaLists;

            triggerExpression = ExpressionParser.Parse(expression, options);

            if (triggerExpression is ExpressionList el)
            {
                //the last list entry is the thing that triggered it
                triggerExpression = el.Nodes.Last();
                if (triggerExpression is ExpressionError e && e.Kind == ExpressionErrorKind.EmptyListEntry)
                {
                    return(LastChar() == ',' ? TriggerState.CommaValue : TriggerState.SemicolonValue);
                }
                if (triggerExpression is ExpressionText l)
                {
                    if (l.Length == 1)
                    {
                        triggerLength = 1;
                        return(PenultimateChar() == ',' ? TriggerState.CommaValue : TriggerState.SemicolonValue);
                    }
                }
            }

            //find the deepest node that touches the end
            var lastNode = triggerExpression.Find(expression.Length);

            if (lastNode == null)
            {
                return(TriggerState.None);
            }

            if (lastNode is ExpressionText lit)
            {
                if (LastChar() == '\\')
                {
                    return(TriggerState.DirectorySeparator);
                }

                if (lit.Value.Length >= 2 && PenultimateChar() == '\\' && IsPossiblePathSegment(LastChar()))
                {
                    triggerLength = 1;
                    return(TriggerState.DirectorySeparator);
                }
            }

            //find the deepest error
            var            error  = lastNode as ExpressionError;
            ExpressionNode parent = lastNode.Parent;

            while (parent != null && error == null)
            {
                error  = parent as ExpressionError;
                parent = parent.Parent;
            }

            if (error is IncompleteExpressionError iee && iee.WasEOF)
            {
                switch (lastNode)
                {
                case ExpressionItem i:
                    if (iee.Kind == ExpressionErrorKind.ExpectingMethodOrTransform)
                    {
                        return(TriggerState.ItemFunctionName);
                    }
                    break;

                case ExpressionItemName ein:
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParenOrDash)
                    {
                        triggerLength = ein.Name.Length;
                        return(TriggerState.Item);
                    }
                    break;

                case ExpressionPropertyName pn:
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParenOrPeriod)
                    {
                        triggerLength = pn.Name.Length;
                        return(TriggerState.Property);
                    }
                    break;

                case ExpressionFunctionName fn:
                    if (iee.Kind == ExpressionErrorKind.IncompleteProperty)
                    {
                        triggerLength = fn.Name.Length;
                        return(TriggerState.PropertyFunctionName);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingLeftParen)
                    {
                        triggerLength = fn.Name.Length;
                        return(TriggerState.ItemFunctionName);
                    }
                    break;

                case ExpressionPropertyFunctionInvocation pfi:
                    if (iee.Kind == ExpressionErrorKind.ExpectingMethodName)
                    {
                        return(TriggerState.PropertyFunctionName);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingClassName)
                    {
                        return(TriggerState.PropertyFunctionClassName);
                    }
                    break;

                case ExpressionClassReference cr:
                    if (iee.Kind == ExpressionErrorKind.ExpectingBracketColonColon)
                    {
                        triggerLength = cr.Name.Length;
                        return(TriggerState.PropertyFunctionClassName);
                    }
                    break;

                case ExpressionMetadata m:
                    if (iee.Kind == ExpressionErrorKind.ExpectingMetadataName)
                    {
                        return(TriggerState.Metadata);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParenOrPeriod)
                    {
                        triggerLength = m.ItemName.Length;
                        return(TriggerState.MetadataOrItem);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParen)
                    {
                        triggerLength = m.MetadataName.Length;
                        return(TriggerState.Metadata);
                    }
                    break;
                }
                return(TriggerState.None);
            }

            if (error != null)
            {
                switch (error.Kind)
                {
                case ExpressionErrorKind.ExpectingPropertyName:
                    return(TriggerState.Property);

                case ExpressionErrorKind.ExpectingItemName:
                    return(TriggerState.Item);

                case ExpressionErrorKind.ExpectingMetadataOrItemName:
                    return(TriggerState.MetadataOrItem);
                }
                return(TriggerState.None);
            }

            return(TriggerState.None);

            char LastChar() => expression[expression.Length - 1];
            char PenultimateChar() => expression[expression.Length - 2];
            bool IsPossiblePathSegment(char c) => c == '_' || char.IsLetterOrDigit(c) || c == '.';
        }
コード例 #5
0
            void VisitPureLiteral(ValueInfo info, MSBuildValueKind kind, ExpressionText node)
            {
                string value = node.GetUnescapedValue();

                rr.ReferenceOffset = node.Offset;
                rr.ReferenceLength = node.Value.Length;
                rr.Reference       = value;

                switch (kind)
                {
                case MSBuildValueKind.TaskOutputParameterName:
                    rr.ReferenceKind = MSBuildReferenceKind.TaskParameter;
                    return;

                case MSBuildValueKind.TargetName:
                    rr.ReferenceKind = MSBuildReferenceKind.Target;
                    return;

                case MSBuildValueKind.NuGetID:
                    rr.ReferenceKind = MSBuildReferenceKind.NuGetID;
                    return;

                case MSBuildValueKind.PropertyName:
                    rr.ReferenceKind = MSBuildReferenceKind.Property;
                    return;

                case MSBuildValueKind.ItemName:
                    rr.ReferenceKind = MSBuildReferenceKind.Item;
                    return;

                case MSBuildValueKind.TargetFramework:
                    rr.ReferenceKind = MSBuildReferenceKind.TargetFramework;
                    return;

                case MSBuildValueKind.TargetFrameworkIdentifier:
                    rr.ReferenceKind = MSBuildReferenceKind.TargetFrameworkIdentifier;
                    return;

                case MSBuildValueKind.TargetFrameworkVersion:
                    rr.ReferenceKind = MSBuildReferenceKind.TargetFrameworkVersion;
                    return;

                case MSBuildValueKind.TargetFrameworkProfile:
                    rr.ReferenceKind = MSBuildReferenceKind.TargetFrameworkProfile;
                    return;
                }

                IReadOnlyList <ConstantInfo> knownVals = info.Values ?? kind.GetSimpleValues(false);

                if (knownVals != null && knownVals.Count != 0)
                {
                    foreach (var kv in knownVals)
                    {
                        if (string.Equals(kv.Name, value, StringComparison.OrdinalIgnoreCase))
                        {
                            rr.ReferenceKind = MSBuildReferenceKind.KnownValue;
                            rr.Reference     = kv;
                            return;
                        }
                    }
                }
            }
コード例 #6
0
            void VisitPureLiteral(XElement element, ValueInfo info, MSBuildValueKind kind, ExpressionText node)
            {
                string value = node.GetUnescapedValue();

                rr.ReferenceOffset = node.Offset;
                rr.ReferenceLength = node.Value.Length;
                rr.Reference       = value;

                switch (kind)
                {
                case MSBuildValueKind.TaskOutputParameterName:
                    rr.ReferenceKind = MSBuildReferenceKind.TaskParameter;
                    return;

                case MSBuildValueKind.TargetName:
                    rr.ReferenceKind = MSBuildReferenceKind.Target;
                    return;

                case MSBuildValueKind.NuGetID:
                    rr.ReferenceKind = MSBuildReferenceKind.NuGetID;
                    return;

                case MSBuildValueKind.PropertyName:
                    rr.ReferenceKind = MSBuildReferenceKind.Property;
                    return;

                case MSBuildValueKind.ItemName:
                    rr.ReferenceKind = MSBuildReferenceKind.Item;
                    return;

                case MSBuildValueKind.TaskName:
                    rr.ReferenceKind = MSBuildReferenceKind.Task;
                    return;

                case MSBuildValueKind.TargetFramework:
                    rr.ReferenceKind = MSBuildReferenceKind.TargetFramework;
                    return;

                case MSBuildValueKind.TargetFrameworkIdentifier:
                    rr.ReferenceKind = MSBuildReferenceKind.TargetFrameworkIdentifier;
                    return;

                case MSBuildValueKind.TargetFrameworkVersion:
                    rr.ReferenceKind = MSBuildReferenceKind.TargetFrameworkVersion;
                    return;

                case MSBuildValueKind.TargetFrameworkProfile:
                    rr.ReferenceKind = MSBuildReferenceKind.TargetFrameworkProfile;
                    return;

                case MSBuildValueKind.MetadataName:
                    //this is used for KeepMetadata/RemoveMetadata.
                    //reasonable to resolve from first item in include.
                    var itemName = MSBuildMetadataReferenceCollector.GetIncludeExpression(element, TextDocument)
                                   .WithAllDescendants()
                                   .OfType <ExpressionItemName> ()
                                   .FirstOrDefault();
                    if (itemName != null)
                    {
                        rr.Reference     = (itemName.Name, value);
                        rr.ReferenceKind = MSBuildReferenceKind.Metadata;
                    }
                    return;
                }

                IReadOnlyList <ConstantInfo> knownVals = info.Values ?? kind.GetSimpleValues(false);

                if (knownVals != null && knownVals.Count != 0)
                {
                    foreach (var kv in knownVals)
                    {
                        if (string.Equals(kv.Name, value, StringComparison.OrdinalIgnoreCase))
                        {
                            rr.ReferenceKind = MSBuildReferenceKind.KnownValue;
                            rr.Reference     = kv;
                            return;
                        }
                    }
                }
            }