public void TestObjectCreate()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     new
            {
                i.CORE_USER.mail
            }));

            expText.AssertExpTextCanBeConvertedToLambda <object>();

            Assert.Equal("new(i.CORE_USER.mail as mail)", expText.Expression);

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     new
            {
                mail2 = i.CORE_USER.mail
            }));

            expText.AssertExpTextCanBeConvertedToLambda <object>();

            Assert.Equal("new(i.CORE_USER.mail as mail2)", expText.Expression);
        }
Beispiel #2
0
 void CheckMatch(ExpressionText node, bool isDeclaration)
 {
     //FIXME: get rid of this trim
     if (IsMatch(node.Value.Trim()))
     {
         Results.Add((node.Offset, node.Length, isDeclaration ? ReferenceUsage.Declaration : ReferenceUsage.Read));
     }
 }
Beispiel #3
0
 void CheckMatch(ExpressionText node)
 {
     //FIXME: get rid of this trim
     if (IsMatch(node.Value.Trim()))
     {
         Results.Add((node.Offset, node.Length, ReferenceUsage.Read));
     }
 }
        private Point GetCaretPoint()
        {
            Point pt = ExpressionText.GetPositionFromCharIndex(ExpressionText.SelectionStart);

            pt.Y += (int)Math.Ceiling(ExpressionText.Font.GetHeight()) + 2;
            pt.X += 2; // for Courier, may need a better method
            return(pt);
        }
        public void AlterationTest()
        {
            // Create inital combination
            ExpressionText expression = _expression1.Combine(_expression2, ExpressionOperator.Plus) as ExpressionText;

            Assert.AreEqual(expression.Result, "12");

            // Alter combined object
            _expression2 = _expression2.Combine(_expression3, ExpressionOperator.Plus) as ExpressionText;
            Assert.AreEqual(expression.Result, "12");
        }
