Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions src/Prometheus.Language.Tests/Parser/ParserTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using Xunit;

namespace Prometheus.Language
{
public class ParserTests
{
[Fact]
public void ParserSimpleObjectType()
{
// arrange
string sourceText = "type a { b: String c: Int }";
Source source = new Source(sourceText);
Lexer lexer = new Lexer();

// act
Parser parser = new Parser();
DocumentNode document = parser.Parse(lexer, source);

// assert
Assert.Collection(document.Definitions,
t =>
{
Assert.IsType<ObjectTypeDefinitionNode>(t);
var objectTypeDefinition = (ObjectTypeDefinitionNode)t;
Assert.Equal(NodeKind.ObjectTypeDefinition, objectTypeDefinition.Kind);
Assert.Equal("a", objectTypeDefinition.Name.Value);
Assert.Collection(objectTypeDefinition.Fields,
f =>
{
Assert.Equal("b", f.Name.Value);
Assert.IsType<NamedTypeNode>(f.Type);
Assert.Equal("String", ((NamedTypeNode)f.Type).Name.Value);
},
f =>
{
Assert.Equal("c", f.Name.Value);
Assert.IsType<NamedTypeNode>(f.Type);
Assert.Equal("Int", ((NamedTypeNode)f.Type).Name.Value);
});
});
}

[Fact]
public void ParserSimpleInterfaceType()
{
// arrange
string sourceText = "interface a { b: String c: Int }";
Source source = new Source(sourceText);
Lexer lexer = new Lexer();

// act
Parser parser = new Parser();
DocumentNode document = parser.Parse(lexer, source);

// assert
Assert.Collection(document.Definitions,
t =>
{
Assert.IsType<InterfaceTypeDefinitionNode>(t);
var objectTypeDefinition = (InterfaceTypeDefinitionNode)t;
Assert.Equal(NodeKind.InterfaceTypeDefinition, objectTypeDefinition.Kind);
Assert.Equal("a", objectTypeDefinition.Name.Value);
Assert.Collection(objectTypeDefinition.Fields,
f =>
{
Assert.Equal("b", f.Name.Value);
Assert.IsType<NamedTypeNode>(f.Type);
Assert.Equal("String", ((NamedTypeNode)f.Type).Name.Value);
},
f =>
{
Assert.Equal("c", f.Name.Value);
Assert.IsType<NamedTypeNode>(f.Type);
Assert.Equal("Int", ((NamedTypeNode)f.Type).Name.Value);
});
});
}
}
}
19 changes: 19 additions & 0 deletions src/Prometheus.Language/AST/ArgumentNode.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
using System;

namespace Prometheus.Language
{
public class ArgumentNode
: ISyntaxNode
{
public ArgumentNode(Location location, NameNode name, IValueNode value)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}

if (value == null)
{
throw new ArgumentNullException(nameof(value));
}

Location = location;
Name = name;
Value = value;
}

public NodeKind Kind { get; } = NodeKind.Argument;
public Location Location { get; }
public NameNode Name { get; }
Expand Down
8 changes: 8 additions & 0 deletions src/Prometheus.Language/AST/BooleanValueNode.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
using System;

