Use curly braces

This commit is contained in:
Tobe O 2019-08-07 22:28:20 -04:00
parent 766ec56f57
commit 4a655abb84
10 changed files with 126 additions and 100 deletions

View file

@ -15,15 +15,17 @@ class FieldContext extends Node {
@override @override
FileSpan get span { FileSpan get span {
if (selectionSet != null) if (selectionSet != null) {
return fieldName.span.expand(selectionSet.span); return fieldName.span.expand(selectionSet.span);
else if (directives.isNotEmpty) } else if (directives.isNotEmpty) {
return directives.fold<FileSpan>( return directives.fold<FileSpan>(
fieldName.span, (out, d) => out.expand(d.span)); fieldName.span, (out, d) => out.expand(d.span));
if (arguments.isNotEmpty) }
if (arguments.isNotEmpty) {
return arguments.fold<FileSpan>( return arguments.fold<FileSpan>(
fieldName.span, (out, a) => out.expand(a.span)); fieldName.span, (out, a) => out.expand(a.span));
else } else {
return fieldName.span; return fieldName.span;
} }
} }
}

View file

@ -10,9 +10,9 @@ class NumberValueContext extends InputValueContext<num> {
num get numberValue { num get numberValue {
var text = NUMBER.text; var text = NUMBER.text;
if (!text.contains('E') && !text.contains('e')) if (!text.contains('E') && !text.contains('e')) {
return num.parse(text); return num.parse(text);
else { } else {
var split = text.split(text.contains('E') ? 'E' : 'e'); var split = text.split(text.contains('E') ? 'E' : 'e');
var base = num.parse(split[0]); var base = num.parse(split[0]);
var exp = num.parse(split[1]); var exp = num.parse(split[1]);

View file

@ -63,8 +63,9 @@ class StringValueContext extends InputValueContext<String> {
default: default:
buf.writeCharCode(next); buf.writeCharCode(next);
} }
} else } else {
throw SyntaxError('Unexpected "\\" in string literal.', span); throw SyntaxError('Unexpected "\\" in string literal.', span);
}
} else { } else {
buf.writeCharCode(ch); buf.writeCharCode(ch);
} }

View file