Beispiel #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ExpressionEditor"/> class.
 /// </summary>
 internal ExpressionEditor()
 {
     InitializeComponent();
     ExpressionText.SetHighlighting("FDO");
     _editor                 = TextEditorFactory.CreateEditor(ExpressionText);
     _editor.KeyPress       += OnEditorKeyPress;
     _editor.DialogKeyPress += OnEditorDialogKeyPress;
     _contextualBuffer       = new StringBuilder();
     _functions              = new SortedList <string, IFdoFunctionDefintion>();
     this.Disposed          += OnDisposed;
 }
        public void PlusTest()
        {
            ExpressionText expression = _expression1.Combine(_expression2, ExpressionOperator.Plus) as ExpressionText;

            // 1 + 2
            Assert.AreEqual(expression.Result, "12");

            expression = expression.Combine(_expression3, ExpressionOperator.Plus) as ExpressionText;

            // 1 + 2 + 3
            Assert.AreEqual(expression.Result, "123");
        }
        private void OnAutoCompleteSelectedIndexChanged(object sender, EventArgs e)
        {
            ExpressionText.Focus();
            if (_autoBox.Visible && _autoBox.SelectedIndex >= 0 && _autoBox.Items.Count > 0)
            {
                string tt = ((_autoBox.SelectedItem as ImageListBoxItem).Tag as AutoCompleteItem).ToolTipText;
                Point  pt = GetCaretPoint();
                pt.X += _autoBox.Width + 10;
                pt.Y += 65;

                _autoCompleteTooltip.Show(tt, this, pt.X, pt.Y);
            }
        }
        public void TestPropertySelector()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) => i.CORE_USER.mail));

            expText.AssertExpTextCanBeConvertedToLambda <string>();

            Assert.Equal("i.CORE_USER.mail", expText.Expression);
        }
        public void TestNullCompare()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     i.deletedAt != null));

            expText.AssertExpTextCanBeConvertedToLambda <bool>();

            Assert.Equal("i.deletedAt != @p0", expText.Expression);
            this.AssertHasArgument("@p0", null, expText);
        }
        public void TestModulus()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     i.deletedAt % 5));

            expText.AssertExpTextCanBeConvertedToLambda <long?>();

            Assert.Equal("i.deletedAt % @p0", expText.Expression);
            this.AssertHasArgument("@p0", 5, expText);
        }
        public void TestNegate()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     !(i.deletedAt == 25)));

            expText.AssertExpTextCanBeConvertedToLambda <bool>();

            Assert.Equal("!(i.deletedAt == @p0)", expText.Expression);
            this.AssertHasArgument("@p0", 25, expText);
        }
        public void TestStaticFunctionCall()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     DbFunctions.Like(i.firstname, "thename")));

            expText.AssertExpTextCanBeConvertedToLambda <bool>();

            Assert.Equal("DbFunctions.Like(i.firstname, @p0)", expText.Expression);
            this.AssertHasArgument("@p0", "thename", expText);
        }
        public void TestNullCoalesce()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            // By default .Net wraps literal local values in objects in lambda expressions
            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     i.CORE_USER.mail ?? "myliteralroadname"));

            expText.AssertExpTextCanBeConvertedToLambda <string>();

            Assert.Equal("i.CORE_USER.mail ?? @p0", expText.Expression);
            this.AssertHasArgument("@p0", "myliteralroadname", expText);
        }
        public void TestBitwise()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     i.deletedAt ^ 3));

            // TODO: Seems not supported by Dynamic.Linq.Core
            // expText.AssertExpTextCanBeConvertedToLambda<long?>();

            Assert.Equal("i.deletedAt ^ @p0", expText.Expression);
            this.AssertHasArgument("@p0", 3, expText);
        }
        public void TestMaterializationAndMethodCall()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            string[] testList = new string[] { "op1", "op2" };

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     testList.ToList().Contains("op1")));

            expText.AssertExpTextCanBeConvertedToLambda <bool>();

            Assert.Equal("@p0", expText.Expression);
            this.AssertHasArgument("@p0", true, expText);
        }
        public void TestAddSubstractMultiply()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     (i.deletedAt * 5) - 5 + 6));

            expText.AssertExpTextCanBeConvertedToLambda <long?>();

            Assert.Equal("(i.deletedAt * @p0 - @p1) + @p2", expText.Expression);
            this.AssertHasArgument("@p0", 5, expText);
            this.AssertHasArgument("@p1", 5, expText);
            this.AssertHasArgument("@p2", 6, expText);
        }
        private void PutAutoCompleteSuggestion()
        {
            if (_autoBox.SelectedItems.Count == 1)
            {
                int    pos = ExpressionText.SelectionStart;
                string context;
                char?  c = GetContextBuffer(out context);

                AutoCompleteItem aci = (_autoBox.SelectedItem as ImageListBoxItem).Tag as AutoCompleteItem;

                string fullText = aci.AutoCompleteText;

                int start     = pos - context.Length;
                int newPos    = start + fullText.Length;
                int selLength = -1;

                //if it's a function, highlight the parameter (or the first parameter if there is multiple arguments
                if (aci.Type == AutoCompleteItemType.Function)
                {
                    newPos = start + aci.Name.Length + 1; //Position the caret just after the opening bracket

                    //Has at least two arguments
                    int idx = fullText.IndexOf(",");
                    if (idx > 0)
                    {
                        selLength = idx - aci.Name.Length - 1;
                    }
                    else
                    {
                        selLength = fullText.IndexOf(")") - fullText.IndexOf("(") - 1;
                    }
                }

                string prefix = ExpressionText.Text.Substring(0, start);
                string suffix = ExpressionText.Text.Substring(pos, ExpressionText.Text.Length - pos);

                ExpressionText.Text           = prefix + fullText + suffix;
                ExpressionText.SelectionStart = newPos;
                if (selLength > 0)
                {
                    ExpressionText.SelectionLength = selLength;
                }
                ExpressionText.ScrollToCaret();
            }
        }
        public void TestStringLiteralInExpression()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            var localExpressionValue = "literal";

            // By default .Net wraps literal local values in objects in lambda expressions
            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     i.CORE_USER.mail.Contains(localExpressionValue)));

            expText.AssertExpTextCanBeConvertedToLambda <bool>();

            Assert.Equal("i.CORE_USER.mail.Contains(@p0)", expText.Expression);
            this.AssertHasArgument("@p0", localExpressionValue, expText);
        }
