argument+directive

This commit is contained in:
thosakwe 2017-07-03 19:03:36 -04:00
parent 5c2649d2d9
commit 9e942d8221
6 changed files with 131 additions and 5 deletions

2
.analysis-options Normal file
View file

@ -0,0 +1,2 @@
analyzer:
strong-mode: true

View file

@ -9,6 +9,8 @@ class ArgumentContext extends Node {
ArgumentContext(this.NAME, this.COLON, this.valueOrVariable);
String get name => NAME.text;
@override
SourceSpan get span =>
new SourceSpan(NAME.span?.start, valueOrVariable.end, toSource());

View file

@ -7,7 +7,6 @@ import 'token_type.dart';
class Parser {
Token _current;
final List<SyntaxError> _errors = [];
int _index = -1;
final List<Token> tokens;
@ -16,8 +15,6 @@ class Parser {
Token get current => _current;
List<SyntaxError> get errors => new List<SyntaxError>.unmodifiable(_errors);
bool next(TokenType type) {
if (peek()?.type == type) {
_current = tokens[++_index];
@ -84,7 +81,7 @@ class Parser {
ARROBA, NAME, null, LPAREN, current, arg, null);
} else
throw new SyntaxError.fromSourceLocation(
'Expected \'(\'', arg.valueOrVariable.span.end);
'Expected \')\'', arg.valueOrVariable.span.end);
} else
throw new SyntaxError.fromSourceLocation(
'Expected argument in directive.', LPAREN.span.end);

View file

@ -1,6 +1,12 @@
import 'package:test/test.dart';
import 'argument_test.dart' as argument;
import 'directive_test.dart' as directive;
import 'value_test.dart' as value;
import 'variable_test.dart' as variable;
main() {
group('argument', argument.main);
group('directive', directive.main);
group('value', value.main);
}
group('variable', variable.main);
}

43
test/argument_test.dart Normal file
View file

@ -0,0 +1,43 @@
import 'package:graphql_parser/graphql_parser.dart';
import 'package:matcher/matcher.dart';
import 'package:test/test.dart';
import 'common.dart';
main() {
test('argument', () {
expect('foo: 2', isArgument('foo', 2));
expect(r'foo: $bar', isArgument('foo', 'bar'));
});
test('exception', () {
expect(() => parseArgument('foo'), throwsSyntaxError);
expect(() => parseArgument('foo:'), throwsSyntaxError);
});
}
ArgumentContext parseArgument(String text) => parse(text).parseArgument();
Matcher isArgument(String name, value) => new _IsArgument(name, value);
class _IsArgument extends Matcher {
final String name;
final value;
_IsArgument(this.name, this.value);
@override
Description describe(Description description) {
return description.add('is an argument named "$name" with value $value');
}
@override
bool matches(item, Map matchState) {
var arg = item is ArgumentContext ? item : parseArgument(item);
if (arg == null) return false;
return equals(name).matches(arg.name, matchState) &&
equals(value).matches(
arg.valueOrVariable.value?.value ??
arg.valueOrVariable.variable?.name,
matchState);
}
}

76
test/directive_test.dart Normal file
View file

@ -0,0 +1,76 @@
import 'package:graphql_parser/graphql_parser.dart';
import 'package:matcher/matcher.dart';
import 'package:test/test.dart';
import 'argument_test.dart';
import 'common.dart';
main() {
test('name only', () {
expect('@foo', isDirective('foo'));
});
test('with value or variable', () {
expect('@foo: 2', isDirective('foo', valueOrVariable: equals(2)));
expect(r'@foo: $bar', isDirective('foo', valueOrVariable: equals('bar')));
});
test('with argument', () {
expect('@foo (bar: 2)', isDirective('foo', argument: isArgument('bar', 2)));
expect(r'@foo (bar: $baz)',
isDirective('foo', argument: isArgument('bar', r'baz')));
});
test('exceptions', () {
expect(() => parseDirective('@'), throwsSyntaxError);
expect(() => parseDirective('@foo:'), throwsSyntaxError);
expect(() => parseDirective('@foo ('), throwsSyntaxError);
expect(() => parseDirective('@foo (bar: 2'), throwsSyntaxError);
expect(() => parseDirective('@foo ()'), throwsSyntaxError);
});
}
DirectiveContext parseDirective(String text) => parse(text).parseDirective();
Matcher isDirective(String name, {Matcher valueOrVariable, Matcher argument}) =>
new _IsDirective(name,
valueOrVariable: valueOrVariable, argument: argument);
class _IsDirective extends Matcher {
final String name;
final Matcher valueOrVariable, argument;
_IsDirective(this.name, {this.valueOrVariable, this.argument});
@override
Description describe(Description description) {
var desc = description.add('is a directive with name "$name"');
if (valueOrVariable != null) {
return valueOrVariable.describe(desc.add(' and '));
} else if (argument != null) {
return argument.describe(desc.add(' and '));
} else
return desc;
}
@override
bool matches(String item, Map matchState) {
var directive = parseDirective(item);
if (directive == null) return false;
if (valueOrVariable != null) {
if (directive.valueOrVariable == null)
return false;
else
return valueOrVariable.matches(
directive.valueOrVariable.value?.value ??
directive.valueOrVariable.variable?.name,
matchState);
} else if (argument != null) {
if (directive.argument == null)
return false;
else
return argument.matches(directive.argument, matchState);
} else
return true;
}
}