diff --git a/.github/check_package.sh b/.github/check_package.sh
new file mode 100755
index 00000000..fe832fcf
--- /dev/null
+++ b/.github/check_package.sh
@@ -0,0 +1,43 @@
+#/bin/bash
+
+set -e
+
+PACKAGE=$1
+
+git diff --exit-code
+
+clean_up () {
+    ARG=$?
+    git checkout .
+    exit $ARG
+} 
+
+trap clean_up EXIT
+
+# Check pubspec
+multipack --only $PACKAGE pubspec clean
+multipack --only $PACKAGE exec git diff --exit-code pubspec.yaml
+
+# Override local dependencies
+multipack pubspec hard_override
+
+multipack --only $PACKAGE pub get
+
+# Check formatting
+echo ""
+echo "A list of incorrectly formatted files may follow:"
+echo ""
+multipack --only $PACKAGE fmt -n . --set-exit-if-changed
+echo ""
+
+# Analyze package
+multipack --only $PACKAGE analyze --version
+multipack --only $PACKAGE analyze --fatal-warnings --no-hints .
+
+# Run tests
+# mockito requires build runner now
+multipack --only $PACKAGE pub run build_runner build --delete-conflicting-outputs || true
+multipack --only $PACKAGE exec [ ! -d ./test ] && exit 0
+multipack --only $PACKAGE pub run test
+
+git checkout .
diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml
index ac115b2e..c1aaa86d 100644
--- a/.github/workflows/dart.yml
+++ b/.github/workflows/dart.yml
@@ -4,6 +4,7 @@ on: pull_request
 jobs:
   packages:
     strategy:
+      fail-fast: false
       matrix:
         package:
           - gql
@@ -16,13 +17,11 @@ jobs:
           - gql_error_link
           - gql_http_link
           - gql_websocket_link
-          - gql_link
           - gql_transform_link
           - cats
-          - gql_example_http_auth_link
     runs-on: ubuntu-latest
     container:
-      image: google/dart:latest
+      image: google/dart:2.12-beta
     name: Check ${{ matrix.package }}
     env:
       PACKAGE: ${{ matrix.package }}
@@ -50,6 +49,10 @@ jobs:
           echo ""
           multipack --only $PACKAGE fmt -n . --set-exit-if-changed
           echo ""
+      - name: Run build_runner if necessary
+        run: |
+          multipack --only $PACKAGE pub run \
+            build_runner build --delete-conflicting-outputs || true
       - name: Analyze package
         run: |
           multipack --only $PACKAGE analyze --version
@@ -65,9 +68,12 @@ jobs:
           - gql_example_cli
           - gql_example_cli_github
           - gql_example_build
+          - gql_example_http_auth_link
+          - gql_example_dio_link
+          # gql_example_flutter would require flutter
     runs-on: ubuntu-latest
     container:
-      image: google/dart:latest
+      image: google/dart:2.12-beta
     name: Check ${{ matrix.package }}
     env:
       PACKAGE: ${{ matrix.package }}
@@ -90,7 +96,8 @@ jobs:
           multipack --only $PACKAGE pub get
       - name: Run builders
         run: |
-          multipack --only $PACKAGE pub run build_runner build --delete-conflicting-outputs
+          multipack --only $PACKAGE pub run \
+            build_runner build --delete-conflicting-outputs || true
       - name: Check build diff
         run: |
           multipack --only $PACKAGE exec git diff --exit-code **/*.gql.dart
@@ -112,7 +119,7 @@ jobs:
           - end_to_end_test
     runs-on: ubuntu-latest
     container:
-      image: google/dart:latest
+      image: google/dart:2.12-beta
     name: Check ${{ matrix.package }}
     env:
       PACKAGE: ${{ matrix.package }}
@@ -158,7 +165,7 @@ jobs:
   publish_dry_run:
     runs-on: ubuntu-latest
     container:
-      image: google/dart:latest
+      image: google/dart:2.12-beta
     env:
       PACKAGES: 'gql,gql_build,gql_code_builder,gql_dedupe_link,gql_dio_link,gql_exec,gql_http_link,gql_link,gql_pedantic,gql_transform_link,gql_error_link,gql_websocket_link'
       PUB_ACCESS_TOKEN: ${{ secrets.PUB_ACCESS_TOKEN }}
@@ -183,7 +190,7 @@ jobs:
   check_svg:
     runs-on: ubuntu-latest
     container:
-      image: google/dart:latest
+      image: google/dart:2.12-beta
     steps:
       - name: Clone repository
         uses: actions/checkout@v2
diff --git a/.gitignore b/.gitignore
index bc6ef711..da9d8101 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@ doc/api/
 .vscode/
 
 **/*.iml
