public void EmptySelectTermShouldThrow() { SelectExpandParser parser = new SelectExpandParser("one,,two", ODataUriParserSettings.DefaultSelectExpandLimit); Action parse = () => parser.ParseSelect(); parse.ShouldThrow <ODataException>().WithMessage(ODataErrorStrings.ExpressionToken_IdentifierExpected("4")); }
/// <summary> /// Uses the ExpressionLexer to visit the next ExpressionToken, and delegates parsing of segments, type segments, identifiers, /// and the star token to other methods. /// </summary> /// <param name="previousSegment">Previously parsed PathSegmentToken, or null if this is the first token.</param> /// <returns>A parsed PathSegmentToken representing the next segment in this path.</returns> private PathSegmentToken ParseSegment(PathSegmentToken previousSegment) { if (this.lexer.CurrentToken.Text.StartsWith("$", StringComparison.CurrentCulture)) { throw new ODataException(ODataErrorStrings.UriSelectParser_SystemTokenInSelectExpand(this.lexer.CurrentToken.Text, this.lexer.ExpressionText)); } string propertyName; if (this.lexer.PeekNextToken().Kind == ExpressionTokenKind.Dot) { propertyName = this.lexer.ReadDottedIdentifier(this.isSelect); } else if (this.lexer.CurrentToken.Kind == ExpressionTokenKind.Star) { if (this.lexer.PeekNextToken().Kind == ExpressionTokenKind.Slash) { throw new ODataException(ODataErrorStrings.ExpressionToken_IdentifierExpected(this.lexer.Position)); } propertyName = this.lexer.CurrentToken.Text; this.lexer.NextToken(); } else { propertyName = this.lexer.CurrentToken.GetIdentifier(); this.lexer.NextToken(); } return(new NonSystemToken(propertyName, null, previousSegment)); }
/// <summary> /// Uses the ExpressionLexer to visit the next ExpressionToken, and delegates parsing of segments, type segments, identifiers, /// and the star token to other methods. /// </summary> /// <param name="previousSegment">Previously parsed PathSegmentToken, or null if this is the first token.</param> /// <param name="allowRef">Whether the $ref operation is valid in this token.</param> /// <returns>A parsed PathSegmentToken representing the next segment in this path.</returns> private PathSegmentToken ParseSegment(PathSegmentToken previousSegment, bool allowRef) { // TODO $count is defined in specification for expand, it is not supported now. Also note $count is not supported with star as expand option. if (this.lexer.CurrentToken.Text.StartsWith("$", StringComparison.Ordinal) && (!allowRef || this.lexer.CurrentToken.Text != UriQueryConstants.RefSegment)) { throw new ODataException(ODataErrorStrings.UriSelectParser_SystemTokenInSelectExpand(this.lexer.CurrentToken.Text, this.lexer.ExpressionText)); } // Some check here to throw exception, both prop1/*/prop2 and */$ref/prop will throw exception, both are for $expand cases if (!isSelect) { if (previousSegment != null && previousSegment.Identifier == UriQueryConstants.Star && this.lexer.CurrentToken.GetIdentifier() != UriQueryConstants.RefSegment) { // Star can only be followed with $ref throw new ODataException(ODataErrorStrings.ExpressionToken_OnlyRefAllowWithStarInExpand); } else if (previousSegment != null && previousSegment.Identifier == UriQueryConstants.RefSegment) { // $ref should not have more property followed. throw new ODataException(ODataErrorStrings.ExpressionToken_NoPropAllowedAfterRef); } } string propertyName; if (this.lexer.PeekNextToken().Kind == ExpressionTokenKind.Dot) { propertyName = this.lexer.ReadDottedIdentifier(this.isSelect); } else if (this.lexer.CurrentToken.Kind == ExpressionTokenKind.Star) { // "*/$ref" is supported in expand if (this.lexer.PeekNextToken().Kind == ExpressionTokenKind.Slash && isSelect) { throw new ODataException(ODataErrorStrings.ExpressionToken_IdentifierExpected(this.lexer.Position)); } else if (previousSegment != null && !isSelect) { // expand option like "customer?$expand=VIPCUstomer/*" is not allowed as specification does not allowed any property before *. throw new ODataException(ODataErrorStrings.ExpressionToken_NoSegmentAllowedBeforeStarInExpand); } propertyName = this.lexer.CurrentToken.Text; this.lexer.NextToken(); } else { propertyName = this.lexer.CurrentToken.GetIdentifier(); this.lexer.NextToken(); } return(new NonSystemToken(propertyName, null, previousSegment)); }