namespace Prometheus.Language
{
public class BooleanValueNode
: IValueNode
{
public BooleanValueNode(Location location, bool value)
{
Location = location;
Value = value;
}

public NodeKind Kind { get; } = NodeKind.BooleanValue;
public Location Location { get; }
public bool Value { get; }
Expand Down
28 changes: 28 additions & 0 deletions src/Prometheus.Language/AST/DirectiveDefinitionNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,34 @@ namespace Prometheus.Language
public class DirectiveDefinitionNode
: ITypeSystemDefinitionNode
{
public DirectiveDefinitionNode(
Location location, NameNode name,
StringValueNode description,
IReadOnlyCollection<InputValueDefinitionNode> arguments,
IReadOnlyCollection<NameNode> locations)
{
if (name == null)
{
throw new System.ArgumentNullException(nameof(name));
}

if (arguments == null)
{
throw new System.ArgumentNullException(nameof(arguments));
}

if (locations == null)
{
throw new System.ArgumentNullException(nameof(locations));
}

Location = location;
Name = name;
Description = description;
Arguments = arguments;
Locations = locations;
}

public NodeKind Kind { get; } = NodeKind.DirectiveDefinition;
public Location Location { get; }
public NameNode Name { get; }
Expand Down
120 changes: 120 additions & 0 deletions src/Prometheus.Language/AST/DirectiveLocation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Prometheus.Language
{
public class DirectiveLocation
: IEquatable<DirectiveLocation>
{
private static readonly Dictionary<string, DirectiveLocation> _locations
= GetAll().ToDictionary(t => t._value);
private string _value;

private DirectiveLocation(string value)
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException(
"The value mustn't be null or empty.",
nameof(value));
}

_value = value;
}

public bool Equals(DirectiveLocation other)
{
if (ReferenceEquals(null, other))
{
return false;
}

if (ReferenceEquals(this, other))
{
return true;
}

return other._value.Equals(_value, StringComparison.Ordinal);
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}

if (ReferenceEquals(this, obj))
{
return true;
}

return Equals(obj as DirectiveLocation);
}

public override int GetHashCode()
{
unchecked
{
return 199 * base.GetHashCode();
}
}

public override string ToString()
{
return _value;
}

public static DirectiveLocation Query = new DirectiveLocation("QUERY");
public static DirectiveLocation Mutation = new DirectiveLocation("MUTATION");
public static DirectiveLocation Subscription = new DirectiveLocation("SUBSCRIPTION");
public static DirectiveLocation Field = new DirectiveLocation("Field");
public static DirectiveLocation FragmentDefinition = new DirectiveLocation("FRAGMENT_DEFINITION");
public static DirectiveLocation FragmentSpread = new DirectiveLocation("FRAGMENT_SPREAD");
public static DirectiveLocation InlineFragment = new DirectiveLocation("INLINE_FRAGMENT");
public static DirectiveLocation Schema = new DirectiveLocation("Schema");
public static DirectiveLocation Scalar = new DirectiveLocation("SCALAR");
public static DirectiveLocation Object = new DirectiveLocation("OBJECT");
public static DirectiveLocation FieldDefinition = new DirectiveLocation("FIELD_DEFINITION");
public static DirectiveLocation ArgumentDefinition = new DirectiveLocation("ARGUMENT_DEFINITION");
public static DirectiveLocation Interface = new DirectiveLocation("INTERFACE");
public static DirectiveLocation Union = new DirectiveLocation("UNION");
public static DirectiveLocation Enum = new DirectiveLocation("ENUM");
public static DirectiveLocation EnumValue = new DirectiveLocation("ENUM_VALUE");
public static DirectiveLocation InputObject = new DirectiveLocation("INPUT_OBJECT");
public static DirectiveLocation InputFieldDefinition = new DirectiveLocation("INPUT_FIELD_DEFINITION");

public static bool IsValidName(string value)
{
return _locations.ContainsKey(value);
}

public static bool TryParse(string value, out DirectiveLocation location)
{
return _locations.TryGetValue(value, out location);
}

private static IEnumerable<DirectiveLocation> GetAll()
{
yield return Query;
yield return Mutation;
yield return Subscription;
yield return Field;
yield return FragmentDefinition;
yield return FragmentSpread;
yield return InlineFragment;
yield return Schema;
yield return Scalar;
yield return Object;
yield return FieldDefinition;
yield return ArgumentDefinition;
yield return Interface;
yield return Union;
yield return Enum;
yield return EnumValue;
yield return InputObject;
yield return InputFieldDefinition;
}
}
}
18 changes: 18 additions & 0 deletions src/Prometheus.Language/AST/DirectiveNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ namespace Prometheus.Language
public class DirectiveNode
: ISyntaxNode
{
public DirectiveNode(Location location, NameNode name,
IReadOnlyCollection<ArgumentNode> arguments)
{
if (name == null)
{
throw new System.ArgumentNullException(nameof(name));
}

if (Arguments == null)
{
throw new System.ArgumentNullException(nameof(Arguments));
}

Location = location;
Name = name;
Arguments = arguments;
}

public NodeKind Kind { get; } = NodeKind.Directive;
public Location Location { get; }
public NameNode Name { get; }
Expand Down
11 changes: 11 additions & 0 deletions src/Prometheus.Language/AST/DocumentNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ namespace Prometheus.Language
public class DocumentNode
: ISyntaxNode
{
public DocumentNode(Location location, IReadOnlyCollection<IDefinitionNode> definitions)
{
if (definitions == null)
{
throw new System.ArgumentNullException(nameof(definitions));
}

Location = location;
Definitions = definitions;
}

public NodeKind Kind { get; } = NodeKind.Document;
public Location Location { get; }
public IReadOnlyCollection<IDefinitionNode> Definitions { get; }
Expand Down
28 changes: 28 additions & 0 deletions src/Prometheus.Language/AST/EnumTypeDefinitionNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,34 @@ namespace Prometheus.Language
public class EnumTypeDefinitionNode
: ITypeDefinitionNode
{
public EnumTypeDefinitionNode(
Location location, NameNode name,
StringValueNode description,
IReadOnlyCollection<DirectiveNode> directives,
IReadOnlyCollection<EnumValueDefinitionNode> values)
{
if (name == null)
{
throw new System.ArgumentNullException(nameof(name));
}

if (directives == null)
{
throw new System.ArgumentNullException(nameof(directives));
}

if (values == null)
{
throw new System.ArgumentNullException(nameof(values));
}

Location = location;
Name = name;
Description = description;
Directives = directives;
Values = values;
}

public NodeKind Kind { get; } = NodeKind.EnumTypeDefinition;
public Location Location { get; }
public NameNode Name { get; }
Expand Down
Loading