+
+**/test/**/*.mocks.dart
diff --git a/cats/lib/src/cat_builder.dart b/cats/lib/src/cat_builder.dart
index 6ce10c0a..9497921e 100644
--- a/cats/lib/src/cat_builder.dart
+++ b/cats/lib/src/cat_builder.dart
@@ -31,7 +31,7 @@ class CatBuilder {
   Scenario buildScenario(File file, Directory folder) {
     var doc = loadYaml(
       file.readAsStringSync(),
-      sourceUrl: file.path,
+      sourceUrl: Uri.parse(file.path),
     );
 
     var schema;
@@ -67,7 +67,7 @@ class CatBuilder {
     );
   }
 
-  Iterable<TestCase> buildTests(YamlNode node, Directory folder) {
+  Iterable<TestCase>? buildTests(YamlNode? node, Directory folder) {
     if (node is YamlList) {
       return node.map((n) => buildTest(n, folder));
     }
@@ -110,7 +110,7 @@ class CatBuilder {
     );
   }
 
-  Action buildAction(YamlMap node) {
+  Action? buildAction(YamlMap node) {
     if (node.containsKey('parse')) {
       return ParsingAction();
     }
@@ -135,7 +135,7 @@ class CatBuilder {
     return null;
   }
 
-  Iterable<Assertion> buildAssertions(YamlNode node) {
+  Iterable<Assertion?>? buildAssertions(YamlNode? node) {
     if (node is YamlList) {
       return node.map((n) => buildAssertion(n));
     }
@@ -147,17 +147,17 @@ class CatBuilder {
     return null;
   }
 
-  Assertion buildAssertion(YamlNode node) {
+  Assertion? buildAssertion(YamlNode? node) {
     if (node is YamlMap) {
       if (node.containsKey('passes')) {
         return PassesAssertion(
-          passes: node['passes'] as bool,
+          passes: node['passes'] as bool?,
         );
       }
 
       if (node.containsKey('syntax-error')) {
         return SyntaxErrorAssertion(
-          syntaxError: node['syntax-error'] as bool,
+          syntaxError: node['syntax-error'] as bool?,
         );
       }
 
diff --git a/cats/lib/src/cat_model.dart b/cats/lib/src/cat_model.dart
index 7331ac13..5b21f2c2 100644
--- a/cats/lib/src/cat_model.dart
+++ b/cats/lib/src/cat_model.dart
@@ -1,7 +1,7 @@
 class Suite {
-  Iterable<Scenario> scenarios;
+  Iterable<Scenario>? scenarios;
 
-  Map<String, ErrorDefinition> errorMapping;
+  Map<String, ErrorDefinition>? errorMapping;
 
   Suite({
     this.scenarios,
@@ -10,15 +10,15 @@ class Suite {
 }
 
 class Scenario {
-  String folder;
-  String file;
+  String? folder;
+  String? file;
 
-  String name;
+  String? name;
 
-  String schema;
-  Map<String, dynamic> testData;
+  String? schema;
+  Map<String, dynamic>? testData;
 
-  Iterable<TestCase> tests;
+  Iterable<TestCase>? tests;
 
   Scenario({
     this.folder,
@@ -31,19 +31,19 @@ class Scenario {
 }
 
 class TestCase {
-  String name;
+  String? name;
 
   String query;
-  String schema;
-  Map<String, dynamic> testData;
+  String? schema;
+  Map<String, dynamic>? testData;
 
-  Action action;
+  Action? action;
 
-  Iterable<Assertion> assertions;
+  Iterable<Assertion?>? assertions;
 
   TestCase({
     this.name,
-    this.query,
+    required this.query,
     this.schema,
     this.testData,
     this.action,
@@ -56,16 +56,16 @@ abstract class Action {}
 class ParsingAction extends Action {}
 
 class ValidationAction extends Action {
-  Iterable<String> validationRules;
+  Iterable<String?> validationRules;
 
   ValidationAction(this.validationRules);
 }
 
 class ExecutionAction extends Action {
-  String operationName;
-  Map<String, dynamic> variables;
-  bool validateQuery;
-  String testValue;
+  String? operationName;
+  Map<String, dynamic>? variables;
+  bool? validateQuery;
+  String? testValue;
 
   ExecutionAction({
     this.operationName,
@@ -78,7 +78,7 @@ class ExecutionAction extends Action {
 abstract class Assertion {}
 
 class PassesAssertion extends Assertion {
-  bool passes;
+  bool? passes;
 
   PassesAssertion({
     this.passes,
@@ -86,7 +86,7 @@ class PassesAssertion extends Assertion {
 }
 
 class SyntaxErrorAssertion extends Assertion {
-  bool syntaxError;
+  bool? syntaxError;
 
   SyntaxErrorAssertion({
     this.syntaxError,
@@ -94,11 +94,11 @@ class SyntaxErrorAssertion extends Assertion {
 }
 
 class DataAssertion extends Assertion {
-  Map<String, dynamic> data;
+  Map<String, dynamic>? data;
 }
 
 class ErrorCountAssertion extends Assertion {
-  int count;
+  int? count;
 
   ErrorCountAssertion({
     this.count,
@@ -106,9 +106,9 @@ class ErrorCountAssertion extends Assertion {
 }
 
 class ErrorCodeAssertion extends Assertion {
-  String errorCode;
-  Map<String, String> args;
-  Iterable<Location> locations;
+  String? errorCode;
+  Map<String, String>? args;
+  Iterable<Location>? locations;
 
   ErrorCodeAssertion({
     this.errorCode,
@@ -118,38 +118,38 @@ class ErrorCodeAssertion extends Assertion {
 }
 
 class ErrorContainsAssertion extends Assertion {
-  String error;
-  Iterable<Location> locations;
+  String? error;
+  Iterable<Location>? locations;
 }
 
 class ErrorRegexAssertion extends Assertion {
-  String errorRegex;
-  Iterable<Location> locations;
+  String? errorRegex;
+  Iterable<Location>? locations;
 }
 
 class ExecutionExceptionContainsAssertion extends Assertion {
-  String exception;
+  String? exception;
 }
 
 class ExecutionExceptionRegexAssertion extends Assertion {
-  String errorRegex;
+  String? errorRegex;
 }
 
 class Location {
-  int line;
-  int column;
+  int? line;
+  int? column;
 }
 
 class ErrorDefinition {
-  String message;
-  String specReference;
-  String implementationReference;
+  String? message;
+  String? specReference;
+  String? implementationReference;
 }
 
 class DriverError {
-  String code;
-  String message;
-  Location location;
+  String? code;
+  String? message;
+  Location? location;
 
   DriverError({
     this.code,
@@ -159,5 +159,5 @@ class DriverError {
 }
 
 class DriverException {
-  String message;
+  String? message;
 }
diff --git a/cats/lib/src/cats_base.dart b/cats/lib/src/cats_base.dart
index 3ff2c74e..70bc111d 100644
--- a/cats/lib/src/cats_base.dart
+++ b/cats/lib/src/cats_base.dart
@@ -4,28 +4,28 @@ import './cat_model.dart';
 
 abstract class CatDriver<Doc> {
   Doc parse({
-    String source,
+    required String source,
   });
 
   Iterable<DriverError> validate({
-    Doc schema,
-    Doc query,
-    Iterable<String> validationRules,
+    Doc? schema,
+    Doc? query,
+    Iterable<String?>? validationRules,
   });
 
-  execute({
-    Doc schema,
+  dynamic execute({
+    Doc? schema,
     dynamic testData,
-    Doc query,
-    String operation,
-    Map<String, dynamic> variables,
+    Doc? query,
+    String? operation,
+    Map<String, dynamic>? variables,
   });
 }
 
 class CatRunner<Doc> {
-  CatBuilder _builder = CatBuilder();
-  CatDriver<Doc> driver;
-  List whitelist;
+  final _builder = CatBuilder();
+  CatDriver<Doc>? driver;
+  List? whitelist;
 
   CatRunner({
     this.driver,
@@ -35,41 +35,41 @@ class CatRunner<Doc> {
   void runSuite(String suitePath) {
     var suite = _builder.buildSuite(suitePath);
 
-    suite.scenarios.forEach(_runScenario);
+    suite.scenarios!.forEach(_runScenario);
   }
 
   void _runScenario(Scenario scenario) {
-    if (whitelist != null && !whitelist.contains(scenario.file)) return;
+    if (whitelist != null && !whitelist!.contains(scenario.file)) return;
     group(scenario.name, () {
-      scenario.tests.forEach(
+      scenario.tests!.forEach(
         (test) => _runTest(test, scenario),
       );
     });
   }
 
   void _runTest(TestCase testCase, Scenario scenario) {
-    var passesAssertion = testCase.assertions.firstWhere(
+    var passesAssertion = testCase.assertions!.firstWhere(
       (a) => a is PassesAssertion,
       orElse: () => null,
-    ) as PassesAssertion;
-    var syntaxAssertion = testCase.assertions.firstWhere(
+    ) as PassesAssertion?;
+    var syntaxAssertion = testCase.assertions!.firstWhere(
       (a) => a is SyntaxErrorAssertion,
       orElse: () => null,
-    ) as SyntaxErrorAssertion;
-    var errorCountAssertion = testCase.assertions.firstWhere(
+    ) as SyntaxErrorAssertion?;
+    var errorCountAssertion = testCase.assertions!.firstWhere(
       (a) => a is ErrorCountAssertion,
       orElse: () => null,
-    ) as ErrorCountAssertion;
+    ) as ErrorCountAssertion?;
     var errorCodeAssertions =
-        testCase.assertions.whereType<ErrorCodeAssertion>();
-    var errorContainsAssertion = testCase.assertions.firstWhere(
+        testCase.assertions!.whereType<ErrorCodeAssertion>();
+    var errorContainsAssertion = testCase.assertions!.firstWhere(
       (a) => a is ErrorContainsAssertion,
       orElse: () => null,
-    ) as ErrorContainsAssertion;
-    var errorRegexAssertion = testCase.assertions.firstWhere(
+    ) as ErrorContainsAssertion?;
+    var errorRegexAssertion = testCase.assertions!.firstWhere(
       (a) => a is ErrorRegexAssertion,
       orElse: () => null,
-    ) as ErrorRegexAssertion;
+    ) as ErrorRegexAssertion?;
 
     group(testCase.name, () {
       var queryDoc;
@@ -85,7 +85,7 @@ class CatRunner<Doc> {
 
       setUp(() {
         try {
-          queryDoc = driver.parse(
+          queryDoc = driver!.parse(
             source: testCase.query,
           );
         } catch (e) {
@@ -97,7 +97,7 @@ class CatRunner<Doc> {
 
           if (schema != null) {
             try {
-              schemaDoc = driver.parse(
+              schemaDoc = driver!.parse(
                 source: schema,
               );
             } catch (e) {
@@ -109,7 +109,7 @@ class CatRunner<Doc> {
               ? (testCase.action as ValidationAction).validationRules
               : null;
 
-          validationErrors = driver.validate(
+          validationErrors = driver!.validate(
             schema: schemaDoc,
             query: queryDoc,
             validationRules: validationRules,
@@ -121,12 +121,12 @@ class CatRunner<Doc> {
           var testData = (testCase.testData ?? scenario.testData);
 
           try {
-            executionResult = driver.execute(
+            executionResult = driver!.execute(
               query: queryDoc,
               schema: schemaDoc,
               testData:
                   testData != null && testData.containsKey(action.testValue)
-                      ? testData[action.testValue]
+                      ? testData[action.testValue!]
                       : testData,
               operation: action.operationName,
               variables: action.variables,
@@ -144,14 +144,14 @@ class CatRunner<Doc> {
             expect(queryParsingError, isNull);
           });
         } else {
-          if ((passesAssertion == null || passesAssertion.passes) &&
-              !(syntaxAssertion != null && syntaxAssertion.syntaxError)) {
+          if ((passesAssertion == null || passesAssertion.passes!) &&
+              !(syntaxAssertion != null && syntaxAssertion.syntaxError!)) {
             test('parses successfuly', () {
               expect(queryDoc, isNotNull);
               expect(queryParsingError, isNull);
             });
           }
-          if (syntaxAssertion != null && syntaxAssertion.syntaxError) {
+          if (syntaxAssertion != null && syntaxAssertion.syntaxError!) {
             test('throws syntax error', () {
               expect(queryDoc, isNull);
               expect(queryParsingError, isNotNull);
diff --git a/cats/pubspec.yaml b/cats/pubspec.yaml
index 4fab83ee..297b3c97 100644
--- a/cats/pubspec.yaml
+++ b/cats/pubspec.yaml
@@ -2,9 +2,9 @@ name: cats
 description: A starting point for Dart libraries or applications.
 repository: https://github.com/gql-dart/gql
 environment: 
-  sdk: '>=2.7.2 <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 dependencies: 
-  test: ^1.6.0
+  test: ^1.16.0
 dev_dependencies: 
-  pedantic: ^1.7.0
-  yaml: ^2.1.16
+  pedantic: ^1.10.0
+  yaml: ^3.0.0
diff --git a/codegen/end_to_end_test/pubspec.yaml b/codegen/end_to_end_test/pubspec.yaml
index 9e7fffbe..0f399961 100644
--- a/codegen/end_to_end_test/pubspec.yaml
+++ b/codegen/end_to_end_test/pubspec.yaml
@@ -6,13 +6,13 @@ repository: https://github.com/gql-dart/gql
 environment: 
   sdk: '>=2.0.0-dev <3.0.0'
 dependencies: 
-  built_collection: '>=2.0.0 <5.0.0'
-  built_value: ^7.0.2
+  built_collection: ^5.0.0
+  built_value: ^8.0.0
   gql_exec: ^0.2.5
   gql_build: ^0.1.3
   gql_code_builder: ^0.1.3
 dev_dependencies: 
   collection: ^1.14.13
   build: ^1.0.0
-  build_runner: ^1.10.1
+  build_runner: ^1.11.1
   test: ^1.0.0
diff --git a/codegen/gql_build/pubspec.yaml b/codegen/gql_build/pubspec.yaml
index bc69d288..c942c5f3 100644
--- a/codegen/gql_build/pubspec.yaml
+++ b/codegen/gql_build/pubspec.yaml
@@ -5,7 +5,7 @@ repository: https://github.com/gql-dart/gql
 environment: 
   sdk: '>=2.7.2 <3.0.0'
 dependencies: 
-  analyzer: ^0.39.14
+  analyzer: ^0.40.1
   gql: ^0.12.4
   path: ^1.6.4
   glob: ^1.2.0
@@ -13,9 +13,9 @@ dependencies:
   gql_code_builder: ^0.1.4
   code_builder: ^3.3.0
   dart_style: ^1.2.9
-  built_value: ^7.1.0
-  built_value_generator: ^7.1.0
-  built_collection: ^4.3.2
+  built_value: ^8.0.0
+  built_value_generator: ^8.0.0
+  built_collection: ^5.0.0
   yaml: ^2.2.1
 dev_dependencies: 
   build_test: ^0.10.7
diff --git a/codegen/gql_code_builder/pubspec.yaml b/codegen/gql_code_builder/pubspec.yaml
index 8dc39612..ff49f4ad 100644
--- a/codegen/gql_code_builder/pubspec.yaml
+++ b/codegen/gql_code_builder/pubspec.yaml
@@ -5,16 +5,16 @@ repository: https://github.com/gql-dart/gql
 environment: 
   sdk: '>=2.7.2 <3.0.0'
 dependencies: 
-  analyzer: ^0.39.14
+  analyzer: ^0.40.1
   gql: ^0.12.4
   code_builder: ^3.3.0
   meta: ^1.1.7
-  built_collection: ^4.0.0
-  built_value: ^7.0.9
+  built_collection: ^5.0.0
+  built_value: ^8.0.0
   path: ^1.6.4
   recase: ^3.0.0
   gql_exec: ^0.2.5
 dev_dependencies: 
   gql_pedantic: ^1.0.2
-  build_runner: ^1.7.4
+  build_runner: ^1.11.1
   test: ^1.0.0
diff --git a/codegen/gql_code_builder/test/enum/enum_fallback_test.dart b/codegen/gql_code_builder/test/enum/enum_fallback_test.dart
index b8886d3a..1a4b8db2 100644
--- a/codegen/gql_code_builder/test/enum/enum_fallback_test.dart
+++ b/codegen/gql_code_builder/test/enum/enum_fallback_test.dart
@@ -6,7 +6,7 @@ import "package:test/test.dart";
 
 void main() {
   final simpleEnum =
-      EnumTypeDefinitionNode(name: NameNode(value: "testEnum"), values: [
+      EnumTypeDefinitionNode(name: NameNode(value: "testEnum"), values: const [
     EnumValueDefinitionNode(name: NameNode(value: "val1")),
     EnumValueDefinitionNode(name: NameNode(value: "val2"))
   ]);
@@ -132,10 +132,12 @@ void main() {
 
   test("works with escaped names", () {
     final clazz = buildEnumClass(
-        EnumTypeDefinitionNode(name: NameNode(value: "testEnum"), values: [
-          EnumValueDefinitionNode(name: NameNode(value: "name")),
-          EnumValueDefinitionNode(name: NameNode(value: "default"))
-        ]),
+        EnumTypeDefinitionNode(
+            name: NameNode(value: "testEnum"),
+            values: const [
+              EnumValueDefinitionNode(name: NameNode(value: "name")),
+              EnumValueDefinitionNode(name: NameNode(value: "default"))
+            ]),
         EnumFallbackConfig(
             generateFallbackValuesGlobally: false,
             fallbackValueMap: {"testEnum": "default"}));
diff --git a/examples/gql_example_build/pubspec.yaml b/examples/gql_example_build/pubspec.yaml
index 8b114f59..466c9a6a 100644
--- a/examples/gql_example_build/pubspec.yaml
+++ b/examples/gql_example_build/pubspec.yaml
@@ -2,7 +2,7 @@ name: gql_example_build
 environment: 
   sdk: '>=2.7.2 <3.0.0'
 dev_dependencies: 
-  build_runner: ^1.10.1
+  build_runner: ^1.11.1
   gql_pedantic: ^1.0.2
   gql_build: ^0.1.3
   test: ^1.0.0
diff --git a/examples/gql_example_cli/pubspec.yaml b/examples/gql_example_cli/pubspec.yaml
index 6df791d7..929af19a 100644
--- a/examples/gql_example_cli/pubspec.yaml
+++ b/examples/gql_example_cli/pubspec.yaml
@@ -8,6 +8,6 @@ dependencies:
   gql_exec: ^0.2.5
   gql_http_link: ^0.3.2
 dev_dependencies: 
-  build_runner: ^1.10.1
+  build_runner: ^1.11.1
   gql_pedantic: ^1.0.2
   gql_build: ^0.1.3
diff --git a/examples/gql_example_cli_github/pubspec.yaml b/examples/gql_example_cli_github/pubspec.yaml
index fc9d9547..31f070d4 100644
--- a/examples/gql_example_cli_github/pubspec.yaml
+++ b/examples/gql_example_cli_github/pubspec.yaml
@@ -9,6 +9,6 @@ dependencies:
   gql_http_link: ^0.3.2
   gql_transform_link: ^0.1.5
 dev_dependencies: 
-  build_runner: ^1.10.1
+  build_runner: ^1.11.1
   gql_pedantic: ^1.0.2
   gql_build: ^0.1.3
diff --git a/examples/gql_example_flutter/pubspec.yaml b/examples/gql_example_flutter/pubspec.yaml
index 2fc4a034..a4b5f472 100644
--- a/examples/gql_example_flutter/pubspec.yaml
+++ b/examples/gql_example_flutter/pubspec.yaml
@@ -11,7 +11,7 @@ dependencies:
   flutter: 
     sdk: flutter
 dev_dependencies: 
-  build_runner: ^1.10.1
+  build_runner: ^1.11.1
   gql_pedantic: ^1.0.2
   gql_build: ^0.1.3
   flutter_test: 
diff --git a/examples/gql_example_http_auth_link/pubspec.yaml b/examples/gql_example_http_auth_link/pubspec.yaml
index 9d8a28ea..570ef0bd 100644
--- a/examples/gql_example_http_auth_link/pubspec.yaml
+++ b/examples/gql_example_http_auth_link/pubspec.yaml
@@ -8,7 +8,7 @@ dependencies:
   gql_error_link: ^0.1.0
   gql_transform_link: ^0.1.5
   gql_http_link: ^0.3.2
-  http: ^0.12.0+2
+  http: ^0.13.0
 dev_dependencies: 
   gql_pedantic: ^1.0.2
   gql_build: ^0.1.3
diff --git a/gql/example/add_typenames.dart b/gql/example/add_typenames.dart
index 61236769..baf67804 100644
--- a/gql/example/add_typenames.dart
+++ b/gql/example/add_typenames.dart
@@ -18,7 +18,7 @@ class AddTypenames extends ast.TransformingVisitor {
           ast.FieldNode(
             name: ast.NameNode(value: "__typename"),
           ),
-          ...node.selectionSet.selections
+          ...node.selectionSet!.selections
         ],
       ),
     );
diff --git a/gql/example/inspect.dart b/gql/example/inspect.dart
index 85cf0d2c..12a4d1d3 100644
--- a/gql/example/inspect.dart
+++ b/gql/example/inspect.dart
@@ -33,7 +33,7 @@ void inspectSchema() {
   print(character.isImplementedBy(droid));
   // prints "true"
 
-  print(schema.query.getField("droids").type.toString());
+  print(schema.query!.getField("droids").type.toString());
   // prints "[Droid!]"
 }
 
@@ -70,7 +70,7 @@ void inspectQuery() {
 
   final query = document.operations.first;
   final droids = query.selectionSet.fields.first;
-  final spreadDroidName = droids.selectionSet.fragmentSpreads.first;
+  final spreadDroidName = droids.selectionSet!.fragmentSpreads.first;
 
   print(
     // dereference fragment spread into fragment definition
diff --git a/gql/example/parse.dart b/gql/example/parse.dart
index a21ad035..7990155f 100644
--- a/gql/example/parse.dart
+++ b/gql/example/parse.dart
@@ -14,6 +14,6 @@ void main() {
   );
 
   print(
-    (doc.definitions.first as ast.OperationDefinitionNode).name.value,
+    (doc.definitions.first as ast.OperationDefinitionNode).name!.value,
   );
 }
diff --git a/gql/example/visit_types.dart b/gql/example/visit_types.dart
index 7b33ed07..3540d941 100644
--- a/gql/example/visit_types.dart
+++ b/gql/example/visit_types.dart
@@ -31,7 +31,7 @@ void main() {
   print(
     v.types
         .map(
-          (t) => t.name.value,
+          (t) => t.name!.value,
         )
         .join("\n"),
   );
diff --git a/gql/lib/src/ast/ast.dart b/gql/lib/src/ast/ast.dart
index 58dfa342..ee3bb6ba 100644
--- a/gql/lib/src/ast/ast.dart
+++ b/gql/lib/src/ast/ast.dart
@@ -7,13 +7,13 @@ void _visitOne<R>(
   Node node,
   Visitor<R> v,
 ) =>
-    node?.accept(v);
+    node.accept(v);
 
 void _visitAll<R>(
   List<Node> nodes,
   Visitor<R> v,
 ) =>
-    nodes?.forEach(
+    nodes.forEach(
       (node) => _visitOne(node, v),
     );
 
@@ -21,11 +21,11 @@ void _visitAll<R>(
 @immutable
 abstract class Node {
   /// [FileSpan] representing the location of the node in the [SourceFile]
-  final FileSpan span;
+  final FileSpan? span;
 
   const Node(this.span);
 
-  List<Object> get _children;
+  List<Object?> get _children;
 
   /// Lets [Visitor] [v] visit children nodes of this node.
   void visitChildren<R>(Visitor<R> v) => _children.forEach(
@@ -43,7 +43,7 @@ abstract class Node {
     if (identical(this, o)) return true;
     if (o.runtimeType != runtimeType) return false;
 
-    return const ListEquality<Object>(
+    return const ListEquality<Object?>(
       DeepCollectionEquality(),
     ).equals(
       (o as Node)._children,
@@ -52,7 +52,7 @@ abstract class Node {
   }
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash(
         _children,
@@ -67,9 +67,8 @@ class DocumentNode extends Node {
 
   const DocumentNode({
     this.definitions = const [],
-    FileSpan span,
-  })  : assert(definitions != null),
-        super(span);
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitDocumentNode(this);
@@ -81,18 +80,18 @@ class DocumentNode extends Node {
 }
 
 abstract class DefinitionNode extends Node {
-  final NameNode name;
+  final NameNode? name;
 
   const DefinitionNode({
-    @required this.name,
-    FileSpan span,
+    required this.name,
+    FileSpan? span,
   }) : super(span);
 }
 
 abstract class ExecutableDefinitionNode extends DefinitionNode {
   const ExecutableDefinitionNode({
-    @required NameNode name,
-    FileSpan span,
+    required NameNode? name,
+    FileSpan? span,
   }) : super(
           name: name,
           span: span,
@@ -138,16 +137,13 @@ class OperationDefinitionNode extends ExecutableDefinitionNode {
   final SelectionSetNode selectionSet;
 
   const OperationDefinitionNode({
-    @required this.type,
-    NameNode name,
+    required this.type,
+    NameNode? name,
     this.variableDefinitions = const [],
     this.directives = const [],
-    @required this.selectionSet,
-    FileSpan span,
-  })  : assert(variableDefinitions != null),
-        assert(directives != null),
-        assert(selectionSet != null),
-        super(
+    required this.selectionSet,
+    FileSpan? span,
+  }) : super(
           name: name,
           span: span,
         );
@@ -156,7 +152,7 @@ class OperationDefinitionNode extends ExecutableDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitOperationDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         type,
         selectionSet,
@@ -170,7 +166,7 @@ class SelectionSetNode extends Node {
 
   const SelectionSetNode({
     this.selections = const [],
-    FileSpan span,
+    FileSpan? span,
   }) : super(span);
 
   @override
@@ -183,11 +179,11 @@ class SelectionSetNode extends Node {
 }
 
 abstract class SelectionNode extends Node {
-  const SelectionNode(FileSpan span) : super(span);
+  const SelectionNode(FileSpan? span) : super(span);
 }
 
 class FieldNode extends SelectionNode {
-  final NameNode alias;
+  final NameNode? alias;
 
   final NameNode name;
 
@@ -195,25 +191,22 @@ class FieldNode extends SelectionNode {
 
   final List<DirectiveNode> directives;
 
-  final SelectionSetNode selectionSet;
+  final SelectionSetNode? selectionSet;
 
   const FieldNode({
     this.alias,
-    @required this.name,
+    required this.name,
     this.arguments = const [],
     this.directives = const [],
     this.selectionSet,
-    FileSpan span,
-  })  : assert(name != null),
-        assert(arguments != null),
-        assert(directives != null),
-        super(span);
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitFieldNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         alias,
         name,
         selectionSet,
@@ -228,12 +221,10 @@ class ArgumentNode extends Node {
   final ValueNode value;
 
   const ArgumentNode({
-    @required this.name,
-    @required this.value,
-    FileSpan span,
-  })  : assert(name != null),
-        assert(value != null),
-        super(span);
+    required this.name,
+    required this.value,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitArgumentNode(this);
@@ -251,12 +242,10 @@ class FragmentSpreadNode extends SelectionNode {
   final List<DirectiveNode> directives;
 
   const FragmentSpreadNode({
-    @required this.name,
+    required this.name,
     this.directives = const [],
-    FileSpan span,
-  })  : assert(name != null),
-        assert(directives != null),
-        super(span);
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitFragmentSpreadNode(this);
@@ -269,7 +258,7 @@ class FragmentSpreadNode extends SelectionNode {
 }
 
 class InlineFragmentNode extends SelectionNode {
-  final TypeConditionNode typeCondition;
+  final TypeConditionNode? typeCondition;
 
   final List<DirectiveNode> directives;
 
@@ -278,17 +267,15 @@ class InlineFragmentNode extends SelectionNode {
   const InlineFragmentNode({
     this.typeCondition,
     this.directives = const [],
-    @required this.selectionSet,
-    FileSpan span,
-  })  : assert(directives != null),
-        assert(selectionSet != null),
-        super(span);
+    required this.selectionSet,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitInlineFragmentNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         typeCondition,
         selectionSet,
         directives,
@@ -303,16 +290,12 @@ class FragmentDefinitionNode extends ExecutableDefinitionNode {
   final SelectionSetNode selectionSet;
 
   const FragmentDefinitionNode({
-    @required NameNode name,
-    @required this.typeCondition,
+    required NameNode name,
+    required this.typeCondition,
     this.directives = const [],
-    @required this.selectionSet,
-    FileSpan span,
-  })  : assert(name != null),
-        assert(typeCondition != null),
-        assert(directives != null),
-        assert(selectionSet != null),
-        super(
+    required this.selectionSet,
+    FileSpan? span,
+  }) : super(
           name: name,
           span: span,
         );
@@ -321,7 +304,7 @@ class FragmentDefinitionNode extends ExecutableDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitFragmentDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         typeCondition,
         selectionSet,
@@ -333,10 +316,9 @@ class TypeConditionNode extends Node {
   final NamedTypeNode on;
 
   const TypeConditionNode({
-    @required this.on,
-    FileSpan span,
-  })  : assert(on != null),
-        super(span);
+    required this.on,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitTypeConditionNode(this);
@@ -348,17 +330,16 @@ class TypeConditionNode extends Node {
 }
 
 abstract class ValueNode extends Node {
-  const ValueNode(FileSpan span) : super(span);
+  const ValueNode(FileSpan? span) : super(span);
 }
 
 class VariableNode extends ValueNode {
   final NameNode name;
 
   const VariableNode({
-    @required this.name,
-    FileSpan span,
-  })  : assert(name != null),
-        super(span);
+    required this.name,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitVariableNode(this);
@@ -373,10 +354,9 @@ class IntValueNode extends ValueNode {
   final String value;
 
   const IntValueNode({
-    @required this.value,
-    FileSpan span,
-  })  : assert(value != null),
-        super(span);
+    required this.value,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitIntValueNode(this);
@@ -391,10 +371,9 @@ class FloatValueNode extends ValueNode {
   final String value;
 
   const FloatValueNode({
-    @required this.value,
-    FileSpan span,
-  })  : assert(value != null),
-        super(span);
+    required this.value,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitFloatValueNode(this);
@@ -411,12 +390,10 @@ class StringValueNode extends ValueNode {
   final bool isBlock;
 
   const StringValueNode({
-    @required this.value,
-    @required this.isBlock,
-    FileSpan span,
-  })  : assert(value != null),
-        assert(isBlock != null),
-        super(span);
+    required this.value,
+    required this.isBlock,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitStringValueNode(this);
@@ -432,10 +409,9 @@ class BooleanValueNode extends ValueNode {
   final bool value;
 
   const BooleanValueNode({
-    @required this.value,
-    FileSpan span,
-  })  : assert(value != null),
-        super(span);
+    required this.value,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitBooleanValueNode(this);
@@ -448,7 +424,7 @@ class BooleanValueNode extends ValueNode {
 
 class NullValueNode extends ValueNode {
   const NullValueNode({
-    FileSpan span,
+    FileSpan? span,
   }) : super(span);
 
   @override
@@ -462,10 +438,9 @@ class EnumValueNode extends ValueNode {
   final NameNode name;
 
   const EnumValueNode({
-    @required this.name,
-    FileSpan span,
-  })  : assert(name != null),
-        super(span);
+    required this.name,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitEnumValueNode(this);
@@ -481,7 +456,7 @@ class ListValueNode extends ValueNode {
 
   const ListValueNode({
     this.values = const [],
-    FileSpan span,
+    FileSpan? span,
   }) : super(span);
 
   @override
@@ -498,7 +473,7 @@ class ObjectValueNode extends ValueNode {
 
   const ObjectValueNode({
     this.fields = const [],
-    FileSpan span,
+    FileSpan? span,
   }) : super(span);
 
   @override
@@ -516,12 +491,10 @@ class ObjectFieldNode extends Node {
   final ValueNode value;
 
   const ObjectFieldNode({
-    @required this.name,
-    @required this.value,
-    FileSpan span,
-  })  : assert(name != null),
-        assert(value != null),
-        super(span);
+    required this.name,
+    required this.value,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitObjectFieldNode(this);
@@ -538,26 +511,23 @@ class VariableDefinitionNode extends Node {
 
   final TypeNode type;
 
-  final DefaultValueNode defaultValue;
+  final DefaultValueNode? defaultValue;
 
   final List<DirectiveNode> directives;
 
   const VariableDefinitionNode({
-    @required this.variable,
-    @required this.type,
+    required this.variable,
+    required this.type,
     this.defaultValue,
     this.directives = const [],
-    FileSpan span,
-  })  : assert(variable != null),
-        assert(type != null),
-        assert(directives != null),
-        super(span);
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitVariableDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         variable,
         type,
         defaultValue,
@@ -566,18 +536,18 @@ class VariableDefinitionNode extends Node {
 }
 
 class DefaultValueNode extends Node {
-  final ValueNode value;
+  final ValueNode? value;
 
   const DefaultValueNode({
-    @required this.value,
-    FileSpan span,
+    required this.value,
+    FileSpan? span,
   }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitDefaultValueNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         value,
       ];
 }
@@ -585,21 +555,17 @@ class DefaultValueNode extends Node {
 abstract class TypeNode extends Node {
   final bool isNonNull;
 
-  const TypeNode(this.isNonNull, FileSpan span)
-      : assert(isNonNull != null),
-        super(span);
+  const TypeNode(this.isNonNull, FileSpan? span) : super(span);
 }
 
 class NamedTypeNode extends TypeNode {
   final NameNode name;
 
   const NamedTypeNode({
-    @required this.name,
+    required this.name,
     bool isNonNull = false,
-    FileSpan span,
-  })  : assert(name != null),
-        assert(isNonNull != null),
-        super(isNonNull, span);
+    FileSpan? span,
+  }) : super(isNonNull, span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitNamedTypeNode(this);
@@ -615,12 +581,10 @@ class ListTypeNode extends TypeNode {
   final TypeNode type;
 
   const ListTypeNode({
-    @required this.type,
-    @required bool isNonNull,
-    FileSpan span,
-  })  : assert(type != null),
-        assert(isNonNull != null),
-        super(isNonNull, span);
+    required this.type,
+    required bool isNonNull,
+    FileSpan? span,
+  }) : super(isNonNull, span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitListTypeNode(this);
@@ -638,12 +602,10 @@ class DirectiveNode extends Node {
   final List<ArgumentNode> arguments;
 
   const DirectiveNode({
-    @required this.name,
+    required this.name,
     this.arguments = const [],
-    FileSpan span,
-  })  : assert(name != null),
-        assert(arguments != null),
-        super(span);
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitDirectiveNode(this);
@@ -659,10 +621,9 @@ class NameNode extends Node {
   final String value;
 
   const NameNode({
-    @required this.value,
-    FileSpan span,
-  })  : assert(value != null),
-        super(span);
+    required this.value,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitNameNode(this);
@@ -675,8 +636,8 @@ class NameNode extends Node {
 
 abstract class TypeSystemDefinitionNode extends DefinitionNode {
   const TypeSystemDefinitionNode({
-    @required NameNode name,
-    FileSpan span,
+    required NameNode? name,
+    FileSpan? span,
   }) : super(
           name: name,
           span: span,
@@ -684,17 +645,15 @@ abstract class TypeSystemDefinitionNode extends DefinitionNode {
 }
 
 abstract class TypeDefinitionNode extends TypeSystemDefinitionNode {
-  final StringValueNode description;
+  final StringValueNode? description;
   final List<DirectiveNode> directives;
 
   const TypeDefinitionNode({
     this.description,
-    @required NameNode name,
+    required NameNode name,
     this.directives = const [],
-    FileSpan span,
-  })  : assert(name != null),
-        assert(directives != null),
-        super(
+    FileSpan? span,
+  }) : super(
           name: name,
           span: span,
         );
@@ -702,8 +661,8 @@ abstract class TypeDefinitionNode extends TypeSystemDefinitionNode {
 
 abstract class TypeSystemExtensionNode extends TypeSystemDefinitionNode {
   const TypeSystemExtensionNode({
-    @required NameNode name,
-    FileSpan span,
+    required NameNode? name,
+    FileSpan? span,
   }) : super(
           name: name,
           span: span,
@@ -714,12 +673,10 @@ abstract class TypeExtensionNode extends TypeSystemExtensionNode {
   final List<DirectiveNode> directives;
 
   const TypeExtensionNode({
-    FileSpan span,
-    @required NameNode name,
+    FileSpan? span,
+    required NameNode name,
     this.directives = const [],
-  })  : assert(name != null),
-        assert(directives != null),
-        super(
+  }) : super(
           name: name,
           span: span,
         );
@@ -732,10 +689,8 @@ class SchemaDefinitionNode extends TypeSystemDefinitionNode {
   const SchemaDefinitionNode({
     this.directives = const [],
     this.operationTypes = const [],
-    FileSpan span,
-  })  : assert(directives != null),
-        assert(operationTypes != null),
-        super(
+    FileSpan? span,
+  }) : super(
           name: null,
           span: span,
         );
@@ -755,12 +710,10 @@ class OperationTypeDefinitionNode extends Node {
   final NamedTypeNode type;
 
   const OperationTypeDefinitionNode({
-    @required this.operation,
-    @required this.type,
-    FileSpan span,
-  })  : assert(operation != null),
-        assert(type != null),
-        super(span);
+    required this.operation,
+    required this.type,
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitOperationTypeDefinitionNode(this);
@@ -774,13 +727,11 @@ class OperationTypeDefinitionNode extends Node {
 
 class ScalarTypeDefinitionNode extends TypeDefinitionNode {
   const ScalarTypeDefinitionNode({
-    StringValueNode description,
-    @required NameNode name,
+    StringValueNode? description,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-    FileSpan span,
-  })  : assert(name != null),
-        assert(directives != null),
-        super(
+    FileSpan? span,
+  }) : super(
           span: span,
           name: name,
           description: description,
@@ -791,7 +742,7 @@ class ScalarTypeDefinitionNode extends TypeDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitScalarTypeDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -805,15 +756,11 @@ class ObjectTypeDefinitionNode extends TypeDefinitionNode {
   const ObjectTypeDefinitionNode({
     this.interfaces = const [],
     this.fields = const [],
-    StringValueNode description,
-    @required NameNode name,
+    StringValueNode? description,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-    FileSpan span,
-  })  : assert(interfaces != null),
-        assert(fields != null),
-        assert(name != null),
-        assert(directives != null),
-        super(
+    FileSpan? span,
+  }) : super(
           span: span,
           name: name,
           description: description,
@@ -824,7 +771,7 @@ class ObjectTypeDefinitionNode extends TypeDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitObjectTypeDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -834,7 +781,7 @@ class ObjectTypeDefinitionNode extends TypeDefinitionNode {
 }
 
 class FieldDefinitionNode extends Node {
-  final StringValueNode description;
+  final StringValueNode? description;
   final NameNode name;
   final TypeNode type;
   final List<DirectiveNode> directives;
@@ -842,22 +789,18 @@ class FieldDefinitionNode extends Node {
 
   const FieldDefinitionNode({
     this.description,
-    @required this.name,
-    @required this.type,
+    required this.name,
+    required this.type,
     this.args = const [],
     this.directives = const [],
-    FileSpan span,
-  })  : assert(type != null),
-        assert(args != null),
-        assert(name != null),
-        assert(directives != null),
-        super(span);
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitFieldDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -867,30 +810,26 @@ class FieldDefinitionNode extends Node {
 }
 
 class InputValueDefinitionNode extends Node {
-  final StringValueNode description;
+  final StringValueNode? description;
   final NameNode name;
   final TypeNode type;
-  final ValueNode defaultValue;
+  final ValueNode? defaultValue;
   final List<DirectiveNode> directives;
 
   const InputValueDefinitionNode({
     this.description,
-    @required this.name,
-    @required this.type,
+    required this.name,
+    required this.type,
     this.defaultValue,
     this.directives = const [],
-    FileSpan span,
-  })  : assert(type != null),
-        assert(name != null),
-        assert(type != null),
-        assert(directives != null),
-        super(span);
+    FileSpan? span,
+  }) : super(span);
 
   @override
   R accept<R>(Visitor<R> v) => v.visitInputValueDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -904,14 +843,11 @@ class InterfaceTypeDefinitionNode extends TypeDefinitionNode {
 
   const InterfaceTypeDefinitionNode({
     this.fields = const [],
-    StringValueNode description,
-    @required NameNode name,
+    StringValueNode? description,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-    FileSpan span,
-  })  : assert(fields != null),
-        assert(name != null),
-        assert(directives != null),
-        super(
+    FileSpan? span,
+  }) : super(
           span: span,
           name: name,
           description: description,
@@ -922,7 +858,7 @@ class InterfaceTypeDefinitionNode extends TypeDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitInterfaceTypeDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -935,14 +871,11 @@ class UnionTypeDefinitionNode extends TypeDefinitionNode {
 
   const UnionTypeDefinitionNode({
     this.types = const [],
-    StringValueNode description,
-    @required NameNode name,
+    StringValueNode? description,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-    FileSpan span,
-  })  : assert(types != null),
-        assert(name != null),
-        assert(directives != null),
-        super(
+    FileSpan? span,
+  }) : super(
           span: span,
           name: name,
           description: description,
@@ -953,7 +886,7 @@ class UnionTypeDefinitionNode extends TypeDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitUnionTypeDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -966,14 +899,11 @@ class EnumTypeDefinitionNode extends TypeDefinitionNode {
 
   const EnumTypeDefinitionNode({
     this.values = const [],
-    StringValueNode description,
-    @required NameNode name,
+    StringValueNode? description,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-    FileSpan span,
-  })  : assert(values != null),
-        assert(name != null),
-        assert(directives != null),
-        super(
+    FileSpan? span,
+  }) : super(
           span: span,
           name: name,
           description: description,
@@ -984,7 +914,7 @@ class EnumTypeDefinitionNode extends TypeDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitEnumTypeDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -996,15 +926,12 @@ class EnumValueDefinitionNode extends TypeDefinitionNode {
   final bool fallback;
 
   const EnumValueDefinitionNode({
-    StringValueNode description,
-    @required NameNode name,
+    StringValueNode? description,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-    FileSpan span,
+    FileSpan? span,
     this.fallback = false,
-  })  : assert(name != null),
-        assert(directives != null),
-        assert(fallback != null),
-        super(
+  }) : super(
           span: span,
           name: name,
           description: description,
@@ -1015,7 +942,7 @@ class EnumValueDefinitionNode extends TypeDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitEnumValueDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -1027,14 +954,11 @@ class InputObjectTypeDefinitionNode extends TypeDefinitionNode {
 
   const InputObjectTypeDefinitionNode({
     this.fields = const [],
-    StringValueNode description,
-    @required NameNode name,
+    StringValueNode? description,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-    FileSpan span,
-  })  : assert(fields != null),
-        assert(name != null),
-        assert(directives != null),
-        super(
+    FileSpan? span,
+  }) : super(
           span: span,
           name: name,
           description: description,
@@ -1045,7 +969,7 @@ class InputObjectTypeDefinitionNode extends TypeDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitInputObjectTypeDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         directives,
@@ -1054,23 +978,19 @@ class InputObjectTypeDefinitionNode extends TypeDefinitionNode {
 }
 
 class DirectiveDefinitionNode extends TypeSystemDefinitionNode {
-  final StringValueNode description;
+  final StringValueNode? description;
   final List<InputValueDefinitionNode> args;
   final List<DirectiveLocation> locations;
   final bool repeatable;
 
   const DirectiveDefinitionNode({
     this.description,
-    @required NameNode name,
+    required NameNode name,
     this.args = const [],
     this.locations = const [],
     this.repeatable = false,
-    FileSpan span,
-  })  : assert(name != null),
-        assert(args != null),
-        assert(locations != null),
-        assert(repeatable != null),
-        super(
+    FileSpan? span,
+  }) : super(
           name: name,
           span: span,
         );
@@ -1079,7 +999,7 @@ class DirectiveDefinitionNode extends TypeSystemDefinitionNode {
   R accept<R>(Visitor<R> v) => v.visitDirectiveDefinitionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         description,
         locations,
@@ -1095,10 +1015,8 @@ class SchemaExtensionNode extends TypeSystemExtensionNode {
   const SchemaExtensionNode({
     this.directives = const [],
     this.operationTypes = const [],
-    FileSpan span,
-  })  : assert(directives != null),
-        assert(operationTypes != null),
-        super(
+    FileSpan? span,
+  }) : super(
           name: null,
           span: span,
         );
@@ -1107,7 +1025,7 @@ class SchemaExtensionNode extends TypeSystemExtensionNode {
   R accept<R>(Visitor<R> v) => v.visitSchemaExtensionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         directives,
         operationTypes,
@@ -1116,12 +1034,10 @@ class SchemaExtensionNode extends TypeSystemExtensionNode {
 
 class ScalarTypeExtensionNode extends TypeExtensionNode {
   const ScalarTypeExtensionNode({
-    FileSpan span,
-    @required NameNode name,
+    FileSpan? span,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-  })  : assert(name != null),
-        assert(directives != null),
-        super(
+  }) : super(
           span: span,
           name: name,
           directives: directives,
@@ -1131,7 +1047,7 @@ class ScalarTypeExtensionNode extends TypeExtensionNode {
   R accept<R>(Visitor<R> v) => v.visitScalarTypeExtensionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         directives,
       ];
@@ -1142,16 +1058,12 @@ class ObjectTypeExtensionNode extends TypeExtensionNode {
   final List<FieldDefinitionNode> fields;
 
   const ObjectTypeExtensionNode({
-    @required NameNode name,
+    required NameNode name,
     this.interfaces = const [],
     this.fields = const [],
-    FileSpan span,
+    FileSpan? span,
     List<DirectiveNode> directives = const [],
-  })  : assert(name != null),
-        assert(interfaces != null),
-        assert(fields != null),
-        assert(directives != null),
-        super(
+  }) : super(
           span: span,
           name: name,
           directives: directives,
@@ -1161,7 +1073,7 @@ class ObjectTypeExtensionNode extends TypeExtensionNode {
   R accept<R>(Visitor<R> v) => v.visitObjectTypeExtensionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         directives,
         interfaces,
@@ -1174,13 +1086,10 @@ class InterfaceTypeExtensionNode extends TypeExtensionNode {
 
   const InterfaceTypeExtensionNode({
     this.fields = const [],
-    @required NameNode name,
-    FileSpan span,
+    required NameNode name,
+    FileSpan? span,
     List<DirectiveNode> directives = const [],
-  })  : assert(name != null),
-        assert(fields != null),
-        assert(directives != null),
-        super(
+  }) : super(
           span: span,
           name: name,
           directives: directives,
@@ -1190,7 +1099,7 @@ class InterfaceTypeExtensionNode extends TypeExtensionNode {
   R accept<R>(Visitor<R> v) => v.visitInterfaceTypeExtensionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         directives,
         fields,
@@ -1202,13 +1111,10 @@ class UnionTypeExtensionNode extends TypeExtensionNode {
 
   const UnionTypeExtensionNode({
     this.types = const [],
-    @required NameNode name,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-    FileSpan span,
-  })  : assert(name != null),
-        assert(types != null),
-        assert(directives != null),
-        super(
+    FileSpan? span,
+  }) : super(
           span: span,
           name: name,
           directives: directives,
@@ -1218,7 +1124,7 @@ class UnionTypeExtensionNode extends TypeExtensionNode {
   R accept<R>(Visitor<R> v) => v.visitUnionTypeExtensionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         directives,
         types,
@@ -1230,13 +1136,10 @@ class EnumTypeExtensionNode extends TypeExtensionNode {
 
   const EnumTypeExtensionNode({
     this.values = const [],
-    FileSpan span,
-    @required NameNode name,
+    FileSpan? span,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-  })  : assert(name != null),
-        assert(values != null),
-        assert(directives != null),
-        super(
+  }) : super(
           span: span,
           name: name,
           directives: directives,
@@ -1246,7 +1149,7 @@ class EnumTypeExtensionNode extends TypeExtensionNode {
   R accept<R>(Visitor<R> v) => v.visitEnumTypeExtensionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         directives,
         values,
@@ -1258,13 +1161,10 @@ class InputObjectTypeExtensionNode extends TypeExtensionNode {
 
   const InputObjectTypeExtensionNode({
     this.fields = const [],
-    FileSpan span,
-    @required NameNode name,
+    FileSpan? span,
+    required NameNode name,
     List<DirectiveNode> directives = const [],
-  })  : assert(name != null),
-        assert(fields != null),
-        assert(directives != null),
-        super(
+  }) : super(
           span: span,
           name: name,
           directives: directives,
@@ -1274,7 +1174,7 @@ class InputObjectTypeExtensionNode extends TypeExtensionNode {
   R accept<R>(Visitor<R> v) => v.visitInputObjectTypeExtensionNode(this);
 
   @override
-  List<Object> get _children => <Object>[
+  List<Object?> get _children => <Object?>[
         name,
         directives,
         fields,
diff --git a/gql/lib/src/ast/transformer.dart b/gql/lib/src/ast/transformer.dart
index 494a2c6d..ec009809 100644
--- a/gql/lib/src/ast/transformer.dart
+++ b/gql/lib/src/ast/transformer.dart
@@ -293,7 +293,7 @@ class _Transformer extends Visitor<Node> {
     this.visitors = const [],
   });
 
-  N _visitOne<N extends Node>(
+  N _visitOne<N extends Node?>(
     N node,
   ) {
     if (node == null) return node;
@@ -303,19 +303,16 @@ class _Transformer extends Visitor<Node> {
 
   List<N> _visitAll<N extends Node>(
     List<N> nodes,
-  ) {
-    if (nodes == null) return nodes;
-
-    return nodes
-        .map(
-          (
-            node,
-          ) =>
-              node.accept(this),
-        )
-        .cast<N>()
-        .toList(growable: false);
-  }
+  ) =>
+      nodes
+          .map(
+            (
+              node,
+            ) =>
+                node.accept(this),
+          )
+          .cast<N>()
+          .toList(growable: false);
 
   @override
   DocumentNode visitDocumentNode(
@@ -379,7 +376,7 @@ class _Transformer extends Visitor<Node> {
     DirectiveDefinitionNode node,
   ) {
     final updatedNode = DirectiveDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       description: _visitOne(node.description),
       locations: node.locations,
       repeatable: node.repeatable,
@@ -412,7 +409,7 @@ class _Transformer extends Visitor<Node> {
     EnumTypeDefinitionNode node,
   ) {
     final updatedNode = EnumTypeDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       description: _visitOne(node.description),
       directives: _visitAll(node.directives),
       values: _visitAll(node.values),
@@ -429,7 +426,7 @@ class _Transformer extends Visitor<Node> {
     EnumTypeExtensionNode node,
   ) {
     final updatedNode = EnumTypeExtensionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       directives: _visitAll(node.directives),
       values: _visitAll(node.values),
     );
@@ -445,7 +442,7 @@ class _Transformer extends Visitor<Node> {
     EnumValueDefinitionNode node,
   ) {
     final updatedNode = EnumValueDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       description: _visitOne(node.description),
       directives: _visitAll(node.directives),
     );
@@ -525,7 +522,7 @@ class _Transformer extends Visitor<Node> {
     FragmentDefinitionNode node,
   ) {
     final updatedNode = FragmentDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       directives: _visitAll(node.directives),
       selectionSet: _visitOne(node.selectionSet),
       typeCondition: _visitOne(node.typeCondition),
@@ -573,7 +570,7 @@ class _Transformer extends Visitor<Node> {
     InputObjectTypeDefinitionNode node,
   ) {
     final updatedNode = InputObjectTypeDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       description: _visitOne(node.description),
       directives: _visitAll(node.directives),
       fields: _visitAll(node.fields),
@@ -590,7 +587,7 @@ class _Transformer extends Visitor<Node> {
     InputObjectTypeExtensionNode node,
   ) {
     final updatedNode = InputObjectTypeExtensionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       directives: _visitAll(node.directives),
       fields: _visitAll(node.fields),
     );
@@ -638,7 +635,7 @@ class _Transformer extends Visitor<Node> {
     InterfaceTypeDefinitionNode node,
   ) {
     final updatedNode = InterfaceTypeDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       description: _visitOne(node.description),
       directives: _visitAll(node.directives),
       fields: _visitAll(node.fields),
@@ -655,7 +652,7 @@ class _Transformer extends Visitor<Node> {
     InterfaceTypeExtensionNode node,
   ) {
     final updatedNode = InterfaceTypeExtensionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       directives: _visitAll(node.directives),
       fields: _visitAll(node.fields),
     );
@@ -754,7 +751,7 @@ class _Transformer extends Visitor<Node> {
     ObjectTypeDefinitionNode node,
   ) {
     final updatedNode = ObjectTypeDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       description: _visitOne(node.description),
       directives: _visitAll(node.directives),
       fields: _visitAll(node.fields),
@@ -772,7 +769,7 @@ class _Transformer extends Visitor<Node> {
     ObjectTypeExtensionNode node,
   ) {
     final updatedNode = ObjectTypeExtensionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       directives: _visitAll(node.directives),
       fields: _visitAll(node.fields),
       interfaces: _visitAll(node.interfaces),
@@ -836,7 +833,7 @@ class _Transformer extends Visitor<Node> {
     ScalarTypeDefinitionNode node,
   ) {
     final updatedNode = ScalarTypeDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       description: _visitOne(node.description),
       directives: _visitAll(node.directives),
     );
@@ -852,7 +849,7 @@ class _Transformer extends Visitor<Node> {
     ScalarTypeExtensionNode node,
   ) {
     final updatedNode = ScalarTypeExtensionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       directives: _visitAll(node.directives),
     );
 
@@ -940,7 +937,7 @@ class _Transformer extends Visitor<Node> {
     UnionTypeDefinitionNode node,
   ) {
     final updatedNode = UnionTypeDefinitionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       description: _visitOne(node.description),
       directives: _visitAll(node.directives),
       types: _visitAll(node.types),
@@ -957,7 +954,7 @@ class _Transformer extends Visitor<Node> {
     UnionTypeExtensionNode node,
   ) {
     final updatedNode = UnionTypeExtensionNode(
-      name: _visitOne(node.name),
+      name: _visitOne(node.name!),
       directives: _visitAll(node.directives),
       types: _visitAll(node.types),
     );
diff --git a/gql/lib/src/ast/visitor.dart b/gql/lib/src/ast/visitor.dart
index 17833461..b7301a1d 100644
--- a/gql/lib/src/ast/visitor.dart
+++ b/gql/lib/src/ast/visitor.dart
@@ -224,267 +224,267 @@ abstract class Visitor<R> {
 }
 
 /// A simple implementation of [Visitor] returning `null` from each visit method.
-class SimpleVisitor<R> implements Visitor<R> {
+class SimpleVisitor<R> implements Visitor<R?> {
   @override
-  R visitDocumentNode(
+  R? visitDocumentNode(
     DocumentNode node,
   ) =>
       null;
 
   @override
-  R visitNameNode(
+  R? visitNameNode(
     NameNode node,
   ) =>
       null;
 
   @override
-  R visitDirectiveNode(
+  R? visitDirectiveNode(
     DirectiveNode node,
   ) =>
       null;
 
   @override
-  R visitListTypeNode(
+  R? visitListTypeNode(
     ListTypeNode node,
   ) =>
       null;
 
   @override
-  R visitNamedTypeNode(
+  R? visitNamedTypeNode(
     NamedTypeNode node,
   ) =>
       null;
 
   @override
-  R visitDefaultValueNode(
+  R? visitDefaultValueNode(
     DefaultValueNode node,
   ) =>
       null;
 
   @override
-  R visitVariableDefinitionNode(
+  R? visitVariableDefinitionNode(
     VariableDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitObjectFieldNode(
+  R? visitObjectFieldNode(
     ObjectFieldNode node,
   ) =>
       null;
 
   @override
-  R visitObjectValueNode(
+  R? visitObjectValueNode(
     ObjectValueNode node,
   ) =>
       null;
 
   @override
-  R visitListValueNode(
+  R? visitListValueNode(
     ListValueNode node,
   ) =>
       null;
 
   @override
-  R visitEnumValueNode(
+  R? visitEnumValueNode(
     EnumValueNode node,
   ) =>
       null;
 
   @override
-  R visitNullValueNode(
+  R? visitNullValueNode(
     NullValueNode node,
   ) =>
       null;
 
   @override
-  R visitBooleanValueNode(
+  R? visitBooleanValueNode(
     BooleanValueNode node,
   ) =>
       null;
 
   @override
-  R visitStringValueNode(
+  R? visitStringValueNode(
     StringValueNode node,
   ) =>
       null;
 
   @override
-  R visitFloatValueNode(
+  R? visitFloatValueNode(
     FloatValueNode node,
   ) =>
       null;
 
   @override
-  R visitIntValueNode(
+  R? visitIntValueNode(
     IntValueNode node,
   ) =>
       null;
 
   @override
-  R visitVariableNode(
+  R? visitVariableNode(
     VariableNode node,
   ) =>
       null;
 
   @override
-  R visitTypeConditionNode(
+  R? visitTypeConditionNode(
     TypeConditionNode node,
   ) =>
       null;
 
   @override
-  R visitFragmentDefinitionNode(
+  R? visitFragmentDefinitionNode(
     FragmentDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitInlineFragmentNode(
+  R? visitInlineFragmentNode(
     InlineFragmentNode node,
   ) =>
       null;
 
   @override
-  R visitFragmentSpreadNode(
+  R? visitFragmentSpreadNode(
     FragmentSpreadNode node,
   ) =>
       null;
 
   @override
-  R visitArgumentNode(
+  R? visitArgumentNode(
     ArgumentNode node,
   ) =>
       null;
 
   @override
-  R visitFieldNode(
+  R? visitFieldNode(
     FieldNode node,
   ) =>
       null;
 
   @override
-  R visitSelectionSetNode(
+  R? visitSelectionSetNode(
     SelectionSetNode node,
   ) =>
       null;
 
   @override
-  R visitOperationDefinitionNode(
+  R? visitOperationDefinitionNode(
     OperationDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitSchemaDefinitionNode(
+  R? visitSchemaDefinitionNode(
     SchemaDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitOperationTypeDefinitionNode(
+  R? visitOperationTypeDefinitionNode(
     OperationTypeDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitScalarTypeDefinitionNode(
+  R? visitScalarTypeDefinitionNode(
     ScalarTypeDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitObjectTypeDefinitionNode(
+  R? visitObjectTypeDefinitionNode(
     ObjectTypeDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitFieldDefinitionNode(
+  R? visitFieldDefinitionNode(
     FieldDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitInputValueDefinitionNode(
+  R? visitInputValueDefinitionNode(
     InputValueDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitInterfaceTypeDefinitionNode(
+  R? visitInterfaceTypeDefinitionNode(
     InterfaceTypeDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitUnionTypeDefinitionNode(
+  R? visitUnionTypeDefinitionNode(
     UnionTypeDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitEnumTypeDefinitionNode(
+  R? visitEnumTypeDefinitionNode(
     EnumTypeDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitEnumValueDefinitionNode(
+  R? visitEnumValueDefinitionNode(
     EnumValueDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitInputObjectTypeDefinitionNode(
+  R? visitInputObjectTypeDefinitionNode(
     InputObjectTypeDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitDirectiveDefinitionNode(
+  R? visitDirectiveDefinitionNode(
     DirectiveDefinitionNode node,
   ) =>
       null;
 
   @override
-  R visitSchemaExtensionNode(
+  R? visitSchemaExtensionNode(
     SchemaExtensionNode node,
   ) =>
       null;
 
   @override
-  R visitScalarTypeExtensionNode(
+  R? visitScalarTypeExtensionNode(
     ScalarTypeExtensionNode node,
   ) =>
       null;
 
   @override
-  R visitObjectTypeExtensionNode(
+  R? visitObjectTypeExtensionNode(
     ObjectTypeExtensionNode node,
   ) =>
       null;
 
   @override
-  R visitInterfaceTypeExtensionNode(
+  R? visitInterfaceTypeExtensionNode(
     InterfaceTypeExtensionNode node,
   ) =>
       null;
 
   @override
-  R visitUnionTypeExtensionNode(
+  R? visitUnionTypeExtensionNode(
     UnionTypeExtensionNode node,
   ) =>
       null;
 
   @override
-  R visitEnumTypeExtensionNode(
+  R? visitEnumTypeExtensionNode(
     EnumTypeExtensionNode node,
   ) =>
       null;
 
   @override
-  R visitInputObjectTypeExtensionNode(
+  R? visitInputObjectTypeExtensionNode(
     InputObjectTypeExtensionNode node,
   ) =>
       null;
@@ -766,7 +766,7 @@ abstract class RecursiveVisitor implements Visitor<void> {
 /// traversing the AST only once and collecting the return
 /// values in the `accumulator`.
 class AccumulatingVisitor<A> extends RecursiveVisitor {
-  List<SimpleVisitor<List<A>>> visitors;
+  List<SimpleVisitor<List<A>>?> visitors;
   List<A> accumulator = [];
 
   AccumulatingVisitor({
@@ -780,7 +780,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitArgumentNode(node) ?? <A>[],
+        (visitor) => visitor!.visitArgumentNode(node) ?? <A>[],
       )
     ];
 
@@ -794,7 +794,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitBooleanValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitBooleanValueNode(node) ?? <A>[],
       )
     ];
 
@@ -808,7 +808,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitDefaultValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitDefaultValueNode(node) ?? <A>[],
       )
     ];
 
@@ -822,7 +822,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitDirectiveDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitDirectiveDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -836,7 +836,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitDirectiveNode(node) ?? <A>[],
+        (visitor) => visitor!.visitDirectiveNode(node) ?? <A>[],
       )
     ];
 
@@ -850,7 +850,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitDocumentNode(node) ?? <A>[],
+        (visitor) => visitor!.visitDocumentNode(node) ?? <A>[],
       )
     ];
 
@@ -864,7 +864,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitEnumTypeDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitEnumTypeDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -878,7 +878,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitEnumTypeExtensionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitEnumTypeExtensionNode(node) ?? <A>[],
       )
     ];
 
@@ -892,7 +892,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitEnumValueDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitEnumValueDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -906,7 +906,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitEnumValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitEnumValueNode(node) ?? <A>[],
       )
     ];
 
@@ -920,7 +920,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitFieldDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitFieldDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -934,7 +934,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitFieldNode(node) ?? <A>[],
+        (visitor) => visitor!.visitFieldNode(node) ?? <A>[],
       )
     ];
 
@@ -948,7 +948,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitFloatValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitFloatValueNode(node) ?? <A>[],
       )
     ];
 
@@ -962,7 +962,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitFragmentDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitFragmentDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -976,7 +976,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitFragmentSpreadNode(node) ?? <A>[],
+        (visitor) => visitor!.visitFragmentSpreadNode(node) ?? <A>[],
       )
     ];
 
@@ -990,7 +990,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitInlineFragmentNode(node) ?? <A>[],
+        (visitor) => visitor!.visitInlineFragmentNode(node) ?? <A>[],
       )
     ];
 
@@ -1004,7 +1004,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitInputObjectTypeDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitInputObjectTypeDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1018,7 +1018,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitInputObjectTypeExtensionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitInputObjectTypeExtensionNode(node) ?? <A>[],
       )
     ];
 
@@ -1032,7 +1032,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitInputValueDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitInputValueDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1046,7 +1046,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitIntValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitIntValueNode(node) ?? <A>[],
       )
     ];
 
@@ -1060,7 +1060,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitInterfaceTypeDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitInterfaceTypeDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1074,7 +1074,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitInterfaceTypeExtensionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitInterfaceTypeExtensionNode(node) ?? <A>[],
       )
     ];
 
@@ -1088,7 +1088,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitListTypeNode(node) ?? <A>[],
+        (visitor) => visitor!.visitListTypeNode(node) ?? <A>[],
       )
     ];
 
@@ -1102,7 +1102,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitListValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitListValueNode(node) ?? <A>[],
       )
     ];
 
@@ -1116,7 +1116,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitNameNode(node) ?? <A>[],
+        (visitor) => visitor!.visitNameNode(node) ?? <A>[],
       )
     ];
 
@@ -1130,7 +1130,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitNamedTypeNode(node) ?? <A>[],
+        (visitor) => visitor!.visitNamedTypeNode(node) ?? <A>[],
       )
     ];
 
@@ -1144,7 +1144,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitNullValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitNullValueNode(node) ?? <A>[],
       )
     ];
 
@@ -1158,7 +1158,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitObjectFieldNode(node) ?? <A>[],
+        (visitor) => visitor!.visitObjectFieldNode(node) ?? <A>[],
       )
     ];
 
@@ -1172,7 +1172,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitObjectTypeDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitObjectTypeDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1186,7 +1186,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitObjectTypeExtensionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitObjectTypeExtensionNode(node) ?? <A>[],
       )
     ];
 
@@ -1200,7 +1200,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitObjectValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitObjectValueNode(node) ?? <A>[],
       )
     ];
 
@@ -1214,7 +1214,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitOperationDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitOperationDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1228,7 +1228,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitOperationTypeDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitOperationTypeDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1242,7 +1242,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitScalarTypeDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitScalarTypeDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1256,7 +1256,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitScalarTypeExtensionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitScalarTypeExtensionNode(node) ?? <A>[],
       )
     ];
 
@@ -1270,7 +1270,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitSchemaDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitSchemaDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1284,7 +1284,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitSchemaExtensionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitSchemaExtensionNode(node) ?? <A>[],
       )
     ];
 
@@ -1298,7 +1298,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitSelectionSetNode(node) ?? <A>[],
+        (visitor) => visitor!.visitSelectionSetNode(node) ?? <A>[],
       )
     ];
 
@@ -1312,7 +1312,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitStringValueNode(node) ?? <A>[],
+        (visitor) => visitor!.visitStringValueNode(node) ?? <A>[],
       )
     ];
 
@@ -1326,7 +1326,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitTypeConditionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitTypeConditionNode(node) ?? <A>[],
       )
     ];
 
@@ -1340,7 +1340,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitUnionTypeDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitUnionTypeDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1354,7 +1354,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitUnionTypeExtensionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitUnionTypeExtensionNode(node) ?? <A>[],
       )
     ];
 
@@ -1368,7 +1368,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitVariableDefinitionNode(node) ?? <A>[],
+        (visitor) => visitor!.visitVariableDefinitionNode(node) ?? <A>[],
       )
     ];
 
@@ -1382,7 +1382,7 @@ class AccumulatingVisitor<A> extends RecursiveVisitor {
     accumulator = [
       ...accumulator,
       ...visitors.expand(
-        (visitor) => visitor.visitVariableNode(node) ?? <A>[],
+        (visitor) => visitor!.visitVariableNode(node) ?? <A>[],
       )
     ];
 
diff --git a/gql/lib/src/language/lexer.dart b/gql/lib/src/language/lexer.dart
index e3699959..167f3109 100644
--- a/gql/lib/src/language/lexer.dart
+++ b/gql/lib/src/language/lexer.dart
@@ -26,9 +26,9 @@ enum TokenKind {
 }
 
 abstract class Token {
-  FileSpan get span;
+  FileSpan? get span;
 
-  TokenKind get kind;
+  TokenKind? get kind;
 
   String get value;
 
@@ -39,16 +39,16 @@ abstract class Token {
 
 class _Token implements Token {
   @override
-  final TokenKind kind;
+  final TokenKind? kind;
   @override
-  final FileSpan span;
+  final FileSpan? span;
 
   const _Token({
     this.kind,
     this.span,
   });
 
-  String get _text => span.text;
+  String get _text => span!.text;
 
   String _getValue() {
     switch (kind) {
@@ -56,11 +56,11 @@ class _Token implements Token {
         return _text.substring(1, _text.length - 1).replaceAllMapped(
           RegExp(r'\\[nrbtf\\/"]'),
           (match) {
-            switch (match.group(0).codeUnitAt(1)) {
+            switch (match.group(0)!.codeUnitAt(1)) {
               case 34: // "
               case 47: // /
               case 92: // \
-                return match.group(0)[1];
+                return match.group(0)![1];
               case 98: // \b
                 return "\b";
               case 102: // \f
@@ -72,17 +72,17 @@ class _Token implements Token {
               case 116: // \t
                 return "\t";
               default:
-                return match.group(0);
+                return match.group(0)!;
             }
           },
         ).replaceAllMapped(
           RegExp(r"\\u[0-9A-Za-z]{4}"),
           (match) => String.fromCharCode(
             uniCharCode(
-              match.group(0).codeUnitAt(2),
-              match.group(0).codeUnitAt(3),
-              match.group(0).codeUnitAt(4),
-              match.group(0).codeUnitAt(5),
+              match.group(0)!.codeUnitAt(2),
+              match.group(0)!.codeUnitAt(3),
+              match.group(0)!.codeUnitAt(4),
+              match.group(0)!.codeUnitAt(5),
             ),
           ),
         );
@@ -91,7 +91,7 @@ class _Token implements Token {
           _text.substring(3, _text.length - 3).replaceAll('\\"""', '"""'),
         );
       default:
-        return span.text;
+        return span!.text;
     }
   }
 
@@ -127,7 +127,7 @@ class _Scanner {
 
   _Scanner(this.src);
 
-  int peek({
+  int? peek({
     int offset = 0,
   }) {
     if (position + offset >= src.length) {
@@ -169,7 +169,7 @@ class _Scanner {
       );
     }
 
-    final code = peek();
+    final code = peek()!;
 
     if ((code >= 65 && code <= 90) ||
         code == 95 ||
@@ -234,7 +234,7 @@ class _Scanner {
 
   Token scanComment() {
     var length = 0;
-    int code;
+    int? code;
 
     do {
       code = peek(offset: ++length);
@@ -301,7 +301,7 @@ class _Scanner {
     var digitOffset = offset;
     var code = peek(offset: digitOffset);
 
-    if (code >= 48 && code <= 57) {
+    if (code != null && code >= 48 && code <= 57) {
       do {
         code = peek(offset: ++digitOffset);
       } while (code != null && code >= 48 && code <= 57);
@@ -352,7 +352,7 @@ class _Scanner {
         );
       }
 
-      if (code == null || (code < 0x0020 && code != 0x0009)) {
+      if (code < 0x0020 && code != 0x0009) {
         throw SourceSpanException(
           "Unexpected character in a string literal",
           src.span(
@@ -378,10 +378,10 @@ class _Scanner {
           case 116: // \t
             break;
           case 117: // \u
-            final isUnicode = isHex(peek(offset: 1)) &&
-                isHex(peek(offset: 2)) &&
-                isHex(peek(offset: 3)) &&
-                isHex(peek(offset: 4));
+            final isUnicode = isHex(peek(offset: 1)!) &&
+                isHex(peek(offset: 2)!) &&
+                isHex(peek(offset: 3)!) &&
+                isHex(peek(offset: 4)!);
 
             if (!isUnicode) {
               throw SourceSpanException(
@@ -429,11 +429,7 @@ class _Scanner {
         );
       }
 
-      if (code == null ||
-          (code < 0x0020 &&
-              code != 0x0009 &&
-              code != 0x000a &&
-              code != 0x000d)) {
+      if (code < 0x0020 && code != 0x0009 && code != 0x000a && code != 0x000d) {
         throw SourceSpanException(
           "Unexpected character in a string literal",
           src.span(position, position),
@@ -526,7 +522,7 @@ int char2Hex(int a) {
 String dedentBlockStringValue(String value) {
   var lines = value.split(RegExp(r"\r\n|[\n\r]"));
 
-  int commonIndent;
+  int? commonIndent;
   for (var i = 1; i < lines.length; i++) {
     final line = lines[i];
     final indent = leadingWhitespace(line);
@@ -542,7 +538,7 @@ String dedentBlockStringValue(String value) {
 
   if (commonIndent != null && commonIndent != 0) {
     lines = lines.map((line) {
-      if (line.length < commonIndent) {
+      if (line.length < commonIndent!) {
         return "";
       } else {
         return line.substring(commonIndent);
diff --git a/gql/lib/src/language/parser.dart b/gql/lib/src/language/parser.dart
index 3d947b1c..f08ae57b 100644
--- a/gql/lib/src/language/parser.dart
+++ b/gql/lib/src/language/parser.dart
@@ -51,8 +51,8 @@ class _Parser {
     ++_position;
   }
 
-  Token _expectToken(TokenKind kind, [String errorMessage]) {
-    final next = _next();
+  Token _expectToken(TokenKind kind, [String? errorMessage]) {
+    final next = _next()!;
     if (next.kind == kind) {
       _advance();
       return next;
@@ -60,12 +60,12 @@ class _Parser {
 
     throw SourceSpanException(
       errorMessage ?? "Expected $kind",
-      _next().span,
+      _next()!.span,
     );
   }
 
-  Token _expectOptionalToken(TokenKind kind) {
-    final next = _next();
+  Token? _expectOptionalToken(TokenKind kind) {
+    final next = _next()!;
     if (next.kind == kind) {
       _advance();
       return next;
@@ -74,8 +74,8 @@ class _Parser {
     return null;
   }
 
-  Token _expectKeyword(String value, [String errorMessage]) {
-    final next = _next();
+  Token _expectKeyword(String value, [String? errorMessage]) {
+    final next = _next()!;
     if (next.kind == TokenKind.name && next.value == value) {
       _advance();
       return next;
@@ -83,12 +83,12 @@ class _Parser {
 
     throw SourceSpanException(
       errorMessage ?? "Expected keyword '$value'",
-      _next().span,
+      _next()!.span,
     );
   }
 
-  Token _expectOptionalKeyword(String value) {
-    final next = _next();
+  Token? _expectOptionalKeyword(String value) {
+    final next = _next()!;
     if (next.kind == TokenKind.name && next.value == value) {
       _advance();
       return next;
@@ -97,7 +97,7 @@ class _Parser {
     return null;
   }
 
-  Token _next({int offset = 0}) {
+  Token? _next({int offset = 0}) {
     if (_position + offset >= _length) return null;
 
     return _tokens[_position + offset];
@@ -107,7 +107,7 @@ class _Parser {
     TokenKind open,
     _ParseFunction<N> parse,
     TokenKind close, [
-    String errorMessage,
+    String? errorMessage,
   ]) {
     _expectToken(open, errorMessage);
 
@@ -124,7 +124,7 @@ class _Parser {
     TokenKind open,
     _ParseFunction<N> parse,
     TokenKind close, [
-    String errorMessage,
+    String? errorMessage,
   ]) {
     if (_peek(open)) {
       return _parseMany<N>(
@@ -148,7 +148,7 @@ class _Parser {
 
   DefinitionNode _parseDefinition() {
     if (_peek(TokenKind.name)) {
-      switch (_next().value) {
+      switch (_next()!.value) {
         case "query":
         case "mutation":
         case "subscription":
@@ -173,14 +173,14 @@ class _Parser {
     }
 
     throw SourceSpanException(
-      "Unknown definition type '${_next().value}'",
-      _next().span,
+      "Unknown definition type '${_next()!.value}'",
+      _next()!.span,
     );
   }
 
   ExecutableDefinitionNode _parseExecutableDefinition() {
     if (_peek(TokenKind.name)) {
-      switch (_next().value) {
+      switch (_next()!.value) {
         case "query":
         case "mutation":
         case "subscription":
@@ -193,8 +193,8 @@ class _Parser {
     }
 
     throw SourceSpanException(
-      "Unknown executable definition '${_next().value}'",
-      _next().span,
+      "Unknown executable definition '${_next()!.value}'",
+      _next()!.span,
     );
   }
 
@@ -224,7 +224,7 @@ class _Parser {
     }
 
     final operationType = _parseOperationType();
-    NameNode name;
+    NameNode? name;
     if (_peek(TokenKind.name)) name = _parseName();
 
     return OperationDefinitionNode(
@@ -249,7 +249,7 @@ class _Parser {
 
     final type = _parseType();
 
-    ValueNode defaultValue;
+    ValueNode? defaultValue;
     if (_expectOptionalToken(TokenKind.equals) != null) {
       defaultValue = _parseValue(isConst: true);
     }
@@ -303,7 +303,7 @@ class _Parser {
   ObjectFieldNode _parseNonConstObjectField() =>
       _parseObjectField(isConst: false);
 
-  ObjectFieldNode _parseObjectField({bool isConst}) {
+  ObjectFieldNode _parseObjectField({bool? isConst}) {
     final name = _parseName("Expected an object field name");
 
     _expectToken(TokenKind.colon, "Missing ':' before object field value");
@@ -315,13 +315,13 @@ class _Parser {
 
   ValueNode _parseNonConstValue() => _parseValue(isConst: false);
 
-  ValueNode _parseValue({bool isConst}) {
-    final token = _next();
+  ValueNode _parseValue({bool? isConst}) {
+    final token = _next()!;
     switch (token.kind) {
       case TokenKind.bracketL:
-        return _parseList(isConst: isConst);
+        return _parseList(isConst: isConst!);
       case TokenKind.braceL:
-        return _parseObject(isConst: isConst);
+        return _parseObject(isConst: isConst!);
       case TokenKind.int:
         _advance();
 
@@ -354,7 +354,7 @@ class _Parser {
           name: _parseName(),
         );
       case TokenKind.dollar:
-        if (!isConst) {
+        if (!isConst!) {
           return _parseVariable();
         }
 
@@ -371,7 +371,7 @@ class _Parser {
   }
 
   StringValueNode _parseStringValue() {
-    final valueToken = _next();
+    final valueToken = _next()!;
     _advance();
 
     return StringValueNode(
@@ -380,7 +380,7 @@ class _Parser {
     );
   }
 
-  ListValueNode _parseList({bool isConst}) => ListValueNode(
+  ListValueNode _parseList({required bool isConst}) => ListValueNode(
         values: _parseMany(
           TokenKind.bracketL,
           isConst ? _parseConstValue : _parseNonConstValue,
@@ -388,7 +388,7 @@ class _Parser {
         ),
       );
 
-  ObjectValueNode _parseObject({bool isConst}) => ObjectValueNode(
+  ObjectValueNode _parseObject({required bool isConst}) => ObjectValueNode(
         fields: _parseMany(
           TokenKind.braceL,
           isConst ? _parseConstObjectField : _parseNonConstObjectField,
@@ -405,7 +405,7 @@ class _Parser {
     return directives;
   }
 
-  DirectiveNode _parseDirective({bool isConst}) {
+  DirectiveNode _parseDirective({required bool isConst}) {
     _expectToken(TokenKind.at, "Expected directive name starting with '@'");
 
     return DirectiveNode(
@@ -414,7 +414,8 @@ class _Parser {
     );
   }
 
-  List<ArgumentNode> _parseArguments({bool isConst}) => _maybeParseMany(
+  List<ArgumentNode> _parseArguments({required bool isConst}) =>
+      _maybeParseMany(
         TokenKind.parenL,
         isConst ? _parseConstArgument : _parseNonConstArgument,
         TokenKind.parenR,
@@ -424,7 +425,7 @@ class _Parser {
 
   ArgumentNode _parseNonConstArgument() => _parseArgument(isConst: false);
 
-  ArgumentNode _parseArgument({bool isConst}) {
+  ArgumentNode _parseArgument({bool? isConst}) {
     final name = _parseName("Expected an argument name");
 
     _expectToken(TokenKind.colon, "Expected ':' followed by argument value");
@@ -491,7 +492,7 @@ class _Parser {
   }
 
   NameNode _parseFragmentName() {
-    final token = _next();
+    final token = _next()!;
     if (token.value == "on") {
       throw SourceSpanException(
         "Invalid fragment name 'on'",
@@ -506,7 +507,7 @@ class _Parser {
     final nameOrAlias = _parseName("Expected a field or field alias name");
 
     NameNode name;
-    NameNode alias;
+    NameNode? alias;
 
     if (_expectOptionalToken(TokenKind.colon) != null) {
       alias = nameOrAlias;
@@ -518,7 +519,7 @@ class _Parser {
     final arguments = _parseArguments(isConst: false);
     final directives = _parseDirectives(isConst: false);
 
-    SelectionSetNode selectionSet;
+    SelectionSetNode? selectionSet;
     if (_peek(TokenKind.braceL)) {
       selectionSet = _parseSelectionSet();
     }
@@ -532,7 +533,7 @@ class _Parser {
     );
   }
 
-  NameNode _parseName([String errorMessage]) {
+  NameNode _parseName([String? errorMessage]) {
     final token = _expectToken(
       TokenKind.name,
       errorMessage ?? "Expected a name",
@@ -551,7 +552,7 @@ class _Parser {
     final token = _next(offset: keywordOffset);
 
     if (_peek(TokenKind.name, offset: keywordOffset)) {
-      switch (token.value) {
+      switch (token!.value) {
         case "schema":
           return _parseSchemaDefinition();
         case "scalar":
@@ -572,7 +573,7 @@ class _Parser {
     }
 
     throw SourceSpanException(
-      "Unknown type system definition type '${token.value}'",
+      "Unknown type system definition type '${token!.value}'",
       token.span,
     );
   }
@@ -582,8 +583,8 @@ class _Parser {
 
     final token = _next();
 
-    if (_peek(TokenKind.name) != null) {
-      switch (token.value) {
+    if (_peek(TokenKind.name)) {
+      switch (token!.value) {
         case "schema":
           return _parseSchemaExtension();
         case "scalar":
@@ -602,7 +603,7 @@ class _Parser {
     }
 
     throw SourceSpanException(
-      "Unknown type system extension type '${token.value}'",
+      "Unknown type system extension type '${token!.value}'",
       token.span,
     );
   }
@@ -647,7 +648,7 @@ class _Parser {
     );
   }
 
-  StringValueNode _parseDescription() {
+  StringValueNode? _parseDescription() {
     if (_peek(TokenKind.string) || _peek(TokenKind.blockString)) {
       return _parseStringValue();
     }
@@ -720,7 +721,7 @@ class _Parser {
     final name = _parseName("Expected an input value name");
     _expectToken(TokenKind.colon, "Expected ':' followed by input value type");
     final type = _parseType();
-    ValueNode defaultValue;
+    ValueNode? defaultValue;
     if (_expectOptionalToken(TokenKind.equals) != null) {
       defaultValue = _parseConstValue();
     }
@@ -925,7 +926,7 @@ class _Parser {
     if (directives.isEmpty && operationTypes.isEmpty) {
       throw SourceSpanException(
         "Schema extension must have either directives or operation types defined",
-        errorToken.span.expand(_next().span),
+        errorToken!.span!.expand(_next()!.span!),
       );
     }
 
@@ -946,7 +947,7 @@ class _Parser {
     if (directives.isEmpty) {
       throw SourceSpanException(
         "Scalar extension must have either directives defined",
-        errorToken.span.expand(_next().span),
+        errorToken!.span!.expand(_next()!.span!),
       );
     }
 
@@ -969,7 +970,7 @@ class _Parser {
     if (interfaces.isEmpty && directives.isEmpty && fields.isEmpty) {
       throw SourceSpanException(
         "Object type extension must define at least one directive or field, or implement at lease one interface",
-        errorToken.span.expand(_next().span),
+        errorToken!.span!.expand(_next()!.span!),
       );
     }
 
@@ -993,7 +994,7 @@ class _Parser {
     if (directives.isEmpty && fields.isEmpty) {
       throw SourceSpanException(
         "Interface type extension must define at least one directive or field",
-        errorToken.span.expand(_next().span),
+        errorToken!.span!.expand(_next()!.span!),
       );
     }
 
@@ -1016,7 +1017,7 @@ class _Parser {
     if (directives.isEmpty && types.isEmpty) {
       throw SourceSpanException(
         "Union type extension must define at least one directive or type",
-        errorToken.span.expand(_next().span),
+        errorToken!.span!.expand(_next()!.span!),
       );
     }
 
@@ -1039,7 +1040,7 @@ class _Parser {
     if (directives.isEmpty && values.isEmpty) {
       throw SourceSpanException(
         "Enum type extension must define at least one directive or value",
-        errorToken.span.expand(_next().span),
+        errorToken!.span!.expand(_next()!.span!),
       );
     }
 
@@ -1062,7 +1063,7 @@ class _Parser {
     if (directives.isEmpty && fields.isEmpty) {
       throw SourceSpanException(
         "Input type extension must define at least one directive or field, or implement at lease one interface",
-        errorToken.span.expand(_next().span),
+        errorToken!.span!.expand(_next()!.span!),
       );
     }
 
diff --git a/gql/lib/src/language/printer.dart b/gql/lib/src/language/printer.dart
index 17a21c8b..17c3c84d 100644
--- a/gql/lib/src/language/printer.dart
+++ b/gql/lib/src/language/printer.dart
@@ -68,14 +68,14 @@ class _PrintVisitor extends Visitor<String> {
         def.variable.accept(this),
         ": ",
         def.type.accept(this),
-        def.defaultValue.accept(this)
+        def.defaultValue!.accept(this)
       ].join();
 
   @override
   String visitDefaultValueNode(DefaultValueNode defaultValueNode) {
     if (defaultValueNode.value == null) return "";
 
-    return " = ${defaultValueNode.value.accept(this)}";
+    return " = ${defaultValueNode.value!.accept(this)}";
   }
 
   @override
@@ -87,11 +87,11 @@ class _PrintVisitor extends Visitor<String> {
         _opType(op.type),
         if (op.name != null) ...[
           " ",
-          op.name.accept(this),
+          op.name!.accept(this),
         ],
-        if (op.variableDefinitions != null && op.variableDefinitions.isNotEmpty)
+        if (op.variableDefinitions.isNotEmpty)
           visitVariableDefinitionSetNode(op.variableDefinitions),
-        if (op.directives != null && op.directives.isNotEmpty) ...[
+        if (op.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(op.directives),
         ],
@@ -106,8 +106,7 @@ class _PrintVisitor extends Visitor<String> {
   String visitDirectiveNode(DirectiveNode directiveNode) => [
         "@",
         directiveNode.name.accept(this),
-        if (directiveNode.arguments != null &&
-            directiveNode.arguments.isNotEmpty)
+        if (directiveNode.arguments.isNotEmpty)
           visitArgumentSetNode(directiveNode.arguments),
       ].join();
 
@@ -208,46 +207,35 @@ class _PrintVisitor extends Visitor<String> {
           FragmentDefinitionNode fragmentDefinitionNode) =>
       [
         "fragment ",
-        fragmentDefinitionNode.name.accept(this),
-        if (fragmentDefinitionNode.typeCondition != null) ...[
-          " ",
-          fragmentDefinitionNode.typeCondition.accept(this),
-        ],
-        if (fragmentDefinitionNode.directives != null &&
-            fragmentDefinitionNode.directives.isNotEmpty) ...[
+        fragmentDefinitionNode.name!.accept(this),
+        " ",
+        fragmentDefinitionNode.typeCondition.accept(this),
+        if (fragmentDefinitionNode.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(fragmentDefinitionNode.directives),
         ],
-        if (fragmentDefinitionNode.selectionSet != null) ...[
-          " ",
-          fragmentDefinitionNode.selectionSet.accept(this),
-        ],
+        " ",
+        fragmentDefinitionNode.selectionSet.accept(this),
       ].join();
 
   @override
   String visitInlineFragmentNode(InlineFragmentNode inlineFragmentNode) => [
         "...",
-        if (inlineFragmentNode.typeCondition != null) ...[
-          " ",
-          inlineFragmentNode.typeCondition.accept(this),
-        ],
-        if (inlineFragmentNode.directives != null &&
-            inlineFragmentNode.directives.isNotEmpty) ...[
+        " ",
+        inlineFragmentNode.typeCondition!.accept(this),
+        if (inlineFragmentNode.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(inlineFragmentNode.directives),
         ],
-        if (inlineFragmentNode.selectionSet != null) ...[
-          " ",
-          inlineFragmentNode.selectionSet.accept(this),
-        ],
+        " ",
+        inlineFragmentNode.selectionSet.accept(this),
       ].join();
 
   @override
   String visitFragmentSpreadNode(FragmentSpreadNode fragmentSpreadNode) => [
         "...",
         fragmentSpreadNode.name.accept(this),
-        if (fragmentSpreadNode.directives != null &&
-            fragmentSpreadNode.directives.isNotEmpty) ...[
+        if (fragmentSpreadNode.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(fragmentSpreadNode.directives),
         ],
@@ -263,20 +251,19 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitFieldNode(FieldNode fieldNode) => [
         if (fieldNode.alias != null) ...[
-          fieldNode.alias.accept(this),
+          fieldNode.alias!.accept(this),
           ": ",
         ],
         fieldNode.name.accept(this),
-        if (fieldNode.arguments != null && fieldNode.arguments.isNotEmpty)
+        if (fieldNode.arguments.isNotEmpty)
           visitArgumentSetNode(fieldNode.arguments),
-        if (fieldNode.directives != null &&
-            fieldNode.directives.isNotEmpty) ...[
+        if (fieldNode.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(fieldNode.directives),
         ],
         if (fieldNode.selectionSet != null) ...[
           " ",
-          visitSelectionSetNode(fieldNode.selectionSet),
+          visitSelectionSetNode(fieldNode.selectionSet!),
         ],
       ].join();
 
@@ -317,13 +304,13 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitScalarTypeDefinitionNode(ScalarTypeDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
         ],
         "scalar",
         " ",
-        node.name.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) ...[
+        node.name!.accept(this),
+        if (node.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(node.directives),
         ],
@@ -332,12 +319,12 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitObjectTypeDefinitionNode(ObjectTypeDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
         ],
         "type",
         " ",
-        node.name.accept(this),
+        node.name!.accept(this),
         " ",
         visitImplementsSetNode(node.interfaces),
         visitDirectiveSetNode(node.directives),
@@ -386,7 +373,7 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitFieldDefinitionNode(FieldDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
           _indent(_tabs),
         ],
@@ -395,7 +382,7 @@ class _PrintVisitor extends Visitor<String> {
         ":",
         " ",
         node.type.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) " ",
+        if (node.directives.isNotEmpty) " ",
         visitDirectiveSetNode(node.directives),
       ].join();
 
@@ -420,7 +407,7 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitInputValueDefinitionNode(InputValueDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
           _indent(_tabs),
         ],
@@ -432,21 +419,21 @@ class _PrintVisitor extends Visitor<String> {
           " ",
           "=",
           " ",
-          node.defaultValue.accept(this),
+          node.defaultValue!.accept(this),
         ],
-        if (node.directives != null && node.directives.isNotEmpty) " ",
+        if (node.directives.isNotEmpty) " ",
         visitDirectiveSetNode(node.directives),
       ].join();
 
   @override
   String visitInterfaceTypeDefinitionNode(InterfaceTypeDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
         ],
         "interface",
         " ",
-        node.name.accept(this),
+        node.name!.accept(this),
         " ",
         visitDirectiveSetNode(node.directives),
         visitFieldSetNode(node.fields),
@@ -455,13 +442,13 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitUnionTypeDefinitionNode(UnionTypeDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
         ],
         "union",
         " ",
-        node.name.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) ...[
+        node.name!.accept(this),
+        if (node.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(node.directives),
         ],
@@ -494,13 +481,13 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitEnumTypeDefinitionNode(EnumTypeDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
         ],
         "enum",
         " ",
-        node.name.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) ...[
+        node.name!.accept(this),
+        if (node.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(node.directives),
         ],
@@ -533,12 +520,12 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitEnumValueDefinitionNode(EnumValueDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
           _indent(_tabs),
         ],
-        node.name.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) " ",
+        node.name!.accept(this),
+        if (node.directives.isNotEmpty) " ",
         visitDirectiveSetNode(node.directives),
       ].join();
 
@@ -547,12 +534,12 @@ class _PrintVisitor extends Visitor<String> {
           InputObjectTypeDefinitionNode node) =>
       [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
         ],
         "input",
         " ",
-        node.name.accept(this),
+        node.name!.accept(this),
         " ",
         visitDirectiveSetNode(node.directives),
         visitInputValueDefinitionSetNode(node.fields),
@@ -583,13 +570,13 @@ class _PrintVisitor extends Visitor<String> {
   @override
   String visitDirectiveDefinitionNode(DirectiveDefinitionNode node) => [
         if (node.description != null) ...[
-          node.description.accept(this),
+          node.description!.accept(this),
           "\n",
         ],
         "directive",
         " ",
         "@",
-        node.name.accept(this),
+        node.name!.accept(this),
         visitArgumentDefinitionSetNode(node.args),
         if (node.repeatable) ...[
           " ",
@@ -627,11 +614,11 @@ class _PrintVisitor extends Visitor<String> {
         "extend",
         " ",
         "schema",
-        if (node.directives != null && node.directives.isNotEmpty) ...[
+        if (node.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(node.directives),
         ],
-        if (node.operationTypes != null && node.operationTypes.isNotEmpty) ...[
+        if (node.operationTypes.isNotEmpty) ...[
           " ",
           visitOperationTypeDefinitionSetNode(node.operationTypes),
         ],
@@ -643,8 +630,8 @@ class _PrintVisitor extends Visitor<String> {
         " ",
         "scalar",
         " ",
-        node.name.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) ...[
+        node.name!.accept(this),
+        if (node.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(node.directives),
         ],
@@ -656,7 +643,7 @@ class _PrintVisitor extends Visitor<String> {
         " ",
         "type",
         " ",
-        node.name.accept(this),
+        node.name!.accept(this),
         " ",
         visitImplementsSetNode(node.interfaces),
         visitDirectiveSetNode(node.directives),
@@ -669,7 +656,7 @@ class _PrintVisitor extends Visitor<String> {
         " ",
         "interface",
         " ",
-        node.name.accept(this),
+        node.name!.accept(this),
         " ",
         visitDirectiveSetNode(node.directives),
         visitFieldSetNode(node.fields),
@@ -681,8 +668,8 @@ class _PrintVisitor extends Visitor<String> {
         " ",
         "union",
         " ",
-        node.name.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) ...[
+        node.name!.accept(this),
+        if (node.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(node.directives),
         ],
@@ -695,8 +682,8 @@ class _PrintVisitor extends Visitor<String> {
         " ",
         "enum",
         " ",
-        node.name.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) ...[
+        node.name!.accept(this),
+        if (node.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(node.directives),
         ],
@@ -710,8 +697,8 @@ class _PrintVisitor extends Visitor<String> {
         " ",
         "input",
         " ",
-        node.name.accept(this),
-        if (node.directives != null && node.directives.isNotEmpty) ...[
+        node.name!.accept(this),
+        if (node.directives.isNotEmpty) ...[
           " ",
           visitDirectiveSetNode(node.directives),
         ],
@@ -719,7 +706,7 @@ class _PrintVisitor extends Visitor<String> {
       ].join();
 }
 
-String _opType(OperationType t) {
+String? _opType(OperationType t) {
   switch (t) {
     case OperationType.query:
       return "query";
@@ -728,12 +715,9 @@ String _opType(OperationType t) {
     case OperationType.subscription:
       return "subscription";
   }
-
-  // dead code to satisfy lint
-  return null;
 }
 
-String _directiveLocation(DirectiveLocation location) {
+String? _directiveLocation(DirectiveLocation location) {
   switch (location) {
     case DirectiveLocation.query:
       return "QUERY";
@@ -772,7 +756,4 @@ String _directiveLocation(DirectiveLocation location) {
     case DirectiveLocation.inputFieldDefinition:
       return "INPUT_FIELD_DEFINITION";
   }
-
-  // dead code to satisfy lint
-  return null;
 }
diff --git a/gql/lib/src/operation/definitions/base_types.dart b/gql/lib/src/operation/definitions/base_types.dart
index c4f6546e..67683298 100644
--- a/gql/lib/src/operation/definitions/base_types.dart
+++ b/gql/lib/src/operation/definitions/base_types.dart
@@ -12,7 +12,7 @@ abstract class ExecutableGraphQLEntity extends GraphQLEntity {
 @immutable
 abstract class ExecutableWithResolver extends ExecutableGraphQLEntity
     implements ExecutableTypeResolver {
-  const ExecutableWithResolver([GetExecutableType getType])
+  const ExecutableWithResolver([GetExecutableType? getType])
       : getType = getType ?? GetExecutableType.withoutContext,
         super();
 
@@ -32,7 +32,7 @@ abstract class ExecutableWithResolver extends ExecutableGraphQLEntity
   }
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash([astNode, getType]);
 }
diff --git a/gql/lib/src/operation/definitions/definitions.dart b/gql/lib/src/operation/definitions/definitions.dart
index b432585a..0d0abdf4 100644
--- a/gql/lib/src/operation/definitions/definitions.dart
+++ b/gql/lib/src/operation/definitions/definitions.dart
@@ -9,15 +9,15 @@ import "package:gql/src/operation/definitions/selections.dart";
 
 @immutable
 abstract class ExecutableDefinition extends ExecutableWithResolver {
-  const ExecutableDefinition([GetExecutableType getType]) : super(getType);
+  const ExecutableDefinition([GetExecutableType? getType]) : super(getType);
 
   @override
   ExecutableDefinitionNode get astNode;
 
-  String get name => astNode.name?.value;
+  String? get name => astNode.name?.value;
 
   static ExecutableDefinition fromNode(ExecutableDefinitionNode astNode,
-      [GetExecutableType getType]) {
+      [GetExecutableType? getType]) {
     if (astNode is OperationDefinitionNode) {
       return OperationDefinition(astNode, getType);
     }
@@ -40,7 +40,7 @@ abstract class ExecutableDefinition extends ExecutableWithResolver {
 class OperationDefinition extends ExecutableDefinition {
   const OperationDefinition(
     this.astNode, [
-    GetExecutableType getType,
+    GetExecutableType? getType,
   ]) : super(getType);
 
   @override
@@ -48,15 +48,15 @@ class OperationDefinition extends ExecutableDefinition {
 
   OperationType get type => astNode.type;
 
-  ObjectTypeDefinition get schemaType =>
-      getType.fromSchema(type.name) as ObjectTypeDefinition;
+  ObjectTypeDefinition? get schemaType =>
+      getType.fromSchema!(type.name) as ObjectTypeDefinition?;
 
   List<VariableDefinition> get variables =>
       astNode.variableDefinitions.map((v) => VariableDefinition(v)).toList();
 
   SelectionSet get selectionSet => SelectionSet(
         astNode.selectionSet,
-        getType.fromSchema(type.name) as ObjectTypeDefinition,
+        getType.fromSchema!(type.name) as ObjectTypeDefinition?,
         getType,
       );
 }
@@ -72,7 +72,7 @@ class OperationDefinition extends ExecutableDefinition {
 /// when querying against an [InterfaceTypeDefinition] or [UnionTypeDefinition].
 @immutable
 class FragmentDefinition extends ExecutableDefinition {
-  const FragmentDefinition(this.astNode, [GetExecutableType getType])
+  const FragmentDefinition(this.astNode, [GetExecutableType? getType])
       : super(getType);
 
   @override
@@ -80,7 +80,7 @@ class FragmentDefinition extends ExecutableDefinition {
 
   TypeCondition get _typeCondition => TypeCondition(astNode.typeCondition);
 
-  TypeDefinition get onType => getType.fromSchema(_typeCondition.on.name);
+  TypeDefinition? get onType => getType.fromSchema!(_typeCondition.on.name);
 
   List<Directive> get directives =>
       astNode.directives.map((d) => Directive(d)).toList();
@@ -104,9 +104,9 @@ class TypeCondition extends ExecutableGraphQLEntity {
   const TypeCondition(this.astNode);
 
   @override
-  final TypeConditionNode astNode;
+  final TypeConditionNode? astNode;
 
-  NamedType get on => NamedType(astNode.on);
+  NamedType get on => NamedType(astNode!.on);
 }
 
 /// [Variables](https://spec.graphql.org/June2018/#sec-Language.Variables)
@@ -120,7 +120,7 @@ class TypeCondition extends ExecutableGraphQLEntity {
 /// the execution of that operation.
 @immutable
 class VariableDefinition extends ExecutableWithResolver {
-  const VariableDefinition(this.astNode, [GetExecutableType getType])
+  const VariableDefinition(this.astNode, [GetExecutableType? getType])
       : super(getType);
 
   @override
diff --git a/gql/lib/src/operation/definitions/selections.dart b/gql/lib/src/operation/definitions/selections.dart
index 32dcddf8..f4372016 100644
--- a/gql/lib/src/operation/definitions/selections.dart
+++ b/gql/lib/src/operation/definitions/selections.dart
@@ -21,15 +21,15 @@ class SelectionSet extends ExecutableWithResolver {
   const SelectionSet(
     this.astNode, [
     this.schemaType,
-    GetExecutableType getType,
+    GetExecutableType? getType,
   ]) : super(getType);
 
-  final TypeDefinition schemaType;
+  final TypeDefinition? schemaType;
 
   @override
-  final SelectionSetNode astNode;
+  final SelectionSetNode? astNode;
 
-  List<Selection> get selections => astNode.selections
+  List<Selection> get selections => astNode!.selections
       .map((selection) => Selection.fromNode(selection, schemaType, getType))
       .toList();
 
@@ -46,9 +46,9 @@ class SelectionSet extends ExecutableWithResolver {
 /// ([Field]s, [FragmentSpread]s, or [InlineFragment]s)s
 @immutable
 abstract class Selection extends ExecutableWithResolver {
-  const Selection([GetExecutableType getType]) : super(getType);
+  const Selection([GetExecutableType? getType]) : super(getType);
 
-  GraphQLEntity get schemaType;
+  GraphQLEntity? get schemaType;
 
   @override
   SelectionNode get astNode;
@@ -59,8 +59,8 @@ abstract class Selection extends ExecutableWithResolver {
     SelectionNode astNode, [
 
     /// The [schemaType] of the containing element
-    TypeDefinition schemaType,
-    GetExecutableType getType,
+    TypeDefinition? schemaType,
+    GetExecutableType? getType,
   ]) {
     if (astNode is FieldNode) {
       // fields can only be selected on Interface and Object types
@@ -79,7 +79,7 @@ abstract class Selection extends ExecutableWithResolver {
     }
     if (astNode is InlineFragmentNode) {
       // inline fragments must always specify a type condition
-      final onType = getType.fromSchema(astNode.typeCondition.on.name.value);
+      final onType = getType!.fromSchema!(astNode.typeCondition!.on.name.value);
       return InlineFragment(astNode, onType, getType);
     }
 
@@ -102,21 +102,21 @@ class Field extends Selection {
   const Field(
     this.astNode, [
     this.schemaType,
-    GetExecutableType getType,
+    GetExecutableType? getType,
   ]) : super(getType);
 
   @override
   final FieldNode astNode;
 
   @override
-  final FieldDefinition schemaType;
+  final FieldDefinition? schemaType;
 
   @override
   String get alias => astNode.alias?.value ?? name;
 
   String get name => astNode.name.value;
 
-  GraphQLType get type => schemaType.type;
+  GraphQLType? get type => schemaType!.type;
 
   List<Argument> get arguments =>
       astNode.arguments.map((a) => Argument(a)).toList();
@@ -124,10 +124,10 @@ class Field extends Selection {
   List<Directive> get directives =>
       astNode.directives.map((d) => Directive(d)).toList();
 
-  SelectionSet get selectionSet => astNode.selectionSet != null
+  SelectionSet? get selectionSet => astNode.selectionSet != null
       ? SelectionSet(
           astNode.selectionSet,
-          getType.fromSchema(type.baseTypeName),
+          getType.fromSchema!(type!.baseTypeName),
           getType,
         )
       : null;
@@ -143,14 +143,14 @@ class Field extends Selection {
 @immutable
 class FragmentSpread extends Selection {
   const FragmentSpread(this.astNode,
-      [this.schemaType, GetExecutableType getType])
+      [this.schemaType, GetExecutableType? getType])
       : super(getType);
 
   @override
   final FragmentSpreadNode astNode;
 
   @override
-  final TypeDefinition schemaType;
+  final TypeDefinition? schemaType;
 
   String get name => astNode.name.value;
 
@@ -180,7 +180,7 @@ class InlineFragment extends Selection {
   const InlineFragment(
     this.astNode, [
     this.schemaType,
-    GetExecutableType getType,
+    GetExecutableType? getType,
   ]) : super(getType);
 
   @override
@@ -188,8 +188,8 @@ class InlineFragment extends Selection {
 
   TypeCondition get typeCondition => TypeCondition(astNode.typeCondition);
 
-  TypeDefinitionWithFieldSet get onType =>
-      getType.fromSchema(onTypeName) as TypeDefinitionWithFieldSet;
+  TypeDefinitionWithFieldSet? get onType =>
+      getType.fromSchema!(onTypeName) as TypeDefinitionWithFieldSet?;
 
   String get onTypeName => typeCondition.on.name;
 
@@ -197,7 +197,7 @@ class InlineFragment extends Selection {
   String get alias => "on$onTypeName";
 
   @override
-  final TypeDefinition schemaType;
+  final TypeDefinition? schemaType;
 
   List<Directive> get directives =>
       astNode.directives.map((d) => Directive(d)).toList();
diff --git a/gql/lib/src/operation/definitions/type_resolver.dart b/gql/lib/src/operation/definitions/type_resolver.dart
index 0a63e7fc..d63de64c 100644
--- a/gql/lib/src/operation/definitions/type_resolver.dart
+++ b/gql/lib/src/operation/definitions/type_resolver.dart
@@ -5,7 +5,7 @@ import "package:gql/src/schema/definitions.dart";
 import "package:gql/src/operation/definitions.dart";
 
 /// Callback to dereference a full fragment definition by name
-typedef ResolveFragment = FragmentDefinition Function(String name);
+typedef ResolveFragment = FragmentDefinition? Function(String name);
 
 /// Container for the [fromSchema] and [fromFragments]
 /// dereferencing callbacks necessary for full type information while
@@ -23,7 +23,7 @@ class GetExecutableType {
   /// usually defined within the given context such as a `GraphQLSchema`.
   ///
   /// See `gql/schema.dart`'s [TypeResolver].
-  final ResolveType fromSchema;
+  final ResolveType? fromSchema;
 
   final ResolveFragment fromFragments;
 
@@ -40,7 +40,7 @@ class GetExecutableType {
   }
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash([fromFragments, fromSchema]);
 
diff --git a/gql/lib/src/operation/executable.dart b/gql/lib/src/operation/executable.dart
index db43614d..aad2ad20 100644
--- a/gql/lib/src/operation/executable.dart
+++ b/gql/lib/src/operation/executable.dart
@@ -26,7 +26,7 @@ class ExecutableDocument extends ExecutableWithResolver {
   ])  : _fragmentNodeMap = _collectImportedFragmentNodes([astNode, ...imports]),
         super();
 
-  final ResolveType getSchemaType;
+  final ResolveType? getSchemaType;
   final Map<String, FragmentDefinitionNode> _fragmentNodeMap;
 
   @override
@@ -36,7 +36,7 @@ class ExecutableDocument extends ExecutableWithResolver {
   @override
   final DocumentNode astNode;
 
-  FragmentDefinition getFragment(String name) {
+  FragmentDefinition? getFragment(String name) {
     final node = _fragmentNodeMap[name];
     if (node == null) {
       return null;
@@ -65,7 +65,7 @@ Map<String, FragmentDefinitionNode> _collectImportedFragmentNodes(
           .whereType<FragmentDefinitionNode>()
           .map(
             (fragmentNode) => MapEntry(
-              fragmentNode.name.value,
+              fragmentNode.name!.value,
               fragmentNode,
             ),
           ),
diff --git a/gql/lib/src/schema/defaults.dart b/gql/lib/src/schema/defaults.dart
index f76ddd88..b9858ee4 100644
--- a/gql/lib/src/schema/defaults.dart
+++ b/gql/lib/src/schema/defaults.dart
@@ -45,19 +45,19 @@ class _BuiltInFieldDefinition extends FieldDefinition {
   }) : super(null);
 
   @override
-  final String name;
+  final String? name;
 
   @override
-  final String description;
+  final String? description;
 
   @override
-  final GraphQLType type;
+  final GraphQLType? type;
 
   @override
-  final List<Directive> directives;
+  final List<Directive>? directives;
 
   @override
-  final List<InputValueDefinition> args;
+  final List<InputValueDefinition>? args;
 }
 
 const typeNameField = _BuiltInFieldDefinition(
@@ -83,15 +83,15 @@ class _BuiltInArgument extends InputValueDefinition {
   }) : super(null);
 
   @override
-  final String description;
+  final String? description;
   @override
-  final String name;
+  final String? name;
   @override
-  final GraphQLType type;
+  final GraphQLType? type;
   @override
-  final Value defaultValue;
+  final Value? defaultValue;
   @override
-  final List<Directive> directives;
+  final List<Directive>? directives;
 }
 
 @immutable
@@ -105,13 +105,13 @@ class _BuiltInDirective extends DirectiveDefinition {
   }) : super(null);
 
   @override
-  final String name;
+  final String? name;
   @override
-  final String description;
+  final String? description;
   @override
-  final List<InputValueDefinition> args;
+  final List<InputValueDefinition>? args;
   @override
-  final List<DirectiveLocation> locations;
+  final List<DirectiveLocation>? locations;
 
   @override
   final bool repeatable;
diff --git a/gql/lib/src/schema/definitions/base_types.dart b/gql/lib/src/schema/definitions/base_types.dart
index 4986b673..5618caef 100644
--- a/gql/lib/src/schema/definitions/base_types.dart
+++ b/gql/lib/src/schema/definitions/base_types.dart
@@ -21,9 +21,9 @@ abstract class GraphQLEntity {
   const GraphQLEntity();
 
   @override
-  String toString() => printNode(astNode);
+  String toString() => printNode(astNode!);
 
-  Node get astNode;
+  Node? get astNode;
 
   @override
   bool operator ==(Object o) {
@@ -43,7 +43,7 @@ abstract class GraphQLEntity {
 @immutable
 abstract class EntityWithResolver extends GraphQLEntity
     implements TypeResolver {
-  const EntityWithResolver([ResolveType getType])
+  const EntityWithResolver([ResolveType? getType])
       : getType = getType ?? TypeResolver.withoutContext,
         super();
 
@@ -63,7 +63,7 @@ abstract class EntityWithResolver extends GraphQLEntity
   }
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash([astNode, getType]);
 }
@@ -109,7 +109,7 @@ abstract class GraphQLType extends EntityWithResolver {
 
   static GraphQLType fromNode(
     TypeNode astNode, [
-    ResolveType getType,
+    ResolveType? getType,
   ]) {
     if (astNode is NamedTypeNode) {
       return NamedType(astNode, getType);
@@ -129,7 +129,7 @@ abstract class GraphQLType extends EntityWithResolver {
 class NamedType extends GraphQLType {
   const NamedType(
     this.astNode, [
-    ResolveType getType,
+    ResolveType? getType,
   ])  : getType = getType ?? TypeResolver.withoutContext,
         super();
 
@@ -142,7 +142,7 @@ class NamedType extends GraphQLType {
   /// (verifiable via [hasResolver]).
   ///
   /// See [TypeResolver] for mor details on type resolution.
-  TypeDefinition get type => getType(name);
+  TypeDefinition? get type => getType(name);
 
   /// Whether it is safe to resolve the referenced type via [type]
   bool get hasResolver => getType != TypeResolver.withoutContext;
@@ -167,7 +167,7 @@ class NamedType extends GraphQLType {
 class ListType extends GraphQLType {
   const ListType(
     this.astNode, [
-    ResolveType getType,
+    ResolveType? getType,
   ])  : getType = getType ?? TypeResolver.withoutContext,
         super();
 
@@ -222,9 +222,9 @@ abstract class TypeSystemDefinition extends GraphQLEntity {
 
   /// The underlying definition node from `gql/ast.dart`
   @override
-  TypeSystemDefinitionNode get astNode;
+  TypeSystemDefinitionNode? get astNode;
 
-  String get name => astNode.name.value;
+  String? get name => astNode!.name!.value;
 }
 
 /// The fundamental unit of any GraphQL Schema ([spec](https://spec.graphql.org/June2018/#TypeDefinition)).
@@ -262,7 +262,7 @@ abstract class TypeDefinition extends TypeSystemDefinition {
   @override
   TypeDefinitionNode get astNode;
 
-  String get description => astNode.description?.value;
+  String? get description => astNode.description?.value;
 
   List<Directive> get directives =>
       astNode.directives.map((d) => Directive(d)).toList();
@@ -307,7 +307,7 @@ abstract class TypeDefinition extends TypeSystemDefinition {
 @immutable
 abstract class TypeDefinitionWithResolver extends TypeDefinition
     implements TypeResolver {
-  const TypeDefinitionWithResolver([ResolveType getType])
+  const TypeDefinitionWithResolver([ResolveType? getType])
       : getType = getType ?? TypeResolver.withoutContext,
         super();
 
@@ -327,7 +327,7 @@ abstract class TypeDefinitionWithResolver extends TypeDefinition
   }
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash([astNode, getType]);
 }
diff --git a/gql/lib/src/schema/definitions/definitions.dart b/gql/lib/src/schema/definitions/definitions.dart
index 0b3bb211..40ce8a86 100644
--- a/gql/lib/src/schema/definitions/definitions.dart
+++ b/gql/lib/src/schema/definitions/definitions.dart
@@ -27,7 +27,6 @@ extension WithTypeName on OperationType {
       case OperationType.subscription:
         return "subscription";
     }
-    throw StateError("Impossible OperationType $this");
   }
 }
 
@@ -48,8 +47,8 @@ extension WithTypeName on OperationType {
 class FieldDefinition extends EntityWithResolver {
   const FieldDefinition(
     this.astNode, [
-    ResolveType getType,
-    bool isOverride,
+    ResolveType? getType,
+    bool? isOverride,
   ])  : getType = getType ?? TypeResolver.withoutContext,
         isOverride = isOverride ?? false;
 
@@ -59,18 +58,18 @@ class FieldDefinition extends EntityWithResolver {
   final bool isOverride;
 
   @override
-  final FieldDefinitionNode astNode;
+  final FieldDefinitionNode? astNode;
 
-  String get name => astNode.name.value;
+  String? get name => astNode!.name.value;
 
-  String get description => astNode.description?.value;
+  String? get description => astNode!.description?.value;
 
-  GraphQLType get type => GraphQLType.fromNode(astNode.type, getType);
+  GraphQLType? get type => GraphQLType.fromNode(astNode!.type, getType);
 
-  List<Directive> get directives =>
-      astNode.directives.map((d) => Directive(d)).toList();
+  List<Directive>? get directives =>
+      astNode!.directives.map((d) => Directive(d)).toList();
 
-  List<InputValueDefinition> get args => astNode.args
+  List<InputValueDefinition>? get args => astNode!.args
       .map(
         (arg) => InputValueDefinition(arg, getType),
       )
@@ -81,7 +80,7 @@ class FieldDefinition extends EntityWithResolver {
 @immutable
 abstract class TypeDefinitionWithFieldSet extends TypeDefinitionWithResolver {
   const TypeDefinitionWithFieldSet([
-    ResolveType getType,
+    ResolveType? getType,
   ])  : getType = getType ?? TypeResolver.withoutContext,
         super();
 
@@ -107,7 +106,7 @@ class InterfaceTypeDefinition extends TypeDefinitionWithFieldSet
     with AbstractType {
   const InterfaceTypeDefinition(
     this.astNode, [
-    ResolveType getType,
+    ResolveType? getType,
   ]) : super(getType);
 
   @override
@@ -150,7 +149,7 @@ class InterfaceTypeDefinition extends TypeDefinitionWithFieldSet
 class ObjectTypeDefinition extends TypeDefinitionWithFieldSet {
   const ObjectTypeDefinition(
     this.astNode, [
-    ResolveType getType,
+    ResolveType? getType,
   ]) : super(getType);
 
   @override
@@ -182,14 +181,14 @@ class ObjectTypeDefinition extends TypeDefinitionWithFieldSet {
       )
       .toList();
 
-  List<InterfaceTypeDefinition> get interfaces => interfaceNames
-      .map((i) => getType(i.name) as InterfaceTypeDefinition)
+  List<InterfaceTypeDefinition?> get interfaces => interfaceNames
+      .map((i) => getType(i.name) as InterfaceTypeDefinition?)
       .toList();
 
   /// Extract all inherited interface names recursively
-  Set<String> get _inheritedFieldNames => interfaces
+  Set<String?> get _inheritedFieldNames => interfaces
       .expand(
-        (face) => face._fields.map((f) => f.name),
+        (face) => face!._fields.map((f) => f.name),
       )
       .toSet();
 }
@@ -206,7 +205,7 @@ class ObjectTypeDefinition extends TypeDefinitionWithFieldSet {
 class UnionTypeDefinition extends TypeDefinitionWithResolver with AbstractType {
   const UnionTypeDefinition(
     this.astNode, [
-    ResolveType getType,
+    ResolveType? getType,
   ]) : getType = getType ?? TypeResolver.withoutContext;
 
   @override
@@ -242,7 +241,7 @@ class UnionTypeDefinition extends TypeDefinitionWithResolver with AbstractType {
 class InputObjectTypeDefinition extends TypeDefinitionWithResolver {
   const InputObjectTypeDefinition(
     this.astNode, [
-    ResolveType getType,
+    ResolveType? getType,
   ]) : getType = getType ?? TypeResolver.withoutContext;
 
   @override
@@ -264,25 +263,25 @@ class InputObjectTypeDefinition extends TypeDefinitionWithResolver {
 class InputValueDefinition extends EntityWithResolver {
   const InputValueDefinition(
     this.astNode, [
-    ResolveType getType,
+    ResolveType? getType,
   ]) : getType = getType ?? TypeResolver.withoutContext;
 
   @override
   final ResolveType getType;
 
   @override
-  final InputValueDefinitionNode astNode;
+  final InputValueDefinitionNode? astNode;
 
-  String get name => astNode.name.value;
+  String? get name => astNode!.name.value;
 
-  String get description => astNode.description?.value;
+  String? get description => astNode!.description?.value;
 
-  GraphQLType get type => GraphQLType.fromNode(astNode.type, getType);
+  GraphQLType? get type => GraphQLType.fromNode(astNode!.type, getType);
 
-  Value get defaultValue => Value.fromNode(astNode.defaultValue);
+  Value? get defaultValue => Value.fromNode(astNode!.defaultValue);
 
-  List<Directive> get directives =>
-      astNode.directives.map((d) => Directive(d)).toList();
+  List<Directive>? get directives =>
+      astNode!.directives.map((d) => Directive(d)).toList();
 }
 
 /*
@@ -341,17 +340,17 @@ class DirectiveDefinition extends TypeSystemDefinition {
   const DirectiveDefinition(this.astNode);
 
   @override
-  final DirectiveDefinitionNode astNode;
+  final DirectiveDefinitionNode? astNode;
 
-  String get description => astNode.description?.value;
+  String? get description => astNode!.description?.value;
 
-  List<InputValueDefinition> get args => astNode.args
+  List<InputValueDefinition>? get args => astNode!.args
       .map((inputValue) => InputValueDefinition(inputValue))
       .toList();
 
-  List<DirectiveLocation> get locations => astNode.locations;
+  List<DirectiveLocation>? get locations => astNode!.locations;
 
-  bool get repeatable => astNode.repeatable;
+  bool get repeatable => astNode!.repeatable;
 }
 
 /// A [Root Operation](https://spec.graphql.org/June2018/#sec-Root-Operation-Types).
diff --git a/gql/lib/src/schema/definitions/type_resolver.dart b/gql/lib/src/schema/definitions/type_resolver.dart
index 278c6742..080edff6 100644
--- a/gql/lib/src/schema/definitions/type_resolver.dart
+++ b/gql/lib/src/schema/definitions/type_resolver.dart
@@ -1,4 +1,3 @@
-import "package:collection/collection.dart";
 import "package:meta/meta.dart";
 import "./base_types.dart" show TypeDefinition;
 import "./definitions.dart"
@@ -9,7 +8,7 @@ import "./definitions.dart"
         InputObjectTypeDefinition;
 
 /// Callback to dereference a full type definition by name
-typedef ResolveType = TypeDefinition Function(String name);
+typedef ResolveType = TypeDefinition? Function(String name);
 
 /// Enables "type resolution" for implementing classes,
 /// allowing for type-dereferencing, such as is done by `GraphQLSchema`.
@@ -22,8 +21,8 @@ abstract class TypeResolver {
   ResolveType get getType;
 
   /// Saturates the [definition] with a [getType] if it extends from [TypeResolver]
-  static TypeDefinition addedTo(
-    TypeDefinition definition,
+  static TypeDefinition? addedTo(
+    TypeDefinition? definition,
     ResolveType getType,
   ) {
     if (definition == null) {
diff --git a/gql/lib/src/schema/definitions/value_types.dart b/gql/lib/src/schema/definitions/value_types.dart
index dd9b373f..bf92993a 100644
--- a/gql/lib/src/schema/definitions/value_types.dart
+++ b/gql/lib/src/schema/definitions/value_types.dart
@@ -21,9 +21,9 @@ abstract class Value extends GraphQLEntity {
   const Value();
 
   @override
-  ValueNode get astNode;
+  ValueNode? get astNode;
 
-  static Value fromNode(ValueNode node) {
+  static Value fromNode(ValueNode? node) {
     if (node is IntValueNode) {
       return IntValue(node);
     }
@@ -79,9 +79,9 @@ class StringValue extends Value {
   const StringValue(this.astNode);
 
   @override
-  final StringValueNode astNode;
+  final StringValueNode? astNode;
 
-  String get value => astNode.value;
+  String get value => astNode!.value;
 }
 
 @immutable
@@ -155,9 +155,9 @@ class DefaultValue extends GraphQLEntity {
   const DefaultValue(this.astNode);
 
   @override
-  final DefaultValueNode astNode;
+  final DefaultValueNode? astNode;
 
-  Value get value => Value.fromNode(astNode.value);
+  Value get value => Value.fromNode(astNode!.value);
 }
 
 // While I don't believe VariableValues are possible in the schema definition,
diff --git a/gql/lib/src/schema/schema.dart b/gql/lib/src/schema/schema.dart
index 66ce0e3d..fdc5db2a 100644
--- a/gql/lib/src/schema/schema.dart
+++ b/gql/lib/src/schema/schema.dart
@@ -1,5 +1,6 @@
 import "dart:collection";
 
+import "package:collection/collection.dart" show IterableExtension;
 import "package:meta/meta.dart";
 import "package:gql/ast.dart";
 
@@ -21,35 +22,35 @@ class GraphQLSchema extends TypeSystemDefinition {
   const GraphQLSchema(
     this.astNode, {
     this.fullDocumentAst,
-    Map<String, TypeDefinition> typeMap,
+    Map<String?, TypeDefinition?>? typeMap,
     this.directives,
   }) : _typeMap = typeMap;
 
   @override
-  final SchemaDefinitionNode astNode;
+  final SchemaDefinitionNode? astNode;
 
-  final DocumentNode fullDocumentAst;
+  final DocumentNode? fullDocumentAst;
 
-  final List<DirectiveDefinition> directives;
+  final List<DirectiveDefinition>? directives;
 
   /// Definition for the given directive [name], if any exists
-  DirectiveDefinition getDirective(String name) => directives.firstWhere(
+  DirectiveDefinition? getDirective(String name) =>
+      directives!.firstWhereOrNull(
         (d) => d.name == name,
-        orElse: () => null,
       );
 
-  List<OperationTypeDefinition> get operationTypes => astNode.operationTypes
+  List<OperationTypeDefinition> get operationTypes => astNode!.operationTypes
       .map(
         (o) => OperationTypeDefinition(o),
       )
       .toList();
 
   /// Map of all type names to their respective [TypeDefinition]s
-  final Map<String, TypeDefinition> _typeMap;
+  final Map<String?, TypeDefinition?>? _typeMap;
 
   /// Map of all type names to their respective [TypeDefinition]s,
   /// with type resolution enabled (if applicable)
-  Map<String, TypeDefinition> get typeMap => _typeMap.map(
+  Map<String?, TypeDefinition?> get typeMap => _typeMap!.map(
         (name, definition) => MapEntry(
           name,
           _withAwareness(definition),
@@ -60,21 +61,21 @@ class GraphQLSchema extends TypeSystemDefinition {
   ///
   /// [EnumTypeDefinition] and [ScalarTypeDefinition] do not accept [getType]
   /// because they cannot include references
-  TypeDefinition _withAwareness(TypeDefinition definition) =>
+  TypeDefinition? _withAwareness(TypeDefinition? definition) =>
       TypeResolver.addedTo(definition, getType) ?? definition;
 
   /// Resolve the given [name] into a [TypeDefinition] defined within the schema
-  TypeDefinition getType(String name) => _withAwareness(_typeMap[name]);
+  TypeDefinition? getType(String name) => _withAwareness(_typeMap![name]);
 
-  ObjectTypeDefinition _getObjectType(String name) =>
-      _withAwareness(_typeMap[name]) as ObjectTypeDefinition;
+  ObjectTypeDefinition? _getObjectType(String name) =>
+      _withAwareness(_typeMap![name]) as ObjectTypeDefinition?;
 
-  Iterable<TypeDefinition> get _allTypeDefinitions =>
-      LinkedHashSet<TypeDefinition>.from(_typeMap.values).map(_withAwareness);
+  Iterable<TypeDefinition?> get _allTypeDefinitions =>
+      LinkedHashSet<TypeDefinition>.from(_typeMap!.values).map(_withAwareness);
 
-  ObjectTypeDefinition get query => _getObjectType("query");
-  ObjectTypeDefinition get mutation => _getObjectType("mutation");
-  ObjectTypeDefinition get subscription => _getObjectType("subscription");
+  ObjectTypeDefinition? get query => _getObjectType("query");
+  ObjectTypeDefinition? get mutation => _getObjectType("mutation");
+  ObjectTypeDefinition? get subscription => _getObjectType("subscription");
 
   List<InterfaceTypeDefinition> get interaces =>
       _getAll<InterfaceTypeDefinition>();
@@ -93,7 +94,7 @@ class GraphQLSchema extends TypeSystemDefinition {
       _allTypeDefinitions.whereType<T>().toList();
 
   /// Get the possible [ObjectTypeDefinition]s that the given [abstractType] could be resolved into
-  List<ObjectTypeDefinition> getPossibleTypes(AbstractType abstractType) {
+  List<ObjectTypeDefinition> getPossibleTypes(AbstractType? abstractType) {
     if (abstractType is UnionTypeDefinition) {
       return abstractType.types;
     }
@@ -128,7 +129,7 @@ GraphQLSchema buildSchema(
     assertValidSDL(documentAST);
   }
   */
-  SchemaDefinitionNode schemaDef;
+  SchemaDefinitionNode? schemaDef;
   final _typeDefs = <TypeDefinitionNode>[];
   final _directiveDefs = <DirectiveDefinitionNode>[];
 
@@ -165,16 +166,16 @@ GraphQLSchema buildSchema(
   );
 }
 
-Map<String, ObjectTypeDefinition> _operationTypeMap(
-  Map<String, TypeDefinition> typeMap,
-  SchemaDefinitionNode schemaDef,
+Map<String, ObjectTypeDefinition?> _operationTypeMap(
+  Map<String?, TypeDefinition> typeMap,
+  SchemaDefinitionNode? schemaDef,
 ) {
   final operationTypeNames = _getOperationTypeNames(schemaDef);
   return Map.fromEntries(
     operationTypeNames.entries
         .map((e) => MapEntry(
               e.key.name,
-              typeMap[e.value] as ObjectTypeDefinition,
+              typeMap[e.value] as ObjectTypeDefinition?,
             ))
         .where((e) => e.value != null),
   );
@@ -182,7 +183,7 @@ Map<String, ObjectTypeDefinition> _operationTypeMap(
 
 /// Resolve a map of { [OperationType]: [String] typeName }
 Map<OperationType, String> _getOperationTypeNames(
-    [SchemaDefinitionNode schema]) {
+    [SchemaDefinitionNode? schema]) {
   if (schema == null) {
     return {
       OperationType.query: "Query",
diff --git a/gql/lib/src/validation/rules/lone_schema_definition.dart b/gql/lib/src/validation/rules/lone_schema_definition.dart
index c10e17a6..c987d9dd 100644
--- a/gql/lib/src/validation/rules/lone_schema_definition.dart
+++ b/gql/lib/src/validation/rules/lone_schema_definition.dart
@@ -4,7 +4,7 @@ import "package:gql/src/validation/validator.dart";
 
 class MultipleSchemaDefinitionsError extends ValidationError {
   const MultipleSchemaDefinitionsError({
-    SchemaDefinitionNode node,
+    SchemaDefinitionNode? node,
   }) : super(
           node: node,
         );
diff --git a/gql/lib/src/validation/rules/unique_argument_names.dart b/gql/lib/src/validation/rules/unique_argument_names.dart
index 31562ada..2b98a87e 100644
--- a/gql/lib/src/validation/rules/unique_argument_names.dart
+++ b/gql/lib/src/validation/rules/unique_argument_names.dart
@@ -4,7 +4,7 @@ import "package:gql/src/validation/validator.dart";
 
 class DuplicateArgumentNameError extends ValidationError {
   const DuplicateArgumentNameError({
-    ArgumentNode node,
+    ArgumentNode? node,
   }) : super(
           node: node,
         );
diff --git a/gql/lib/src/validation/rules/unique_directive_names.dart b/gql/lib/src/validation/rules/unique_directive_names.dart
index 2a1b1351..2121bdd0 100644
--- a/gql/lib/src/validation/rules/unique_directive_names.dart
+++ b/gql/lib/src/validation/rules/unique_directive_names.dart
@@ -4,7 +4,7 @@ import "package:gql/src/validation/validator.dart";
 
 class DuplicateDirectiveNameError extends ValidationError {
   const DuplicateDirectiveNameError({
-    DirectiveDefinitionNode node,
+    DirectiveDefinitionNode? node,
   }) : super(
           node: node,
         );
@@ -16,13 +16,13 @@ class UniqueDirectiveNames extends ValidatingVisitor {
   @override
   List<ValidationError> visitDirectiveDefinitionNode(
       DirectiveDefinitionNode node) {
-    if (directiveNames.contains(node.name.value)) {
+    if (directiveNames.contains(node.name!.value)) {
       return [
         DuplicateDirectiveNameError(node: node),
       ];
     }
 
-    directiveNames.add(node.name.value);
+    directiveNames.add(node.name!.value);
 
     return [];
   }
diff --git a/gql/lib/src/validation/rules/unique_enum_value_names.dart b/gql/lib/src/validation/rules/unique_enum_value_names.dart
index 54a57ef9..7199b24a 100644
--- a/gql/lib/src/validation/rules/unique_enum_value_names.dart
+++ b/gql/lib/src/validation/rules/unique_enum_value_names.dart
@@ -3,11 +3,11 @@ import "package:gql/src/validation/validating_visitor.dart";
 import "package:gql/src/validation/validator.dart";
 
 class DuplicateEnumValueNameError extends ValidationError {
-  final EnumValueDefinitionNode valueNode;
+  final EnumValueDefinitionNode? valueNode;
 
   const DuplicateEnumValueNameError({
     this.valueNode,
-    NameNode nameNode,
+    NameNode? nameNode,
   }) : super(
           node: nameNode,
         );
@@ -31,7 +31,7 @@ class UniqueEnumValueNames extends ValidatingVisitor {
       node.values.fold<_Accumulator>(
         _Accumulator(),
         (fold, node) {
-          if (fold.valueNames.contains(node.name.value)) {
+          if (fold.valueNames.contains(node.name!.value)) {
             return _Accumulator(
               valueNames: fold.valueNames,
               errors: [
@@ -47,7 +47,7 @@ class UniqueEnumValueNames extends ValidatingVisitor {
           return _Accumulator(
             valueNames: [
               ...fold.valueNames,
-              node.name.value,
+              node.name!.value,
             ],
             errors: fold.errors,
           );
diff --git a/gql/lib/src/validation/rules/unique_field_definition_names.dart b/gql/lib/src/validation/rules/unique_field_definition_names.dart
index 42c9e119..1e874466 100644
--- a/gql/lib/src/validation/rules/unique_field_definition_names.dart
+++ b/gql/lib/src/validation/rules/unique_field_definition_names.dart
@@ -3,11 +3,11 @@ import "package:gql/src/validation/validating_visitor.dart";
 import "package:gql/src/validation/validator.dart";
 
 class DuplicateFieldDefinitionNameError extends ValidationError {
-  final TypeDefinitionNode typeNode;
+  final TypeDefinitionNode? typeNode;
 
   const DuplicateFieldDefinitionNameError({
     this.typeNode,
-    NameNode nameNode,
+    NameNode? nameNode,
   }) : super(
           node: nameNode,
         );
diff --git a/gql/lib/src/validation/rules/unique_input_field_names.dart b/gql/lib/src/validation/rules/unique_input_field_names.dart
index 7336fa8f..5e8f451d 100644
--- a/gql/lib/src/validation/rules/unique_input_field_names.dart
+++ b/gql/lib/src/validation/rules/unique_input_field_names.dart
@@ -4,7 +4,7 @@ import "package:gql/src/validation/validator.dart";
 
 class DuplicateInputFieldNameError extends ValidationError {
   const DuplicateInputFieldNameError({
-    ObjectFieldNode node,
+    ObjectFieldNode? node,
   }) : super(
           node: node,
         );
diff --git a/gql/lib/src/validation/rules/unique_operation_types.dart b/gql/lib/src/validation/rules/unique_operation_types.dart
index 5a704b1d..607fe4c8 100644
--- a/gql/lib/src/validation/rules/unique_operation_types.dart
+++ b/gql/lib/src/validation/rules/unique_operation_types.dart
@@ -4,7 +4,7 @@ import "package:gql/src/validation/validator.dart";
 
 class DuplicateOperationTypeError extends ValidationError {
   const DuplicateOperationTypeError({
-    OperationTypeDefinitionNode node,
+    OperationTypeDefinitionNode? node,
   }) : super(
           node: node,
         );
diff --git a/gql/lib/src/validation/rules/unique_type_names.dart b/gql/lib/src/validation/rules/unique_type_names.dart
index d0534802..33663df8 100644
--- a/gql/lib/src/validation/rules/unique_type_names.dart
+++ b/gql/lib/src/validation/rules/unique_type_names.dart
@@ -4,7 +4,7 @@ import "package:gql/src/validation/validator.dart";
 
 class DuplicateTypeNameError extends ValidationError {
   const DuplicateTypeNameError({
-    TypeDefinitionNode node,
+    TypeDefinitionNode? node,
   }) : super(
           node: node,
         );
@@ -14,13 +14,13 @@ class UniqueTypeNames extends ValidatingVisitor {
   List<String> typeDefinitionsNames = [];
 
   List<ValidationError> _visitTypeDefinitionNode(TypeDefinitionNode node) {
-    if (typeDefinitionsNames.contains(node.name.value)) {
+    if (typeDefinitionsNames.contains(node.name!.value)) {
       return [
         DuplicateTypeNameError(node: node),
       ];
     }
 
-    typeDefinitionsNames.add(node.name.value);
+    typeDefinitionsNames.add(node.name!.value);
 
     return [];
   }
diff --git a/gql/lib/src/validation/validator.dart b/gql/lib/src/validation/validator.dart
index 4c32aff2..573c4606 100644
--- a/gql/lib/src/validation/validator.dart
+++ b/gql/lib/src/validation/validator.dart
@@ -78,8 +78,8 @@ List<ValidationError> validateRequest(
 /// A base class for validation errors
 @immutable
 abstract class ValidationError {
-  final String message;
-  final ast.Node node;
+  final String? message;
+  final ast.Node? node;
 
   const ValidationError({
     this.message,
@@ -99,7 +99,7 @@ enum ValidationRule {
   uniqueArgumentNames
 }
 
-ValidatingVisitor _mapRule(ValidationRule rule) {
+ValidatingVisitor? _mapRule(ValidationRule rule) {
   switch (rule) {
     case ValidationRule.uniqueDirectiveNames:
       return UniqueDirectiveNames();
@@ -123,17 +123,17 @@ ValidatingVisitor _mapRule(ValidationRule rule) {
 }
 
 class _Validator {
-  Set<ValidationRule> rules;
+  Set<ValidationRule>? rules;
 
   _Validator({
     this.rules,
   });
 
   List<ValidationError> validate({
-    ast.Node node,
+    required ast.Node node,
   }) {
     final visitor = ast.AccumulatingVisitor<ValidationError>(
-      visitors: rules.map(_mapRule).toList(),
+      visitors: rules!.map(_mapRule).toList(),
     );
 
     node.accept(visitor);
diff --git a/gql/pubspec.yaml b/gql/pubspec.yaml
index ae23a377..096426d9 100644
--- a/gql/pubspec.yaml
+++ b/gql/pubspec.yaml
@@ -1,15 +1,15 @@
 name: gql
-version: 0.12.4
+version: 1.0.0-nullsafety.0
 description: GraphQL tools for parsing, transforming and printing GraphQL documents.
 repository: https://github.com/gql-dart/gql
 environment: 
-  sdk: '>=2.7.2 <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 dependencies: 
-  source_span: ^1.5.5
-  meta: ^1.1.7
-  collection: ^1.14.11
+  collection: ^1.15.0
+  meta: ^1.3.0
+  source_span: ^1.8.1
 dev_dependencies: 
-  test: ^1.0.0
-  gql_pedantic: ^1.0.1
+  gql_pedantic: ^1.0.2
+  test: ^1.16.2
   cats: 
     path: ../cats
diff --git a/gql/test/lexer_test.dart b/gql/test/lexer_test.dart
index eb102b74..74eb03f7 100644
--- a/gql/test/lexer_test.dart
+++ b/gql/test/lexer_test.dart
@@ -3,27 +3,27 @@ import "package:source_span/source_span.dart";
 import "package:test/test.dart";
 
 Matcher token({
-  TokenKind kind,
-  int start,
-  int end,
-  int line,
-  int column,
-  String value,
+  TokenKind? kind,
+  int? start,
+  int? end,
+  int? line,
+  int? column,
+  String? value,
 }) =>
     predicate(
       (Token token) =>
           token.kind == kind &&
-          token.span.start.offset == start &&
-          token.span.end.offset == end &&
-          token.span.start.line == line - 1 &&
-          token.span.start.column == column - 1 &&
+          token.span!.start.offset == start &&
+          token.span!.end.offset == end &&
+          token.span!.start.line == line! - 1 &&
+          token.span!.start.column == column! - 1 &&
           (value == null || token.value == value),
       "token of ${kind} at $line:$column($start-$end) $value",
     );
 
 void main() {
   group("Lexer", () {
-    Lexer lexer;
+    late Lexer lexer;
 
     List<Token> tokenize(String text, {bool skipComments = true}) =>
         lexer.tokenize(
diff --git a/gql/test/operation_test.dart b/gql/test/operation_test.dart
index 20ee0417..a2828587 100644
--- a/gql/test/operation_test.dart
+++ b/gql/test/operation_test.dart
@@ -15,7 +15,7 @@ void main() {
 
     test("Can dereference schemaType", () {
       final query = document.operations.first;
-      expect(query.schemaType.name, equals("StarWarsQuery"));
+      expect(query.schemaType!.name, equals("StarWarsQuery"));
     });
   });
 
@@ -29,7 +29,7 @@ void main() {
     test("Can dereference fragmentType", () {
       final mutationField = document.operations.first.selectionSet.fields.first;
 
-      final spreads = mutationField.selectionSet.fragmentSpreads;
+      final spreads = mutationField.selectionSet!.fragmentSpreads;
       expect(spreads.first.fragment.name, equals("info"));
 
       final relationships = spreads[1].fragment;
@@ -37,7 +37,7 @@ void main() {
 
       final relationshipsFriends = relationships.selectionSet.fields.first;
       expect(
-        relationshipsFriends.selectionSet.fragmentSpreads.first.fragment.name,
+        relationshipsFriends.selectionSet!.fragmentSpreads.first.fragment.name,
         equals("friendNetwork"),
       );
     });
diff --git a/gql/test/parser_test.dart b/gql/test/parser_test.dart
index 8172d28a..5dab499f 100644
--- a/gql/test/parser_test.dart
+++ b/gql/test/parser_test.dart
@@ -2,30 +2,31 @@ import "package:gql/src/language/parser.dart";
 import "package:source_span/source_span.dart";
 import "package:test/test.dart";
 
-final throwsSourceSpanException = (
+final Matcher Function(String, int, int, [int, int]) throwsSourceSpanException =
+    (
   String message,
   int startLine,
   int startColumn, [
-  int endLine,
-  int endColumn,
+  int? endLine,
+  int? endColumn,
 ]) =>
-    throwsA(
-      allOf(
-        TypeMatcher<SourceSpanException>(),
-        predicate(
-          (SourceSpanException e) => e.message == message,
-          "error messages match",
-        ),
-        predicate(
-          (SourceSpanException e) =>
-              e.span.start.line == startLine - 1 &&
-              e.span.start.column == startColumn - 1 &&
-              e.span.end.line == (endLine ?? startLine) - 1 &&
-              e.span.end.column == (endColumn ?? startColumn + 1) - 1,
-          "span matches",
-        ),
-      ),
-    );
+        throwsA(
+          allOf(
+            TypeMatcher<SourceSpanException>(),
+            predicate(
+              (SourceSpanException e) => e.message == message,
+              "error messages match",
+            ),
+            predicate(
+              (SourceSpanException e) =>
+                  e.span!.start.line == startLine - 1 &&
+                  e.span!.start.column == startColumn - 1 &&
+                  e.span!.end.line == (endLine ?? startLine) - 1 &&
+                  e.span!.end.column == (endColumn ?? startColumn + 1) - 1,
+              "span matches",
+            ),
+          ),
+        );
 
 void main() {
   group("Parser", () {
diff --git a/gql/test/scenarios_test.dart b/gql/test/scenarios_test.dart
index 81fd54de..e6120c06 100644
--- a/gql/test/scenarios_test.dart
+++ b/gql/test/scenarios_test.dart
@@ -9,7 +9,7 @@ class RecursiveVisitor extends ast.RecursiveVisitor {}
 class MyDriver extends CatDriver<ast.DocumentNode> {
   @override
   ast.DocumentNode parse({
-    source,
+    required source,
   }) =>
       lang.parseString(source);
 
@@ -18,7 +18,7 @@ class MyDriver extends CatDriver<ast.DocumentNode> {
     schema,
     dynamic testData,
     query,
-    String operation,
+    String? operation,
     variables,
   }) =>
       null;
@@ -29,7 +29,7 @@ class MyDriver extends CatDriver<ast.DocumentNode> {
     query,
     validationRules,
   }) =>
-      null;
+      [];
 }
 
 void main() {
diff --git a/gql/test/schema_test.dart b/gql/test/schema_test.dart
index fc5e6551..753b5297 100644
--- a/gql/test/schema_test.dart
+++ b/gql/test/schema_test.dart
@@ -25,7 +25,7 @@ void main() {
     test("Can dereference an object interace", () {
       final droid = schema.getType("Droid") as ObjectTypeDefinition;
       expect(
-        droid.interfaces[0].name,
+        droid.interfaces[0]!.name,
         equals("Character"),
       );
     });
@@ -44,25 +44,25 @@ void main() {
     });
 
     test("schema.getPossibleTypes results", () {
-      final character = schema.getType("Character") as InterfaceTypeDefinition;
+      final character = schema.getType("Character") as InterfaceTypeDefinition?;
       final searchResult = schema.getType(
         "SearchResult",
-      ) as UnionTypeDefinition;
+      ) as UnionTypeDefinition?;
 
-      final human = schema.getType("Human") as ObjectTypeDefinition;
-      final droid = schema.getType("Droid") as ObjectTypeDefinition;
-      final starship = schema.getType("Starship") as ObjectTypeDefinition;
+      final human = schema.getType("Human") as ObjectTypeDefinition?;
+      final droid = schema.getType("Droid") as ObjectTypeDefinition?;
+      final starship = schema.getType("Starship") as ObjectTypeDefinition?;
 
       expect(
         schema.getPossibleTypes(searchResult),
         unorderedEquals(
-          <ObjectTypeDefinition>{droid, starship, human},
+          <ObjectTypeDefinition?>{droid, starship, human},
         ),
       );
 
       expect(
         schema.getPossibleTypes(character),
-        unorderedEquals(<ObjectTypeDefinition>{
+        unorderedEquals(<ObjectTypeDefinition?>{
           droid,
           human,
         }),
@@ -70,50 +70,51 @@ void main() {
     });
 
     test("Type dereferencing", () {
-      final starshipsType = schema.query.getField("starships").type as ListType;
+      final starshipsType =
+          schema.query!.getField("starships").type as ListType;
 
       expect(starshipsType.baseTypeName, equals("Starship"));
 
-      final starship = (starshipsType.type as NamedType).type;
+      final starship = (starshipsType.type as NamedType).type!;
       expect(starship.runtimeType, equals(ObjectTypeDefinition));
       expect(starship.name, equals("Starship"));
     });
 
     test("mutation arguments", () {
-      final updateHuman = schema.mutation.getField("updateHuman");
+      final updateHuman = schema.mutation!.getField("updateHuman");
 
-      expect(updateHuman.args.first.name, equals("id"));
-      expect(updateHuman.args.first.type.isNonNull, equals(true));
+      expect(updateHuman.args!.first.name, equals("id"));
+      expect(updateHuman.args!.first.type!.isNonNull, equals(true));
 
-      final inputTypeRef = updateHuman.args.last.type as NamedType;
+      final inputTypeRef = updateHuman.args!.last.type as NamedType;
       expect(inputTypeRef.name, equals("HumanInput"));
       expect(inputTypeRef.isNonNull, equals(true));
       expect(inputTypeRef.hasResolver, equals(true));
 
-      final inputType = inputTypeRef.type;
+      final inputType = inputTypeRef.type!;
       expect(inputType.runtimeType, equals(InputObjectTypeDefinition));
       expect(inputType.name, equals("HumanInput"));
     });
 
     test("mutation arguments", () {
-      final updateHuman = schema.mutation.getField("updateHuman");
+      final updateHuman = schema.mutation!.getField("updateHuman");
 
-      expect(updateHuman.args.first.name, equals("id"));
-      expect(updateHuman.args.first.type.isNonNull, equals(true));
+      expect(updateHuman.args!.first.name, equals("id"));
+      expect(updateHuman.args!.first.type!.isNonNull, equals(true));
 
-      final inputTypeRef = updateHuman.args.last.type as NamedType;
+      final inputTypeRef = updateHuman.args!.last.type as NamedType;
       expect(inputTypeRef.name, equals("HumanInput"));
       expect(inputTypeRef.isNonNull, equals(true));
       expect(inputTypeRef.hasResolver, equals(true));
 
-      final inputType = inputTypeRef.type;
+      final inputType = inputTypeRef.type!;
       expect(inputType.runtimeType, equals(InputObjectTypeDefinition));
       expect(inputType.name, equals("HumanInput"));
     });
 
     test("Contains default directives", () {
       expect(
-        schema.directives.map((d) => d.name),
+        schema.directives!.map((d) => d.name),
         containsAll(<String>{"skip", "include", "deprecated"}),
       );
     });
diff --git a/links/gql_dedupe_link/.gitignore b/links/gql_dedupe_link/.gitignore
index 50602ac6..41ce92d9 100644
--- a/links/gql_dedupe_link/.gitignore
+++ b/links/gql_dedupe_link/.gitignore
@@ -4,6 +4,8 @@
 # Remove the following pattern if you wish to check in your lock file
 pubspec.lock
 
+test/**/*.mocks.dart
+
 # Conventional directory for build outputs
 build/
 
diff --git a/links/gql_dedupe_link/lib/gql_dedupe_link.dart b/links/gql_dedupe_link/lib/gql_dedupe_link.dart
index 7b66b942..c121d891 100644
--- a/links/gql_dedupe_link/lib/gql_dedupe_link.dart
+++ b/links/gql_dedupe_link/lib/gql_dedupe_link.dart
@@ -12,13 +12,13 @@ class DedupeLink extends Link {
   @override
   Stream<Response> request(
     Request request, [
-    NextLink forward,
+    NextLink? forward,
   ]) {
     if (_inFlight.containsKey(request)) {
-      return _inFlight[request].split();
+      return _inFlight[request]!.split();
     }
 
-    final splitter = StreamSplitter(forward(request));
+    final splitter = StreamSplitter(forward!(request));
 
     _inFlight[request] = splitter;
 
diff --git a/links/gql_dedupe_link/pubspec.yaml b/links/gql_dedupe_link/pubspec.yaml
index 305dfcba..475e2f99 100644
--- a/links/gql_dedupe_link/pubspec.yaml
+++ b/links/gql_dedupe_link/pubspec.yaml
@@ -3,14 +3,14 @@ version: 1.0.10
 description: GQL Link to deduplicate identical in-flight execution requests
 repository: https://github.com/gql-dart/gql
 environment: 
-  sdk: '>=2.7.2 <3.0.0'
+  sdk: '>=2.12.0-259.12.beta <3.0.0'
 dependencies: 
-  meta: ^1.1.7
+  meta: ^1.3.0
   gql_exec: ^0.2.5
   gql_link: ^0.3.1
-  async: ^2.3.0
+  async: ^2.5.0
 dev_dependencies: 
-  test: ^1.0.0
-  mockito: ^4.1.1
+  test: ^1.16.2
+  mockito: ^5.0.0-nullsafety.7
   gql: ^0.12.3
   gql_pedantic: ^1.0.2
diff --git a/links/gql_dedupe_link/test/gql_dedupe_link_test.dart b/links/gql_dedupe_link/test/gql_dedupe_link_test.dart
index edb95900..c2e90db2 100644
--- a/links/gql_dedupe_link/test/gql_dedupe_link_test.dart
+++ b/links/gql_dedupe_link/test/gql_dedupe_link_test.dart
@@ -7,7 +7,16 @@ import "package:gql_link/gql_link.dart";
 import "package:mockito/mockito.dart";
 import "package:test/test.dart";
 
-class MockLink extends Mock implements Link {}
+class MockLink extends Mock implements Link {
+  @override
+  Stream<Response> request(Request? request, [NextLink? forward]) =>
+      super.noSuchMethod(
+        Invocation.method(#request, [request, forward]),
+        returnValue: Stream.fromIterable(
+          <Response>[],
+        ),
+      ) as Stream<Response>;
+}
 
 void main() {
   group("DedupeLink", () {
diff --git a/links/gql_error_link/example/gql_error_link_example.dart b/links/gql_error_link/example/gql_error_link_example.dart
index ff7c021c..b102f517 100644
--- a/links/gql_error_link/example/gql_error_link_example.dart
+++ b/links/gql_error_link/example/gql_error_link_example.dart
@@ -16,7 +16,7 @@ final terminatingLink = Link.function(
 
     // Otherwise, yield some [Response].
     yield Response(
-      data: <String, String>{
+      data: <String, String?>{
         "magic": token.token,
       },
     );
@@ -25,7 +25,7 @@ final terminatingLink = Link.function(
 
 // In this case [AuthToken] is a simple container of a [String] token.
 class AuthToken extends ContextEntry {
-  final String token;
+  final String? token;
 
   const AuthToken({this.token});
 
diff --git a/links/gql_error_link/lib/gql_error_link.dart b/links/gql_error_link/lib/gql_error_link.dart
index 1f5a4d26..a8ff98b2 100644
--- a/links/gql_error_link/lib/gql_error_link.dart
+++ b/links/gql_error_link/lib/gql_error_link.dart
@@ -7,14 +7,14 @@ import "package:gql_link/gql_link.dart";
 import "package:gql_exec/gql_exec.dart";
 
 /// A handler of GraphQL errors.
-typedef ErrorHandler = Stream<Response> Function(
+typedef ErrorHandler = Stream<Response>? Function(
   Request request,
   NextLink forward,
   Response response,
 );
 
 /// A handler of Link Exceptions.
-typedef ExceptionHandler = Stream<Response> Function(
+typedef ExceptionHandler = Stream<Response>? Function(
   Request request,
   NextLink forward,
   LinkException exception,
@@ -28,8 +28,8 @@ typedef ExceptionHandler = Stream<Response> Function(
 /// `null`, the original stream is left intact and will be allowed to continue
 /// streaming new events.
 class ErrorLink extends Link {
-  final ErrorHandler onGraphQLError;
-  final ExceptionHandler onException;
+  final ErrorHandler? onGraphQLError;
+  final ExceptionHandler? onException;
 
   const ErrorLink({
     this.onGraphQLError,
@@ -41,12 +41,12 @@ class ErrorLink extends Link {
     Request request, [
     forward,
   ]) async* {
-    await for (final result in Result.captureStream(forward(request))) {
+    await for (final result in Result.captureStream(forward!(request))) {
       if (result.isError) {
-        final error = result.asError.error;
+        final error = result.asError!.error;
 
         if (onException != null && error is LinkException) {
-          final stream = onException(request, forward, error);
+          final stream = onException!(request, forward, error);
 
           if (stream != null) {
             yield* stream;
@@ -59,11 +59,11 @@ class ErrorLink extends Link {
       }
 
       if (result.isValue) {
-        final response = result.asValue.value;
+        final response = result.asValue!.value;
         final errors = response.errors;
 
         if (onGraphQLError != null && errors != null && errors.isNotEmpty) {
-          final stream = onGraphQLError(request, forward, response);
+          final stream = onGraphQLError!(request, forward, response);
 
           if (stream != null) {
             yield* stream;
diff --git a/links/gql_error_link/pubspec.yaml b/links/gql_error_link/pubspec.yaml
index 5def8136..9e6f0909 100644
--- a/links/gql_error_link/pubspec.yaml
+++ b/links/gql_error_link/pubspec.yaml
@@ -3,14 +3,14 @@ version: 0.1.0
 description: GQL Link to handle execution errors and exceptions
 repository: https://github.com/gql-dart/gql
 environment: 
-  sdk: '>=2.7.2 <3.0.0'
+  sdk: '>=2.12.0-259.12.beta <3.0.0'
 dependencies: 
-  async: ^2.3.0
+  async: ^2.5.0
   gql_exec: ^0.2.5
   gql_link: ^0.3.1
-  meta: ^1.1.7
+  meta: ^1.3.0
 dev_dependencies: 
-  test: ^1.0.0
-  mockito: ^4.1.1
+  test: ^1.16.2
+  mockito: ^5.0.0-nullsafety.7
   gql: ^0.12.3
   gql_pedantic: ^1.0.2
diff --git a/links/gql_error_link/test/gql_error_link_test.dart b/links/gql_error_link/test/gql_error_link_test.dart
index 2e9107c0..e6f4a9a9 100644
--- a/links/gql_error_link/test/gql_error_link_test.dart
+++ b/links/gql_error_link/test/gql_error_link_test.dart
@@ -1,5 +1,6 @@
 import "dart:async";
 
+import "package:gql/language.dart";
 import "package:gql_error_link/gql_error_link.dart";
 import "package:gql_exec/gql_exec.dart";
 import "package:gql_link/gql_link.dart";
@@ -19,13 +20,18 @@ class TestException extends LinkException {
 }
 
 void main() {
+  Request req() => Request(
+        operation: Operation(document: parseString("")),
+        variables: const <String, dynamic>{"i": 12},
+      );
+
   group("ErrorLink", () {
     group("passthrough", () {
       test("response", () {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Stream.fromIterable([
             Response(data: const <String, dynamic>{"a": 1}),
           ]),
@@ -44,7 +50,7 @@ void main() {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Stream.fromIterable([
             Response(
               data: const <String, dynamic>{"a": 1},
@@ -73,7 +79,7 @@ void main() {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.error(TestException(1)),
@@ -94,7 +100,7 @@ void main() {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Stream.fromIterable([
             Response(data: const <String, dynamic>{"a": 1}),
             Response(data: const <String, dynamic>{"a": 1}),
@@ -115,7 +121,7 @@ void main() {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.value(Response(data: const <String, dynamic>{"a": 1})),
@@ -138,7 +144,7 @@ void main() {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.error(TestException(1)),
@@ -161,7 +167,7 @@ void main() {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.error(TestException(1)),
@@ -186,7 +192,7 @@ void main() {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.error("exception"),
@@ -215,7 +221,7 @@ void main() {
         );
 
         final responseStream = errorLink.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.error(TestException(1)),
@@ -249,7 +255,7 @@ void main() {
         );
 
         final responseStream = errorLink.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.error(TestException(1)),
@@ -280,7 +286,7 @@ void main() {
         );
 
         final responseStream = errorLink.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.error(TestException(1)),
@@ -305,7 +311,7 @@ void main() {
         final link = ErrorLink();
 
         final responseStream = link.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.value(
@@ -336,7 +342,7 @@ void main() {
         );
 
         final responseStream = errorLink.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.value(
@@ -384,7 +390,7 @@ void main() {
         );
 
         final responseStream = errorLink.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.value(
@@ -429,7 +435,7 @@ void main() {
         );
 
         final responseStream = errorLink.request(
-          null,
+          req(),
           (request) => Result.releaseStream(
             Stream.fromIterable([
               Result.value(
diff --git a/links/gql_exec/lib/src/context.dart b/links/gql_exec/lib/src/context.dart
index 0574d99a..b42ff1fc 100644
--- a/links/gql_exec/lib/src/context.dart
+++ b/links/gql_exec/lib/src/context.dart
@@ -14,13 +14,13 @@ abstract class ContextEntry {
   const ContextEntry();
 
   /// List of values to be used for equality.
-  List<Object> get fieldsForEquality;
+  List<Object?> get fieldsForEquality;
 
   @override
   bool operator ==(Object o) =>
       identical(this, o) ||
       (o.runtimeType == runtimeType &&
-          const ListEquality<Object>(
+          const ListEquality<Object?>(
             DeepCollectionEquality(),
           ).equals(
             (o as ContextEntry).fieldsForEquality,
@@ -28,7 +28,7 @@ abstract class ContextEntry {
           ));
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash(
         fieldsForEquality,
@@ -41,21 +41,19 @@ abstract class ContextEntry {
 /// Context entries appear only once per type.
 @immutable
 class Context {
-  final Map<Type, ContextEntry> _context;
+  final Map<Type, ContextEntry?> _context;
 
   /// Create an empty context.
   ///
   /// Entries may be added later using [withEntry].
   const Context() : _context = const <Type, ContextEntry>{};
 
-  const Context._fromMap(Map<Type, ContextEntry> context)
-      : _context = context,
-        assert(context != null);
+  const Context._fromMap(Map<Type, ContextEntry?> context) : _context = context;
 
   /// Creates a context from initial values represented as a map
   ///
   /// Every values runtime [Type] must be exactly the [Type] defined by the key.
-  factory Context.fromMap(Map<Type, ContextEntry> context) {
+  factory Context.fromMap(Map<Type, ContextEntry?> context) {
     assert(
       context.entries.every(
         (entry) => entry.value == null || entry.value.runtimeType == entry.key,
@@ -70,8 +68,7 @@ class Context {
   ///
   /// If more then one entry per type is provided, the last one is used.
   Context.fromList(List<ContextEntry> entries)
-      : assert(entries != null),
-        _context = entries.fold(
+      : _context = entries.fold<Map<Type, ContextEntry>>(
           <Type, ContextEntry>{},
           (ctx, e) => <Type, ContextEntry>{
             ...ctx,
@@ -80,7 +77,7 @@ class Context {
         );
 
   /// Create a [Context] with [entry] added to the existing entries.
-  Context withEntry<T extends ContextEntry>(T entry) {
+  Context withEntry<T extends ContextEntry?>(T entry) {
     if (entry != null && T != entry.runtimeType) {
       throw ArgumentError.value(
         entry,
@@ -90,7 +87,7 @@ class Context {
     }
 
     return Context.fromMap(
-      <Type, ContextEntry>{
+      <Type, ContextEntry?>{
         ..._context,
         T: entry,
       },
@@ -99,9 +96,9 @@ class Context {
 
   /// Create a [Context] by updating entry of type [T]
   Context updateEntry<T extends ContextEntry>(
-    ContextUpdater<T> update,
+    ContextUpdater<T?> update,
   ) =>
-      withEntry<T>(
+      withEntry<T?>(
         update(
           entry<T>(),
         ),
@@ -113,7 +110,7 @@ class Context {
   /// the [defaultValue] is returned.
   ///
   /// If provided, [defaultValue] must exactly match the return type [T].
-  T entry<T extends ContextEntry>([T defaultValue]) {
+  T? entry<T extends ContextEntry?>([T? defaultValue]) {
     if (defaultValue != null && T != defaultValue.runtimeType) {
       throw ArgumentError.value(
         defaultValue,
@@ -121,7 +118,7 @@ class Context {
         "does not match the expected return type '${T}'",
       );
     }
-    return _context.containsKey(T) ? _context[T] as T : defaultValue;
+    return _context.containsKey(T) ? _context[T] as T? : defaultValue;
   }
 
   List<Object> _getChildren() => [
@@ -132,7 +129,7 @@ class Context {
   bool operator ==(Object o) =>
       identical(this, o) ||
       (o is Context &&
-          const ListEquality<Object>(
+          const ListEquality<Object?>(
             DeepCollectionEquality(),
           ).equals(
             o._getChildren(),
@@ -140,7 +137,7 @@ class Context {
           ));
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash(
         _getChildren(),
diff --git a/links/gql_exec/lib/src/error.dart b/links/gql_exec/lib/src/error.dart
index 570e0631..9a3c3729 100644
--- a/links/gql_exec/lib/src/error.dart
+++ b/links/gql_exec/lib/src/error.dart
@@ -8,22 +8,22 @@ class GraphQLError {
   final String message;
 
   /// Locations of the nodes in document which caused the error
-  final List<ErrorLocation> locations;
+  final List<ErrorLocation>? locations;
 
   /// Path of the error node in the query
-  final List<dynamic /* String | int */ > path;
+  final List<dynamic /* String | int */ >? path;
 
   /// Implementation-specific extensions to this error
-  final Map<String, dynamic> extensions;
+  final Map<String, dynamic>? extensions;
 
   const GraphQLError({
-    @required this.message,
+    required this.message,
     this.locations,
     this.path,
     this.extensions,
-  }) : assert(message != null);
+  });
 
-  List<Object> _getChildren() => [
+  List<Object?> _getChildren() => [
         message,
         locations,
         path,
@@ -38,7 +38,7 @@ class GraphQLError {
   bool operator ==(Object o) =>
       identical(this, o) ||
       (o is GraphQLError &&
-          const ListEquality<Object>(
+          const ListEquality<Object?>(
             DeepCollectionEquality(),
           ).equals(
             o._getChildren(),
@@ -46,7 +46,7 @@ class GraphQLError {
           ));
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash(
         _getChildren(),
@@ -60,10 +60,9 @@ class ErrorLocation {
   final int column;
 
   const ErrorLocation({
-    @required this.line,
-    @required this.column,
-  })  : assert(line != null),
-        assert(column != null);
+    required this.line,
+    required this.column,
+  });
 
   List<Object> _getChildren() => [
         line,
@@ -74,7 +73,7 @@ class ErrorLocation {
   bool operator ==(Object o) =>
       identical(this, o) ||
       (o is ErrorLocation &&
-          const ListEquality<Object>(
+          const ListEquality<Object?>(
             DeepCollectionEquality(),
           ).equals(
             o._getChildren(),
@@ -82,7 +81,7 @@ class ErrorLocation {
           ));
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash(
         _getChildren(),
diff --git a/links/gql_exec/lib/src/operation.dart b/links/gql_exec/lib/src/operation.dart
index a4822e80..8199fcc9 100644
--- a/links/gql_exec/lib/src/operation.dart
+++ b/links/gql_exec/lib/src/operation.dart
@@ -14,14 +14,14 @@ class Operation {
   /// Name of the executable definition
   ///
   /// Must be specified if [document] contains more than one [OperationDefinitionNode]
-  final String operationName;
+  final String? operationName;
 
   const Operation({
-    @required this.document,
+    required this.document,
     this.operationName,
-  }) : assert(document != null);
+  });
 
-  List<Object> _getChildren() => [
+  List<Object?> _getChildren() => [
         document,
         operationName,
       ];
@@ -30,7 +30,7 @@ class Operation {
   bool operator ==(Object o) =>
       identical(this, o) ||
       (o is Operation &&
-          const ListEquality<Object>(
+          const ListEquality<Object?>(
             DeepCollectionEquality(),
           ).equals(
             o._getChildren(),
@@ -38,7 +38,7 @@ class Operation {
           ));
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash(
         _getChildren(),
diff --git a/links/gql_exec/lib/src/request.dart b/links/gql_exec/lib/src/request.dart
index 16f51217..7b4dbcaf 100644
--- a/links/gql_exec/lib/src/request.dart
+++ b/links/gql_exec/lib/src/request.dart
@@ -16,11 +16,10 @@ class Request {
   final Context context;
 
   const Request({
-    @required this.operation,
+    required this.operation,
     this.variables = const <String, dynamic>{},
     this.context = const Context(),
-  })  : assert(operation != null),
-        assert(context != null);
+  });
 
   /// Clone this request adding an [entry] to [context]
   Request withContextEntry<T extends ContextEntry>(T entry) => Request(
@@ -31,7 +30,7 @@ class Request {
 
   /// Clone this request updating an [entry] in the [context]
   Request updateContextEntry<T extends ContextEntry>(
-    ContextUpdater<T> update,
+    ContextUpdater<T?> update,
   ) =>
       Request(
         operation: operation,
@@ -49,7 +48,7 @@ class Request {
   bool operator ==(Object o) =>
       identical(this, o) ||
       (o is Request &&
-          const ListEquality<Object>(
+          const ListEquality<Object?>(
             DeepCollectionEquality(),
           ).equals(
             o._getChildren(),
@@ -57,7 +56,7 @@ class Request {
           ));
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash(
         _getChildren(),
diff --git a/links/gql_exec/lib/src/response.dart b/links/gql_exec/lib/src/response.dart
index 0de81123..aab91421 100644
--- a/links/gql_exec/lib/src/response.dart
+++ b/links/gql_exec/lib/src/response.dart
@@ -7,12 +7,12 @@ import "package:meta/meta.dart";
 @immutable
 class Response {
   /// Error returned executing the [Request]
-  final List<GraphQLError> errors;
+  final List<GraphQLError>? errors;
 
   /// Data returned executing the [Request]
   ///
   /// Follows the shape of requested document.
-  final Map<String, dynamic> data;
+  final Map<String, dynamic>? data;
 
   /// A [Context] to be returned along with a [Response]
   final Context context;
@@ -21,7 +21,7 @@ class Response {
     this.errors,
     this.data,
     this.context = const Context(),
-  }) : assert(context != null);
+  });
 
   /// Clone this response adding an [entry] to [context]
   Response withContextEntry<T extends ContextEntry>(T entry) => Response(
@@ -32,7 +32,7 @@ class Response {
 
   /// Clone this response updating an [entry] to [context]
   Response updateContextEntry<T extends ContextEntry>(
-    ContextUpdater<T> update,
+    ContextUpdater<T?> update,
   ) =>
       Response(
         errors: errors,
@@ -40,7 +40,7 @@ class Response {
         context: context.updateEntry<T>(update),
       );
 
-  List<Object> _getChildren() => [
+  List<Object?> _getChildren() => [
         errors,
         data,
         context,
@@ -50,7 +50,7 @@ class Response {
   bool operator ==(Object o) =>
       identical(this, o) ||
       (o is Response &&
-          const ListEquality<Object>(
+          const ListEquality<Object?>(
             DeepCollectionEquality(),
           ).equals(
             o._getChildren(),
@@ -58,7 +58,7 @@ class Response {
           ));
 
   @override
-  int get hashCode => const ListEquality<Object>(
+  int get hashCode => const ListEquality<Object?>(
         DeepCollectionEquality(),
       ).hash(
         _getChildren(),
@@ -73,14 +73,14 @@ class Response {
 @immutable
 class ResponseExtensions extends ContextEntry {
   /// [Response] extensions
-  final dynamic extensions;
+  final dynamic? extensions;
 
-  const ResponseExtensions(
+  const ResponseExtensions([
     this.extensions,
-  );
+  ]);
 
   @override
-  List<Object> get fieldsForEquality => [
-        extensions,
+  List<Object?> get fieldsForEquality => [
+        extensions as Object?,
       ];
 }
diff --git a/links/gql_exec/pubspec.yaml b/links/gql_exec/pubspec.yaml
index f3e4a690..20b33aae 100644
--- a/links/gql_exec/pubspec.yaml
+++ b/links/gql_exec/pubspec.yaml
@@ -1,13 +1,13 @@
 name: gql_exec
-version: 0.2.5
+version: 0.3.0-nullsafety.0
 description: Basis for GraphQL execution layer to support Link and Client.
 repository: https://github.com/gql-dart/gql
 environment: 
-  sdk: '>=2.7.2 <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 dependencies: 
+  collection: ^1.15.0
+  meta: ^1.3.0
   gql: ^0.12.3
-  meta: ^1.1.7
-  collection: ^1.14.11
 dev_dependencies: 
-  test: ^1.0.0
+  test: ^1.16.2
   gql_pedantic: ^1.0.2
diff --git a/links/gql_http_link/.gitignore b/links/gql_http_link/.gitignore
index 50602ac6..41ce92d9 100644
--- a/links/gql_http_link/.gitignore
+++ b/links/gql_http_link/.gitignore
@@ -4,6 +4,8 @@
 # Remove the following pattern if you wish to check in your lock file
 pubspec.lock
 
+test/**/*.mocks.dart
+
 # Conventional directory for build outputs
 build/
 
diff --git a/links/gql_http_link/analysis_options.yaml b/links/gql_http_link/analysis_options.yaml
index 8dd3be2b..c2fb402d 100644
--- a/links/gql_http_link/analysis_options.yaml
+++ b/links/gql_http_link/analysis_options.yaml
@@ -1 +1,5 @@
 include: package:gql_pedantic/analysis_options.yaml
+
+analyzer:
+  exclude:
+    - **/*.mocks.dart
diff --git a/links/gql_http_link/lib/src/_utils.dart b/links/gql_http_link/lib/src/_utils.dart
index 97ece858..af2709a8 100644
--- a/links/gql_http_link/lib/src/_utils.dart
+++ b/links/gql_http_link/lib/src/_utils.dart
@@ -1,6 +1,4 @@
 import "dart:convert";
-import "dart:typed_data";
-import "package:meta/meta.dart";
 
 import "package:http/http.dart";
 import "package:gql/ast.dart";
@@ -13,7 +11,7 @@ extension WithType on gql.Request {
         .toList();
     if (operation.operationName != null) {
       definitions.removeWhere(
-        (node) => node.name.value != operation.operationName,
+        (node) => node.name!.value != operation.operationName,
       );
     }
     // TODO differentiate error types, add exception
@@ -38,7 +36,7 @@ extension WithType on gql.Request {
 /// ```
 Map<String, MultipartFile> extractFlattenedFileMap(
   dynamic body, {
-  Map<String, MultipartFile> currentMap,
+  Map<String, MultipartFile>? currentMap,
   List<String> currentPath = const <String>[],
 }) {
   currentMap ??= <String, MultipartFile>{};
diff --git a/links/gql_http_link/lib/src/exceptions.dart b/links/gql_http_link/lib/src/exceptions.dart
index 236fc6ff..ebce8d7b 100644
--- a/links/gql_http_link/lib/src/exceptions.dart
+++ b/links/gql_http_link/lib/src/exceptions.dart
@@ -10,8 +10,8 @@ class HttpLinkParserException extends ResponseFormatException {
   final http.Response response;
 
   const HttpLinkParserException({
-    @required dynamic originalException,
-    @required this.response,
+    required dynamic originalException,
+    required this.response,
   }) : super(
           originalException: originalException,
         );
@@ -25,8 +25,8 @@ class HttpLinkServerException extends ServerException {
   final http.Response response;
 
   const HttpLinkServerException({
-    @required this.response,
-    @required Response parsedResponse,
+    required this.response,
+    required Response parsedResponse,
   }) : super(
           parsedResponse: parsedResponse,
         );
diff --git a/links/gql_http_link/lib/src/link.dart b/links/gql_http_link/lib/src/link.dart
index be72cea3..8c30e33a 100644
--- a/links/gql_http_link/lib/src/link.dart
+++ b/links/gql_http_link/lib/src/link.dart
@@ -9,7 +9,7 @@ import "package:meta/meta.dart";
 import "./_utils.dart";
 import "./exceptions.dart";
 
-typedef HttpResponseDecoder = FutureOr<Map<String, dynamic>> Function(
+typedef HttpResponseDecoder = FutureOr<Map<String, dynamic>?> Function(
     http.Response httpResponse);
 
 /// HTTP link headers
@@ -22,7 +22,7 @@ class HttpLinkHeaders extends ContextEntry {
 
   const HttpLinkHeaders({
     this.headers = const {},
-  }) : assert(headers != null);
+  });
 
   @override
   List<Object> get fieldsForEquality => [
@@ -40,10 +40,9 @@ class HttpLinkResponseContext extends ContextEntry {
   final Map<String, String> headers;
 
   const HttpLinkResponseContext({
-    @required this.statusCode,
-    @required this.headers,
-  })  : assert(statusCode != null),
-        assert(headers != null);
+    required this.statusCode,
+    required this.headers,
+  });
 
   @override
   List<Object> get fieldsForEquality => [
@@ -84,15 +83,15 @@ class HttpLink extends Link {
   /// ```
   HttpResponseDecoder httpResponseDecoder;
 
-  static Map<String, dynamic> _defaultHttpResponseDecoder(
+  static Map<String, dynamic>? _defaultHttpResponseDecoder(
           http.Response httpResponse) =>
       json.decode(
         utf8.decode(
           httpResponse.bodyBytes,
         ),
-      ) as Map<String, dynamic>;
+      ) as Map<String, dynamic>?;
 
-  http.Client _httpClient;
+  http.Client? _httpClient;
 
   /// Construct the Link
   ///
@@ -101,7 +100,7 @@ class HttpLink extends Link {
     String uri, {
     this.defaultHeaders = const {},
     this.useGETForQueries = false,
-    http.Client httpClient,
+    http.Client? httpClient,
     this.serializer = const RequestSerializer(),
     this.parser = const ResponseParser(),
     this.httpResponseDecoder = _defaultHttpResponseDecoder,
@@ -112,7 +111,7 @@ class HttpLink extends Link {
   @override
   Stream<Response> request(
     Request request, [
-    NextLink forward,
+    NextLink? forward,
   ]) async* {
     final httpResponse = await _executeRequest(request);
 
@@ -154,7 +153,7 @@ class HttpLink extends Link {
   Future<Response> _parseHttpResponse(http.Response httpResponse) async {
     try {
       final responseBody = await httpResponseDecoder(httpResponse);
-      return parser.parseResponse(responseBody);
+      return parser.parseResponse(responseBody!);
     } catch (e) {
       throw HttpLinkParserException(
         originalException: e,
@@ -166,7 +165,7 @@ class HttpLink extends Link {
   Future<http.Response> _executeRequest(Request request) async {
     final httpRequest = _prepareRequest(request);
     try {
-      final response = await _httpClient.send(httpRequest);
+      final response = await _httpClient!.send(httpRequest);
       return http.Response.fromStream(response);
     } catch (e) {
       throw ServerException(
@@ -251,7 +250,7 @@ class HttpLink extends Link {
 
 Map<String, String> _getHttpLinkHeaders(Request request) {
   try {
-    final HttpLinkHeaders linkHeaders = request.context.entry();
+    final HttpLinkHeaders? linkHeaders = request.context.entry();
 
     return {
       if (linkHeaders != null) ...linkHeaders.headers,
diff --git a/links/gql_http_link/pubspec.yaml b/links/gql_http_link/pubspec.yaml
index 839c12cd..49db6da4 100644
--- a/links/gql_http_link/pubspec.yaml
+++ b/links/gql_http_link/pubspec.yaml
@@ -3,16 +3,16 @@ version: 0.3.3
 description: GQL Terminating Link to execute requests via HTTP using JSON.
 repository: https://github.com/gql-dart/gql
 environment: 
-  sdk: '>=2.7.2 <3.0.0'
+  sdk: '>=2.12.0-259.12.beta <3.0.0'
 dependencies: 
-  meta: ^1.1.7
+  meta: ^1.3.0
   gql: ^0.12.3
   gql_exec: ^0.2.5
   gql_link: ^0.3.1
-  http: ^0.12.1
-  http_parser: ^3.1.4
+  http: ^0.13.0
+  http_parser: ^4.0.0
 dev_dependencies: 
-  test: ^1.0.0
-  mockito: ^4.1.1
+  test: ^1.16.2
+  mockito: ^5.0.0-nullsafety.7
   gql_pedantic: ^1.0.2
-  http_parser: ^3.1.4
+  build_runner: ^1.11.1
diff --git a/links/gql_http_link/test/gql_http_link_test.dart b/links/gql_http_link/test/gql_http_link_test.dart
index ca5574b2..f730dcca 100644
--- a/links/gql_http_link/test/gql_http_link_test.dart
+++ b/links/gql_http_link/test/gql_http_link_test.dart
@@ -10,12 +10,7 @@ import "package:mockito/mockito.dart";
 import "package:test/test.dart";
 
 import "./helpers.dart";
-
-class MockClient extends Mock implements http.Client {}
-
-class MockRequestSerializer extends Mock implements RequestSerializer {}
-
-class MockResponseParser extends Mock implements ResponseParser {}
+import "./mocks/mocks.dart";
 
 class CustomScalar {
   const CustomScalar(this.value);
@@ -25,19 +20,19 @@ class CustomScalar {
 
 void main() {
   group("HttpLink", () {
-    MockClient client;
-    Request request;
-    HttpLink link;
+    late MockHttpClient client;
+    late Request request;
+    late HttpLink link;
 
     final Stream<Response> Function([
-      Request customRequest,
+      Request? customRequest,
     ]) execute = ([
-      Request customRequest,
+      Request? customRequest,
     ]) =>
         link.request(customRequest ?? request);
 
     setUp(() {
-      client = MockClient();
+      client = MockHttpClient();
       request = Request(
         operation: Operation(
           document: parseString("query MyQuery {}"),
@@ -194,7 +189,7 @@ void main() {
     });
 
     test("adds default headers", () async {
-      final client = MockClient();
+      final client = MockHttpClient();
       final link = HttpLink(
         "/graphql-test",
         httpClient: client,
@@ -446,7 +441,7 @@ void main() {
         ),
       );
 
-      HttpLinkServerException exception;
+      HttpLinkServerException? exception;
 
       try {
         await execute().first;
@@ -458,7 +453,7 @@ void main() {
         exception,
         TypeMatcher<HttpLinkServerException>(),
       );
-      expect(exception.response.body, data);
+      expect(exception!.response.body, data);
       expect(
         exception.parsedResponse,
         equals(
@@ -485,12 +480,12 @@ void main() {
         ),
       );
 
-      HttpLinkServerException exception;
+      HttpLinkServerException? exception;
 
       try {
         await execute().first;
-      } catch (e) {
-        exception = e as HttpLinkServerException;
+      } on HttpLinkServerException catch (e) {
+        exception = e;
       }
 
       expect(
@@ -498,7 +493,7 @@ void main() {
         TypeMatcher<HttpLinkServerException>(),
       );
       expect(
-        exception.response.body,
+        exception!.response.body,
         data,
       );
       expect(
@@ -516,7 +511,7 @@ void main() {
 
     test("throws SerializerException when unable to serialize request",
         () async {
-      final client = MockClient();
+      final client = MockHttpClient();
       final serializer = MockRequestSerializer();
       final link = HttpLink(
         "/graphql-test",
@@ -545,7 +540,7 @@ void main() {
         ),
       ).thenThrow(originalException);
 
-      RequestFormatException exception;
+      RequestFormatException? exception;
 
       try {
         await link
@@ -567,7 +562,7 @@ void main() {
         TypeMatcher<RequestFormatException>(),
       );
       expect(
-        exception.originalException,
+        exception!.originalException,
         originalException,
       );
     });
@@ -584,7 +579,7 @@ void main() {
         ),
       );
 
-      ResponseFormatException exception;
+      ResponseFormatException? exception;
 
       try {
         await link
@@ -606,7 +601,7 @@ void main() {
         TypeMatcher<ResponseFormatException>(),
       );
       expect(
-        exception.originalException,
+        exception!.originalException,
         TypeMatcher<FormatException>(),
       );
     });
@@ -621,11 +616,11 @@ void main() {
   });
 
   group("HttpLink useGETForQueries", () {
-    MockClient client;
-    HttpLink link;
+    late MockHttpClient client;
+    late HttpLink link;
 
     setUp(() {
-      client = MockClient();
+      client = MockHttpClient();
       link = HttpLink(
         "/graphql-test",
         httpClient: client,
diff --git a/links/gql_http_link/test/helpers.dart b/links/gql_http_link/test/helpers.dart
index c7e124cf..0dc7928f 100644
--- a/links/gql_http_link/test/helpers.dart
+++ b/links/gql_http_link/test/helpers.dart
@@ -5,7 +5,7 @@ import "package:http/http.dart" as http;
 
 http.StreamedResponse simpleResponse(
   String body, [
-  int status,
+  int? status,
   Map<String, String> headers = const {},
 ]) {
   final List<int> bytes = utf8.encode(body);
diff --git a/links/gql_http_link/test/mocks/gql_exec.dart b/links/gql_http_link/test/mocks/gql_exec.dart
new file mode 100644
index 00000000..8b3ba6be
--- /dev/null
+++ b/links/gql_http_link/test/mocks/gql_exec.dart
@@ -0,0 +1,8 @@
+import "package:mockito/annotations.dart";
+
+import "package:gql_link/gql_link.dart";
+
+export "./gql_exec.mocks.dart";
+
+@GenerateMocks([RequestSerializer, ResponseParser])
+void main() {}
diff --git a/links/gql_http_link/test/mocks/http.dart b/links/gql_http_link/test/mocks/http.dart
new file mode 100644
index 00000000..704902a6
--- /dev/null
+++ b/links/gql_http_link/test/mocks/http.dart
@@ -0,0 +1,9 @@
+import "package:mockito/annotations.dart";
+import "package:http/http.dart" as http;
+
+export "./http.mocks.dart";
+
+@GenerateMocks([], customMocks: [
+  MockSpec<http.Client>(returnNullOnMissingStub: true, as: #MockHttpClient)
+])
+void main() {}
diff --git a/links/gql_http_link/test/mocks/mocks.dart b/links/gql_http_link/test/mocks/mocks.dart
new file mode 100644
index 00000000..6cbc93ef
--- /dev/null
+++ b/links/gql_http_link/test/mocks/mocks.dart
@@ -0,0 +1,2 @@
+export "./gql_exec.dart" hide main;
+export "./http.dart" hide main;
diff --git a/links/gql_http_link/test/multipart_upload_test.dart b/links/gql_http_link/test/multipart_upload_test.dart
index 5f536500..dc8c83cd 100644
--- a/links/gql_http_link/test/multipart_upload_test.dart
+++ b/links/gql_http_link/test/multipart_upload_test.dart
@@ -4,23 +4,17 @@ import "dart:typed_data";
 import "package:gql_exec/gql_exec.dart";
 import "package:gql/language.dart";
 import "package:gql_http_link/gql_http_link.dart";
-import "package:gql_link/gql_link.dart";
 import "package:http/http.dart" as http;
 import "package:http_parser/http_parser.dart";
 import "package:mockito/mockito.dart";
 import "package:test/test.dart";
 
 import "./helpers.dart";
-
-class MockClient extends Mock implements http.Client {}
-
-class MockRequestSerializer extends Mock implements RequestSerializer {}
-
-class MockResponseParser extends Mock implements ResponseParser {}
+import "./mocks/mocks.dart";
 
 void main() {
-  MockClient mockHttpClient;
-  HttpLink httpLink;
+  MockHttpClient? mockHttpClient;
+  late HttpLink httpLink;
 
   const String uploadMutation = r"""
     mutation($files: [Upload!]!) {
@@ -82,9 +76,9 @@ void main() {
       ];
 
   group("upload", () {
-    Request gqlRequest;
+    late Request gqlRequest;
     setUp(() {
-      mockHttpClient = MockClient();
+      mockHttpClient = MockHttpClient();
 
       httpLink = HttpLink(
         "http://localhost:3001/graphql",
@@ -102,9 +96,9 @@ void main() {
     });
 
     test("request encoding", () async {
-      Uint8List bodyBytes;
+      Uint8List? bodyBytes;
       when(
-        mockHttpClient.send(any),
+        mockHttpClient!.send(any),
       ).thenAnswer((i) async {
         bodyBytes = await (i.positionalArguments[0] as http.BaseRequest)
             .finalize()
@@ -115,11 +109,11 @@ void main() {
       await httpLink.request(gqlRequest).first;
 
       final http.MultipartRequest request = verify(
-        mockHttpClient.send(captureAny),
+        mockHttpClient!.send(captureAny),
       ).captured.first as http.MultipartRequest;
 
       final List<String> contentTypeStringSplit =
-          request.headers["content-type"].split("; boundary=");
+          request.headers["content-type"]!.split("; boundary=");
 
       expect(request.method, "POST");
       expect(request.url.toString(), "http://localhost:3001/graphql");
@@ -169,14 +163,14 @@ void main() {
 
     test("response data", () async {
       when(
-        mockHttpClient.send(any),
+        mockHttpClient!.send(any),
       ).thenAnswer(
         (i) async => simpleResponse(expectedResponse),
       );
 
       final response = await httpLink.request(gqlRequest).first;
 
-      final multipleUpload = (response.data["multipleUpload"] as List<dynamic>)
+      final multipleUpload = (response.data!["multipleUpload"] as List<dynamic>)
           .cast<Map<String, dynamic>>();
 
       expect(multipleUpload, <Map<String, String>>[
@@ -198,7 +192,7 @@ void main() {
 
   group("file upload useGETForQueries behavior", () {
     setUp(() {
-      mockHttpClient = MockClient();
+      mockHttpClient = MockHttpClient();
 
       httpLink = HttpLink(
         "http://localhost:3001/graphql",
@@ -208,9 +202,9 @@ void main() {
     });
 
     test("query request encoding with files", () async {
-      Uint8List bodyBytes;
+      Uint8List? bodyBytes;
       when(
-        mockHttpClient.send(any),
+        mockHttpClient!.send(any),
       ).thenAnswer((i) async {
         bodyBytes = await (i.positionalArguments[0] as http.BaseRequest)
             .finalize()
@@ -230,11 +224,11 @@ void main() {
       await httpLink.request(gqlQueryWithFiles).first;
 
       final http.MultipartRequest request = verify(
-        mockHttpClient.send(captureAny),
+        mockHttpClient!.send(captureAny),
       ).captured.first as http.MultipartRequest;
 
       final List<String> contentTypeStringSplit =
-          request.headers["content-type"].split("; boundary=");
+          request.headers["content-type"]!.split("; boundary=");
 
       expect(request.method, "POST");
       expect(request.url.toString(), "http://localhost:3001/graphql");
diff --git a/links/gql_link/example/gql_link_example.dart b/links/gql_link/example/gql_link_example.dart
index 0dcf06d5..41409e7b 100644
--- a/links/gql_link/example/gql_link_example.dart
+++ b/links/gql_link/example/gql_link_example.dart
@@ -8,7 +8,7 @@ class MyLinkContext extends ContextEntry {
   const MyLinkContext(this.value);
 
   @override
-  List<Object> get fieldsForEquality => null;
+  List<Object> get fieldsForEquality => [];
 }
 
 class MyLink extends Link {
@@ -17,7 +17,7 @@ class MyLink extends Link {
         [
           Response(
             data: <String, dynamic>{
-              "context": request.context.entry<MyLinkContext>().value,
+              "context": request.context.entry<MyLinkContext>()?.value,
             },
           ),
         ],
diff --git a/links/gql_link/lib/src/exceptions.dart b/links/gql_link/lib/src/exceptions.dart
index 9a504867..3f196be3 100644
--- a/links/gql_link/lib/src/exceptions.dart
+++ b/links/gql_link/lib/src/exceptions.dart
@@ -23,7 +23,7 @@ class RequestFormatException extends LinkException {
   final Request request;
 
   const RequestFormatException({
-    @required this.request,
+    required this.request,
     dynamic originalException,
   }) : super(originalException);
 
@@ -74,10 +74,10 @@ class ContextWriteException extends LinkException {
 @immutable
 class ServerException extends LinkException {
   /// The parsed response
-  final Response parsedResponse;
+  final Response? parsedResponse;
 
   const ServerException({
-    @required this.parsedResponse,
+    this.parsedResponse,
     dynamic originalException,
   }) : super(originalException);
 
diff --git a/links/gql_link/lib/src/link.dart b/links/gql_link/lib/src/link.dart
index e86cafee..cd83d35f 100644
--- a/links/gql_link/lib/src/link.dart
+++ b/links/gql_link/lib/src/link.dart
@@ -17,7 +17,7 @@ typedef LinkRouter = Link Function(
 /// Used by [Link.function]
 typedef LinkFunction = Stream<Response> Function(
   Request request, [
-  NextLink forward,
+  NextLink? forward,
 ]);
 
 /// [DocumentNode]-based GraphQL execution interface
@@ -93,7 +93,7 @@ abstract class Link {
     ///   the next [Link]
     ///
     /// Terminating [Link]s do not call this function.
-    NextLink forward,
+    NextLink? forward,
   ]);
 }
 
@@ -105,7 +105,7 @@ class _FunctionLink extends Link {
   @override
   Stream<Response> request(
     Request request, [
-    NextLink forward,
+    NextLink? forward,
   ]) =>
       function(request, forward);
 }
@@ -118,12 +118,12 @@ class _LinkChain extends Link {
   @override
   Stream<Response> request(
     Request request, [
-    NextLink forward,
+    NextLink? forward,
   ]) =>
-      links.reversed.fold<NextLink>(
+      links.reversed.fold<NextLink?>(
         forward,
         (fw, link) => (op) => link.request(op, fw),
-      )(request);
+      )!(request);
 }
 
 class _PassthroughLink extends Link {
@@ -132,9 +132,9 @@ class _PassthroughLink extends Link {
   @override
   Stream<Response> request(
     Request request, [
-    NextLink forward,
+    NextLink? forward,
   ]) =>
-      forward(request);
+      forward!(request);
 }
 
 class _RouterLink extends Link {
@@ -142,12 +142,12 @@ class _RouterLink extends Link {
 
   const _RouterLink(
     this.routeFn,
-  ) : assert(routeFn != null);
+  );
 
   @override
   Stream<Response> request(
     Request request, [
-    NextLink forward,
+    NextLink? forward,
   ]) async* {
     final link = routeFn(request);
 
diff --git a/links/gql_link/lib/src/request_serializer.dart b/links/gql_link/lib/src/request_serializer.dart
index 8c242aa6..ce85854e 100644
--- a/links/gql_link/lib/src/request_serializer.dart
+++ b/links/gql_link/lib/src/request_serializer.dart
@@ -9,7 +9,7 @@ class RequestSerializer {
   ///
   /// Extend this to add non-standard behavior
   Map<String, dynamic> serializeRequest(Request request) {
-    final RequestExtensionsThunk thunk = request.context.entry();
+    final RequestExtensionsThunk? thunk = request.context.entry();
 
     return <String, dynamic>{
       "operationName": request.operation.operationName,
diff --git a/links/gql_link/lib/src/response_parser.dart b/links/gql_link/lib/src/response_parser.dart
index 18050270..bd807de5 100644
--- a/links/gql_link/lib/src/response_parser.dart
+++ b/links/gql_link/lib/src/response_parser.dart
@@ -8,12 +8,12 @@ class ResponseParser {
   ///
   /// Extend this to add non-standard behavior
   Response parseResponse(Map<String, dynamic> body) => Response(
-        errors: (body["errors"] as List)
+        errors: (body["errors"] as List?)
             ?.map(
               (dynamic error) => parseError(error as Map<String, dynamic>),
             )
-            ?.toList(),
-        data: body["data"] as Map<String, dynamic>,
+            .toList(),
+        data: body["data"] as Map<String, dynamic>?,
         context: Context().withEntry(
           ResponseExtensions(
             body["extensions"],
@@ -27,11 +27,11 @@ class ResponseParser {
   GraphQLError parseError(Map<String, dynamic> error) => GraphQLError(
         message: error["message"] as String,
         path: error["path"] as List,
-        locations: (error["locations"] as List)
+        locations: (error["locations"] as List?)
             ?.map(
               (dynamic error) => parseLocation(error as Map<String, dynamic>),
             )
-            ?.toList(),
+            .toList(),
         extensions: error["extensions"] as Map<String, dynamic>,
       );
 
diff --git a/links/gql_link/pubspec.yaml b/links/gql_link/pubspec.yaml
index bb89ec3b..74d22972 100644
--- a/links/gql_link/pubspec.yaml
+++ b/links/gql_link/pubspec.yaml
@@ -1,9 +1,9 @@
 name: gql_link
-version: 0.3.1
+version: 0.4.0-nullsafety.0
 description: A simple and modular AST-based GraphQL request execution interface.
 repository: https://github.com/gql-dart/gql
 environment: 
-  sdk: '>=2.7.2 <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 dependencies: 
   meta: ^1.1.7
   gql: ^0.12.3
diff --git a/links/gql_transform_link/lib/gql_transform_link.dart b/links/gql_transform_link/lib/gql_transform_link.dart
index 868f26e6..68d76088 100644
--- a/links/gql_transform_link/lib/gql_transform_link.dart
+++ b/links/gql_transform_link/lib/gql_transform_link.dart
@@ -11,8 +11,8 @@ typedef ResponseTransformer = Response Function(Response response);
 
 /// A [Link] to transform [Request]s and [Response]s
 class TransformLink extends Link {
-  final RequestTransformer requestTransformer;
-  final ResponseTransformer responseTransformer;
+  final RequestTransformer? requestTransformer;
+  final ResponseTransformer? responseTransformer;
 
   TransformLink({
     this.requestTransformer,
@@ -22,15 +22,15 @@ class TransformLink extends Link {
   @override
   Stream<Response> request(
     Request request, [
-    NextLink forward,
+    NextLink? forward,
   ]) {
     final req =
-        requestTransformer != null ? requestTransformer(request) : request;
+        requestTransformer != null ? requestTransformer!(request) : request;
 
     if (responseTransformer == null) {
-      return forward(req);
+      return forward!(req);
     }
 
-    return forward(req).map(responseTransformer);
+    return forward!(req).map(responseTransformer!);
   }
 }
diff --git a/links/gql_transform_link/pubspec.yaml b/links/gql_transform_link/pubspec.yaml
index 2bde5caf..c2a2ac2e 100644
--- a/links/gql_transform_link/pubspec.yaml
+++ b/links/gql_transform_link/pubspec.yaml
@@ -3,12 +3,12 @@ version: 0.1.5
 description: GQL Link to transform Requests and Responses. May be used to update context, document, variables, data, errors, etc.
 repository: https://github.com/gql-dart/gql
 environment: 
-  sdk: '>=2.7.2 <3.0.0'
+  sdk: '>=2.12.0-259.12.beta <3.0.0'
 dependencies: 
   gql_exec: ^0.2.5
   gql_link: ^0.3.1
 dev_dependencies: 
-  test: ^1.0.0
-  mockito: ^4.1.1
+  test: ^1.16.2
+  mockito: ^5.0.0-nullsafety.7
   gql: ^0.12.3
   gql_pedantic: ^1.0.2
diff --git a/links/gql_transform_link/test/gql_transform_link_test.dart b/links/gql_transform_link/test/gql_transform_link_test.dart
index 51318e19..eb16cd8c 100644
--- a/links/gql_transform_link/test/gql_transform_link_test.dart
+++ b/links/gql_transform_link/test/gql_transform_link_test.dart
@@ -7,7 +7,16 @@ import "package:gql_transform_link/gql_transform_link.dart";
 import "package:mockito/mockito.dart";
 import "package:test/test.dart";
 
-class MockLink extends Mock implements Link {}
+class MockLink extends Mock implements Link {
+  @override
+  Stream<Response> request(Request? request, [NextLink? forward]) =>
+      super.noSuchMethod(
+        Invocation.method(#request, [request, forward]),
+        returnValue: Stream.fromIterable(
+          <Response>[],
+        ),
+      ) as Stream<Response>;
+}
 
 void main() {
   group("Transform Link", () {