Fix Dart 1 error
This commit is contained in:
parent
2691ecf6ee
commit
6e8189fc6e
34 changed files with 163 additions and 157 deletions
|
@ -1,6 +1,7 @@
|
|||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../token.dart';
|
||||
import 'node.dart';
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
class AliasContext extends Node {
|
||||
final Token NAME1, COLON, NAME2;
|
||||
|
@ -15,7 +16,4 @@ class AliasContext extends Node {
|
|||
|
||||
@override
|
||||
FileSpan get span => NAME1.span.expand(COLON.span).expand(NAME2.span);
|
||||
|
||||
@override
|
||||
String toSource() => '${NAME1.text}:${NAME2.text}';
|
||||
}
|
||||
|
|
|
@ -14,7 +14,4 @@ class ArgumentContext extends Node {
|
|||
@override
|
||||
FileSpan get span =>
|
||||
NAME.span.expand(COLON.span).expand(valueOrVariable.span);
|
||||
|
||||
@override
|
||||
String toSource() => '${NAME.text}:${valueOrVariable.toSource()}';
|
||||
}
|
||||
|
|
|
@ -16,16 +16,4 @@ class ArrayValueContext extends ValueContext {
|
|||
|
||||
@override
|
||||
List get value => values.map((v) => v.value).toList();
|
||||
|
||||
@override
|
||||
String toSource() {
|
||||
var buf = new StringBuffer('[');
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i > 0) buf.write(',');
|
||||
buf.write(values[i].toSource());
|
||||
}
|
||||
|
||||
return buf.toString() + ']';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,4 @@ class BooleanValueContext extends ValueContext {
|
|||
|
||||
@override
|
||||
FileSpan get span => BOOLEAN.span;
|
||||
|
||||
@override
|
||||
String toSource() => BOOLEAN.text;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,4 @@ class DefaultValueContext extends Node {
|
|||
|
||||
@override
|
||||
FileSpan get span => EQUALS.span.expand(value.span);
|
||||
|
||||
@override
|
||||
String toSource() => '=${value.toSource()}';
|
||||
}
|
||||
|
|
|
@ -26,14 +26,4 @@ class DirectiveContext extends Node {
|
|||
|
||||
return out;
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() {
|
||||
if (valueOrVariable != null)
|
||||
return '@${NAME.text}:${valueOrVariable.toSource()}';
|
||||
else if (argument != null)
|
||||
return '@${NAME.text}(${argument.toSource()})';
|
||||
else
|
||||
return '@${NAME.text}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,4 @@ class DocumentContext extends Node {
|
|||
.map<FileSpan>((d) => d.span)
|
||||
.reduce((a, b) => a.expand(b));
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() {
|
||||
if (definitions.isEmpty) return '(empty document)';
|
||||
return definitions.map((d) => d.toSource()).join();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,4 @@ class FieldContext extends Node {
|
|||
else
|
||||
return fieldName.span;
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() => span.text;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,4 @@ class FieldNameContext extends Node {
|
|||
|
||||
@override
|
||||
FileSpan get span => alias?.span ?? NAME.span;
|
||||
|
||||
@override
|
||||
String toSource() => alias?.toSource() ?? NAME.text;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,4 @@ class FragmentDefinitionContext extends DefinitionContext {
|
|||
out = directives.fold<FileSpan>(out, (o, d) => o.expand(d.span));
|
||||
return out.expand(selectionSet.span);
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() =>
|
||||
'fragment ${NAME.text} on ' +
|
||||
typeCondition.toSource() +
|
||||
directives.map((d) => d.toSource()).join() +
|
||||
selectionSet.toSource();
|
||||
}
|
||||
|
|
|
@ -17,9 +17,4 @@ class FragmentSpreadContext extends Node {
|
|||
if (directives.isEmpty) return out;
|
||||
return directives.fold<FileSpan>(out, (o, d) => o.expand(d.span));
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() {
|
||||
return '...${NAME.text}' + directives.map((d) => d.toSource()).join();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,4 @@ class InlineFragmentContext extends Node {
|
|||
out = directives.fold<FileSpan>(out, (o, d) => o.expand(d.span));
|
||||
return out.expand(selectionSet.span);
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() =>
|
||||
'...on${typeCondition.toSource()}' +
|
||||
directives.map((d) => d.toSource()).join() +
|
||||
selectionSet.toSource();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,4 @@ class ListTypeContext extends Node {
|
|||
|
||||
@override
|
||||
FileSpan get span => LBRACKET.span.expand(type.span).expand(RBRACKET.span);
|
||||
|
||||
@override
|
||||
String toSource() => '[${type.toSource()}]';
|
||||
}
|
||||
|
|
|
@ -2,9 +2,4 @@ import 'package:source_span/source_span.dart';
|
|||
|
||||
abstract class Node {
|
||||
FileSpan get span;
|
||||
|
||||
SourceLocation get start => span.start;
|
||||
SourceLocation get end => span.end;
|
||||
|
||||
String toSource();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,4 @@ class NumberValueContext extends ValueContext {
|
|||
|
||||
@override
|
||||
FileSpan get span => NUMBER.span;
|
||||
|
||||
@override
|
||||
String toSource() => NUMBER.text;
|
||||
}
|
||||
|
|
|
@ -28,12 +28,4 @@ class OperationDefinitionContext extends DefinitionContext {
|
|||
out = directives.fold<FileSpan>(out, (o, d) => o.expand(d.span));
|
||||
return out.expand(selectionSet.span);
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() {
|
||||
if (TYPE == null) return selectionSet.toSource();
|
||||
return '${TYPE.text} ${NAME.text} ${variableDefinitions.toSource()} ' +
|
||||
directives.map((d) => d.toSource()).join() +
|
||||
' ${selectionSet.toSource()}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,4 @@ class SelectionContext extends Node {
|
|||
@override
|
||||
FileSpan get span =>
|
||||
field?.span ?? fragmentSpread?.span ?? inlineFragment?.span;
|
||||
|
||||
@override
|
||||
String toSource() =>
|
||||
field?.toSource() ??
|
||||
fragmentSpread?.toSource() ??
|
||||
inlineFragment?.toSource();
|
||||
}
|
||||
|
|
|
@ -15,16 +15,4 @@ class SelectionSetContext extends Node {
|
|||
selections.fold<FileSpan>(LBRACE.span, (out, s) => out.expand(s.span));
|
||||
return out.expand(RBRACE.span);
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() {
|
||||
var buf = new StringBuffer('{');
|
||||
|
||||
for (int i = 0; i < selections.length; i++) {
|
||||
if (i > 0) buf.write(',');
|
||||
buf.write(selections[i].toSource());
|
||||
}
|
||||
|
||||
return buf.toString() + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,4 @@ class StringValueContext extends ValueContext {
|
|||
|
||||
@override
|
||||
get value => stringValue;
|
||||
|
||||
@override
|
||||
String toSource() => STRING.text;
|
||||
}
|
||||
|
|
|
@ -20,19 +20,4 @@ class TypeContext extends Node {
|
|||
var out = typeName?.span ?? listType.span;
|
||||
return EXCLAMATION != null ? out.expand(EXCLAMATION.span) : out;
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() {
|
||||
var buf = new StringBuffer();
|
||||
|
||||
if (typeName != null) {
|
||||
buf.write(typeName.toSource());
|
||||
} else if (listType != null) {
|
||||
buf.write(listType.toSource());
|
||||
}
|
||||
|
||||
if (!isNullable) buf.write('!');
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,4 @@ class TypeConditionContext extends Node {
|
|||
|
||||
@override
|
||||
FileSpan get span => typeName.span;
|
||||
|
||||
@override
|
||||
String toSource() => typeName.toSource();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,4 @@ class TypeNameContext extends Node {
|
|||
FileSpan get span => NAME.span;
|
||||
|
||||
TypeNameContext(this.NAME);
|
||||
|
||||
@override
|
||||
String toSource() => NAME.text;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,4 @@ class ValueOrVariableContext extends Node {
|
|||
|
||||
@override
|
||||
FileSpan get span => value?.span ?? variable.span;
|
||||
|
||||
@override
|
||||
String toSource() => '${value?.toSource() ?? variable.toSource()}';
|
||||
}
|
||||
|
|
|
@ -12,7 +12,4 @@ class VariableContext extends Node {
|
|||
@override
|
||||
FileSpan get span => DOLLAR.span.expand(NAME.span);
|
||||
// new FileSpan(DOLLAR?.span?.start, NAME?.span?.end, toSource());
|
||||
|
||||
@override
|
||||
String toSource() => '\$${NAME.text}';
|
||||
}
|
||||
|
|
|
@ -16,8 +16,4 @@ class VariableDefinitionContext extends Node {
|
|||
|
||||
@override
|
||||
FileSpan get span => variable.span.expand(defaultValue?.span ?? type.span);
|
||||
|
||||
@override
|
||||
String toSource() =>
|
||||
'${variable.toSource()}:${type.toSource()}${defaultValue?.toSource() ?? ""}';
|
||||
}
|
||||
|
|
|
@ -15,17 +15,4 @@ class VariableDefinitionsContext extends Node {
|
|||
LPAREN.span, (o, v) => o.expand(v.span));
|
||||
return out.expand(RPAREN.span);
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() {
|
||||
var buf = new StringBuffer('(');
|
||||
|
||||
for (int i = 0; i < variableDefinitions.length; i++) {
|
||||
if (i > 0) buf.write(',');
|
||||
buf.write(variableDefinitions[i].toSource());
|
||||
}
|
||||
|
||||
buf.write(')');
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'syntax_error.dart';
|
|||
import 'token.dart';
|
||||
import 'token_type.dart';
|
||||
|
||||
final RegExp _comment = RegExp(r'#[^\n]*');
|
||||
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]+)?');
|
||||
|
|
|
@ -39,7 +39,7 @@ class _IsArgument extends Matcher {
|
|||
bool matches(item, Map matchState) {
|
||||
var arg = item is ArgumentContext ? item : parseArgument(item.toString());
|
||||
if (arg == null) return false;
|
||||
print(arg.toSource());
|
||||
print(arg.span.highlight());
|
||||
return equals(name).matches(arg.name, matchState) &&
|
||||
equals(value).matches(
|
||||
arg.valueOrVariable.value?.value ??
|
||||
|
|
|
@ -4,4 +4,5 @@ import 'package:test/test.dart';
|
|||
|
||||
Parser parse(String text) => new Parser(scan(text));
|
||||
|
||||
final Matcher throwsSyntaxError = throwsA(const isInstanceOf<SyntaxError>());
|
||||
final Matcher throwsSyntaxError =
|
||||
throwsA(predicate((x) => x is SyntaxError, 'is a syntax error'));
|
||||
|
|
|
@ -63,10 +63,9 @@ main() {
|
|||
var doc =
|
||||
parse(r'query foo ($one: [int] = 2) @foo @bar: 2 {foo, bar: baz}')
|
||||
.parseDocument();
|
||||
print(doc.toSource());
|
||||
print(doc.span.highlight());
|
||||
expect(doc.definitions, hasLength(1));
|
||||
expect(doc.definitions.first,
|
||||
const isInstanceOf<OperationDefinitionContext>());
|
||||
expect(doc.definitions.first is OperationDefinitionContext, isTrue);
|
||||
var op = doc.definitions.first as OperationDefinitionContext;
|
||||
expect(op.isMutation, isFalse);
|
||||
expect(op.isQuery, isTrue);
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
|
|
144
graphql_server/lib/src/query_executor.dart
Normal file
144
graphql_server/lib/src/query_executor.dart
Normal file
|
@ -0,0 +1,144 @@
|
|||
import 'package:graphql_parser/graphql_parser.dart';
|
||||
import 'package:symbol_table/symbol_table.dart';
|
||||
|
||||
class GraphQLQueryExecutor {
|
||||
const GraphQLQueryExecutor();
|
||||
|
||||
Map<String, dynamic> visitDocument(DocumentContext ctx, Map<String, dynamic> inputData) {
|
||||
var scope = new SymbolTable();
|
||||
return ctx.definitions.fold(inputData, (o, def) {
|
||||
var result = visitDefinition(def, o, scope);
|
||||
return result ?? o;
|
||||
});
|
||||
}
|
||||
|
||||
Map<String, dynamic> visitDefinition(
|
||||
DefinitionContext ctx, inputData, SymbolTable scope) {
|
||||
if (ctx is OperationDefinitionContext)
|
||||
return visitOperationDefinition(ctx, inputData, scope);
|
||||
else if (ctx is FragmentDefinitionContext)
|
||||
return visitFragmentDefinition(ctx, inputData, scope);
|
||||
else
|
||||
throw new UnsupportedError('Unsupported definition: $ctx');
|
||||
}
|
||||
|
||||
Map<String, dynamic> visitOperationDefinition(
|
||||
OperationDefinitionContext ctx, inputData, SymbolTable scope) {
|
||||
// Add variable definitions
|
||||
ctx.variableDefinitions?.variableDefinitions?.forEach((def) {
|
||||
scope.assign(def.variable.name, def.defaultValue?.value?.value);
|
||||
});
|
||||
|
||||
callback(o, SelectionContext sel) {
|
||||
var result = visitSelection(sel, o, scope);
|
||||
return result ?? o;
|
||||
}
|
||||
|
||||
if (inputData is List) {
|
||||
return {
|
||||
'data': inputData.map((x) {
|
||||
return ctx.selectionSet.selections.fold(x, callback);
|
||||
}).toList()
|
||||
};
|
||||
} else if (inputData is Map) {
|
||||
return {'data': ctx.selectionSet.selections.fold(inputData, callback)};
|
||||
} else
|
||||
throw new UnsupportedError(
|
||||
'Cannot execute GraphQL queries against $inputData.');
|
||||
}
|
||||
|
||||
Map<String, dynamic> visitFragmentDefinition(
|
||||
FragmentDefinitionContext ctx, inputData, SymbolTable scope) {}
|
||||
|
||||
visitSelection(SelectionContext ctx, inputData, SymbolTable scope) {
|
||||
if (inputData is! Map && inputData is! List)
|
||||
return inputData;
|
||||
else if (inputData is List)
|
||||
return inputData.map((x) => visitSelection(ctx, x, scope)).toList();
|
||||
|
||||
if (ctx.field != null)
|
||||
return visitField(ctx.field, inputData, scope);
|
||||
// TODO: Spread, inline fragment
|
||||
else
|
||||
throw new UnsupportedError('Unsupported selection: $ctx');
|
||||
}
|
||||
|
||||
visitField(FieldContext ctx, inputData, SymbolTable scope, [value]) {
|
||||
bool hasValue = value != null;
|
||||
var s = scope.createChild();
|
||||
Map out = {};
|
||||
|
||||
value ??= inputData[ctx.fieldName.name];
|
||||
|
||||
// Apply arguments to query lists...
|
||||
if (ctx.arguments.isNotEmpty) {
|
||||
var listSearch = value is List ? value : inputData;
|
||||
|
||||
if (listSearch is! List)
|
||||
throw new UnsupportedError('Arguments are only supported on Lists.');
|
||||
value = listSearch.firstWhere((x) {
|
||||
if (x is! Map)
|
||||
return null;
|
||||
else {
|
||||
return ctx.arguments.every((a) {
|
||||
var value;
|
||||
|
||||
if (a.valueOrVariable.value != null)
|
||||
value = a.valueOrVariable.value.value;
|
||||
else {
|
||||
// TODO: Unknown key
|
||||
value = scope.resolve(a.valueOrVariable.variable.name).value;
|
||||
}
|
||||
|
||||
// print('Looking for ${a.name} == $value in $x');
|
||||
return x[a.name] == value;
|
||||
});
|
||||
}
|
||||
}, orElse: () => null);
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
//print('Why is ${ctx.fieldName.name} null in $inputData??? hasValue: $hasValue');
|
||||
return value;
|
||||
}
|
||||
|
||||
if (ctx.selectionSet == null) return value;
|
||||
|
||||
var target = {};
|
||||
|
||||
for (var selection in ctx.selectionSet.selections) {
|
||||
if (selection.field != null) {
|
||||
// Get the corresponding data
|
||||
var key = selection.field.fieldName.name;
|
||||
var childValue = value[key];
|
||||
|
||||
if (childValue is! List && childValue is! Map)
|
||||
target[key] = childValue;
|
||||
else {
|
||||
applyFieldSelection(x, [root]) {
|
||||
//print('Select ${selection.field.fieldName.name} from $x');
|
||||
return visitField(selection.field, root ?? x, s, x);
|
||||
}
|
||||
|
||||
var output = childValue is List
|
||||
? childValue
|
||||
.map((x) => applyFieldSelection(x, childValue))
|
||||
.toList()
|
||||
: applyFieldSelection(childValue);
|
||||
//print('$key => $output');
|
||||
target[key] = output;
|
||||
}
|
||||
}
|
||||
// TODO: Spread, inline fragment
|
||||
}
|
||||
|
||||
// Set this as the value within the current scope...
|
||||
if (hasValue) {
|
||||
return target;
|
||||
} else
|
||||
out[ctx.fieldName.name] = target;
|
||||
s.create(ctx.fieldName.name, value: target);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
5
graphql_server/pubspec.yaml
Normal file
5
graphql_server/pubspec.yaml
Normal file
|
@ -0,0 +1,5 @@
|
|||
name: graphql_server
|
||||
dependencies:
|
||||
graphql_parser:
|
||||
path: ../graphql_parser
|
||||
symbol_table: ^1.0.0
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
cd graphql_parser && pub get && pub run test -j2 && cd..
|
||||
cd graphql_parser && pub get && pub run test -j2 && cd ..
|
Loading…
Reference in a new issue