static TriggerState GetTriggerState(string expression, out int triggerLength, out ExpressionNode triggerExpression) { triggerLength = 0; if (expression.Length == 0) { triggerExpression = new ExpressionLiteral(0, "", true); return(TriggerState.Value); } if (expression.Length == 1) { triggerExpression = new ExpressionLiteral(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 ExpressionLiteral 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 ExpressionLiteral 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.ExpectingRightParen && p.Name.Length == 1) { triggerLength = 1; return(TriggerState.Property); } 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 == '.'; }
void VisitPureLiteral(ValueInfo info, MSBuildValueKind kind, ExpressionLiteral 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; return; } } } }
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 ExpressionLiteral(0, "", true); return(TriggerState.Value); } if (expression.Length == 1) { triggerExpression = new ExpressionLiteral(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)); }
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 ExpressionLiteral(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++; } } }