public BreakBlock(BreakType breakType, CustomListItemsContext ctx, NatvisExpressionEvaluator evaluator) { _breakType = breakType; _ctx = ctx; _evaluator = evaluator; }
public ExecBlock(ExecType execType, CustomListItemsContext ctx, NatvisExpressionEvaluator evaluator) { _exec = execType; _ctx = ctx; _evaluator = evaluator; }
public ItemBlock(CustomListItemType customListItem, CustomListItemsContext ctx, NatvisExpressionEvaluator evaluator) { _customListItem = customListItem; _ctx = ctx; _evaluator = evaluator; }
public IList <ICodeBlock> Parse(object[] codeBlocks, CustomListItemsContext ctx) { var blocks = new List <ICodeBlock>(); foreach (object codeBlock in CombineConditionalCodeBlocks(codeBlocks)) { if (codeBlock is CustomListItemType customListItemType) { blocks.Add(new ItemBlock(customListItemType, ctx, _evaluator)); } else if (codeBlock is ExecType execType) { blocks.Add(new ExecBlock(execType, ctx, _evaluator)); } else if (codeBlock is LoopType loopType) { blocks.Add(new LoopBlock(loopType, ctx, _evaluator, this)); } else if (codeBlock is BreakType breakType) { blocks.Add(new BreakBlock(breakType, ctx, _evaluator)); } else if (codeBlock is ConditionalCodeBlockGroup codeBlockGroup) { blocks.Add(new ConditionalBlock(codeBlockGroup, ctx, _evaluator, this)); } else { throw new NotSupportedException($"{codeBlock.GetType()} is unknown."); } } return(blocks); }
public LoopBlock(LoopType loopType, CustomListItemsContext ctx, NatvisExpressionEvaluator evaluator, CodeBlockParser parser) { _loop = loopType; _ctx = ctx; _evaluator = evaluator; IList <ICodeBlock> loopBlocks = parser.Parse(loopType.CodeBlock ?? new object[0], ctx); _loopInstructions = new MultipleInstructionsBlock(loopBlocks); }
/// <summary> /// Evaluates the name of an <Item> node. /// /// If no Name attribute is present, the resulting name is "[<index>]", where <index> /// counts all custom list items, starting at 0. It is increased in all cases, even if a /// Name attribute is present or the evaluation fails. /// /// If a Name attribute is present, the name is evaluated as mixed expression, i.e. a /// string that contains text that is intended to be interpreted verbatim and zero or more /// expressions to be evaluated. Expressions are contained within a set of curly braces. /// /// Eg. "Test: {5 + 8}, {17 + 2}" -> "Test: 13, 19" /// /// Name can include curly braces, to escape them use '{{' and '}}'. /// /// Eg. "Test: {{{5 + 8}, {17 + 2}}}" -> "Test: {13, 19}" /// /// Only the first error is captured in the expression result. /// </summary> async Task <string> EvaluateItemNameAsync(string mixedExpression, CustomListItemsContext ctx) { int currIndex = ctx.ItemAutoIndex++; if (string.IsNullOrEmpty(mixedExpression)) { return($"[{currIndex}]"); } var stringBuilder = new StringBuilder(); for (int i = 0; i < mixedExpression.Length; i++) { char c = mixedExpression[i]; if (c == '{') { if (i + 1 < mixedExpression.Length && mixedExpression[i + 1] == '{') { stringBuilder.Append('{'); i++; continue; } int j = i + 1; var expressionBuilder = new StringBuilder(); while (mixedExpression[j] != '}' && j < mixedExpression.Length) { expressionBuilder.Append(mixedExpression[j]); j++; } IVariableInformation result = await _evaluator.EvaluateExpressionAsync( expressionBuilder.ToString(), _ctx.Variable, _ctx.NatvisScope, null); stringBuilder.Append(await result.ValueAsync()); i = j; } else if (c == '}') { // Accept both } and }} as closing braces to match native behavior. stringBuilder.Append('}'); if (i + 1 < mixedExpression.Length && mixedExpression[i + 1] == '}') { i++; } } else { stringBuilder.Append(c); } } return(stringBuilder.ToString()); }
public ConditionalBlock(ConditionalCodeBlockGroup conditionGroup, CustomListItemsContext ctx, NatvisExpressionEvaluator evaluator, CodeBlockParser parser) { _conditionGroup = conditionGroup; _ctx = ctx; _evaluator = evaluator; _innerBlocks = conditionGroup.ConditionalCode .Select(branch => new MultipleInstructionsBlock( parser.Parse(branch.CodeBlock ?? new object[0], ctx))) .ToList(); }
async Task InitContextAsync() { if (_ctx != null && _blocks != null) { return; } _ctx = new CustomListItemsContext(new NatvisScope(_natvisScope), _variable); foreach (var varType in _customList.Variable ?? Enumerable.Empty <VariableType>()) { _ctx.NatvisScope.AddScopedName(varType.Name, _nameTransformer.TransformName(varType.Name)); await _evaluator.DeclareVariableAsync(_variable, varType.Name, varType.InitialValue, _ctx.NatvisScope); } _blocks = new MultipleInstructionsBlock( _parser.Parse(_customList.CodeBlock ?? new object[0], _ctx)); }