diff --git a/.appveyor.yml b/.appveyor.yml
index c75361a..1704e61 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -57,7 +57,8 @@ init:
install:
- ps: |
Execute-Action "installing tools" {
- choco install codecov msbuild-sonarqube-runner opencover.portable
+ choco install codecov opencover.portable -y
+ dotnet tool install --global dotnet-sonarscanner
}
dotnet_csproj:
@@ -74,19 +75,10 @@ before_build:
- ps: |
Execute-Action "beginning code analysis" {
if ($env:APPVEYOR_PULL_REQUEST_NUMBER) {
- # For security reasons, AppVeyor only exposes secure variables for pull requests from the same repositoy.
- # If $env:SONARQUBE_GITHUB_TOKEN is not set, then it is a pull request from another repository and we'll
- # skip SonarQube analysis.
- if ($env:SONARQUBE_GITHUB_TOKEN) {
- MSBuild.SonarQube.Runner.exe begin /o:$env:SONARQUBE_ORGANIZATION /k:$env:APPVEYOR_PROJECT_NAME /v:$env:APPVEYOR_BUILD_VERSION /d:sonar.host.url=https://sonarcloud.io /d:sonar.login=$env:SONARQUBE_TOKEN /d:sonar.cs.opencover.reportsPaths=coverage.xml /d:sonar.coverage.exclusions=**/*Tests.cs,**/*Tests.*.cs,**/*Mock.cs /d:sonar.github.pullRequest=$env:APPVEYOR_PULL_REQUEST_NUMBER /d:sonar.github.repository=$env:APPVEYOR_REPO_NAME /d:sonar.github.oauth=$env:SONARQUBE_GITHUB_TOKEN
-
- $env:SONARQUBE_RUNNING = $true
- }
+ dotnet sonarscanner begin /o:$env:SONARQUBE_ORGANIZATION /k:$env:APPVEYOR_PROJECT_NAME /v:$env:APPVEYOR_BUILD_VERSION /d:sonar.host.url=https://sonarcloud.io /d:sonar.login=$env:SONARQUBE_TOKEN /d:sonar.cs.opencover.reportsPaths=coverage.xml /d:sonar.coverage.exclusions=**/*Tests.cs /d:sonar.github.pullRequest=$env:APPVEYOR_PULL_REQUEST_NUMBER /d:sonar.github.repository=$env:APPVEYOR_REPO_NAME /d:sonar.github.oauth=$env:SONARQUBE_GITHUB_TOKEN
}
else {
- MSBuild.SonarQube.Runner.exe begin /o:$env:SONARQUBE_ORGANIZATION /k:$env:APPVEYOR_PROJECT_NAME /v:$env:APPVEYOR_BUILD_VERSION /d:sonar.host.url=https://sonarcloud.io /d:sonar.login=$env:SONARQUBE_TOKEN /d:sonar.cs.opencover.reportsPaths=coverage.xml /d:sonar.coverage.exclusions=**/*Tests.cs,**/*Tests.*.cs,**/*Mock.cs
-
- $env:SONARQUBE_RUNNING = $true
+ dotnet sonarscanner begin /o:$env:SONARQUBE_ORGANIZATION /k:$env:APPVEYOR_PROJECT_NAME /v:$env:APPVEYOR_BUILD_VERSION /d:sonar.host.url=https://sonarcloud.io /d:sonar.login=$env:SONARQUBE_TOKEN /d:sonar.cs.opencover.reportsPaths=coverage.xml /d:sonar.coverage.exclusions=**/*Tests.cs
}
}
@@ -134,9 +126,7 @@ after_test:
- ps: |
Execute-Action "ending code analysis" {
- if ($env:SONARQUBE_RUNNING -eq $true) {
- MSBuild.SonarQube.Runner.exe end /d:sonar.login=$env:SONARQUBE_TOKEN
- }
+ dotnet sonarscanner end /d:sonar.login=$env:SONARQUBE_TOKEN
}
artifacts:
diff --git a/src/PartialResponse.Core/DelimiterOptions.cs b/src/PartialResponse.Core/DelimiterOptions.cs
new file mode 100644
index 0000000..b4a8db6
--- /dev/null
+++ b/src/PartialResponse.Core/DelimiterOptions.cs
@@ -0,0 +1,95 @@
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+
+namespace PartialResponse.Core
+{
+ ///
+ /// Represents delimiter options for parser
+ ///
+ public class DelimiterOptions
+ {
+ private static DelimiterOptions defaultOptions;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Characters representing field delimiters.
+ /// Characters representing nested field delimiters.
+ /// Characters representing field group start delimiters.
+ /// Characters representing field group end delimiters.
+ public DelimiterOptions(char[] fieldsDelimiters, char[] nestedFieldDelimiters, char[] fieldGroupStartDelimiters, char[] fieldGroupEndDelimiters)
+ {
+ var map = new Dictionary();
+
+ foreach (var c in fieldsDelimiters ?? throw new ArgumentNullException(nameof(fieldsDelimiters)))
+ {
+ map.Add(c, TokenType.FieldsDelimiter);
+ }
+
+ foreach (var c in nestedFieldDelimiters ?? throw new ArgumentNullException(nameof(nestedFieldDelimiters)))
+ {
+ map.Add(c, TokenType.NestedFieldDelimiter);
+ }
+
+ foreach (var c in fieldGroupStartDelimiters ?? throw new ArgumentNullException(nameof(fieldGroupStartDelimiters)))
+ {
+ map.Add(c, TokenType.FieldGroupStartDelimiter);
+ }
+
+ foreach (var c in fieldGroupEndDelimiters ?? throw new ArgumentNullException(nameof(fieldGroupEndDelimiters)))
+ {
+ map.Add(c, TokenType.FieldGroupEndDelimiter);
+ }
+
+ this.DelimiterToTokenTypeMap = map;
+
+ this.FieldsDelimiters = fieldsDelimiters;
+ this.NestedFieldDelimiters = nestedFieldDelimiters;
+ this.FieldGroupStartDelimiters = fieldGroupStartDelimiters;
+ this.FieldGroupEndDelimiters = fieldGroupEndDelimiters;
+ }
+
+ ///
+ /// Gets default options for parser. Default options are:
+ /// field delimiters - ','
+ /// nested field delimiters - '/'
+ /// field group start delimiters - '('
+ /// field group end delimiters - ')'
+ ///
+ public static DelimiterOptions DefaultOptions
+ {
+ get
+ {
+ return defaultOptions
+ ?? (defaultOptions = new DelimiterOptions(new[] { ',' }, new[] { '/' }, new[] { '(' }, new[] { ')' }));
+ }
+ }
+
+ ///
+ /// Gets delimiter to token type map.
+ ///
+ public IReadOnlyDictionary DelimiterToTokenTypeMap { get; }
+
+ ///
+ /// Gets fields delimiters.
+ ///
+ public char[] FieldsDelimiters { get; }
+
+ ///
+ /// Gets nested field delimiters.
+ ///
+ public char[] NestedFieldDelimiters { get; }
+
+ ///
+ /// Gets nested field group start delimiters.
+ ///
+ public char[] FieldGroupStartDelimiters { get; }
+
+ ///
+ /// Gets nested field group end delimiters.
+ ///
+ public char[] FieldGroupEndDelimiters { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/PartialResponse.Core/Field.cs b/src/PartialResponse.Core/Field.cs
index ba9c10a..ef73b27 100644
--- a/src/PartialResponse.Core/Field.cs
+++ b/src/PartialResponse.Core/Field.cs
@@ -1,6 +1,7 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
+using System.Linq;
namespace PartialResponse.Core
{
@@ -16,15 +17,20 @@ public struct Field
///
/// Initializes a new instance of the structure.
///
- /// The value of the field.
- public Field(string value)
+ /// The value of the field.
+ public Field(params string[] parts)
{
- if (value == null)
+ if (parts == null)
+ {
+ throw new ArgumentNullException(nameof(parts));
+ }
+
+ if (parts.Length == 0 || parts.Any(string.IsNullOrEmpty))
{
- throw new ArgumentNullException(nameof(value));
+ throw new ArgumentException("Parts cannot be empty or null", nameof(parts));
}
- this.Parts = value.Split('/');
+ this.Parts = parts;
}
///
@@ -77,14 +83,5 @@ public bool Matches(string[] parts, bool ignoreCase)
return true;
}
-
- ///
- /// Returns a string that represents the current object.
- ///
- /// A string that represents the current object.
- public override string ToString()
- {
- return string.Join("/", this.Parts);
- }
}
}
\ No newline at end of file
diff --git a/src/PartialResponse.Core/Fields.cs b/src/PartialResponse.Core/Fields.cs
index 0d40e93..b9cc982 100644
--- a/src/PartialResponse.Core/Fields.cs
+++ b/src/PartialResponse.Core/Fields.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using System.Collections.Generic;
@@ -14,7 +14,7 @@ namespace PartialResponse.Core
/// from your code.
public struct Fields
{
- private IEnumerable values;
+ private readonly IEnumerable values;
private Fields(IEnumerable values)
{
@@ -36,8 +36,10 @@ public IEnumerable Values
/// The value.
/// When this method returns, contains the equivalent of the value,
/// if the conversion succeeded, or null if the conversion failed.
+ /// Optional options which allow to specify custom delimiters. If no value provided
+ /// a default options are used.
/// true if value was converted successfully; otherwise, false.
- public static bool TryParse(string value, out Fields result)
+ public static bool TryParse(string value, out Fields result, DelimiterOptions options = null)
{
if (value == null)
{
@@ -46,7 +48,7 @@ public static bool TryParse(string value, out Fields result)
using (var reader = new StringReader(value))
{
- var context = new ParserContext(reader);
+ var context = new ParserContext(reader, options ?? DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
parser.Parse();
@@ -68,10 +70,12 @@ public static bool TryParse(string value, out Fields result)
/// Indicates whether a field matches the specified value.
///
/// The value to match.
+ /// Delimiter options to use when matching. If no options provided then the
+ /// default options are used.
/// true if a field matches the specified value; otherwise, false.
- public bool Matches(string value)
+ public bool Matches(string value, DelimiterOptions delimiterOptions = null)
{
- return this.Matches(value, false);
+ return this.Matches(value, false, delimiterOptions);
}
///
@@ -79,15 +83,23 @@ public bool Matches(string value)
///
/// The value to match.
/// A value which indicates whether matching should be case-insensitive.
+ /// Delimiter options to use when matching. If no options provided then the
+ /// default options are used.
/// true if a field matches the specified value; otherwise, false.
- public bool Matches(string value, bool ignoreCase)
+ public bool Matches(string value, bool ignoreCase, DelimiterOptions delimiterOptions = null)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
- var parts = value.Split('/');
+ if (!this.Values.Any())
+ {
+ return false;
+ }
+
+ var separators = (delimiterOptions ?? DelimiterOptions.DefaultOptions).NestedFieldDelimiters;
+ var parts = value.Split(separators);
return this.Values.Any(field => field.Matches(parts, ignoreCase));
}
diff --git a/src/PartialResponse.Core/Parser.cs b/src/PartialResponse.Core/Parser.cs
index 01d07b5..2e90880 100644
--- a/src/PartialResponse.Core/Parser.cs
+++ b/src/PartialResponse.Core/Parser.cs
@@ -1,7 +1,8 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using System.Collections.Generic;
+using System.Linq;
namespace PartialResponse.Core
{
@@ -12,7 +13,7 @@ namespace PartialResponse.Core
/// from your code.
public class Parser
{
- private readonly Stack prefixes = new Stack();
+ private readonly Stack> prefixes = new Stack>();
private readonly Dictionary handlers;
private readonly ParserContext context;
private readonly Tokenizer tokenizer;
@@ -34,13 +35,14 @@ public Parser(ParserContext context)
this.context = context;
- this.tokenizer = new Tokenizer(context.Source);
+ this.tokenizer = new Tokenizer(context.Source, context.Options.DelimiterToTokenTypeMap);
+
this.handlers = new Dictionary
{
- { TokenType.ForwardSlash, this.HandleForwardSlash },
- { TokenType.LeftParenthesis, this.HandleLeftParenthesis },
- { TokenType.RightParenthesis, this.HandleRightParenthesis },
- { TokenType.Comma, this.HandleComma },
+ { TokenType.NestedFieldDelimiter, this.HandleNestedFieldDelimiter },
+ { TokenType.FieldGroupStartDelimiter, this.HandleFieldGroupStartDelimiter },
+ { TokenType.FieldGroupEndDelimiter, this.HandleFieldGroupEndDelimiter },
+ { TokenType.FieldsDelimiter, this.HandleFieldsDelimiter },
{ TokenType.Eof, this.HandleEof }
};
}
@@ -78,26 +80,26 @@ private void HandleIdentifier(bool acceptEnd)
return;
}
- string prefix;
+ List prefixes;
if (this.prefixes.Count > 0)
{
- var previousPrefix = this.depth > 0 && this.previousToken.Type != TokenType.ForwardSlash ? this.prefixes.Peek() : this.prefixes.Pop();
+ prefixes = this.depth > 0 && this.previousToken.Type != TokenType.NestedFieldDelimiter
+ ? this.prefixes.Peek().ToList() // creating a copy of existing prefixes when we are diving deep
+ : this.prefixes.Pop();
- prefix = $"{previousPrefix}/{this.currentToken.Value}";
+ prefixes.Add(this.currentToken.Value);
}
else
{
- prefix = this.currentToken.Value;
+ prefixes = new List { this.currentToken.Value };
}
- this.prefixes.Push(prefix);
+ this.prefixes.Push(prefixes);
this.NextToken();
- Action handler;
-
- if (!this.handlers.TryGetValue(this.currentToken.Type, out handler))
+ if (!this.handlers.TryGetValue(this.currentToken.Type, out var handler))
{
this.context.Error = new UnexpectedTokenError(this.currentToken);
@@ -107,13 +109,13 @@ private void HandleIdentifier(bool acceptEnd)
handler();
}
- private void HandleForwardSlash()
+ private void HandleNestedFieldDelimiter()
{
this.NextToken();
this.HandleIdentifier(acceptEnd: false);
}
- private void HandleLeftParenthesis()
+ private void HandleFieldGroupStartDelimiter()
{
this.depth++;
@@ -121,7 +123,7 @@ private void HandleLeftParenthesis()
this.HandleIdentifier(acceptEnd: false);
}
- private void HandleRightParenthesis()
+ private void HandleFieldGroupEndDelimiter()
{
do
{
@@ -129,7 +131,7 @@ private void HandleRightParenthesis()
if (this.previousToken.Type == TokenType.Identifier)
{
- this.context.Values.Add(new Field(value));
+ this.context.Values.Add(new Field(value.ToArray()));
}
this.depth--;
@@ -143,11 +145,11 @@ private void HandleRightParenthesis()
this.NextToken();
}
- while (this.currentToken.Type == TokenType.RightParenthesis);
+ while (this.currentToken.Type == TokenType.FieldGroupEndDelimiter);
if (this.currentToken.Type != TokenType.Eof)
{
- if (this.currentToken.Type != TokenType.Comma)
+ if (this.currentToken.Type != TokenType.FieldsDelimiter)
{
this.context.Error = new UnexpectedTokenError(this.currentToken);
@@ -161,11 +163,11 @@ private void HandleRightParenthesis()
}
}
- private void HandleComma()
+ private void HandleFieldsDelimiter()
{
var value = this.prefixes.Pop();
- this.context.Values.Add(new Field(value));
+ this.context.Values.Add(new Field(value.ToArray()));
this.NextToken();
this.HandleIdentifier(acceptEnd: false);
@@ -182,7 +184,7 @@ private void HandleEof()
var value = this.prefixes.Pop();
- this.context.Values.Add(new Field(value));
+ this.context.Values.Add(new Field(value.ToArray()));
}
private void NextToken()
diff --git a/src/PartialResponse.Core/ParserContext.cs b/src/PartialResponse.Core/ParserContext.cs
index 2573886..9a04693 100644
--- a/src/PartialResponse.Core/ParserContext.cs
+++ b/src/PartialResponse.Core/ParserContext.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using System.Collections.Generic;
@@ -17,14 +17,21 @@ public class ParserContext
/// Initializes a new instance of the class.
///
/// A representing the input string.
- public ParserContext(TextReader source)
+ /// Delimiters options for parser.
+ public ParserContext(TextReader source, DelimiterOptions options)
{
if (source == null)
{
- throw new ArgumentNullException();
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ if (options == null)
+ {
+ throw new ArgumentNullException(nameof(options));
}
this.Source = source;
+ this.Options = options;
this.Values = new List();
}
@@ -38,12 +45,17 @@ public ParserContext(TextReader source)
/// Gets the representing the input string.
///
/// The representing the input string.
- public TextReader Source { get; private set; }
+ public TextReader Source { get; }
///
/// Gets the values that are extracted while parsing.
///
/// The values that are extracted while parsing.
- public List Values { get; private set; }
+ public List Values { get; }
+
+ ///
+ /// Gets delimiters options.
+ ///
+ public DelimiterOptions Options { get; }
}
}
\ No newline at end of file
diff --git a/src/PartialResponse.Core/Token.cs b/src/PartialResponse.Core/Token.cs
index fa19430..7d31b66 100644
--- a/src/PartialResponse.Core/Token.cs
+++ b/src/PartialResponse.Core/Token.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
namespace PartialResponse.Core
{
diff --git a/src/PartialResponse.Core/TokenType.cs b/src/PartialResponse.Core/TokenType.cs
index e960e3a..a7bb22a 100644
--- a/src/PartialResponse.Core/TokenType.cs
+++ b/src/PartialResponse.Core/TokenType.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
namespace PartialResponse.Core
{
@@ -17,24 +17,24 @@ public enum TokenType
Identifier,
///
- /// A forward slash ('/') delimiter.
+ /// A nested field delimiter, for example - forward slash ('/').
///
- ForwardSlash,
+ NestedFieldDelimiter,
///
- /// An opening parenthesis ('(').
+ /// A field group start delimiter, for example - opening parenthesis ('(').
///
- LeftParenthesis,
+ FieldGroupStartDelimiter,
///
- /// A closing parenthesis (')').
+ /// A field group end delimiter, for example - closing parenthesis (')').
///
- RightParenthesis,
+ FieldGroupEndDelimiter,
///
- /// A comma (',') delimiter.
+ /// A fields delimiter, for example - comma (',').
///
- Comma,
+ FieldsDelimiter,
///
/// A space, horizontal tab, new line, or carriage return. Typically, a contiguous run of whitespace is a
@@ -47,4 +47,4 @@ public enum TokenType
///
Eof
}
-}
\ No newline at end of file
+}
diff --git a/src/PartialResponse.Core/Tokenizer.cs b/src/PartialResponse.Core/Tokenizer.cs
index 6011a87..49b871e 100644
--- a/src/PartialResponse.Core/Tokenizer.cs
+++ b/src/PartialResponse.Core/Tokenizer.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using System.Collections.Generic;
@@ -15,14 +15,8 @@ namespace PartialResponse.Core
public class Tokenizer
{
private readonly TextReader source;
+ private readonly IReadOnlyDictionary tokensMap;
private readonly StringBuilder buffer = new StringBuilder();
- private readonly Dictionary tokens = new Dictionary()
- {
- ['/'] = TokenType.ForwardSlash,
- ['('] = TokenType.LeftParenthesis,
- [')'] = TokenType.RightParenthesis,
- [','] = TokenType.Comma
- };
private int position = -1;
@@ -30,14 +24,21 @@ public class Tokenizer
/// Initializes a new instance of the class.
///
/// A representing the input string.
- public Tokenizer(TextReader source)
+ /// A map of non-identifier tokens to their character representations.
+ public Tokenizer(TextReader source, IReadOnlyDictionary tokensMap)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
+ if (tokensMap == null)
+ {
+ throw new ArgumentNullException(nameof(tokensMap));
+ }
+
this.source = source;
+ this.tokensMap = tokensMap;
}
///
@@ -51,28 +52,29 @@ public Token NextToken()
return new Token(null, TokenType.Eof, this.position);
}
- Token token;
-
- TokenType tokenType;
-
- if (this.tokens.TryGetValue(this.GetCurrentCharacter(), out tokenType))
+ if (this.tokensMap.TryGetValue(this.GetCurrentCharacter(), out var tokenType))
{
this.TakeCharacter();
- token = new Token(this.buffer.ToString(), tokenType, this.position);
+ return this.CreateToken(tokenType);
}
- else if (this.IsWhiteSpace(this.GetCurrentCharacter()))
+ else if (char.IsWhiteSpace(this.GetCurrentCharacter()))
{
- this.TakeCharactersWhile(character => this.IsWhiteSpace(character));
+ this.TakeCharactersWhile(character => char.IsWhiteSpace(character));
- token = new Token(this.buffer.ToString(), TokenType.WhiteSpace, this.position);
+ return this.CreateToken(TokenType.WhiteSpace);
}
else
{
- this.TakeCharactersWhile(character => !this.tokens.ContainsKey(character) && !this.IsWhiteSpace(character));
+ this.TakeCharactersWhile(character => !this.tokensMap.ContainsKey(character) && !char.IsWhiteSpace(character));
- token = new Token(this.buffer.ToString(), TokenType.Identifier, this.position);
+ return this.CreateToken(TokenType.Identifier);
}
+ }
+
+ private Token CreateToken(TokenType tokenType)
+ {
+ var token = new Token(this.buffer.ToString(), tokenType, this.position);
this.buffer.Clear();
@@ -96,15 +98,6 @@ private void TakeCharacter()
this.position++;
}
- private bool IsWhiteSpace(char character)
- {
- return
- character == ' ' ||
- character == '\t' ||
- character == '\r' ||
- character == '\n';
- }
-
private char GetCurrentCharacter()
{
var value = this.source.Peek();
diff --git a/src/PartialResponse.Core/UnexpectedTokenError.cs b/src/PartialResponse.Core/UnexpectedTokenError.cs
index 35351e8..7e40440 100644
--- a/src/PartialResponse.Core/UnexpectedTokenError.cs
+++ b/src/PartialResponse.Core/UnexpectedTokenError.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
namespace PartialResponse.Core
{
diff --git a/stylecop.json b/stylecop.json
index 1049ef0..b4c5402 100644
--- a/stylecop.json
+++ b/stylecop.json
@@ -2,7 +2,7 @@
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
"settings": {
"documentationRules": {
- "copyrightText": "Copyright (c) Arjen Post. See LICENSE in the project root for license information.",
+ "copyrightText": "Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.",
"documentInternalElements": false,
"xmlHeader": false
},
diff --git a/test/PartialResponse.Core.Tests/FieldTests.cs b/test/PartialResponse.Core.Tests/FieldTests.cs
index bd86303..a6b38b7 100644
--- a/test/PartialResponse.Core.Tests/FieldTests.cs
+++ b/test/PartialResponse.Core.Tests/FieldTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using Xunit;
@@ -8,39 +8,34 @@ namespace PartialResponse.Core.Tests
public class FieldTests
{
[Fact]
- public void TheConstructorShouldThrowIfValueIsNull()
+ public void TheConstructorShouldThrowIfValuesIsNull()
{
// Arrange
- string value = null;
+ string[] value = null;
// Act
Assert.Throws(() => new Field(value));
}
[Fact]
- public void ThePartsPropertyShouldContainSingleValue()
+ public void TheConstructorShouldThrowIfOneOfValuesIsNull()
{
// Arrange
- var value = "foo";
+ string value = null;
// Act
- var field = new Field(value);
-
- // Assert
- Assert.Equal(new[] { "foo" }, field.Parts);
+ Assert.Throws(() => new Field("bla", value));
}
[Fact]
- public void ThePartsPropertyShouldContainMultipleValues()
+ public void ThePartsPropertyShouldContainSingleValue()
{
// Arrange
- var value = "foo/bar";
-
// Act
- var field = new Field(value);
+ var field = new Field("foo");
// Assert
- Assert.Equal(new[] { "foo", "bar" }, field.Parts);
+ Assert.Equal(new[] { "foo" }, field.Parts);
}
[Fact]
@@ -72,7 +67,7 @@ public void TheMatchesMethodShouldReturnFalseForDifferentValues()
public void TheMatchesMethodShouldReturnFalseForDifferentNestedValues()
{
// Arrange
- var field = new Field("foo/bar");
+ var field = new Field("foo", "bar");
// Act
var result = field.Matches(new[] { "foo", "baz" });
@@ -111,7 +106,7 @@ public void TheMatchesMethodShouldReturnTrueForSamePrefixValues()
public void TheMatchesMethodShouldReturnTrueForOtherSuffixValue()
{
// Arrange
- var field = new Field("foo/bar");
+ var field = new Field("foo", "bar");
// Act
var result = field.Matches(new[] { "foo" });
@@ -145,19 +140,5 @@ public void TheMatchesMethodShouldIgnoreCase()
// Assert
Assert.True(result);
}
-
- [Fact]
- public void TheToStringMethodShouldReturnValue()
- {
- // Arrange
- var value = "foo/bar";
- var field = new Field(value);
-
- // Act
- var result = field.Matches(new[] { "foo" });
-
- // Assert
- Assert.Equal(value, field.ToString());
- }
}
}
\ No newline at end of file
diff --git a/test/PartialResponse.Core.Tests/FieldsTests.cs b/test/PartialResponse.Core.Tests/FieldsTests.cs
index d4e80ad..4d4f3ab 100644
--- a/test/PartialResponse.Core.Tests/FieldsTests.cs
+++ b/test/PartialResponse.Core.Tests/FieldsTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using Xunit;
diff --git a/test/PartialResponse.Core.Tests/ParserContextTests.cs b/test/PartialResponse.Core.Tests/ParserContextTests.cs
index 8f3590b..d82062e 100644
--- a/test/PartialResponse.Core.Tests/ParserContextTests.cs
+++ b/test/PartialResponse.Core.Tests/ParserContextTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using System.IO;
@@ -15,7 +15,17 @@ public void TheConstructorShouldThrowIfSourceIsNull()
TextReader source = null;
// Act
- Assert.Throws(() => new ParserContext(source));
+ Assert.Throws(() => new ParserContext(source, DelimiterOptions.DefaultOptions));
+ }
+
+ [Fact]
+ public void TheConstructorShouldThrowIfDelimiterOptionsIsNull()
+ {
+ // Arrange
+ DelimiterOptions options = null;
+
+ // Act
+ Assert.Throws(() => new ParserContext(new StringReader(string.Empty), options));
}
}
}
diff --git a/test/PartialResponse.Core.Tests/ParserTests.cs b/test/PartialResponse.Core.Tests/ParserTests.cs
index 26d896b..e78d971 100644
--- a/test/PartialResponse.Core.Tests/ParserTests.cs
+++ b/test/PartialResponse.Core.Tests/ParserTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using System.IO;
@@ -24,7 +24,7 @@ public void TheParseMethodShouldParseEmptySource()
{
// Arrange
var source = new StringReader(string.Empty);
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -35,15 +35,18 @@ public void TheParseMethodShouldParseEmptySource()
}
[Theory]
- [InlineData("/", TokenType.ForwardSlash)]
- [InlineData("(", TokenType.LeftParenthesis)]
- [InlineData(")", TokenType.RightParenthesis)]
- [InlineData(",", TokenType.Comma)]
+ [InlineData("/", TokenType.NestedFieldDelimiter)]
+ [InlineData(".", TokenType.NestedFieldDelimiter)]
+ [InlineData("(", TokenType.FieldGroupStartDelimiter)]
+ [InlineData("[", TokenType.FieldGroupStartDelimiter)]
+ [InlineData(")", TokenType.FieldGroupEndDelimiter)]
+ [InlineData("]", TokenType.FieldGroupEndDelimiter)]
+ [InlineData(",", TokenType.FieldsDelimiter)]
public void TheParseMethodShouldSetErrorIfIllegalTokenAtStart(string value, TokenType tokenType)
{
// Arrange
var source = new StringReader(value);
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -58,7 +61,7 @@ public void TheParseMethodShouldParseSingleIdentifier()
{
// Arrange
var source = new StringReader("foo");
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -73,7 +76,7 @@ public void TheParseMethodShouldParseNestedIdentifier()
{
// Arrange
var source = new StringReader("foo/bar");
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -84,16 +87,28 @@ public void TheParseMethodShouldParseNestedIdentifier()
}
[Theory]
- [InlineData("/", TokenType.ForwardSlash)]
- [InlineData("(", TokenType.LeftParenthesis)]
- [InlineData(")", TokenType.RightParenthesis)]
- [InlineData(",", TokenType.Comma)]
- [InlineData("", TokenType.Eof)]
- public void TheParseMethodShouldSetErrorIfIllegalTokenAfterForwardSlash(string value, TokenType tokenType)
+ [InlineData(".", "/", TokenType.NestedFieldDelimiter)]
+ [InlineData(".", ".", TokenType.NestedFieldDelimiter)]
+ [InlineData(".", "(", TokenType.FieldGroupStartDelimiter)]
+ [InlineData(".", "[", TokenType.FieldGroupStartDelimiter)]
+ [InlineData(".", ")", TokenType.FieldGroupEndDelimiter)]
+ [InlineData(".", "]", TokenType.FieldGroupEndDelimiter)]
+ [InlineData(".", ",", TokenType.FieldsDelimiter)]
+ [InlineData(".", "", TokenType.Eof)]
+
+ [InlineData("/", "/", TokenType.NestedFieldDelimiter)]
+ [InlineData("/", ".", TokenType.NestedFieldDelimiter)]
+ [InlineData("/", "(", TokenType.FieldGroupStartDelimiter)]
+ [InlineData("/", "[", TokenType.FieldGroupStartDelimiter)]
+ [InlineData("/", ")", TokenType.FieldGroupEndDelimiter)]
+ [InlineData("/", "]", TokenType.FieldGroupEndDelimiter)]
+ [InlineData("/", ",", TokenType.FieldsDelimiter)]
+ [InlineData("/", "", TokenType.Eof)]
+ public void TheParseMethodShouldSetErrorIfIllegalTokenAfterNestedFieldDelimiter(string delimiter, string value, TokenType tokenType)
{
// Arrange
- var source = new StringReader($"foo/{value}");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{delimiter}{value}");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -108,7 +123,7 @@ public void TheParseMethodShouldParseMultipleIdentifiers()
{
// Arrange
var source = new StringReader("foo,bar");
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -119,16 +134,19 @@ public void TheParseMethodShouldParseMultipleIdentifiers()
}
[Theory]
- [InlineData("/", TokenType.ForwardSlash)]
- [InlineData("(", TokenType.LeftParenthesis)]
- [InlineData(")", TokenType.RightParenthesis)]
- [InlineData(",", TokenType.Comma)]
+ [InlineData("/", TokenType.NestedFieldDelimiter)]
+ [InlineData(".", TokenType.NestedFieldDelimiter)]
+ [InlineData("(", TokenType.FieldGroupStartDelimiter)]
+ [InlineData("[", TokenType.FieldGroupStartDelimiter)]
+ [InlineData(")", TokenType.FieldGroupEndDelimiter)]
+ [InlineData("]", TokenType.FieldGroupEndDelimiter)]
+ [InlineData(",", TokenType.FieldsDelimiter)]
[InlineData("", TokenType.Eof)]
public void TheParseMethodShouldSetErrorIfIllegalTokenAfterComma(string value, TokenType tokenType)
{
// Arrange
var source = new StringReader($"foo,{value}");
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -138,12 +156,14 @@ public void TheParseMethodShouldSetErrorIfIllegalTokenAfterComma(string value, T
Assert.Equal(tokenType, context.Error.Type);
}
- [Fact]
- public void TheParseMethodShouldParseGroupedIdentifier()
+ [Theory]
+ [InlineData("(", ")")]
+ [InlineData("[", "]")]
+ public void TheParseMethodShouldParseGroupedIdentifier(string leftGroupDelimiter, string rightGroupDelimiter)
{
// Arrange
- var source = new StringReader("foo(bar)");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{leftGroupDelimiter}bar{rightGroupDelimiter}");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -153,12 +173,14 @@ public void TheParseMethodShouldParseGroupedIdentifier()
Assert.Equal(new[] { "foo/bar" }, context.Values.Select(value => string.Join("/", value.Parts)));
}
- [Fact]
- public void TheParseMethodShouldParseGroupedMultipleIdentifiers()
+ [Theory]
+ [InlineData("(", ")")]
+ [InlineData("[", "]")]
+ public void TheParseMethodShouldParseGroupedMultipleIdentifiers(string leftGroupDelimiter, string rightGroupDelimiter)
{
// Arrange
- var source = new StringReader("foo(bar,baz)");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{leftGroupDelimiter}bar,baz{rightGroupDelimiter}");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -168,12 +190,14 @@ public void TheParseMethodShouldParseGroupedMultipleIdentifiers()
Assert.Equal(new[] { "foo/bar", "foo/baz" }, context.Values.Select(value => string.Join("/", value.Parts)));
}
- [Fact]
- public void TheParseMethodShouldParseIdentifierAfterGroupedMultipleIdentifiers()
+ [Theory]
+ [InlineData("(", ")")]
+ [InlineData("[", "]")]
+ public void TheParseMethodShouldParseIdentifierAfterGroupedMultipleIdentifiers(string leftGroupDelimiter, string rightGroupDelimiter)
{
// Arrange
- var source = new StringReader("foo(bar,baz),qux");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{leftGroupDelimiter}bar,baz{rightGroupDelimiter},qux");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -183,12 +207,16 @@ public void TheParseMethodShouldParseIdentifierAfterGroupedMultipleIdentifiers()
Assert.Equal(new[] { "foo/bar", "foo/baz", "qux" }, context.Values.Select(value => string.Join("/", value.Parts)));
}
- [Fact]
- public void TheParseMethodShouldParseGroupedNestedIdentifier()
+ [Theory]
+ [InlineData("(", ")", "/")]
+ [InlineData("[", "]", "/")]
+ [InlineData("(", ")", ".")]
+ [InlineData("[", "]", ".")]
+ public void TheParseMethodShouldParseGroupedNestedIdentifier(string leftGroupDelimiter, string rightGroupDelimiter, string nestedFieldDelimiter)
{
// Arrange
- var source = new StringReader("foo(bar/baz)");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{leftGroupDelimiter}bar{nestedFieldDelimiter}baz{rightGroupDelimiter}");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -198,12 +226,16 @@ public void TheParseMethodShouldParseGroupedNestedIdentifier()
Assert.Equal(new[] { "foo/bar/baz" }, context.Values.Select(value => string.Join("/", value.Parts)));
}
- [Fact]
- public void TheParseMethodShouldParseGroupedMultipleNestedIdentifier()
+ [Theory]
+ [InlineData("(", ")", "/")]
+ [InlineData("[", "]", "/")]
+ [InlineData("(", ")", ".")]
+ [InlineData("[", "]", ".")]
+ public void TheParseMethodShouldParseGroupedMultipleNestedIdentifier(string leftGroupDelimiter, string rightGroupDelimiter, string nestedFieldDelimiter)
{
// Arrange
- var source = new StringReader("foo(bar/baz,qux/quux)");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{leftGroupDelimiter}bar{nestedFieldDelimiter}baz,qux{nestedFieldDelimiter}quux{rightGroupDelimiter}");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -213,12 +245,14 @@ public void TheParseMethodShouldParseGroupedMultipleNestedIdentifier()
Assert.Equal(new[] { "foo/bar/baz", "foo/qux/quux" }, context.Values.Select(value => string.Join("/", value.Parts)));
}
- [Fact]
- public void TheParseMethodShouldSetErrorIfTooManyLeftParenthesis()
+ [Theory]
+ [InlineData("(")]
+ [InlineData("[")]
+ public void TheParseMethodShouldSetErrorIfTooManyLeftDelimiters(string leftDelimiter)
{
// Arrange
- var source = new StringReader("foo(bar");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{leftDelimiter}bar");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -228,32 +262,45 @@ public void TheParseMethodShouldSetErrorIfTooManyLeftParenthesis()
Assert.Equal(TokenType.Eof, context.Error.Type);
}
- [Fact]
- public void TheParseMethodShouldSetErrorIfTooManyRightParenthesis()
+ [Theory]
+ [InlineData(")")]
+ [InlineData("]")]
+ public void TheParseMethodShouldSetErrorIfTooManyRightDelimiters(string rightDelimiter)
{
// Arrange
- var source = new StringReader("foo(bar))");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo(bar{rightDelimiter}{rightDelimiter}");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
parser.Parse();
// Assert
- Assert.Equal(TokenType.RightParenthesis, context.Error.Type);
+ Assert.Equal(TokenType.FieldGroupEndDelimiter, context.Error.Type);
}
[Theory]
- [InlineData("/", TokenType.ForwardSlash)]
- [InlineData("(", TokenType.LeftParenthesis)]
- [InlineData(")", TokenType.RightParenthesis)]
- [InlineData(",", TokenType.Comma)]
- [InlineData("", TokenType.Eof)]
- public void TheParseMethodShouldSetErrorIfIllegalTokenAfterLeftParenthesis(string value, TokenType tokenType)
+ [InlineData("(", "/", TokenType.NestedFieldDelimiter)]
+ [InlineData("(", ".", TokenType.NestedFieldDelimiter)]
+ [InlineData("(", "(", TokenType.FieldGroupStartDelimiter)]
+ [InlineData("(", "[", TokenType.FieldGroupStartDelimiter)]
+ [InlineData("(", ")", TokenType.FieldGroupEndDelimiter)]
+ [InlineData("(", "]", TokenType.FieldGroupEndDelimiter)]
+ [InlineData("(", ",", TokenType.FieldsDelimiter)]
+ [InlineData("(", "", TokenType.Eof)]
+ [InlineData("[", "/", TokenType.NestedFieldDelimiter)]
+ [InlineData("[", ".", TokenType.NestedFieldDelimiter)]
+ [InlineData("[", "(", TokenType.FieldGroupStartDelimiter)]
+ [InlineData("[", "[", TokenType.FieldGroupStartDelimiter)]
+ [InlineData("[", ")", TokenType.FieldGroupEndDelimiter)]
+ [InlineData("[", "]", TokenType.FieldGroupEndDelimiter)]
+ [InlineData("[", ",", TokenType.FieldsDelimiter)]
+ [InlineData("[", "", TokenType.Eof)]
+ public void TheParseMethodShouldSetErrorIfIllegalTokenAfterLeftGroupDelimiter(string delimiter, string value, TokenType tokenType)
{
// Arrange
- var source = new StringReader($"foo({value}");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{delimiter}{value}");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -264,13 +311,13 @@ public void TheParseMethodShouldSetErrorIfIllegalTokenAfterLeftParenthesis(strin
}
[Theory]
- [InlineData("/", TokenType.ForwardSlash)]
- [InlineData("(", TokenType.LeftParenthesis)]
- public void TheParseMethodShouldSetErrorIfIllegalTokenAfterRightParenthesis(string value, TokenType tokenType)
+ [InlineData(")", "/", TokenType.NestedFieldDelimiter)]
+ [InlineData("]", "(", TokenType.FieldGroupStartDelimiter)]
+ public void TheParseMethodShouldSetErrorIfIllegalTokenAfterRightGroupDelimiter(string delimiter, string value, TokenType tokenType)
{
// Arrange
- var source = new StringReader($"foo(bar){value}");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo(bar{delimiter}{value}");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -280,12 +327,14 @@ public void TheParseMethodShouldSetErrorIfIllegalTokenAfterRightParenthesis(stri
Assert.Equal(tokenType, context.Error.Type);
}
- [Fact]
- public void TheParseMethodShouldParseIdentifierAfterGroupedIdentifier()
+ [Theory]
+ [InlineData("(", ")")]
+ [InlineData("[", "]")]
+ public void TheParseMethodShouldParseIdentifierAfterGroupedIdentifier(string left, string right)
{
// Arrange
- var source = new StringReader("foo(bar),baz");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{left}bar{right},baz");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -295,12 +344,14 @@ public void TheParseMethodShouldParseIdentifierAfterGroupedIdentifier()
Assert.Equal(new[] { "foo/bar", "baz" }, context.Values.Select(value => string.Join("/", value.Parts)));
}
- [Fact]
- public void TheParseMethodShouldParseIdentifierAfterNestedGroupedIdentifiers()
+ [Theory]
+ [InlineData("(", ")")]
+ [InlineData("[", "]")]
+ public void TheParseMethodShouldParseIdentifierAfterNestedGroupedIdentifiers(string left, string right)
{
// Arrange
- var source = new StringReader("foo(bar(baz)),qux");
- var context = new ParserContext(source);
+ var source = new StringReader($"foo{left}bar{left}baz{right}{right},qux");
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -315,7 +366,7 @@ public void TheParseMethodShouldIgnoreSpace()
{
// Arrange
var source = new StringReader(" foo");
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -330,7 +381,7 @@ public void TheParseMethodShouldIgnoreTab()
{
// Arrange
var source = new StringReader("\tfoo");
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -345,7 +396,7 @@ public void TheParseMethodShouldIgnoreCarriageReturn()
{
// Arrange
var source = new StringReader("\rfoo");
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
@@ -360,7 +411,7 @@ public void TheParseMethodShouldIgnoreNewLine()
{
// Arrange
var source = new StringReader("\nfoo");
- var context = new ParserContext(source);
+ var context = new ParserContext(source, DelimiterOptions.DefaultOptions);
var parser = new Parser(context);
// Act
diff --git a/test/PartialResponse.Core.Tests/TokenTests.cs b/test/PartialResponse.Core.Tests/TokenTests.cs
index 54bfced..c800c10 100644
--- a/test/PartialResponse.Core.Tests/TokenTests.cs
+++ b/test/PartialResponse.Core.Tests/TokenTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using Xunit;
diff --git a/test/PartialResponse.Core.Tests/TokenizerTests.cs b/test/PartialResponse.Core.Tests/TokenizerTests.cs
index f7b599c..d2c7477 100644
--- a/test/PartialResponse.Core.Tests/TokenizerTests.cs
+++ b/test/PartialResponse.Core.Tests/TokenizerTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using System;
using System.IO;
@@ -11,122 +11,82 @@ public class TokenizerTests
[Fact]
public void TheConstructorShouldThrowIfReaderIsNull()
{
- // Arrange
- TextReader reader = null;
-
// Act
- Assert.Throws("source", () => new Tokenizer(reader));
+ Assert.Throws("source", () => new Tokenizer(null, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap));
}
[Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeForwardSlash()
+ public void TheConstructorShouldThrowIfDelimiterMapIsNull()
{
- // Arrange
- var reader = new StringReader("/");
- var tokenizer = new Tokenizer(reader);
-
// Act
- var token = tokenizer.NextToken();
-
- // Assert
- Assert.Equal(TokenType.ForwardSlash, token.Type);
- }
-
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenValueForwardSlash()
- {
- // Arrange
- var reader = new StringReader("/");
- var tokenizer = new Tokenizer(reader);
-
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
- Assert.Equal("/", token.Value);
+ Assert.Throws("tokensMap", () => new Tokenizer(new StringReader(string.Empty), null));
}
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeLeftParenthesis()
+ [Theory]
+ [InlineData("/")]
+ [InlineData(".")]
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueNestedFieldDelimiter(string data)
{
// Arrange
- var reader = new StringReader("(");
- var tokenizer = new Tokenizer(reader);
+ var reader = new StringReader(data);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
// Act
var token = tokenizer.NextToken();
// Assert
- Assert.Equal(TokenType.LeftParenthesis, token.Type);
+ Assert.Equal(TokenType.NestedFieldDelimiter, token.Type);
+ Assert.Equal(data, token.Value);
}
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenValueLeftParenthesis()
+ [Theory]
+ [InlineData("(")]
+ [InlineData("[")]
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueStartGroupDelimiter(string data)
{
// Arrange
- var reader = new StringReader("(");
- var tokenizer = new Tokenizer(reader);
+ var reader = new StringReader(data);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
// Act
var token = tokenizer.NextToken();
// Assert
- Assert.Equal("(", token.Value);
- }
+ Assert.Equal(TokenType.FieldGroupStartDelimiter, token.Type);
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeRightParenthesis()
- {
- // Arrange
- var reader = new StringReader(")");
- var tokenizer = new Tokenizer(reader);
-
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
- Assert.Equal(TokenType.RightParenthesis, token.Type);
+ Assert.Equal(data, token.Value);
}
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenValueRightParenthesis()
+ [Theory]
+ [InlineData(")")]
+ [InlineData("]")]
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueEndGroupDelimiter(string data)
{
// Arrange
- var reader = new StringReader(")");
- var tokenizer = new Tokenizer(reader);
+ var reader = new StringReader(data);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
// Act
var token = tokenizer.NextToken();
// Assert
- Assert.Equal(")", token.Value);
- }
-
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeComma()
- {
- // Arrange
- var reader = new StringReader(",");
- var tokenizer = new Tokenizer(reader);
+ Assert.Equal(TokenType.FieldGroupEndDelimiter, token.Type);
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
- Assert.Equal(TokenType.Comma, token.Type);
+ Assert.Equal(data, token.Value);
}
[Fact]
- public void TheNextTokenMethodShouldReturnTokenValueComma()
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueFieldsDelimiter()
{
// Arrange
var reader = new StringReader(",");
- var tokenizer = new Tokenizer(reader);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
// Act
var token = tokenizer.NextToken();
// Assert
+ Assert.Equal(TokenType.FieldsDelimiter, token.Type);
Assert.Equal(",", token.Value);
}
@@ -135,62 +95,32 @@ public void TheNextTokenMethodShouldReturnTokenValueComma()
[InlineData("\t")]
[InlineData("\r")]
[InlineData("\n")]
- public void TheNextTokenMethodShouldReturnTokenTypeWhiteSpace(string value)
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueWhiteSpace(string value)
{
// Arrange
var reader = new StringReader(value);
- var tokenizer = new Tokenizer(reader);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
// Act
var token = tokenizer.NextToken();
// Assert
Assert.Equal(TokenType.WhiteSpace, token.Type);
- }
-
- [Theory]
- [InlineData(" ")]
- [InlineData("\t")]
- [InlineData("\r")]
- [InlineData("\n")]
- public void TheNextTokenMethodShouldReturnTokenValueWhiteSpace(string value)
- {
- // Arrange
- var reader = new StringReader(value);
- var tokenizer = new Tokenizer(reader);
-
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
Assert.Equal(value, token.Value);
}
[Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeIdentifier()
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueIdentifier()
{
// Arrange
var reader = new StringReader("foo");
- var tokenizer = new Tokenizer(reader);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
// Act
var token = tokenizer.NextToken();
// Assert
Assert.Equal(TokenType.Identifier, token.Type);
- }
-
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenValueIdentifier()
- {
- // Arrange
- var reader = new StringReader("foo");
- var tokenizer = new Tokenizer(reader);
-
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
Assert.Equal("foo", token.Value);
}
@@ -199,7 +129,7 @@ public void TheNextTokenMethodShouldReturnTokenTypeEofIfEndReached()
{
// Arrange
var reader = new StringReader("foo");
- var tokenizer = new Tokenizer(reader);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
tokenizer.NextToken();
@@ -211,55 +141,28 @@ public void TheNextTokenMethodShouldReturnTokenTypeEofIfEndReached()
}
[Fact]
- public void TheNextTokenMethodShouldReturnTokenValueIdentifierBeforeForwardSlash()
- {
- // Arrange
- var reader = new StringReader("foo/");
- var tokenizer = new Tokenizer(reader);
-
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
- Assert.Equal("foo", token.Value);
- }
-
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeIdentifierBeforeForwardSlash()
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueIdentifierBeforeForwardSlash()
{
// Arrange
var reader = new StringReader("foo/");
- var tokenizer = new Tokenizer(reader);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
// Act
var token = tokenizer.NextToken();
// Assert
Assert.Equal(TokenType.Identifier, token.Type);
- }
-
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenValueIdentifierAfterForwardSlash()
- {
- // Arrange
- var reader = new StringReader("/foo");
- var tokenizer = new Tokenizer(reader);
-
- tokenizer.NextToken();
-
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
Assert.Equal("foo", token.Value);
}
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeIdentifierAfterForwardSlash()
+ [Theory]
+ [InlineData("/")]
+ [InlineData(".")]
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueIdentifierAfterNestedFieldDelimiter(string delimiter)
{
// Arrange
- var reader = new StringReader("/foo");
- var tokenizer = new Tokenizer(reader);
+ var reader = new StringReader($"{delimiter}foo");
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
tokenizer.NextToken();
@@ -268,58 +171,30 @@ public void TheNextTokenMethodShouldReturnTokenTypeIdentifierAfterForwardSlash()
// Assert
Assert.Equal(TokenType.Identifier, token.Type);
- }
-
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenValueIdentifierBeforeWhiteSpace()
- {
- // Arrange
- var reader = new StringReader("foo ");
- var tokenizer = new Tokenizer(reader);
-
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
Assert.Equal("foo", token.Value);
}
[Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeIdentifierBeforeWhiteSpace()
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueIdentifierBeforeWhiteSpace()
{
// Arrange
var reader = new StringReader("foo ");
- var tokenizer = new Tokenizer(reader);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
// Act
var token = tokenizer.NextToken();
// Assert
Assert.Equal(TokenType.Identifier, token.Type);
- }
-
- [Fact]
- public void TheNextTokenMethodShouldReturnTokenValueIdentifierAfterWhiteSpace()
- {
- // Arrange
- var reader = new StringReader(" foo");
- var tokenizer = new Tokenizer(reader);
-
- tokenizer.NextToken();
-
- // Act
- var token = tokenizer.NextToken();
-
- // Assert
Assert.Equal("foo", token.Value);
}
[Fact]
- public void TheNextTokenMethodShouldReturnTokenTypeIdentifierAfterWhiteSpace()
+ public void TheNextTokenMethodShouldReturnTokenTypeAndValueIdentifierAfterWhiteSpace()
{
// Arrange
var reader = new StringReader(" foo");
- var tokenizer = new Tokenizer(reader);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
tokenizer.NextToken();
@@ -328,6 +203,7 @@ public void TheNextTokenMethodShouldReturnTokenTypeIdentifierAfterWhiteSpace()
// Assert
Assert.Equal(TokenType.Identifier, token.Type);
+ Assert.Equal("foo", token.Value);
}
[Fact]
@@ -335,7 +211,7 @@ public void TheNextTokenMethodShouldReturnTokenPosition()
{
// Arrange
var reader = new StringReader("foo/");
- var tokenizer = new Tokenizer(reader);
+ var tokenizer = new Tokenizer(reader, DelimiterOptions.DefaultOptions.DelimiterToTokenTypeMap);
tokenizer.NextToken();
diff --git a/test/PartialResponse.Core.Tests/UnexpectedTokenErrorTests.cs b/test/PartialResponse.Core.Tests/UnexpectedTokenErrorTests.cs
index 0079fd2..0cfacc6 100644
--- a/test/PartialResponse.Core.Tests/UnexpectedTokenErrorTests.cs
+++ b/test/PartialResponse.Core.Tests/UnexpectedTokenErrorTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Arjen Post. See LICENSE in the project root for license information.
+// Copyright (c) Arjen Post and contributors. See LICENSE in the project root for license information.
using Xunit;