From 225a83078b84b987178f361bf6eb4d37b2d69039 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:38:53 -0400 Subject: [PATCH 01/69] Deprecate value in favor of constant; valueorvariable -> input value --- .../lib/src/language/ast/constant.dart | 11 +++++++++++ .../lib/src/language/ast/input_value.dart | 16 ++++++++++++++++ graphql_parser/lib/src/language/ast/value.dart | 5 ----- .../lib/src/language/ast/value_or_variable.dart | 16 ---------------- 4 files changed, 27 insertions(+), 21 deletions(-) create mode 100644 graphql_parser/lib/src/language/ast/constant.dart create mode 100644 graphql_parser/lib/src/language/ast/input_value.dart delete mode 100644 graphql_parser/lib/src/language/ast/value.dart delete mode 100644 graphql_parser/lib/src/language/ast/value_or_variable.dart diff --git a/graphql_parser/lib/src/language/ast/constant.dart b/graphql_parser/lib/src/language/ast/constant.dart new file mode 100644 index 00000000..3338a83d --- /dev/null +++ b/graphql_parser/lib/src/language/ast/constant.dart @@ -0,0 +1,11 @@ +import 'node.dart'; + +abstract class ConstantContext extends Node { + T get value; +} + +/// Use [ConstantContext] instead. This class remains solely for backwards compatibility. +@deprecated +abstract class ValueContext extends ConstantContext { + T get value; +} diff --git a/graphql_parser/lib/src/language/ast/input_value.dart b/graphql_parser/lib/src/language/ast/input_value.dart new file mode 100644 index 00000000..238fbec0 --- /dev/null +++ b/graphql_parser/lib/src/language/ast/input_value.dart @@ -0,0 +1,16 @@ +import 'package:source_span/source_span.dart'; +import 'constant.dart'; +import 'node.dart'; +import 'variable.dart'; + +class InputValueContext extends Node { + final ConstantContext constant; + final VariableContext variable; + + InputValueContext(this.constant, this.variable) { + assert(constant != null || variable != null); + } + + @override + FileSpan get span => constant?.span ?? variable.span; +} diff --git a/graphql_parser/lib/src/language/ast/value.dart b/graphql_parser/lib/src/language/ast/value.dart deleted file mode 100644 index edc4e368..00000000 --- a/graphql_parser/lib/src/language/ast/value.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'node.dart'; - -abstract class ValueContext extends Node { - T get value; -} diff --git a/graphql_parser/lib/src/language/ast/value_or_variable.dart b/graphql_parser/lib/src/language/ast/value_or_variable.dart deleted file mode 100644 index 7b28b1e4..00000000 --- a/graphql_parser/lib/src/language/ast/value_or_variable.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'node.dart'; -import 'package:source_span/source_span.dart'; -import 'value.dart'; -import 'variable.dart'; - -class ValueOrVariableContext extends Node { - final ValueContext value; - final VariableContext variable; - - ValueOrVariableContext(this.value, this.variable) { - assert(value != null || variable != null); - } - - @override - FileSpan get span => value?.span ?? variable.span; -} From deb6673654b054f23c1093e118b1b0f2f677256d Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:41:46 -0400 Subject: [PATCH 02/69] Add computeValue --- graphql_parser/lib/src/language/ast/argument.dart | 13 ++++++++----- graphql_parser/lib/src/language/ast/constant.dart | 1 + .../lib/src/language/ast/input_value.dart | 3 +++ graphql_parser/lib/src/language/ast/variable.dart | 2 ++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/argument.dart b/graphql_parser/lib/src/language/ast/argument.dart index 3a85a067..6639874a 100644 --- a/graphql_parser/lib/src/language/ast/argument.dart +++ b/graphql_parser/lib/src/language/ast/argument.dart @@ -1,17 +1,20 @@ import 'package:source_span/source_span.dart'; import '../token.dart'; import 'node.dart'; -import 'value_or_variable.dart'; +import 'input_value.dart'; class ArgumentContext extends Node { final Token NAME, COLON; - final ValueOrVariableContext valueOrVariable; + final InputValueContext value; - ArgumentContext(this.NAME, this.COLON, this.valueOrVariable); + ArgumentContext(this.NAME, this.COLON, this.value); + + /// Use [value] instead. + @deprecated + InputValueContext get valueOrVariable => value; String get name => NAME.text; @override - FileSpan get span => - NAME.span.expand(COLON.span).expand(valueOrVariable.span); + FileSpan get span => NAME.span.expand(COLON.span).expand(value.span); } diff --git a/graphql_parser/lib/src/language/ast/constant.dart b/graphql_parser/lib/src/language/ast/constant.dart index 3338a83d..fff707cf 100644 --- a/graphql_parser/lib/src/language/ast/constant.dart +++ b/graphql_parser/lib/src/language/ast/constant.dart @@ -2,6 +2,7 @@ import 'node.dart'; abstract class ConstantContext extends Node { T get value; + T computeValue(Map variables) => value; } /// Use [ConstantContext] instead. This class remains solely for backwards compatibility. diff --git a/graphql_parser/lib/src/language/ast/input_value.dart b/graphql_parser/lib/src/language/ast/input_value.dart index 238fbec0..103c07f4 100644 --- a/graphql_parser/lib/src/language/ast/input_value.dart +++ b/graphql_parser/lib/src/language/ast/input_value.dart @@ -13,4 +13,7 @@ class InputValueContext extends Node { @override FileSpan get span => constant?.span ?? variable.span; + + Object computeValue(Map variables) => + constant?.computeValue(variables) ?? variable?.computeValue(variables); } diff --git a/graphql_parser/lib/src/language/ast/variable.dart b/graphql_parser/lib/src/language/ast/variable.dart index 71e7ab56..b1c356b4 100644 --- a/graphql_parser/lib/src/language/ast/variable.dart +++ b/graphql_parser/lib/src/language/ast/variable.dart @@ -11,5 +11,7 @@ class VariableContext extends Node { @override FileSpan get span => DOLLAR.span.expand(NAME.span); + + Object computeValue(Map variables) => variables[name]; // new FileSpan(DOLLAR?.span?.start, NAME?.span?.end, toSource()); } From ae50e0dae70870bd26c038c9a746ecdf040796b5 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:43:24 -0400 Subject: [PATCH 03/69] Remove input value context --- graphql_parser/example/example.dart | 2 +- .../lib/src/language/ast/array_value.dart | 3 ++- .../lib/src/language/ast/input_value.dart | 18 ++---------------- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/graphql_parser/example/example.dart b/graphql_parser/example/example.dart index 34566298..5a3f1be4 100644 --- a/graphql_parser/example/example.dart +++ b/graphql_parser/example/example.dart @@ -19,7 +19,7 @@ main() { var projectField = operation.selectionSet.selections.first.field; print(projectField.fieldName.name); // project print(projectField.arguments.first.name); // name - print(projectField.arguments.first.valueOrVariable.value.value); // GraphQL + print(projectField.arguments.first.value); // GraphQL var taglineField = projectField.selectionSet.selections.first.field; print(taglineField.fieldName.name); // tagline diff --git a/graphql_parser/lib/src/language/ast/array_value.dart b/graphql_parser/lib/src/language/ast/array_value.dart index 63633b5a..ff6ed44b 100644 --- a/graphql_parser/lib/src/language/ast/array_value.dart +++ b/graphql_parser/lib/src/language/ast/array_value.dart @@ -1,6 +1,7 @@ import 'package:source_span/source_span.dart'; import '../token.dart'; -import 'value.dart'; +import 'constant.dart'; +import 'input_value.dart'; class ListValueContext extends ValueContext { final Token LBRACKET, RBRACKET; diff --git a/graphql_parser/lib/src/language/ast/input_value.dart b/graphql_parser/lib/src/language/ast/input_value.dart index 103c07f4..29e703ca 100644 --- a/graphql_parser/lib/src/language/ast/input_value.dart +++ b/graphql_parser/lib/src/language/ast/input_value.dart @@ -1,19 +1,5 @@ -import 'package:source_span/source_span.dart'; -import 'constant.dart'; import 'node.dart'; -import 'variable.dart'; -class InputValueContext extends Node { - final ConstantContext constant; - final VariableContext variable; - - InputValueContext(this.constant, this.variable) { - assert(constant != null || variable != null); - } - - @override - FileSpan get span => constant?.span ?? variable.span; - - Object computeValue(Map variables) => - constant?.computeValue(variables) ?? variable?.computeValue(variables); +abstract class InputValueContext extends Node { + T computeValue(Map variables); } From 87ab0b4230a07da24a9c9eaa9c8421c477aea8ac Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:44:25 -0400 Subject: [PATCH 04/69] Fix ValueContext --- graphql_parser/lib/src/language/ast/array_value.dart | 9 +++++---- graphql_parser/lib/src/language/ast/constant.dart | 10 +++------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/array_value.dart b/graphql_parser/lib/src/language/ast/array_value.dart index ff6ed44b..1408a5bd 100644 --- a/graphql_parser/lib/src/language/ast/array_value.dart +++ b/graphql_parser/lib/src/language/ast/array_value.dart @@ -1,11 +1,10 @@ import 'package:source_span/source_span.dart'; import '../token.dart'; -import 'constant.dart'; import 'input_value.dart'; -class ListValueContext extends ValueContext { +class ListValueContext extends InputValueContext { final Token LBRACKET, RBRACKET; - final List values = []; + final List values = []; ListValueContext(this.LBRACKET, this.RBRACKET); @@ -16,5 +15,7 @@ class ListValueContext extends ValueContext { } @override - List get value => values.map((v) => v.value).toList(); + computeValue(Map variables) { + return values.map((v) => v.computeValue(variables)).toList(); + } } diff --git a/graphql_parser/lib/src/language/ast/constant.dart b/graphql_parser/lib/src/language/ast/constant.dart index fff707cf..2f71709c 100644 --- a/graphql_parser/lib/src/language/ast/constant.dart +++ b/graphql_parser/lib/src/language/ast/constant.dart @@ -1,12 +1,8 @@ -import 'node.dart'; - -abstract class ConstantContext extends Node { - T get value; - T computeValue(Map variables) => value; -} +import 'input_value.dart'; /// Use [ConstantContext] instead. This class remains solely for backwards compatibility. @deprecated -abstract class ValueContext extends ConstantContext { +abstract class ValueContext extends InputValueContext { T get value; + T computeValue(Map variables) => value; } From 31fd0ba7b2605d6ad61680dc62ad5d689dafed7d Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:44:41 -0400 Subject: [PATCH 05/69] export input_value --- graphql_parser/lib/src/language/ast/ast.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/ast.dart b/graphql_parser/lib/src/language/ast/ast.dart index 3fff886d..253a430b 100644 --- a/graphql_parser/lib/src/language/ast/ast.dart +++ b/graphql_parser/lib/src/language/ast/ast.dart @@ -13,6 +13,7 @@ export 'field_name.dart'; export 'fragment_definition.dart'; export 'fragment_spread.dart'; export 'inline_fragment.dart'; +export 'input_value.dart'; export 'list_type.dart'; export 'misc_value.dart'; export 'node.dart'; @@ -24,8 +25,6 @@ export 'string_value.dart'; export 'type.dart'; export 'type_condition.dart'; export 'type_name.dart'; -export 'value.dart'; -export 'value_or_variable.dart'; export 'variable.dart'; export 'variable_definition.dart'; export 'variable_definitions.dart'; From cd55bef9f673f7ce081e310f3fac056082475842 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:45:24 -0400 Subject: [PATCH 06/69] Update boolean value --- graphql_parser/lib/src/language/ast/boolean_value.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/boolean_value.dart b/graphql_parser/lib/src/language/ast/boolean_value.dart index 528abfd4..62b78046 100644 --- a/graphql_parser/lib/src/language/ast/boolean_value.dart +++ b/graphql_parser/lib/src/language/ast/boolean_value.dart @@ -1,8 +1,8 @@ -import '../token.dart'; import 'package:source_span/source_span.dart'; -import 'value.dart'; +import 'input_value.dart'; +import '../token.dart'; -class BooleanValueContext extends ValueContext { +class BooleanValueContext extends InputValueContext { bool _valueCache; final Token BOOLEAN; @@ -13,8 +13,8 @@ class BooleanValueContext extends ValueContext { bool get booleanValue => _valueCache ??= BOOLEAN.text == 'true'; @override - bool get value => booleanValue; + FileSpan get span => BOOLEAN.span; @override - FileSpan get span => BOOLEAN.span; + bool computeValue(Map variables) => booleanValue; } From 3383e522b664dc93efabdb3fe5e0422c9ecac065 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:45:44 -0400 Subject: [PATCH 07/69] Update default value --- graphql_parser/lib/src/language/ast/default_value.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/default_value.dart b/graphql_parser/lib/src/language/ast/default_value.dart index 3395a688..de41a580 100644 --- a/graphql_parser/lib/src/language/ast/default_value.dart +++ b/graphql_parser/lib/src/language/ast/default_value.dart @@ -1,11 +1,11 @@ -import '../token.dart'; -import 'node.dart'; import 'package:source_span/source_span.dart'; -import 'value.dart'; +import '../token.dart'; +import 'input_value.dart'; +import 'node.dart'; class DefaultValueContext extends Node { final Token EQUALS; - final ValueContext value; + final InputValueContext value; DefaultValueContext(this.EQUALS, this.value); From b26732d8048960a77fb2faf600bad18e18ea8ca1 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:46:38 -0400 Subject: [PATCH 08/69] Update DirectiveContext --- graphql_parser/lib/src/language/ast/directive.dart | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/directive.dart b/graphql_parser/lib/src/language/ast/directive.dart index a9f172a0..d0899f57 100644 --- a/graphql_parser/lib/src/language/ast/directive.dart +++ b/graphql_parser/lib/src/language/ast/directive.dart @@ -1,25 +1,29 @@ +import 'package:source_span/source_span.dart'; import '../token.dart'; import 'argument.dart'; +import 'input_value.dart'; import 'node.dart'; -import 'package:source_span/source_span.dart'; -import 'value_or_variable.dart'; class DirectiveContext extends Node { final Token ARROBA, NAME, COLON, LPAREN, RPAREN; final ArgumentContext argument; - final ValueOrVariableContext valueOrVariable; + final InputValueContext value; DirectiveContext(this.ARROBA, this.NAME, this.COLON, this.LPAREN, this.RPAREN, - this.argument, this.valueOrVariable) { + this.argument, this.value) { assert(NAME != null); } + /// Use [value] instead. + @deprecated + InputValueContext get valueOrVariable => value; + @override FileSpan get span { var out = ARROBA.span.expand(NAME.span); if (COLON != null) { - out = out.expand(COLON.span).expand(valueOrVariable.span); + out = out.expand(COLON.span).expand(value.span); } else if (LPAREN != null) { out = out.expand(LPAREN.span).expand(argument.span).expand(RPAREN.span); } From bf2ef30ade9b1f84f4de05ae1dfd978875c42392 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:48:12 -0400 Subject: [PATCH 09/69] Update misc_values --- .../lib/src/language/ast/misc_value.dart | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/misc_value.dart b/graphql_parser/lib/src/language/ast/misc_value.dart index d7f3a2ce..0aa1facb 100644 --- a/graphql_parser/lib/src/language/ast/misc_value.dart +++ b/graphql_parser/lib/src/language/ast/misc_value.dart @@ -1,10 +1,9 @@ import 'package:source_span/source_span.dart'; - import '../token.dart'; +import 'input_value.dart'; import 'node.dart'; -import 'value.dart'; -class NullValueContext extends ValueContext { +class NullValueContext extends InputValueContext { final Token NULL; NullValueContext(this.NULL); @@ -13,10 +12,10 @@ class NullValueContext extends ValueContext { FileSpan get span => NULL.span; @override - Null get value => null; + Null computeValue(Map variables) => null; } -class EnumValueContext extends ValueContext { +class EnumValueContext extends InputValueContext { final Token NAME; EnumValueContext(this.NAME); @@ -25,10 +24,10 @@ class EnumValueContext extends ValueContext { FileSpan get span => NAME.span; @override - String get value => NAME.span.text; + String computeValue(Map variables) => NAME.span.text; } -class ObjectValueContext extends ValueContext> { +class ObjectValueContext extends InputValueContext> { final Token LBRACE; final List fields; final Token RBRACE; @@ -47,13 +46,13 @@ class ObjectValueContext extends ValueContext> { } @override - Map get value { + Map computeValue(Map variables) { if (fields.isEmpty) { return {}; } else { return fields.fold>({}, (map, field) { - return map..[field.NAME.text] = field.value.value; + return map..[field.NAME.text] = field.value.computeValue(variables); }); } } @@ -62,7 +61,7 @@ class ObjectValueContext extends ValueContext> { class ObjectFieldContext extends Node { final Token NAME; final Token COLON; - final ValueContext value; + final InputValueContext value; ObjectFieldContext(this.NAME, this.COLON, this.value); From 5e43d414ae5f5c105ebe7fc41c12751494fa82b0 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:48:41 -0400 Subject: [PATCH 10/69] Update number_value --- graphql_parser/lib/src/language/ast/number_value.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/number_value.dart b/graphql_parser/lib/src/language/ast/number_value.dart index 8d5bb90c..8c18cfe1 100644 --- a/graphql_parser/lib/src/language/ast/number_value.dart +++ b/graphql_parser/lib/src/language/ast/number_value.dart @@ -1,9 +1,9 @@ import 'dart:math' as math; import 'package:source_span/source_span.dart'; import '../token.dart'; -import 'value.dart'; +import 'input_value.dart'; -class NumberValueContext extends ValueContext { +class NumberValueContext extends InputValueContext { final Token NUMBER; NumberValueContext(this.NUMBER); @@ -21,8 +21,8 @@ class NumberValueContext extends ValueContext { } @override - num get value => numberValue; + FileSpan get span => NUMBER.span; @override - FileSpan get span => NUMBER.span; + num computeValue(Map variables) => numberValue; } From b0c9ad79943651cef62ac5d5d753d2fe62da8e2a Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:49:18 -0400 Subject: [PATCH 11/69] Update string_value --- graphql_parser/lib/src/language/ast/string_value.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/string_value.dart b/graphql_parser/lib/src/language/ast/string_value.dart index e5eef5cc..1fa664fb 100644 --- a/graphql_parser/lib/src/language/ast/string_value.dart +++ b/graphql_parser/lib/src/language/ast/string_value.dart @@ -3,9 +3,9 @@ import 'package:source_span/source_span.dart'; import '../syntax_error.dart'; import '../token.dart'; -import 'value.dart'; +import 'input_value.dart'; -class StringValueContext extends ValueContext { +class StringValueContext extends InputValueContext { final Token STRING; final bool isBlockString; @@ -74,5 +74,5 @@ class StringValueContext extends ValueContext { } @override - get value => stringValue; + String computeValue(Map variables) => stringValue; } From 1988b401a073e7fabee87494064bd29f33098612 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:53:11 -0400 Subject: [PATCH 12/69] Update parser --- graphql_parser/lib/src/language/parser.dart | 29 +++++++++------------ graphql_parser/test/argument_test.dart | 7 +++-- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/graphql_parser/lib/src/language/parser.dart b/graphql_parser/lib/src/language/parser.dart index 810bf8ab..3ec93031 100644 --- a/graphql_parser/lib/src/language/parser.dart +++ b/graphql_parser/lib/src/language/parser.dart @@ -440,18 +440,9 @@ class Parser { return null; } - ValueOrVariableContext parseValueOrVariable() { - var value = parseValue(); - if (value != null) - return new ValueOrVariableContext(value, null); - else { - var variable = parseVariable(); - if (variable != null) - return new ValueOrVariableContext(null, variable); - else - return null; - } - } + /// Use [parseInputValue] instead. + @deprecated + InputValueContext parseValueOrVariable() => parseInputValue(); VariableContext parseVariable() { if (next(TokenType.DOLLAR)) { @@ -498,14 +489,18 @@ class Parser { return null; } - ValueContext parseValue() { + /// Use [parseInputValue] instead. + @deprecated + InputValueContext parseValue() => parseInputValue(); + + InputValueContext parseInputValue() { return (parseNumberValue() ?? parseStringValue() ?? parseBooleanValue() ?? parseNullValue() ?? parseEnumValue() ?? parseListValue() ?? - parseObjectValue()) as ValueContext; + parseObjectValue()) as InputValueContext; } StringValueContext parseStringValue() => next(TokenType.STRING) @@ -532,14 +527,14 @@ class Parser { if (next(TokenType.LBRACKET)) { var LBRACKET = current; var lastSpan = LBRACKET.span; - List values = []; - ValueContext value = parseValue(); + List values = []; + var value = parseInputValue(); while (value != null) { lastSpan = value.span; values.add(value); eatCommas(); - value = parseValue(); + value = parseInputValue(); } eatCommas(); diff --git a/graphql_parser/test/argument_test.dart b/graphql_parser/test/argument_test.dart index ba473144..69077681 100644 --- a/graphql_parser/test/argument_test.dart +++ b/graphql_parser/test/argument_test.dart @@ -54,10 +54,9 @@ class _IsArgument extends Matcher { if (arg == null) return false; print(arg.span.highlight()); return equals(name).matches(arg.name, matchState) && - equals(value).matches( - arg.valueOrVariable.value?.value ?? - arg.valueOrVariable.variable?.name, - matchState); + ((arg is VariableContext && + equals(value).matches(arg.name, matchState)) || + equals(value).matches(arg.value.computeValue({}), matchState)); } } From ca212150161bd0dacd697d942893e09e98ea7e9b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:53:45 -0400 Subject: [PATCH 13/69] VariableContext extends input value --- graphql_parser/lib/src/language/ast/variable.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/variable.dart b/graphql_parser/lib/src/language/ast/variable.dart index b1c356b4..e8fb4bdb 100644 --- a/graphql_parser/lib/src/language/ast/variable.dart +++ b/graphql_parser/lib/src/language/ast/variable.dart @@ -1,8 +1,8 @@ -import '../token.dart'; -import 'node.dart'; import 'package:source_span/source_span.dart'; +import '../token.dart'; +import 'input_value.dart'; -class VariableContext extends Node { +class VariableContext extends InputValueContext { final Token DOLLAR, NAME; VariableContext(this.DOLLAR, this.NAME); @@ -12,6 +12,7 @@ class VariableContext extends Node { @override FileSpan get span => DOLLAR.span.expand(NAME.span); + @override Object computeValue(Map variables) => variables[name]; // new FileSpan(DOLLAR?.span?.start, NAME?.span?.end, toSource()); } From 8a9e0a278bd082f85729b5fc7e5838324ab8248c Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:54:12 -0400 Subject: [PATCH 14/69] Parse variable as input value --- graphql_parser/lib/src/language/parser.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graphql_parser/lib/src/language/parser.dart b/graphql_parser/lib/src/language/parser.dart index 3ec93031..100ab614 100644 --- a/graphql_parser/lib/src/language/parser.dart +++ b/graphql_parser/lib/src/language/parser.dart @@ -494,7 +494,8 @@ class Parser { InputValueContext parseValue() => parseInputValue(); InputValueContext parseInputValue() { - return (parseNumberValue() ?? + return (parseVariable() ?? + parseNumberValue() ?? parseStringValue() ?? parseBooleanValue() ?? parseNullValue() ?? From 7190d0c28d78e9dea4637be666a2e8b60317453f Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:55:20 -0400 Subject: [PATCH 15/69] Fix directive test --- graphql_parser/test/directive_test.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/graphql_parser/test/directive_test.dart b/graphql_parser/test/directive_test.dart index 454c89aa..ff500c09 100644 --- a/graphql_parser/test/directive_test.dart +++ b/graphql_parser/test/directive_test.dart @@ -67,13 +67,17 @@ class _IsDirective extends Matcher { item is DirectiveContext ? item : parseDirective(item.toString()); if (directive == null) return false; if (valueOrVariable != null) { - if (directive.valueOrVariable == null) + if (directive.value == null) return false; - else - return valueOrVariable.matches( - directive.valueOrVariable.value?.value ?? - directive.valueOrVariable.variable?.name, - matchState); + else { + var v = directive.value; + if (v is VariableContext) { + return valueOrVariable.matches(v.name, matchState); + } else { + return valueOrVariable.matches( + directive.value.computeValue({}), matchState); + } + } } else if (argument != null) { if (directive.argument == null) return false; From 112c0873bb4d9b5e27bfd48dae5941fb38e9ee89 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:56:15 -0400 Subject: [PATCH 16/69] Export deprecated value --- graphql_parser/lib/src/language/ast/ast.dart | 1 + .../src/language/ast/{constant.dart => deprecated_value.dart} | 0 2 files changed, 1 insertion(+) rename graphql_parser/lib/src/language/ast/{constant.dart => deprecated_value.dart} (100%) diff --git a/graphql_parser/lib/src/language/ast/ast.dart b/graphql_parser/lib/src/language/ast/ast.dart index 253a430b..a274ade4 100644 --- a/graphql_parser/lib/src/language/ast/ast.dart +++ b/graphql_parser/lib/src/language/ast/ast.dart @@ -6,6 +6,7 @@ export 'argument.dart'; export 'boolean_value.dart'; export 'default_value.dart'; export 'definition.dart'; +export 'deprecated_value.dart'; export 'directive.dart'; export 'document.dart'; export 'field.dart'; diff --git a/graphql_parser/lib/src/language/ast/constant.dart b/graphql_parser/lib/src/language/ast/deprecated_value.dart similarity index 100% rename from graphql_parser/lib/src/language/ast/constant.dart rename to graphql_parser/lib/src/language/ast/deprecated_value.dart From 19f62c9a984974caa744ae9c77abc8c91f01eba5 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:56:48 -0400 Subject: [PATCH 17/69] Statically fix all tests --- graphql_parser/test/value_test.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graphql_parser/test/value_test.dart b/graphql_parser/test/value_test.dart index 61e90f48..0d0a42f0 100644 --- a/graphql_parser/test/value_test.dart +++ b/graphql_parser/test/value_test.dart @@ -72,7 +72,7 @@ main() { }); } -ValueContext parseValue(String text) => parse(text).parseValue(); +InputValueContext parseValue(String text) => parse(text).parseInputValue(); Matcher isValue(value) => new _IsValue(value); @@ -87,7 +87,7 @@ class _IsValue extends Matcher { @override bool matches(item, Map matchState) { - var v = item is ValueContext ? item : parseValue(item.toString()); - return equals(value).matches(v.value, matchState); + var v = item is InputValueContext ? item : parseValue(item.toString()); + return equals(value).matches(v.computeValue({}), matchState); } } From dc0dbd62122c1125dae977c59fcf4d798c155b39 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:57:36 -0400 Subject: [PATCH 18/69] Fix warnings in parser --- graphql_parser/lib/src/language/parser.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/parser.dart b/graphql_parser/lib/src/language/parser.dart index 100ab614..dc49bb51 100644 --- a/graphql_parser/lib/src/language/parser.dart +++ b/graphql_parser/lib/src/language/parser.dart @@ -357,7 +357,7 @@ class Parser { if (next(TokenType.COLON)) { var COLON = current; - var val = parseValueOrVariable(); + var val = parseInputValue(); if (val != null) return new DirectiveContext( ARROBA, NAME, COLON, null, null, null, val); @@ -376,7 +376,7 @@ class Parser { ARROBA, NAME, null, LPAREN, current, arg, null); } else { errors.add( - new SyntaxError('Missing \')\'', arg.valueOrVariable.span)); + new SyntaxError('Missing \')\'', arg.value.span)); return null; } } else { @@ -423,7 +423,7 @@ class Parser { var NAME = current; if (next(TokenType.COLON)) { var COLON = current; - var val = parseValueOrVariable(); + var val = parseInputValue(); if (val != null) return new ArgumentContext(NAME, COLON, val); else { @@ -462,7 +462,7 @@ class Parser { DefaultValueContext parseDefaultValue() { if (next(TokenType.EQUALS)) { var EQUALS = current; - var value = parseValue(); + var value = parseInputValue(); if (value != null) { return new DefaultValueContext(EQUALS, value); } else { @@ -582,7 +582,7 @@ class Parser { if (next(TokenType.COLON)) { var COLON = current; - var value = parseValue(); + var value = parseInputValue(); if (value != null) { return new ObjectFieldContext(NAME, COLON, value); From ad0d6dded7f626bf087661f90dddb5b93e1cdcc1 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:57:45 -0400 Subject: [PATCH 19/69] Fix warning in value test --- graphql_parser/test/value_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql_parser/test/value_test.dart b/graphql_parser/test/value_test.dart index 0d0a42f0..5e07a23a 100644 --- a/graphql_parser/test/value_test.dart +++ b/graphql_parser/test/value_test.dart @@ -64,7 +64,7 @@ main() { test('exceptions', () { var throwsSyntaxError = predicate((x) { - var parser = parse(x.toString())..parseValue(); + var parser = parse(x.toString())..parseInputValue(); return parser.errors.isNotEmpty; }, 'fails to parse value'); From 71adb0bbe7e41c762892fe5497dc0044622f46f7 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 21:57:51 -0400 Subject: [PATCH 20/69] Formatting --- graphql_parser/lib/src/language/parser.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/graphql_parser/lib/src/language/parser.dart b/graphql_parser/lib/src/language/parser.dart index dc49bb51..fff390f5 100644 --- a/graphql_parser/lib/src/language/parser.dart +++ b/graphql_parser/lib/src/language/parser.dart @@ -375,8 +375,7 @@ class Parser { return new DirectiveContext( ARROBA, NAME, null, LPAREN, current, arg, null); } else { - errors.add( - new SyntaxError('Missing \')\'', arg.value.span)); + errors.add(new SyntaxError('Missing \')\'', arg.value.span)); return null; } } else { From 73db8d519b10f9c0758e2c6e561118705a8408a2 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:03:01 -0400 Subject: [PATCH 21/69] Fix arg test --- graphql_parser/test/argument_test.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/graphql_parser/test/argument_test.dart b/graphql_parser/test/argument_test.dart index 69077681..e5f8b764 100644 --- a/graphql_parser/test/argument_test.dart +++ b/graphql_parser/test/argument_test.dart @@ -53,9 +53,10 @@ class _IsArgument extends Matcher { var arg = item is ArgumentContext ? item : parseArgument(item.toString()); if (arg == null) return false; print(arg.span.highlight()); + + var v = arg.value; return equals(name).matches(arg.name, matchState) && - ((arg is VariableContext && - equals(value).matches(arg.name, matchState)) || + ((v is VariableContext && equals(value).matches(v.name, matchState)) || equals(value).matches(arg.value.computeValue({}), matchState)); } } From 0f8db7542084940b37c744bfe16445a5bf3ef7bc Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:05:09 -0400 Subject: [PATCH 22/69] 1.2.0 CHANGELOG --- graphql_parser/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/graphql_parser/CHANGELOG.md b/graphql_parser/CHANGELOG.md index 1d4243fa..a56f0295 100644 --- a/graphql_parser/CHANGELOG.md +++ b/graphql_parser/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.2.0 +* Combine `ValueContext` and `VariableContext` into a single `InputValueContext` supertype. + * Add `T computeValue(Map variables);` + * Resolve [#23](https://github.com/angel-dart/graphql/issues/23). +* Deprecate old `ValueOrVariable` class, and parser/AST methods related to it. + # 1.1.3 * Add `Parser.nextName`, and remove all formerly-reserved words from the lexer. Resolves [#19](https://github.com/angel-dart/graphql/issues/19). From 84037855fa6f3de16b06a81dd8e250e5388baeda Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:19:10 -0400 Subject: [PATCH 23/69] Issue 23 test --- graphql_parser/test/issue23_test.dart | 94 +++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 graphql_parser/test/issue23_test.dart diff --git a/graphql_parser/test/issue23_test.dart b/graphql_parser/test/issue23_test.dart new file mode 100644 index 00000000..2648fd30 --- /dev/null +++ b/graphql_parser/test/issue23_test.dart @@ -0,0 +1,94 @@ +import 'package:graphql_parser/graphql_parser.dart'; +import 'package:test/test.dart'; + +/// This is an *extremely* verbose test, but basically it +/// parses both documents, and makes sure that $memberId has +/// a valid value. +/// +/// Resolves https://github.com/angel-dart/graphql/issues/23. +void main() { + void testStr(String name, String text) { + test('name', () { + final List tokens = scan(text); + final Parser parser = Parser(tokens); + + if (parser.errors.isNotEmpty) { + print(parser.errors.toString()); + } + expect(parser.errors, isEmpty); + + // Parse the GraphQL document using recursive descent + final DocumentContext doc = parser.parseDocument(); + + expect(doc.definitions, isNotNull); + expect(doc.definitions, isNotEmpty); + + // Sanity check + var queryDef = doc.definitions[0] as OperationDefinitionContext; + expect(queryDef.isQuery, true); + expect(queryDef.name, 'customerMemberAttributes'); + expect(queryDef.variableDefinitions.variableDefinitions, hasLength(1)); + var memberIdDef = queryDef.variableDefinitions.variableDefinitions[0]; + expect(memberIdDef.variable.name, 'memberId'); + + // Find $memberId + var customerByCustomerId = queryDef.selectionSet.selections[0]; + var customerMemberAttributesByCustomerId = + customerByCustomerId.field.selectionSet.selections[0]; + var nodes0 = + customerMemberAttributesByCustomerId.field.selectionSet.selections[0]; + var customerMemberAttributeId = nodes0.field.selectionSet.selections[0]; + expect(customerMemberAttributeId.field.fieldName.name, + 'customerMemberAttributeId'); + var memberAttr = nodes0.field.selectionSet.selections[1]; + expect(memberAttr.field.fieldName.name, + 'memberAttributesByCustomerMemberAttributeId'); + expect(memberAttr.field.arguments, hasLength(1)); + var condition = memberAttr.field.arguments[0]; + expect(condition.name, 'condition'); + expect(condition.value, TypeMatcher()); + var conditionValue = condition.value as ObjectValueContext; + var memberId = + conditionValue.fields.singleWhere((f) => f.NAME.text == 'memberId'); + expect(memberId.value, TypeMatcher()); + print('Found \$memberId: Instance of $T'); + }); + } + + testStr('member id as var', memberIdAsVar); + testStr('member id as constant', memberIdAsConstant); +} + +final String memberIdAsVar = r''' +query customerMemberAttributes($memberId: Int!){ + customerByCustomerId(customerId: 7) { + customerMemberAttributesByCustomerId { + nodes { + customerMemberAttributeId + memberAttributesByCustomerMemberAttributeId(condition: {memberId: $memberId}) { + nodes { + memberAttributeId + } + } + } + } + } +} +'''; + +final String memberIdAsConstant = r''' +query customerMemberAttributes($memberId: Int!){ + customerByCustomerId(customerId: 7) { + customerMemberAttributesByCustomerId { + nodes { + customerMemberAttributeId + memberAttributesByCustomerMemberAttributeId(condition: {memberId: 7}) { + nodes { + memberAttributeId + } + } + } + } + } +} +'''; From 6455dde6b6a79f86fbff2d84ac58ed3ff78ee083 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:24:02 -0400 Subject: [PATCH 24/69] pedantic: ast/alias.dart --- graphql_parser/analysis_options.yaml | 1 + .../lib/src/language/ast/alias.dart | 25 ++++++++++++++----- graphql_parser/pubspec.yaml | 1 + 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/graphql_parser/analysis_options.yaml b/graphql_parser/analysis_options.yaml index eae1e42a..c230cee7 100644 --- a/graphql_parser/analysis_options.yaml +++ b/graphql_parser/analysis_options.yaml @@ -1,3 +1,4 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false \ No newline at end of file diff --git a/graphql_parser/lib/src/language/ast/alias.dart b/graphql_parser/lib/src/language/ast/alias.dart index 986b4370..137be2bd 100644 --- a/graphql_parser/lib/src/language/ast/alias.dart +++ b/graphql_parser/lib/src/language/ast/alias.dart @@ -1,19 +1,32 @@ import 'package:source_span/source_span.dart'; - import '../token.dart'; import 'node.dart'; +/// An alternate name for a field within a [SelectionSet]. class AliasContext extends Node { - final Token NAME1, COLON, NAME2; + /// The source tokens. + final Token name1, colon, name2; - AliasContext(this.NAME1, this.COLON, this.NAME2); + AliasContext(this.name1, this.colon, this.name2); + + /// Use [name1] instead. + @deprecated + Token get NAME1 => name1; + + /// Use [colon] instead. + @deprecated + Token get COLON => colon; + + /// Use [name2] instead. + @deprecated + Token get NAME2 => name2; /// The aliased name of the value. - String get alias => NAME1.text; + String get alias => name1.text; /// The actual name of the value. - String get name => NAME2.text; + String get name => name2.text; @override - FileSpan get span => NAME1.span.expand(COLON.span).expand(NAME2.span); + FileSpan get span => name1.span.expand(colon.span).expand(name2.span); } diff --git a/graphql_parser/pubspec.yaml b/graphql_parser/pubspec.yaml index d5028445..2f6a1ca0 100644 --- a/graphql_parser/pubspec.yaml +++ b/graphql_parser/pubspec.yaml @@ -11,4 +11,5 @@ dependencies: string_scanner: ^1.0.0 dev_dependencies: matcher: any + pedantic: ^1.0.0 test: ">=0.12.0 <2.0.0" From 766ec56f574ea4a8db1733a0e07d3bc4799c08e9 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:24:19 -0400 Subject: [PATCH 25/69] Remove "new " --- graphql_parser/README.md | 2 +- graphql_parser/example/example.dart | 2 +- .../lib/src/language/ast/string_value.dart | 8 +- .../lib/src/language/ast/variable.dart | 2 +- graphql_parser/lib/src/language/lexer.dart | 22 +-- graphql_parser/lib/src/language/parser.dart | 128 +++++++++--------- graphql_parser/test/argument_test.dart | 4 +- graphql_parser/test/common.dart | 2 +- graphql_parser/test/directive_test.dart | 4 +- graphql_parser/test/field_test.dart | 4 +- graphql_parser/test/fragment_spread_test.dart | 2 +- graphql_parser/test/inline_fragment_test.dart | 2 +- graphql_parser/test/selection_set_test.dart | 2 +- graphql_parser/test/type_test.dart | 4 +- graphql_parser/test/value_test.dart | 2 +- .../test/variable_definition_test.dart | 2 +- graphql_parser/test/variable_test.dart | 2 +- 17 files changed, 97 insertions(+), 97 deletions(-) diff --git a/graphql_parser/README.md b/graphql_parser/README.md index b90fa864..a91d3e49 100644 --- a/graphql_parser/README.md +++ b/graphql_parser/README.md @@ -33,7 +33,7 @@ import 'package:graphql_parser/graphql_parser.dart'; doSomething(String text) { var tokens = scan(text); - var parser = new Parser(tokens); + var parser = Parser(tokens); if (parser.errors.isNotEmpty) { // Handle errors... diff --git a/graphql_parser/example/example.dart b/graphql_parser/example/example.dart index 5a3f1be4..aabba873 100644 --- a/graphql_parser/example/example.dart +++ b/graphql_parser/example/example.dart @@ -11,7 +11,7 @@ final String text = ''' main() { var tokens = scan(text); - var parser = new Parser(tokens); + var parser = Parser(tokens); var doc = parser.parseDocument(); var operation = doc.definitions.first as OperationDefinitionContext; diff --git a/graphql_parser/lib/src/language/ast/string_value.dart b/graphql_parser/lib/src/language/ast/string_value.dart index 1fa664fb..8789c886 100644 --- a/graphql_parser/lib/src/language/ast/string_value.dart +++ b/graphql_parser/lib/src/language/ast/string_value.dart @@ -24,7 +24,7 @@ class StringValueContext extends InputValueContext { } var codeUnits = text.codeUnits; - var buf = new StringBuffer(); + var buf = StringBuffer(); for (int i = 0; i < codeUnits.length; i++) { var ch = codeUnits[i]; @@ -35,9 +35,9 @@ class StringValueContext extends InputValueContext { c2 = codeUnits[++i], c3 = codeUnits[++i], c4 = codeUnits[++i]; - var hexString = new String.fromCharCodes([c1, c2, c3, c4]); + var hexString = String.fromCharCodes([c1, c2, c3, c4]); var hexNumber = int.parse(hexString, radix: 16); - buf.write(new String.fromCharCode(hexNumber)); + buf.write(String.fromCharCode(hexNumber)); continue; } @@ -64,7 +64,7 @@ class StringValueContext extends InputValueContext { buf.writeCharCode(next); } } else - throw new SyntaxError('Unexpected "\\" in string literal.', span); + throw SyntaxError('Unexpected "\\" in string literal.', span); } else { buf.writeCharCode(ch); } diff --git a/graphql_parser/lib/src/language/ast/variable.dart b/graphql_parser/lib/src/language/ast/variable.dart index e8fb4bdb..96222aee 100644 --- a/graphql_parser/lib/src/language/ast/variable.dart +++ b/graphql_parser/lib/src/language/ast/variable.dart @@ -14,5 +14,5 @@ class VariableContext extends InputValueContext { @override Object computeValue(Map variables) => variables[name]; - // new FileSpan(DOLLAR?.span?.start, NAME?.span?.end, toSource()); + // FileSpan(DOLLAR?.span?.start, NAME?.span?.end, toSource()); } diff --git a/graphql_parser/lib/src/language/lexer.dart b/graphql_parser/lib/src/language/lexer.dart index 85ff83c0..7d5d2658 100644 --- a/graphql_parser/lib/src/language/lexer.dart +++ b/graphql_parser/lib/src/language/lexer.dart @@ -4,14 +4,14 @@ import 'syntax_error.dart'; import 'token.dart'; import 'token_type.dart'; -final RegExp _comment = new RegExp(r'#[^\n]*'); -final RegExp _whitespace = new RegExp('[ \t\n\r]+'); -// final RegExp _boolean = new RegExp(r'true|false'); -final RegExp _number = new RegExp(r'-?[0-9]+(\.[0-9]+)?(E|e(\+|-)?[0-9]+)?'); -final RegExp _string = new RegExp( +final RegExp _comment = RegExp(r'#[^\n]*'); +final RegExp _whitespace = RegExp('[ \t\n\r]+'); +// final RegExp _boolean = RegExp(r'true|false'); +final RegExp _number = RegExp(r'-?[0-9]+(\.[0-9]+)?(E|e(\+|-)?[0-9]+)?'); +final RegExp _string = RegExp( r'"((\\(["\\/bfnrt]|(u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))|([^"\\]))*"'); -final RegExp _blockString = new RegExp(r'"""(([^"])|(\\"""))*"""'); -final RegExp _name = new RegExp(r'[_A-Za-z][_0-9A-Za-z]*'); +final RegExp _blockString = RegExp(r'"""(([^"])|(\\"""))*"""'); +final RegExp _name = RegExp(r'[_A-Za-z][_0-9A-Za-z]*'); final Map _patterns = { '@': TokenType.ARROBA, @@ -42,7 +42,7 @@ final Map _patterns = { List scan(String text, {sourceUrl}) { List out = []; - var scanner = new SpanScanner(text, sourceUrl: sourceUrl); + var scanner = SpanScanner(text, sourceUrl: sourceUrl); while (!scanner.isDone) { List potential = []; @@ -54,14 +54,14 @@ List scan(String text, {sourceUrl}) { for (var pattern in _patterns.keys) { if (scanner.matches(pattern)) { - potential.add(new Token( + potential.add(Token( _patterns[pattern], scanner.lastMatch[0], scanner.lastSpan)); } } if (potential.isEmpty) { - var ch = new String.fromCharCode(scanner.readChar()); - throw new SyntaxError("Unexpected token '$ch'.", scanner.emptySpan); + var ch = String.fromCharCode(scanner.readChar()); + throw SyntaxError("Unexpected token '$ch'.", scanner.emptySpan); } else { // Choose longest token potential.sort((a, b) => b.text.length.compareTo(a.text.length)); diff --git a/graphql_parser/lib/src/language/parser.dart b/graphql_parser/lib/src/language/parser.dart index fff390f5..64bd6476 100644 --- a/graphql_parser/lib/src/language/parser.dart +++ b/graphql_parser/lib/src/language/parser.dart @@ -60,7 +60,7 @@ class Parser { def = parseDefinition(); } - return new DocumentContext()..definitions.addAll(defs); + return DocumentContext()..definitions.addAll(defs); } DefinitionContext parseDefinition() => @@ -69,7 +69,7 @@ class Parser { OperationDefinitionContext parseOperationDefinition() { var selectionSet = parseSelectionSet(); if (selectionSet != null) - return new OperationDefinitionContext(null, null, null, selectionSet); + return OperationDefinitionContext(null, null, null, selectionSet); else { if (nextName('mutation') || nextName('query') || @@ -80,11 +80,11 @@ class Parser { var dirs = parseDirectives(); var selectionSet = parseSelectionSet(); if (selectionSet != null) - return new OperationDefinitionContext( + return OperationDefinitionContext( TYPE, NAME, variables, selectionSet) ..directives.addAll(dirs); else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing selection set in fragment definition.', NAME?.span ?? TYPE.span)); return null; @@ -106,29 +106,29 @@ class Parser { var dirs = parseDirectives(); var selectionSet = parseSelectionSet(); if (selectionSet != null) - return new FragmentDefinitionContext( + return FragmentDefinitionContext( FRAGMENT, NAME, ON, typeCondition, selectionSet) ..directives.addAll(dirs); else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Expected selection set in fragment definition.', typeCondition.span)); return null; } } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Expected type condition after "on" in fragment definition.', ON.span)); return null; } } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Expected "on" after name "${NAME.text}" in fragment definition.', NAME.span)); return null; } } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Expected name after "fragment" in fragment definition.', FRAGMENT.span)); return null; @@ -142,7 +142,7 @@ class Parser { var ELLIPSIS = current; if (next(TokenType.NAME, exclude: ['on'])) { var NAME = current; - return new FragmentSpreadContext(ELLIPSIS, NAME) + return FragmentSpreadContext(ELLIPSIS, NAME) ..directives.addAll(parseDirectives()); } else { _index--; @@ -162,11 +162,11 @@ class Parser { var directives = parseDirectives(); var selectionSet = parseSelectionSet(); if (selectionSet != null) { - return new InlineFragmentContext( + return InlineFragmentContext( ELLIPSIS, ON, typeCondition, selectionSet) ..directives.addAll(directives); } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing selection set in inline fragment.', directives.isEmpty ? typeCondition.span @@ -174,13 +174,13 @@ class Parser { return null; } } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing type condition after "on" in inline fragment.', ON.span)); return null; } } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing "on" after "..." in inline fragment.', ELLIPSIS.span)); return null; } @@ -202,10 +202,10 @@ class Parser { eatCommas(); if (next(TokenType.RBRACE)) - return new SelectionSetContext(LBRACE, current) + return SelectionSetContext(LBRACE, current) ..selections.addAll(selections); else { - errors.add(new SyntaxError('Missing "}" after selection set.', + errors.add(SyntaxError('Missing "}" after selection set.', selections.isEmpty ? LBRACE.span : selections.last.span)); return null; } @@ -215,13 +215,13 @@ class Parser { SelectionContext parseSelection() { var field = parseField(); - if (field != null) return new SelectionContext(field); + if (field != null) return SelectionContext(field); var fragmentSpread = parseFragmentSpread(); if (fragmentSpread != null) - return new SelectionContext(null, fragmentSpread); + return SelectionContext(null, fragmentSpread); var inlineFragment = parseInlineFragment(); if (inlineFragment != null) - return new SelectionContext(null, null, inlineFragment); + return SelectionContext(null, null, inlineFragment); else return null; } @@ -232,7 +232,7 @@ class Parser { var args = parseArguments(); var directives = parseDirectives(); var selectionSet = parseSelectionSet(); - return new FieldContext(fieldName, selectionSet) + return FieldContext(fieldName, selectionSet) ..arguments.addAll(args ?? []) ..directives.addAll(directives); } else @@ -245,15 +245,15 @@ class Parser { if (next(TokenType.COLON)) { var COLON = current; if (next(TokenType.NAME)) - return new FieldNameContext( - null, new AliasContext(NAME1, COLON, current)); + return FieldNameContext( + null, AliasContext(NAME1, COLON, current)); else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing name after colon in alias.', COLON.span)); return null; } } else - return new FieldNameContext(NAME1); + return FieldNameContext(NAME1); } else return null; } @@ -271,10 +271,10 @@ class Parser { } if (next(TokenType.RPAREN)) - return new VariableDefinitionsContext(LPAREN, current) + return VariableDefinitionsContext(LPAREN, current) ..variableDefinitions.addAll(defs); else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing ")" after variable definitions.', LPAREN.span)); return null; } @@ -290,15 +290,15 @@ class Parser { var type = parseType(); if (type != null) { var defaultValue = parseDefaultValue(); - return new VariableDefinitionContext( + return VariableDefinitionContext( variable, COLON, type, defaultValue); } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing type in variable definition.', COLON.span)); return null; } } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing ":" in variable definition.', variable.span)); return null; } @@ -309,11 +309,11 @@ class Parser { TypeContext parseType() { var name = parseTypeName(); if (name != null) { - return new TypeContext(name, null, maybe(TokenType.EXCLAMATION)); + return TypeContext(name, null, maybe(TokenType.EXCLAMATION)); } else { var listType = parseListType(); if (listType != null) { - return new TypeContext(null, listType, maybe(TokenType.EXCLAMATION)); + return TypeContext(null, listType, maybe(TokenType.EXCLAMATION)); } else return null; } @@ -325,13 +325,13 @@ class Parser { var type = parseType(); if (type != null) { if (next(TokenType.RBRACKET)) { - return new ListTypeContext(LBRACKET, type, current); + return ListTypeContext(LBRACKET, type, current); } else { - errors.add(new SyntaxError('Missing "]" in list type.', type.span)); + errors.add(SyntaxError('Missing "]" in list type.', type.span)); return null; } } else { - errors.add(new SyntaxError('Missing type after "[".', LBRACKET.span)); + errors.add(SyntaxError('Missing type after "[".', LBRACKET.span)); return null; } } else @@ -359,10 +359,10 @@ class Parser { var COLON = current; var val = parseInputValue(); if (val != null) - return new DirectiveContext( + return DirectiveContext( ARROBA, NAME, COLON, null, null, null, val); else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing value or variable in directive after colon.', COLON.span)); return null; @@ -372,22 +372,22 @@ class Parser { var arg = parseArgument(); if (arg != null) { if (next(TokenType.RPAREN)) { - return new DirectiveContext( + return DirectiveContext( ARROBA, NAME, null, LPAREN, current, arg, null); } else { - errors.add(new SyntaxError('Missing \')\'', arg.value.span)); + errors.add(SyntaxError('Missing \')\'', arg.value.span)); return null; } } else { errors.add( - new SyntaxError('Missing argument in directive.', LPAREN.span)); + SyntaxError('Missing argument in directive.', LPAREN.span)); return null; } } else - return new DirectiveContext( + return DirectiveContext( ARROBA, NAME, null, null, null, null, null); } else { - errors.add(new SyntaxError('Missing name for directive.', ARROBA.span)); + errors.add(SyntaxError('Missing name for directive.', ARROBA.span)); return null; } } else @@ -410,7 +410,7 @@ class Parser { return out; else { errors - .add(new SyntaxError('Missing ")" in argument list.', LPAREN.span)); + .add(SyntaxError('Missing ")" in argument list.', LPAREN.span)); return null; } } else @@ -424,14 +424,14 @@ class Parser { var COLON = current; var val = parseInputValue(); if (val != null) - return new ArgumentContext(NAME, COLON, val); + return ArgumentContext(NAME, COLON, val); else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing value or variable in argument.', COLON.span)); return null; } } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing colon after name in argument.', NAME.span)); return null; } @@ -447,9 +447,9 @@ class Parser { if (next(TokenType.DOLLAR)) { var DOLLAR = current; if (next(TokenType.NAME)) - return new VariableContext(DOLLAR, current); + return VariableContext(DOLLAR, current); else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing name for variable; found a lone "\$" instead.', DOLLAR.span)); return null; @@ -463,10 +463,10 @@ class Parser { var EQUALS = current; var value = parseInputValue(); if (value != null) { - return new DefaultValueContext(EQUALS, value); + return DefaultValueContext(EQUALS, value); } else { errors - .add(new SyntaxError('Missing value after "=" sign.', EQUALS.span)); + .add(SyntaxError('Missing value after "=" sign.', EQUALS.span)); return null; } } else @@ -476,14 +476,14 @@ class Parser { TypeConditionContext parseTypeCondition() { var name = parseTypeName(); if (name != null) - return new TypeConditionContext(name); + return TypeConditionContext(name); else return null; } TypeNameContext parseTypeName() { if (next(TokenType.NAME)) { - return new TypeNameContext(current); + return TypeNameContext(current); } else return null; } @@ -504,24 +504,24 @@ class Parser { } StringValueContext parseStringValue() => next(TokenType.STRING) - ? new StringValueContext(current) + ? StringValueContext(current) : (next(TokenType.BLOCK_STRING) - ? new StringValueContext(current, isBlockString: true) + ? StringValueContext(current, isBlockString: true) : null); NumberValueContext parseNumberValue() => - next(TokenType.NUMBER) ? new NumberValueContext(current) : null; + next(TokenType.NUMBER) ? NumberValueContext(current) : null; BooleanValueContext parseBooleanValue() => (nextName('true') || nextName('false')) - ? new BooleanValueContext(current) + ? BooleanValueContext(current) : null; EnumValueContext parseEnumValue() => - next(TokenType.NAME) ? new EnumValueContext(current) : null; + next(TokenType.NAME) ? EnumValueContext(current) : null; NullValueContext parseNullValue() => - nextName('null') ? new NullValueContext(current) : null; + nextName('null') ? NullValueContext(current) : null; ListValueContext parseListValue() { if (next(TokenType.LBRACKET)) { @@ -539,9 +539,9 @@ class Parser { eatCommas(); if (next(TokenType.RBRACKET)) { - return new ListValueContext(LBRACKET, current)..values.addAll(values); + return ListValueContext(LBRACKET, current)..values.addAll(values); } else { - errors.add(new SyntaxError('Unterminated list literal.', lastSpan)); + errors.add(SyntaxError('Unterminated list literal.', lastSpan)); return null; } } else @@ -565,9 +565,9 @@ class Parser { eatCommas(); if (next(TokenType.RBRACE)) { - return new ObjectValueContext(LBRACE, fields, current); + return ObjectValueContext(LBRACE, fields, current); } else { - errors.add(new SyntaxError('Unterminated object literal.', lastSpan)); + errors.add(SyntaxError('Unterminated object literal.', lastSpan)); return null; } } else { @@ -584,13 +584,13 @@ class Parser { var value = parseInputValue(); if (value != null) { - return new ObjectFieldContext(NAME, COLON, value); + return ObjectFieldContext(NAME, COLON, value); } else { - errors.add(new SyntaxError('Missing value after ":".', COLON.span)); + errors.add(SyntaxError('Missing value after ":".', COLON.span)); return null; } } else { - errors.add(new SyntaxError( + errors.add(SyntaxError( 'Missing ":" after name "${NAME.span.text}".', NAME.span)); return null; } diff --git a/graphql_parser/test/argument_test.dart b/graphql_parser/test/argument_test.dart index e5f8b764..e15262de 100644 --- a/graphql_parser/test/argument_test.dart +++ b/graphql_parser/test/argument_test.dart @@ -32,10 +32,10 @@ ArgumentContext parseArgument(String text) => parse(text).parseArgument(); List parseArgumentList(String text) => parse(text).parseArguments(); -Matcher isArgument(String name, value) => new _IsArgument(name, value); +Matcher isArgument(String name, value) => _IsArgument(name, value); Matcher isArgumentList(List arguments) => - new _IsArgumentList(arguments); + _IsArgumentList(arguments); class _IsArgument extends Matcher { final String name; diff --git a/graphql_parser/test/common.dart b/graphql_parser/test/common.dart index 728b96a8..e30cb713 100644 --- a/graphql_parser/test/common.dart +++ b/graphql_parser/test/common.dart @@ -1,3 +1,3 @@ import 'package:graphql_parser/graphql_parser.dart'; -Parser parse(String text) => new Parser(scan(text)); +Parser parse(String text) => Parser(scan(text)); diff --git a/graphql_parser/test/directive_test.dart b/graphql_parser/test/directive_test.dart index ff500c09..9dc30a4e 100644 --- a/graphql_parser/test/directive_test.dart +++ b/graphql_parser/test/directive_test.dart @@ -37,11 +37,11 @@ main() { DirectiveContext parseDirective(String text) => parse(text).parseDirective(); Matcher isDirective(String name, {Matcher valueOrVariable, Matcher argument}) => - new _IsDirective(name, + _IsDirective(name, valueOrVariable: valueOrVariable, argument: argument); Matcher isDirectiveList(List directives) => - new _IsDirectiveList(directives); + _IsDirectiveList(directives); class _IsDirective extends Matcher { final String name; diff --git a/graphql_parser/test/field_test.dart b/graphql_parser/test/field_test.dart index a0b3634e..30acb837 100644 --- a/graphql_parser/test/field_test.dart +++ b/graphql_parser/test/field_test.dart @@ -86,10 +86,10 @@ Matcher isField( Matcher arguments, Matcher directives, Matcher selectionSet}) => - new _IsField(fieldName, arguments, directives, selectionSet); + _IsField(fieldName, arguments, directives, selectionSet); Matcher isFieldName(String name, {String alias}) => - new _IsFieldName(name, alias); + _IsFieldName(name, alias); class _IsField extends Matcher { final Matcher fieldName, arguments, directives, selectionSet; diff --git a/graphql_parser/test/fragment_spread_test.dart b/graphql_parser/test/fragment_spread_test.dart index e40b4827..6fca400d 100644 --- a/graphql_parser/test/fragment_spread_test.dart +++ b/graphql_parser/test/fragment_spread_test.dart @@ -25,7 +25,7 @@ FragmentSpreadContext parseFragmentSpread(String text) => parse(text).parseFragmentSpread(); Matcher isFragmentSpread(String name, {Matcher directives}) => - new _IsFragmentSpread(name, directives); + _IsFragmentSpread(name, directives); class _IsFragmentSpread extends Matcher { final String name; diff --git a/graphql_parser/test/inline_fragment_test.dart b/graphql_parser/test/inline_fragment_test.dart index 5ad6fbca..1936e820 100644 --- a/graphql_parser/test/inline_fragment_test.dart +++ b/graphql_parser/test/inline_fragment_test.dart @@ -47,7 +47,7 @@ InlineFragmentContext parseInlineFragment(String text) => Matcher isInlineFragment(String name, {Matcher directives, Matcher selectionSet}) => - new _IsInlineFragment(name, directives, selectionSet); + _IsInlineFragment(name, directives, selectionSet); class _IsInlineFragment extends Matcher { final String name; diff --git a/graphql_parser/test/selection_set_test.dart b/graphql_parser/test/selection_set_test.dart index 438db5bd..9cf89624 100644 --- a/graphql_parser/test/selection_set_test.dart +++ b/graphql_parser/test/selection_set_test.dart @@ -56,7 +56,7 @@ SelectionSetContext parseSelectionSet(String text) => parse(text).parseSelectionSet(); Matcher isSelectionSet(List selections) => - new _IsSelectionSet(selections); + _IsSelectionSet(selections); class _IsSelectionSet extends Matcher { final List selections; diff --git a/graphql_parser/test/type_test.dart b/graphql_parser/test/type_test.dart index 1da1f4f8..86ad0043 100644 --- a/graphql_parser/test/type_test.dart +++ b/graphql_parser/test/type_test.dart @@ -49,10 +49,10 @@ main() { TypeContext parseType(String text) => parse(text).parseType(); Matcher isListType(Matcher innerType, {bool isNullable}) => - new _IsListType(innerType, isNullable: isNullable != false); + _IsListType(innerType, isNullable: isNullable != false); Matcher isType(String name, {bool isNullable}) => - new _IsType(name, nonNull: isNullable != true); + _IsType(name, nonNull: isNullable != true); class _IsListType extends Matcher { final Matcher innerType; diff --git a/graphql_parser/test/value_test.dart b/graphql_parser/test/value_test.dart index 5e07a23a..a5edaaaf 100644 --- a/graphql_parser/test/value_test.dart +++ b/graphql_parser/test/value_test.dart @@ -74,7 +74,7 @@ main() { InputValueContext parseValue(String text) => parse(text).parseInputValue(); -Matcher isValue(value) => new _IsValue(value); +Matcher isValue(value) => _IsValue(value); class _IsValue extends Matcher { final value; diff --git a/graphql_parser/test/variable_definition_test.dart b/graphql_parser/test/variable_definition_test.dart index 04f85987..f3380aea 100644 --- a/graphql_parser/test/variable_definition_test.dart +++ b/graphql_parser/test/variable_definition_test.dart @@ -42,7 +42,7 @@ VariableDefinitionContext parseVariableDefinition(String text) => Matcher isVariableDefinition(String name, {Matcher type, Matcher defaultValue}) => - new _IsVariableDefinition(name, type, defaultValue); + _IsVariableDefinition(name, type, defaultValue); class _IsVariableDefinition extends Matcher { final String name; diff --git a/graphql_parser/test/variable_test.dart b/graphql_parser/test/variable_test.dart index d4484666..eb9759f3 100644 --- a/graphql_parser/test/variable_test.dart +++ b/graphql_parser/test/variable_test.dart @@ -22,7 +22,7 @@ main() { }); } -Matcher isVariable(String name) => new _IsVariable(name); +Matcher isVariable(String name) => _IsVariable(name); class _IsVariable extends Matcher { final String name; From 4a655abb8428dbbaf6163ca765cff43125d80468 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:28:20 -0400 Subject: [PATCH 26/69] Use curly braces --- .../lib/src/language/ast/field.dart | 10 +- .../lib/src/language/ast/number_value.dart | 4 +- .../lib/src/language/ast/string_value.dart | 3 +- graphql_parser/lib/src/language/parser.dart | 150 ++++++++++-------- graphql_parser/lib/src/language/token.dart | 5 +- graphql_parser/test/directive_test.dart | 18 ++- graphql_parser/test/field_test.dart | 17 +- graphql_parser/test/fragment_spread_test.dart | 8 +- graphql_parser/test/selection_set_test.dart | 6 +- graphql_parser/test/type_test.dart | 5 +- 10 files changed, 126 insertions(+), 100 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/field.dart b/graphql_parser/lib/src/language/ast/field.dart index 3ac2c965..5aca6469 100644 --- a/graphql_parser/lib/src/language/ast/field.dart +++ b/graphql_parser/lib/src/language/ast/field.dart @@ -15,15 +15,17 @@ class FieldContext extends Node { @override FileSpan get span { - if (selectionSet != null) + if (selectionSet != null) { return fieldName.span.expand(selectionSet.span); - else if (directives.isNotEmpty) + } else if (directives.isNotEmpty) { return directives.fold( fieldName.span, (out, d) => out.expand(d.span)); - if (arguments.isNotEmpty) + } + if (arguments.isNotEmpty) { return arguments.fold( fieldName.span, (out, a) => out.expand(a.span)); - else + } else { return fieldName.span; + } } } diff --git a/graphql_parser/lib/src/language/ast/number_value.dart b/graphql_parser/lib/src/language/ast/number_value.dart index 8c18cfe1..d5fe010d 100644 --- a/graphql_parser/lib/src/language/ast/number_value.dart +++ b/graphql_parser/lib/src/language/ast/number_value.dart @@ -10,9 +10,9 @@ class NumberValueContext extends InputValueContext { num get numberValue { var text = NUMBER.text; - if (!text.contains('E') && !text.contains('e')) + if (!text.contains('E') && !text.contains('e')) { return num.parse(text); - else { + } else { var split = text.split(text.contains('E') ? 'E' : 'e'); var base = num.parse(split[0]); var exp = num.parse(split[1]); diff --git a/graphql_parser/lib/src/language/ast/string_value.dart b/graphql_parser/lib/src/language/ast/string_value.dart index 8789c886..da713b42 100644 --- a/graphql_parser/lib/src/language/ast/string_value.dart +++ b/graphql_parser/lib/src/language/ast/string_value.dart @@ -63,8 +63,9 @@ class StringValueContext extends InputValueContext { default: buf.writeCharCode(next); } - } else + } else { throw SyntaxError('Unexpected "\\" in string literal.', span); + } } else { buf.writeCharCode(ch); } diff --git a/graphql_parser/lib/src/language/parser.dart b/graphql_parser/lib/src/language/parser.dart index 64bd6476..9ea7d33c 100644 --- a/graphql_parser/lib/src/language/parser.dart +++ b/graphql_parser/lib/src/language/parser.dart @@ -68,9 +68,9 @@ class Parser { OperationDefinitionContext parseOperationDefinition() { var selectionSet = parseSelectionSet(); - if (selectionSet != null) + if (selectionSet != null) { return OperationDefinitionContext(null, null, null, selectionSet); - else { + } else { if (nextName('mutation') || nextName('query') || nextName('subscription')) { @@ -79,18 +79,18 @@ class Parser { var variables = parseVariableDefinitions(); var dirs = parseDirectives(); var selectionSet = parseSelectionSet(); - if (selectionSet != null) - return OperationDefinitionContext( - TYPE, NAME, variables, selectionSet) + if (selectionSet != null) { + return OperationDefinitionContext(TYPE, NAME, variables, selectionSet) ..directives.addAll(dirs); - else { + } else { errors.add(SyntaxError( 'Missing selection set in fragment definition.', NAME?.span ?? TYPE.span)); return null; } - } else + } else { return null; + } } } @@ -105,11 +105,11 @@ class Parser { if (typeCondition != null) { var dirs = parseDirectives(); var selectionSet = parseSelectionSet(); - if (selectionSet != null) + if (selectionSet != null) { return FragmentDefinitionContext( FRAGMENT, NAME, ON, typeCondition, selectionSet) ..directives.addAll(dirs); - else { + } else { errors.add(SyntaxError( 'Expected selection set in fragment definition.', typeCondition.span)); @@ -133,8 +133,9 @@ class Parser { FRAGMENT.span)); return null; } - } else + } else { return null; + } } FragmentSpreadContext parseFragmentSpread() { @@ -148,8 +149,9 @@ class Parser { _index--; return null; } - } else + } else { return null; + } } InlineFragmentContext parseInlineFragment() { @@ -184,8 +186,9 @@ class Parser { 'Missing "on" after "..." in inline fragment.', ELLIPSIS.span)); return null; } - } else + } else { return null; + } } SelectionSetContext parseSelectionSet() { @@ -201,29 +204,30 @@ class Parser { } eatCommas(); - if (next(TokenType.RBRACE)) + if (next(TokenType.RBRACE)) { return SelectionSetContext(LBRACE, current) ..selections.addAll(selections); - else { + } else { errors.add(SyntaxError('Missing "}" after selection set.', selections.isEmpty ? LBRACE.span : selections.last.span)); return null; } - } else + } else { return null; + } } SelectionContext parseSelection() { var field = parseField(); if (field != null) return SelectionContext(field); var fragmentSpread = parseFragmentSpread(); - if (fragmentSpread != null) - return SelectionContext(null, fragmentSpread); + if (fragmentSpread != null) return SelectionContext(null, fragmentSpread); var inlineFragment = parseInlineFragment(); - if (inlineFragment != null) + if (inlineFragment != null) { return SelectionContext(null, null, inlineFragment); - else + } else { return null; + } } FieldContext parseField() { @@ -235,8 +239,9 @@ class Parser { return FieldContext(fieldName, selectionSet) ..arguments.addAll(args ?? []) ..directives.addAll(directives); - } else + } else { return null; + } } FieldNameContext parseFieldName() { @@ -244,18 +249,19 @@ class Parser { var NAME1 = current; if (next(TokenType.COLON)) { var COLON = current; - if (next(TokenType.NAME)) - return FieldNameContext( - null, AliasContext(NAME1, COLON, current)); - else { - errors.add(SyntaxError( - 'Missing name after colon in alias.', COLON.span)); + if (next(TokenType.NAME)) { + return FieldNameContext(null, AliasContext(NAME1, COLON, current)); + } else { + errors.add( + SyntaxError('Missing name after colon in alias.', COLON.span)); return null; } - } else + } else { return FieldNameContext(NAME1); - } else + } + } else { return null; + } } VariableDefinitionsContext parseVariableDefinitions() { @@ -270,16 +276,17 @@ class Parser { def = parseVariableDefinition(); } - if (next(TokenType.RPAREN)) + if (next(TokenType.RPAREN)) { return VariableDefinitionsContext(LPAREN, current) ..variableDefinitions.addAll(defs); - else { + } else { errors.add(SyntaxError( 'Missing ")" after variable definitions.', LPAREN.span)); return null; } - } else + } else { return null; + } } VariableDefinitionContext parseVariableDefinition() { @@ -290,20 +297,20 @@ class Parser { var type = parseType(); if (type != null) { var defaultValue = parseDefaultValue(); - return VariableDefinitionContext( - variable, COLON, type, defaultValue); + return VariableDefinitionContext(variable, COLON, type, defaultValue); } else { - errors.add(SyntaxError( - 'Missing type in variable definition.', COLON.span)); + errors.add( + SyntaxError('Missing type in variable definition.', COLON.span)); return null; } } else { - errors.add(SyntaxError( - 'Missing ":" in variable definition.', variable.span)); + errors.add( + SyntaxError('Missing ":" in variable definition.', variable.span)); return null; } - } else + } else { return null; + } } TypeContext parseType() { @@ -314,8 +321,9 @@ class Parser { var listType = parseListType(); if (listType != null) { return TypeContext(null, listType, maybe(TokenType.EXCLAMATION)); - } else + } else { return null; + } } } @@ -334,8 +342,9 @@ class Parser { errors.add(SyntaxError('Missing type after "[".', LBRACKET.span)); return null; } - } else + } else { return null; + } } List parseDirectives() { @@ -358,10 +367,9 @@ class Parser { if (next(TokenType.COLON)) { var COLON = current; var val = parseInputValue(); - if (val != null) - return DirectiveContext( - ARROBA, NAME, COLON, null, null, null, val); - else { + if (val != null) { + return DirectiveContext(ARROBA, NAME, COLON, null, null, null, val); + } else { errors.add(SyntaxError( 'Missing value or variable in directive after colon.', COLON.span)); @@ -383,15 +391,16 @@ class Parser { SyntaxError('Missing argument in directive.', LPAREN.span)); return null; } - } else - return DirectiveContext( - ARROBA, NAME, null, null, null, null, null); + } else { + return DirectiveContext(ARROBA, NAME, null, null, null, null, null); + } } else { errors.add(SyntaxError('Missing name for directive.', ARROBA.span)); return null; } - } else + } else { return null; + } } List parseArguments() { @@ -406,15 +415,15 @@ class Parser { arg = parseArgument(); } - if (next(TokenType.RPAREN)) + if (next(TokenType.RPAREN)) { return out; - else { - errors - .add(SyntaxError('Missing ")" in argument list.', LPAREN.span)); + } else { + errors.add(SyntaxError('Missing ")" in argument list.', LPAREN.span)); return null; } - } else + } else { return []; + } } ArgumentContext parseArgument() { @@ -423,20 +432,21 @@ class Parser { if (next(TokenType.COLON)) { var COLON = current; var val = parseInputValue(); - if (val != null) + if (val != null) { return ArgumentContext(NAME, COLON, val); - else { + } else { errors.add(SyntaxError( 'Missing value or variable in argument.', COLON.span)); return null; } } else { - errors.add(SyntaxError( - 'Missing colon after name in argument.', NAME.span)); + errors.add( + SyntaxError('Missing colon after name in argument.', NAME.span)); return null; } - } else + } else { return null; + } } /// Use [parseInputValue] instead. @@ -446,16 +456,17 @@ class Parser { VariableContext parseVariable() { if (next(TokenType.DOLLAR)) { var DOLLAR = current; - if (next(TokenType.NAME)) + if (next(TokenType.NAME)) { return VariableContext(DOLLAR, current); - else { + } else { errors.add(SyntaxError( 'Missing name for variable; found a lone "\$" instead.', DOLLAR.span)); return null; } - } else + } else { return null; + } } DefaultValueContext parseDefaultValue() { @@ -465,27 +476,29 @@ class Parser { if (value != null) { return DefaultValueContext(EQUALS, value); } else { - errors - .add(SyntaxError('Missing value after "=" sign.', EQUALS.span)); + errors.add(SyntaxError('Missing value after "=" sign.', EQUALS.span)); return null; } - } else + } else { return null; + } } TypeConditionContext parseTypeCondition() { var name = parseTypeName(); - if (name != null) + if (name != null) { return TypeConditionContext(name); - else + } else { return null; + } } TypeNameContext parseTypeName() { if (next(TokenType.NAME)) { return TypeNameContext(current); - } else + } else { return null; + } } /// Use [parseInputValue] instead. @@ -544,8 +557,9 @@ class Parser { errors.add(SyntaxError('Unterminated list literal.', lastSpan)); return null; } - } else + } else { return null; + } } ObjectValueContext parseObjectValue() { diff --git a/graphql_parser/lib/src/language/token.dart b/graphql_parser/lib/src/language/token.dart index 5d12c90d..4a8498ae 100644 --- a/graphql_parser/lib/src/language/token.dart +++ b/graphql_parser/lib/src/language/token.dart @@ -10,9 +10,10 @@ class Token { @override String toString() { - if (span == null) + if (span == null) { return "'$text' -> $type"; - else + } else { return "(${span.start.line}:${span.start.column}) '$text' -> $type"; + } } } diff --git a/graphql_parser/test/directive_test.dart b/graphql_parser/test/directive_test.dart index 9dc30a4e..001c4ea8 100644 --- a/graphql_parser/test/directive_test.dart +++ b/graphql_parser/test/directive_test.dart @@ -37,8 +37,7 @@ main() { DirectiveContext parseDirective(String text) => parse(text).parseDirective(); Matcher isDirective(String name, {Matcher valueOrVariable, Matcher argument}) => - _IsDirective(name, - valueOrVariable: valueOrVariable, argument: argument); + _IsDirective(name, valueOrVariable: valueOrVariable, argument: argument); Matcher isDirectiveList(List directives) => _IsDirectiveList(directives); @@ -57,8 +56,9 @@ class _IsDirective extends Matcher { return valueOrVariable.describe(desc.add(' and ')); } else if (argument != null) { return argument.describe(desc.add(' and ')); - } else + } else { return desc; + } } @override @@ -67,9 +67,9 @@ class _IsDirective extends Matcher { item is DirectiveContext ? item : parseDirective(item.toString()); if (directive == null) return false; if (valueOrVariable != null) { - if (directive.value == null) + if (directive.value == null) { return false; - else { + } else { var v = directive.value; if (v is VariableContext) { return valueOrVariable.matches(v.name, matchState); @@ -79,12 +79,14 @@ class _IsDirective extends Matcher { } } } else if (argument != null) { - if (directive.argument == null) + if (directive.argument == null) { return false; - else + } else { return argument.matches(directive.argument, matchState); - } else + } + } else { return true; + } } } diff --git a/graphql_parser/test/field_test.dart b/graphql_parser/test/field_test.dart index 30acb837..e39f3f63 100644 --- a/graphql_parser/test/field_test.dart +++ b/graphql_parser/test/field_test.dart @@ -88,8 +88,7 @@ Matcher isField( Matcher selectionSet}) => _IsField(fieldName, arguments, directives, selectionSet); -Matcher isFieldName(String name, {String alias}) => - _IsFieldName(name, alias); +Matcher isFieldName(String name, {String alias}) => _IsFieldName(name, alias); class _IsField extends Matcher { final Matcher fieldName, arguments, directives, selectionSet; @@ -106,10 +105,12 @@ class _IsField extends Matcher { bool matches(item, Map matchState) { var field = item is FieldContext ? item : parseField(item.toString()); if (field == null) return false; - if (fieldName != null && !fieldName.matches(field.fieldName, matchState)) + if (fieldName != null && !fieldName.matches(field.fieldName, matchState)) { return false; - if (arguments != null && !arguments.matches(field.arguments, matchState)) + } + if (arguments != null && !arguments.matches(field.arguments, matchState)) { return false; + } return true; } } @@ -121,9 +122,10 @@ class _IsFieldName extends Matcher { @override Description describe(Description description) { - if (realName != null) + if (realName != null) { return description .add('is field with name "$name" and alias "$realName"'); + } return description.add('is field with name "$name"'); } @@ -131,10 +133,11 @@ class _IsFieldName extends Matcher { bool matches(item, Map matchState) { var fieldName = item is FieldNameContext ? item : parseFieldName(item.toString()); - if (realName != null) + if (realName != null) { return fieldName.alias?.alias == name && fieldName.alias?.name == realName; - else + } else { return fieldName.name == name; + } } } diff --git a/graphql_parser/test/fragment_spread_test.dart b/graphql_parser/test/fragment_spread_test.dart index 6fca400d..752e1122 100644 --- a/graphql_parser/test/fragment_spread_test.dart +++ b/graphql_parser/test/fragment_spread_test.dart @@ -35,9 +35,10 @@ class _IsFragmentSpread extends Matcher { @override Description describe(Description description) { - if (directives != null) + if (directives != null) { return directives.describe( description.add('is a fragment spread named "$name" that also ')); + } return description.add('is a fragment spread named "$name"'); } @@ -48,9 +49,10 @@ class _IsFragmentSpread extends Matcher { : parseFragmentSpread(item.toString()); if (spread == null) return false; if (spread.name != name) return false; - if (directives != null) + if (directives != null) { return directives.matches(spread.directives, matchState); - else + } else { return true; + } } } diff --git a/graphql_parser/test/selection_set_test.dart b/graphql_parser/test/selection_set_test.dart index 9cf89624..cd482481 100644 --- a/graphql_parser/test/selection_set_test.dart +++ b/graphql_parser/test/selection_set_test.dart @@ -55,8 +55,7 @@ main() { SelectionSetContext parseSelectionSet(String text) => parse(text).parseSelectionSet(); -Matcher isSelectionSet(List selections) => - _IsSelectionSet(selections); +Matcher isSelectionSet(List selections) => _IsSelectionSet(selections); class _IsSelectionSet extends Matcher { final List selections; @@ -87,8 +86,9 @@ class _IsSelectionSet extends Matcher { for (int i = 0; i < set.selections.length; i++) { var sel = set.selections[i]; if (!selections[i].matches( - sel.field ?? sel.fragmentSpread ?? sel.inlineFragment, matchState)) + sel.field ?? sel.fragmentSpread ?? sel.inlineFragment, matchState)) { return false; + } } return true; diff --git a/graphql_parser/test/type_test.dart b/graphql_parser/test/type_test.dart index 86ad0043..5ecb0030 100644 --- a/graphql_parser/test/type_test.dart +++ b/graphql_parser/test/type_test.dart @@ -84,10 +84,11 @@ class _IsType extends Matcher { @override Description describe(Description description) { - if (nonNull == true) + if (nonNull == true) { return description.add('is non-null type named "$name"'); - else + } else { return description.add('is nullable type named "$name"'); + } } @override From 29d840d7da4c8a5cb6de30eead895039b17ccfaf Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:28:31 -0400 Subject: [PATCH 27/69] Use = instead of : --- graphql_parser/lib/src/language/ast/string_value.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql_parser/lib/src/language/ast/string_value.dart b/graphql_parser/lib/src/language/ast/string_value.dart index da713b42..c6588f5b 100644 --- a/graphql_parser/lib/src/language/ast/string_value.dart +++ b/graphql_parser/lib/src/language/ast/string_value.dart @@ -9,7 +9,7 @@ class StringValueContext extends InputValueContext { final Token STRING; final bool isBlockString; - StringValueContext(this.STRING, {this.isBlockString: false}); + StringValueContext(this.STRING, {this.isBlockString = false}); @override FileSpan get span => STRING.span; From 44da964dca43eff8e1cc7556b7b6e5917bd31d23 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:30:26 -0400 Subject: [PATCH 28/69] pedantic: ast/argument.dart --- .../lib/src/language/ast/argument.dart | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/argument.dart b/graphql_parser/lib/src/language/ast/argument.dart index 6639874a..f1150bd4 100644 --- a/graphql_parser/lib/src/language/ast/argument.dart +++ b/graphql_parser/lib/src/language/ast/argument.dart @@ -3,18 +3,31 @@ import '../token.dart'; import 'node.dart'; import 'input_value.dart'; +/// An argument passed to a [FieldContext]. class ArgumentContext extends Node { - final Token NAME, COLON; + /// The source tokens. + final Token nameToken, colon; + + /// The value of the argument. final InputValueContext value; - ArgumentContext(this.NAME, this.COLON, this.value); + ArgumentContext(this.nameToken, this.colon, this.value); /// Use [value] instead. @deprecated InputValueContext get valueOrVariable => value; - String get name => NAME.text; + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; + + /// Use [colon] instead. + @deprecated + Token get COLON => colon; + + /// The name of the argument, as a [String]. + String get name => nameToken.text; @override - FileSpan get span => NAME.span.expand(COLON.span).expand(value.span); + FileSpan get span => nameToken.span.expand(colon.span).expand(value.span); } From b1787d9c8de9ccf736ad5e6186f605ac5bf0496b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:31:23 -0400 Subject: [PATCH 29/69] pedantic: ast/default_value.dart --- .../lib/src/language/ast/default_value.dart | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/default_value.dart b/graphql_parser/lib/src/language/ast/default_value.dart index de41a580..8da3414a 100644 --- a/graphql_parser/lib/src/language/ast/default_value.dart +++ b/graphql_parser/lib/src/language/ast/default_value.dart @@ -3,12 +3,20 @@ import '../token.dart'; import 'input_value.dart'; import 'node.dart'; +/// The default value to be passed to an [ArgumentContext]. class DefaultValueContext extends Node { - final Token EQUALS; + /// The source token. + final Token equals; + + /// The default value for the argument. final InputValueContext value; - DefaultValueContext(this.EQUALS, this.value); + DefaultValueContext(this.equals, this.value); + + /// Use [equals] instead. + @deprecated + Token get EQUALS => equals; @override - FileSpan get span => EQUALS.span.expand(value.span); + FileSpan get span => equals.span.expand(value.span); } From 5f178c4a13328d2a8a4fea6418e9ef2f8eb6fbcd Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:33:11 -0400 Subject: [PATCH 30/69] pedantic: ast/array_value.dart --- .../lib/src/language/ast/array_value.dart | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/array_value.dart b/graphql_parser/lib/src/language/ast/array_value.dart index 1408a5bd..4e7204f3 100644 --- a/graphql_parser/lib/src/language/ast/array_value.dart +++ b/graphql_parser/lib/src/language/ast/array_value.dart @@ -2,16 +2,28 @@ import 'package:source_span/source_span.dart'; import '../token.dart'; import 'input_value.dart'; +/// A GraphQL list value literal. class ListValueContext extends InputValueContext { - final Token LBRACKET, RBRACKET; + /// The source tokens. + final Token lBracket, rBracket; + + /// The child values. final List values = []; - ListValueContext(this.LBRACKET, this.RBRACKET); + ListValueContext(this.lBracket, this.rBracket); + + /// Use [lBracket] instead. + @deprecated + Token get LBRACKET => lBracket; + + /// Use [rBracket] instead. + @deprecated + Token get RBRACKET => rBracket; @override FileSpan get span { - var out = values.fold(LBRACKET.span, (o, v) => o.expand(v.span)); - return out.expand(RBRACKET.span); + var out = values.fold(lBracket.span, (o, v) => o.expand(v.span)); + return out.expand(rBracket.span); } @override From a1ce812088455bea6aecfd1aec2fe02593b3cd2b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:34:23 -0400 Subject: [PATCH 31/69] pedantic: ast/boolean_value.dart --- .../lib/src/language/ast/boolean_value.dart | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/boolean_value.dart b/graphql_parser/lib/src/language/ast/boolean_value.dart index 62b78046..423f0cde 100644 --- a/graphql_parser/lib/src/language/ast/boolean_value.dart +++ b/graphql_parser/lib/src/language/ast/boolean_value.dart @@ -2,18 +2,26 @@ import 'package:source_span/source_span.dart'; import 'input_value.dart'; import '../token.dart'; +/// A GraphQL boolean value literal. class BooleanValueContext extends InputValueContext { bool _valueCache; - final Token BOOLEAN; - BooleanValueContext(this.BOOLEAN) { - assert(BOOLEAN?.text == 'true' || BOOLEAN?.text == 'false'); + /// The source token. + final Token boolean; + + BooleanValueContext(this.boolean) { + assert(boolean?.text == 'true' || boolean?.text == 'false'); } - bool get booleanValue => _valueCache ??= BOOLEAN.text == 'true'; + /// The [bool] value of this literal. + bool get booleanValue => _valueCache ??= boolean.text == 'true'; + + /// Use [boolean] instead. + @deprecated + Token get BOOLEAN => boolean; @override - FileSpan get span => BOOLEAN.span; + FileSpan get span => boolean.span; @override bool computeValue(Map variables) => booleanValue; From 5567b07a9bbb5700a7c7f1c2010fdeec06a5d11d Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:37:31 -0400 Subject: [PATCH 32/69] pedantic: ast/directive.dart --- .../lib/src/language/ast/directive.dart | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/directive.dart b/graphql_parser/lib/src/language/ast/directive.dart index d0899f57..0115fd40 100644 --- a/graphql_parser/lib/src/language/ast/directive.dart +++ b/graphql_parser/lib/src/language/ast/directive.dart @@ -4,28 +4,47 @@ import 'argument.dart'; import 'input_value.dart'; import 'node.dart'; +/// A GraphQL directive, which may or may not have runtime semantics. class DirectiveContext extends Node { - final Token ARROBA, NAME, COLON, LPAREN, RPAREN; + /// The source tokens. + final Token arroba, name, colon, lParen, rParen; + /// The argument being passed as the directive. final ArgumentContext argument; + /// The (optional) value being passed with the directive. final InputValueContext value; - DirectiveContext(this.ARROBA, this.NAME, this.COLON, this.LPAREN, this.RPAREN, + DirectiveContext(this.arroba, this.name, this.colon, this.lParen, this.rParen, this.argument, this.value) { - assert(NAME != null); + assert(name != null); } /// Use [value] instead. @deprecated InputValueContext get valueOrVariable => value; + @deprecated + Token get ARROBA => arroba; + + @deprecated + Token get NAME => name; + + @deprecated + Token get COLON => colon; + + @deprecated + Token get LPAREN => lParen; + + @deprecated + Token get RPAREN => rParen; + @override FileSpan get span { - var out = ARROBA.span.expand(NAME.span); + var out = arroba.span.expand(name.span); - if (COLON != null) { - out = out.expand(COLON.span).expand(value.span); - } else if (LPAREN != null) { - out = out.expand(LPAREN.span).expand(argument.span).expand(RPAREN.span); + if (colon != null) { + out = out.expand(colon.span).expand(value.span); + } else if (lParen != null) { + out = out.expand(lParen.span).expand(argument.span).expand(rParen.span); } return out; From 5182ff0bf26dc7f84063c0fcdc86cb05a5af6031 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:39:29 -0400 Subject: [PATCH 33/69] pedantic: ast/field_name.dart --- .../lib/src/language/ast/field_name.dart | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/field_name.dart b/graphql_parser/lib/src/language/ast/field_name.dart index d6e80dea..4841d6ce 100644 --- a/graphql_parser/lib/src/language/ast/field_name.dart +++ b/graphql_parser/lib/src/language/ast/field_name.dart @@ -3,16 +3,25 @@ import '../token.dart'; import 'alias.dart'; import 'node.dart'; +/// The name of a GraphQL [FieldContext], which may or may not be [alias]ed. class FieldNameContext extends Node { - final Token NAME; + /// The source token. + final Token nameToken; + + /// An (optional) alias for the field. final AliasContext alias; - FieldNameContext(this.NAME, [this.alias]) { - assert(NAME != null || alias != null); + FieldNameContext(this.nameToken, [this.alias]) { + assert(nameToken != null || alias != null); } - String get name => NAME?.text; + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; + + /// The [String] value of the [nameToken], if any. + String get name => nameToken?.text; @override - FileSpan get span => alias?.span ?? NAME.span; + FileSpan get span => alias?.span ?? nameToken.span; } From 6490324a0997c61e0044dee6a894dded56bb82b8 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:43:10 -0400 Subject: [PATCH 34/69] pedantic: frag def --- .../src/language/ast/fragment_definition.dart | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/fragment_definition.dart b/graphql_parser/lib/src/language/ast/fragment_definition.dart index 23787e07..00204bf2 100644 --- a/graphql_parser/lib/src/language/ast/fragment_definition.dart +++ b/graphql_parser/lib/src/language/ast/fragment_definition.dart @@ -5,22 +5,43 @@ import 'package:source_span/source_span.dart'; import 'selection_set.dart'; import 'type_condition.dart'; +/// A GraphQL query fragment definition. class FragmentDefinitionContext extends ExecutableDefinitionContext { - final Token FRAGMENT, NAME, ON; + /// The source tokens. + final Token fragmentToken, nameToken, onToken; + + /// The type to which this fragment applies. final TypeConditionContext typeCondition; + + /// Any directives on the fragment. final List directives = []; + + /// The selections to apply when the [typeCondition] is met. final SelectionSetContext selectionSet; - String get name => NAME.text; + /// The [String] value of the [nameToken]. + String get name => nameToken.text; - FragmentDefinitionContext( - this.FRAGMENT, this.NAME, this.ON, this.typeCondition, this.selectionSet); + FragmentDefinitionContext(this.fragmentToken, this.nameToken, this.onToken, + this.typeCondition, this.selectionSet); + + /// Use [fragmentToken] instead. + @deprecated + Token get FRAGMENT => fragmentToken; + + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; + + /// Use [onToken] instead. + @deprecated + Token get ON => onToken; @override FileSpan get span { - var out = FRAGMENT.span - .expand(NAME.span) - .expand(ON.span) + var out = fragmentToken.span + .expand(nameToken.span) + .expand(onToken.span) .expand(typeCondition.span); out = directives.fold(out, (o, d) => o.expand(d.span)); return out.expand(selectionSet.span); From 018de5b5464f12fadd237c154a7d86d17fd8c037 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:45:42 -0400 Subject: [PATCH 35/69] use *Token naming for token members --- .../lib/src/language/ast/alias.dart | 23 ++++++------- .../lib/src/language/ast/argument.dart | 10 +++--- .../lib/src/language/ast/array_value.dart | 17 +++++----- .../lib/src/language/ast/boolean_value.dart | 14 ++++---- .../lib/src/language/ast/default_value.dart | 10 +++--- .../src/language/ast/deprecated_value.dart | 3 ++ .../lib/src/language/ast/directive.dart | 33 +++++++++++-------- 7 files changed, 60 insertions(+), 50 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/alias.dart b/graphql_parser/lib/src/language/ast/alias.dart index 137be2bd..1c986bd2 100644 --- a/graphql_parser/lib/src/language/ast/alias.dart +++ b/graphql_parser/lib/src/language/ast/alias.dart @@ -5,28 +5,29 @@ import 'node.dart'; /// An alternate name for a field within a [SelectionSet]. class AliasContext extends Node { /// The source tokens. - final Token name1, colon, name2; + final Token nameToken1, colonToken, nameToken2; - AliasContext(this.name1, this.colon, this.name2); + AliasContext(this.nameToken1, this.colonToken, this.nameToken2); - /// Use [name1] instead. + /// Use [nameToken1] instead. @deprecated - Token get NAME1 => name1; + Token get NAME1 => nameToken1; - /// Use [colon] instead. + /// Use [colonToken] instead. @deprecated - Token get COLON => colon; + Token get COLON => colonToken; - /// Use [name2] instead. + /// Use [nameToken2] instead. @deprecated - Token get NAME2 => name2; + Token get NAME2 => nameToken2; /// The aliased name of the value. - String get alias => name1.text; + String get alias => nameToken1.text; /// The actual name of the value. - String get name => name2.text; + String get name => nameToken2.text; @override - FileSpan get span => name1.span.expand(colon.span).expand(name2.span); + FileSpan get span => + nameToken1.span.expand(colonToken.span).expand(nameToken2.span); } diff --git a/graphql_parser/lib/src/language/ast/argument.dart b/graphql_parser/lib/src/language/ast/argument.dart index f1150bd4..8b3e8294 100644 --- a/graphql_parser/lib/src/language/ast/argument.dart +++ b/graphql_parser/lib/src/language/ast/argument.dart @@ -6,12 +6,12 @@ import 'input_value.dart'; /// An argument passed to a [FieldContext]. class ArgumentContext extends Node { /// The source tokens. - final Token nameToken, colon; + final Token nameToken, colonToken; /// The value of the argument. final InputValueContext value; - ArgumentContext(this.nameToken, this.colon, this.value); + ArgumentContext(this.nameToken, this.colonToken, this.value); /// Use [value] instead. @deprecated @@ -21,13 +21,13 @@ class ArgumentContext extends Node { @deprecated Token get NAME => nameToken; - /// Use [colon] instead. + /// Use [colonToken] instead. @deprecated - Token get COLON => colon; + Token get COLON => colonToken; /// The name of the argument, as a [String]. String get name => nameToken.text; @override - FileSpan get span => nameToken.span.expand(colon.span).expand(value.span); + FileSpan get span => nameToken.span.expand(colonToken.span).expand(value.span); } diff --git a/graphql_parser/lib/src/language/ast/array_value.dart b/graphql_parser/lib/src/language/ast/array_value.dart index 4e7204f3..51afb3df 100644 --- a/graphql_parser/lib/src/language/ast/array_value.dart +++ b/graphql_parser/lib/src/language/ast/array_value.dart @@ -5,25 +5,26 @@ import 'input_value.dart'; /// A GraphQL list value literal. class ListValueContext extends InputValueContext { /// The source tokens. - final Token lBracket, rBracket; + final Token lBracketToken, rBracketToken; /// The child values. final List values = []; - ListValueContext(this.lBracket, this.rBracket); + ListValueContext(this.lBracketToken, this.rBracketToken); - /// Use [lBracket] instead. + /// Use [lBracketToken] instead. @deprecated - Token get LBRACKET => lBracket; + Token get LBRACKET => lBracketToken; - /// Use [rBracket] instead. + /// Use [rBracketToken] instead. @deprecated - Token get RBRACKET => rBracket; + Token get RBRACKET => rBracketToken; @override FileSpan get span { - var out = values.fold(lBracket.span, (o, v) => o.expand(v.span)); - return out.expand(rBracket.span); + var out = + values.fold(lBracketToken.span, (o, v) => o.expand(v.span)); + return out.expand(rBracketToken.span); } @override diff --git a/graphql_parser/lib/src/language/ast/boolean_value.dart b/graphql_parser/lib/src/language/ast/boolean_value.dart index 423f0cde..0b8cfe8f 100644 --- a/graphql_parser/lib/src/language/ast/boolean_value.dart +++ b/graphql_parser/lib/src/language/ast/boolean_value.dart @@ -7,21 +7,21 @@ class BooleanValueContext extends InputValueContext { bool _valueCache; /// The source token. - final Token boolean; + final Token booleanToken; - BooleanValueContext(this.boolean) { - assert(boolean?.text == 'true' || boolean?.text == 'false'); + BooleanValueContext(this.booleanToken) { + assert(booleanToken?.text == 'true' || booleanToken?.text == 'false'); } /// The [bool] value of this literal. - bool get booleanValue => _valueCache ??= boolean.text == 'true'; + bool get booleanValue => _valueCache ??= booleanToken.text == 'true'; - /// Use [boolean] instead. + /// Use [booleanToken] instead. @deprecated - Token get BOOLEAN => boolean; + Token get BOOLEAN => booleanToken; @override - FileSpan get span => boolean.span; + FileSpan get span => booleanToken.span; @override bool computeValue(Map variables) => booleanValue; diff --git a/graphql_parser/lib/src/language/ast/default_value.dart b/graphql_parser/lib/src/language/ast/default_value.dart index 8da3414a..d3b805b5 100644 --- a/graphql_parser/lib/src/language/ast/default_value.dart +++ b/graphql_parser/lib/src/language/ast/default_value.dart @@ -6,17 +6,17 @@ import 'node.dart'; /// The default value to be passed to an [ArgumentContext]. class DefaultValueContext extends Node { /// The source token. - final Token equals; + final Token equalsToken; /// The default value for the argument. final InputValueContext value; - DefaultValueContext(this.equals, this.value); + DefaultValueContext(this.equalsToken, this.value); - /// Use [equals] instead. + /// Use [equalsToken] instead. @deprecated - Token get EQUALS => equals; + Token get EQUALS => equalsToken; @override - FileSpan get span => equals.span.expand(value.span); + FileSpan get span => equalsToken.span.expand(value.span); } diff --git a/graphql_parser/lib/src/language/ast/deprecated_value.dart b/graphql_parser/lib/src/language/ast/deprecated_value.dart index 2f71709c..5dfca6ef 100644 --- a/graphql_parser/lib/src/language/ast/deprecated_value.dart +++ b/graphql_parser/lib/src/language/ast/deprecated_value.dart @@ -3,6 +3,9 @@ import 'input_value.dart'; /// Use [ConstantContext] instead. This class remains solely for backwards compatibility. @deprecated abstract class ValueContext extends InputValueContext { + /// Return a constant value. T get value; + + @override T computeValue(Map variables) => value; } diff --git a/graphql_parser/lib/src/language/ast/directive.dart b/graphql_parser/lib/src/language/ast/directive.dart index 0115fd40..c641aed6 100644 --- a/graphql_parser/lib/src/language/ast/directive.dart +++ b/graphql_parser/lib/src/language/ast/directive.dart @@ -7,15 +7,17 @@ import 'node.dart'; /// A GraphQL directive, which may or may not have runtime semantics. class DirectiveContext extends Node { /// The source tokens. - final Token arroba, name, colon, lParen, rParen; + final Token arrobaToken, nameToken, colonToken, lParenToken, rParenToken; + /// The argument being passed as the directive. final ArgumentContext argument; + /// The (optional) value being passed with the directive. final InputValueContext value; - DirectiveContext(this.arroba, this.name, this.colon, this.lParen, this.rParen, - this.argument, this.value) { - assert(name != null); + DirectiveContext(this.arrobaToken, this.nameToken, this.colonToken, + this.lParenToken, this.rParenToken, this.argument, this.value) { + assert(nameToken != null); } /// Use [value] instead. @@ -23,28 +25,31 @@ class DirectiveContext extends Node { InputValueContext get valueOrVariable => value; @deprecated - Token get ARROBA => arroba; + Token get ARROBA => arrobaToken; @deprecated - Token get NAME => name; + Token get NAME => nameToken; @deprecated - Token get COLON => colon; + Token get COLON => colonToken; @deprecated - Token get LPAREN => lParen; + Token get LPAREN => lParenToken; @deprecated - Token get RPAREN => rParen; + Token get RPAREN => rParenToken; @override FileSpan get span { - var out = arroba.span.expand(name.span); + var out = arrobaToken.span.expand(nameToken.span); - if (colon != null) { - out = out.expand(colon.span).expand(value.span); - } else if (lParen != null) { - out = out.expand(lParen.span).expand(argument.span).expand(rParen.span); + if (colonToken != null) { + out = out.expand(colonToken.span).expand(value.span); + } else if (lParenToken != null) { + out = out + .expand(lParenToken.span) + .expand(argument.span) + .expand(rParenToken.span); } return out; From 5e4b2b520e1f1e042167f3eeabf1ad41d6c22edc Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:45:51 -0400 Subject: [PATCH 36/69] Formatting --- graphql_parser/lib/src/language/ast/argument.dart | 3 ++- graphql_parser/lib/src/language/lexer.dart | 4 ++-- graphql_parser/test/argument_test.dart | 3 +-- graphql_parser/test/issue23_test.dart | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/argument.dart b/graphql_parser/lib/src/language/ast/argument.dart index 8b3e8294..00382da8 100644 --- a/graphql_parser/lib/src/language/ast/argument.dart +++ b/graphql_parser/lib/src/language/ast/argument.dart @@ -29,5 +29,6 @@ class ArgumentContext extends Node { String get name => nameToken.text; @override - FileSpan get span => nameToken.span.expand(colonToken.span).expand(value.span); + FileSpan get span => + nameToken.span.expand(colonToken.span).expand(value.span); } diff --git a/graphql_parser/lib/src/language/lexer.dart b/graphql_parser/lib/src/language/lexer.dart index 7d5d2658..1d7c35fd 100644 --- a/graphql_parser/lib/src/language/lexer.dart +++ b/graphql_parser/lib/src/language/lexer.dart @@ -54,8 +54,8 @@ List scan(String text, {sourceUrl}) { for (var pattern in _patterns.keys) { if (scanner.matches(pattern)) { - potential.add(Token( - _patterns[pattern], scanner.lastMatch[0], scanner.lastSpan)); + potential.add( + Token(_patterns[pattern], scanner.lastMatch[0], scanner.lastSpan)); } } diff --git a/graphql_parser/test/argument_test.dart b/graphql_parser/test/argument_test.dart index e15262de..fbe12542 100644 --- a/graphql_parser/test/argument_test.dart +++ b/graphql_parser/test/argument_test.dart @@ -34,8 +34,7 @@ List parseArgumentList(String text) => Matcher isArgument(String name, value) => _IsArgument(name, value); -Matcher isArgumentList(List arguments) => - _IsArgumentList(arguments); +Matcher isArgumentList(List arguments) => _IsArgumentList(arguments); class _IsArgument extends Matcher { final String name; diff --git a/graphql_parser/test/issue23_test.dart b/graphql_parser/test/issue23_test.dart index 2648fd30..aa64175b 100644 --- a/graphql_parser/test/issue23_test.dart +++ b/graphql_parser/test/issue23_test.dart @@ -4,7 +4,7 @@ import 'package:test/test.dart'; /// This is an *extremely* verbose test, but basically it /// parses both documents, and makes sure that $memberId has /// a valid value. -/// +/// /// Resolves https://github.com/angel-dart/graphql/issues/23. void main() { void testStr(String name, String text) { From e5e77787f628fabd946ce8f616ee3bd0f13d2266 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:47:04 -0400 Subject: [PATCH 37/69] definition.dart: comments --- graphql_parser/lib/src/language/ast/definition.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/graphql_parser/lib/src/language/ast/definition.dart b/graphql_parser/lib/src/language/ast/definition.dart index efc72ee0..d129d422 100644 --- a/graphql_parser/lib/src/language/ast/definition.dart +++ b/graphql_parser/lib/src/language/ast/definition.dart @@ -1,9 +1,13 @@ import 'node.dart'; +/// The base class for top-level GraphQL definitions. abstract class DefinitionContext extends Node {} +/// An executable definition. abstract class ExecutableDefinitionContext extends DefinitionContext {} +/// An ad-hoc type system declared in GraphQL. abstract class TypeSystemDefinitionContext extends DefinitionContext {} +/// An extension to an existing ad-hoc type system. abstract class TypeSystemExtensionContext extends DefinitionContext {} From 61a06da999ebc69522de7e0bd485ad2404a0ce5a Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:47:51 -0400 Subject: [PATCH 38/69] Update comments in directive.dart --- graphql_parser/lib/src/language/ast/directive.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/graphql_parser/lib/src/language/ast/directive.dart b/graphql_parser/lib/src/language/ast/directive.dart index c641aed6..65a53c23 100644 --- a/graphql_parser/lib/src/language/ast/directive.dart +++ b/graphql_parser/lib/src/language/ast/directive.dart @@ -24,18 +24,23 @@ class DirectiveContext extends Node { @deprecated InputValueContext get valueOrVariable => value; + /// Use [arrobaToken] instead. @deprecated Token get ARROBA => arrobaToken; +/// Use [nameToken] instead. @deprecated Token get NAME => nameToken; +/// Use [colonToken] instead. @deprecated Token get COLON => colonToken; +/// Use [lParenToken] instead. @deprecated Token get LPAREN => lParenToken; +/// Use [rParenToken] instead. @deprecated Token get RPAREN => rParenToken; From 4881363dc7eb1836cdc3d749969d9e236962f599 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:48:26 -0400 Subject: [PATCH 39/69] document: comments --- graphql_parser/lib/src/language/ast/document.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/graphql_parser/lib/src/language/ast/document.dart b/graphql_parser/lib/src/language/ast/document.dart index d705e0d6..278d4d9c 100644 --- a/graphql_parser/lib/src/language/ast/document.dart +++ b/graphql_parser/lib/src/language/ast/document.dart @@ -2,7 +2,9 @@ import 'package:source_span/source_span.dart'; import 'definition.dart'; import 'node.dart'; +/// A GraphQL document. class DocumentContext extends Node { + /// The top-level definitions in the document. final List definitions = []; @override From 517d3ee3164a92e3ef5636a2f1c5120b6465343a Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:49:39 -0400 Subject: [PATCH 40/69] FieldContext: comments --- graphql_parser/lib/src/language/ast/field.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/graphql_parser/lib/src/language/ast/field.dart b/graphql_parser/lib/src/language/ast/field.dart index 5aca6469..2998d822 100644 --- a/graphql_parser/lib/src/language/ast/field.dart +++ b/graphql_parser/lib/src/language/ast/field.dart @@ -5,10 +5,18 @@ import 'field_name.dart'; import 'node.dart'; import 'selection_set.dart'; +/// A field in a GraphQL [SelectionSet]. class FieldContext extends Node { + /// The name of this field. final FieldNameContext fieldName; + + /// Any arguments this field expects. final List arguments = []; + + /// Any directives affixed to this field. final List directives = []; + + /// The list of selections to resolve on an object. final SelectionSetContext selectionSet; FieldContext(this.fieldName, [this.selectionSet]); From a749205c1a97e1d1d8a5ef3588735207d5049219 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:51:09 -0400 Subject: [PATCH 41/69] fragment_spread: pedantic --- .../lib/src/language/ast/fragment_spread.dart | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/fragment_spread.dart b/graphql_parser/lib/src/language/ast/fragment_spread.dart index dcac0070..36a68383 100644 --- a/graphql_parser/lib/src/language/ast/fragment_spread.dart +++ b/graphql_parser/lib/src/language/ast/fragment_spread.dart @@ -3,17 +3,30 @@ import 'directive.dart'; import 'node.dart'; import 'package:source_span/source_span.dart'; +/// A GraphQL fragment spread. class FragmentSpreadContext extends Node { - final Token ELLIPSIS, NAME; + /// The source tokens. + final Token ellipsisToken, nameToken; + + /// Any directives affixed to this fragment spread. final List directives = []; - FragmentSpreadContext(this.ELLIPSIS, this.NAME); + FragmentSpreadContext(this.ellipsisToken, this.nameToken); - String get name => NAME.text; + /// The [String] value of the [nameToken]. + String get name => nameToken.text; + + /// Use [ellipsisToken] instead. + @deprecated + Token get ELLIPSIS => ellipsisToken; + + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; @override FileSpan get span { - var out = ELLIPSIS.span.expand(NAME.span); + var out = ellipsisToken.span.expand(nameToken.span); if (directives.isEmpty) return out; return directives.fold(out, (o, d) => o.expand(d.span)); } From fcbf95fc3f02db3cc9f6bf441becbf08e98f2d6b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:53:28 -0400 Subject: [PATCH 42/69] pedantic: inline_fragment --- .../lib/src/language/ast/inline_fragment.dart | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/inline_fragment.dart b/graphql_parser/lib/src/language/ast/inline_fragment.dart index 7f616bc5..d73a8080 100644 --- a/graphql_parser/lib/src/language/ast/inline_fragment.dart +++ b/graphql_parser/lib/src/language/ast/inline_fragment.dart @@ -5,18 +5,35 @@ import 'package:source_span/source_span.dart'; import 'selection_set.dart'; import 'type_condition.dart'; +/// An inline fragment, which typically appears in a [SelectionSetContext]. class InlineFragmentContext extends Node { - final Token ELLIPSIS, ON; + /// The source tokens. + final Token ellipsisToken, onToken; + + /// The type which this fragment matches. final TypeConditionContext typeCondition; + + /// Any directives affixed to this inline fragment. final List directives = []; + + /// The selections applied when the [typeCondition] is met. final SelectionSetContext selectionSet; InlineFragmentContext( - this.ELLIPSIS, this.ON, this.typeCondition, this.selectionSet); + this.ellipsisToken, this.onToken, this.typeCondition, this.selectionSet); + + /// Use [ellipsisToken] instead. + @deprecated + Token get ELLIPSIS => ellipsisToken; + + /// Use [onToken] instead. + @deprecated + Token get ON => onToken; @override FileSpan get span { - var out = ELLIPSIS.span.expand(ON.span).expand(typeCondition.span); + var out = + ellipsisToken.span.expand(onToken.span).expand(typeCondition.span); out = directives.fold(out, (o, d) => o.expand(d.span)); return out.expand(selectionSet.span); } From c9473420e10b8d39080348ef1d1686a8e0d9c101 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:54:01 -0400 Subject: [PATCH 43/69] comments: input_value --- graphql_parser/lib/src/language/ast/input_value.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/graphql_parser/lib/src/language/ast/input_value.dart b/graphql_parser/lib/src/language/ast/input_value.dart index 29e703ca..213eb5dd 100644 --- a/graphql_parser/lib/src/language/ast/input_value.dart +++ b/graphql_parser/lib/src/language/ast/input_value.dart @@ -1,5 +1,7 @@ import 'node.dart'; +/// Represents a value in GraphQL. abstract class InputValueContext extends Node { + /// Computes the value, relative to some set of [variables]. T computeValue(Map variables); } From c83c9e1fc3afc1386f1e610d403fc4bef30f01bd Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 22:57:27 -0400 Subject: [PATCH 44/69] ListType: pedantic + type->innerType --- .../lib/src/language/ast/list_type.dart | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/list_type.dart b/graphql_parser/lib/src/language/ast/list_type.dart index ea8ef20c..ee770e00 100644 --- a/graphql_parser/lib/src/language/ast/list_type.dart +++ b/graphql_parser/lib/src/language/ast/list_type.dart @@ -3,12 +3,29 @@ import 'node.dart'; import 'package:source_span/source_span.dart'; import 'type.dart'; +/// Represents a type that holds a list of another type. class ListTypeContext extends Node { - final Token LBRACKET, RBRACKET; - final TypeContext type; + /// The source tokens. + final Token lBracketToken, rBracketToken; - ListTypeContext(this.LBRACKET, this.type, this.RBRACKET); + /// The inner type. + final TypeContext innerType; + + ListTypeContext(this.lBracketToken, this.innerType, this.rBracketToken); + + /// Use [innerType] instead. + @deprecated + TypeContext get type => innerType; + + /// Use [lBracketToken] instead. + @deprecated + Token get LBRACKET => lBracketToken; + + /// Use [rBracketToken] instead. + @deprecated + Token get RBRACKET => rBracketToken; @override - FileSpan get span => LBRACKET.span.expand(type.span).expand(RBRACKET.span); + FileSpan get span => + lBracketToken.span.expand(innerType.span).expand(rBracketToken.span); } From 84080c4fe3a61f62bd398d4df352d4e418a8fdb8 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:01:54 -0400 Subject: [PATCH 45/69] pedantic: misc_value --- .../lib/src/language/ast/misc_value.dart | 71 ++++++++++++++----- graphql_parser/test/issue23_test.dart | 4 +- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/misc_value.dart b/graphql_parser/lib/src/language/ast/misc_value.dart index 0aa1facb..9307e4c1 100644 --- a/graphql_parser/lib/src/language/ast/misc_value.dart +++ b/graphql_parser/lib/src/language/ast/misc_value.dart @@ -3,46 +3,68 @@ import '../token.dart'; import 'input_value.dart'; import 'node.dart'; +/// A GraphQL `null` literal. class NullValueContext extends InputValueContext { - final Token NULL; + /// The source token. + final Token nullToken; - NullValueContext(this.NULL); + NullValueContext(this.nullToken); + + /// Use [nullToken] instead. + @deprecated + Token get NULL => nullToken; @override - FileSpan get span => NULL.span; + FileSpan get span => nullToken.span; @override Null computeValue(Map variables) => null; } +/// A GraphQL enumeration literal. class EnumValueContext extends InputValueContext { - final Token NAME; + /// The source token. + final Token nameToken; - EnumValueContext(this.NAME); + EnumValueContext(this.nameToken); + + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; @override - FileSpan get span => NAME.span; + FileSpan get span => nameToken.span; @override - String computeValue(Map variables) => NAME.span.text; + String computeValue(Map variables) => nameToken.span.text; } +/// A GraphQL object literal. class ObjectValueContext extends InputValueContext> { - final Token LBRACE; - final List fields; - final Token RBRACE; + /// The source tokens. + final Token lBraceToken, rBraceToken; - ObjectValueContext(this.LBRACE, this.fields, this.RBRACE); + /// The fields in the object. + final List fields; + + ObjectValueContext(this.lBraceToken, this.fields, this.rBraceToken); + + /// Use [lBraceToken] instead. + Token get LBRACE => lBraceToken; + + /// Use [rBraceToken] instead. + @deprecated + Token get RBRACE => rBraceToken; @override FileSpan get span { - var left = LBRACE.span; + var left = lBraceToken.span; for (var field in fields) { left = left.expand(field.span); } - return left.expand(RBRACE.span); + return left.expand(rBraceToken.span); } @override @@ -52,19 +74,32 @@ class ObjectValueContext extends InputValueContext> { } else { return fields.fold>({}, (map, field) { - return map..[field.NAME.text] = field.value.computeValue(variables); + return map + ..[field.nameToken.text] = field.value.computeValue(variables); }); } } } +/// A field within an [ObjectValueContext]. class ObjectFieldContext extends Node { - final Token NAME; - final Token COLON; + /// The source tokens. + final Token nameToken, colonToken; + + /// The associated value. final InputValueContext value; - ObjectFieldContext(this.NAME, this.COLON, this.value); + ObjectFieldContext(this.nameToken, this.colonToken, this.value); + + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; + + /// Use [colonToken] instead. + @deprecated + Token get COLON => colonToken; @override - FileSpan get span => NAME.span.expand(COLON.span).expand(value.span); + FileSpan get span => + nameToken.span.expand(colonToken.span).expand(value.span); } diff --git a/graphql_parser/test/issue23_test.dart b/graphql_parser/test/issue23_test.dart index aa64175b..6ab4950a 100644 --- a/graphql_parser/test/issue23_test.dart +++ b/graphql_parser/test/issue23_test.dart @@ -48,8 +48,8 @@ void main() { expect(condition.name, 'condition'); expect(condition.value, TypeMatcher()); var conditionValue = condition.value as ObjectValueContext; - var memberId = - conditionValue.fields.singleWhere((f) => f.NAME.text == 'memberId'); + var memberId = conditionValue.fields + .singleWhere((f) => f.nameToken.text == 'memberId'); expect(memberId.value, TypeMatcher()); print('Found \$memberId: Instance of $T'); }); From 4ec6077802c6d440405e3f7d2a38e753be524d4b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:02:03 -0400 Subject: [PATCH 46/69] Formatting --- graphql_parser/lib/src/language/ast/directive.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/directive.dart b/graphql_parser/lib/src/language/ast/directive.dart index 65a53c23..4e7200ed 100644 --- a/graphql_parser/lib/src/language/ast/directive.dart +++ b/graphql_parser/lib/src/language/ast/directive.dart @@ -28,19 +28,19 @@ class DirectiveContext extends Node { @deprecated Token get ARROBA => arrobaToken; -/// Use [nameToken] instead. + /// Use [nameToken] instead. @deprecated Token get NAME => nameToken; -/// Use [colonToken] instead. + /// Use [colonToken] instead. @deprecated Token get COLON => colonToken; -/// Use [lParenToken] instead. + /// Use [lParenToken] instead. @deprecated Token get LPAREN => lParenToken; -/// Use [rParenToken] instead. + /// Use [rParenToken] instead. @deprecated Token get RPAREN => rParenToken; From a43550c13f88cfe93a05cb171e46e94d3179ef30 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:04:48 -0400 Subject: [PATCH 47/69] pedantic: typecontext --- graphql_parser/lib/src/language/ast/type.dart | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/type.dart b/graphql_parser/lib/src/language/ast/type.dart index 48b4bcda..d82a97e3 100644 --- a/graphql_parser/lib/src/language/ast/type.dart +++ b/graphql_parser/lib/src/language/ast/type.dart @@ -4,20 +4,31 @@ import 'list_type.dart'; import 'node.dart'; import 'type_name.dart'; +/// A GraphQL type node. class TypeContext extends Node { - final Token EXCLAMATION; + /// A source token, present in a nullable type literal. + final Token exclamationToken; + + /// The name of the referenced type. final TypeNameContext typeName; + + /// A list type that is being referenced. final ListTypeContext listType; - bool get isNullable => EXCLAMATION == null; + /// Whether the type is nullable. + bool get isNullable => exclamationToken == null; - TypeContext(this.typeName, this.listType, [this.EXCLAMATION]) { + TypeContext(this.typeName, this.listType, [this.exclamationToken]) { assert(typeName != null || listType != null); } + /// Use [exclamationToken] instead. + @deprecated + Token get EXCLAMATION => exclamationToken; + @override FileSpan get span { var out = typeName?.span ?? listType.span; - return EXCLAMATION != null ? out.expand(EXCLAMATION.span) : out; + return exclamationToken != null ? out.expand(exclamationToken.span) : out; } } From 4048c634327510b447a5ffc41a48dba3eb36cd8b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:05:02 -0400 Subject: [PATCH 48/69] Fix type_test --- graphql_parser/test/type_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql_parser/test/type_test.dart b/graphql_parser/test/type_test.dart index 5ecb0030..93b017ca 100644 --- a/graphql_parser/test/type_test.dart +++ b/graphql_parser/test/type_test.dart @@ -72,7 +72,7 @@ class _IsListType extends Matcher { var type = item is TypeContext ? item : parseType(item.toString()); if (type.listType == null) return false; if (type.isNullable != (isNullable != false)) return false; - return innerType.matches(type.listType.type, matchState); + return innerType.matches(type.listType.innerType, matchState); } } From 5ef551e8df4b8a2e25a6d481b7f5f97f0ec88b52 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:06:23 -0400 Subject: [PATCH 49/69] pedantic: variable --- .../lib/src/language/ast/variable.dart | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/variable.dart b/graphql_parser/lib/src/language/ast/variable.dart index 96222aee..576734e4 100644 --- a/graphql_parser/lib/src/language/ast/variable.dart +++ b/graphql_parser/lib/src/language/ast/variable.dart @@ -2,17 +2,27 @@ import 'package:source_span/source_span.dart'; import '../token.dart'; import 'input_value.dart'; +/// A variable reference in GraphQL. class VariableContext extends InputValueContext { - final Token DOLLAR, NAME; + /// The source tokens. + final Token dollarToken, nameToken; - VariableContext(this.DOLLAR, this.NAME); + VariableContext(this.dollarToken, this.nameToken); - String get name => NAME.text; + /// The [String] value of the [nameToken]. + String get name => nameToken.text; + + /// Use [dollarToken] instead. + @deprecated + Token get DOLLAR => dollarToken; + + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; @override - FileSpan get span => DOLLAR.span.expand(NAME.span); + FileSpan get span => dollarToken.span.expand(nameToken.span); @override Object computeValue(Map variables) => variables[name]; - // FileSpan(DOLLAR?.span?.start, NAME?.span?.end, toSource()); } From a79f6c51c1ff0c1b29c3e40c9cf775c068716d3f Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:07:32 -0400 Subject: [PATCH 50/69] pedantic: number_value --- .../lib/src/language/ast/number_value.dart | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/number_value.dart b/graphql_parser/lib/src/language/ast/number_value.dart index d5fe010d..733bf0e4 100644 --- a/graphql_parser/lib/src/language/ast/number_value.dart +++ b/graphql_parser/lib/src/language/ast/number_value.dart @@ -3,13 +3,16 @@ import 'package:source_span/source_span.dart'; import '../token.dart'; import 'input_value.dart'; +/// A GraphQL number literal. class NumberValueContext extends InputValueContext { - final Token NUMBER; + /// The source token. + final Token numberToken; - NumberValueContext(this.NUMBER); + NumberValueContext(this.numberToken); + /// The [num] value of the [numberToken]. num get numberValue { - var text = NUMBER.text; + var text = numberToken.text; if (!text.contains('E') && !text.contains('e')) { return num.parse(text); } else { @@ -20,8 +23,12 @@ class NumberValueContext extends InputValueContext { } } + /// Use [numberToken] instead. + @deprecated + Token get NUMBER => numberToken; + @override - FileSpan get span => NUMBER.span; + FileSpan get span => numberToken.span; @override num computeValue(Map variables) => numberValue; From d15337714ee2ea7f081524bb6ff6be7e6a1f00ba Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:10:37 -0400 Subject: [PATCH 51/69] pedantic: op_def --- .../language/ast/operation_definition.dart | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/operation_definition.dart b/graphql_parser/lib/src/language/ast/operation_definition.dart index 06967ac7..d614fb6b 100644 --- a/graphql_parser/lib/src/language/ast/operation_definition.dart +++ b/graphql_parser/lib/src/language/ast/operation_definition.dart @@ -1,37 +1,58 @@ import 'package:source_span/source_span.dart'; - import '../token.dart'; import 'definition.dart'; import 'directive.dart'; import 'selection_set.dart'; import 'variable_definitions.dart'; +/// An executable GraphQL operation definition. class OperationDefinitionContext extends ExecutableDefinitionContext { - final Token TYPE, NAME; + /// The source tokens. + final Token typeToken, nameToken; + + /// The variables defined in the operation. final VariableDefinitionsContext variableDefinitions; + + /// Any directives affixed to this operation. final List directives = []; + + /// The selections to be applied to an object resolved in this operation. final SelectionSetContext selectionSet; - bool get isMutation => TYPE?.text == 'mutation'; + /// Whether this operation is a `mutation`. + bool get isMutation => typeToken?.text == 'mutation'; - bool get isSubscription => TYPE?.text == 'subscription'; + /// Whether this operation is a `subscription`. + bool get isSubscription => typeToken?.text == 'subscription'; - bool get isQuery => TYPE?.text == 'query' || TYPE == null; + /// Whether this operation is a `query`. + bool get isQuery => typeToken?.text == 'query' || typeToken == null; - String get name => NAME?.text; + /// The [String] value of the [nameToken]. + String get name => nameToken?.text; - OperationDefinitionContext( - this.TYPE, this.NAME, this.variableDefinitions, this.selectionSet) { - assert(TYPE == null || - TYPE.text == 'query' || - TYPE.text == 'mutation' || - TYPE.text == 'subscription'); + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; + + /// Use [typeToken] instead. + @deprecated + Token get TYPE => typeToken; + + OperationDefinitionContext(this.typeToken, this.nameToken, + this.variableDefinitions, this.selectionSet) { + assert(typeToken == null || + typeToken.text == 'query' || + typeToken.text == 'mutation' || + typeToken.text == 'subscription'); } @override FileSpan get span { - if (TYPE == null) return selectionSet.span; - var out = NAME == null ? TYPE.span : TYPE.span.expand(NAME.span); + if (typeToken == null) return selectionSet.span; + var out = nameToken == null + ? typeToken.span + : typeToken.span.expand(nameToken.span); out = directives.fold(out, (o, d) => o.expand(d.span)); return out.expand(selectionSet.span); } From 7f28d673e6950a6c40bba6464a26337a07a8d18e Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:14:51 -0400 Subject: [PATCH 52/69] pedantic: var defs --- .../language/ast/variable_definitions.dart | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/variable_definitions.dart b/graphql_parser/lib/src/language/ast/variable_definitions.dart index 852ee94e..fd1fbafd 100644 --- a/graphql_parser/lib/src/language/ast/variable_definitions.dart +++ b/graphql_parser/lib/src/language/ast/variable_definitions.dart @@ -3,16 +3,27 @@ import 'node.dart'; import 'package:source_span/source_span.dart'; import 'variable_definition.dart'; +/// A set of variable definitions in a GraphQL operation. class VariableDefinitionsContext extends Node { - final Token LPAREN, RPAREN; + final Token lParenToken, rParenToken; + + /// The variables defined in this node. final List variableDefinitions = []; - VariableDefinitionsContext(this.LPAREN, this.RPAREN); + VariableDefinitionsContext(this.lParenToken, this.rParenToken); + + /// Use [lParenToken] instead. + @deprecated + Token get LPAREN => lParenToken; + + /// Use [rParenToken] instead. + @deprecated + Token get RPAREN => rParenToken; @override FileSpan get span { var out = variableDefinitions.fold( - LPAREN.span, (o, v) => o.expand(v.span)); - return out.expand(RPAREN.span); + lParenToken.span, (o, v) => o.expand(v.span)); + return out.expand(rParenToken.span); } } From b245dde4fbcdd5f77e9e41282aff8f0ca0038256 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:17:05 -0400 Subject: [PATCH 53/69] pedantic: var def --- .../src/language/ast/variable_definition.dart | 16 ++++++++++++++-- .../src/language/ast/variable_definitions.dart | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/variable_definition.dart b/graphql_parser/lib/src/language/ast/variable_definition.dart index 9585bfd1..7432798a 100644 --- a/graphql_parser/lib/src/language/ast/variable_definition.dart +++ b/graphql_parser/lib/src/language/ast/variable_definition.dart @@ -5,15 +5,27 @@ import 'package:source_span/source_span.dart'; import 'type.dart'; import 'variable.dart'; +/// A single variable definition. class VariableDefinitionContext extends Node { - final Token COLON; + /// The source token. + final Token colonToken; + + /// The declared variable. final VariableContext variable; + + /// The type of the variable. final TypeContext type; + + /// The default value of the variable. final DefaultValueContext defaultValue; - VariableDefinitionContext(this.variable, this.COLON, this.type, + VariableDefinitionContext(this.variable, this.colonToken, this.type, [this.defaultValue]); + /// Use [colonToken] instead. + @deprecated + Token get COLON => colonToken; + @override FileSpan get span => variable.span.expand(defaultValue?.span ?? type.span); } diff --git a/graphql_parser/lib/src/language/ast/variable_definitions.dart b/graphql_parser/lib/src/language/ast/variable_definitions.dart index fd1fbafd..ddc4405f 100644 --- a/graphql_parser/lib/src/language/ast/variable_definitions.dart +++ b/graphql_parser/lib/src/language/ast/variable_definitions.dart @@ -5,6 +5,7 @@ import 'variable_definition.dart'; /// A set of variable definitions in a GraphQL operation. class VariableDefinitionsContext extends Node { + /// The source tokens. final Token lParenToken, rParenToken; /// The variables defined in this node. From cba6d7840d220fd6d7655d5cfffe83aaee6ced4c Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:18:14 -0400 Subject: [PATCH 54/69] pedantic: type_name --- .../lib/src/language/ast/type_name.dart | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/type_name.dart b/graphql_parser/lib/src/language/ast/type_name.dart index d7d9675a..209de19b 100644 --- a/graphql_parser/lib/src/language/ast/type_name.dart +++ b/graphql_parser/lib/src/language/ast/type_name.dart @@ -2,13 +2,20 @@ import 'node.dart'; import 'package:source_span/source_span.dart'; import '../token.dart'; +/// The name of a GraphQL type. class TypeNameContext extends Node { - final Token NAME; + /// The source token. + final Token nameToken; - String get name => NAME.text; + TypeNameContext(this.nameToken); + + /// Use [nameToken] instead. + @deprecated + Token get NAME => nameToken; + + /// The [String] value of the [nameToken]. + String get name => nameToken.text; @override - FileSpan get span => NAME.span; - - TypeNameContext(this.NAME); + FileSpan get span => nameToken.span; } From 0fb5e16565f0160f008d944371695fdb3853c8d2 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:19:31 -0400 Subject: [PATCH 55/69] pedantic: string_value --- .../lib/src/language/ast/string_value.dart | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/string_value.dart b/graphql_parser/lib/src/language/ast/string_value.dart index c6588f5b..29bc71af 100644 --- a/graphql_parser/lib/src/language/ast/string_value.dart +++ b/graphql_parser/lib/src/language/ast/string_value.dart @@ -5,22 +5,31 @@ import '../syntax_error.dart'; import '../token.dart'; import 'input_value.dart'; +/// A GraphQL string value literal. class StringValueContext extends InputValueContext { - final Token STRING; + /// The source token. + final Token stringToken; + + /// Whether this is a block string. final bool isBlockString; - StringValueContext(this.STRING, {this.isBlockString = false}); + StringValueContext(this.stringToken, {this.isBlockString = false}); @override - FileSpan get span => STRING.span; + FileSpan get span => stringToken.span; + /// Use [stringToken] instead. + @deprecated + Token get STRING => stringToken; + + /// The [String] value of the [stringToken]. String get stringValue { String text; if (!isBlockString) { - text = STRING.text.substring(1, STRING.text.length - 1); + text = stringToken.text.substring(1, stringToken.text.length - 1); } else { - text = STRING.text.substring(3, STRING.text.length - 3).trim(); + text = stringToken.text.substring(3, stringToken.text.length - 3).trim(); } var codeUnits = text.codeUnits; From 9f28e73483b5c9445e3221457f0349d0cf1404df Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 7 Aug 2019 23:21:09 -0400 Subject: [PATCH 56/69] pedantic: done (graphql_parser) --- .../lib/src/language/ast/selection_set.dart | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/graphql_parser/lib/src/language/ast/selection_set.dart b/graphql_parser/lib/src/language/ast/selection_set.dart index 36453c67..4097d94e 100644 --- a/graphql_parser/lib/src/language/ast/selection_set.dart +++ b/graphql_parser/lib/src/language/ast/selection_set.dart @@ -4,20 +4,33 @@ import '../token.dart'; import 'node.dart'; import 'selection.dart'; +/// A set of GraphQL selections - fields, fragments, or inline fragments. class SelectionSetContext extends Node { - final Token LBRACE, RBRACE; + /// The source tokens. + final Token lBraceToken, rBraceToken; + + /// The selections to be applied. final List selections = []; - SelectionSetContext(this.LBRACE, this.RBRACE); + SelectionSetContext(this.lBraceToken, this.rBraceToken); + /// A synthetic [SelectionSetContext] produced from a set of [selections]. factory SelectionSetContext.merged(List selections) = _MergedSelectionSetContext; + /// Use [lBraceToken] instead. + @deprecated + Token get LBRACE => lBraceToken; + + /// Use [rBraceToken] instead. + @deprecated + Token get RBRACE => rBraceToken; + @override FileSpan get span { - var out = - selections.fold(LBRACE.span, (out, s) => out.expand(s.span)); - return out.expand(RBRACE.span); + var out = selections.fold( + lBraceToken.span, (out, s) => out.expand(s.span)); + return out.expand(rBraceToken.span); } } From fa0e957788b89e1e336da3cc3b9213b44e8bce87 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 13 Aug 2019 22:44:04 -0400 Subject: [PATCH 57/69] Experimental implement of file upload spec --- angel_graphql/lib/src/graphql_http.dart | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/angel_graphql/lib/src/graphql_http.dart b/angel_graphql/lib/src/graphql_http.dart index 61e11305..b2c20bd0 100644 --- a/angel_graphql/lib/src/graphql_http.dart +++ b/angel_graphql/lib/src/graphql_http.dart @@ -16,6 +16,8 @@ final Validator graphQlPostBody = new Validator({ 'variables': predicate((v) => v == null || v is String || v is Map), }); +final RegExp _num = RegExp(r'^[0-9]+$'); + /// A [RequestHandler] that serves a spec-compliant GraphQL backend. /// /// Follows the guidelines listed here: @@ -80,6 +82,35 @@ RequestHandler graphQLHttp(GraphQL graphQL, if (await validate(graphQlPostBody)(req, res) as bool) { return await executeMap(req.bodyAsMap); } + } else if (req.headers.contentType?.mimeType == 'multipart/form-data') { + // TODO: Support file uploads in batch requests. + var fields = await req.parseBody().then((_) => req.bodyAsMap); + var operations = fields['operations'] as String; + var map = fields.containsKey('map') + ? json.decode(fields['map'] as String) + : null; + var variables = Map.from(globalVariables); + for (var entry in (map as Map).entries) { + var key = int.parse(entry.key as String); + var objectPaths = entry.value as List; + for (var objectPath in objectPaths) { + var subPaths = (objectPath as String).split('.'); + if (subPaths[0] == 'variables') { + var current = variables; + for (int i = 0; i < subPaths.length; i++) { + var name = subPaths[0]; + if (_num.hasMatch(name)) { + (current as List)[int.parse(name)] = req.uploadedFiles[key]; + } + } + } + } + } + return await sendGraphQLResponse(await graphQL.parseAndExecute( + operations, + sourceUrl: 'input', + globalVariables: variables, + )); } else { throw new AngelHttpException.badRequest(); } From 36ab0cdb2a566c921a81c9e854f79ba682497139 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 13 Aug 2019 22:50:04 -0400 Subject: [PATCH 58/69] Create graphQLUpload schema type --- angel_graphql/lib/angel_graphql.dart | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/angel_graphql/lib/angel_graphql.dart b/angel_graphql/lib/angel_graphql.dart index 7673a86e..780cc100 100644 --- a/angel_graphql/lib/angel_graphql.dart +++ b/angel_graphql/lib/angel_graphql.dart @@ -1,4 +1,46 @@ +import 'package:angel_framework/angel_framework.dart'; +import 'package:graphql_schema/graphql_schema.dart'; export 'src/graphiql.dart'; export 'src/graphql_http.dart'; export 'src/graphql_ws.dart'; export 'src/resolvers.dart'; + +/// The canonical [GraphQLUploadType] instance. +final GraphQLUploadType graphQLUpload = GraphQLUploadType(); + +/// A [GraphQLScalarType] that is used to read uploaded files from +/// `multipart/form-data` requests. +class GraphQLUploadType extends GraphQLScalarType { + @override + String get name => 'Upload'; + + @override + String get description => + 'Represents a file that has been uploaded to the server.'; + + @override + GraphQLType coerceToInputObject() => this; + + @override + UploadedFile deserialize(UploadedFile serialized) => serialized; + + @override + UploadedFile serialize(UploadedFile value) => value; + + @override + ValidationResult validate(String key, UploadedFile input) { + if (input != null && input is! UploadedFile) { + return _Vr(false, errors: ['Expected "$key" to be a boolean.']); + } + return _Vr(true, value: input); + } +} + +// TODO: Really need to make the validation result constructors *public* +class _Vr implements ValidationResult { + final bool successful; + final List errors; + final T value; + + _Vr(this.successful, {this.errors, this.value}); +} From b2fe33f0adb9cc99314f2dbafc6403716424b50e Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 13 Aug 2019 22:55:46 -0400 Subject: [PATCH 59/69] Add validation --- angel_graphql/lib/src/graphql_http.dart | 39 ++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/angel_graphql/lib/src/graphql_http.dart b/angel_graphql/lib/src/graphql_http.dart index b2c20bd0..6ee80a83 100644 --- a/angel_graphql/lib/src/graphql_http.dart +++ b/angel_graphql/lib/src/graphql_http.dart @@ -86,23 +86,60 @@ RequestHandler graphQLHttp(GraphQL graphQL, // TODO: Support file uploads in batch requests. var fields = await req.parseBody().then((_) => req.bodyAsMap); var operations = fields['operations'] as String; + if (operations == null) { + throw AngelHttpException.badRequest( + message: 'Missing "operations" field.'); + } var map = fields.containsKey('map') ? json.decode(fields['map'] as String) : null; + if (map is! Map) { + throw AngelHttpException.badRequest( + message: '"map" field must decode to a JSON object.'); + } var variables = Map.from(globalVariables); for (var entry in (map as Map).entries) { var key = int.parse(entry.key as String); + if (req.uploadedFiles.length < key) { + throw AngelHttpException.badRequest( + message: + '"map" contained key "$key", but the number of uploaded files was ${req.uploadedFiles.length}.'); + } + if (entry.value is! List) { + throw AngelHttpException.badRequest( + message: + 'The value for "$key" in the "map" field was not a JSON array.'); + } var objectPaths = entry.value as List; for (var objectPath in objectPaths) { var subPaths = (objectPath as String).split('.'); if (subPaths[0] == 'variables') { - var current = variables; + Object current = variables; for (int i = 0; i < subPaths.length; i++) { var name = subPaths[0]; + var parent = subPaths.take(i).join('.'); if (_num.hasMatch(name)) { + if (current is! List) { + throw AngelHttpException.badRequest( + message: + 'Object "$parent" is not a JSON array, but the ' + '"map" field contained a mapping to $parent.$name.'); + } (current as List)[int.parse(name)] = req.uploadedFiles[key]; + } else { + if (current is! Map) { + throw AngelHttpException.badRequest( + message: + 'Object "$parent" is not a JSON object, but the ' + '"map" field contained a mapping to $parent.$name.'); + } + (current as Map)[name] = req.uploadedFiles[key]; } } + } else { + throw AngelHttpException.badRequest( + message: + 'All array values in the "map" field must begin with "variables.".'); } } } From 9fd290ca683cb7a2f9289d87d0f0f65e3f3e13b2 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 13 Aug 2019 22:58:15 -0400 Subject: [PATCH 60/69] Use name instead of parsed int index --- angel_graphql/lib/src/graphql_http.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/angel_graphql/lib/src/graphql_http.dart b/angel_graphql/lib/src/graphql_http.dart index 6ee80a83..5f71a031 100644 --- a/angel_graphql/lib/src/graphql_http.dart +++ b/angel_graphql/lib/src/graphql_http.dart @@ -99,16 +99,18 @@ RequestHandler graphQLHttp(GraphQL graphQL, } var variables = Map.from(globalVariables); for (var entry in (map as Map).entries) { - var key = int.parse(entry.key as String); - if (req.uploadedFiles.length < key) { + var file = req.uploadedFiles + .firstWhere((f) => f.name == entry.key, orElse: () => null); + if (file == null) { throw AngelHttpException.badRequest( message: - '"map" contained key "$key", but the number of uploaded files was ${req.uploadedFiles.length}.'); + '"map" contained key "${entry.key}", but no uploaded file ' + 'has that name.'); } if (entry.value is! List) { throw AngelHttpException.badRequest( message: - 'The value for "$key" in the "map" field was not a JSON array.'); + 'The value for "${entry.key}" in the "map" field was not a JSON array.'); } var objectPaths = entry.value as List; for (var objectPath in objectPaths) { @@ -125,7 +127,7 @@ RequestHandler graphQLHttp(GraphQL graphQL, 'Object "$parent" is not a JSON array, but the ' '"map" field contained a mapping to $parent.$name.'); } - (current as List)[int.parse(name)] = req.uploadedFiles[key]; + (current as List)[int.parse(name)] = file; } else { if (current is! Map) { throw AngelHttpException.badRequest( @@ -133,7 +135,7 @@ RequestHandler graphQLHttp(GraphQL graphQL, 'Object "$parent" is not a JSON object, but the ' '"map" field contained a mapping to $parent.$name.'); } - (current as Map)[name] = req.uploadedFiles[key]; + (current as Map)[name] = file; } } } else { From 02a816f5dd2e8b0ffb5b9b8762d3b9b34cbc95ad Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 10:51:11 -0400 Subject: [PATCH 61/69] Update graphql_server deps + version --- graphql_server/pubspec.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/graphql_server/pubspec.yaml b/graphql_server/pubspec.yaml index 09081d32..206a6476 100644 --- a/graphql_server/pubspec.yaml +++ b/graphql_server/pubspec.yaml @@ -1,5 +1,5 @@ name: graphql_server -version: 1.0.1 +version: 1.1.0 author: Tobe O description: Base package for implementing GraphQL servers. You might prefer `package:angel_graphql`, the fastest way to implement GraphQL backends in Dart. homepage: https://github.com/angel-dart/graphql @@ -16,4 +16,7 @@ dependencies: tuple: ^1.0.0 dev_dependencies: pedantic: ^1.0.0 - test: ">=0.12.0 <2.0.0" \ No newline at end of file + test: ">=0.12.0 <2.0.0" +dependency_overrides: + graphql_parser: + path: ../graphql_parser \ No newline at end of file From 917477cb890af6de927ab30e28acd17a21b0ee6b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 10:59:18 -0400 Subject: [PATCH 62/69] Remove use of deprecated value members --- graphql_server/lib/graphql_server.dart | 55 ++++++++++++++------------ graphql_server/lib/introspection.dart | 2 +- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/graphql_server/lib/graphql_server.dart b/graphql_server/lib/graphql_server.dart index 796422af..09336492 100644 --- a/graphql_server/lib/graphql_server.dart +++ b/graphql_server/lib/graphql_server.dart @@ -55,7 +55,7 @@ class GraphQL { GraphQLType convertType(TypeContext ctx) { if (ctx.listType != null) { - return GraphQLListType(convertType(ctx.listType.type)); + return GraphQLListType(convertType(ctx.listType.innerType)); } else if (ctx.typeName != null) { switch (ctx.typeName.name) { case 'Int': @@ -161,7 +161,8 @@ class GraphQL { if (value == null) { if (defaultValue != null) { - coercedValues[variableName] = defaultValue.value.value; + coercedValues[variableName] = + defaultValue.value.computeValue(variableValues); } else if (!variableType.isNullable) { throw GraphQLException.fromSourceSpan( 'Missing required variable "$variableName".', @@ -400,11 +401,11 @@ class GraphQL { var argumentType = argumentDefinition.type; var defaultValue = argumentDefinition.defaultValue; - var value = argumentValues.firstWhere((a) => a.name == argumentName, - orElse: () => null); + var argumentValue = argumentValues + .firstWhere((a) => a.name == argumentName, orElse: () => null); - if (value?.valueOrVariable?.variable != null) { - var variableName = value.valueOrVariable.variable.name; + if (argumentValue.value is VariableContext) { + var variableName = (argumentValue.value as VariableContext).name; var variableValue = variableValues[variableName]; if (variableValues.containsKey(variableName)) { @@ -414,11 +415,11 @@ class GraphQL { } else if (argumentType is GraphQLNonNullableType) { throw GraphQLException.fromSourceSpan( 'Missing value for argument "$argumentName" of field "$fieldName".', - value.valueOrVariable.span); + argumentValue.value.span); } else { continue; } - } else if (value == null) { + } else if (argumentValue == null) { if (defaultValue != null || argumentDefinition.defaultsToNull) { coercedValues[argumentName] = defaultValue; } else if (argumentType is GraphQLNonNullableType) { @@ -430,7 +431,7 @@ class GraphQL { } else { try { var validation = argumentType.validate( - fieldName, value.valueOrVariable.value.value); + fieldName, argumentValue.value.computeValue(variableValues)); if (!validation.successful) { var errors = [ @@ -438,7 +439,7 @@ class GraphQL { 'Type coercion error for value of argument "$argumentName" of field "$fieldName".', locations: [ GraphExceptionErrorLocation.fromSourceLocation( - value.valueOrVariable.span.start) + argumentValue.value.span.start) ], ) ]; @@ -449,7 +450,7 @@ class GraphQL { error, locations: [ GraphExceptionErrorLocation.fromSourceLocation( - value.valueOrVariable.span.start) + argumentValue.value.span.start) ], ), ); @@ -466,14 +467,14 @@ class GraphQL { 'Type coercion error for value of argument "$argumentName" of field "$fieldName".', locations: [ GraphExceptionErrorLocation.fromSourceLocation( - value.valueOrVariable.span.start) + argumentValue.value.span.start) ], ), GraphQLExceptionError( e.message.toString(), locations: [ GraphExceptionErrorLocation.fromSourceLocation( - value.valueOrVariable.span.start) + argumentValue.value.span.start) ], ), ]); @@ -699,25 +700,27 @@ class GraphQL { SelectionContext selection, Map variableValues) { if (selection.field == null) return null; var directive = selection.field.directives.firstWhere((d) { - var vv = d.valueOrVariable; - if (vv.value != null) return vv.value.value == name; - return vv.variable.name == name; + var vv = d.value; + if (vv is VariableContext) { + return vv.name == name; + } else { + return vv.computeValue(variableValues) == name; + } }, orElse: () => null); if (directive == null) return null; if (directive.argument?.name != argumentName) return null; - var vv = directive.argument.valueOrVariable; - - if (vv.value != null) return vv.value.value; - - var vname = vv.variable.name; - if (!variableValues.containsKey(vname)) { - throw GraphQLException.fromSourceSpan( - 'Unknown variable: "$vname"', vv.span); + var vv = directive.argument.value; + if (vv is VariableContext) { + var vname = vv.name; + if (!variableValues.containsKey(vname)) { + throw GraphQLException.fromSourceSpan( + 'Unknown variable: "$vname"', vv.span); + } + return variableValues[vname]; } - - return variableValues[vname]; + return vv.computeValue(variableValues); } bool doesFragmentTypeApply( diff --git a/graphql_server/lib/introspection.dart b/graphql_server/lib/introspection.dart index 8ccd68da..47604f61 100644 --- a/graphql_server/lib/introspection.dart +++ b/graphql_server/lib/introspection.dart @@ -382,7 +382,7 @@ GraphQLObjectType _reflectDirectiveType() { field( 'name', graphQLString.nonNullable(), - resolve: (obj, _) => (obj as DirectiveContext).NAME.span.text, + resolve: (obj, _) => (obj as DirectiveContext).nameToken.span.text, ), field( 'description', From 2ca155375b6fe1659de238148e164c136c95fad5 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 11:03:57 -0400 Subject: [PATCH 63/69] Null check on argumentValue in coerceArgumentValues --- graphql_server/lib/graphql_server.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql_server/lib/graphql_server.dart b/graphql_server/lib/graphql_server.dart index 09336492..6966bd47 100644 --- a/graphql_server/lib/graphql_server.dart +++ b/graphql_server/lib/graphql_server.dart @@ -404,7 +404,7 @@ class GraphQL { var argumentValue = argumentValues .firstWhere((a) => a.name == argumentName, orElse: () => null); - if (argumentValue.value is VariableContext) { + if (argumentValue?.value is VariableContext) { var variableName = (argumentValue.value as VariableContext).name; var variableValue = variableValues[variableName]; From 4e7972ca5cb47e3bddb71bcd7e5ed8cdf6bd4682 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 11:58:19 -0400 Subject: [PATCH 64/69] coerce variable values the same as other values --- graphql_server/CHANGELOG.md | 6 ++++++ graphql_server/lib/graphql_server.dart | 17 +---------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/graphql_server/CHANGELOG.md b/graphql_server/CHANGELOG.md index 25c38458..f6a1d166 100644 --- a/graphql_server/CHANGELOG.md +++ b/graphql_server/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.1.0 +* Updates for `package:graphql_parser@1.2.0`. +* Now that variables are `InputValueContext` descendants, handle them the +same way as other values in `coerceArgumentValues`. TLDR - Removed +now-obsolete, variable-specific logic in `coerceArgumentValues`. + # 1.0.1 * Fix a bug where `globalVariables` were not being properly passed to field resolvers. diff --git a/graphql_server/lib/graphql_server.dart b/graphql_server/lib/graphql_server.dart index 6966bd47..2ff007ff 100644 --- a/graphql_server/lib/graphql_server.dart +++ b/graphql_server/lib/graphql_server.dart @@ -404,22 +404,7 @@ class GraphQL { var argumentValue = argumentValues .firstWhere((a) => a.name == argumentName, orElse: () => null); - if (argumentValue?.value is VariableContext) { - var variableName = (argumentValue.value as VariableContext).name; - var variableValue = variableValues[variableName]; - - if (variableValues.containsKey(variableName)) { - coercedValues[argumentName] = variableValue; - } else if (defaultValue != null || argumentDefinition.defaultsToNull) { - coercedValues[argumentName] = defaultValue; - } else if (argumentType is GraphQLNonNullableType) { - throw GraphQLException.fromSourceSpan( - 'Missing value for argument "$argumentName" of field "$fieldName".', - argumentValue.value.span); - } else { - continue; - } - } else if (argumentValue == null) { + if (argumentValue == null) { if (defaultValue != null || argumentDefinition.defaultsToNull) { coercedValues[argumentName] = defaultValue; } else if (argumentType is GraphQLNonNullableType) { From 899fe0fe54ddbaceb574c0c03f33eed841624a04 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 12:02:51 -0400 Subject: [PATCH 65/69] Pedantic fixes in angel_graphql --- angel_graphql/README.md | 8 +++---- angel_graphql/lib/src/graphiql.dart | 4 ++-- angel_graphql/lib/src/graphql_http.dart | 31 ++++++++++--------------- angel_graphql/lib/src/graphql_ws.dart | 5 ++-- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/angel_graphql/README.md b/angel_graphql/README.md index 74683163..bbb1f67c 100644 --- a/angel_graphql/README.md +++ b/angel_graphql/README.md @@ -74,7 +74,7 @@ Future configureServer(Angel app) async { convertDartType(Todo), resolve: resolveViaServiceRead(todoService), inputs: [ - new GraphQLFieldInput('id', graphQLId.nonNullable()), + GraphQLFieldInput('id', graphQLId.nonNullable()), ], ), ], @@ -107,7 +107,7 @@ In *development*, it's also highly recommended to mount the interface, for easy querying and feedback. ```dart -app.all('/graphql', graphQLHttp(new GraphQL(schema))); +app.all('/graphql', graphQLHttp(GraphQL(schema))); app.get('/graphiql', graphiQL()); ``` @@ -116,7 +116,7 @@ All that's left now is just to start the server! ```dart var server = await http.startServer('127.0.0.1', 3000); var uri = - new Uri(scheme: 'http', host: server.address.address, port: server.port); + Uri(scheme: 'http', host: server.address.address, port: server.port); var graphiqlUri = uri.replace(path: 'graphiql'); print('Listening at $uri'); print('Access graphiql at $graphiqlUri'); @@ -214,7 +214,7 @@ var queryType = objectType( convertDartType(Todo), resolve: resolveViaServiceRead(todoService), inputs: [ - new GraphQLFieldInput('id', graphQLId.nonNullable()), + GraphQLFieldInput('id', graphQLId.nonNullable()), ], ), ], diff --git a/angel_graphql/lib/src/graphiql.dart b/angel_graphql/lib/src/graphiql.dart index 6483a768..d64b8b4d 100644 --- a/angel_graphql/lib/src/graphiql.dart +++ b/angel_graphql/lib/src/graphiql.dart @@ -9,7 +9,7 @@ RequestHandler graphiQL( {String graphQLEndpoint = '/graphql', String subscriptionsEndpoint}) { return (req, res) { res - ..contentType = new MediaType('text', 'html') + ..contentType = MediaType('text', 'html') ..write(renderGraphiql( graphqlEndpoint: graphQLEndpoint, subscriptionsEndpoint: subscriptionsEndpoint)) @@ -30,7 +30,7 @@ String renderGraphiql( '''; subscriptionsFetcher = ''' - let subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient('$subscriptionsEndpoint', { + let subscriptionsClient = window.SubscriptionsTransportWs.SubscriptionClient('$subscriptionsEndpoint', { reconnect: true }); let $fetcherName = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLFetcher); diff --git a/angel_graphql/lib/src/graphql_http.dart b/angel_graphql/lib/src/graphql_http.dart index 5f71a031..59f787d2 100644 --- a/angel_graphql/lib/src/graphql_http.dart +++ b/angel_graphql/lib/src/graphql_http.dart @@ -7,10 +7,9 @@ import 'package:graphql_parser/graphql_parser.dart'; import 'package:graphql_schema/graphql_schema.dart'; import 'package:graphql_server/graphql_server.dart'; -final ContentType graphQlContentType = - new ContentType('application', 'graphql'); +final ContentType graphQlContentType = ContentType('application', 'graphql'); -final Validator graphQlPostBody = new Validator({ +final Validator graphQlPostBody = Validator({ 'query*': isNonEmptyString, 'operation_name': isNonEmptyString, 'variables': predicate((v) => v == null || v is String || v is Map), @@ -151,29 +150,23 @@ RequestHandler graphQLHttp(GraphQL graphQL, globalVariables: variables, )); } else { - throw new AngelHttpException.badRequest(); + throw AngelHttpException.badRequest(); } } else { - throw new AngelHttpException.badRequest(); + throw AngelHttpException.badRequest(); } } on ValidationException catch (e) { - var errors = [ - new GraphQLExceptionError(e.message) - ]; + var errors = [GraphQLExceptionError(e.message)]; - errors - .addAll(e.errors.map((ee) => new GraphQLExceptionError(ee)).toList()); - return new GraphQLException(errors).toJson(); + errors.addAll(e.errors.map((ee) => GraphQLExceptionError(ee)).toList()); + return GraphQLException(errors).toJson(); } on AngelHttpException catch (e) { - var errors = [ - new GraphQLExceptionError(e.message) - ]; + var errors = [GraphQLExceptionError(e.message)]; - errors - .addAll(e.errors.map((ee) => new GraphQLExceptionError(ee)).toList()); - return new GraphQLException(errors).toJson(); + errors.addAll(e.errors.map((ee) => GraphQLExceptionError(ee)).toList()); + return GraphQLException(errors).toJson(); } on SyntaxError catch (e) { - return new GraphQLException.fromSourceSpan(e.message, e.span); + return GraphQLException.fromSourceSpan(e.message, e.span); } on GraphQLException catch (e) { return e.toJson(); } catch (e, st) { @@ -184,7 +177,7 @@ RequestHandler graphQLHttp(GraphQL graphQL, st); } - return new GraphQLException.fromMessage(e.toString()).toJson(); + return GraphQLException.fromMessage(e.toString()).toJson(); } }; } diff --git a/angel_graphql/lib/src/graphql_ws.dart b/angel_graphql/lib/src/graphql_ws.dart index 0698b65c..89201468 100644 --- a/angel_graphql/lib/src/graphql_ws.dart +++ b/angel_graphql/lib/src/graphql_ws.dart @@ -22,11 +22,12 @@ RequestHandler graphQLWS(GraphQL graphQL, {Duration keepAliveInterval}) { await res.detach(); var socket = await WebSocketTransformer.upgrade(req.rawRequest, protocolSelector: (protocols) { - if (protocols.contains('graphql-ws')) + if (protocols.contains('graphql-ws')) { return 'graphql-ws'; - else + } else { throw AngelHttpException.badRequest( message: 'Only the "graphql-ws" protocol is allowed.'); + } }); var channel = IOWebSocketChannel(socket); var client = stw.RemoteClient(channel.cast()); From 34cf2065fba665785a294010a6fc793489ec871a Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 12:04:57 -0400 Subject: [PATCH 66/69] Pass variables in graphQLWS (fix #26) --- angel_graphql/lib/src/graphql_ws.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/angel_graphql/lib/src/graphql_ws.dart b/angel_graphql/lib/src/graphql_ws.dart index 89201468..29f8ba2d 100644 --- a/angel_graphql/lib/src/graphql_ws.dart +++ b/angel_graphql/lib/src/graphql_ws.dart @@ -70,6 +70,7 @@ class _GraphQLWSServer extends stw.Server { operationName: operationName, sourceUrl: 'input', globalVariables: globalVariables, + variableValues: variables, ); return stw.GraphQLResult(data); } on GraphQLException catch (e) { From 2bf39a81e151918f0af0161c414785454da30254 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 12:07:45 -0400 Subject: [PATCH 67/69] Pass `argumentName`, not `fieldName`, to type validations. --- graphql_server/CHANGELOG.md | 1 + graphql_server/lib/graphql_server.dart | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/graphql_server/CHANGELOG.md b/graphql_server/CHANGELOG.md index f6a1d166..b8d17ebc 100644 --- a/graphql_server/CHANGELOG.md +++ b/graphql_server/CHANGELOG.md @@ -3,6 +3,7 @@ * Now that variables are `InputValueContext` descendants, handle them the same way as other values in `coerceArgumentValues`. TLDR - Removed now-obsolete, variable-specific logic in `coerceArgumentValues`. +* Pass `argumentName`, not `fieldName`, to type validations. # 1.0.1 * Fix a bug where `globalVariables` were not being properly passed diff --git a/graphql_server/lib/graphql_server.dart b/graphql_server/lib/graphql_server.dart index 2ff007ff..b8355dae 100644 --- a/graphql_server/lib/graphql_server.dart +++ b/graphql_server/lib/graphql_server.dart @@ -416,7 +416,7 @@ class GraphQL { } else { try { var validation = argumentType.validate( - fieldName, argumentValue.value.computeValue(variableValues)); + argumentName, argumentValue.value.computeValue(variableValues)); if (!validation.successful) { var errors = [ From d92df27c8abcba711a135f979005dbf66a9f6dbc Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 12:14:25 -0400 Subject: [PATCH 68/69] Fix iteration on object paths --- angel_graphql/lib/src/graphql_http.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/angel_graphql/lib/src/graphql_http.dart b/angel_graphql/lib/src/graphql_http.dart index 59f787d2..4607b3f9 100644 --- a/angel_graphql/lib/src/graphql_http.dart +++ b/angel_graphql/lib/src/graphql_http.dart @@ -116,8 +116,8 @@ RequestHandler graphQLHttp(GraphQL graphQL, var subPaths = (objectPath as String).split('.'); if (subPaths[0] == 'variables') { Object current = variables; - for (int i = 0; i < subPaths.length; i++) { - var name = subPaths[0]; + for (int i = 1; i < subPaths.length; i++) { + var name = subPaths[i]; var parent = subPaths.take(i).join('.'); if (_num.hasMatch(name)) { if (current is! List) { From 4249b80f9f4233a86aa5c87f98385cf5174afb15 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 14 Aug 2019 12:14:28 -0400 Subject: [PATCH 69/69] CHANGELOG --- angel_graphql/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/angel_graphql/CHANGELOG.md b/angel_graphql/CHANGELOG.md index c26a73cd..faaed134 100644 --- a/angel_graphql/CHANGELOG.md +++ b/angel_graphql/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.1.0 +* Support the GraphQL multipart spec: https://github.com/jaydenseric/graphql-multipart-request-spec + # 1.0.0 * Apply `package:pedantic`.