docs: public <T extends Node> T sort(T nodeToBeSorted) {
  
          NodeVisitorStub visitor = new NodeVisitorStub() {
  
              @Override
              public TraversalControl visitDocument(Document node, TraverserContext<Node> context) {
                  Document changedNode = node.transform(builder -> {
                      List<Definition> definitions = sort(node.getDefinitions(), comparingDefinitions());
                      builder.definitions(definitions);
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitOperationDefinition(OperationDefinition node, TraverserContext<Node> context) {
                  OperationDefinition changedNode = node.transform(builder -> {
                      builder.variableDefinitions(sort(node.getVariableDefinitions(), comparing(VariableDefinition::getName)));
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.selectionSet(sortSelectionSet(node.getSelectionSet()));
                  });
                  return changeNode(context, changedNode);
              }
  
  
              @Override
              public TraversalControl visitField(Field node, TraverserContext<Node> context) {
                  Field changedNode = node.transform(builder -> {
                      builder.arguments(sort(node.getArguments(), comparing(Argument::getName)));
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.selectionSet(sortSelectionSet(node.getSelectionSet()));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitFragmentDefinition(FragmentDefinition node, TraverserContext<Node> context) {
                  FragmentDefinition changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.selectionSet(sortSelectionSet(node.getSelectionSet()));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitInlineFragment(InlineFragment node, TraverserContext<Node> context) {
                  InlineFragment changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.selectionSet(sortSelectionSet(node.getSelectionSet()));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitFragmentSpread(FragmentSpread node, TraverserContext<Node> context) {
                  FragmentSpread changedNode = node.transform(builder -> {
                      List<Directive> directives = sort(node.getDirectives(), comparing(Directive::getName));
                      builder.directives(directives);
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitDirective(Directive node, TraverserContext<Node> context) {
                  Directive changedNode = node.transform(builder -> {
                      List<Argument> arguments = sort(node.getArguments(), comparing(Argument::getName));
                      builder.arguments(arguments);
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitObjectValue(ObjectValue node, TraverserContext<Node> context) {
                  ObjectValue changedNode = node.transform(builder -> {
                      List<ObjectField> objectFields = sort(node.getObjectFields(), comparing(ObjectField::getName));
                      builder.objectFields(objectFields);
                  });
                  return changeNode(context, changedNode);
              }
  
              // SDL classes here
  
              @Override
              public TraversalControl visitSchemaDefinition(SchemaDefinition node, TraverserContext<Node> context) {
                  SchemaDefinition changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.operationTypeDefinitions(sort(node.getOperationTypeDefinitions(), comparing(OperationTypeDefinition::getName)));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitEnumTypeDefinition(EnumTypeDefinition node, TraverserContext<Node> context) {
                  EnumTypeDefinition changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.enumValueDefinitions(sort(node.getEnumValueDefinitions(), comparing(EnumValueDefinition::getName)));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitScalarTypeDefinition(ScalarTypeDefinition node, TraverserContext<Node> context) {
                  ScalarTypeDefinition changedNode = node.transform(builder -> {
                      List<Directive> directives = sort(node.getDirectives(), comparing(Directive::getName));
                      builder.directives(directives);
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitInputObjectTypeDefinition(InputObjectTypeDefinition node, TraverserContext<Node> context) {
                  InputObjectTypeDefinition changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.inputValueDefinitions(sort(node.getInputValueDefinitions(), comparing(InputValueDefinition::getName)));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitObjectTypeDefinition(ObjectTypeDefinition node, TraverserContext<Node> context) {
                  ObjectTypeDefinition changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.implementz(sort(node.getImplements(), comparingTypes()));
                      builder.fieldDefinitions(sort(node.getFieldDefinitions(), comparing(FieldDefinition::getName)));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitInterfaceTypeDefinition(InterfaceTypeDefinition node, TraverserContext<Node> context) {
                  InterfaceTypeDefinition changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.definitions(sort(node.getFieldDefinitions(), comparing(FieldDefinition::getName)));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitUnionTypeDefinition(UnionTypeDefinition node, TraverserContext<Node> context) {
                  UnionTypeDefinition changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.memberTypes(sort(node.getMemberTypes(), comparingTypes()));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitFieldDefinition(FieldDefinition node, TraverserContext<Node> context) {
                  FieldDefinition changedNode = node.transform(builder -> {
                      builder.directives(sort(node.getDirectives(), comparing(Directive::getName)));
                      builder.inputValueDefinitions(sort(node.getInputValueDefinitions(), comparing(InputValueDefinition::getName)));
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitInputValueDefinition(InputValueDefinition node, TraverserContext<Node> context) {
                  InputValueDefinition changedNode = node.transform(builder -> {
                      List<Directive> directives = sort(node.getDirectives(), comparing(Directive::getName));
                      builder.directives(directives);
                  });
                  return changeNode(context, changedNode);
              }
  
              @Override
              public TraversalControl visitDirectiveDefinition(DirectiveDefinition node, TraverserContext<Node> context) {
                  DirectiveDefinition changedNode = node.transform(builder -> {
                      builder.inputValueDefinitions(sort(node.getInputValueDefinitions(), comparing(InputValueDefinition::getName)));
                      builder.directiveLocations(sort(node.getDirectiveLocations(), comparing(DirectiveLocation::getName)));
                  });
                  return changeNode(context, changedNode);
              }
          };
  
          AstTransformer astTransformer = new AstTransformer();
          Node newDoc = astTransformer.transform(nodeToBeSorted, visitor);
          //noinspection unchecked
          return (T) newDoc;
      }