Beispiel #20
0
 internal MSBuildPropertyValue Collapse(IMSBuildEvaluationContext context)
 {
     if (multiple != null)
     {
         var oldMultiple = multiple;
         multiple = new ExpressionNode[oldMultiple.Count];
         for (int i = 0; i < multiple.Count; i++)
         {
             multiple[i] = new ExpressionText(0, context.Evaluate(oldMultiple[i]), true);
         }
         Value = multiple[0];
     }
     else
     {
         Value = new ExpressionText(0, context.Evaluate(Value), true);
     }
     isCollapsed = true;
     return(this);
 }
        public void TestParameterRenaming()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i, CORE_PERSON i2) => i.firstname == i2.firstname));

            expText.AssertExpTextCanBeConvertedToLambda <bool>();

            Assert.Equal("i.firstname == i2.firstname", expText.Expression);
            Assert.Empty(expText.Arguments);

            // Rename arguments
            expText.SetParameterMapping("i", "rootprojection.DBFIELD.field");
            expText.SetParameterMapping("i2", "rootprojection2.DBFIELD");

            Assert.Equal("rootprojection.DBFIELD.field.firstname == rootprojection2.DBFIELD.firstname", expText.Expression);
            Assert.Empty(expText.Arguments);
        }
        public void TestArrayAccessor()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            string[] strings = { "a", "b" };

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(LambdaBuilder.Lambda((CORE_PERSON i) => strings[0]));
            expText.AssertExpTextCanBeConvertedToLambda <string>();

            Assert.Equal("@p0", expText.Expression);

            this.AssertHasArgument("@p0", "a", expText);

            expText = expVisitor.GetExpressionText(LambdaBuilder.Lambda((CORE_PERSON i) => strings[(int)i.changedAt]));
            expText.AssertExpTextCanBeConvertedToLambda <string>();

            Assert.Equal("@p0[Int32(i.changedAt)]", expText.Expression);

            this.AssertHasArgument("@p0", strings, expText);
        }
Beispiel #23
0
        static TriggerState GetTriggerState(
            string expression, TriggerReason reason, char typedChar, bool isCondition,
            out int triggerLength, out ExpressionNode triggerExpression, out ExpressionNode triggerNode, out ListKind listKind)
        {
            triggerLength = 0;
            listKind      = ListKind.None;

            var isNewline   = typedChar == '\n';
            var isTypedChar = reason == TriggerReason.TypedChar;

            if (isTypedChar && !isNewline && expression.Length > 0 && expression[expression.Length - 1] != typedChar)
            {
                triggerExpression = null;
                triggerNode       = null;
                LoggingService.LogWarning($"Expression text '{expression}' is not consistent with typed character '{typedChar}'");
                return(TriggerState.None);
            }

            if (expression.Length == 0)
            {
                //automatically trigger at the start of an expression regardless
                triggerExpression = new ExpressionText(0, expression, true);
                triggerNode       = triggerExpression;
                return(TriggerState.Value);
            }

            if (isCondition)
            {
                triggerExpression = ExpressionParser.ParseCondition(expression);
            }
            else
            {
                const ExpressionOptions options = ExpressionOptions.ItemsMetadataAndLists | ExpressionOptions.CommaLists;
                triggerExpression = ExpressionParser.Parse(expression, options);
            }

            return(GetTriggerState(triggerExpression, reason, typedChar, out triggerLength, out triggerNode, out listKind));
        }