@ -68,9 +68,9 @@ class Parser {
OperationDefinitionContext parseOperationDefinition() { OperationDefinitionContext parseOperationDefinition() {
var selectionSet = parseSelectionSet(); var selectionSet = parseSelectionSet();
if (selectionSet != null) if (selectionSet != null) {
return OperationDefinitionContext(null, null, null, selectionSet); return OperationDefinitionContext(null, null, null, selectionSet);
else { } else {
if (nextName('mutation') || if (nextName('mutation') ||
nextName('query') || nextName('query') ||
nextName('subscription')) { nextName('subscription')) {
@ -79,20 +79,20 @@ class Parser {
var variables = parseVariableDefinitions(); var variables = parseVariableDefinitions();
var dirs = parseDirectives(); var dirs = parseDirectives();
var selectionSet = parseSelectionSet(); var selectionSet = parseSelectionSet();
if (selectionSet != null) if (selectionSet != null) {
return OperationDefinitionContext( return OperationDefinitionContext(TYPE, NAME, variables, selectionSet)
TYPE, NAME, variables, selectionSet)
..directives.addAll(dirs); ..directives.addAll(dirs);
else { } else {
errors.add(SyntaxError( errors.add(SyntaxError(
'Missing selection set in fragment definition.', 'Missing selection set in fragment definition.',
NAME?.span ?? TYPE.span)); NAME?.span ?? TYPE.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
} }
}
FragmentDefinitionContext parseFragmentDefinition() { FragmentDefinitionContext parseFragmentDefinition() {
if (nextName('fragment')) { if (nextName('fragment')) {
@ -105,11 +105,11 @@ class Parser {
if (typeCondition != null) { if (typeCondition != null) {
var dirs = parseDirectives(); var dirs = parseDirectives();
var selectionSet = parseSelectionSet(); var selectionSet = parseSelectionSet();
if (selectionSet != null) if (selectionSet != null) {
return FragmentDefinitionContext( return FragmentDefinitionContext(
FRAGMENT, NAME, ON, typeCondition, selectionSet) FRAGMENT, NAME, ON, typeCondition, selectionSet)
..directives.addAll(dirs); ..directives.addAll(dirs);
else { } else {
errors.add(SyntaxError( errors.add(SyntaxError(
'Expected selection set in fragment definition.', 'Expected selection set in fragment definition.',
typeCondition.span)); typeCondition.span));
@ -133,9 +133,10 @@ class Parser {
FRAGMENT.span)); FRAGMENT.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
FragmentSpreadContext parseFragmentSpread() { FragmentSpreadContext parseFragmentSpread() {
if (next(TokenType.ELLIPSIS)) { if (next(TokenType.ELLIPSIS)) {
@ -148,9 +149,10 @@ class Parser {
_index--; _index--;
return null; return null;
} }
} else } else {
return null; return null;
} }
}
InlineFragmentContext parseInlineFragment() { InlineFragmentContext parseInlineFragment() {
if (next(TokenType.ELLIPSIS)) { if (next(TokenType.ELLIPSIS)) {
@ -184,9 +186,10 @@ class Parser {
'Missing "on" after "..." in inline fragment.', ELLIPSIS.span)); 'Missing "on" after "..." in inline fragment.', ELLIPSIS.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
SelectionSetContext parseSelectionSet() { SelectionSetContext parseSelectionSet() {
if (next(TokenType.LBRACE)) { if (next(TokenType.LBRACE)) {
@ -201,30 +204,31 @@ class Parser {
} }
eatCommas(); eatCommas();
if (next(TokenType.RBRACE)) if (next(TokenType.RBRACE)) {
return SelectionSetContext(LBRACE, current) return SelectionSetContext(LBRACE, current)
..selections.addAll(selections); ..selections.addAll(selections);
else { } else {
errors.add(SyntaxError('Missing "}" after selection set.', errors.add(SyntaxError('Missing "}" after selection set.',
selections.isEmpty ? LBRACE.span : selections.last.span)); selections.isEmpty ? LBRACE.span : selections.last.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
SelectionContext parseSelection() { SelectionContext parseSelection() {
var field = parseField(); var field = parseField();
if (field != null) return SelectionContext(field); if (field != null) return SelectionContext(field);
var fragmentSpread = parseFragmentSpread(); var fragmentSpread = parseFragmentSpread();
if (fragmentSpread != null) if (fragmentSpread != null) return SelectionContext(null, fragmentSpread);
return SelectionContext(null, fragmentSpread);
var inlineFragment = parseInlineFragment(); var inlineFragment = parseInlineFragment();
if (inlineFragment != null) if (inlineFragment != null) {
return SelectionContext(null, null, inlineFragment); return SelectionContext(null, null, inlineFragment);
else } else {
return null; return null;
} }
}
FieldContext parseField() { FieldContext parseField() {
var fieldName = parseFieldName(); var fieldName = parseFieldName();
@ -235,28 +239,30 @@ class Parser {
return FieldContext(fieldName, selectionSet) return FieldContext(fieldName, selectionSet)
..arguments.addAll(args ?? <ArgumentContext>[]) ..arguments.addAll(args ?? <ArgumentContext>[])
..directives.addAll(directives); ..directives.addAll(directives);
} else } else {
return null; return null;
} }
}
FieldNameContext parseFieldName() { FieldNameContext parseFieldName() {
if (next(TokenType.NAME)) { if (next(TokenType.NAME)) {
var NAME1 = current; var NAME1 = current;
if (next(TokenType.COLON)) { if (next(TokenType.COLON)) {
var COLON = current; var COLON = current;
if (next(TokenType.NAME)) if (next(TokenType.NAME)) {
return FieldNameContext( return FieldNameContext(null, AliasContext(NAME1, COLON, current));
null, AliasContext(NAME1, COLON, current)); } else {
else { errors.add(
errors.add(SyntaxError( SyntaxError('Missing name after colon in alias.', COLON.span));
'Missing name after colon in alias.', COLON.span));
return null; return null;
} }
} else } else {
return FieldNameContext(NAME1); return FieldNameContext(NAME1);
} else }
} else {
return null; return null;
} }
}
VariableDefinitionsContext parseVariableDefinitions() { VariableDefinitionsContext parseVariableDefinitions() {
if (next(TokenType.LPAREN)) { if (next(TokenType.LPAREN)) {
@ -270,17 +276,18 @@ class Parser {
def = parseVariableDefinition(); def = parseVariableDefinition();
} }
if (next(TokenType.RPAREN)) if (next(TokenType.RPAREN)) {
return VariableDefinitionsContext(LPAREN, current) return VariableDefinitionsContext(LPAREN, current)
..variableDefinitions.addAll(defs); ..variableDefinitions.addAll(defs);
else { } else {
errors.add(SyntaxError( errors.add(SyntaxError(
'Missing ")" after variable definitions.', LPAREN.span)); 'Missing ")" after variable definitions.', LPAREN.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
VariableDefinitionContext parseVariableDefinition() { VariableDefinitionContext parseVariableDefinition() {
var variable = parseVariable(); var variable = parseVariable();
@ -290,21 +297,21 @@ class Parser {
var type = parseType(); var type = parseType();
if (type != null) { if (type != null) {
var defaultValue = parseDefaultValue(); var defaultValue = parseDefaultValue();
return VariableDefinitionContext( return VariableDefinitionContext(variable, COLON, type, defaultValue);
variable, COLON, type, defaultValue);
} else { } else {
errors.add(SyntaxError( errors.add(
'Missing type in variable definition.', COLON.span)); SyntaxError('Missing type in variable definition.', COLON.span));
return null; return null;
} }
} else { } else {
errors.add(SyntaxError( errors.add(
'Missing ":" in variable definition.', variable.span)); SyntaxError('Missing ":" in variable definition.', variable.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
TypeContext parseType() { TypeContext parseType() {
var name = parseTypeName(); var name = parseTypeName();
@ -314,10 +321,11 @@ class Parser {
var listType = parseListType(); var listType = parseListType();
if (listType != null) { if (listType != null) {
return TypeContext(null, listType, maybe(TokenType.EXCLAMATION)); return TypeContext(null, listType, maybe(TokenType.EXCLAMATION));
} else } else {
return null; return null;
} }
} }
}
ListTypeContext parseListType() { ListTypeContext parseListType() {
if (next(TokenType.LBRACKET)) { if (next(TokenType.LBRACKET)) {
@ -334,9 +342,10 @@ class Parser {
errors.add(SyntaxError('Missing type after "[".', LBRACKET.span)); errors.add(SyntaxError('Missing type after "[".', LBRACKET.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
List<DirectiveContext> parseDirectives() { List<DirectiveContext> parseDirectives() {
List<DirectiveContext> out = []; List<DirectiveContext> out = [];
@ -358,10 +367,9 @@ class Parser {
if (next(TokenType.COLON)) { if (next(TokenType.COLON)) {
var COLON = current; var COLON = current;
var val = parseInputValue(); var val = parseInputValue();
if (val != null) if (val != null) {
return DirectiveContext( return DirectiveContext(ARROBA, NAME, COLON, null, null, null, val);
ARROBA, NAME, COLON, null, null, null, val); } else {
else {
errors.add(SyntaxError( errors.add(SyntaxError(
'Missing value or variable in directive after colon.', 'Missing value or variable in directive after colon.',
COLON.span)); COLON.span));
@ -383,16 +391,17 @@ class Parser {
SyntaxError('Missing argument in directive.', LPAREN.span)); SyntaxError('Missing argument in directive.', LPAREN.span));
return null; return null;
} }
} else } else {
return DirectiveContext( return DirectiveContext(ARROBA, NAME, null, null, null, null, null);
ARROBA, NAME, null, null, null, null, null); }
} else { } else {
errors.add(SyntaxError('Missing name for directive.', ARROBA.span)); errors.add(SyntaxError('Missing name for directive.', ARROBA.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
List<ArgumentContext> parseArguments() { List<ArgumentContext> parseArguments() {
if (next(TokenType.LPAREN)) { if (next(TokenType.LPAREN)) {
@ -406,16 +415,16 @@ class Parser {
arg = parseArgument(); arg = parseArgument();
} }
if (next(TokenType.RPAREN)) if (next(TokenType.RPAREN)) {
return out; return out;
else { } else {
errors errors.add(SyntaxError('Missing ")" in argument list.', LPAREN.span));
.add(SyntaxError('Missing ")" in argument list.', LPAREN.span));
return null; return null;
} }
} else } else {
return []; return [];
} }
}
ArgumentContext parseArgument() { ArgumentContext parseArgument() {
if (next(TokenType.NAME)) { if (next(TokenType.NAME)) {
@ -423,21 +432,22 @@ class Parser {
if (next(TokenType.COLON)) { if (next(TokenType.COLON)) {
var COLON = current; var COLON = current;
var val = parseInputValue(); var val = parseInputValue();
if (val != null) if (val != null) {
return ArgumentContext(NAME, COLON, val); return ArgumentContext(NAME, COLON, val);
else { } else {
errors.add(SyntaxError( errors.add(SyntaxError(
'Missing value or variable in argument.', COLON.span)); 'Missing value or variable in argument.', COLON.span));
return null; return null;
} }
} else { } else {
errors.add(SyntaxError( errors.add(
'Missing colon after name in argument.', NAME.span)); SyntaxError('Missing colon after name in argument.', NAME.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
/// Use [parseInputValue] instead. /// Use [parseInputValue] instead.
@deprecated @deprecated
@ -446,17 +456,18 @@ class Parser {
VariableContext parseVariable() { VariableContext parseVariable() {
if (next(TokenType.DOLLAR)) { if (next(TokenType.DOLLAR)) {
var DOLLAR = current; var DOLLAR = current;
if (next(TokenType.NAME)) if (next(TokenType.NAME)) {
return VariableContext(DOLLAR, current); return VariableContext(DOLLAR, current);
else { } else {
errors.add(SyntaxError( errors.add(SyntaxError(
'Missing name for variable; found a lone "\$" instead.', 'Missing name for variable; found a lone "\$" instead.',
DOLLAR.span)); DOLLAR.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
DefaultValueContext parseDefaultValue() { DefaultValueContext parseDefaultValue() {
if (next(TokenType.EQUALS)) { if (next(TokenType.EQUALS)) {
@ -465,28 +476,30 @@ class Parser {
if (value != null) { if (value != null) {
return DefaultValueContext(EQUALS, value); return DefaultValueContext(EQUALS, value);
} else { } else {
errors errors.add(SyntaxError('Missing value after "=" sign.', EQUALS.span));
.add(SyntaxError('Missing value after "=" sign.', EQUALS.span));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
TypeConditionContext parseTypeCondition() { TypeConditionContext parseTypeCondition() {
var name = parseTypeName(); var name = parseTypeName();
if (name != null) if (name != null) {
return TypeConditionContext(name); return TypeConditionContext(name);
else } else {
return null; return null;
} }
}
TypeNameContext parseTypeName() { TypeNameContext parseTypeName() {
if (next(TokenType.NAME)) { if (next(TokenType.NAME)) {
return TypeNameContext(current); return TypeNameContext(current);
} else } else {
return null; return null;
} }
}
/// Use [parseInputValue] instead. /// Use [parseInputValue] instead.
@deprecated @deprecated
@ -544,9 +557,10 @@ class Parser {
errors.add(SyntaxError('Unterminated list literal.', lastSpan)); errors.add(SyntaxError('Unterminated list literal.', lastSpan));
return null; return null;
} }
} else } else {
return null; return null;
} }
}
ObjectValueContext parseObjectValue() { ObjectValueContext parseObjectValue() {
if (next(TokenType.LBRACE)) { if (next(TokenType.LBRACE)) {

View file

@ -10,9 +10,10 @@ class Token {
@override @override
String toString() { String toString() {
if (span == null) if (span == null) {
return "'$text' -> $type"; return "'$text' -> $type";
else } else {
return "(${span.start.line}:${span.start.column}) '$text' -> $type"; return "(${span.start.line}:${span.start.column}) '$text' -> $type";
} }
} }
}

View file

@ -37,8 +37,7 @@ main() {
DirectiveContext parseDirective(String text) => parse(text).parseDirective(); DirectiveContext parseDirective(String text) => parse(text).parseDirective();
Matcher isDirective(String name, {Matcher valueOrVariable, Matcher argument}) => Matcher isDirective(String name, {Matcher valueOrVariable, Matcher argument}) =>
_IsDirective(name, _IsDirective(name, valueOrVariable: valueOrVariable, argument: argument);
valueOrVariable: valueOrVariable, argument: argument);
Matcher isDirectiveList(List<Matcher> directives) => Matcher isDirectiveList(List<Matcher> directives) =>
_IsDirectiveList(directives); _IsDirectiveList(directives);
@ -57,9 +56,10 @@ class _IsDirective extends Matcher {
return valueOrVariable.describe(desc.add(' and ')); return valueOrVariable.describe(desc.add(' and '));
} else if (argument != null) { } else if (argument != null) {
return argument.describe(desc.add(' and ')); return argument.describe(desc.add(' and '));
} else } else {
return desc; return desc;
} }
}
@override @override
bool matches(item, Map matchState) { bool matches(item, Map matchState) {
@ -67,9 +67,9 @@ class _IsDirective extends Matcher {
item is DirectiveContext ? item : parseDirective(item.toString()); item is DirectiveContext ? item : parseDirective(item.toString());
if (directive == null) return false; if (directive == null) return false;
if (valueOrVariable != null) { if (valueOrVariable != null) {
if (directive.value == null) if (directive.value == null) {
return false; return false;
else { } else {
var v = directive.value; var v = directive.value;
if (v is VariableContext) { if (v is VariableContext) {
return valueOrVariable.matches(v.name, matchState); return valueOrVariable.matches(v.name, matchState);
@ -79,14 +79,16 @@ class _IsDirective extends Matcher {
} }
} }
} else if (argument != null) { } else if (argument != null) {
if (directive.argument == null) if (directive.argument == null) {
return false; return false;
else } else {
return argument.matches(directive.argument, matchState); return argument.matches(directive.argument, matchState);
} else }
} else {
return true; return true;
} }
} }
}
class _IsDirectiveList extends Matcher { class _IsDirectiveList extends Matcher {
final List<Matcher> directives; final List<Matcher> directives;

View file

@ -88,8 +88,7 @@ Matcher isField(
Matcher selectionSet}) => Matcher selectionSet}) =>
_IsField(fieldName, arguments, directives, selectionSet); _IsField(fieldName, arguments, directives, selectionSet);
Matcher isFieldName(String name, {String alias}) => Matcher isFieldName(String name, {String alias}) => _IsFieldName(name, alias);
_IsFieldName(name, alias);
class _IsField extends Matcher { class _IsField extends Matcher {
final Matcher fieldName, arguments, directives, selectionSet; final Matcher fieldName, arguments, directives, selectionSet;
@ -106,10 +105,12 @@ class _IsField extends Matcher {
bool matches(item, Map matchState) { bool matches(item, Map matchState) {
var field = item is FieldContext ? item : parseField(item.toString()); var field = item is FieldContext ? item : parseField(item.toString());
if (field == null) return false; if (field == null) return false;
if (fieldName != null && !fieldName.matches(field.fieldName, matchState)) if (fieldName != null && !fieldName.matches(field.fieldName, matchState)) {
return false; return false;
if (arguments != null && !arguments.matches(field.arguments, matchState)) }
if (arguments != null && !arguments.matches(field.arguments, matchState)) {
return false; return false;
}
return true; return true;
} }
} }
@ -121,9 +122,10 @@ class _IsFieldName extends Matcher {
@override @override
Description describe(Description description) { Description describe(Description description) {
if (realName != null) if (realName != null) {
return description return description
.add('is field with name "$name" and alias "$realName"'); .add('is field with name "$name" and alias "$realName"');
}
return description.add('is field with name "$name"'); return description.add('is field with name "$name"');
} }
@ -131,10 +133,11 @@ class _IsFieldName extends Matcher {
bool matches(item, Map matchState) { bool matches(item, Map matchState) {
var fieldName = var fieldName =
item is FieldNameContext ? item : parseFieldName(item.toString()); item is FieldNameContext ? item : parseFieldName(item.toString());
if (realName != null) if (realName != null) {
return fieldName.alias?.alias == name && return fieldName.alias?.alias == name &&
fieldName.alias?.name == realName; fieldName.alias?.name == realName;
else } else {
return fieldName.name == name; return fieldName.name == name;
} }
} }
}

View file

@ -35,9 +35,10 @@ class _IsFragmentSpread extends Matcher {
@override @override
Description describe(Description description) { Description describe(Description description) {
if (directives != null) if (directives != null) {
return directives.describe( return directives.describe(
description.add('is a fragment spread named "$name" that also ')); description.add('is a fragment spread named "$name" that also '));
}
return description.add('is a fragment spread named "$name"'); return description.add('is a fragment spread named "$name"');
} }
@ -48,9 +49,10 @@ class _IsFragmentSpread extends Matcher {
: parseFragmentSpread(item.toString()); : parseFragmentSpread(item.toString());
if (spread == null) return false; if (spread == null) return false;
if (spread.name != name) return false; if (spread.name != name) return false;
if (directives != null) if (directives != null) {
return directives.matches(spread.directives, matchState); return directives.matches(spread.directives, matchState);
else } else {
return true; return true;
} }
} }
}

View file

@ -55,8 +55,7 @@ main() {
SelectionSetContext parseSelectionSet(String text) => SelectionSetContext parseSelectionSet(String text) =>
parse(text).parseSelectionSet(); parse(text).parseSelectionSet();
Matcher isSelectionSet(List<Matcher> selections) => Matcher isSelectionSet(List<Matcher> selections) => _IsSelectionSet(selections);
_IsSelectionSet(selections);
class _IsSelectionSet extends Matcher { class _IsSelectionSet extends Matcher {
final List<Matcher> selections; final List<Matcher> selections;
@ -87,9 +86,10 @@ class _IsSelectionSet extends Matcher {
for (int i = 0; i < set.selections.length; i++) { for (int i = 0; i < set.selections.length; i++) {
var sel = set.selections[i]; var sel = set.selections[i];
if (!selections[i].matches( if (!selections[i].matches(
sel.field ?? sel.fragmentSpread ?? sel.inlineFragment, matchState)) sel.field ?? sel.fragmentSpread ?? sel.inlineFragment, matchState)) {
return false; return false;
} }
}
return true; return true;
} }

View file

@ -84,11 +84,12 @@ class _IsType extends Matcher {
@override @override
Description describe(Description description) { Description describe(Description description) {
if (nonNull == true) if (nonNull == true) {
return description.add('is non-null type named "$name"'); return description.add('is non-null type named "$name"');
else } else {
return description.add('is nullable type named "$name"'); return description.add('is nullable type named "$name"');
} }
}
@override @override
bool matches(item, Map matchState) { bool matches(item, Map matchState) {