Beispiel #24
0
        /// <summary>
        ///
        /// </summary>
        public static void AssertExpTextCanBeConvertedToLambda <TResult>(
            this ExpressionText expText)
        {
            ParsingConfig pc = ParsingConfig.Default;

            pc.AllowNewToEvaluateAnyType = true;
            pc.CustomTypeProvider        = new CustomTypeProvider();

            // Build the parameters...
            List <ParameterExpression> parameters = new List <ParameterExpression>();

            foreach (var p in expText.Parameters2.Values)
            {
                parameters.Add(p);
            }

            DynamicExpressionParser.ParseLambda(
                pc,
                true,
                parameters.ToArray(),
                typeof(TResult),
                expText.Expression,
                new object[] { expText.Arguments });
        }
        public void TestObjectAccessor()
        {
            GetExpressionTextVisitor expVisitor = new GetExpressionTextVisitor();

            var sampleObject = new
            {
                prop1 = new
                {
                    prop2  = "My string",
                    number = 58
                }
            };

            ExpressionText expText = null;

            expText = expVisitor.GetExpressionText(
                LambdaBuilder.Lambda((CORE_PERSON i) =>
                                     i.CORE_USER.mail.Contains(sampleObject.prop1.prop2)));

            expText.AssertExpTextCanBeConvertedToLambda <bool>();

            Assert.Equal("@p0", expText.Expression);
            this.AssertHasArgument("@p0", true, expText);
        }
Beispiel #26
0
            void VisitPureLiteral(XElement element, ITypedSymbol valueDescriptor, MSBuildValueKind inferredKind, ExpressionText node)
            {
                string value = node.GetUnescapedValue();

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

                switch (inferredKind)
                {
                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)
                                   .WithAllDescendants()
                                   .OfType <ExpressionItemName> ()
                                   .FirstOrDefault();
                    if (itemName != null)
                    {
                        rr.Reference     = (itemName.Name, value);
                        rr.ReferenceKind = MSBuildReferenceKind.Metadata;
                    }
                    return;
                }

                var knownVals = (IReadOnlyList <ISymbol>)valueDescriptor.CustomType?.Values ?? inferredKind.GetSimpleValues(true);

                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;
                        }
                    }
                }
            }
        static TriggerState GetTriggerState(string expression, char typedChar, out int triggerLength, out ExpressionNode triggerExpression, out ListKind listKind)
        {
            var isExplicit = typedChar == '\0';
            var isNewline  = typedChar == '\n';

            triggerLength = 0;
            listKind      = ListKind.None;

            if (!isExplicit && !isNewline && expression.Length > 0 && expression[expression.Length - 1] != typedChar)
            {
                triggerExpression = null;
                LoggingService.LogWarning($"Expression text '{expression}' is not consistent with typed character '{typedChar}'");
                return(TriggerState.None);
            }

            if (expression.Length == 0)
            {
                triggerExpression = new ExpressionText(0, expression, true);
            }
            else
            {
                const ExpressionOptions options = ExpressionOptions.ItemsMetadataAndLists | ExpressionOptions.CommaLists;
                triggerExpression = ExpressionParser.Parse(expression, options);
            }

            if (triggerExpression is ListExpression el)
            {
                //the last list entry is the thing that triggered it
                triggerExpression = el.Nodes.Last();
                if (triggerExpression is ExpressionError e && e.Kind == ExpressionErrorKind.EmptyListEntry)
                {
                    triggerLength = 0;
                    listKind      = LastChar() == ',' ? ListKind.Comma : ListKind.Semicolon;
                    return(TriggerState.Value);
                }
                var separator = expression[triggerExpression.Offset - 1];
                listKind = separator == ',' ? ListKind.Comma : ListKind.Semicolon;
            }

            if (triggerExpression is ExpressionText text)
            {
                var val = text.Value;
                int leadingWhitespace = 0;
                for (int i = 0; i < val.Length; i++)
                {
                    if (char.IsWhiteSpace(val[i]))
                    {
                        leadingWhitespace++;
                    }
                    else
                    {
                        break;
                    }
                }

                var length = val.Length - leadingWhitespace;
                if (length == 0)
                {
                    triggerLength = 0;
                    return(isExplicit ? TriggerState.Value : TriggerState.None);
                }

                var firstChar = val[leadingWhitespace];

                if (length == 1)
                {
                    triggerLength = 1;
                    switch (firstChar)
                    {
                    case '$': return(TriggerState.PropertyOrValue);

                    case '@': return(TriggerState.ItemOrValue);

                    case '%': return(TriggerState.MetadataOrValue);

                    default:
                        if (char.IsLetterOrDigit(firstChar))
                        {
                            return(TriggerState.Value);
                        }
                        break;
                    }
                }
                else if (isExplicit && char.IsLetterOrDigit(firstChar))
                {
                    triggerLength = length;
                    return(TriggerState.Value);
                }

                triggerLength = 0;
                return(TriggerState.None);
            }

            //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)
                    {
                        if (isExplicit || ein.Name.Length == 1)
                        {
                            triggerLength = ein.Name.Length;
                            return(TriggerState.ItemName);
                        }
                        return(TriggerState.None);
                    }
                    break;

                case ExpressionPropertyName pn:
                    if (iee.Kind == ExpressionErrorKind.ExpectingRightParenOrPeriod)
                    {
                        if (isExplicit || pn.Name.Length == 1)
                        {
                            triggerLength = pn.Name.Length;
                            return(TriggerState.PropertyName);
                        }
                        return(TriggerState.None);
                    }
                    break;

                case ExpressionFunctionName fn:
                    if (iee.Kind == ExpressionErrorKind.IncompleteProperty)
                    {
                        if (isExplicit || fn.Name.Length == 1)
                        {
                            triggerLength = fn.Name.Length;
                            return(TriggerState.PropertyFunctionName);
                        }
                        return(TriggerState.None);
                    }
                    if (iee.Kind == ExpressionErrorKind.ExpectingLeftParen)
                    {
                        if (isExplicit || fn.Name.Length == 1)
                        {
                            triggerLength = fn.Name.Length;
                            return(TriggerState.ItemFunctionName);
                        }
                        return(TriggerState.None);
                    }
                    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 ||
                        ((iee.Kind == ExpressionErrorKind.ExpectingRightParenOrValue || iee.Kind == ExpressionErrorKind.ExpectingRightParenOrComma) && cr.Parent is ExpressionArgumentList)
                        )
                    {
                        if (isExplicit || cr.Name.Length == 1)
                        {
                            triggerLength = cr.Name.Length;
                            return(cr.Parent is ExpressionArgumentList? TriggerState.BareFunctionArgumentValue : TriggerState.PropertyFunctionClassName);
                        }
                        return(TriggerState.None);
                    }
                    break;

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

                case ExpressionText expressionText: {
                    if (
                        (error.Kind == ExpressionErrorKind.IncompleteString && (expressionText.Parent is ExpressionArgumentList || expressionText.Parent is ExpressionItemTransform)) ||
                        (error.Kind == ExpressionErrorKind.ExpectingRightParenOrValue && expressionText.Parent is ExpressionArgumentList)
                        )
                    {
                        return(GetTriggerState(expressionText.Value, typedChar, out triggerLength, out triggerExpression, out _));
                    }
                }
                break;

                case ExpressionArgumentList argList: {
                    if (error.Kind == ExpressionErrorKind.ExpectingRightParenOrValue)
                    {
                        return(TriggerState.BareFunctionArgumentValue);
                    }
                }
                break;
                }
            }

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

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

                case ExpressionErrorKind.ExpectingMetadataOrItemName:
                    return(TriggerState.MetadataOrItemName);
                }
                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 == '.';
        }
        public static TriggerState GetConditionTriggerState(
            string expression,
            char typedChar, 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, typedChar, out triggerLength, out triggerExpression, out _));
        }
 private void button1_Click(object sender, EventArgs e)
 {
     PrefixPostfix.Clear();
     ExpressionText.Clear();
     re = "";
 }
 protected override void Execute(NativeActivityContext context)
 {
     // this line, commented or not, is the same!
     Predicate.ExpressionText = ExpressionText.Get(context);
     context.ScheduleActivity(Assign, new CompletionCallback(AssignComplete));
 }